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
105
106
107
108
109
110
111
112
113
|
import {RPC} from '@0xproject/dev-utils';
import {promisify} from '@0xproject/utils';
import {BigNumber} from 'bignumber.js';
import * as chai from 'chai';
import Web3 = require('web3');
import * as multiSigWalletJSON from '../../build/contracts/MultiSigWalletWithTimeLock.json';
import * as truffleConf from '../../truffle.js';
import {Artifacts} from '../../util/artifacts';
import {constants} from '../../util/constants';
import {MultiSigWrapper} from '../../util/multi_sig_wrapper';
import {ContractInstance} from '../../util/types';
import {chaiSetup} from './utils/chai_setup';
const {MultiSigWalletWithTimeLock} = new Artifacts(artifacts);
const MULTI_SIG_ABI = (multiSigWalletJSON as any).abi;
chaiSetup.configure();
const expect = chai.expect;
// In order to benefit from type-safety, we re-assign the global web3 instance injected by Truffle
// with type `any` to a variable of type `Web3`.
const web3: Web3 = (global as any).web3;
contract('MultiSigWalletWithTimeLock', (accounts: string[]) => {
const owners = [accounts[0], accounts[1]];
const SECONDS_TIME_LOCKED = 10000;
let multiSig: ContractInstance;
let multiSigWrapper: MultiSigWrapper;
let txId: number;
let initialSecondsTimeLocked: number;
let rpc: RPC;
before(async () => {
multiSig = await MultiSigWalletWithTimeLock.deployed();
multiSigWrapper = new MultiSigWrapper(multiSig);
const secondsTimeLocked = await multiSig.secondsTimeLocked.call();
initialSecondsTimeLocked = secondsTimeLocked.toNumber();
const rpcUrl = `http://${truffleConf.networks.development.host}:${truffleConf.networks.development.port}`;
rpc = new RPC(rpcUrl);
});
describe('changeTimeLock', () => {
it('should throw when not called by wallet', async () => {
return expect(multiSig.changeTimeLock(SECONDS_TIME_LOCKED, {from: owners[0]}))
.to.be.rejectedWith(constants.REVERT);
});
it('should throw without enough confirmations', async () => {
const destination = multiSig.address;
const from = owners[0];
const dataParams = {
name: 'changeTimeLock',
abi: MULTI_SIG_ABI,
args: [SECONDS_TIME_LOCKED],
};
const subRes = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
txId = subRes.logs[0].args.transactionId.toNumber();
return expect(multiSig.executeTransaction(txId)).to.be.rejectedWith(constants.REVERT);
});
it('should set confirmation time with enough confirmations', async () => {
const res = await multiSig.confirmTransaction(txId, {from: owners[1]});
expect(res.logs).to.have.length(2);
const blockNum = await promisify<number>(web3.eth.getBlockNumber)();
const blockInfo = await promisify<Web3.BlockWithoutTransactionData>(web3.eth.getBlock)(blockNum);
const timestamp = new BigNumber(blockInfo.timestamp);
const confirmationTimeBigNum = new BigNumber(await multiSig.confirmationTimes.call(txId));
expect(timestamp).to.be.bignumber.equal(confirmationTimeBigNum);
});
it('should be executable with enough confirmations and secondsTimeLocked of 0', async () => {
expect(initialSecondsTimeLocked).to.be.equal(0);
const res = await multiSig.executeTransaction(txId);
expect(res.logs).to.have.length(2);
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call());
expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED);
});
const newSecondsTimeLocked = 0;
it('should throw if it has enough confirmations but is not past the time lock', async () => {
const destination = multiSig.address;
const from = owners[0];
const dataParams = {
name: 'changeTimeLock',
abi: MULTI_SIG_ABI,
args: [newSecondsTimeLocked],
};
const subRes = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams);
txId = subRes.logs[0].args.transactionId.toNumber();
const confRes = await multiSig.confirmTransaction(txId, {from: owners[1]});
expect(confRes.logs).to.have.length(2);
return expect(multiSig.executeTransaction(txId)).to.be.rejectedWith(constants.REVERT);
});
it('should execute if it has enough confirmations and is past the time lock', async () => {
await rpc.increaseTimeAsync(SECONDS_TIME_LOCKED);
await multiSig.executeTransaction(txId);
const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.call());
expect(secondsTimeLocked).to.be.bignumber.equal(newSecondsTimeLocked);
});
});
});
|