Skip to content

Commit e0575ce

Browse files
authored
Merge pull request #25 from gnosis/feature/optimize_personal_edition
Optimize Personal Edition
2 parents 299e972 + 68685cd commit e0575ce

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+10133
-3261
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
build/
2-
node_modules/
2+
node_modules/
3+
.DS_Store

.travis.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
language: node_js
2+
node_js:
3+
- '9'
4+
cache:
5+
directories:
6+
- node_modules
7+
before_script:
8+
- truffle compile

README.md

Lines changed: 59 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Gnosis Safe Contracts
22
=====================
33

4-
The Gnosis Safe is a multisignature wallet with support for confirmations using signed messages based on [ERC191](https://github.com/ethereum/EIPs/issues/191). It is the successor of the [Gnosis Multisig Wallet](https://github.com/gnosis/MultiSigWallet) 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 extensions, which allow to do transactions with different requirements.
4+
The Gnosis Safe is a multisignature wallet with support for confirmations using signed messages based on [ERC191](https://github.com/ethereum/EIPs/issues/191). It is the successor of the [Gnosis Multisig Wallet](https://github.com/gnosis/MultiSigWallet) 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.
55

66
Contracts
77
---------
@@ -15,71 +15,92 @@ The nonce prevents replay attacks and is increased with every successfully execu
1515
### Contract Creations
1616
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.
1717

18+
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.
19+
20+
#### SelfAuthorized.sol
21+
The self authorized contract implements the `authorized()` so that only the contract itself is authorized to perform actions.
22+
1823
#### Proxy.sol
1924
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`.
2025

26+
#### DelegateConstructorProxy.sol
27+
This is an extension to the proxy contract that allows further initialization logic to be passed to the constructor.
28+
29+
#### PayingProxy.sol
30+
This is an extension to the delegate constructor proxy contract that pays a specific amount to a target address after initialization.
31+
2132
#### ProxyFactory.sol
2233
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.
2334

35+
#### MasterCopy.sol
36+
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.
37+
38+
#### ModuleManager.sol
39+
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.
40+
41+
#### OwnerManager.sol
42+
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.
43+
2444
### Gnosis Safe
2545
#### GnosisSafe.sol
26-
The Gnosis Safe contract implements all basic multisignature functionality. It allows to execute Safe transactions and Safe extensions.
46+
The Gnosis Safe contract implements all basic multisignature functionality. It allows to execute Safe transactions and Safe modules.
47+
48+
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.
49+
50+
Before a Safe transaction can be executed, the transaction has to be confirmed by the required number of owners.
2751

28-
Safe transactions can be used to configure the wallet like managing owners, updating the master copy address or whitelisting of extensions. All configuration functions can only be called via transactions sent from the Safe itself. This assures that configuration changes require owner confirmations.
52+
There are multiple implementations of the Gnosis Safe contract with different methods to check if a transaction has been confirmed by the required owners.
2953

30-
Before a Safe transaction can be executed, the transaction has to be confirmed by the required number of owners. There are two ways to confirm transactions:
54+
#### GnosisSafePersonalEdition.sol
55+
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.
3156

32-
1. Owners represented by private key controlled accounts can sign the transaction hash.
33-
2. Owners represented by contract accounts (e.g. other Safe contracts) or private key controlled accounts can confirm a transaction by calling the `confirmTransaction` function.
57+
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.
3458

35-
Once the required number of confirmations is available `executeTransaction` can be called by sending confirmation signatures and references to confirmations sent using `confirmTransaction`. In case the account calling `executeTransaction` is a wallet owner its call can be used as confirmation and the owner doesn't have to confirm with a signed message or `confirmTransaction`.
59+
`execTransactionAndPaySubmitter` expects all confirmations sorted by owner address. This is required to easily validate no confirmation duplicates exist.
3660

37-
`executeTransaction` expects all confirmations sorted by owner address. This is required to easily validate no confirmation duplicates exist.
61+
#### GnosisSafeTeamEdition.sol
62+
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.
3863

39-
##### Example execution
64+
##### Example execution for State Channel Edition
4065

41-
Assuming we have 4 owners in a 4 out of 4 multisig configuration:
66+
Assuming we have 2 owners in a 2 out of 2 multisig configuration:
4267

4368
1. `0x1` (Private key)
4469
2. `0x2` (Private key)
45-
3. `0x3` (Safe contract)
46-
4. `0x4` (Private key)
4770

48-
`0x1` and `0x2` are confirming by signing a message. `0x3` is confirming by sending a `confirmTransaction` transaction. `0x4` is calling the `executeTransaction` function and therefore also confirming the transaction.
71+
`0x1` and `0x2` are confirming by signing a message.
4972

50-
The Safe transaction parameters used for `executeTransaction` have to be set like the following:
51-
* `v = [v_0x1, v_0x2]`
52-
* `r = [r_0x1, r_0x2]`
53-
* `s = [s_0x1, s_0x2]`
54-
* `owners = [0x3, 0x4]`
55-
* `indices = [2, 3]`
73+
The signatures bytes used for `execTransaction` have to be build like the following:
74+
* `bytes = 0x{r_0x1}{s_0x1}{v_0x1}{r_0x2}{s_0x2}{v_0x2}`
5675

57-
`v`, `r` and `s` are the signature parameters for the signed confirmation messages. Position `0` in `v` represents `0x1`'s signature part and corresponds to position `0` in `r` and `s`. The `owners` array contains owner addresses confirming transaction by sending a `confirmTransaction` or calling `executeTransaction`. Their address position in the sorted array of all confirming owner addresses is set in the `indices` array starting from position 0:
76+
`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.
5877

59-
`allConfirmingOwners = [0x1, 0x2, 0x3, 0x4]`
78+
### Modules
79+
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.
6080

61-
Position of `0x3` is `2` and position of `0x4` is `3` in `indices` array.
81+
#### StateChannelModule.sol
82+
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.
6283

63-
### Extensions
64-
Extensions allow to execute transactions from the Safe without the requirement of multiple signatures. Extensions define their own requirements for execution. Every extension has to implement the interface for extensions. This interface requires only one function `isExecutable` receiving all transaction parameters and evaluating if a transaction is allowed to be executed. Extension transactions don't require a nonce as they don't require replay protection.
84+
#### DailyLimitModule.sol
85+
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.
6586

66-
#### DailyLimitExtension.sol
67-
The Daily Limit Extensions 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.
87+
#### SocialRecoveryModule.sol
88+
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.
6889

69-
#### SocialRecoveryExtension.sol
70-
The Social Recovery Extensions 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.
71-
72-
#### WhitelistExtension.sol
73-
The Whitelist Extensions allows an owner to execute arbitrary transactions to specific addresses without confirmation by other owners. The whitelist can be maintained via Safe transactions.
90+
#### WhitelistModule.sol
91+
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.
7492

7593
### Libraries
7694
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`.
7795

7896
#### MultiSend.sol
7997
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.
8098

81-
#### CreateAndAddExtension.sol
82-
This library allows to create a new Safe extension and whitelist this extension for the Safe in one single transaction.
99+
#### CreateAndAddModules.sol
100+
This library allows to create new Safe modules and whitelist these modules for the Safe in one single transaction.
101+
102+
#### Note on naming of execute function of the safes
103+
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.
83104

84105
Install
85106
-------
@@ -101,6 +122,10 @@ truffle test
101122
truffle deploy
102123
```
103124

125+
Audits
126+
---------
127+
- [by Alexey Akhunov](docs/alexey_audit.md)
128+
104129
Security and Liability
105130
----------------------
106131
All contracts are WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@@ -112,11 +137,7 @@ All smart contracts are released under GPL v.3.
112137
Contributors
113138
------------
114139
- Stefan George ([Georgi87](https://github.com/Georgi87))
140+
- Richard Meissner ([rmeissner](https://github.com/rmeissner))
115141
- Christian Lundkvist ([christianlundkvist](https://github.com/christianlundkvist))
116142
- Nick Dodson ([SilentCicero](https://github.com/SilentCicero))
117143
- Gonçalo Sá ([GNSPS](https://github.com/GNSPS))
118-
- Richard Meissner ([rmeissner](https://github.com/rmeissner))
119-
120-
Reviewers
121-
---------
122-
The code has not been reviewed yet.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
pragma solidity 0.4.24;
2+
import "./Proxy.sol";
3+
4+
5+
/// @title Delegate Constructor Proxy - Generic proxy contract allows to execute all transactions applying the code of a master contract. It is possible to send along initialization data with the constructor.
6+
/// @author Stefan George - <stefan@gnosis.pm>
7+
/// @author Richard Meissner - <richard@gnosis.pm>
8+
contract DelegateConstructorProxy is Proxy {
9+
10+
/// @dev Constructor function sets address of master copy contract.
11+
/// @param _masterCopy Master copy address.
12+
/// @param initializer Data used for a delegate call to initialize the contract.
13+
constructor(address _masterCopy, bytes initializer) Proxy(_masterCopy)
14+
public
15+
{
16+
if (initializer.length > 0) {
17+
// solium-disable-next-line security/no-inline-assembly
18+
assembly {
19+
let masterCopy := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)
20+
let success := delegatecall(sub(gas, 10000), masterCopy, add(initializer, 0x20), mload(initializer), 0, 0)
21+
let ptr := mload(0x40)
22+
returndatacopy(ptr, 0, returndatasize)
23+
if eq(success, 0) { revert(ptr, returndatasize) }
24+
}
25+
}
26+
}
27+
}

contracts/Enum.sol

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
pragma solidity 0.4.24;
2+
3+
4+
/// @title Enum - Collection of enums
5+
/// @author Richard Meissner - <richard@gnosis.pm>
6+
contract Enum {
7+
enum Operation {
8+
Call,
9+
DelegateCall,
10+
Create
11+
}
12+
}

contracts/Extension.sol

Lines changed: 0 additions & 18 deletions
This file was deleted.

0 commit comments

Comments
 (0)