Merge pull request #2014 from jalextowle/feature/contracts/3.0/utils-unit-tests
Added Unit Tests to Utils
This commit is contained in:
commit
bd42c33daa
@ -46,7 +46,7 @@ describe('Authorizable', () => {
|
|||||||
await blockchainLifecycle.revertAsync();
|
await blockchainLifecycle.revertAsync();
|
||||||
});
|
});
|
||||||
describe('addAuthorizedAddress', () => {
|
describe('addAuthorizedAddress', () => {
|
||||||
it('should throw if not called by owner', async () => {
|
it('should revert if not called by owner', async () => {
|
||||||
const expectedError = new OwnableRevertErrors.OnlyOwnerError(notOwner, owner);
|
const expectedError = new OwnableRevertErrors.OnlyOwnerError(notOwner, owner);
|
||||||
const tx = authorizable.addAuthorizedAddress.sendTransactionAsync(notOwner, { from: notOwner });
|
const tx = authorizable.addAuthorizedAddress.sendTransactionAsync(notOwner, { from: notOwner });
|
||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
@ -60,7 +60,7 @@ describe('Authorizable', () => {
|
|||||||
const isAuthorized = await authorizable.authorized.callAsync(address);
|
const isAuthorized = await authorizable.authorized.callAsync(address);
|
||||||
expect(isAuthorized).to.be.true();
|
expect(isAuthorized).to.be.true();
|
||||||
});
|
});
|
||||||
it('should throw if owner attempts to authorize a duplicate address', async () => {
|
it('should revert if owner attempts to authorize a duplicate address', async () => {
|
||||||
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||||
address,
|
address,
|
||||||
{ from: owner },
|
{ from: owner },
|
||||||
@ -74,7 +74,7 @@ describe('Authorizable', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('removeAuthorizedAddress', () => {
|
describe('removeAuthorizedAddress', () => {
|
||||||
it('should throw if not called by owner', async () => {
|
it('should revert if not called by owner', async () => {
|
||||||
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||||
address,
|
address,
|
||||||
{ from: owner },
|
{ from: owner },
|
||||||
@ -100,7 +100,7 @@ describe('Authorizable', () => {
|
|||||||
expect(isAuthorized).to.be.false();
|
expect(isAuthorized).to.be.false();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if owner attempts to remove an address that is not authorized', async () => {
|
it('should revert if owner attempts to remove an address that is not authorized', async () => {
|
||||||
return expectTransactionFailedAsync(
|
return expectTransactionFailedAsync(
|
||||||
authorizable.removeAuthorizedAddress.sendTransactionAsync(address, {
|
authorizable.removeAuthorizedAddress.sendTransactionAsync(address, {
|
||||||
from: owner,
|
from: owner,
|
||||||
@ -111,7 +111,7 @@ describe('Authorizable', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('removeAuthorizedAddressAtIndex', () => {
|
describe('removeAuthorizedAddressAtIndex', () => {
|
||||||
it('should throw if not called by owner', async () => {
|
it('should revert if not called by owner', async () => {
|
||||||
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||||
address,
|
address,
|
||||||
{ from: owner },
|
{ from: owner },
|
||||||
@ -124,7 +124,7 @@ describe('Authorizable', () => {
|
|||||||
});
|
});
|
||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
it('should throw if index is >= authorities.length', async () => {
|
it('should revert if index is >= authorities.length', async () => {
|
||||||
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||||
address,
|
address,
|
||||||
{ from: owner },
|
{ from: owner },
|
||||||
@ -138,7 +138,7 @@ describe('Authorizable', () => {
|
|||||||
RevertReason.IndexOutOfBounds,
|
RevertReason.IndexOutOfBounds,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('should throw if owner attempts to remove an address that is not authorized', async () => {
|
it('should revert if owner attempts to remove an address that is not authorized', async () => {
|
||||||
const index = new BigNumber(0);
|
const index = new BigNumber(0);
|
||||||
return expectTransactionFailedAsync(
|
return expectTransactionFailedAsync(
|
||||||
authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, {
|
authorizable.removeAuthorizedAddressAtIndex.sendTransactionAsync(address, index, {
|
||||||
@ -147,7 +147,7 @@ describe('Authorizable', () => {
|
|||||||
RevertReason.TargetNotAuthorized,
|
RevertReason.TargetNotAuthorized,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it('should throw if address at index does not match target', async () => {
|
it('should revert if address at index does not match target', async () => {
|
||||||
const address1 = address;
|
const address1 = address;
|
||||||
const address2 = notOwner;
|
const address2 = notOwner;
|
||||||
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
await authorizable.addAuthorizedAddress.awaitTransactionSuccessAsync(
|
||||||
|
@ -166,7 +166,7 @@ describe('ERC1155Token', () => {
|
|||||||
];
|
];
|
||||||
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedFinalBalances);
|
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedFinalBalances);
|
||||||
});
|
});
|
||||||
it('should throw if transfer reverts', async () => {
|
it('should revert if transfer reverts', async () => {
|
||||||
// setup test parameters
|
// setup test parameters
|
||||||
const tokenToTransfer = fungibleToken;
|
const tokenToTransfer = fungibleToken;
|
||||||
const valueToTransfer = spenderInitialFungibleBalance.plus(1);
|
const valueToTransfer = spenderInitialFungibleBalance.plus(1);
|
||||||
@ -187,7 +187,7 @@ describe('ERC1155Token', () => {
|
|||||||
);
|
);
|
||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
it('should throw if callback reverts', async () => {
|
it('should revert if callback reverts', async () => {
|
||||||
// setup test parameters
|
// setup test parameters
|
||||||
const tokenToTransfer = fungibleToken;
|
const tokenToTransfer = fungibleToken;
|
||||||
const valueToTransfer = fungibleValueToTransfer;
|
const valueToTransfer = fungibleValueToTransfer;
|
||||||
@ -342,7 +342,7 @@ describe('ERC1155Token', () => {
|
|||||||
];
|
];
|
||||||
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
|
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
|
||||||
});
|
});
|
||||||
it('should throw if transfer reverts', async () => {
|
it('should revert if transfer reverts', async () => {
|
||||||
// setup test parameters
|
// setup test parameters
|
||||||
const tokensToTransfer = [fungibleToken];
|
const tokensToTransfer = [fungibleToken];
|
||||||
const valuesToTransfer = [spenderInitialFungibleBalance.plus(1)];
|
const valuesToTransfer = [spenderInitialFungibleBalance.plus(1)];
|
||||||
@ -363,7 +363,7 @@ describe('ERC1155Token', () => {
|
|||||||
);
|
);
|
||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
it('should throw if callback reverts', async () => {
|
it('should revert if callback reverts', async () => {
|
||||||
// setup test parameters
|
// setup test parameters
|
||||||
const tokensToTransfer = [fungibleToken];
|
const tokensToTransfer = [fungibleToken];
|
||||||
const valuesToTransfer = [fungibleValueToTransfer];
|
const valuesToTransfer = [fungibleValueToTransfer];
|
||||||
@ -417,7 +417,7 @@ describe('ERC1155Token', () => {
|
|||||||
];
|
];
|
||||||
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedFinalBalances);
|
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedFinalBalances);
|
||||||
});
|
});
|
||||||
it('should throw if trying to transfer tokens via safeTransferFrom by an unapproved account', async () => {
|
it('should revert if trying to transfer tokens via safeTransferFrom by an unapproved account', async () => {
|
||||||
// check approval not set
|
// check approval not set
|
||||||
const isApprovedForAllCheck = await erc1155Wrapper.isApprovedForAllAsync(spender, delegatedSpender);
|
const isApprovedForAllCheck = await erc1155Wrapper.isApprovedForAllAsync(spender, delegatedSpender);
|
||||||
expect(isApprovedForAllCheck).to.be.false();
|
expect(isApprovedForAllCheck).to.be.false();
|
||||||
@ -470,7 +470,7 @@ describe('ERC1155Token', () => {
|
|||||||
];
|
];
|
||||||
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
|
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
|
||||||
});
|
});
|
||||||
it('should throw if trying to transfer tokens via safeBatchTransferFrom by an unapproved account', async () => {
|
it('should revert if trying to transfer tokens via safeBatchTransferFrom by an unapproved account', async () => {
|
||||||
// check approval not set
|
// check approval not set
|
||||||
const isApprovedForAllCheck = await erc1155Wrapper.isApprovedForAllAsync(spender, delegatedSpender);
|
const isApprovedForAllCheck = await erc1155Wrapper.isApprovedForAllAsync(spender, delegatedSpender);
|
||||||
expect(isApprovedForAllCheck).to.be.false();
|
expect(isApprovedForAllCheck).to.be.false();
|
||||||
|
@ -54,7 +54,7 @@ describe('UnlimitedAllowanceToken', () => {
|
|||||||
await blockchainLifecycle.revertAsync();
|
await blockchainLifecycle.revertAsync();
|
||||||
});
|
});
|
||||||
describe('transfer', () => {
|
describe('transfer', () => {
|
||||||
it('should throw if owner has insufficient balance', async () => {
|
it('should revert if owner has insufficient balance', async () => {
|
||||||
const ownerBalance = await token.balanceOf.callAsync(owner);
|
const ownerBalance = await token.balanceOf.callAsync(owner);
|
||||||
const amountToTransfer = ownerBalance.plus(1);
|
const amountToTransfer = ownerBalance.plus(1);
|
||||||
return expectContractCallFailedAsync(
|
return expectContractCallFailedAsync(
|
||||||
@ -89,7 +89,7 @@ describe('UnlimitedAllowanceToken', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('transferFrom', () => {
|
describe('transferFrom', () => {
|
||||||
it('should throw if owner has insufficient balance', async () => {
|
it('should revert if owner has insufficient balance', async () => {
|
||||||
const ownerBalance = await token.balanceOf.callAsync(owner);
|
const ownerBalance = await token.balanceOf.callAsync(owner);
|
||||||
const amountToTransfer = ownerBalance.plus(1);
|
const amountToTransfer = ownerBalance.plus(1);
|
||||||
await web3Wrapper.awaitTransactionSuccessAsync(
|
await web3Wrapper.awaitTransactionSuccessAsync(
|
||||||
@ -104,7 +104,7 @@ describe('UnlimitedAllowanceToken', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if spender has insufficient allowance', async () => {
|
it('should revert if spender has insufficient allowance', async () => {
|
||||||
const ownerBalance = await token.balanceOf.callAsync(owner);
|
const ownerBalance = await token.balanceOf.callAsync(owner);
|
||||||
const amountToTransfer = ownerBalance;
|
const amountToTransfer = ownerBalance;
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ describe('EtherToken', () => {
|
|||||||
await blockchainLifecycle.revertAsync();
|
await blockchainLifecycle.revertAsync();
|
||||||
});
|
});
|
||||||
describe('deposit', () => {
|
describe('deposit', () => {
|
||||||
it('should throw if caller attempts to deposit more Ether than caller balance', async () => {
|
it('should revert if caller attempts to deposit more Ether than caller balance', async () => {
|
||||||
const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account);
|
const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account);
|
||||||
const ethToDeposit = initEthBalance.plus(1);
|
const ethToDeposit = initEthBalance.plus(1);
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ describe('EtherToken', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('withdraw', () => {
|
describe('withdraw', () => {
|
||||||
it('should throw if caller attempts to withdraw greater than caller balance', async () => {
|
it('should revert if caller attempts to withdraw greater than caller balance', async () => {
|
||||||
const initEthTokenBalance = await etherToken.balanceOf.callAsync(account);
|
const initEthTokenBalance = await etherToken.balanceOf.callAsync(account);
|
||||||
const ethTokensToWithdraw = initEthTokenBalance.plus(1);
|
const ethTokensToWithdraw = initEthTokenBalance.plus(1);
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@ pragma experimental ABIEncoderV2;
|
|||||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/ReentrancyGuard.sol";
|
import "@0x/contracts-utils/contracts/src/ReentrancyGuard.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/RichErrors.sol";
|
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol";
|
||||||
import "./interfaces/IAssetProxyDispatcher.sol";
|
import "./interfaces/IAssetProxyDispatcher.sol";
|
||||||
|
@ -380,7 +380,7 @@ describe('Exchange core', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if fully filled', async () => {
|
it('should revert if fully filled', async () => {
|
||||||
signedOrder = await orderFactory.newSignedOrderAsync();
|
signedOrder = await orderFactory.newSignedOrderAsync();
|
||||||
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
const orderHashHex = orderHashUtils.getOrderHashHex(signedOrder);
|
||||||
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
|
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress);
|
||||||
@ -423,7 +423,7 @@ describe('Exchange core', () => {
|
|||||||
).to.be.bignumber.equal(signedOrder.takerFee);
|
).to.be.bignumber.equal(signedOrder.takerFee);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if order is expired', async () => {
|
it('should revert if order is expired', async () => {
|
||||||
const currentTimestamp = await getLatestBlockTimestampAsync();
|
const currentTimestamp = await getLatestBlockTimestampAsync();
|
||||||
signedOrder = await orderFactory.newSignedOrderAsync({
|
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||||
expirationTimeSeconds: new BigNumber(currentTimestamp).minus(10),
|
expirationTimeSeconds: new BigNumber(currentTimestamp).minus(10),
|
||||||
@ -742,14 +742,14 @@ describe('Exchange core', () => {
|
|||||||
signedOrder = await orderFactory.newSignedOrderAsync();
|
signedOrder = await orderFactory.newSignedOrderAsync();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if not sent by maker', async () => {
|
it('should revert if not sent by maker', async () => {
|
||||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||||
const expectedError = new ExchangeRevertErrors.InvalidMakerError(orderHash, takerAddress);
|
const expectedError = new ExchangeRevertErrors.InvalidMakerError(orderHash, takerAddress);
|
||||||
const tx = exchangeWrapper.cancelOrderAsync(signedOrder, takerAddress);
|
const tx = exchangeWrapper.cancelOrderAsync(signedOrder, takerAddress);
|
||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if makerAssetAmount is 0', async () => {
|
it('should revert if makerAssetAmount is 0', async () => {
|
||||||
signedOrder = await orderFactory.newSignedOrderAsync({
|
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||||
makerAssetAmount: new BigNumber(0),
|
makerAssetAmount: new BigNumber(0),
|
||||||
});
|
});
|
||||||
@ -762,7 +762,7 @@ describe('Exchange core', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if takerAssetAmount is 0', async () => {
|
it('should revert if takerAssetAmount is 0', async () => {
|
||||||
signedOrder = await orderFactory.newSignedOrderAsync({
|
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||||
takerAssetAmount: new BigNumber(0),
|
takerAssetAmount: new BigNumber(0),
|
||||||
});
|
});
|
||||||
@ -800,7 +800,7 @@ describe('Exchange core', () => {
|
|||||||
expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(logArgs.orderHash);
|
expect(orderHashUtils.getOrderHashHex(signedOrder)).to.be.equal(logArgs.orderHash);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if already cancelled', async () => {
|
it('should revert if already cancelled', async () => {
|
||||||
await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress);
|
await exchangeWrapper.cancelOrderAsync(signedOrder, makerAddress);
|
||||||
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
const orderHash = orderHashUtils.getOrderHashHex(signedOrder);
|
||||||
const expectedError = new ExchangeRevertErrors.OrderStatusError(orderHash, OrderStatus.Cancelled);
|
const expectedError = new ExchangeRevertErrors.OrderStatusError(orderHash, OrderStatus.Cancelled);
|
||||||
@ -808,7 +808,7 @@ describe('Exchange core', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if order is expired', async () => {
|
it('should revert if order is expired', async () => {
|
||||||
const currentTimestamp = await getLatestBlockTimestampAsync();
|
const currentTimestamp = await getLatestBlockTimestampAsync();
|
||||||
signedOrder = await orderFactory.newSignedOrderAsync({
|
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||||
expirationTimeSeconds: new BigNumber(currentTimestamp).minus(10),
|
expirationTimeSeconds: new BigNumber(currentTimestamp).minus(10),
|
||||||
@ -819,7 +819,7 @@ describe('Exchange core', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if rounding error is greater than 0.1%', async () => {
|
it('should revert if rounding error is greater than 0.1%', async () => {
|
||||||
signedOrder = await orderFactory.newSignedOrderAsync({
|
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||||
makerAssetAmount: new BigNumber(1001),
|
makerAssetAmount: new BigNumber(1001),
|
||||||
takerAssetAmount: new BigNumber(3),
|
takerAssetAmount: new BigNumber(3),
|
||||||
@ -936,7 +936,7 @@ describe('Exchange core', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Testing Exchange of ERC721 Tokens', () => {
|
describe('Testing Exchange of ERC721 Tokens', () => {
|
||||||
it('should throw when maker does not own the token with id makerAssetId', async () => {
|
it('should revert when maker does not own the token with id makerAssetId', async () => {
|
||||||
// Construct Exchange parameters
|
// Construct Exchange parameters
|
||||||
const makerAssetId = erc721TakerAssetIds[0];
|
const makerAssetId = erc721TakerAssetIds[0];
|
||||||
const takerAssetId = erc721TakerAssetIds[1];
|
const takerAssetId = erc721TakerAssetIds[1];
|
||||||
@ -963,7 +963,7 @@ describe('Exchange core', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when taker does not own the token with id takerAssetId', async () => {
|
it('should revert when taker does not own the token with id takerAssetId', async () => {
|
||||||
// Construct Exchange parameters
|
// Construct Exchange parameters
|
||||||
const makerAssetId = erc721MakerAssetIds[0];
|
const makerAssetId = erc721MakerAssetIds[0];
|
||||||
const takerAssetId = erc721MakerAssetIds[1];
|
const takerAssetId = erc721MakerAssetIds[1];
|
||||||
@ -990,7 +990,7 @@ describe('Exchange core', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when makerAssetAmount is greater than 1', async () => {
|
it('should revert when makerAssetAmount is greater than 1', async () => {
|
||||||
// Construct Exchange parameters
|
// Construct Exchange parameters
|
||||||
const makerAssetId = erc721MakerAssetIds[0];
|
const makerAssetId = erc721MakerAssetIds[0];
|
||||||
const takerAssetId = erc721TakerAssetIds[0];
|
const takerAssetId = erc721TakerAssetIds[0];
|
||||||
@ -1017,7 +1017,7 @@ describe('Exchange core', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when takerAssetAmount is greater than 1', async () => {
|
it('should revert when takerAssetAmount is greater than 1', async () => {
|
||||||
// Construct Exchange parameters
|
// Construct Exchange parameters
|
||||||
const makerAssetId = erc721MakerAssetIds[0];
|
const makerAssetId = erc721MakerAssetIds[0];
|
||||||
const takerAssetId = erc721TakerAssetIds[0];
|
const takerAssetId = erc721TakerAssetIds[0];
|
||||||
@ -1044,7 +1044,7 @@ describe('Exchange core', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw on partial fill', async () => {
|
it('should revert on partial fill', async () => {
|
||||||
// Construct Exchange parameters
|
// Construct Exchange parameters
|
||||||
const makerAssetId = erc721MakerAssetIds[0];
|
const makerAssetId = erc721MakerAssetIds[0];
|
||||||
signedOrder = await orderFactory.newSignedOrderAsync({
|
signedOrder = await orderFactory.newSignedOrderAsync({
|
||||||
|
@ -114,7 +114,7 @@ describe('AssetProxyDispatcher', () => {
|
|||||||
expect(proxyAddress).to.be.equal(erc721Proxy.address);
|
expect(proxyAddress).to.be.equal(erc721Proxy.address);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if a proxy with the same id is already registered', async () => {
|
it('should revert if a proxy with the same id is already registered', async () => {
|
||||||
// Initial registration
|
// Initial registration
|
||||||
await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, {
|
await assetProxyDispatcher.registerAssetProxy.awaitTransactionSuccessAsync(erc20Proxy.address, {
|
||||||
from: owner,
|
from: owner,
|
||||||
@ -134,7 +134,7 @@ describe('AssetProxyDispatcher', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if requesting address is not owner', async () => {
|
it('should revert if requesting address is not owner', async () => {
|
||||||
const expectedError = new OwnableRevertErrors.OnlyOwnerError(notOwner, owner);
|
const expectedError = new OwnableRevertErrors.OnlyOwnerError(notOwner, owner);
|
||||||
const tx = assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, {
|
const tx = assetProxyDispatcher.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, {
|
||||||
from: notOwner,
|
from: notOwner,
|
||||||
@ -250,7 +250,7 @@ describe('AssetProxyDispatcher', () => {
|
|||||||
expect(newBalances).to.deep.equal(erc20Balances);
|
expect(newBalances).to.deep.equal(erc20Balances);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if dispatching to unregistered proxy', async () => {
|
it('should revert if dispatching to unregistered proxy', async () => {
|
||||||
// Construct metadata for ERC20 proxy
|
// Construct metadata for ERC20 proxy
|
||||||
const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
|
const encodedAssetData = assetDataUtils.encodeERC20AssetData(erc20TokenA.address);
|
||||||
// Perform a transfer from makerAddress to takerAddress
|
// Perform a transfer from makerAddress to takerAddress
|
||||||
|
@ -154,7 +154,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when taker is specified and order is claimed by other', async () => {
|
it('should revert when taker is specified and order is claimed by other', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
orderScenario: {
|
orderScenario: {
|
||||||
@ -165,7 +165,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if makerAssetAmount is 0', async () => {
|
it('should revert if makerAssetAmount is 0', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
orderScenario: {
|
orderScenario: {
|
||||||
@ -177,7 +177,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if takerAssetAmount is 0', async () => {
|
it('should revert if takerAssetAmount is 0', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
orderScenario: {
|
orderScenario: {
|
||||||
@ -189,7 +189,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if takerAssetFillAmount is 0', async () => {
|
it('should revert if takerAssetFillAmount is 0', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.Zero,
|
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.Zero,
|
||||||
@ -197,7 +197,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if an order is expired', async () => {
|
it('should revert if an order is expired', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
orderScenario: {
|
orderScenario: {
|
||||||
@ -310,7 +310,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if maker balance is too low to fill order', async () => {
|
it('should revert if maker balance is too low to fill order', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
makerStateScenario: {
|
makerStateScenario: {
|
||||||
@ -321,7 +321,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if taker balance is too low to fill order', async () => {
|
it('should revert if taker balance is too low to fill order', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
takerStateScenario: {
|
takerStateScenario: {
|
||||||
@ -332,7 +332,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if maker allowances are too low to fill order', async () => {
|
it('should revert if maker allowances are too low to fill order', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
makerStateScenario: {
|
makerStateScenario: {
|
||||||
@ -343,7 +343,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if taker allowances are too low to fill order', async () => {
|
it('should revert if taker allowances are too low to fill order', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
takerStateScenario: {
|
takerStateScenario: {
|
||||||
@ -354,7 +354,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if maker fee balance is too low to fill order', async () => {
|
it('should revert if maker fee balance is too low to fill order', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
makerStateScenario: {
|
makerStateScenario: {
|
||||||
@ -365,7 +365,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if taker fee balance is too low to fill order', async () => {
|
it('should revert if taker fee balance is too low to fill order', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
takerStateScenario: {
|
takerStateScenario: {
|
||||||
@ -376,7 +376,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if maker fee allowances are too low to fill order', async () => {
|
it('should revert if maker fee allowances are too low to fill order', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
makerStateScenario: {
|
makerStateScenario: {
|
||||||
@ -387,7 +387,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
|
|||||||
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if taker fee allowances are too low to fill order', async () => {
|
it('should revert if taker fee allowances are too low to fill order', async () => {
|
||||||
const fillScenario = {
|
const fillScenario = {
|
||||||
...defaultFillScenario,
|
...defaultFillScenario,
|
||||||
takerStateScenario: {
|
takerStateScenario: {
|
||||||
|
@ -1286,7 +1286,7 @@ describe('matchOrders', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should throw if left order is not fillable', async () => {
|
it('Should revert if left order is not fillable', async () => {
|
||||||
// Create orders to match
|
// Create orders to match
|
||||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
||||||
@ -1305,7 +1305,7 @@ describe('matchOrders', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should throw if right order is not fillable', async () => {
|
it('Should revert if right order is not fillable', async () => {
|
||||||
// Create orders to match
|
// Create orders to match
|
||||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
||||||
@ -1324,7 +1324,7 @@ describe('matchOrders', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if there is not a positive spread', async () => {
|
it('should revert if there is not a positive spread', async () => {
|
||||||
// Create orders to match
|
// Create orders to match
|
||||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
||||||
@ -1342,7 +1342,7 @@ describe('matchOrders', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if the left maker asset is not equal to the right taker asset ', async () => {
|
it('should revert if the left maker asset is not equal to the right taker asset ', async () => {
|
||||||
// Create orders to match
|
// Create orders to match
|
||||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
||||||
@ -1373,7 +1373,7 @@ describe('matchOrders', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if the right maker asset is not equal to the left taker asset', async () => {
|
it('should revert if the right maker asset is not equal to the left taker asset', async () => {
|
||||||
// Create orders to match
|
// Create orders to match
|
||||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||||
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
|
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
|
||||||
@ -2416,7 +2416,7 @@ describe('matchOrders', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should throw if left order is not fillable', async () => {
|
it('Should revert if left order is not fillable', async () => {
|
||||||
// Create orders to match
|
// Create orders to match
|
||||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
||||||
@ -2435,7 +2435,7 @@ describe('matchOrders', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Should throw if right order is not fillable', async () => {
|
it('Should revert if right order is not fillable', async () => {
|
||||||
// Create orders to match
|
// Create orders to match
|
||||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
||||||
@ -2454,7 +2454,7 @@ describe('matchOrders', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if there is not a positive spread', async () => {
|
it('should revert if there is not a positive spread', async () => {
|
||||||
// Create orders to match
|
// Create orders to match
|
||||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
||||||
@ -2472,7 +2472,7 @@ describe('matchOrders', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if the left maker asset is not equal to the right taker asset ', async () => {
|
it('should revert if the left maker asset is not equal to the right taker asset ', async () => {
|
||||||
// Create orders to match
|
// Create orders to match
|
||||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||||
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
makerAssetAmount: Web3Wrapper.toBaseUnitAmount(5, 18),
|
||||||
@ -2503,7 +2503,7 @@ describe('matchOrders', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if the right maker asset is not equal to the left taker asset', async () => {
|
it('should revert if the right maker asset is not equal to the left taker asset', async () => {
|
||||||
// Create orders to match
|
// Create orders to match
|
||||||
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
const signedOrderLeft = await orderFactoryLeft.newSignedOrderAsync({
|
||||||
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
|
takerAssetData: assetDataUtils.encodeERC20AssetData(defaultERC20MakerAssetAddress),
|
||||||
|
@ -495,7 +495,7 @@ describe('MixinSignatureValidator', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when SignatureType=Validator, signature is valid and validator is not approved', async () => {
|
it('should revert when SignatureType=Validator, signature is valid and validator is not approved', async () => {
|
||||||
// Set approval of signature validator to false
|
// Set approval of signature validator to false
|
||||||
await signatureValidator.setSignatureValidatorApproval.awaitTransactionSuccessAsync(
|
await signatureValidator.setSignatureValidatorApproval.awaitTransactionSuccessAsync(
|
||||||
validatorWallet.address,
|
validatorWallet.address,
|
||||||
@ -702,7 +702,7 @@ describe('MixinSignatureValidator', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when SignatureType=Validator, signature is valid and validator is not approved', async () => {
|
it('should revert when SignatureType=Validator, signature is valid and validator is not approved', async () => {
|
||||||
// Set approval of signature validator to false
|
// Set approval of signature validator to false
|
||||||
await signatureValidator.setSignatureValidatorApproval.awaitTransactionSuccessAsync(
|
await signatureValidator.setSignatureValidatorApproval.awaitTransactionSuccessAsync(
|
||||||
validatorWallet.address,
|
validatorWallet.address,
|
||||||
|
@ -234,7 +234,7 @@ describe('Exchange wrappers', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if a signedOrder is expired', async () => {
|
it('should revert if a signedOrder is expired', async () => {
|
||||||
const currentTimestamp = await getLatestBlockTimestampAsync();
|
const currentTimestamp = await getLatestBlockTimestampAsync();
|
||||||
const signedOrder = await orderFactory.newSignedOrderAsync({
|
const signedOrder = await orderFactory.newSignedOrderAsync({
|
||||||
expirationTimeSeconds: new BigNumber(currentTimestamp).minus(10),
|
expirationTimeSeconds: new BigNumber(currentTimestamp).minus(10),
|
||||||
@ -245,7 +245,7 @@ describe('Exchange wrappers', () => {
|
|||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if entire takerAssetFillAmount not filled', async () => {
|
it('should revert if entire takerAssetFillAmount not filled', async () => {
|
||||||
const signedOrder = await orderFactory.newSignedOrderAsync();
|
const signedOrder = await orderFactory.newSignedOrderAsync();
|
||||||
|
|
||||||
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
|
await exchangeWrapper.fillOrderAsync(signedOrder, takerAddress, {
|
||||||
@ -815,7 +815,7 @@ describe('Exchange wrappers', () => {
|
|||||||
expect(newBalances).to.be.deep.equal(erc20Balances);
|
expect(newBalances).to.be.deep.equal(erc20Balances);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if a single signedOrder does not fill the expected amount', async () => {
|
it('should revert if a single signedOrder does not fill the expected amount', async () => {
|
||||||
const takerAssetFillAmounts: BigNumber[] = [];
|
const takerAssetFillAmounts: BigNumber[] = [];
|
||||||
_.forEach(signedOrders, signedOrder => {
|
_.forEach(signedOrders, signedOrder => {
|
||||||
const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
|
const takerAssetFillAmount = signedOrder.takerAssetAmount.div(2);
|
||||||
@ -922,7 +922,7 @@ describe('Exchange wrappers', () => {
|
|||||||
expect(newBalances).to.be.deep.equal(erc20Balances);
|
expect(newBalances).to.be.deep.equal(erc20Balances);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not throw if an order is invalid and fill the remaining orders', async () => {
|
it('should not revert if an order is invalid and fill the remaining orders', async () => {
|
||||||
const makerAssetAddress = erc20TokenA.address;
|
const makerAssetAddress = erc20TokenA.address;
|
||||||
const takerAssetAddress = erc20TokenB.address;
|
const takerAssetAddress = erc20TokenB.address;
|
||||||
|
|
||||||
@ -1132,7 +1132,7 @@ describe('Exchange wrappers', () => {
|
|||||||
expect(newBalances).to.be.deep.equal(erc20Balances);
|
expect(newBalances).to.be.deep.equal(erc20Balances);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when a signedOrder does not use the same takerAssetAddress', async () => {
|
it('should revert when a signedOrder does not use the same takerAssetAddress', async () => {
|
||||||
signedOrders = [
|
signedOrders = [
|
||||||
await orderFactory.newSignedOrderAsync(),
|
await orderFactory.newSignedOrderAsync(),
|
||||||
await orderFactory.newSignedOrderAsync({
|
await orderFactory.newSignedOrderAsync({
|
||||||
@ -1510,7 +1510,7 @@ describe('Exchange wrappers', () => {
|
|||||||
expect(newBalances).to.be.deep.equal(erc20Balances);
|
expect(newBalances).to.be.deep.equal(erc20Balances);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when a signedOrder does not use the same makerAssetAddress', async () => {
|
it('should revert when a signedOrder does not use the same makerAssetAddress', async () => {
|
||||||
signedOrders = [
|
signedOrders = [
|
||||||
await orderFactory.newSignedOrderAsync(),
|
await orderFactory.newSignedOrderAsync(),
|
||||||
await orderFactory.newSignedOrderAsync({
|
await orderFactory.newSignedOrderAsync({
|
||||||
|
@ -115,7 +115,7 @@ describe('AssetProxyOwner', () => {
|
|||||||
expect(isErc20ProxyRegistered).to.equal(true);
|
expect(isErc20ProxyRegistered).to.equal(true);
|
||||||
expect(isErc721ProxyRegistered).to.equal(true);
|
expect(isErc721ProxyRegistered).to.equal(true);
|
||||||
});
|
});
|
||||||
it('should throw if a null address is included in assetProxyContracts', async () => {
|
it('should revert if a null address is included in assetProxyContracts', async () => {
|
||||||
const assetProxyContractAddresses = [erc20Proxy.address, constants.NULL_ADDRESS];
|
const assetProxyContractAddresses = [erc20Proxy.address, constants.NULL_ADDRESS];
|
||||||
return expectContractCreationFailedAsync(
|
return expectContractCreationFailedAsync(
|
||||||
(AssetProxyOwnerContract.deployFrom0xArtifactAsync(
|
(AssetProxyOwnerContract.deployFrom0xArtifactAsync(
|
||||||
@ -158,7 +158,7 @@ describe('AssetProxyOwner', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('registerAssetProxy', () => {
|
describe('registerAssetProxy', () => {
|
||||||
it('should throw if not called by multisig', async () => {
|
it('should revert if not called by multisig', async () => {
|
||||||
const isRegistered = true;
|
const isRegistered = true;
|
||||||
return expectTransactionFailedWithoutReasonAsync(
|
return expectTransactionFailedWithoutReasonAsync(
|
||||||
testAssetProxyOwner.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, isRegistered, {
|
testAssetProxyOwner.registerAssetProxy.sendTransactionAsync(erc20Proxy.address, isRegistered, {
|
||||||
@ -338,7 +338,7 @@ describe('AssetProxyOwner', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('executeRemoveAuthorizedAddressAtIndex', () => {
|
describe('executeRemoveAuthorizedAddressAtIndex', () => {
|
||||||
it('should throw without the required confirmations', async () => {
|
it('should revert without the required confirmations', async () => {
|
||||||
const removeAuthorizedAddressAtIndexData = erc20Proxy.removeAuthorizedAddressAtIndex.getABIEncodedTransactionData(
|
const removeAuthorizedAddressAtIndexData = erc20Proxy.removeAuthorizedAddressAtIndex.getABIEncodedTransactionData(
|
||||||
authorized,
|
authorized,
|
||||||
erc20Index,
|
erc20Index,
|
||||||
@ -359,7 +359,7 @@ describe('AssetProxyOwner', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if tx destination is not registered', async () => {
|
it('should revert if tx destination is not registered', async () => {
|
||||||
const removeAuthorizedAddressAtIndexData = erc721Proxy.removeAuthorizedAddressAtIndex.getABIEncodedTransactionData(
|
const removeAuthorizedAddressAtIndexData = erc721Proxy.removeAuthorizedAddressAtIndex.getABIEncodedTransactionData(
|
||||||
authorized,
|
authorized,
|
||||||
erc721Index,
|
erc721Index,
|
||||||
@ -382,7 +382,7 @@ describe('AssetProxyOwner', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if tx data is not for removeAuthorizedAddressAtIndex', async () => {
|
it('should revert if tx data is not for removeAuthorizedAddressAtIndex', async () => {
|
||||||
const newAuthorized = owners[1];
|
const newAuthorized = owners[1];
|
||||||
const addAuthorizedAddressData = erc20Proxy.addAuthorizedAddress.getABIEncodedTransactionData(
|
const addAuthorizedAddressData = erc20Proxy.addAuthorizedAddress.getABIEncodedTransactionData(
|
||||||
newAuthorized,
|
newAuthorized,
|
||||||
@ -468,7 +468,7 @@ describe('AssetProxyOwner', () => {
|
|||||||
expect(isAuthorizedAfter).to.equal(false);
|
expect(isAuthorizedAfter).to.equal(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if already executed', async () => {
|
it('should revert if already executed', async () => {
|
||||||
const removeAuthorizedAddressAtIndexData = erc20Proxy.removeAuthorizedAddressAtIndex.getABIEncodedTransactionData(
|
const removeAuthorizedAddressAtIndexData = erc20Proxy.removeAuthorizedAddressAtIndex.getABIEncodedTransactionData(
|
||||||
authorized,
|
authorized,
|
||||||
erc20Index,
|
erc20Index,
|
||||||
|
@ -241,13 +241,13 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
multiSigWrapper = new MultiSigWrapper(multiSig, provider);
|
multiSigWrapper = new MultiSigWrapper(multiSig, provider);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw when not called by wallet', async () => {
|
it('should revert when not called by wallet', async () => {
|
||||||
return expectTransactionFailedWithoutReasonAsync(
|
return expectTransactionFailedWithoutReasonAsync(
|
||||||
multiSig.changeTimeLock.sendTransactionAsync(SECONDS_TIME_LOCKED, { from: owners[0] }),
|
multiSig.changeTimeLock.sendTransactionAsync(SECONDS_TIME_LOCKED, { from: owners[0] }),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw without enough confirmations', async () => {
|
it('should revert without enough confirmations', async () => {
|
||||||
const destination = multiSig.address;
|
const destination = multiSig.address;
|
||||||
const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(SECONDS_TIME_LOCKED);
|
const changeTimeLockData = multiSig.changeTimeLock.getABIEncodedTransactionData(SECONDS_TIME_LOCKED);
|
||||||
const res = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]);
|
const res = await multiSigWrapper.submitTransactionAsync(destination, changeTimeLockData, owners[0]);
|
||||||
@ -325,7 +325,7 @@ describe('MultiSigWalletWithTimeLock', () => {
|
|||||||
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
await multiSigWrapper.confirmTransactionAsync(txId, owners[1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if it has enough confirmations but is not past the time lock', async () => {
|
it('should revert if it has enough confirmations but is not past the time lock', async () => {
|
||||||
return expectTransactionFailedAsync(
|
return expectTransactionFailedAsync(
|
||||||
multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }),
|
multiSig.executeTransaction.sendTransactionAsync(txId, { from: owners[0] }),
|
||||||
RevertReason.TimeLockIncomplete,
|
RevertReason.TimeLockIncomplete,
|
||||||
|
@ -42,6 +42,7 @@ export const constants = {
|
|||||||
NUM_ERC1155_FUNGIBLE_TOKENS_MINT: 4,
|
NUM_ERC1155_FUNGIBLE_TOKENS_MINT: 4,
|
||||||
NUM_ERC1155_NONFUNGIBLE_TOKENS_MINT: 4,
|
NUM_ERC1155_NONFUNGIBLE_TOKENS_MINT: 4,
|
||||||
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
NULL_ADDRESS: '0x0000000000000000000000000000000000000000',
|
||||||
|
NULL_BYTES32: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||||
UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
|
UNLIMITED_ALLOWANCE_IN_BASE_UNITS: new BigNumber(2).pow(256).minus(1),
|
||||||
TESTRPC_PRIVATE_KEYS: _.map(TESTRPC_PRIVATE_KEYS_STRINGS, privateKeyString => ethUtil.toBuffer(privateKeyString)),
|
TESTRPC_PRIVATE_KEYS: _.map(TESTRPC_PRIVATE_KEYS_STRINGS, privateKeyString => ethUtil.toBuffer(privateKeyString)),
|
||||||
INITIAL_ERC20_BALANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18),
|
INITIAL_ERC20_BALANCE: Web3Wrapper.toBaseUnitAmount(new BigNumber(10000), 18),
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Updated RichErrors to the library pattern, and implemented RichErrors for all remaining reverts and requires",
|
"note": "Updated RichErrors to the library pattern, and implemented RichErrors for all remaining reverts and requires",
|
||||||
"pr": 1913
|
"pr": 1913
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added unit tests for all of the internal functions in the package",
|
||||||
|
"pr": 2014
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -30,11 +30,16 @@
|
|||||||
"src/LibEIP712.sol",
|
"src/LibEIP712.sol",
|
||||||
"src/Ownable.sol",
|
"src/Ownable.sol",
|
||||||
"src/ReentrancyGuard.sol",
|
"src/ReentrancyGuard.sol",
|
||||||
"src/RichErrors.sol",
|
|
||||||
"src/SafeMath.sol",
|
"src/SafeMath.sol",
|
||||||
"src/interfaces/IOwnable.sol",
|
"src/interfaces/IOwnable.sol",
|
||||||
"test/TestConstants.sol",
|
"test/TestConstants.sol",
|
||||||
|
"test/TestLibAddress.sol",
|
||||||
"test/TestLibAddressArray.sol",
|
"test/TestLibAddressArray.sol",
|
||||||
"test/TestLibBytes.sol"
|
"test/TestLibBytes.sol",
|
||||||
|
"test/TestLibEIP712.sol",
|
||||||
|
"test/TestLibRichErrors.sol",
|
||||||
|
"test/TestOwnable.sol",
|
||||||
|
"test/TestReentrancyGuard.sol",
|
||||||
|
"test/TestSafeMath.sol"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright 2018 ZeroEx Intl.
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright 2018 ZeroEx Intl.
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
Copyright 2019 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.5.9;
|
|
||||||
|
|
||||||
|
|
||||||
contract RichErrors {
|
|
||||||
|
|
||||||
// bytes4(keccak256("Error(string)"))
|
|
||||||
bytes4 internal constant STANDARD_ERROR_SELECTOR =
|
|
||||||
0x08c379a0;
|
|
||||||
|
|
||||||
// solhint-disable func-name-mixedcase
|
|
||||||
/// @dev ABI encode a standard, string revert error payload.
|
|
||||||
/// This is the same payload that would be included by a `revert(string)`
|
|
||||||
/// solidity statement. It has the function signature `Error(string)`.
|
|
||||||
/// @param message The error string.
|
|
||||||
/// @return The ABI encoded error.
|
|
||||||
function StandardError(
|
|
||||||
string memory message
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (bytes memory)
|
|
||||||
{
|
|
||||||
return abi.encodeWithSelector(
|
|
||||||
STANDARD_ERROR_SELECTOR,
|
|
||||||
bytes(message)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// solhint-enable func-name-mixedcase
|
|
||||||
|
|
||||||
/// @dev Reverts an encoded rich revert reason `errorData`.
|
|
||||||
/// @param errorData ABI encoded error data.
|
|
||||||
function _rrevert(bytes memory errorData)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
{
|
|
||||||
assembly {
|
|
||||||
revert(add(errorData, 0x20), mload(errorData))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
35
contracts/utils/contracts/test/TestLibAddress.sol
Normal file
35
contracts/utils/contracts/test/TestLibAddress.sol
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
|
||||||
|
import "../src/LibAddress.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestLibAddress {
|
||||||
|
|
||||||
|
using LibAddress for address;
|
||||||
|
|
||||||
|
function externalIsContract(address account)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return account.isContract();
|
||||||
|
}
|
||||||
|
}
|
52
contracts/utils/contracts/test/TestLibEIP712.sol
Normal file
52
contracts/utils/contracts/test/TestLibEIP712.sol
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
|
||||||
|
import "../src/LibEIP712.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestLibEIP712 is
|
||||||
|
LibEIP712
|
||||||
|
{
|
||||||
|
function externalHashEIP712DomainSeperator(
|
||||||
|
string calldata name,
|
||||||
|
string calldata version,
|
||||||
|
uint256 chainid,
|
||||||
|
address verifyingcontractaddress
|
||||||
|
)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (bytes32)
|
||||||
|
{
|
||||||
|
return _hashEIP712Domain(
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
chainid,
|
||||||
|
verifyingcontractaddress
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function externalHashEIP712Message(bytes32 eip712DomainHash, bytes32 hashStruct)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (bytes32)
|
||||||
|
{
|
||||||
|
return _hashEIP712Message(eip712DomainHash, hashStruct);
|
||||||
|
}
|
||||||
|
}
|
32
contracts/utils/contracts/test/TestLibRichErrors.sol
Normal file
32
contracts/utils/contracts/test/TestLibRichErrors.sol
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
|
||||||
|
import "../src/LibRichErrors.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestLibRichErrors {
|
||||||
|
|
||||||
|
function externalRRevert(bytes calldata errorData)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
{
|
||||||
|
LibRichErrors._rrevert(errorData);
|
||||||
|
}
|
||||||
|
}
|
16
contracts/utils/contracts/test/TestOwnable.sol
Normal file
16
contracts/utils/contracts/test/TestOwnable.sol
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
pragma solidity ^0.5.9;
|
||||||
|
|
||||||
|
import "../src/Ownable.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestOwnable is
|
||||||
|
Ownable
|
||||||
|
{
|
||||||
|
function externalOnlyOwner()
|
||||||
|
external
|
||||||
|
onlyOwner
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
67
contracts/utils/contracts/test/TestReentrancyGuard.sol
Normal file
67
contracts/utils/contracts/test/TestReentrancyGuard.sol
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
|
||||||
|
import "../src/ReentrancyGuard.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestReentrancyGuard is
|
||||||
|
ReentrancyGuard
|
||||||
|
{
|
||||||
|
uint256 internal counter = 2;
|
||||||
|
|
||||||
|
/// @dev Exposes the nonReentrant modifier publicly.
|
||||||
|
/// @param shouldBeAttacked True if the contract should be attacked.
|
||||||
|
/// @return True if successful.
|
||||||
|
function guarded(bool shouldBeAttacked)
|
||||||
|
external
|
||||||
|
nonReentrant
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
if (shouldBeAttacked) {
|
||||||
|
return this.exploitive();
|
||||||
|
} else {
|
||||||
|
return this.nonExploitive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev This is a function that will reenter the current contract.
|
||||||
|
/// @return True if successful.
|
||||||
|
function exploitive()
|
||||||
|
external
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
if (counter > 0) {
|
||||||
|
counter--;
|
||||||
|
this.guarded(true);
|
||||||
|
} else {
|
||||||
|
counter = 2;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev This is a function that will not reenter the current contract.
|
||||||
|
/// @return True if successful.
|
||||||
|
function nonExploitive()
|
||||||
|
external
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
74
contracts/utils/contracts/test/TestSafeMath.sol
Normal file
74
contracts/utils/contracts/test/TestSafeMath.sol
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
|
||||||
|
import "../src/SafeMath.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract TestSafeMath is
|
||||||
|
SafeMath
|
||||||
|
{
|
||||||
|
function externalSafeMul(uint256 a, uint256 b)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
|
return _safeMul(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function externalSafeDiv(uint256 a, uint256 b)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
|
return _safeDiv(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function externalSafeSub(uint256 a, uint256 b)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
|
return _safeSub(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function externalSafeAdd(uint256 a, uint256 b)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
|
return _safeAdd(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function externalMaxUint256(uint256 a, uint256 b)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
|
return _max256(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
function externalMinUint256(uint256 a, uint256 b)
|
||||||
|
external
|
||||||
|
pure
|
||||||
|
returns (uint256)
|
||||||
|
{
|
||||||
|
return _min256(a, b);
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,7 @@
|
|||||||
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
"lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"abis": "./generated-artifacts/@(IOwnable|LibAddress|LibBytes|LibEIP712|Ownable|ReentrancyGuard|RichErrors|SafeMath|TestConstants|TestLibAddressArray|TestLibBytes).json",
|
"abis": "./generated-artifacts/@(IOwnable|LibAddress|LibBytes|LibEIP1271|LibEIP712|Ownable|ReentrancyGuard|SafeMath|TestConstants|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestLibRichErrors|TestOwnable|TestReentrancyGuard|TestSafeMath).json",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -8,24 +8,36 @@ import { ContractArtifact } from 'ethereum-types';
|
|||||||
import * as IOwnable from '../generated-artifacts/IOwnable.json';
|
import * as IOwnable from '../generated-artifacts/IOwnable.json';
|
||||||
import * as LibAddress from '../generated-artifacts/LibAddress.json';
|
import * as LibAddress from '../generated-artifacts/LibAddress.json';
|
||||||
import * as LibBytes from '../generated-artifacts/LibBytes.json';
|
import * as LibBytes from '../generated-artifacts/LibBytes.json';
|
||||||
|
import * as LibEIP1271 from '../generated-artifacts/LibEIP1271.json';
|
||||||
import * as LibEIP712 from '../generated-artifacts/LibEIP712.json';
|
import * as LibEIP712 from '../generated-artifacts/LibEIP712.json';
|
||||||
import * as Ownable from '../generated-artifacts/Ownable.json';
|
import * as Ownable from '../generated-artifacts/Ownable.json';
|
||||||
import * as ReentrancyGuard from '../generated-artifacts/ReentrancyGuard.json';
|
import * as ReentrancyGuard from '../generated-artifacts/ReentrancyGuard.json';
|
||||||
import * as RichErrors from '../generated-artifacts/RichErrors.json';
|
|
||||||
import * as SafeMath from '../generated-artifacts/SafeMath.json';
|
import * as SafeMath from '../generated-artifacts/SafeMath.json';
|
||||||
import * as TestConstants from '../generated-artifacts/TestConstants.json';
|
import * as TestConstants from '../generated-artifacts/TestConstants.json';
|
||||||
|
import * as TestLibAddress from '../generated-artifacts/TestLibAddress.json';
|
||||||
import * as TestLibAddressArray from '../generated-artifacts/TestLibAddressArray.json';
|
import * as TestLibAddressArray from '../generated-artifacts/TestLibAddressArray.json';
|
||||||
import * as TestLibBytes from '../generated-artifacts/TestLibBytes.json';
|
import * as TestLibBytes from '../generated-artifacts/TestLibBytes.json';
|
||||||
|
import * as TestLibEIP712 from '../generated-artifacts/TestLibEIP712.json';
|
||||||
|
import * as TestLibRichErrors from '../generated-artifacts/TestLibRichErrors.json';
|
||||||
|
import * as TestOwnable from '../generated-artifacts/TestOwnable.json';
|
||||||
|
import * as TestReentrancyGuard from '../generated-artifacts/TestReentrancyGuard.json';
|
||||||
|
import * as TestSafeMath from '../generated-artifacts/TestSafeMath.json';
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
LibAddress: LibAddress as ContractArtifact,
|
LibAddress: LibAddress as ContractArtifact,
|
||||||
LibBytes: LibBytes as ContractArtifact,
|
LibBytes: LibBytes as ContractArtifact,
|
||||||
|
LibEIP1271: LibEIP1271 as ContractArtifact,
|
||||||
LibEIP712: LibEIP712 as ContractArtifact,
|
LibEIP712: LibEIP712 as ContractArtifact,
|
||||||
Ownable: Ownable as ContractArtifact,
|
Ownable: Ownable as ContractArtifact,
|
||||||
ReentrancyGuard: ReentrancyGuard as ContractArtifact,
|
ReentrancyGuard: ReentrancyGuard as ContractArtifact,
|
||||||
RichErrors: RichErrors as ContractArtifact,
|
|
||||||
SafeMath: SafeMath as ContractArtifact,
|
SafeMath: SafeMath as ContractArtifact,
|
||||||
IOwnable: IOwnable as ContractArtifact,
|
IOwnable: IOwnable as ContractArtifact,
|
||||||
TestConstants: TestConstants as ContractArtifact,
|
TestConstants: TestConstants as ContractArtifact,
|
||||||
|
TestLibAddress: TestLibAddress as ContractArtifact,
|
||||||
TestLibAddressArray: TestLibAddressArray as ContractArtifact,
|
TestLibAddressArray: TestLibAddressArray as ContractArtifact,
|
||||||
TestLibBytes: TestLibBytes as ContractArtifact,
|
TestLibBytes: TestLibBytes as ContractArtifact,
|
||||||
|
TestLibEIP712: TestLibEIP712 as ContractArtifact,
|
||||||
|
TestLibRichErrors: TestLibRichErrors as ContractArtifact,
|
||||||
|
TestOwnable: TestOwnable as ContractArtifact,
|
||||||
|
TestReentrancyGuard: TestReentrancyGuard as ContractArtifact,
|
||||||
|
TestSafeMath: TestSafeMath as ContractArtifact,
|
||||||
};
|
};
|
||||||
|
@ -6,11 +6,17 @@
|
|||||||
export * from '../generated-wrappers/i_ownable';
|
export * from '../generated-wrappers/i_ownable';
|
||||||
export * from '../generated-wrappers/lib_address';
|
export * from '../generated-wrappers/lib_address';
|
||||||
export * from '../generated-wrappers/lib_bytes';
|
export * from '../generated-wrappers/lib_bytes';
|
||||||
|
export * from '../generated-wrappers/lib_e_i_p1271';
|
||||||
export * from '../generated-wrappers/lib_e_i_p712';
|
export * from '../generated-wrappers/lib_e_i_p712';
|
||||||
export * from '../generated-wrappers/ownable';
|
export * from '../generated-wrappers/ownable';
|
||||||
export * from '../generated-wrappers/reentrancy_guard';
|
export * from '../generated-wrappers/reentrancy_guard';
|
||||||
export * from '../generated-wrappers/rich_errors';
|
|
||||||
export * from '../generated-wrappers/safe_math';
|
export * from '../generated-wrappers/safe_math';
|
||||||
export * from '../generated-wrappers/test_constants';
|
export * from '../generated-wrappers/test_constants';
|
||||||
|
export * from '../generated-wrappers/test_lib_address';
|
||||||
export * from '../generated-wrappers/test_lib_address_array';
|
export * from '../generated-wrappers/test_lib_address_array';
|
||||||
export * from '../generated-wrappers/test_lib_bytes';
|
export * from '../generated-wrappers/test_lib_bytes';
|
||||||
|
export * from '../generated-wrappers/test_lib_e_i_p712';
|
||||||
|
export * from '../generated-wrappers/test_lib_rich_errors';
|
||||||
|
export * from '../generated-wrappers/test_ownable';
|
||||||
|
export * from '../generated-wrappers/test_reentrancy_guard';
|
||||||
|
export * from '../generated-wrappers/test_safe_math';
|
||||||
|
37
contracts/utils/test/lib_address.ts
Normal file
37
contracts/utils/test/lib_address.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { chaiSetup, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||||
|
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||||
|
import * as chai from 'chai';
|
||||||
|
|
||||||
|
import { artifacts, TestLibAddressContract } from '../src';
|
||||||
|
|
||||||
|
chaiSetup.configure();
|
||||||
|
const expect = chai.expect;
|
||||||
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
|
describe('LibAddress', () => {
|
||||||
|
let lib: TestLibAddressContract;
|
||||||
|
let nonContract: string;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
await blockchainLifecycle.startAsync();
|
||||||
|
nonContract = (await web3Wrapper.getAvailableAddressesAsync())[0];
|
||||||
|
// Deploy LibAddress
|
||||||
|
lib = await TestLibAddressContract.deployFrom0xArtifactAsync(artifacts.TestLibAddress, provider, txDefaults);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await blockchainLifecycle.revertAsync();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isContract', () => {
|
||||||
|
it('should return false for a non-contract address', async () => {
|
||||||
|
const isContract = await lib.externalIsContract.callAsync(nonContract);
|
||||||
|
expect(isContract).to.be.false();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true for a non-contract address', async () => {
|
||||||
|
const isContract = await lib.externalIsContract.callAsync(lib.address);
|
||||||
|
expect(isContract).to.be.true();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
111
contracts/utils/test/lib_eip712.ts
Normal file
111
contracts/utils/test/lib_eip712.ts
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import { chaiSetup, constants, hexConcat, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||||
|
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||||
|
import { BigNumber, signTypedDataUtils } from '@0x/utils';
|
||||||
|
import * as chai from 'chai';
|
||||||
|
import * as ethUtil from 'ethereumjs-util';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { artifacts, TestLibEIP712Contract } from '../src';
|
||||||
|
|
||||||
|
chaiSetup.configure();
|
||||||
|
const expect = chai.expect;
|
||||||
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a specific instance of EIP712 domain hashing.
|
||||||
|
* @param lib The LibEIP712 contract to call.
|
||||||
|
* @param name The name of the domain.
|
||||||
|
* @param version The version of the domain.
|
||||||
|
* @param chainId The chain id of the domain.
|
||||||
|
* @param verifyingContractAddress The verifying contract address of the domain.
|
||||||
|
*/
|
||||||
|
async function testHashEIP712DomainAsync(
|
||||||
|
lib: TestLibEIP712Contract,
|
||||||
|
name: string,
|
||||||
|
version: string,
|
||||||
|
chainId: number,
|
||||||
|
verifyingContractAddress: string,
|
||||||
|
): Promise<void> {
|
||||||
|
const expectedHash = signTypedDataUtils.generateDomainHash({
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
chainId,
|
||||||
|
verifyingContractAddress,
|
||||||
|
});
|
||||||
|
const actualHash = await lib.externalHashEIP712DomainSeperator.callAsync(
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
new BigNumber(chainId),
|
||||||
|
verifyingContractAddress,
|
||||||
|
);
|
||||||
|
expect(actualHash).to.be.eq(hexConcat(expectedHash));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests a specific instance of EIP712 message hashing.
|
||||||
|
* @param lib The LibEIP712 contract to call.
|
||||||
|
* @param domainHash The hash of the EIP712 domain of this instance.
|
||||||
|
* @param hashStruct The hash of the struct of this instance.
|
||||||
|
*/
|
||||||
|
async function testHashEIP712MessageAsync(
|
||||||
|
lib: TestLibEIP712Contract,
|
||||||
|
domainHash: string,
|
||||||
|
hashStruct: string,
|
||||||
|
): Promise<void> {
|
||||||
|
const input = '0x1901'.concat(
|
||||||
|
domainHash.slice(2, domainHash.length).concat(hashStruct.slice(2, hashStruct.length)),
|
||||||
|
);
|
||||||
|
const expectedHash = '0x'.concat(ethUtil.sha3(input).toString('hex'));
|
||||||
|
const actualHash = await lib.externalHashEIP712Message.callAsync(domainHash, hashStruct);
|
||||||
|
expect(actualHash).to.be.eq(expectedHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('LibEIP712', () => {
|
||||||
|
let lib: TestLibEIP712Contract;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
await blockchainLifecycle.startAsync();
|
||||||
|
// Deploy LibEIP712
|
||||||
|
lib = await TestLibEIP712Contract.deployFrom0xArtifactAsync(artifacts.TestLibEIP712, provider, txDefaults);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await blockchainLifecycle.revertAsync();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_hashEIP712Domain', async () => {
|
||||||
|
it('should correctly hash empty input', async () => {
|
||||||
|
await testHashEIP712DomainAsync(lib, '', '', 0, constants.NULL_ADDRESS);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly hash non-empty input', async () => {
|
||||||
|
await testHashEIP712DomainAsync(lib, '_hashEIP712Domain', '1.0', 62, lib.address);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly hash non-empty input', async () => {
|
||||||
|
await testHashEIP712DomainAsync(lib, '_hashEIP712Domain', '2.0', 0, lib.address);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_hashEIP712Message', () => {
|
||||||
|
it('should correctly hash empty input', async () => {
|
||||||
|
await testHashEIP712MessageAsync(lib, constants.NULL_BYTES32, constants.NULL_BYTES32);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly hash non-empty input', async () => {
|
||||||
|
await testHashEIP712MessageAsync(
|
||||||
|
lib,
|
||||||
|
'0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6', // keccak256(abi.encode(1))
|
||||||
|
'0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace', // keccak256(abi.encode(2))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly hash non-empty input', async () => {
|
||||||
|
await testHashEIP712MessageAsync(
|
||||||
|
lib,
|
||||||
|
'0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace', // keccak256(abi.encode(2))
|
||||||
|
'0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b', // keccak256(abi.encode(3))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
40
contracts/utils/test/lib_rich_errors.ts
Normal file
40
contracts/utils/test/lib_rich_errors.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||||
|
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||||
|
import { StringRevertError } from '@0x/utils';
|
||||||
|
import * as chai from 'chai';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { artifacts, TestLibRichErrorsContract } from '../src';
|
||||||
|
|
||||||
|
chaiSetup.configure();
|
||||||
|
const expect = chai.expect;
|
||||||
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
|
describe('LibRichErrors', () => {
|
||||||
|
let lib: TestLibRichErrorsContract;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
await blockchainLifecycle.startAsync();
|
||||||
|
// Deploy SafeMath
|
||||||
|
lib = await TestLibRichErrorsContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestLibRichErrors,
|
||||||
|
provider,
|
||||||
|
txDefaults,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await blockchainLifecycle.revertAsync();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_rrevert', () => {
|
||||||
|
it('should correctly revert the extra bytes', async () => {
|
||||||
|
return expect(lib.externalRRevert.callAsync(constants.NULL_BYTES)).to.revertWith(constants.NULL_BYTES);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly revert a StringRevertError', async () => {
|
||||||
|
const error = new StringRevertError('foo');
|
||||||
|
return expect(lib.externalRRevert.callAsync(error.encode())).to.revertWith(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
59
contracts/utils/test/ownable.ts
Normal file
59
contracts/utils/test/ownable.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||||
|
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||||
|
import { OwnableRevertErrors } from '@0x/utils';
|
||||||
|
import * as chai from 'chai';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { artifacts, TestOwnableContract } from '../src';
|
||||||
|
|
||||||
|
chaiSetup.configure();
|
||||||
|
const expect = chai.expect;
|
||||||
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
|
describe('Ownable', () => {
|
||||||
|
let ownable: TestOwnableContract;
|
||||||
|
let owner: string;
|
||||||
|
let nonOwner: string;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
const accounts = await web3Wrapper.getAvailableAddressesAsync();
|
||||||
|
owner = await accounts[0];
|
||||||
|
nonOwner = await accounts[1];
|
||||||
|
await blockchainLifecycle.startAsync();
|
||||||
|
// Deploy Ownable from the owner address
|
||||||
|
txDefaults.from = owner;
|
||||||
|
ownable = await TestOwnableContract.deployFrom0xArtifactAsync(artifacts.TestOwnable, provider, txDefaults);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await blockchainLifecycle.revertAsync();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onlyOwner', () => {
|
||||||
|
it('should revert if sender is not the owner', async () => {
|
||||||
|
const expectedError = new OwnableRevertErrors.OnlyOwnerError(nonOwner, owner);
|
||||||
|
return expect(ownable.externalOnlyOwner.callAsync({ from: nonOwner })).to.revertWith(expectedError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should succeed if sender is the owner', async () => {
|
||||||
|
const isSuccessful = await ownable.externalOnlyOwner.callAsync({ from: owner });
|
||||||
|
expect(isSuccessful).to.be.true();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('transferOwnership', () => {
|
||||||
|
it('should not transfer ownership if the specified new owner is the zero address', async () => {
|
||||||
|
expect(
|
||||||
|
ownable.transferOwnership.sendTransactionAsync(constants.NULL_ADDRESS, { from: owner }),
|
||||||
|
).to.be.fulfilled('');
|
||||||
|
const updatedOwner = await ownable.owner.callAsync();
|
||||||
|
expect(updatedOwner).to.be.eq(owner);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should transfer ownership if the specified new owner is not the zero address', async () => {
|
||||||
|
expect(ownable.transferOwnership.sendTransactionAsync(nonOwner, { from: owner })).to.be.fulfilled('');
|
||||||
|
const updatedOwner = await ownable.owner.callAsync();
|
||||||
|
expect(updatedOwner).to.be.eq(nonOwner);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
41
contracts/utils/test/reentrancy_guard.ts
Normal file
41
contracts/utils/test/reentrancy_guard.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { chaiSetup, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||||
|
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||||
|
import { ReentrancyGuardRevertErrors } from '@0x/utils';
|
||||||
|
import * as chai from 'chai';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { artifacts, TestReentrancyGuardContract } from '../src';
|
||||||
|
|
||||||
|
chaiSetup.configure();
|
||||||
|
const expect = chai.expect;
|
||||||
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
|
describe('ReentrancyGuard', () => {
|
||||||
|
let guard: TestReentrancyGuardContract;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
await blockchainLifecycle.startAsync();
|
||||||
|
// Deploy TestReentrancyGuard
|
||||||
|
guard = await TestReentrancyGuardContract.deployFrom0xArtifactAsync(
|
||||||
|
artifacts.TestReentrancyGuard,
|
||||||
|
provider,
|
||||||
|
txDefaults,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await blockchainLifecycle.revertAsync();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('nonReentrant', () => {
|
||||||
|
it('should revert if reentrancy occurs', async () => {
|
||||||
|
const expectedError = new ReentrancyGuardRevertErrors.IllegalReentrancyError();
|
||||||
|
return expect(guard.guarded.sendTransactionAsync(true)).to.revertWith(expectedError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should succeed if reentrancy does not occur', async () => {
|
||||||
|
const isSuccessful = await guard.guarded.callAsync(false);
|
||||||
|
expect(isSuccessful).to.be.true();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
171
contracts/utils/test/safe_math.ts
Normal file
171
contracts/utils/test/safe_math.ts
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||||
|
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||||
|
import { BigNumber, SafeMathRevertErrors } from '@0x/utils';
|
||||||
|
import * as chai from 'chai';
|
||||||
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
|
import { artifacts, TestSafeMathContract } from '../src';
|
||||||
|
|
||||||
|
chaiSetup.configure();
|
||||||
|
const expect = chai.expect;
|
||||||
|
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||||
|
|
||||||
|
function toBigNumber(a: number | string): BigNumber {
|
||||||
|
return new BigNumber(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('SafeMath', () => {
|
||||||
|
let safeMath: TestSafeMathContract;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
await blockchainLifecycle.startAsync();
|
||||||
|
// Deploy SafeMath
|
||||||
|
safeMath = await TestSafeMathContract.deployFrom0xArtifactAsync(artifacts.TestSafeMath, provider, txDefaults);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await blockchainLifecycle.revertAsync();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_safeMul', () => {
|
||||||
|
it('should return zero if first argument is zero', async () => {
|
||||||
|
const result = await safeMath.externalSafeMul.callAsync(constants.ZERO_AMOUNT, toBigNumber(1));
|
||||||
|
expect(result).bignumber.to.be.eq(constants.ZERO_AMOUNT);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return zero if second argument is zero', async () => {
|
||||||
|
const result = await safeMath.externalSafeMul.callAsync(toBigNumber(1), constants.ZERO_AMOUNT);
|
||||||
|
expect(result).bignumber.to.be.eq(constants.ZERO_AMOUNT);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should revert if the multiplication overflows', async () => {
|
||||||
|
const a = toBigNumber('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); // The largest uint256 number
|
||||||
|
const b = toBigNumber(2);
|
||||||
|
const expectedError = new SafeMathRevertErrors.SafeMathError(
|
||||||
|
SafeMathRevertErrors.SafeMathErrorCodes.Uint256MultiplicationOverflow,
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
);
|
||||||
|
return expect(safeMath.externalSafeMul.callAsync(a, b)).to.revertWith(expectedError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should calculate correct value for values that don't overflow", async () => {
|
||||||
|
const result = await safeMath.externalSafeMul.callAsync(toBigNumber(15), toBigNumber(13));
|
||||||
|
expect(result).bignumber.to.be.eq(toBigNumber(195));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_safeDiv', () => {
|
||||||
|
it('should return the correct value if both values are the same', async () => {
|
||||||
|
const result = await safeMath.externalSafeDiv.callAsync(toBigNumber(1), toBigNumber(1));
|
||||||
|
expect(result).bignumber.to.be.eq(toBigNumber(1));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the correct value if the values are different', async () => {
|
||||||
|
const result = await safeMath.externalSafeDiv.callAsync(toBigNumber(3), toBigNumber(2));
|
||||||
|
expect(result).bignumber.to.be.eq(toBigNumber(1));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return zero if the numerator is smaller than the denominator', async () => {
|
||||||
|
const result = await safeMath.externalSafeDiv.callAsync(toBigNumber(2), toBigNumber(3));
|
||||||
|
expect(result).bignumber.to.be.eq(constants.ZERO_AMOUNT);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return zero if first argument is zero', async () => {
|
||||||
|
const result = await safeMath.externalSafeDiv.callAsync(constants.ZERO_AMOUNT, toBigNumber(1));
|
||||||
|
expect(result).bignumber.to.be.eq(constants.ZERO_AMOUNT);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should revert if second argument is zero', async () => {
|
||||||
|
const errMessage = 'VM Exception while processing transaction: invalid opcode';
|
||||||
|
return expect(safeMath.externalSafeDiv.callAsync(toBigNumber(1), constants.ZERO_AMOUNT)).to.be.rejectedWith(
|
||||||
|
errMessage,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_safeSub', () => {
|
||||||
|
it('should revert if the subtraction underflows', async () => {
|
||||||
|
const a = toBigNumber(0);
|
||||||
|
const b = toBigNumber(1);
|
||||||
|
const expectedError = new SafeMathRevertErrors.SafeMathError(
|
||||||
|
SafeMathRevertErrors.SafeMathErrorCodes.Uint256SubtractionUnderflow,
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
);
|
||||||
|
return expect(safeMath.externalSafeSub.callAsync(a, b)).to.revertWith(expectedError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calculate correct value for values that are equal', async () => {
|
||||||
|
const result = await safeMath.externalSafeMul.callAsync(constants.ZERO_AMOUNT, constants.ZERO_AMOUNT);
|
||||||
|
expect(result).bignumber.to.be.eq(constants.ZERO_AMOUNT);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calculate correct value for values that are not equal', async () => {
|
||||||
|
const result = await safeMath.externalSafeSub.callAsync(toBigNumber(15), toBigNumber(13));
|
||||||
|
expect(result).bignumber.to.be.eq(toBigNumber(2));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_safeAdd', () => {
|
||||||
|
it('should revert if the addition overflows', async () => {
|
||||||
|
const a = toBigNumber('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'); // The largest uint256 number
|
||||||
|
const b = toBigNumber(1);
|
||||||
|
const expectedError = new SafeMathRevertErrors.SafeMathError(
|
||||||
|
SafeMathRevertErrors.SafeMathErrorCodes.Uint256AdditionOverflow,
|
||||||
|
a,
|
||||||
|
b,
|
||||||
|
);
|
||||||
|
return expect(safeMath.externalSafeAdd.callAsync(a, b)).to.revertWith(expectedError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calculate correct value if addition does not overflow', async () => {
|
||||||
|
const result = await safeMath.externalSafeAdd.callAsync(toBigNumber(15), toBigNumber(13));
|
||||||
|
expect(result).bignumber.to.be.eq(toBigNumber(28));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calculate correct value if first argument is zero', async () => {
|
||||||
|
const result = await safeMath.externalSafeAdd.callAsync(constants.ZERO_AMOUNT, toBigNumber(13));
|
||||||
|
expect(result).bignumber.to.be.eq(toBigNumber(13));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should calculate correct value if second argument is zero', async () => {
|
||||||
|
const result = await safeMath.externalSafeAdd.callAsync(toBigNumber(13), constants.ZERO_AMOUNT);
|
||||||
|
expect(result).bignumber.to.be.eq(toBigNumber(13));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_maxUint256', () => {
|
||||||
|
it('should return first argument if it is greater than the second', async () => {
|
||||||
|
const result = await safeMath.externalMaxUint256.callAsync(toBigNumber(13), constants.ZERO_AMOUNT);
|
||||||
|
expect(result).bignumber.to.be.eq(toBigNumber(13));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return first argument if it is equal the second', async () => {
|
||||||
|
const result = await safeMath.externalMaxUint256.callAsync(constants.ZERO_AMOUNT, constants.ZERO_AMOUNT);
|
||||||
|
expect(result).bignumber.to.be.eq(constants.ZERO_AMOUNT);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return second argument if it is greater than the first', async () => {
|
||||||
|
const result = await safeMath.externalMaxUint256.callAsync(constants.ZERO_AMOUNT, toBigNumber(13));
|
||||||
|
expect(result).bignumber.to.be.eq(toBigNumber(13));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_minUint256', () => {
|
||||||
|
it('should return first argument if it is less than the second', async () => {
|
||||||
|
const result = await safeMath.externalMaxUint256.callAsync(constants.ZERO_AMOUNT, toBigNumber(13));
|
||||||
|
expect(result).bignumber.to.be.eq(toBigNumber(13));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return first argument if it is equal the second', async () => {
|
||||||
|
const result = await safeMath.externalMaxUint256.callAsync(constants.ZERO_AMOUNT, constants.ZERO_AMOUNT);
|
||||||
|
expect(result).bignumber.to.be.eq(constants.ZERO_AMOUNT);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return second argument if it is less than the first', async () => {
|
||||||
|
const result = await safeMath.externalMaxUint256.callAsync(toBigNumber(13), constants.ZERO_AMOUNT);
|
||||||
|
expect(result).bignumber.to.be.eq(toBigNumber(13));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -6,14 +6,20 @@
|
|||||||
"generated-artifacts/IOwnable.json",
|
"generated-artifacts/IOwnable.json",
|
||||||
"generated-artifacts/LibAddress.json",
|
"generated-artifacts/LibAddress.json",
|
||||||
"generated-artifacts/LibBytes.json",
|
"generated-artifacts/LibBytes.json",
|
||||||
|
"generated-artifacts/LibEIP1271.json",
|
||||||
"generated-artifacts/LibEIP712.json",
|
"generated-artifacts/LibEIP712.json",
|
||||||
"generated-artifacts/Ownable.json",
|
"generated-artifacts/Ownable.json",
|
||||||
"generated-artifacts/ReentrancyGuard.json",
|
"generated-artifacts/ReentrancyGuard.json",
|
||||||
"generated-artifacts/RichErrors.json",
|
|
||||||
"generated-artifacts/SafeMath.json",
|
"generated-artifacts/SafeMath.json",
|
||||||
"generated-artifacts/TestConstants.json",
|
"generated-artifacts/TestConstants.json",
|
||||||
|
"generated-artifacts/TestLibAddress.json",
|
||||||
"generated-artifacts/TestLibAddressArray.json",
|
"generated-artifacts/TestLibAddressArray.json",
|
||||||
"generated-artifacts/TestLibBytes.json"
|
"generated-artifacts/TestLibBytes.json",
|
||||||
|
"generated-artifacts/TestLibEIP712.json",
|
||||||
|
"generated-artifacts/TestLibRichErrors.json",
|
||||||
|
"generated-artifacts/TestOwnable.json",
|
||||||
|
"generated-artifacts/TestReentrancyGuard.json",
|
||||||
|
"generated-artifacts/TestSafeMath.json"
|
||||||
],
|
],
|
||||||
"exclude": ["./deploy/solc/solc_bin"]
|
"exclude": ["./deploy/solc/solc_bin"]
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ export enum SafeMathErrorCodes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class SafeMathError extends RevertError {
|
export class SafeMathError extends RevertError {
|
||||||
constructor(error?: SafeMathErrorCodes, a?: BigNumber | number | string, b?: BigNumber | number | string) {
|
constructor(error?: SafeMathErrorCodes, a?: BigNumber, b?: BigNumber) {
|
||||||
super('SafeMathError', 'SafeMathError(uint8 error, uint256 a, uint256 b)', {
|
super('SafeMathError', 'SafeMathError(uint8 error, uint256 a, uint256 b)', {
|
||||||
error,
|
error,
|
||||||
a,
|
a,
|
||||||
|
@ -20,6 +20,28 @@ export const signTypedDataUtils = {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Generates the hash of a EIP712 Domain with the default schema
|
||||||
|
* @param domain An EIP712 domain with the default schema containing a name, version, chain id,
|
||||||
|
* and verifying address.
|
||||||
|
* @return A buffer that contains the hash of the domain.
|
||||||
|
*/
|
||||||
|
generateDomainHash(domain: EIP712Object): Buffer {
|
||||||
|
return signTypedDataUtils._structHash(
|
||||||
|
'EIP712Domain',
|
||||||
|
domain,
|
||||||
|
// HACK(jalextowle): When we consolidate our testing packages into test-utils, we can use a constant
|
||||||
|
// to eliminate code duplication. At the moment, there isn't a good way to do that because of cyclic-dependencies.
|
||||||
|
{
|
||||||
|
EIP712Domain: [
|
||||||
|
{ name: 'name', type: 'string' },
|
||||||
|
{ name: 'version', type: 'string' },
|
||||||
|
{ name: 'chainId', type: 'uint256' },
|
||||||
|
{ name: 'verifyingContractAddress', type: 'address' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
_findDependencies(primaryType: string, types: EIP712Types, found: string[] = []): string[] {
|
_findDependencies(primaryType: string, types: EIP712Types, found: string[] = []): string[] {
|
||||||
if (found.includes(primaryType) || types[primaryType] === undefined) {
|
if (found.includes(primaryType) || types[primaryType] === undefined) {
|
||||||
return found;
|
return found;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user