Compare commits

..

4 Commits

Author SHA1 Message Date
Github Actions
15a508f3ea Publish
- @0x/contracts-integrations@2.7.17
 - @0x/contracts-zero-ex@0.14.0
 - @0x/asset-swapper@5.5.1
 - @0x/contract-wrappers-test@12.2.30
 - @0x/migrations@6.5.6
 - @0x/protocol-utils@1.1.0
2020-12-16 20:09:57 +00:00
Github Actions
b3c20ff909 Updated CHANGELOGS & MD docs 2020-12-16 20:09:48 +00:00
Lawrence Forman
682c07cb73 Add mtx tooling to @0x/protocol-utils (#90)
* `@0x/contracts-zero-ex`: Use the `MetaTransaction` class from `@0x/protocol-utils` in tests.

* `@0x/protocol-utils`: Add the `MetaTransaction` class for EP mtxs + refactors

* update changelogs

* `@0x/protocol-utils`: Add mtx tests

* `@0x/protocol-utils`: Rename `mtx.ts` to `meta_transactions.ts` and misc review feedback

Co-authored-by: Lawrence Forman <me@merklejerk.com>
2020-12-16 14:22:00 -05:00
Jacob Evans
602605ab4b Disable Bancor Service for non-mainnet (#89)
* Disable Bancor Service for non-mainnet

* Fix import

* Fix mocked tests
2020-12-16 21:58:39 +10:00
25 changed files with 553 additions and 205 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/contracts-integrations", "name": "@0x/contracts-integrations",
"version": "2.7.16", "version": "2.7.17",
"private": true, "private": true,
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
@@ -65,9 +65,9 @@
"@0x/contracts-utils": "^4.6.3", "@0x/contracts-utils": "^4.6.3",
"@0x/coordinator-server": "^1.0.5", "@0x/coordinator-server": "^1.0.5",
"@0x/dev-utils": "^4.1.3", "@0x/dev-utils": "^4.1.3",
"@0x/migrations": "^6.5.5", "@0x/migrations": "^6.5.6",
"@0x/order-utils": "^10.4.10", "@0x/order-utils": "^10.4.10",
"@0x/protocol-utils": "^1.0.1", "@0x/protocol-utils": "^1.1.0",
"@0x/sol-compiler": "^4.4.1", "@0x/sol-compiler": "^4.4.1",
"@0x/tslint-config": "^4.1.3", "@0x/tslint-config": "^4.1.3",
"@0x/web3-wrapper": "^7.3.0", "@0x/web3-wrapper": "^7.3.0",
@@ -93,7 +93,7 @@
"typescript": "3.0.1" "typescript": "3.0.1"
}, },
"dependencies": { "dependencies": {
"@0x/asset-swapper": "^5.5.0", "@0x/asset-swapper": "^5.5.1",
"@0x/base-contract": "^6.2.14", "@0x/base-contract": "^6.2.14",
"@0x/contracts-asset-proxy": "^3.7.0", "@0x/contracts-asset-proxy": "^3.7.0",
"@0x/contracts-erc1155": "^2.1.18", "@0x/contracts-erc1155": "^2.1.18",
@@ -103,7 +103,7 @@
"@0x/contracts-multisig": "^4.1.19", "@0x/contracts-multisig": "^4.1.19",
"@0x/contracts-staking": "^2.0.26", "@0x/contracts-staking": "^2.0.26",
"@0x/contracts-test-utils": "^5.3.15", "@0x/contracts-test-utils": "^5.3.15",
"@0x/contracts-zero-ex": "^0.13.0", "@0x/contracts-zero-ex": "^0.14.0",
"@0x/subproviders": "^6.2.3", "@0x/subproviders": "^6.2.3",
"@0x/types": "^3.3.1", "@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6", "@0x/typescript-typings": "^5.1.6",

View File

@@ -1,4 +1,14 @@
[ [
{
"version": "0.14.0",
"changes": [
{
"note": "Use the `MetaTransaction` class from `@0x/protocol-utils` in tests.",
"pr": 90
}
],
"timestamp": 1608149382
},
{ {
"version": "0.13.0", "version": "0.13.0",
"changes": [ "changes": [

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v0.14.0 - _December 16, 2020_
* Use the `MetaTransaction` class from `@0x/protocol-utils` in tests. (#90)
## v0.13.0 - _December 16, 2020_ ## v0.13.0 - _December 16, 2020_
* Address audit feedback in UniswapFeature (#82) * Address audit feedback in UniswapFeature (#82)

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/contracts-zero-ex", "name": "@0x/contracts-zero-ex",
"version": "0.13.0", "version": "0.14.0",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@@ -61,6 +61,7 @@
"@0x/contracts-gen": "^2.0.24", "@0x/contracts-gen": "^2.0.24",
"@0x/contracts-test-utils": "^5.3.15", "@0x/contracts-test-utils": "^5.3.15",
"@0x/dev-utils": "^4.1.3", "@0x/dev-utils": "^4.1.3",
"@0x/order-utils": "^10.4.10",
"@0x/sol-compiler": "^4.4.1", "@0x/sol-compiler": "^4.4.1",
"@0x/ts-doc-gen": "^0.0.28", "@0x/ts-doc-gen": "^0.0.28",
"@0x/tslint-config": "^4.1.3", "@0x/tslint-config": "^4.1.3",
@@ -82,8 +83,7 @@
}, },
"dependencies": { "dependencies": {
"@0x/base-contract": "^6.2.14", "@0x/base-contract": "^6.2.14",
"@0x/order-utils": "^10.4.10", "@0x/protocol-utils": "^1.1.0",
"@0x/protocol-utils": "^1.0.1",
"@0x/subproviders": "^6.2.3", "@0x/subproviders": "^6.2.3",
"@0x/types": "^3.3.1", "@0x/types": "^3.3.1",
"@0x/typescript-typings": "^5.1.6", "@0x/typescript-typings": "^5.1.6",

View File

@@ -6,9 +6,7 @@ import {
randomAddress, randomAddress,
verifyEventsFromLogs, verifyEventsFromLogs,
} from '@0x/contracts-test-utils'; } from '@0x/contracts-test-utils';
import { getExchangeProxyMetaTransactionHash, signatureUtils } from '@0x/order-utils'; import { MetaTransaction, MetaTransactionFields } from '@0x/protocol-utils';
import { Signature } from '@0x/protocol-utils';
import { ExchangeProxyMetaTransaction } from '@0x/types';
import { BigNumber, hexUtils, StringRevertError, ZeroExRevertErrors } from '@0x/utils'; import { BigNumber, hexUtils, StringRevertError, ZeroExRevertErrors } from '@0x/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
@@ -31,6 +29,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
let owner: string; let owner: string;
let maker: string; let maker: string;
let sender: string; let sender: string;
let notSigner: string;
let signers: string[]; let signers: string[];
let zeroEx: IZeroExContract; let zeroEx: IZeroExContract;
let feature: MetaTransactionsFeatureContract; let feature: MetaTransactionsFeatureContract;
@@ -45,7 +44,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
const REENTRANCY_FLAG_MTX = 0x1; const REENTRANCY_FLAG_MTX = 0x1;
before(async () => { before(async () => {
[owner, maker, sender, ...signers] = await env.getAccountAddressesAsync(); [owner, maker, sender, notSigner, ...signers] = await env.getAccountAddressesAsync();
transformERC20Feature = await TestMetaTransactionsTransformERC20FeatureContract.deployFrom0xArtifactAsync( transformERC20Feature = await TestMetaTransactionsTransformERC20FeatureContract.deployFrom0xArtifactAsync(
artifacts.TestMetaTransactionsTransformERC20Feature, artifacts.TestMetaTransactionsTransformERC20Feature,
env.provider, env.provider,
@@ -83,19 +82,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
); );
}); });
function sigstruct(signature: string): Signature { function getRandomMetaTransaction(fields: Partial<MetaTransactionFields> = {}): MetaTransaction {
return { return new MetaTransaction({
v: parseInt(hexUtils.slice(signature, 0, 1), 16),
signatureType: parseInt(hexUtils.slice(signature, 65, 66), 16),
r: hexUtils.slice(signature, 1, 33),
s: hexUtils.slice(signature, 33, 65),
};
}
function getRandomMetaTransaction(
fields: Partial<ExchangeProxyMetaTransaction> = {},
): ExchangeProxyMetaTransaction {
return {
signer: _.sampleSize(signers)[0], signer: _.sampleSize(signers)[0],
sender, sender,
minGasPrice: getRandomInteger('2', '1e9'), minGasPrice: getRandomInteger('2', '1e9'),
@@ -106,28 +94,16 @@ blockchainTests.resets('MetaTransactions feature', env => {
value: getRandomInteger(1, '1e18'), value: getRandomInteger(1, '1e18'),
feeToken: feeToken.address, feeToken: feeToken.address,
feeAmount: getRandomInteger(1, MAX_FEE_AMOUNT), feeAmount: getRandomInteger(1, MAX_FEE_AMOUNT),
domain: { chainId: 1, // Ganache's `chainid` opcode is hardcoded as 1
chainId: 1, // Ganache's `chainid` opcode is hardcoded as 1 verifyingContract: zeroEx.address,
verifyingContract: zeroEx.address,
},
...fields, ...fields,
}; });
}
async function signMetaTransactionAsync(mtx: ExchangeProxyMetaTransaction, signer?: string): Promise<Signature> {
return sigstruct(
await signatureUtils.ecSignHashAsync(
env.provider,
getExchangeProxyMetaTransactionHash(mtx),
signer || mtx.signer,
),
);
} }
describe('getMetaTransactionHash()', () => { describe('getMetaTransactionHash()', () => {
it('generates the correct hash', async () => { it('generates the correct hash', async () => {
const mtx = getRandomMetaTransaction(); const mtx = getRandomMetaTransaction();
const expected = getExchangeProxyMetaTransactionHash(mtx); const expected = mtx.getHash();
const actual = await feature.getMetaTransactionHash(mtx).callAsync(); const actual = await feature.getMetaTransactionHash(mtx).callAsync();
expect(actual).to.eq(expected); expect(actual).to.eq(expected);
}); });
@@ -163,7 +139,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
const mtx = getRandomMetaTransaction({ const mtx = getRandomMetaTransaction({
callData: nativeOrdersFeature.fillLimitOrder(order, sig, fillAmount).getABIEncodedTransactionData(), callData: nativeOrdersFeature.fillLimitOrder(order, sig, fillAmount).getABIEncodedTransactionData(),
}); });
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: mtx.value, value: mtx.value,
@@ -198,7 +174,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
callData: nativeOrdersFeature.fillRfqOrder(order, sig, fillAmount).getABIEncodedTransactionData(), callData: nativeOrdersFeature.fillRfqOrder(order, sig, fillAmount).getABIEncodedTransactionData(),
value: ZERO_AMOUNT, value: ZERO_AMOUNT,
}); });
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: 0, value: 0,
@@ -237,7 +213,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
) )
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
}); });
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: mtx.value, value: mtx.value,
@@ -275,7 +251,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
) )
.getABIEncodedTransactionData(); .getABIEncodedTransactionData();
const mtx = getRandomMetaTransaction({ callData }); const mtx = getRandomMetaTransaction({ callData });
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: mtx.value, value: mtx.value,
@@ -315,7 +291,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
) )
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
}); });
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: mtx.value, value: mtx.value,
@@ -340,7 +316,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
) )
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
}); });
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: mtx.value, value: mtx.value,
@@ -363,8 +339,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
) )
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: mtx.value, value: mtx.value,
@@ -393,8 +369,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
const mtx = getRandomMetaTransaction({ const mtx = getRandomMetaTransaction({
callData: transformERC20Feature.createTransformWallet().getABIEncodedTransactionData(), callData: transformERC20Feature.createTransformWallet().getABIEncodedTransactionData(),
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: mtx.value, value: mtx.value,
@@ -421,8 +397,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
) )
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: mtx.value, value: mtx.value,
@@ -439,8 +415,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
it('fails if not enough ETH provided', async () => { it('fails if not enough ETH provided', async () => {
const mtx = getRandomMetaTransaction(); const mtx = getRandomMetaTransaction();
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: mtx.value.minus(1), value: mtx.value.minus(1),
@@ -457,8 +433,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
it('fails if gas price too low', async () => { it('fails if gas price too low', async () => {
const mtx = getRandomMetaTransaction(); const mtx = getRandomMetaTransaction();
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice.minus(1), gasPrice: mtx.minGasPrice.minus(1),
value: mtx.value, value: mtx.value,
@@ -476,8 +452,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
it('fails if gas price too high', async () => { it('fails if gas price too high', async () => {
const mtx = getRandomMetaTransaction(); const mtx = getRandomMetaTransaction();
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.maxGasPrice.plus(1), gasPrice: mtx.maxGasPrice.plus(1),
value: mtx.value, value: mtx.value,
@@ -497,8 +473,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
const mtx = getRandomMetaTransaction({ const mtx = getRandomMetaTransaction({
expirationTimeSeconds: new BigNumber(Math.floor(_.now() / 1000 - 60)), expirationTimeSeconds: new BigNumber(Math.floor(_.now() / 1000 - 60)),
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.maxGasPrice, gasPrice: mtx.maxGasPrice,
value: mtx.value, value: mtx.value,
@@ -518,8 +494,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
const mtx = getRandomMetaTransaction({ const mtx = getRandomMetaTransaction({
sender: requiredSender, sender: requiredSender,
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.maxGasPrice, gasPrice: mtx.maxGasPrice,
value: mtx.value, value: mtx.value,
@@ -536,8 +512,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
it('fails if signature is wrong', async () => { it('fails if signature is wrong', async () => {
const mtx = getRandomMetaTransaction({ signer: signers[0] }); const mtx = getRandomMetaTransaction({ signer: signers[0] });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx, signers[1]); const signature = await mtx.clone({ signer: notSigner }).getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.maxGasPrice, gasPrice: mtx.maxGasPrice,
value: mtx.value, value: mtx.value,
@@ -567,8 +543,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
value: TRANSFORM_ERC20_REENTER_VALUE, value: TRANSFORM_ERC20_REENTER_VALUE,
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.maxGasPrice, gasPrice: mtx.maxGasPrice,
value: mtx.value, value: mtx.value,
@@ -600,8 +576,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
value: TRANSFORM_ERC20_BATCH_REENTER_VALUE, value: TRANSFORM_ERC20_BATCH_REENTER_VALUE,
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.maxGasPrice, gasPrice: mtx.maxGasPrice,
value: mtx.value, value: mtx.value,
@@ -633,8 +609,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
value: TRANSFORM_ERC20_REENTER_VALUE, value: TRANSFORM_ERC20_REENTER_VALUE,
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.maxGasPrice, gasPrice: mtx.maxGasPrice,
value: mtx.value, value: mtx.value,
@@ -666,8 +642,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
value: TRANSFORM_ERC20_BATCH_REENTER_VALUE, value: TRANSFORM_ERC20_BATCH_REENTER_VALUE,
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.maxGasPrice, gasPrice: mtx.maxGasPrice,
value: mtx.value, value: mtx.value,
@@ -703,7 +679,9 @@ blockchainTests.resets('MetaTransactions feature', env => {
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
}); });
}); });
const signatures = await Promise.all(mtxs.map(async mtx => signMetaTransactionAsync(mtx))); const signatures = await Promise.all(
mtxs.map(async mtx => mtx.getSignatureWithProviderAsync(env.provider)),
);
const callOpts = { const callOpts = {
gasPrice: BigNumber.max(...mtxs.map(mtx => mtx.minGasPrice)), gasPrice: BigNumber.max(...mtxs.map(mtx => mtx.minGasPrice)),
value: BigNumber.sum(...mtxs.map(mtx => mtx.value)), value: BigNumber.sum(...mtxs.map(mtx => mtx.value)),
@@ -728,9 +706,9 @@ blockchainTests.resets('MetaTransactions feature', env => {
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
}); });
})(); })();
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const mtxs = _.times(2, () => mtx); const mtxs = _.times(2, () => mtx);
const signatures = await Promise.all(mtxs.map(async m => signMetaTransactionAsync(m))); const signatures = await Promise.all(mtxs.map(async m => m.getSignatureWithProviderAsync(env.provider)));
const callOpts = { const callOpts = {
gasPrice: BigNumber.max(...mtxs.map(m => m.minGasPrice)), gasPrice: BigNumber.max(...mtxs.map(m => m.minGasPrice)),
value: BigNumber.sum(...mtxs.map(m => m.value)), value: BigNumber.sum(...mtxs.map(m => m.value)),
@@ -756,8 +734,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
) )
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: mtx.value, value: mtx.value,
@@ -786,8 +764,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
value: TRANSFORM_ERC20_REENTER_VALUE, value: TRANSFORM_ERC20_REENTER_VALUE,
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.maxGasPrice, gasPrice: mtx.maxGasPrice,
value: mtx.value, value: mtx.value,
@@ -819,8 +797,8 @@ blockchainTests.resets('MetaTransactions feature', env => {
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
value: TRANSFORM_ERC20_BATCH_REENTER_VALUE, value: TRANSFORM_ERC20_BATCH_REENTER_VALUE,
}); });
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.maxGasPrice, gasPrice: mtx.maxGasPrice,
value: mtx.value, value: mtx.value,
@@ -859,7 +837,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
) )
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
}); });
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: mtx.value, value: mtx.value,
@@ -873,7 +851,7 @@ blockchainTests.resets('MetaTransactions feature', env => {
describe('getMetaTransactionHashExecutedBlock()', () => { describe('getMetaTransactionHashExecutedBlock()', () => {
it('returns zero for an unexecuted mtx', async () => { it('returns zero for an unexecuted mtx', async () => {
const mtx = getRandomMetaTransaction(); const mtx = getRandomMetaTransaction();
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const block = await feature.getMetaTransactionHashExecutedBlock(mtxHash).callAsync(); const block = await feature.getMetaTransactionHashExecutedBlock(mtxHash).callAsync();
expect(block).to.bignumber.eq(0); expect(block).to.bignumber.eq(0);
}); });
@@ -891,13 +869,13 @@ blockchainTests.resets('MetaTransactions feature', env => {
) )
.getABIEncodedTransactionData(), .getABIEncodedTransactionData(),
}); });
const signature = await signMetaTransactionAsync(mtx); const signature = await mtx.getSignatureWithProviderAsync(env.provider);
const callOpts = { const callOpts = {
gasPrice: mtx.minGasPrice, gasPrice: mtx.minGasPrice,
value: mtx.value, value: mtx.value,
}; };
const receipt = await feature.executeMetaTransaction(mtx, signature).awaitTransactionSuccessAsync(callOpts); const receipt = await feature.executeMetaTransaction(mtx, signature).awaitTransactionSuccessAsync(callOpts);
const mtxHash = getExchangeProxyMetaTransactionHash(mtx); const mtxHash = mtx.getHash();
const block = await feature.getMetaTransactionHashExecutedBlock(mtxHash).callAsync(); const block = await feature.getMetaTransactionHashExecutedBlock(mtxHash).callAsync();
expect(block).to.bignumber.eq(receipt.blockNumber); expect(block).to.bignumber.eq(receipt.blockNumber);
}); });

View File

@@ -1,4 +1,13 @@
[ [
{
"timestamp": 1608149382,
"version": "5.5.1",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"version": "5.5.0", "version": "5.5.0",
"changes": [ "changes": [

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v5.5.1 - _December 16, 2020_
* Dependencies updated
## v5.5.0 - _December 16, 2020_ ## v5.5.0 - _December 16, 2020_
* Bancor now supported in all pairs (#88) * Bancor now supported in all pairs (#88)

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/asset-swapper", "name": "@0x/asset-swapper",
"version": "5.5.0", "version": "5.5.1",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@@ -94,9 +94,9 @@
"@0x/contracts-gen": "^2.0.24", "@0x/contracts-gen": "^2.0.24",
"@0x/contracts-test-utils": "^5.3.15", "@0x/contracts-test-utils": "^5.3.15",
"@0x/contracts-utils": "^4.6.3", "@0x/contracts-utils": "^4.6.3",
"@0x/contracts-zero-ex": "^0.13.0", "@0x/contracts-zero-ex": "^0.14.0",
"@0x/mesh-rpc-client": "^9.4.2", "@0x/mesh-rpc-client": "^9.4.2",
"@0x/migrations": "^6.5.5", "@0x/migrations": "^6.5.6",
"@0x/sol-compiler": "^4.4.1", "@0x/sol-compiler": "^4.4.1",
"@0x/subproviders": "^6.2.3", "@0x/subproviders": "^6.2.3",
"@0x/ts-doc-gen": "^0.0.28", "@0x/ts-doc-gen": "^0.0.28",

View File

@@ -1,4 +1,4 @@
import { getContractAddressesForChainOrThrow } from '@0x/contract-addresses'; import { ChainId, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { DevUtilsContract } from '@0x/contract-wrappers'; import { DevUtilsContract } from '@0x/contract-wrappers';
import { schemas } from '@0x/json-schemas'; import { schemas } from '@0x/json-schemas';
import { assetDataUtils, SignedOrder } from '@0x/order-utils'; import { assetDataUtils, SignedOrder } from '@0x/order-utils';
@@ -26,6 +26,7 @@ import {
import { assert } from './utils/assert'; import { assert } from './utils/assert';
import { calculateLiquidity } from './utils/calculate_liquidity'; import { calculateLiquidity } from './utils/calculate_liquidity';
import { MarketOperationUtils } from './utils/market_operation_utils'; import { MarketOperationUtils } from './utils/market_operation_utils';
import { BancorService } from './utils/market_operation_utils/bancor_service';
import { createDummyOrderForSampler } from './utils/market_operation_utils/orders'; import { createDummyOrderForSampler } from './utils/market_operation_utils/orders';
import { DexOrderSampler } from './utils/market_operation_utils/sampler'; import { DexOrderSampler } from './utils/market_operation_utils/sampler';
import { SourceFilters } from './utils/market_operation_utils/source_filters'; import { SourceFilters } from './utils/market_operation_utils/source_filters';
@@ -208,15 +209,18 @@ export class SwapQuoter {
gas: samplerGasLimit, gas: samplerGasLimit,
}, },
); );
this._marketOperationUtils = new MarketOperationUtils( this._marketOperationUtils = new MarketOperationUtils(
new DexOrderSampler( new DexOrderSampler(
samplerContract, samplerContract,
samplerOverrides, samplerOverrides,
provider,
undefined, // balancer pool cache undefined, // balancer pool cache
undefined, // cream pool cache undefined, // cream pool cache
tokenAdjacencyGraph, tokenAdjacencyGraph,
liquidityProviderRegistry, liquidityProviderRegistry,
this.chainId === ChainId.Mainnet // Enable Bancor only on Mainnet
? async () => BancorService.createAsync(provider)
: async () => undefined,
), ),
this._contractAddresses, this._contractAddresses,
{ {

View File

@@ -1,10 +1,10 @@
import { SupportedProvider } from '@0x/dev-utils';
import { BigNumber, NULL_BYTES } from '@0x/utils'; import { BigNumber, NULL_BYTES } from '@0x/utils';
import { SamplerOverrides } from '../../types'; import { SamplerOverrides } from '../../types';
import { ERC20BridgeSamplerContract } from '../../wrappers'; import { ERC20BridgeSamplerContract } from '../../wrappers';
import { BalancerPoolsCache } from './balancer_utils'; import { BalancerPoolsCache } from './balancer_utils';
import { BancorService } from './bancor_service';
import { CreamPoolsCache } from './cream_utils'; import { CreamPoolsCache } from './cream_utils';
import { SamplerOperations } from './sampler_operations'; import { SamplerOperations } from './sampler_operations';
import { BatchedOperation, LiquidityProviderRegistry, TokenAdjacencyGraph } from './types'; import { BatchedOperation, LiquidityProviderRegistry, TokenAdjacencyGraph } from './types';
@@ -35,19 +35,19 @@ export class DexOrderSampler extends SamplerOperations {
constructor( constructor(
_samplerContract: ERC20BridgeSamplerContract, _samplerContract: ERC20BridgeSamplerContract,
private readonly _samplerOverrides?: SamplerOverrides, private readonly _samplerOverrides?: SamplerOverrides,
provider?: SupportedProvider,
balancerPoolsCache?: BalancerPoolsCache, balancerPoolsCache?: BalancerPoolsCache,
creamPoolsCache?: CreamPoolsCache, creamPoolsCache?: CreamPoolsCache,
tokenAdjacencyGraph?: TokenAdjacencyGraph, tokenAdjacencyGraph?: TokenAdjacencyGraph,
liquidityProviderRegistry?: LiquidityProviderRegistry, liquidityProviderRegistry?: LiquidityProviderRegistry,
bancorServiceFn: () => Promise<BancorService | undefined> = async () => undefined,
) { ) {
super( super(
_samplerContract, _samplerContract,
provider,
balancerPoolsCache, balancerPoolsCache,
creamPoolsCache, creamPoolsCache,
tokenAdjacencyGraph, tokenAdjacencyGraph,
liquidityProviderRegistry, liquidityProviderRegistry,
bancorServiceFn,
); );
} }

View File

@@ -1,4 +1,3 @@
import { SupportedProvider } from '@0x/dev-utils';
import { SignedOrder } from '@0x/types'; import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils'; import { BigNumber } from '@0x/utils';
import * as _ from 'lodash'; import * as _ from 'lodash';
@@ -81,23 +80,16 @@ export class SamplerOperations {
constructor( constructor(
protected readonly _samplerContract: ERC20BridgeSamplerContract, protected readonly _samplerContract: ERC20BridgeSamplerContract,
public readonly provider?: SupportedProvider,
public readonly balancerPoolsCache: BalancerPoolsCache = new BalancerPoolsCache(), public readonly balancerPoolsCache: BalancerPoolsCache = new BalancerPoolsCache(),
public readonly creamPoolsCache: CreamPoolsCache = new CreamPoolsCache(), public readonly creamPoolsCache: CreamPoolsCache = new CreamPoolsCache(),
protected readonly tokenAdjacencyGraph: TokenAdjacencyGraph = { default: [] }, protected readonly tokenAdjacencyGraph: TokenAdjacencyGraph = { default: [] },
public readonly liquidityProviderRegistry: LiquidityProviderRegistry = LIQUIDITY_PROVIDER_REGISTRY, public readonly liquidityProviderRegistry: LiquidityProviderRegistry = LIQUIDITY_PROVIDER_REGISTRY,
bancorServiceFn: () => Promise<BancorService | undefined> = async () => undefined,
) { ) {
// Initialize the Bancor service, fetching paths in the background // Initialize the Bancor service, fetching paths in the background
this.initBancorServiceAsync().catch(/* do nothing */); bancorServiceFn()
} .then(service => (this._bancorService = service))
.catch(/* do nothing */);
public async initBancorServiceAsync(): Promise<void> {
if (this.provider === undefined) {
return;
}
if (this._bancorService === undefined) {
this._bancorService = await BancorService.createAsync(this.provider);
}
} }
public getTokenDecimals(makerTokenAddress: string, takerTokenAddress: string): BatchedOperation<BigNumber[]> { public getTokenDecimals(makerTokenAddress: string, takerTokenAddress: string): BatchedOperation<BigNumber[]> {

View File

@@ -102,7 +102,15 @@ describe('DexSampler tests', () => {
return expectedFillableAmounts; return expectedFillableAmounts;
}, },
}); });
const dexOrderSampler = new DexOrderSampler(sampler); const dexOrderSampler = new DexOrderSampler(
sampler,
undefined,
undefined,
undefined,
undefined,
undefined,
async () => undefined,
);
const [fillableAmounts] = await dexOrderSampler.executeAsync( const [fillableAmounts] = await dexOrderSampler.executeAsync(
dexOrderSampler.getOrderFillableMakerAmounts(ORDERS, exchangeAddress), dexOrderSampler.getOrderFillableMakerAmounts(ORDERS, exchangeAddress),
); );
@@ -118,7 +126,15 @@ describe('DexSampler tests', () => {
return expectedFillableAmounts; return expectedFillableAmounts;
}, },
}); });
const dexOrderSampler = new DexOrderSampler(sampler); const dexOrderSampler = new DexOrderSampler(
sampler,
undefined,
undefined,
undefined,
undefined,
undefined,
async () => undefined,
);
const [fillableAmounts] = await dexOrderSampler.executeAsync( const [fillableAmounts] = await dexOrderSampler.executeAsync(
dexOrderSampler.getOrderFillableTakerAmounts(ORDERS, exchangeAddress), dexOrderSampler.getOrderFillableTakerAmounts(ORDERS, exchangeAddress),
); );
@@ -138,7 +154,15 @@ describe('DexSampler tests', () => {
return ['0x', expectedMakerFillAmounts]; return ['0x', expectedMakerFillAmounts];
}, },
}); });
const dexOrderSampler = new DexOrderSampler(sampler); const dexOrderSampler = new DexOrderSampler(
sampler,
undefined,
undefined,
undefined,
undefined,
undefined,
async () => undefined,
);
const [fillableAmounts] = await dexOrderSampler.executeAsync( const [fillableAmounts] = await dexOrderSampler.executeAsync(
dexOrderSampler.getKyberSellQuotes( dexOrderSampler.getKyberSellQuotes(
'0x', '0x',
@@ -169,8 +193,10 @@ describe('DexSampler tests', () => {
undefined, undefined,
undefined, undefined,
undefined, undefined,
undefined, {
{ [poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost } }, [poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost },
},
async () => undefined,
); );
const [result] = await dexOrderSampler.executeAsync( const [result] = await dexOrderSampler.executeAsync(
dexOrderSampler.getSellQuotes( dexOrderSampler.getSellQuotes(
@@ -211,8 +237,10 @@ describe('DexSampler tests', () => {
undefined, undefined,
undefined, undefined,
undefined, undefined,
undefined, {
{ [poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost } }, [poolAddress]: { tokens: [expectedMakerToken, expectedTakerToken], gasCost },
},
async () => undefined,
); );
const [result] = await dexOrderSampler.executeAsync( const [result] = await dexOrderSampler.executeAsync(
dexOrderSampler.getBuyQuotes( dexOrderSampler.getBuyQuotes(
@@ -247,7 +275,15 @@ describe('DexSampler tests', () => {
return expectedMakerFillAmounts; return expectedMakerFillAmounts;
}, },
}); });
const dexOrderSampler = new DexOrderSampler(sampler); const dexOrderSampler = new DexOrderSampler(
sampler,
undefined,
undefined,
undefined,
undefined,
undefined,
async () => undefined,
);
const [fillableAmounts] = await dexOrderSampler.executeAsync( const [fillableAmounts] = await dexOrderSampler.executeAsync(
dexOrderSampler.getEth2DaiSellQuotes(expectedMakerToken, expectedTakerToken, expectedTakerFillAmounts), dexOrderSampler.getEth2DaiSellQuotes(expectedMakerToken, expectedTakerToken, expectedTakerFillAmounts),
); );
@@ -267,7 +303,15 @@ describe('DexSampler tests', () => {
return expectedMakerFillAmounts; return expectedMakerFillAmounts;
}, },
}); });
const dexOrderSampler = new DexOrderSampler(sampler); const dexOrderSampler = new DexOrderSampler(
sampler,
undefined,
undefined,
undefined,
undefined,
undefined,
async () => undefined,
);
const [fillableAmounts] = await dexOrderSampler.executeAsync( const [fillableAmounts] = await dexOrderSampler.executeAsync(
dexOrderSampler.getUniswapSellQuotes(expectedMakerToken, expectedTakerToken, expectedTakerFillAmounts), dexOrderSampler.getUniswapSellQuotes(expectedMakerToken, expectedTakerToken, expectedTakerFillAmounts),
); );
@@ -286,7 +330,15 @@ describe('DexSampler tests', () => {
return expectedMakerFillAmounts; return expectedMakerFillAmounts;
}, },
}); });
const dexOrderSampler = new DexOrderSampler(sampler); const dexOrderSampler = new DexOrderSampler(
sampler,
undefined,
undefined,
undefined,
undefined,
undefined,
async () => undefined,
);
const [fillableAmounts] = await dexOrderSampler.executeAsync( const [fillableAmounts] = await dexOrderSampler.executeAsync(
dexOrderSampler.getUniswapV2SellQuotes( dexOrderSampler.getUniswapV2SellQuotes(
[expectedMakerToken, expectedTakerToken], [expectedMakerToken, expectedTakerToken],
@@ -309,7 +361,15 @@ describe('DexSampler tests', () => {
return expectedTakerFillAmounts; return expectedTakerFillAmounts;
}, },
}); });
const dexOrderSampler = new DexOrderSampler(sampler); const dexOrderSampler = new DexOrderSampler(
sampler,
undefined,
undefined,
undefined,
undefined,
undefined,
async () => undefined,
);
const [fillableAmounts] = await dexOrderSampler.executeAsync( const [fillableAmounts] = await dexOrderSampler.executeAsync(
dexOrderSampler.getEth2DaiBuyQuotes(expectedMakerToken, expectedTakerToken, expectedMakerFillAmounts), dexOrderSampler.getEth2DaiBuyQuotes(expectedMakerToken, expectedTakerToken, expectedMakerFillAmounts),
); );
@@ -329,7 +389,15 @@ describe('DexSampler tests', () => {
return expectedTakerFillAmounts; return expectedTakerFillAmounts;
}, },
}); });
const dexOrderSampler = new DexOrderSampler(sampler); const dexOrderSampler = new DexOrderSampler(
sampler,
undefined,
undefined,
undefined,
undefined,
undefined,
async () => undefined,
);
const [fillableAmounts] = await dexOrderSampler.executeAsync( const [fillableAmounts] = await dexOrderSampler.executeAsync(
dexOrderSampler.getUniswapBuyQuotes(expectedMakerToken, expectedTakerToken, expectedMakerFillAmounts), dexOrderSampler.getUniswapBuyQuotes(expectedMakerToken, expectedTakerToken, expectedMakerFillAmounts),
); );
@@ -381,8 +449,9 @@ describe('DexSampler tests', () => {
undefined, undefined,
undefined, undefined,
undefined, undefined,
undefined,
tokenAdjacencyGraph, tokenAdjacencyGraph,
undefined,
async () => undefined,
); );
const [quotes] = await dexOrderSampler.executeAsync( const [quotes] = await dexOrderSampler.executeAsync(
dexOrderSampler.getSellQuotes( dexOrderSampler.getSellQuotes(
@@ -436,8 +505,11 @@ describe('DexSampler tests', () => {
const dexOrderSampler = new DexOrderSampler( const dexOrderSampler = new DexOrderSampler(
new MockSamplerContract({}), new MockSamplerContract({}),
undefined, undefined,
undefined,
balancerPoolsCache, balancerPoolsCache,
undefined,
undefined,
undefined,
async () => undefined,
); );
const quotes = await dexOrderSampler.getBalancerSellQuotesOffChainAsync( const quotes = await dexOrderSampler.getBalancerSellQuotesOffChainAsync(
expectedMakerToken, expectedMakerToken,
@@ -486,8 +558,9 @@ describe('DexSampler tests', () => {
undefined, undefined,
undefined, undefined,
undefined, undefined,
undefined,
tokenAdjacencyGraph, tokenAdjacencyGraph,
undefined,
async () => undefined,
); );
const [quotes] = await dexOrderSampler.executeAsync( const [quotes] = await dexOrderSampler.executeAsync(
dexOrderSampler.getBuyQuotes(sources, expectedMakerToken, expectedTakerToken, expectedMakerFillAmounts), dexOrderSampler.getBuyQuotes(sources, expectedMakerToken, expectedTakerToken, expectedMakerFillAmounts),
@@ -532,8 +605,11 @@ describe('DexSampler tests', () => {
const dexOrderSampler = new DexOrderSampler( const dexOrderSampler = new DexOrderSampler(
new MockSamplerContract({}), new MockSamplerContract({}),
undefined, undefined,
undefined,
balancerPoolsCache, balancerPoolsCache,
undefined,
undefined,
undefined,
async () => undefined,
); );
const quotes = await dexOrderSampler.getBalancerBuyQuotesOffChainAsync( const quotes = await dexOrderSampler.getBalancerBuyQuotesOffChainAsync(
expectedMakerToken, expectedMakerToken,
@@ -560,7 +636,15 @@ describe('DexSampler tests', () => {
return expectedFillableTakerAmounts; return expectedFillableTakerAmounts;
}, },
}); });
const dexOrderSampler = new DexOrderSampler(sampler); const dexOrderSampler = new DexOrderSampler(
sampler,
undefined,
undefined,
undefined,
undefined,
undefined,
async () => undefined,
);
const [fillableMakerAmounts, fillableTakerAmounts] = await dexOrderSampler.executeAsync( const [fillableMakerAmounts, fillableTakerAmounts] = await dexOrderSampler.executeAsync(
dexOrderSampler.getOrderFillableMakerAmounts(ORDERS, exchangeAddress), dexOrderSampler.getOrderFillableMakerAmounts(ORDERS, exchangeAddress),
dexOrderSampler.getOrderFillableTakerAmounts(ORDERS, exchangeAddress), dexOrderSampler.getOrderFillableTakerAmounts(ORDERS, exchangeAddress),

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/contract-wrappers-test", "name": "@0x/contract-wrappers-test",
"version": "12.2.29", "version": "12.2.30",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@@ -34,7 +34,7 @@
"@0x/contract-wrappers": "^13.11.0", "@0x/contract-wrappers": "^13.11.0",
"@0x/contracts-test-utils": "^5.3.15", "@0x/contracts-test-utils": "^5.3.15",
"@0x/dev-utils": "^4.1.3", "@0x/dev-utils": "^4.1.3",
"@0x/migrations": "^6.5.5", "@0x/migrations": "^6.5.6",
"@0x/order-utils": "^10.4.10", "@0x/order-utils": "^10.4.10",
"@0x/subproviders": "^6.2.3", "@0x/subproviders": "^6.2.3",
"@0x/ts-doc-gen": "^0.0.28", "@0x/ts-doc-gen": "^0.0.28",

View File

@@ -1,4 +1,13 @@
[ [
{
"timestamp": 1608149382,
"version": "6.5.6",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{ {
"timestamp": 1608105788, "timestamp": 1608105788,
"version": "6.5.5", "version": "6.5.5",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v6.5.6 - _December 16, 2020_
* Dependencies updated
## v6.5.5 - _December 16, 2020_ ## v6.5.5 - _December 16, 2020_
* Dependencies updated * Dependencies updated

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/migrations", "name": "@0x/migrations",
"version": "6.5.5", "version": "6.5.6",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },
@@ -81,7 +81,7 @@
"@0x/contracts-multisig": "^4.1.19", "@0x/contracts-multisig": "^4.1.19",
"@0x/contracts-staking": "^2.0.26", "@0x/contracts-staking": "^2.0.26",
"@0x/contracts-utils": "^4.6.3", "@0x/contracts-utils": "^4.6.3",
"@0x/contracts-zero-ex": "^0.13.0", "@0x/contracts-zero-ex": "^0.14.0",
"@0x/sol-compiler": "^4.4.1", "@0x/sol-compiler": "^4.4.1",
"@0x/subproviders": "^6.2.3", "@0x/subproviders": "^6.2.3",
"@0x/typescript-typings": "^5.1.6", "@0x/typescript-typings": "^5.1.6",

View File

@@ -1,4 +1,14 @@
[ [
{
"version": "1.1.0",
"changes": [
{
"note": "Add the `MetaTransaction` class for EP mtxs",
"pr": 90
}
],
"timestamp": 1608149382
},
{ {
"timestamp": 1607485227, "timestamp": 1607485227,
"version": "1.0.1", "version": "1.0.1",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG CHANGELOG
## v1.1.0 - _December 16, 2020_
* Add the `MetaTransaction` class for EP mtxs (#90)
## v1.0.1 - _December 9, 2020_ ## v1.0.1 - _December 9, 2020_
* Dependencies updated * Dependencies updated

View File

@@ -1,6 +1,6 @@
{ {
"name": "@0x/protocol-utils", "name": "@0x/protocol-utils",
"version": "1.0.1", "version": "1.1.0",
"engines": { "engines": {
"node": ">=6.12" "node": ">=6.12"
}, },

View File

@@ -1 +1,4 @@
import { BigNumber } from '@0x/utils';
export const ETH_TOKEN_ADDRESS = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'; export const ETH_TOKEN_ADDRESS = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
export const ZERO = new BigNumber(0);

View File

@@ -7,6 +7,8 @@ export interface EIP712Domain {
verifyingContract: string; verifyingContract: string;
} }
export type EIP712_STRUCT_ABI = Array<{ type: string; name: string }>;
export const EIP712_DOMAIN_PARAMETERS = [ export const EIP712_DOMAIN_PARAMETERS = [
{ name: 'name', type: 'string' }, { name: 'name', type: 'string' },
{ name: 'version', type: 'string' }, { name: 'version', type: 'string' },
@@ -68,3 +70,12 @@ export function getExchangeProxyEIP712Hash(structHash: string, chainId?: number,
hexUtils.concat('0x1901', getExchangeProxyEIP712DomainHash(chainId, verifyingContract), structHash), hexUtils.concat('0x1901', getExchangeProxyEIP712DomainHash(chainId, verifyingContract), structHash),
); );
} }
/**
* Compute the type hash of an EIP712 struct given its ABI.
*/
export function getTypeHash(structName: string, abi: EIP712_STRUCT_ABI): string {
return hexUtils.hash(
hexUtils.toHex(Buffer.from([`${structName}(`, abi.map(a => `${a.type} ${a.name}`).join(','), ')'].join(''))),
);
}

View File

@@ -4,6 +4,7 @@ export const RevertError = _RevertErrors.RevertError;
export * from './eip712_utils'; export * from './eip712_utils';
export * from './orders'; export * from './orders';
export * from './meta_transactions';
export * from './signature_utils'; export * from './signature_utils';
export * from './transformer_utils'; export * from './transformer_utils';
export * from './constants'; export * from './constants';

View File

@@ -0,0 +1,171 @@
import { getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { SupportedProvider } from '@0x/subproviders';
import { EIP712TypedData } from '@0x/types';
import { BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils';
import { ZERO } from './constants';
import {
createExchangeProxyEIP712Domain,
EIP712_DOMAIN_PARAMETERS,
getExchangeProxyEIP712Hash,
getTypeHash,
} from './eip712_utils';
import {
eip712SignTypedDataWithKey,
eip712SignTypedDataWithProviderAsync,
ethSignHashWithKey,
ethSignHashWithProviderAsync,
Signature,
SignatureType,
} from './signature_utils';
const MTX_DEFAULT_VALUES = {
signer: NULL_ADDRESS,
sender: NULL_ADDRESS,
minGasPrice: ZERO,
maxGasPrice: ZERO,
expirationTimeSeconds: ZERO,
salt: ZERO,
callData: hexUtils.leftPad(0),
value: ZERO,
feeToken: NULL_ADDRESS,
feeAmount: ZERO,
chainId: 1,
verifyingContract: getContractAddressesForChainOrThrow(1).exchangeProxy,
};
export type MetaTransactionFields = typeof MTX_DEFAULT_VALUES;
export class MetaTransaction {
public static readonly STRUCT_NAME = 'MetaTransactionData';
public static readonly STRUCT_ABI = [
{ type: 'address', name: 'signer' },
{ type: 'address', name: 'sender' },
{ type: 'uint256', name: 'minGasPrice' },
{ type: 'uint256', name: 'maxGasPrice' },
{ type: 'uint256', name: 'expirationTimeSeconds' },
{ type: 'uint256', name: 'salt' },
{ type: 'bytes', name: 'callData' },
{ type: 'uint256', name: 'value' },
{ type: 'address', name: 'feeToken' },
{ type: 'uint256', name: 'feeAmount' },
];
public static readonly TYPE_HASH = getTypeHash(MetaTransaction.STRUCT_NAME, MetaTransaction.STRUCT_ABI);
public signer: string;
public sender: string;
public minGasPrice: BigNumber;
public maxGasPrice: BigNumber;
public expirationTimeSeconds: BigNumber;
public salt: BigNumber;
public callData: string;
public value: BigNumber;
public feeToken: string;
public feeAmount: BigNumber;
public chainId: number;
public verifyingContract: string;
public constructor(fields: Partial<MetaTransactionFields> = {}) {
const _fields = { ...MTX_DEFAULT_VALUES, ...fields };
this.signer = _fields.signer;
this.sender = _fields.sender;
this.minGasPrice = _fields.minGasPrice;
this.maxGasPrice = _fields.maxGasPrice;
this.expirationTimeSeconds = _fields.expirationTimeSeconds;
this.salt = _fields.salt;
this.callData = _fields.callData;
this.value = _fields.value;
this.feeToken = _fields.feeToken;
this.feeAmount = _fields.feeAmount;
this.chainId = _fields.chainId;
this.verifyingContract = _fields.verifyingContract;
}
public clone(fields: Partial<MetaTransactionFields> = {}): MetaTransaction {
return new MetaTransaction({
signer: this.signer,
sender: this.sender,
minGasPrice: this.minGasPrice,
maxGasPrice: this.maxGasPrice,
expirationTimeSeconds: this.expirationTimeSeconds,
salt: this.salt,
callData: this.callData,
value: this.value,
feeToken: this.feeToken,
feeAmount: this.feeAmount,
chainId: this.chainId,
verifyingContract: this.verifyingContract,
...fields,
});
}
public getStructHash(): string {
return hexUtils.hash(
hexUtils.concat(
hexUtils.leftPad(MetaTransaction.TYPE_HASH),
hexUtils.leftPad(this.signer),
hexUtils.leftPad(this.sender),
hexUtils.leftPad(this.minGasPrice),
hexUtils.leftPad(this.maxGasPrice),
hexUtils.leftPad(this.expirationTimeSeconds),
hexUtils.leftPad(this.salt),
hexUtils.hash(this.callData),
hexUtils.leftPad(this.value),
hexUtils.leftPad(this.feeToken),
hexUtils.leftPad(this.feeAmount),
),
);
}
public getEIP712TypedData(): EIP712TypedData {
return {
types: {
EIP712Domain: EIP712_DOMAIN_PARAMETERS,
[MetaTransaction.STRUCT_NAME]: MetaTransaction.STRUCT_ABI,
},
domain: createExchangeProxyEIP712Domain(this.chainId, this.verifyingContract) as any,
primaryType: MetaTransaction.STRUCT_NAME,
message: {
signer: this.signer,
sender: this.sender,
minGasPrice: this.minGasPrice.toString(10),
maxGasPrice: this.maxGasPrice.toString(10),
expirationTimeSeconds: this.expirationTimeSeconds.toString(10),
salt: this.salt.toString(10),
callData: this.callData,
value: this.value.toString(10),
feeToken: this.feeToken,
feeAmount: this.feeAmount.toString(10),
},
};
}
public getHash(): string {
return getExchangeProxyEIP712Hash(this.getStructHash(), this.chainId, this.verifyingContract);
}
public async getSignatureWithProviderAsync(
provider: SupportedProvider,
type: SignatureType = SignatureType.EthSign,
): Promise<Signature> {
switch (type) {
case SignatureType.EIP712:
return eip712SignTypedDataWithProviderAsync(this.getEIP712TypedData(), this.signer, provider);
case SignatureType.EthSign:
return ethSignHashWithProviderAsync(this.getHash(), this.signer, provider);
default:
throw new Error(`Cannot sign with signature type: ${type}`);
}
}
public getSignatureWithKey(key: string, type: SignatureType = SignatureType.EthSign): Signature {
switch (type) {
case SignatureType.EIP712:
return eip712SignTypedDataWithKey(this.getEIP712TypedData(), key);
case SignatureType.EthSign:
return ethSignHashWithKey(this.getHash(), key);
default:
throw new Error(`Cannot sign with signature type: ${type}`);
}
}
}

View File

@@ -1,8 +1,15 @@
import { getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { SupportedProvider } from '@0x/subproviders'; import { SupportedProvider } from '@0x/subproviders';
import { EIP712TypedData } from '@0x/types'; import { EIP712TypedData } from '@0x/types';
import { BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils'; import { BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils';
import { createExchangeProxyEIP712Domain, EIP712_DOMAIN_PARAMETERS, getExchangeProxyEIP712Hash } from './eip712_utils'; import { ZERO } from './constants';
import {
createExchangeProxyEIP712Domain,
EIP712_DOMAIN_PARAMETERS,
getExchangeProxyEIP712Hash,
getTypeHash,
} from './eip712_utils';
import { import {
eip712SignTypedDataWithKey, eip712SignTypedDataWithKey,
eip712SignTypedDataWithProviderAsync, eip712SignTypedDataWithProviderAsync,
@@ -12,7 +19,6 @@ import {
SignatureType, SignatureType,
} from './signature_utils'; } from './signature_utils';
const ZERO = new BigNumber(0);
const COMMON_ORDER_DEFAULT_VALUES = { const COMMON_ORDER_DEFAULT_VALUES = {
makerToken: NULL_ADDRESS, makerToken: NULL_ADDRESS,
takerToken: NULL_ADDRESS, takerToken: NULL_ADDRESS,
@@ -24,7 +30,7 @@ const COMMON_ORDER_DEFAULT_VALUES = {
expiry: ZERO, expiry: ZERO,
salt: ZERO, salt: ZERO,
chainId: 1, chainId: 1,
verifyingContract: '0xdef1c0ded9bec7f1a1670819833240f027b25eff', verifyingContract: getContractAddressesForChainOrThrow(1).exchangeProxy,
}; };
const LIMIT_ORDER_DEFAULT_VALUES = { const LIMIT_ORDER_DEFAULT_VALUES = {
...COMMON_ORDER_DEFAULT_VALUES, ...COMMON_ORDER_DEFAULT_VALUES,
@@ -117,30 +123,22 @@ export abstract class OrderBase {
} }
export class LimitOrder extends OrderBase { export class LimitOrder extends OrderBase {
public static readonly TYPE_HASH = hexUtils.hash( public static readonly STRUCT_NAME = 'LimitOrder';
hexUtils.toHex( public static readonly STRUCT_ABI = [
Buffer.from( { type: 'address', name: 'makerToken' },
[ { type: 'address', name: 'takerToken' },
'LimitOrder(', { type: 'uint128', name: 'makerAmount' },
[ { type: 'uint128', name: 'takerAmount' },
'address makerToken', { type: 'uint128', name: 'takerTokenFeeAmount' },
'address takerToken', { type: 'address', name: 'maker' },
'uint128 makerAmount', { type: 'address', name: 'taker' },
'uint128 takerAmount', { type: 'address', name: 'sender' },
'uint128 takerTokenFeeAmount', { type: 'address', name: 'feeRecipient' },
'address maker', { type: 'bytes32', name: 'pool' },
'address taker', { type: 'uint64', name: 'expiry' },
'address sender', { type: 'uint256', name: 'salt' },
'address feeRecipient', ];
'bytes32 pool', public static readonly TYPE_HASH = getTypeHash(LimitOrder.STRUCT_NAME, LimitOrder.STRUCT_ABI);
'uint64 expiry',
'uint256 salt',
].join(','),
')',
].join(''),
),
),
);
public takerTokenFeeAmount: BigNumber; public takerTokenFeeAmount: BigNumber;
public sender: string; public sender: string;
@@ -198,23 +196,10 @@ export class LimitOrder extends OrderBase {
return { return {
types: { types: {
EIP712Domain: EIP712_DOMAIN_PARAMETERS, EIP712Domain: EIP712_DOMAIN_PARAMETERS,
LimitOrder: [ [LimitOrder.STRUCT_NAME]: LimitOrder.STRUCT_ABI,
{ type: 'address', name: 'makerToken' },
{ type: 'address', name: 'takerToken' },
{ type: 'uint128', name: 'makerAmount' },
{ type: 'uint128', name: 'takerAmount' },
{ type: 'uint128', name: 'takerTokenFeeAmount' },
{ type: 'address', name: 'maker' },
{ type: 'address', name: 'taker' },
{ type: 'address', name: 'sender' },
{ type: 'address', name: 'feeRecipient' },
{ type: 'bytes32', name: 'pool' },
{ type: 'uint64', name: 'expiry' },
{ type: 'uint256', name: 'salt' },
],
}, },
domain: createExchangeProxyEIP712Domain(this.chainId, this.verifyingContract) as any, domain: createExchangeProxyEIP712Domain(this.chainId, this.verifyingContract) as any,
primaryType: 'LimitOrder', primaryType: LimitOrder.STRUCT_NAME,
message: { message: {
makerToken: this.makerToken, makerToken: this.makerToken,
takerToken: this.takerToken, takerToken: this.takerToken,
@@ -234,28 +219,20 @@ export class LimitOrder extends OrderBase {
} }
export class RfqOrder extends OrderBase { export class RfqOrder extends OrderBase {
public static readonly TYPE_HASH = hexUtils.hash( public static readonly STRUCT_NAME = 'RfqOrder';
hexUtils.toHex( public static readonly STRUCT_ABI = [
Buffer.from( { type: 'address', name: 'makerToken' },
[ { type: 'address', name: 'takerToken' },
'RfqOrder(', { type: 'uint128', name: 'makerAmount' },
[ { type: 'uint128', name: 'takerAmount' },
'address makerToken', { type: 'address', name: 'maker' },
'address takerToken', { type: 'address', name: 'taker' },
'uint128 makerAmount', { type: 'address', name: 'txOrigin' },
'uint128 takerAmount', { type: 'bytes32', name: 'pool' },
'address maker', { type: 'uint64', name: 'expiry' },
'address taker', { type: 'uint256', name: 'salt' },
'address txOrigin', ];
'bytes32 pool', public static readonly TYPE_HASH = getTypeHash(RfqOrder.STRUCT_NAME, RfqOrder.STRUCT_ABI);
'uint64 expiry',
'uint256 salt',
].join(','),
')',
].join(''),
),
),
);
public txOrigin: string; public txOrigin: string;
@@ -305,21 +282,10 @@ export class RfqOrder extends OrderBase {
return { return {
types: { types: {
EIP712Domain: EIP712_DOMAIN_PARAMETERS, EIP712Domain: EIP712_DOMAIN_PARAMETERS,
RfqOrder: [ [RfqOrder.STRUCT_NAME]: RfqOrder.STRUCT_ABI,
{ type: 'address', name: 'makerToken' },
{ type: 'address', name: 'takerToken' },
{ type: 'uint128', name: 'makerAmount' },
{ type: 'uint128', name: 'takerAmount' },
{ type: 'address', name: 'maker' },
{ type: 'address', name: 'taker' },
{ type: 'address', name: 'txOrigin' },
{ type: 'bytes32', name: 'pool' },
{ type: 'uint64', name: 'expiry' },
{ type: 'uint256', name: 'salt' },
],
}, },
domain: createExchangeProxyEIP712Domain(this.chainId, this.verifyingContract) as any, domain: createExchangeProxyEIP712Domain(this.chainId, this.verifyingContract) as any,
primaryType: 'RfqOrder', primaryType: RfqOrder.STRUCT_NAME,
message: { message: {
makerToken: this.makerToken, makerToken: this.makerToken,
takerToken: this.takerToken, takerToken: this.takerToken,

View File

@@ -0,0 +1,84 @@
import { chaiSetup, web3Factory, Web3Wrapper } from '@0x/dev-utils';
import { Web3ProviderEngine } from '@0x/subproviders';
import { BigNumber } from '@0x/utils';
import { expect } from 'chai';
import * as ethjs from 'ethereumjs-util';
import { MetaTransaction } from '../src/meta_transactions';
import { SignatureType } from '../src/signature_utils';
chaiSetup.configure();
describe('mtxs', () => {
let provider: Web3ProviderEngine;
let providerMaker: string;
const key = '0xee094b79aa0315914955f2f09be9abe541dcdc51f0aae5bec5453e9f73a471a6';
const keyMaker = ethjs.bufferToHex(ethjs.privateToAddress(ethjs.toBuffer(key)));
before(async () => {
provider = web3Factory.getRpcProvider({ shouldUseInProcessGanache: true });
[providerMaker] = await new Web3Wrapper(provider).getAvailableAddressesAsync();
});
describe('MetaTransaction', () => {
const mtx = new MetaTransaction({
signer: '0x349e8d89e8b37214d9ce3949fc5754152c525bc3',
sender: '0x83c62b2e67dea0df2a27be0def7a22bd7102642c',
minGasPrice: new BigNumber(1234),
maxGasPrice: new BigNumber(5678),
expirationTimeSeconds: new BigNumber(9101112),
salt: new BigNumber(2001),
callData: '0x12345678',
value: new BigNumber(1001),
feeToken: '0xcc3c7ea403427154ec908203ba6c418bd699f7ce',
feeAmount: new BigNumber(9101112),
chainId: 8008,
verifyingContract: '0x6701704d2421c64ee9aa93ec7f96ede81c4be77d',
});
it('can get the struct hash', () => {
const actual = mtx.getStructHash();
const expected = '0x164b8bfaed3718d233d4cc87501d0d8fa0a72ed7deeb8e591524133f17867180';
expect(actual).to.eq(expected);
});
it('can get the EIP712 hash', () => {
const actual = mtx.getHash();
const expected = '0x068f2f98836e489070608461768bfd3331128787d09278d38869c2b56bfc34a4';
expect(actual).to.eq(expected);
});
it('can get an EthSign signature with a provider', async () => {
const actual = await mtx.clone({ signer: providerMaker }).getSignatureWithProviderAsync(provider);
const expected = {
signatureType: SignatureType.EthSign,
r: '0xbb831776a2d6639d4e4d1641f158773ce202881bac74dddb2672d5ff5521ef5c',
s: '0x746a61ccfdfee3afae15f4a3bd67ded2ce555d89d482940a844eeffaede2ee8a',
v: 27,
};
expect(actual).to.deep.eq(expected);
});
it('can get an EthSign signature with a private key', () => {
const actual = mtx.clone({ signer: keyMaker }).getSignatureWithKey(key);
const expected = {
signatureType: SignatureType.EthSign,
r: '0xbf19b5ef62df8c8315727087e9d8562e3b88d32452ac8193e3ed9f5354a220ef',
s: '0x512387e81b2c03e4bc4cf72ee5293c86498c17fde3ae89f18dd0705076a7f472',
v: 28,
};
expect(actual).to.deep.eq(expected);
});
it('can get an EIP712 signature with a private key', () => {
const actual = mtx.clone({ signer: keyMaker }).getSignatureWithKey(key, SignatureType.EIP712);
const expected = {
signatureType: SignatureType.EIP712,
r: '0x050c6b80a3fafa1b816fdfd646f3e90862a21d3fbf3ed675eaf9c89e092ec405',
s: '0x179600bd412820233598628b85b58f1e9f6da4555421f45266ec2ebf94153d1d',
v: 27,
};
expect(actual).to.deep.eq(expected);
});
});
});