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

@@ -5,11 +5,25 @@ import {
getRandomInteger,
randomAddress,
} from '@0x/contracts-test-utils';
import { LimitOrder, LimitOrderFields, OrderBase, OrderInfo, RfqOrder, RfqOrderFields } from '@0x/protocol-utils';
import {
LimitOrder,
LimitOrderFields,
OrderBase,
OrderInfo,
OtcOrder,
RfqOrder,
RfqOrderFields,
SignatureType,
} from '@0x/protocol-utils';
import { BigNumber, hexUtils } from '@0x/utils';
import { TransactionReceiptWithDecodedLogs } from 'ethereum-types';
import { IZeroExContract, IZeroExLimitOrderFilledEventArgs, IZeroExRfqOrderFilledEventArgs } from '../../src/wrappers';
import {
IZeroExContract,
IZeroExLimitOrderFilledEventArgs,
IZeroExOtcOrderFilledEventArgs,
IZeroExRfqOrderFilledEventArgs,
} from '../../src/wrappers';
import { artifacts } from '../artifacts';
import { fullMigrateAsync } from '../utils/migration';
import { TestMintableERC20TokenContract } from '../wrappers';
@@ -20,6 +34,7 @@ interface RfqOrderFilledAmounts {
makerTokenFilledAmount: BigNumber;
takerTokenFilledAmount: BigNumber;
}
interface OtcOrderFilledAmounts extends RfqOrderFilledAmounts {}
interface LimitOrderFilledAmounts {
makerTokenFilledAmount: BigNumber;
@@ -27,6 +42,12 @@ interface LimitOrderFilledAmounts {
takerTokenFeeFilledAmount: BigNumber;
}
export enum OtcOrderWethOptions {
LeaveAsWeth,
WrapEth,
UnwrapWeth,
}
export class NativeOrdersTestEnvironment {
public static async createAsync(
env: BlockchainTestsEnvironment,
@@ -71,7 +92,7 @@ export class NativeOrdersTestEnvironment {
) {}
public async prepareBalancesForOrdersAsync(
orders: LimitOrder[] | RfqOrder[],
orders: LimitOrder[] | RfqOrder[] | OtcOrder[],
taker: string = this.taker,
): Promise<void> {
await this.makerToken
@@ -128,6 +149,51 @@ export class NativeOrdersTestEnvironment {
.awaitTransactionSuccessAsync({ from: taker });
}
public async fillOtcOrderAsync(
order: OtcOrder,
fillAmount: BigNumber | number = order.takerAmount,
taker: string = this.taker,
unwrapWeth: boolean = false,
): Promise<TransactionReceiptWithDecodedLogs> {
await this.prepareBalancesForOrdersAsync([order], taker);
return this.zeroEx
.fillOtcOrder(
order,
await order.getSignatureWithProviderAsync(this._env.provider),
new BigNumber(fillAmount),
unwrapWeth,
)
.awaitTransactionSuccessAsync({ from: taker });
}
public async fillTakerSignedOtcOrderAsync(
order: OtcOrder,
origin: string = order.txOrigin,
taker: string = order.taker,
unwrapWeth: boolean = false,
): Promise<TransactionReceiptWithDecodedLogs> {
await this.prepareBalancesForOrdersAsync([order], taker);
return this.zeroEx
.fillTakerSignedOtcOrder(
order,
await order.getSignatureWithProviderAsync(this._env.provider),
await order.getSignatureWithProviderAsync(this._env.provider, SignatureType.EthSign, taker),
unwrapWeth,
)
.awaitTransactionSuccessAsync({ from: origin });
}
public async fillOtcOrderWithEthAsync(
order: OtcOrder,
fillAmount: BigNumber | number = order.takerAmount,
taker: string = this.taker,
): Promise<TransactionReceiptWithDecodedLogs> {
await this.prepareBalancesForOrdersAsync([order], taker);
return this.zeroEx
.fillOtcOrderWithEth(order, await order.getSignatureWithProviderAsync(this._env.provider))
.awaitTransactionSuccessAsync({ from: taker, value: fillAmount });
}
public createLimitOrderFilledEventArgs(
order: LimitOrder,
takerTokenFillAmount: BigNumber = order.takerAmount,
@@ -175,6 +241,25 @@ export class NativeOrdersTestEnvironment {
pool: order.pool,
};
}
public createOtcOrderFilledEventArgs(
order: OtcOrder,
takerTokenFillAmount: BigNumber = order.takerAmount,
): IZeroExOtcOrderFilledEventArgs {
const { makerTokenFilledAmount, takerTokenFilledAmount } = computeOtcOrderFilledAmounts(
order,
takerTokenFillAmount,
);
return {
takerTokenFilledAmount,
makerTokenFilledAmount,
orderHash: order.getHash(),
maker: order.maker,
taker: order.taker !== NULL_ADDRESS ? order.taker : this.taker,
makerToken: order.makerToken,
takerToken: order.takerToken,
};
}
}
/**
@@ -216,6 +301,27 @@ export function getRandomRfqOrder(fields: Partial<RfqOrderFields> = {}): RfqOrde
});
}
/**
* Generate a random OTC Order
*/
export function getRandomOtcOrder(fields: Partial<OtcOrder> = {}): OtcOrder {
return new OtcOrder({
makerToken: randomAddress(),
takerToken: randomAddress(),
makerAmount: getRandomInteger('1e18', '100e18'),
takerAmount: getRandomInteger('1e6', '100e6'),
maker: randomAddress(),
taker: randomAddress(),
txOrigin: randomAddress(),
expiryAndNonce: OtcOrder.encodeExpiryAndNonce(
fields.expiry ?? new BigNumber(Math.floor(Date.now() / 1000 + 60)), // expiry
fields.nonceBucket ?? getRandomInteger(0, OtcOrder.MAX_NONCE_BUCKET), // nonceBucket
fields.nonce ?? getRandomInteger(0, OtcOrder.MAX_NONCE_VALUE), // nonce
),
...fields,
});
}
/**
* Asserts the fields of an OrderInfo object.
*/
@@ -286,6 +392,24 @@ export function computeRfqOrderFilledAmounts(
};
}
/**
* Computes the maker and taker amounts filled for the given OTC order.
*/
export function computeOtcOrderFilledAmounts(
order: OtcOrder,
takerTokenFillAmount: BigNumber = order.takerAmount,
): OtcOrderFilledAmounts {
const fillAmount = BigNumber.min(order.takerAmount, takerTokenFillAmount, order.takerAmount);
const makerTokenFilledAmount = fillAmount
.times(order.makerAmount)
.div(order.takerAmount)
.integerValue(BigNumber.ROUND_DOWN);
return {
makerTokenFilledAmount,
takerTokenFilledAmount: fillAmount,
};
}
/**
* Computes the remaining fillable amount in maker token for
* the given order.