-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Expand file tree
/
Copy pathgnosisSafeNestedSafes.js
More file actions
104 lines (87 loc) · 5.57 KB
/
gnosisSafeNestedSafes.js
File metadata and controls
104 lines (87 loc) · 5.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
const utils = require('./utils/general')
const safeUtils = require('./utils/execution')
const abi = require('ethereumjs-abi')
const GnosisSafe = artifacts.require("./GnosisSafe.sol")
const ProxyFactory = artifacts.require("./GnosisSafeProxyFactory.sol")
contract('GnosisSafe using nested safes', function(accounts) {
let lw
let owner1Safe
let owner2Safe
let gnosisSafe
let executor = accounts[8]
const CALL = 0
beforeEach(async function () {
// Create lightwallet
lw = await utils.createLightwallet()
// Create Master Copies
let proxyFactory = await ProxyFactory.new()
let gnosisSafeMasterCopy = await utils.deployContract("deploying Gnosis Safe Mastercopy", GnosisSafe)
// Create Gnosis Safe
let owner1SafeData = await gnosisSafeMasterCopy.contract.methods.setup(
[lw.accounts[0], lw.accounts[1]], 2, utils.Address0, "0x", utils.Address0, utils.Address0, 0, utils.Address0
).encodeABI()
owner1Safe = await utils.getParamFromTxEvent(
await proxyFactory.createProxy(gnosisSafeMasterCopy.address, owner1SafeData),
'ProxyCreation', 'proxy', proxyFactory.address, GnosisSafe, 'create Gnosis Safe Proxy',
)
let owner2SafeData = await gnosisSafeMasterCopy.contract.methods.setup(
[lw.accounts[2], lw.accounts[3]], 2, utils.Address0, "0x", utils.Address0, utils.Address0, 0, utils.Address0
).encodeABI()
owner2Safe = await utils.getParamFromTxEvent(
await proxyFactory.createProxy(gnosisSafeMasterCopy.address, owner2SafeData),
'ProxyCreation', 'proxy', proxyFactory.address, GnosisSafe, 'create Gnosis Safe Proxy',
)
let gnosisSafeData = await gnosisSafeMasterCopy.contract.methods.setup(
[owner1Safe.address, owner2Safe.address], 2, utils.Address0, "0x", utils.Address0, utils.Address0, 0, utils.Address0
).encodeABI()
gnosisSafe = await utils.getParamFromTxEvent(
await proxyFactory.createProxy(gnosisSafeMasterCopy.address, gnosisSafeData),
'ProxyCreation', 'proxy', proxyFactory.address, GnosisSafe, 'create Gnosis Safe Proxy',
)
})
it('should use EIP-1271 (contract signatures)', async () => {
// Deposit some spare money for execution to owner safes
assert.equal(await web3.eth.getBalance(owner1Safe.address), 0)
await web3.eth.sendTransaction({from: accounts[0], to: owner1Safe.address, value: web3.utils.toWei("0.1", 'ether')})
assert.equal(await web3.eth.getBalance(owner1Safe.address), web3.utils.toWei("0.1", 'ether'))
assert.equal(await web3.eth.getBalance(owner2Safe.address), 0)
await web3.eth.sendTransaction({from: accounts[0], to: owner2Safe.address, value: web3.utils.toWei("0.1", 'ether')})
assert.equal(await web3.eth.getBalance(owner2Safe.address), web3.utils.toWei("0.1", 'ether'))
// Deposit 1 ETH
assert.equal(await web3.eth.getBalance(gnosisSafe.address), 0)
await web3.eth.sendTransaction({from: accounts[0], to: gnosisSafe.address, value: web3.utils.toWei("1", 'ether')})
assert.equal(await web3.eth.getBalance(gnosisSafe.address), web3.utils.toWei("1", 'ether'))
// Withdraw 1 ETH
let to = accounts[9]
let value = web3.utils.toWei("1", 'ether')
let data = "0x"
let operation = CALL
let sigs = "0x"
let nonce = await gnosisSafe.nonce()
let messageData = await gnosisSafe.encodeTransactionData(to, value, data, operation, 0, 0, 0, utils.Address0, utils.Address0, nonce)
let signMessageData = owner1Safe.contract.methods.signMessage(messageData).encodeABI()
// Use on-chain Safe signature
await safeUtils.executeTransaction(lw, owner1Safe, 'approve transaction signature on contract', [lw.accounts[0], lw.accounts[1]], owner1Safe.address, 0, signMessageData, CALL, executor)
// Use off-chain Safe signature
let messageHash = await owner2Safe.getMessageHash(messageData)
let owner2Sigs = utils.signTransaction(lw, [lw.accounts[2], lw.accounts[3]], messageHash).slice(2)
let encodedOwner2Signs = abi.rawEncode(['bytes'], [ new Buffer(owner2Sigs, 'hex') ]).toString('hex').slice(64)
// Pack signatures in correct order
if (owner1Safe.address < owner2Safe.address) {
sigs += "000000000000000000000000" + owner1Safe.address.replace('0x', '') + "0000000000000000000000000000000000000000000000000000000000000082" + "00" // r, s, v
sigs += "000000000000000000000000" + owner2Safe.address.replace('0x', '') + "00000000000000000000000000000000000000000000000000000000000000a2" + "00" // r, s, v
} else {
sigs += "000000000000000000000000" + owner2Safe.address.replace('0x', '') + "00000000000000000000000000000000000000000000000000000000000000a2" + "00" // r, s, v
sigs += "000000000000000000000000" + owner1Safe.address.replace('0x', '') + "0000000000000000000000000000000000000000000000000000000000000082" + "00" // r, s, v
}
// Append additional signature data
sigs += "0000000000000000000000000000000000000000000000000000000000000000" + encodedOwner2Signs
// Execute Transaction
let tx = await gnosisSafe.execTransaction(
to, value, data, operation, 0, 0, 0, utils.Address0, utils.Address0, sigs, {from: executor}
)
utils.checkTxEvent(tx, 'ExecutionFailed', gnosisSafe.address, false, "execute withdrawal")
// Safe should be empty again
assert.equal(await web3.eth.getBalance(gnosisSafe.address), 0)
})
})