Address spot check feedback (#251)

* UniswapV3 VIP (#237)

* `@0x/contracts-zero-ex`: Add UniswapV3Feature

* `@0x/contracts-zero-ex`: Add UniswapV3 VIP
`@0x/contract-artifacts`: Regenerate.
`@0x/contract-wrappers`: Regenerate.
`@0x/asset-swapper`: Add UniswapV3 VIP support.

* address review comments and appease linter

* `@0x/contracts-zero-ex`: Add UniswapV3Feature tests

* Multiplex UniswapV3 (#241)

* Add UniswapV3 support to Multiplex batchFill

* Add AssetSwapper support for Multiplex UniswapV3

* fix repo scripts that use PKG= env var (#242)

Co-authored-by: Lawrence Forman <me@merklejerk.com>

* `@0x/asset-swapper`: Adjust uniswap gas overhead

Co-authored-by: Lawrence Forman <me@merklejerk.com>
Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com>

* OTC orders feature (#244)

* Add OTC orders feature contracts

* Address PR feedback

* Remove partial fills for takerSigned variant

* Add function to query the min valid nonce

* Add ETH support

* Tightly pack expiry, nonceBucket, and nonce

* Address PR feedback

* OTC orders unit tests

* Bump prettier version

* Skip unnecessary math if takerTokenFillAmount == order.takerAmount

* appease CI

* Update contract-artifacts and contract-wrappers and CHANGELOGs

* `@0x/contracts-zero-ex`: Address spot check feedback

* `regen wrappers

* prettier

* `@0x/asset-swapper`: prettier and tweak gas schedule slightly for uni3

Co-authored-by: Lawrence Forman <me@merklejerk.com>
Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com>
This commit is contained in:
Lawrence Forman
2021-06-02 00:21:14 -04:00
committed by GitHub
parent 289474e2ce
commit 901d400d62
112 changed files with 6392 additions and 794 deletions

View File

@@ -534,9 +534,14 @@ blockchainTests.skip('Coordinator Client', env => {
const signedOrders = [signedOrder, signedOrderWithDifferentFeeRecipient];
const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount, takerTokenFillAmount];
await coordinatorClient
.batchFillOrdersAsync(signedOrders, takerAssetFillAmounts, signedOrders.map(o => o.signature), {
from: takerAddress,
})
.batchFillOrdersAsync(
signedOrders,
takerAssetFillAmounts,
signedOrders.map(o => o.signature),
{
from: takerAddress,
},
)
.then(res => {
expect(res).to.be.undefined();
})
@@ -570,9 +575,14 @@ blockchainTests.skip('Coordinator Client', env => {
const signedOrders = [signedOrder, signedOrderWithDifferentCoordinatorOperator];
const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount, takerTokenFillAmount];
await coordinatorClient
.batchFillOrdersAsync(signedOrders, takerAssetFillAmounts, signedOrders.map(o => o.signature), {
from: takerAddress,
})
.batchFillOrdersAsync(
signedOrders,
takerAssetFillAmounts,
signedOrders.map(o => o.signature),
{
from: takerAddress,
},
)
.then(res => {
expect(res).to.be.undefined();
})
@@ -600,9 +610,14 @@ blockchainTests.skip('Coordinator Client', env => {
const signedOrders = [signedOrder, signedOrderWithDifferentCoordinatorOperator];
const takerAssetFillAmounts = [takerTokenFillAmount, takerTokenFillAmount, takerTokenFillAmount];
await coordinatorClient
.batchFillOrdersAsync(signedOrders, takerAssetFillAmounts, signedOrders.map(o => o.signature), {
from: takerAddress,
})
.batchFillOrdersAsync(
signedOrders,
takerAssetFillAmounts,
signedOrders.map(o => o.signature),
{
from: takerAddress,
},
)
.then(res => {
expect(res).to.be.undefined();
})

View File

@@ -267,7 +267,11 @@ blockchainTests.resets('Coordinator integration tests', env => {
expectedBalances.simulateFills(orders, taker.address, txReceipt, deployment, value);
await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, orders.map(order => expectedFillEvent(order)), ExchangeEvents.Fill);
verifyEvents(
txReceipt,
orders.map(order => expectedFillEvent(order)),
ExchangeEvents.Fill,
);
});
it(`${fnName} should fill the orders if called by approver (eth fee, no refund)`, async () => {
await balanceStore.updateBalancesAsync();
@@ -280,7 +284,11 @@ blockchainTests.resets('Coordinator integration tests', env => {
expectedBalances.simulateFills(orders, taker.address, txReceipt, deployment, value);
await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, orders.map(order => expectedFillEvent(order)), ExchangeEvents.Fill);
verifyEvents(
txReceipt,
orders.map(order => expectedFillEvent(order)),
ExchangeEvents.Fill,
);
});
it(`${fnName} should fill the orders if called by approver (mixed fees, refund)`, async () => {
await balanceStore.updateBalancesAsync();
@@ -293,7 +301,11 @@ blockchainTests.resets('Coordinator integration tests', env => {
expectedBalances.simulateFills(orders, taker.address, txReceipt, deployment, value);
await balanceStore.updateBalancesAsync();
balanceStore.assertEquals(expectedBalances);
verifyEvents(txReceipt, orders.map(order => expectedFillEvent(order)), ExchangeEvents.Fill);
verifyEvents(
txReceipt,
orders.map(order => expectedFillEvent(order)),
ExchangeEvents.Fill,
);
});
it(`${fnName} should revert with an invalid approval signature`, async () => {
const approvalSignature = hexUtils.concat(
@@ -360,7 +372,11 @@ blockchainTests.resets('Coordinator integration tests', env => {
.executeTransaction(transaction, maker.address, transaction.signature, [])
.awaitTransactionSuccessAsync({ from: maker.address });
verifyEvents(txReceipt, orders.map(order => expectedCancelEvent(order)), ExchangeEvents.Cancel);
verifyEvents(
txReceipt,
orders.map(order => expectedCancelEvent(order)),
ExchangeEvents.Cancel,
);
});
it('cancelOrdersUpTo call should be successful without an approval', async () => {
const data = exchangeDataEncoder.encodeOrdersToExchangeData(ExchangeFunctionName.CancelOrdersUpTo, []);

View File

@@ -186,13 +186,13 @@ blockchainTests.resets('LibAssetData', env => {
});
it('should decode multiasset data', async () => {
expect(await devUtils.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData).callAsync()).to.deep.equal(
[
AssetProxyId.MultiAsset,
KNOWN_MULTI_ASSET_ENCODING.amounts,
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
],
);
expect(
await devUtils.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData).callAsync(),
).to.deep.equal([
AssetProxyId.MultiAsset,
KNOWN_MULTI_ASSET_ENCODING.amounts,
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
]);
});
it('should encode StaticCall data', async () => {

View File

@@ -278,15 +278,21 @@ blockchainTests.resets('matchOrders integration tests', env => {
ExchangeRevertErrors.BatchMatchOrdersErrorCodes.InvalidLengthRightSignatures,
);
let tx = deployment.exchange
.batchMatchOrders(leftOrders, rightOrders, leftOrders.map(order => order.signature), [
rightOrders[0].signature,
])
.batchMatchOrders(
leftOrders,
rightOrders,
leftOrders.map(order => order.signature),
[rightOrders[0].signature],
)
.awaitTransactionSuccessAsync({ from: matcher.address });
await expect(tx).to.revertWith(expectedError);
tx = deployment.exchange
.batchMatchOrdersWithMaximalFill(leftOrders, rightOrders, leftOrders.map(order => order.signature), [
rightOrders[0].signature,
])
.batchMatchOrdersWithMaximalFill(
leftOrders,
rightOrders,
leftOrders.map(order => order.signature),
[rightOrders[0].signature],
)
.awaitTransactionSuccessAsync({ from: matcher.address });
return expect(tx).to.revertWith(expectedError);
});
@@ -475,7 +481,10 @@ blockchainTests.resets('matchOrders integration tests', env => {
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
matchIndices: [[0, 0], [1, 0]],
matchIndices: [
[0, 0],
[1, 0],
],
shouldMaximallyFill: false,
});
});
@@ -524,7 +533,10 @@ blockchainTests.resets('matchOrders integration tests', env => {
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
matchIndices: [[0, 0], [0, 1]],
matchIndices: [
[0, 0],
[0, 1],
],
shouldMaximallyFill: false,
});
});
@@ -626,7 +638,11 @@ blockchainTests.resets('matchOrders integration tests', env => {
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
matchIndices: [[0, 0], [0, 1], [1, 1]],
matchIndices: [
[0, 0],
[0, 1],
[1, 1],
],
shouldMaximallyFill: false,
});
});
@@ -801,7 +817,11 @@ blockchainTests.resets('matchOrders integration tests', env => {
],
leftOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
rightOrdersTakerAssetFilledAmounts: [constants.ZERO_AMOUNT, constants.ZERO_AMOUNT],
matchIndices: [[0, 0], [1, 0], [1, 1]],
matchIndices: [
[0, 0],
[1, 0],
[1, 1],
],
shouldMaximallyFill: true,
});
});

View File

@@ -106,7 +106,12 @@ blockchainTests.fork.resets('Forwarder mainnet tests', env => {
orders[1].takerAssetAmount.dividedToIntegerBy(2),
);
const [wethSpentAmount, makerAssetAcquiredAmount] = await forwarder
.marketSellOrdersWithEth(orders, orders.map(o => o.signature), [], [])
.marketSellOrdersWithEth(
orders,
orders.map(o => o.signature),
[],
[],
)
.callAsync({
from: takerAddress,
value: ethSellAmount,
@@ -161,7 +166,13 @@ blockchainTests.fork.resets('Forwarder mainnet tests', env => {
orders[1].makerAssetAmount.dividedToIntegerBy(2),
);
const [wethSpentAmount, makerAssetAcquiredAmount] = await forwarder
.marketBuyOrdersWithEth(orders, makerAssetBuyAmount, orders.map(o => o.signature), [], [])
.marketBuyOrdersWithEth(
orders,
makerAssetBuyAmount,
orders.map(o => o.signature),
[],
[],
)
.callAsync({
from: takerAddress,
value: ethSellAmount,

View File

@@ -190,9 +190,14 @@ export function MakerMixin<TBase extends Constructor>(Base: TBase): TBase & Cons
rightTakerAssetData,
makerFeeAssetData,
takerFeeAssetData,
] = [leftMakerToken, leftTakerToken, rightMakerToken, rightTakerToken, makerFeeToken, takerFeeToken].map(
token => encodeERC20AssetData(token.address),
);
] = [
leftMakerToken,
leftTakerToken,
rightMakerToken,
rightTakerToken,
makerFeeToken,
takerFeeToken,
].map(token => encodeERC20AssetData(token.address));
// Construct and sign the left order
const leftOrder = await this.signOrderAsync({

View File

@@ -8,7 +8,10 @@ import { Actor, Constructor } from './base';
* Useful for BalanceStore.
*/
export function actorAddressesByName(actors: Actor[]): ObjectMap<string> {
return _.zipObject(actors.map(actor => actor.name), actors.map(actor => actor.address));
return _.zipObject(
actors.map(actor => actor.name),
actors.map(actor => actor.address),
);
}
/**

View File

@@ -77,19 +77,24 @@ tests('Exchange signature validation fuzz tests', env => {
before(async () => {
chainId = await env.web3Wrapper.getChainIdAsync();
accounts = await env.getAccountAddressesAsync();
privateKeys = _.zipObject(accounts, accounts.map((a, i) => constants.TESTRPC_PRIVATE_KEYS[i]));
privateKeys = _.zipObject(
accounts,
accounts.map((a, i) => constants.TESTRPC_PRIVATE_KEYS[i]),
);
deployment = await DeploymentManager.deployAsync(env, {
numErc20TokensToDeploy: 0,
numErc721TokensToDeploy: 0,
numErc1155TokensToDeploy: 0,
});
exchange = deployment.exchange;
walletContractAddress = (await TestSignatureValidationWalletContract.deployFrom0xArtifactAsync(
artifacts.TestSignatureValidationWallet,
env.provider,
env.txDefaults,
{},
)).address;
walletContractAddress = (
await TestSignatureValidationWalletContract.deployFrom0xArtifactAsync(
artifacts.TestSignatureValidationWallet,
env.provider,
env.txDefaults,
{},
)
).address;
// This just has to be a contract address that doesn't implement the
// wallet spec.
notWalletContractAddress = exchange.address;
@@ -715,7 +720,7 @@ tests('Exchange signature validation fuzz tests', env => {
invalidTestTransactionMangledSignature(),
];
const simulationEnvironment = new SimulationEnvironment(deployment, new BlockchainBalanceStore({}, {}), []);
const simulation = new class extends Simulation {
const simulation = new (class extends Simulation {
// tslint:disable-next-line: prefer-function-over-method
protected async *_assertionGenerator(): AsyncIterableIterator<AssertionResult | void> {
while (true) {
@@ -723,7 +728,7 @@ tests('Exchange signature validation fuzz tests', env => {
yield (await action!.next()).value;
}
}
}(simulationEnvironment);
})(simulationEnvironment);
simulation.resets = true;
return simulation.fuzzAsync();
});