aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/test/asset_proxy_owner.ts
diff options
context:
space:
mode:
authorAmir Bandeali <abandeali1@gmail.com>2018-05-05 10:09:01 +0800
committerAmir Bandeali <abandeali1@gmail.com>2018-05-25 06:39:19 +0800
commit22ad9e1e1a0c6d2fa5c1b1249d02ef119ef4517e (patch)
tree3eae13e15b47bae477c56df31c4f690cc935316a /packages/contracts/test/asset_proxy_owner.ts
parentcc44f5f75d8a1152be9fd49491a9c194cfa2b285 (diff)
downloaddexon-0x-contracts-22ad9e1e1a0c6d2fa5c1b1249d02ef119ef4517e.tar.gz
dexon-0x-contracts-22ad9e1e1a0c6d2fa5c1b1249d02ef119ef4517e.tar.zst
dexon-0x-contracts-22ad9e1e1a0c6d2fa5c1b1249d02ef119ef4517e.zip
Address feedback, rename contract to AssetProxyOwner
Diffstat (limited to 'packages/contracts/test/asset_proxy_owner.ts')
-rw-r--r--packages/contracts/test/asset_proxy_owner.ts358
1 files changed, 358 insertions, 0 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..7b470e82e
--- /dev/null
+++ b/packages/contracts/test/asset_proxy_owner.ts
@@ -0,0 +1,358 @@
+import { LogWithDecodedArgs, ZeroEx } from '0x.js';
+import { BlockchainLifecycle } from '@0xproject/dev-utils';
+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);
+const zeroEx = new ZeroEx(provider, { networkId: constants.TESTRPC_NETWORK_ID });
+
+describe('AssetProxyOwner', () => {
+ let owners: string[];
+ let authorized: string;
+ const requiredApprovals = 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,
+ requiredApprovals,
+ SECONDS_TIME_LOCKED,
+ defaultAssetProxyContractAddresses,
+ ]);
+ multiSigWrapper = new MultiSigWrapper(multiSig, zeroEx);
+ 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,
+ requiredApprovals,
+ SECONDS_TIME_LOCKED,
+ assetProxyContractAddresses,
+ );
+ 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, ZeroEx.NULL_ADDRESS];
+ expect(
+ AssetProxyOwnerContract.deployFrom0xArtifactAsync(
+ artifacts.AssetProxyOwner,
+ provider,
+ txDefaults,
+ owners,
+ requiredApprovals,
+ SECONDS_TIME_LOCKED,
+ assetProxyContractAddresses,
+ ),
+ ).to.be.rejectedWith(constants.REVERT);
+ });
+ });
+ describe('readFirst4', () => {
+ it('should return the first 4 bytes of a byte array of arbitrary length', async () => {
+ const addAuthorizedAddressData = erc20Proxy.addAuthorizedAddress.getABIEncodedTransactionData(owners[0]);
+ const removeAuthorizedAddressData = erc20Proxy.removeAuthorizedAddress.getABIEncodedTransactionData(
+ owners[0],
+ );
+ const expectedAddAuthorizedAddressSelector = addAuthorizedAddressData.slice(0, 10);
+ const expectedRemoveAuthorizedAddressSelector = removeAuthorizedAddressData.slice(0, 10);
+ const [addAuthorizedAddressSelector, removeAuthorizedAddressSelector] = await Promise.all([
+ multiSig.readFirst4.callAsync(addAuthorizedAddressData),
+ multiSig.readFirst4.callAsync(removeAuthorizedAddressData),
+ ]);
+ expect(expectedAddAuthorizedAddressSelector).to.equal(addAuthorizedAddressSelector);
+ expect(expectedRemoveAuthorizedAddressSelector).to.equal(removeAuthorizedAddressSelector);
+ });
+ });
+
+ 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;
+ 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 = ZeroEx.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);
+ });
+ });
+});