diff options
author | Amir Bandeali <abandeali1@gmail.com> | 2018-05-25 08:24:52 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-25 08:24:52 +0800 |
commit | 654698b20880398eded74342c8030a6009938103 (patch) | |
tree | 0c206bee801971372866051b08b1710a05eb431a /packages/contracts/test | |
parent | 895a9093aa5f204f9f7ad0fedb2934a8b6c40b17 (diff) | |
parent | 237ebb07161c46fa85ca778a1c2ff60f63611bd7 (diff) | |
download | dexon-sol-tools-654698b20880398eded74342c8030a6009938103.tar dexon-sol-tools-654698b20880398eded74342c8030a6009938103.tar.gz dexon-sol-tools-654698b20880398eded74342c8030a6009938103.tar.bz2 dexon-sol-tools-654698b20880398eded74342c8030a6009938103.tar.lz dexon-sol-tools-654698b20880398eded74342c8030a6009938103.tar.xz dexon-sol-tools-654698b20880398eded74342c8030a6009938103.tar.zst dexon-sol-tools-654698b20880398eded74342c8030a6009938103.zip |
Merge pull request #571 from 0xProject/feature/contracts/proxyOwner
Update MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress
Diffstat (limited to 'packages/contracts/test')
-rw-r--r-- | packages/contracts/test/asset_proxy_owner.ts | 345 | ||||
-rw-r--r-- | packages/contracts/test/exchange/core.ts | 9 | ||||
-rw-r--r-- | packages/contracts/test/libraries/lib_bytes.ts | 14 | ||||
-rw-r--r-- | packages/contracts/test/multi_sig_with_time_lock.ts | 150 | ||||
-rw-r--r-- | packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts | 205 |
5 files changed, 404 insertions, 319 deletions
diff --git a/packages/contracts/test/asset_proxy_owner.ts b/packages/contracts/test/asset_proxy_owner.ts new file mode 100644 index 000000000..db68b5678 --- /dev/null +++ b/packages/contracts/test/asset_proxy_owner.ts @@ -0,0 +1,345 @@ +import { BlockchainLifecycle } from '@0xproject/dev-utils'; +import { LogWithDecodedArgs } from '@0xproject/types'; +import { BigNumber } from '@0xproject/utils'; +import * as chai from 'chai'; +import * as _ from 'lodash'; +import 'make-promises-safe'; +import * as Web3 from 'web3'; + +import { + AssetProxyOwnerContract, + AssetProxyRegistrationContractEventArgs, + ExecutionContractEventArgs, + ExecutionFailureContractEventArgs, + SubmissionContractEventArgs, +} from '../src/contract_wrappers/generated/asset_proxy_owner'; +import { MixinAuthorizableContract } from '../src/contract_wrappers/generated/mixin_authorizable'; +import { artifacts } from '../src/utils/artifacts'; +import { chaiSetup } from '../src/utils/chai_setup'; +import { constants } from '../src/utils/constants'; +import { MultiSigWrapper } from '../src/utils/multi_sig_wrapper'; +import { provider, txDefaults, web3Wrapper } from '../src/utils/web3_wrapper'; + +chaiSetup.configure(); +const expect = chai.expect; +const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); + +describe('AssetProxyOwner', () => { + let owners: string[]; + let authorized: string; + const REQUIRED_APPROVALS = new BigNumber(2); + const SECONDS_TIME_LOCKED = new BigNumber(1000000); + + let erc20Proxy: MixinAuthorizableContract; + let erc721Proxy: MixinAuthorizableContract; + let multiSig: AssetProxyOwnerContract; + let multiSigWrapper: MultiSigWrapper; + + before(async () => { + const accounts = await web3Wrapper.getAvailableAddressesAsync(); + owners = [accounts[0], accounts[1]]; + const initialOwner = (authorized = accounts[0]); + erc20Proxy = await MixinAuthorizableContract.deployFrom0xArtifactAsync( + artifacts.MixinAuthorizable, + provider, + txDefaults, + ); + erc721Proxy = await MixinAuthorizableContract.deployFrom0xArtifactAsync( + artifacts.MixinAuthorizable, + provider, + txDefaults, + ); + const defaultAssetProxyContractAddresses: string[] = []; + multiSig = await AssetProxyOwnerContract.deployFrom0xArtifactAsync( + artifacts.AssetProxyOwner, + provider, + txDefaults, + owners, + defaultAssetProxyContractAddresses, + REQUIRED_APPROVALS, + SECONDS_TIME_LOCKED, + ); + multiSigWrapper = new MultiSigWrapper(multiSig, provider); + await erc20Proxy.transferOwnership.sendTransactionAsync(multiSig.address, { from: initialOwner }); + await erc721Proxy.transferOwnership.sendTransactionAsync(multiSig.address, { from: initialOwner }); + }); + beforeEach(async () => { + await blockchainLifecycle.startAsync(); + }); + afterEach(async () => { + await blockchainLifecycle.revertAsync(); + }); + + describe('constructor', () => { + it('should register passed in assetProxyContracts', async () => { + const assetProxyContractAddresses = [erc20Proxy.address, erc721Proxy.address]; + const newMultiSig = await AssetProxyOwnerContract.deployFrom0xArtifactAsync( + artifacts.AssetProxyOwner, + provider, + txDefaults, + owners, + assetProxyContractAddresses, + REQUIRED_APPROVALS, + SECONDS_TIME_LOCKED, + ); + const isErc20ProxyRegistered = await newMultiSig.isAssetProxyRegistered.callAsync(erc20Proxy.address); + const isErc721ProxyRegistered = await newMultiSig.isAssetProxyRegistered.callAsync(erc721Proxy.address); + expect(isErc20ProxyRegistered).to.equal(true); + expect(isErc721ProxyRegistered).to.equal(true); + }); + it('should throw if a null address is included in assetProxyContracts', async () => { + const assetProxyContractAddresses = [erc20Proxy.address, constants.NULL_ADDRESS]; + return expect( + AssetProxyOwnerContract.deployFrom0xArtifactAsync( + artifacts.AssetProxyOwner, + provider, + txDefaults, + owners, + assetProxyContractAddresses, + REQUIRED_APPROVALS, + SECONDS_TIME_LOCKED, + ), + ).to.be.rejectedWith(constants.REVERT); + }); + }); + + describe('isFunctionRemoveAuthorizedAddress', () => { + it('should throw if data is not for removeAuthorizedAddress', async () => { + const notRemoveAuthorizedAddressData = erc20Proxy.addAuthorizedAddress.getABIEncodedTransactionData( + owners[0], + ); + return expect( + multiSig.isFunctionRemoveAuthorizedAddress.callAsync(notRemoveAuthorizedAddressData), + ).to.be.rejectedWith(constants.REVERT); + }); + + it('should return true if data is for removeAuthorizedAddress', async () => { + const removeAuthorizedAddressData = erc20Proxy.removeAuthorizedAddress.getABIEncodedTransactionData( + owners[0], + ); + const isFunctionRemoveAuthorizedAddress = await multiSig.isFunctionRemoveAuthorizedAddress.callAsync( + removeAuthorizedAddressData, + ); + expect(isFunctionRemoveAuthorizedAddress).to.be.true(); + }); + }); + + describe('registerAssetProxy', () => { + it('should throw if not called by multisig', async () => { + const isRegistered = true; + return expect( + multiSig.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, isRegistered, { from: owners[0] }), + ).to.be.rejectedWith(constants.REVERT); + }); + + it('should register an address if called by multisig after timelock', async () => { + const addressToRegister = erc20Proxy.address; + const isRegistered = true; + const registerAssetProxyData = multiSig.registerAssetProxy.getABIEncodedTransactionData( + addressToRegister, + isRegistered, + ); + const submitTxRes = await multiSigWrapper.submitTransactionAsync( + multiSig.address, + registerAssetProxyData, + owners[0], + ); + const log = submitTxRes.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; + const txId = log.args.transactionId; + + await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); + await web3Wrapper.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber()); + + const executeTxRes = await multiSigWrapper.executeTransactionAsync(txId, owners[0]); + const registerLog = executeTxRes.logs[0] as LogWithDecodedArgs<AssetProxyRegistrationContractEventArgs>; + expect(registerLog.args.assetProxyContract).to.equal(addressToRegister); + expect(registerLog.args.isRegistered).to.equal(isRegistered); + + const isAssetProxyRegistered = await multiSig.isAssetProxyRegistered.callAsync(addressToRegister); + expect(isAssetProxyRegistered).to.equal(isRegistered); + }); + + it('should fail if registering a null address', async () => { + const addressToRegister = constants.NULL_ADDRESS; + const isRegistered = true; + const registerAssetProxyData = multiSig.registerAssetProxy.getABIEncodedTransactionData( + addressToRegister, + isRegistered, + ); + const submitTxRes = await multiSigWrapper.submitTransactionAsync( + multiSig.address, + registerAssetProxyData, + owners[0], + ); + const log = submitTxRes.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; + const txId = log.args.transactionId; + + await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); + await web3Wrapper.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber()); + + const executeTxRes = await multiSigWrapper.executeTransactionAsync(txId, owners[0]); + const failureLog = executeTxRes.logs[0] as LogWithDecodedArgs<ExecutionFailureContractEventArgs>; + expect(failureLog.args.transactionId).to.be.bignumber.equal(txId); + + const isAssetProxyRegistered = await multiSig.isAssetProxyRegistered.callAsync(addressToRegister); + expect(isAssetProxyRegistered).to.equal(false); + }); + }); + + describe('executeRemoveAuthorizedAddress', () => { + before('authorize both proxies and register erc20 proxy', async () => { + // Only register ERC20 proxy + const addressToRegister = erc20Proxy.address; + const isRegistered = true; + const registerAssetProxyData = multiSig.registerAssetProxy.getABIEncodedTransactionData( + addressToRegister, + isRegistered, + ); + const registerAssetProxySubmitRes = await multiSigWrapper.submitTransactionAsync( + multiSig.address, + registerAssetProxyData, + owners[0], + ); + const registerAssetProxySubmitLog = registerAssetProxySubmitRes.logs[0] as LogWithDecodedArgs< + SubmissionContractEventArgs + >; + const registerAssetProxyTxId = registerAssetProxySubmitLog.args.transactionId; + await multiSigWrapper.confirmTransactionAsync(registerAssetProxyTxId, owners[1]); + + const addAuthorizedAddressData = erc20Proxy.addAuthorizedAddress.getABIEncodedTransactionData(authorized); + const erc20AddAuthorizedAddressSubmitRes = await multiSigWrapper.submitTransactionAsync( + erc20Proxy.address, + addAuthorizedAddressData, + owners[0], + ); + const erc721AddAuthorizedAddressSubmitRes = await multiSigWrapper.submitTransactionAsync( + erc721Proxy.address, + addAuthorizedAddressData, + owners[0], + ); + const erc20AddAuthorizedAddressSubmitLog = erc20AddAuthorizedAddressSubmitRes.logs[0] as LogWithDecodedArgs< + SubmissionContractEventArgs + >; + const erc721AddAuthorizedAddressSubmitLog = erc721AddAuthorizedAddressSubmitRes + .logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; + const erc20AddAuthorizedAddressTxId = erc20AddAuthorizedAddressSubmitLog.args.transactionId; + const erc721AddAuthorizedAddressTxId = erc721AddAuthorizedAddressSubmitLog.args.transactionId; + + await multiSigWrapper.confirmTransactionAsync(erc20AddAuthorizedAddressTxId, owners[1]); + await multiSigWrapper.confirmTransactionAsync(erc721AddAuthorizedAddressTxId, owners[1]); + await web3Wrapper.increaseTimeAsync(SECONDS_TIME_LOCKED.toNumber()); + await multiSigWrapper.executeTransactionAsync(registerAssetProxyTxId, owners[0]); + await multiSigWrapper.executeTransactionAsync(erc20AddAuthorizedAddressTxId, owners[0]); + await multiSigWrapper.executeTransactionAsync(erc721AddAuthorizedAddressTxId, owners[0]); + }); + + it('should throw without the required confirmations', async () => { + const removeAuthorizedAddressData = erc20Proxy.removeAuthorizedAddress.getABIEncodedTransactionData( + authorized, + ); + const res = await multiSigWrapper.submitTransactionAsync( + erc20Proxy.address, + removeAuthorizedAddressData, + owners[0], + ); + const log = res.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; + const txId = log.args.transactionId; + + return expect( + multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }), + ).to.be.rejectedWith(constants.REVERT); + }); + + it('should throw if tx destination is not registered', async () => { + const removeAuthorizedAddressData = erc721Proxy.removeAuthorizedAddress.getABIEncodedTransactionData( + authorized, + ); + const res = await multiSigWrapper.submitTransactionAsync( + erc721Proxy.address, + removeAuthorizedAddressData, + owners[0], + ); + const log = res.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; + const txId = log.args.transactionId; + + await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); + + return expect( + multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }), + ).to.be.rejectedWith(constants.REVERT); + }); + + it('should throw if tx data is not for removeAuthorizedAddress', async () => { + const newAuthorized = owners[1]; + const addAuthorizedAddressData = erc20Proxy.addAuthorizedAddress.getABIEncodedTransactionData( + newAuthorized, + ); + const res = await multiSigWrapper.submitTransactionAsync( + erc20Proxy.address, + addAuthorizedAddressData, + owners[0], + ); + const log = res.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; + const txId = log.args.transactionId; + + await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); + + return expect( + multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }), + ).to.be.rejectedWith(constants.REVERT); + }); + + it('should execute removeAuthorizedAddress for registered address if fully confirmed', async () => { + const removeAuthorizedAddressData = erc20Proxy.removeAuthorizedAddress.getABIEncodedTransactionData( + authorized, + ); + const submitRes = await multiSigWrapper.submitTransactionAsync( + erc20Proxy.address, + removeAuthorizedAddressData, + owners[0], + ); + const submitLog = submitRes.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; + const txId = submitLog.args.transactionId; + + await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); + + const execRes = await multiSigWrapper.executeRemoveAuthorizedAddressAsync(txId, owners[0]); + const execLog = execRes.logs[0] as LogWithDecodedArgs<ExecutionContractEventArgs>; + expect(execLog.args.transactionId).to.be.bignumber.equal(txId); + + const tx = await multiSig.transactions.callAsync(txId); + const isExecuted = tx[3]; + expect(isExecuted).to.equal(true); + + const isAuthorized = await erc20Proxy.authorized.callAsync(authorized); + expect(isAuthorized).to.equal(false); + }); + + it('should throw if already executed', async () => { + const removeAuthorizedAddressData = erc20Proxy.removeAuthorizedAddress.getABIEncodedTransactionData( + authorized, + ); + const submitRes = await multiSigWrapper.submitTransactionAsync( + erc20Proxy.address, + removeAuthorizedAddressData, + owners[0], + ); + const submitLog = submitRes.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; + const txId = submitLog.args.transactionId; + + await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); + + const execRes = await multiSigWrapper.executeRemoveAuthorizedAddressAsync(txId, owners[0]); + const execLog = execRes.logs[0] as LogWithDecodedArgs<ExecutionContractEventArgs>; + expect(execLog.args.transactionId).to.be.bignumber.equal(txId); + + const tx = await multiSig.transactions.callAsync(txId); + const isExecuted = tx[3]; + expect(isExecuted).to.equal(true); + + return expect( + multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }), + ).to.be.rejectedWith(constants.REVERT); + }); + }); +}); diff --git a/packages/contracts/test/exchange/core.ts b/packages/contracts/test/exchange/core.ts index f5cae7c7c..be8d14cb0 100644 --- a/packages/contracts/test/exchange/core.ts +++ b/packages/contracts/test/exchange/core.ts @@ -127,11 +127,6 @@ describe('Exchange core', () => { afterEach(async () => { await blockchainLifecycle.revertAsync(); }); - describe('internal functions', () => { - it('should include transferViaTokenTransferProxy', () => { - expect((exchange as any).transferViaTokenTransferProxy).to.be.undefined(); - }); - }); describe('fillOrder', () => { beforeEach(async () => { @@ -708,7 +703,7 @@ describe('Exchange core', () => { // Create 3 orders with makerEpoch values: 0,1,2,3 // Since we cancelled with makerEpoch=1, orders with makerEpoch<=1 will not be processed erc20Balances = await erc20Wrapper.getBalancesAsync(); - const signedOrders = await Promise.all([ + const signedOrders = [ orderFactory.newSignedOrder({ makerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(9), 18), takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(9), 18), @@ -729,7 +724,7 @@ describe('Exchange core', () => { takerAssetAmount: Web3Wrapper.toBaseUnitAmount(new BigNumber(7979), 18), salt: new BigNumber(3), }), - ]); + ]; await exchangeWrapper.batchFillOrdersNoThrowAsync(signedOrders, takerAddress); const newBalances = await erc20Wrapper.getBalancesAsync(); diff --git a/packages/contracts/test/libraries/lib_bytes.ts b/packages/contracts/test/libraries/lib_bytes.ts index ce3adbdae..968bac300 100644 --- a/packages/contracts/test/libraries/lib_bytes.ts +++ b/packages/contracts/test/libraries/lib_bytes.ts @@ -248,4 +248,18 @@ describe('LibBytes', () => { it('should fail if the length between the offset and end of the byte array is too short to hold a uint256)', async () => {}); }); */ + + describe('readFirst4', () => { + it('should revert if byte array has a length < 4', async () => { + const byteArrayLessThan4Bytes = '0x010101'; + return expect(libBytes.publicReadFirst4.callAsync(byteArrayLessThan4Bytes)).to.be.rejectedWith( + constants.REVERT, + ); + }); + it('should return the first 4 bytes of a byte array of arbitrary length', async () => { + const first4Bytes = await libBytes.publicReadFirst4.callAsync(byteArrayLongerThan32Bytes); + const expectedFirst4Bytes = byteArrayLongerThan32Bytes.slice(0, 10); + expect(first4Bytes).to.equal(expectedFirst4Bytes); + }); + }); }); diff --git a/packages/contracts/test/multi_sig_with_time_lock.ts b/packages/contracts/test/multi_sig_with_time_lock.ts index 732077df2..ace0f0045 100644 --- a/packages/contracts/test/multi_sig_with_time_lock.ts +++ b/packages/contracts/test/multi_sig_with_time_lock.ts @@ -1,40 +1,39 @@ import { BlockchainLifecycle, web3Factory } from '@0xproject/dev-utils'; import { LogWithDecodedArgs } from '@0xproject/types'; -import { AbiDecoder, BigNumber } from '@0xproject/utils'; +import { BigNumber } from '@0xproject/utils'; import { Web3Wrapper } from '@0xproject/web3-wrapper'; import * as chai from 'chai'; +import * as _ from 'lodash'; import 'make-promises-safe'; import * as Web3 from 'web3'; -import * as multiSigWalletJSON from '../../build/contracts/MultiSigWalletWithTimeLock.json'; -import { MultiSigWalletContract } from '../src/contract_wrappers/generated/multi_sig_wallet'; -import { MultiSigWalletWithTimeLockContract } from '../src/contract_wrappers/generated/multi_sig_wallet_with_time_lock'; +import { + MultiSigWalletWithTimeLockContract, + SubmissionContractEventArgs, +} from '../src/contract_wrappers/generated/multi_sig_wallet_with_time_lock'; import { artifacts } from '../src/utils/artifacts'; import { chaiSetup } from '../src/utils/chai_setup'; import { constants } from '../src/utils/constants'; import { MultiSigWrapper } from '../src/utils/multi_sig_wrapper'; -import { SubmissionContractEventArgs } from '../src/utils/types'; import { provider, txDefaults, web3Wrapper } from '../src/utils/web3_wrapper'; -const MULTI_SIG_ABI = artifacts.MultiSigWalletWithTimeLock.compilerOutput.abi; chaiSetup.configure(); const expect = chai.expect; const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -const abiDecoder = new AbiDecoder([MULTI_SIG_ABI]); describe('MultiSigWalletWithTimeLock', () => { let owners: string[]; + const REQUIRED_APPROVALS = new BigNumber(2); + const SECONDS_TIME_LOCKED = new BigNumber(1000000); + before(async () => { const accounts = await web3Wrapper.getAvailableAddressesAsync(); owners = [accounts[0], accounts[1]]; }); - const SIGNATURES_REQUIRED = new BigNumber(2); - const SECONDS_TIME_LOCKED = new BigNumber(10000); let multiSig: MultiSigWalletWithTimeLockContract; let multiSigWrapper: MultiSigWrapper; - let txId: BigNumber; - let initialSecondsTimeLocked: number; + beforeEach(async () => { await blockchainLifecycle.startAsync(); }); @@ -51,19 +50,18 @@ describe('MultiSigWalletWithTimeLock', () => { await blockchainLifecycle.revertAsync(); }); before('deploy a wallet', async () => { + const secondsTimeLocked = new BigNumber(0); multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync( artifacts.MultiSigWalletWithTimeLock, provider, txDefaults, owners, - SIGNATURES_REQUIRED, - new BigNumber(0), + REQUIRED_APPROVALS, + secondsTimeLocked, ); - multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract); - - const secondsTimeLocked = await multiSig.secondsTimeLocked.callAsync(); - initialSecondsTimeLocked = secondsTimeLocked.toNumber(); + multiSigWrapper = new MultiSigWrapper(multiSig, provider); }); + it('should throw when not called by wallet', async () => { return expect( multiSig.changeTimeLock.sendTransactionAsync(SECONDS_TIME_LOCKED, { from: owners[0] }), @@ -72,22 +70,11 @@ describe('MultiSigWalletWithTimeLock', () => { 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.toNumber()], - }; - const txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); - const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync( - txHash, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - const log = abiDecoder.tryToDecodeLogOrNoop(txReceipt.logs[0]) as LogWithDecodedArgs< - SubmissionContractEventArgs - >; + const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(SECONDS_TIME_LOCKED); + const res = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]); + const log = res.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; + const txId = log.args.transactionId; - txId = log.args.transactionId; return expect( multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }), ).to.be.rejectedWith(constants.REVERT); @@ -95,28 +82,13 @@ describe('MultiSigWalletWithTimeLock', () => { it('should set confirmation time with enough confirmations', async () => { const destination = multiSig.address; - const from = owners[0]; - const dataParams = { - name: 'changeTimeLock', - abi: MULTI_SIG_ABI, - args: [SECONDS_TIME_LOCKED.toNumber()], - }; - let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); - const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync( - txHash, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - const log = abiDecoder.tryToDecodeLogOrNoop(txReceipt.logs[0]) as LogWithDecodedArgs< - SubmissionContractEventArgs - >; + const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(SECONDS_TIME_LOCKED); + const subRes = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]); + const subLog = subRes.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; + const txId = subLog.args.transactionId; - txId = log.args.transactionId; - txHash = await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] }); - const res = await web3Wrapper.awaitTransactionSuccessAsync( - txHash, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - expect(res.logs).to.have.length(2); + const confirmRes = await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); + expect(confirmRes.logs).to.have.length(2); const blockNum = await web3Wrapper.getBlockNumberAsync(); const blockInfo = await web3Wrapper.getBlockAsync(blockNum); @@ -128,33 +100,13 @@ describe('MultiSigWalletWithTimeLock', () => { it('should be executable with enough confirmations and secondsTimeLocked of 0', async () => { const destination = multiSig.address; - const from = owners[0]; - const dataParams = { - name: 'changeTimeLock', - abi: MULTI_SIG_ABI, - args: [SECONDS_TIME_LOCKED.toNumber()], - }; - let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); - const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync( - txHash, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - const log = abiDecoder.tryToDecodeLogOrNoop(txReceipt.logs[0]) as LogWithDecodedArgs< - SubmissionContractEventArgs - >; - - txId = log.args.transactionId; - txHash = await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] }); - await web3Wrapper.awaitTransactionSuccessAsync(txHash, constants.AWAIT_TRANSACTION_MINED_MS); - - expect(initialSecondsTimeLocked).to.be.equal(0); + const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(SECONDS_TIME_LOCKED); + const subRes = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]); + const subLog = subRes.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; + const txId = subLog.args.transactionId; - txHash = await multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }); - const res = await web3Wrapper.awaitTransactionSuccessAsync( - txHash, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - expect(res.logs).to.have.length(2); + await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); + await multiSigWrapper.executeTransactionAsync(txId, owners[1]); const secondsTimeLocked = new BigNumber(await multiSig.secondsTimeLocked.callAsync()); expect(secondsTimeLocked).to.be.bignumber.equal(SECONDS_TIME_LOCKED); @@ -167,45 +119,29 @@ describe('MultiSigWalletWithTimeLock', () => { after(async () => { await blockchainLifecycle.revertAsync(); }); - before('deploy a wallet', async () => { + let txId: BigNumber; + const newSecondsTimeLocked = new BigNumber(0); + before('deploy a wallet, submit transaction to change timelock, and confirm the transaction', async () => { multiSig = await MultiSigWalletWithTimeLockContract.deployFrom0xArtifactAsync( artifacts.MultiSigWalletWithTimeLock, provider, txDefaults, owners, - SIGNATURES_REQUIRED, + REQUIRED_APPROVALS, SECONDS_TIME_LOCKED, ); - multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract); + multiSigWrapper = new MultiSigWrapper(multiSig, provider); - const secondsTimeLocked = await multiSig.secondsTimeLocked.callAsync(); - initialSecondsTimeLocked = secondsTimeLocked.toNumber(); - const destination = multiSig.address; - const from = owners[0]; - const dataParams = { - name: 'changeTimeLock', - abi: MULTI_SIG_ABI, - args: [newSecondsTimeLocked], - }; - let txHash = await multiSigWrapper.submitTransactionAsync(destination, from, dataParams); - let txReceipt = await web3Wrapper.awaitTransactionSuccessAsync( - txHash, - constants.AWAIT_TRANSACTION_MINED_MS, + const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(newSecondsTimeLocked); + const res = await multiSigWrapper.submitTransactionAsync( + multiSig.address, + changeTimeLockData, + owners[0], ); - const log = abiDecoder.tryToDecodeLogOrNoop(txReceipt.logs[0]) as LogWithDecodedArgs< - SubmissionContractEventArgs - >; + const log = res.logs[0] as LogWithDecodedArgs<SubmissionContractEventArgs>; txId = log.args.transactionId; - txHash = await multiSig.confirmTransaction.sendTransactionAsync(txId, { - from: owners[1], - }); - txReceipt = await web3Wrapper.awaitTransactionSuccessAsync( - txHash, - constants.AWAIT_TRANSACTION_MINED_MS, - ); - expect(txReceipt.logs).to.have.length(2); + await multiSigWrapper.confirmTransactionAsync(txId, owners[1]); }); - const newSecondsTimeLocked = 0; it('should throw if it has enough confirmations but is not past the time lock', async () => { return expect( multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }), diff --git a/packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts b/packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts deleted file mode 100644 index dcd206b1c..000000000 --- a/packages/contracts/test/multi_sig_with_time_lock_except_remove_auth_addr.ts +++ /dev/null @@ -1,205 +0,0 @@ -/* - * - * @TODO: Before deploying, the MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress contract must be updated - * to have a mapping of all approved addresses. These tests must be updated appropriately. - * For now, these tests have been commented out by @hysz (greg@0xproject.com). - * -import { LogWithDecodedArgs, ZeroEx } from '0x.js'; -import { BlockchainLifecycle, devConstants, web3Factory } from '@0xproject/dev-utils'; -import { AbiDecoder, BigNumber } from '@0xproject/utils'; -import { Web3Wrapper } from '@0xproject/web3-wrapper'; -import * as chai from 'chai'; -import 'make-promises-safe'; -import * as Web3 from 'web3'; - -import { MultiSigWalletContract } from '../src/contract_wrappers/generated/multi_sig_wallet'; -import { MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract } from '../src/contract_wrappers/generated/multi_sig_wallet_with_time_lock_except_remove_authorized_address'; -import { TokenTransferProxyContract } from '../src/contract_wrappers/generated/token_transfer_proxy'; -import { artifacts } from '../src/utils/artifacts'; -import { constants } from '../src/utils/constants'; -import { crypto } from '../src/utils/crypto'; -import { MultiSigWrapper } from '../src/utils/multi_sig_wrapper'; -import { ContractName, SubmissionContractEventArgs, TransactionDataParams } from '../src/utils/types'; - -import { chaiSetup } from './utils/chai_setup'; - -import { provider, txDefaults, web3Wrapper } from './utils/web3_wrapper'; - -const PROXY_ABI = artifacts.TokenTransferProxy.compilerOutput.abi; -const MUTISIG_WALLET_WITH_TIME_LOCK_EXCEPT_REMOVE_AUTHORIZED_ADDRESS_ABI = - artifacts.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress.compilerOutput.abi; - -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); -const abiDecoder = new AbiDecoder([MUTISIG_WALLET_WITH_TIME_LOCK_EXCEPT_REMOVE_AUTHORIZED_ADDRESS_ABI]); - -describe('MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress', () => { - const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID }); - let owners: string[]; - const requiredApprovals = new BigNumber(2); - const SECONDS_TIME_LOCKED = new BigNumber(1000000); - - // initialize fake addresses - let authorizedAddress: string; - let unauthorizedAddress: string; - - let tokenTransferProxy: TokenTransferProxyContract; - let multiSig: MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract; - let multiSigWrapper: MultiSigWrapper; - - let validDestination: string; - before(async () => { - const accounts = await web3Wrapper.getAvailableAddressesAsync(); - owners = [accounts[0], accounts[1]]; - [authorizedAddress, unauthorizedAddress] = accounts; - const initialOwner = accounts[0]; - tokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync( - artifacts.TokenTransferProxy, - provider, - txDefaults, - ); - await tokenTransferProxy.addAuthorizedAddress.sendTransactionAsync(authorizedAddress, { - from: initialOwner, - }); - multiSig = await MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddressContract.deployFrom0xArtifactAsync( - artifacts.MultiSigWalletWithTimeLockExceptRemoveAuthorizedAddress, - provider, - txDefaults, - owners, - requiredApprovals, - SECONDS_TIME_LOCKED, - tokenTransferProxy.address, - ); - await tokenTransferProxy.transferOwnership.sendTransactionAsync(multiSig.address, { - from: initialOwner, - }); - multiSigWrapper = new MultiSigWrapper((multiSig as any) as MultiSigWalletContract); - validDestination = tokenTransferProxy.address; - }); - beforeEach(async () => { - await blockchainLifecycle.startAsync(); - }); - afterEach(async () => { - await blockchainLifecycle.revertAsync(); - }); - - 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.callAsync(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.callAsync(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 txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); - const res = await zeroEx.awaitTransactionMinedAsync(txHash); - const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; - const txId = log.args.transactionId; - - return expect( - multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }), - ).to.be.rejectedWith(constants.REVERT); - }); - - it('should throw if tx destination is not the tokenTransferProxy', async () => { - const invalidTokenTransferProxy = await TokenTransferProxyContract.deployFrom0xArtifactAsync( - artifacts.TokenTransferProxy, - provider, - txDefaults, - ); - const invalidDestination = invalidTokenTransferProxy.address; - const dataParams: TransactionDataParams = { - name: 'removeAuthorizedAddress', - abi: PROXY_ABI, - args: [authorizedAddress], - }; - const txHash = await multiSigWrapper.submitTransactionAsync(invalidDestination, owners[0], dataParams); - const res = await zeroEx.awaitTransactionMinedAsync(txHash); - const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; - const txId = log.args.transactionId; - await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] }); - const isConfirmed = await multiSig.isConfirmed.callAsync(txId); - expect(isConfirmed).to.be.true(); - - return expect( - multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }), - ).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 txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); - const res = await zeroEx.awaitTransactionMinedAsync(txHash); - const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; - const txId = log.args.transactionId; - await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] }); - const isConfirmed = await multiSig.isConfirmed.callAsync(txId); - expect(isConfirmed).to.be.true(); - - return expect( - multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }), - ).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 txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); - const res = await zeroEx.awaitTransactionMinedAsync(txHash); - const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; - const txId = log.args.transactionId; - await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] }); - const isConfirmed = await multiSig.isConfirmed.callAsync(txId); - expect(isConfirmed).to.be.true(); - await multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }); - const isAuthorized = await tokenTransferProxy.authorized.callAsync(authorizedAddress); - expect(isAuthorized).to.be.false(); - }); - - it('should throw if already executed', async () => { - const dataParams: TransactionDataParams = { - name: 'removeAuthorizedAddress', - abi: PROXY_ABI, - args: [authorizedAddress], - }; - const txHash = await multiSigWrapper.submitTransactionAsync(validDestination, owners[0], dataParams); - const res = await zeroEx.awaitTransactionMinedAsync(txHash); - const log = abiDecoder.tryToDecodeLogOrNoop(res.logs[0]) as LogWithDecodedArgs<SubmissionContractEventArgs>; - const txId = log.args.transactionId; - await multiSig.confirmTransaction.sendTransactionAsync(txId, { from: owners[1] }); - const isConfirmed = await multiSig.isConfirmed.callAsync(txId); - expect(isConfirmed).to.be.true(); - await multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }); - const tx = await multiSig.transactions.callAsync(txId); - const isExecuted = tx[3]; - expect(isExecuted).to.be.true(); - return expect( - multiSig.executeRemoveAuthorizedAddress.sendTransactionAsync(txId, { from: owners[1] }), - ).to.be.rejectedWith(constants.REVERT); - }); - }); -}); - -*/ |