aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/test/ts/multi_sig_with_time_lock_except_remove_auth_addr.ts
blob: 62aa625fedb08ea54ac3c7b3c60073e9053b16bc (plain) (blame)
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import * as chai from 'chai';

import * as tokenTransferProxyJSON from '../../build/contracts/TokenTransferProxy.json';
import { Artifacts } from '../../util/artifacts';
import { constants } from '../../util/constants';
import { crypto } from '../../util/crypto';
import { MultiSigWrapper } from '../../util/multi_sig_wrapper';
import { ContractInstance, TransactionDataParams } from '../../util/types';

import { chaiSetup } from './utils/chai_setup';
const { TokenTransferProxy, MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress } = new Artifacts(artifacts);
const PROXY_ABI = (tokenTransferProxyJSON as any).abi;

chaiSetup.configure();
const expect = chai.expect;

contract('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', (accounts: string[]) => {
    const owners = [accounts[0], accounts[1]];
    const requiredApprovals = 2;
    const SECONDS_TIME_LOCKED = 1000000;

    // initialize fake addresses
    const authorizedAddress = `0x${crypto
        .solSHA3([accounts[0]])
        .slice(0, 20)
        .toString('hex')}`;
    const unauthorizedAddress = `0x${crypto
        .solSHA3([accounts[1]])
        .slice(0, 20)
        .toString('hex')}`;

    let tokenTransferProxy: ContractInstance;
    let multiSig: ContractInstance;
    let multiSigWrapper: MultiSigWrapper;

    let validDestination: string;

    beforeEach(async () => {
        const initialOwner = accounts[0];
        tokenTransferProxy = await TokenTransferProxy.new({ from: initialOwner });
        await tokenTransferProxy.addAuthorizedAddress(authorizedAddress, {
            from: initialOwner,
        });
        multiSig = await MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.new(
            owners,
            requiredApprovals,
            SECONDS_TIME_LOCKED,
            tokenTransferProxy.address,
        );
        await tokenTransferProxy.transferOwnership(multiSig.address, {
            from: initialOwner,
        });
        multiSigWrapper = new MultiSigWrapper(multiSig);
        validDestination = tokenTransferProxy.address;
    });

    describe('isFunctionRemoveAuthorizedAddress', () => {
        it('should throw if data is not for removeAuthorizedAddress', async () => {
            const data = MultiSigWrapper.encodeFnArgs('addAuthorizedAddress', PROXY_ABI, [owners[0]]);
            return expect(multiSig.isFunctionRemoveAuthorizedAddress.call(data)).to.be.rejectedWith(constants.REVERT);
        });

        it('should return true if data is for removeAuthorizedAddress', async () => {
            const data = MultiSigWrapper.encodeFnArgs('removeAuthorizedAddress', PROXY_ABI, [owners[0]]);
            const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress.call(data);
            expect(isFunctionRemoveAuthorizedAddress).to.be.true();
        });
    });

    describe('executeRemoveAuthorizedAddress', () => {
        it('should throw without the required confirmations', async () => {
            const dataParams: TransactionDataParams = {
                name: 'removeAuthorizedAddress',
                abi: PROXY_ABI,
                args: [authorizedAddress],
            };
            const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
            const txId = res.logs[0].args.transactionId.toString();

            return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.REVERT);
        });

        it('should throw if tx destination is not the tokenTransferProxy', async () => {
            const invalidTokenTransferProxy = await TokenTransferProxy.new();
            const invalidDestination = invalidTokenTransferProxy.address;
            const dataParams: TransactionDataParams = {
                name: 'removeAuthorizedAddress',
                abi: PROXY_ABI,
                args: [authorizedAddress],
            };
            const res = await multiSigWrapper.submitTransactionAsync(invalidDestination, owners[0], dataParams);
            const txId = res.logs[0].args.transactionId.toString();
            await multiSig.confirmTransaction(txId, { from: owners[1] });
            const isConfirmed = await multiSig.isConfirmed.call(txId);
            expect(isConfirmed).to.be.true();

            return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.REVERT);
        });

        it('should throw if tx data is not for removeAuthorizedAddress', async () => {
            const dataParams: TransactionDataParams = {
                name: 'addAuthorizedAddress',
                abi: PROXY_ABI,
                args: [unauthorizedAddress],
            };
            const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
            const txId = res.logs[0].args.transactionId.toString();
            await multiSig.confirmTransaction(txId, { from: owners[1] });
            const isConfirmed = await multiSig.isConfirmed.call(txId);
            expect(isConfirmed).to.be.true();

            return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.REVERT);
        });

        it('should execute removeAuthorizedAddress for valid tokenTransferProxy if fully confirmed', async () => {
            const dataParams: TransactionDataParams = {
                name: 'removeAuthorizedAddress',
                abi: PROXY_ABI,
                args: [authorizedAddress],
            };
            const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
            const txId = res.logs[0].args.transactionId.toString();
            await multiSig.confirmTransaction(txId, { from: owners[1] });
            const isConfirmed = await multiSig.isConfirmed.call(txId);
            expect(isConfirmed).to.be.true();
            await multiSig.executeRemoveAuthorizedAddress(txId);

            const isAuthorized = await tokenTransferProxy.authorized.call(authorizedAddress);
            expect(isAuthorized).to.be.false();
        });

        it('should throw if already executed', async () => {
            const dataParams: TransactionDataParams = {
                name: 'removeAuthorizedAddress',
                abi: PROXY_ABI,
                args: [authorizedAddress],
            };
            const res = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams);
            const txId = res.logs[0].args.transactionId.toString();
            await multiSig.confirmTransaction(txId, { from: owners[1] });
            const isConfirmed = await multiSig.isConfirmed.call(txId);
            expect(isConfirmed).to.be.true();
            await multiSig.executeRemoveAuthorizedAddress(txId);
            const tx = await multiSig.transactions.call(txId);
            const isExecuted = tx[3];
            expect(isExecuted).to.be.true();
            return expect(multiSig.executeRemoveAuthorizedAddress(txId)).to.be.rejectedWith(constants.REVERT);
        });
    });
});