Skip to content

Commit 6a74860

Browse files
authored
L2 Safe (#280)
1 parent 367aca9 commit 6a74860

File tree

70 files changed

+801
-2172
lines changed

Some content is hidden

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

70 files changed

+801
-2172
lines changed

.github/workflows/ci.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,30 @@ jobs:
2020
uses: coverallsapp/github-action@master
2121
with:
2222
github-token: ${{ secrets.GITHUB_TOKEN }}
23+
tests-other:
24+
runs-on: ubuntu-latest
25+
strategy:
26+
fail-fast: false
27+
matrix:
28+
contract-name: ["GnosisSafeL2"]
29+
env:
30+
SAFE_CONTRACT_UNDER_TEST: ${{ matrix.contract-name }}
31+
steps:
32+
- uses: actions/checkout@v2
33+
- uses: actions/setup-node@v2
34+
with:
35+
node-version: 15
36+
- uses: actions/cache@v2
37+
with:
38+
path: "**/node_modules"
39+
key: ${{ runner.os }}-modules-${{ hashFiles('**/yarn.lock') }}
40+
- run: yarn
41+
- run: yarn build
42+
- run: yarn coverage
43+
- name: Coveralls
44+
uses: coverallsapp/github-action@master
45+
with:
46+
github-token: ${{ secrets.GITHUB_TOKEN }}
2347
benchmarks:
2448
runs-on: ubuntu-latest
2549
strategy:

benchmark/GnosisSafe.ERC1155.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { expect } from "chai";
22
import { waffle, ethers } from "hardhat";
33
import "@nomiclabs/hardhat-ethers";
4-
import { buildSafeTransaction } from "../test/utils/execution";
4+
import { buildSafeTransaction } from "../src/utils/execution";
55
import { BigNumber } from "ethers";
66
import { benchmark, Contracts } from "./utils/setup"
77

benchmark/GnosisSafe.ERC20.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { expect } from "chai";
22
import { waffle, ethers } from "hardhat";
33
import "@nomiclabs/hardhat-ethers";
4-
import { buildSafeTransaction } from "../test/utils/execution";
4+
import { buildSafeTransaction } from "../src/utils/execution";
55
import { BigNumber } from "ethers";
66
import { benchmark, Contracts } from "./utils/setup"
77

benchmark/GnosisSafe.Ether.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { expect } from "chai";
22
import { waffle, ethers } from "hardhat";
33
import "@nomiclabs/hardhat-ethers";
4-
import { buildSafeTransaction } from "../test/utils/execution";
4+
import { buildSafeTransaction } from "../src/utils/execution";
55
import { BigNumber } from "ethers";
66
import { benchmark } from "./utils/setup"
77

benchmark/GnosisSafe.Proxy.spec.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import { expect } from "chai";
2-
import { waffle, ethers } from "hardhat";
31
import "@nomiclabs/hardhat-ethers";
4-
import { buildSafeTransaction } from "../test/utils/execution";
5-
import { BigNumber } from "ethers";
2+
import { buildSafeTransaction } from "../src/utils/execution";
63
import { benchmark } from "./utils/setup"
74
import { getFactory } from "../test/utils/setup";
85

benchmark/utils/setup.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { expect } from "chai";
22
import hre, { deployments, waffle } from "hardhat";
33
import "@nomiclabs/hardhat-ethers";
44
import { getDefaultCallbackHandler, getSafeWithOwners } from "../../test/utils/setup";
5-
import { logGas, executeTx, SafeTransaction, safeSignTypedData, SafeSignature, executeContractCallWithSigners } from "../../test/utils/execution";
5+
import { logGas, executeTx, SafeTransaction, safeSignTypedData, SafeSignature, executeContractCallWithSigners } from "../../src/utils/execution";
66
import { Wallet, Contract } from "ethers";
77
import { AddressZero } from "@ethersproject/constants";
88

contracts/GnosisSafe.sol

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ contract GnosisSafe
134134
bytes memory signatures
135135
)
136136
public
137+
virtual
137138
payable
138139
returns (bool success)
139140
{
@@ -193,12 +194,11 @@ contract GnosisSafe
193194
private
194195
returns (uint256 payment)
195196
{
196-
// solium-disable-next-line security/no-tx-origin
197+
// solhint-disable-next-line avoid-tx-origin
197198
address payable receiver = refundReceiver == address(0) ? payable(tx.origin) : refundReceiver;
198199
if (gasToken == address(0)) {
199200
// For ETH we will only adjust the gas price to not be higher than the actual used gas price
200201
payment = gasUsed.add(baseGas).mul(gasPrice < tx.gasprice ? gasPrice : tx.gasprice);
201-
// solium-disable-next-line security/no-send
202202
require(receiver.send(payment), "GS011");
203203
} else {
204204
payment = gasUsed.add(baseGas).mul(gasPrice);
@@ -213,8 +213,8 @@ contract GnosisSafe
213213
* @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.
214214
*/
215215
function checkSignatures(bytes32 dataHash, bytes memory data, bytes memory signatures)
216-
view
217216
public
217+
view
218218
{
219219
// Load threshold to avoid multiple storage loads
220220
uint256 _threshold = threshold;
@@ -246,15 +246,15 @@ contract GnosisSafe
246246

247247
// Check if the contract signature is in bounds: start of data is s + 32 and end is start + signature length
248248
uint256 contractSignatureLen;
249-
// solium-disable-next-line security/no-inline-assembly
249+
// solhint-disable-next-line no-inline-assembly
250250
assembly {
251251
contractSignatureLen := mload(add(add(signatures, s), 0x20))
252252
}
253253
require(uint256(s).add(32).add(contractSignatureLen) <= signatures.length, "GS023");
254254

255255
// Check signature
256256
bytes memory contractSignature;
257-
// solium-disable-next-line security/no-inline-assembly
257+
// solhint-disable-next-line no-inline-assembly
258258
assembly {
259259
// The signature data for contract signatures is appended to the concatenated signatures and the offset is stored in s
260260
contractSignature := add(add(signatures, s), 0x20)
@@ -296,7 +296,6 @@ contract GnosisSafe
296296
{
297297
uint256 startGas = gasleft();
298298
// We don't provide an error message here, as we use it to return the estimate
299-
// solium-disable-next-line error-reason
300299
require(execute(to, value, data, operation, gasleft()));
301300
uint256 requiredGas = startGas - gasleft();
302301
// Convert response to string and return via error message
@@ -332,7 +331,7 @@ contract GnosisSafe
332331
/// @dev Returns the chain id used by this contract.
333332
function getChainId() public view returns (uint256) {
334333
uint256 id;
335-
// solium-disable-next-line security/no-inline-assembly
334+
// solhint-disable-next-line no-inline-assembly
336335
assembly {
337336
id := chainid()
338337
}

contracts/GnosisSafeL2.sol

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// SPDX-License-Identifier: LGPL-3.0-only
2+
pragma solidity >=0.7.0 <0.9.0;
3+
4+
import "./GnosisSafe.sol";
5+
6+
/// @title Gnosis Safe - A multisignature wallet with support for confirmations using signed messages based on ERC191.
7+
/// @author Stefan George - <stefan@gnosis.io>
8+
/// @author Richard Meissner - <richard@gnosis.io>
9+
contract GnosisSafeL2
10+
is GnosisSafe {
11+
12+
event SafeMultiSigTransaction(
13+
address to,
14+
uint256 value,
15+
bytes data,
16+
Enum.Operation operation,
17+
uint256 safeTxGas,
18+
uint256 baseGas,
19+
uint256 gasPrice,
20+
address gasToken,
21+
address payable refundReceiver,
22+
bytes signatures,
23+
// We combine nonce, sender and threshold into one to avoid stack too deep
24+
// Dev note: additionalInfo should not contain `bytes`, as this complicates decoding
25+
bytes additionalInfo
26+
);
27+
28+
event SafeModuleTransaction(
29+
address module,
30+
address to,
31+
uint256 value,
32+
bytes data,
33+
Enum.Operation operation
34+
);
35+
36+
/// @dev Allows to execute a Safe transaction confirmed by required number of owners and then pays the account that submitted the transaction.
37+
/// Note: The fees are always transfered, even if the user transaction fails.
38+
/// @param to Destination address of Safe transaction.
39+
/// @param value Ether value of Safe transaction.
40+
/// @param data Data payload of Safe transaction.
41+
/// @param operation Operation type of Safe transaction.
42+
/// @param safeTxGas Gas that should be used for the Safe transaction.
43+
/// @param baseGas Gas costs that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)
44+
/// @param gasPrice Gas price that should be used for the payment calculation.
45+
/// @param gasToken Token address (or 0 if ETH) that is used for the payment.
46+
/// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
47+
/// @param signatures Packed signature data ({bytes32 r}{bytes32 s}{uint8 v})
48+
function execTransaction(
49+
address to,
50+
uint256 value,
51+
bytes calldata data,
52+
Enum.Operation operation,
53+
uint256 safeTxGas,
54+
uint256 baseGas,
55+
uint256 gasPrice,
56+
address gasToken,
57+
address payable refundReceiver,
58+
bytes memory signatures
59+
)
60+
public
61+
override
62+
payable
63+
returns (bool)
64+
{
65+
bytes memory additionalInfo;
66+
{
67+
additionalInfo = abi.encode(nonce, msg.sender, threshold);
68+
}
69+
emit SafeMultiSigTransaction(
70+
to,
71+
value,
72+
data,
73+
operation,
74+
safeTxGas,
75+
baseGas,
76+
gasPrice,
77+
gasToken,
78+
refundReceiver,
79+
signatures,
80+
additionalInfo
81+
);
82+
return super.execTransaction(
83+
to,
84+
value,
85+
data,
86+
operation,
87+
safeTxGas,
88+
baseGas,
89+
gasPrice,
90+
gasToken,
91+
refundReceiver,
92+
signatures
93+
);
94+
}
95+
96+
/// @dev Allows a Module to execute a Safe transaction without any further confirmations.
97+
/// @param to Destination address of module transaction.
98+
/// @param value Ether value of module transaction.
99+
/// @param data Data payload of module transaction.
100+
/// @param operation Operation type of module transaction.
101+
function execTransactionFromModule(address to, uint256 value, bytes memory data, Enum.Operation operation)
102+
public
103+
override
104+
returns (bool success)
105+
{
106+
emit SafeModuleTransaction(
107+
msg.sender,
108+
to,
109+
value,
110+
data,
111+
operation
112+
);
113+
success = super.execTransactionFromModule(to, value, data, operation);
114+
}
115+
}

contracts/accessors/SimulateTxAccessor.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import "../base/Executor.sol";
88
contract SimulateTxAccessor is Executor {
99

1010
bytes32 constant private GUARD_VALUE = keccak256("simulate_tx_accessor.guard.bytes32");
11-
bytes32 guard;
11+
bytes32 private guard;
1212

1313
constructor() {
1414
guard = GUARD_VALUE;
@@ -27,7 +27,7 @@ contract SimulateTxAccessor is Executor {
2727
uint256 startGas = gasleft();
2828
success = execute(to, value, data, operation, gasleft());
2929
estimate = startGas - gasleft();
30-
// solium-disable-next-line security/no-inline-assembly
30+
// solhint-disable-next-line no-inline-assembly
3131
assembly {
3232
// Load free memory location
3333
let ptr := mload(0x40)

contracts/base/Executor.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ contract Executor {
1313
uint256 txGas
1414
) internal returns (bool success) {
1515
if (operation == Enum.Operation.DelegateCall) {
16-
// solium-disable-next-line security/no-inline-assembly
16+
// solhint-disable-next-line no-inline-assembly
1717
assembly {
1818
success := delegatecall(
1919
txGas,
@@ -25,7 +25,7 @@ contract Executor {
2525
)
2626
}
2727
} else {
28-
// solium-disable-next-line security/no-inline-assembly
28+
// solhint-disable-next-line no-inline-assembly
2929
assembly {
3030
success := call(
3131
txGas,

0 commit comments

Comments
 (0)