Reverted to version of dydx bridge that only allows from to be the account owner

This commit is contained in:
Greg Hysen
2019-12-12 21:03:02 -08:00
parent 3300aaa1b9
commit 5ca7169ee5
5 changed files with 293 additions and 321 deletions

View File

@@ -20,6 +20,7 @@ pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "../interfaces/IERC20Bridge.sol";
import "../interfaces/IDydxBridge.sol";
import "../interfaces/IDydx.sol";
@@ -31,16 +32,16 @@ contract DydxBridge is
DeploymentConstants
{
using LibSafeMath for uint256;
/// @dev Callback for `IERC20Bridge`. Deposits or withdraws tokens from a dydx account.
/// Notes:
/// 1. This bridge must be set as an operator of the input dydx account.
/// 2. This function may only be called in the context of the 0x Exchange.
/// 3. The maker of the 0x order must be the dydx account owner.
/// 4. To deposit into dydx use this function in the `takerAssetData`.
/// (The `to` address is the 0x order maker and dydx account owner).
/// 5. To withdraw from dydx use this function in the `makerAssetData`.
/// (The `from` address is the 0x order maker and dydx account owner).
/// @param from The sender of the tokens.
/// 3. The maker or taker of the 0x order must be the dydx account owner.
/// 4. Deposits into dydx are made from the `from` address.
/// 5. Withdrawals from dydx are made to the `to` address.
/// @param from The sender of the tokens and owner of the dydx account.
/// @param to The recipient of the tokens.
/// @param amount Minimum amount of `toTokenAddress` tokens to deposit or withdraw.
/// @param encodedBridgeData An abi-encoded `BridgeData` struct.
@@ -64,37 +65,89 @@ contract DydxBridge is
// Decode bridge data.
(BridgeData memory bridgeData) = abi.decode(encodedBridgeData, (BridgeData));
// Cache dydx contract.
IDydx dydx = IDydx(_getDydxAddress());
// The dydx accounts are owned by the `from` address.
IDydx.AccountInfo[] memory accounts = _createAccounts(from, bridgeData);
// Create dydx action.
IDydx.AccountInfo[] memory accounts = new IDydx.AccountInfo[](1);
IDydx.ActionArgs[] memory actions = new IDydx.ActionArgs[](1);
if (bridgeData.action == BridgeAction.Deposit) {
// We interpret `to` as the 0x order maker and `from` as the taker.
accounts[0] = IDydx.AccountInfo({
owner: to,
number: bridgeData.accountNumber
});
// Deposit tokens from the `to` address into their dydx account.
actions[0] = _createDepositAction(
// Create dydx actions to run on the dydx accounts.
IDydx.ActionArgs[] memory actions = _createActions(
from,
to,
amount,
bridgeData
);
} else if (bridgeData.action == BridgeAction.Withdraw) {
// We interpret `from` as the 0x order maker and `to` as the taker.
accounts[0] = IDydx.AccountInfo({
owner: from,
number: bridgeData.accountNumber
});
// Withdraw tokens from dydx account owned by `from` into the `to` address.
actions[0] = _createWithdrawAction(
to,
amount,
bridgeData
// Run operation. This will revert on failure.
IDydx(_getDydxAddress()).operate(accounts, actions);
return BRIDGE_SUCCESS;
}
/// @dev Creates an array of accounts for dydx to operate on.
/// All accounts must belong to the same owner.
/// @param accountOwner Owner of the dydx account.
/// @param bridgeData A `BridgeData` struct.
function _createAccounts(
address accountOwner,
BridgeData memory bridgeData
)
internal
returns (IDydx.AccountInfo[] memory accounts)
{
uint256[] memory accountNumbers = bridgeData.accountNumbers;
uint256 nAccounts = accountNumbers.length;
accounts = new IDydx.AccountInfo[](nAccounts);
for (uint256 i = 0; i < nAccounts; ++i) {
accounts[i] = IDydx.AccountInfo({
owner: accountOwner,
number: accountNumbers[i]
});
}
}
/// @dev Creates an array of actions to carry out on dydx.
/// @param depositFrom Deposit value from this address (owner of the dydx account).
/// @param withdrawTo Withdraw value to this address.
/// @param amount The amount of value available to operate on.
/// @param bridgeData A `BridgeData` struct.
function _createActions(
address depositFrom,
address withdrawTo,
uint256 amount,
BridgeData memory bridgeData
)
internal
returns (IDydx.ActionArgs[] memory actions)
{
BridgeAction[] memory bridgeActions = bridgeData.actions;
uint256 nBridgeActions = bridgeActions.length;
actions = new IDydx.ActionArgs[](nBridgeActions);
for (uint256 i = 0; i < nBridgeActions; ++i) {
// Cache current bridge action.
BridgeAction memory bridgeAction = bridgeActions[i];
// Scale amount, if conversion rate is set.
uint256 scaledAmount;
if (bridgeAction.conversionRateDenominator > 0) {
scaledAmount = amount
.safeMul(bridgeAction.conversionRateNumerator)
.safeDiv(bridgeAction.conversionRateDenominator);
} else {
scaledAmount = amount;
}
// Construct dydx action.
if (bridgeAction.actionType == BridgeActionType.Deposit) {
// Deposit tokens from the account owner into their dydx account.
actions[i] = _createDepositAction(
depositFrom,
scaledAmount,
bridgeAction
);
} else if (bridgeAction.actionType == BridgeActionType.Withdraw) {
// Withdraw tokens from dydx to the `otherAccount`.
actions[i] = _createWithdrawAction(
withdrawTo,
scaledAmount,
bridgeAction
);
} else {
// If all values in the `Action` enum are handled then this
@@ -102,21 +155,18 @@ contract DydxBridge is
// from `uint8` to `Action`.
revert("DydxBridge/UNRECOGNIZED_BRIDGE_ACTION");
}
// Run operation. This will revert on failure.
dydx.operate(accounts, actions);
return BRIDGE_SUCCESS;
}
}
/// @dev Returns a dydx `DepositAction`.
/// @param depositFrom Deposit tokens from this address who is also the account owner.
/// @param amount of tokens to deposit.
/// @param bridgeData A `BridgeData` struct.
/// @param bridgeAction A `BridgeAction` struct.
/// @return depositAction The encoded dydx action.
function _createDepositAction(
address depositFrom,
uint256 amount,
BridgeData memory bridgeData
BridgeAction memory bridgeAction
)
internal
pure
@@ -136,8 +186,8 @@ contract DydxBridge is
depositAction = IDydx.ActionArgs({
actionType: IDydx.ActionType.Deposit, // deposit tokens.
amount: dydxAmount, // amount to deposit.
accountId: 0, // index in the `accounts` when calling `operate`.
primaryMarketId: bridgeData.marketId, // indicates which token to deposit.
accountId: bridgeAction.accountId, // index in the `accounts` when calling `operate`.
primaryMarketId: bridgeAction.marketId, // indicates which token to deposit.
otherAddress: depositFrom, // deposit from the account owner.
// unused parameters
secondaryMarketId: 0,
@@ -149,12 +199,12 @@ contract DydxBridge is
/// @dev Returns a dydx `WithdrawAction`.
/// @param withdrawTo Withdraw tokens to this address.
/// @param amount of tokens to withdraw.
/// @param bridgeData A `BridgeData` struct.
/// @param bridgeAction A `BridgeAction` struct.
/// @return withdrawAction The encoded dydx action.
function _createWithdrawAction(
address withdrawTo,
uint256 amount,
BridgeData memory bridgeData
BridgeAction memory bridgeAction
)
internal
pure
@@ -174,8 +224,8 @@ contract DydxBridge is
withdrawAction = IDydx.ActionArgs({
actionType: IDydx.ActionType.Withdraw, // withdraw tokens.
amount: amountToWithdraw, // amount to withdraw.
accountId: 0, // index in the `accounts` when calling `operate`.
primaryMarketId: bridgeData.marketId, // indicates which token to withdraw.
accountId: bridgeAction.accountId, // index in the `accounts` when calling `operate`.
primaryMarketId: bridgeAction.marketId, // indicates which token to withdraw.
otherAddress: withdrawTo, // withdraw tokens to this address.
// unused parameters
secondaryMarketId: 0,

View File

@@ -21,14 +21,22 @@ pragma solidity ^0.5.9;
interface IDydxBridge {
enum BridgeAction {
/// @dev This is the subset of `IDydx.ActionType` that are supported by the bridge.
enum BridgeActionType {
Deposit, // Deposit tokens into dydx account.
Withdraw // Withdraw tokens from dydx account.
}
struct BridgeData {
BridgeAction action; // Action to run on dydx account.
uint256 accountNumber; // Account number used to identify the owner's specific account.
struct BridgeAction {
BridgeActionType actionType; // Action to run on dydx account.
uint256 accountId; // Index in `BridgeData.accountNumbers` for this action.
uint256 marketId; // Market to operate on.
uint256 conversionRateNumerator; // Optional. If set, transfer amount is scaled by (conversionRateNumerator/conversionRateDenominator).
uint256 conversionRateDenominator; // Optional. If set, transfer amount is scaled by (conversionRateNumerator/conversionRateDenominator).
}
struct BridgeData {
uint256[] accountNumbers; // Account number used to identify the owner's specific account.
BridgeAction[] actions; // Actions to carry out on the owner's accounts.
}
}

View File

@@ -5,6 +5,7 @@ export {
ERC20ProxyContract,
ERC721ProxyContract,
Eth2DaiBridgeContract,
DydxBridgeContract,
IAssetDataContract,
IAssetProxyContract,
MultiAssetProxyContract,

View File

@@ -7,8 +7,9 @@ import { artifacts } from './artifacts';
import { TestDydxBridgeContract, TestDydxBridgeEvents } from './wrappers';
blockchainTests.resets('DydxBridge unit tests', env => {
const accountNumber = new BigNumber(1);
const defaultAccountNumber = new BigNumber(1);
const marketId = new BigNumber(2);
const defaultAmount = new BigNumber(4);
const notAuthorized = '0x0000000000000000000000000000000000000001';
let testContract: TestDydxBridgeContract;
let authorized: string;
@@ -30,147 +31,214 @@ blockchainTests.resets('DydxBridge unit tests', env => {
});
describe('bridgeTransferFrom()', () => {
interface BridgeData {
action: number;
accountNumber: BigNumber;
marketId: BigNumber;
}
enum DydxBridgeActions {
enum BridgeActionType {
Deposit,
Withdraw,
}
let defaultBridgeData: any;
let bridgeDataEncoder: AbiEncoder.DataType;
interface BrigeAction {
actionType: BridgeActionType;
accountId: BigNumber;
marketId: BigNumber;
conversionRateNumerator: BigNumber;
conversionRateDenominator: BigNumber;
}
interface BridgeData {
accountNumbers: BigNumber[];
actions: BrigeAction[];
}
const defaultDepositAction = {
actionType: BridgeActionType.Deposit as number,
accountId: constants.ZERO_AMOUNT,
marketId,
conversionRateNumerator: constants.ZERO_AMOUNT,
conversionRateDenominator: constants.ZERO_AMOUNT,
};
const defaultWithdrawAction = {
actionType: BridgeActionType.Withdraw as number,
accountId: constants.ZERO_AMOUNT,
marketId,
conversionRateNumerator: constants.ZERO_AMOUNT,
conversionRateDenominator: constants.ZERO_AMOUNT,
};
const bridgeDataEncoder = AbiEncoder.create([
{
name: 'bridgeData',
type: 'tuple',
components: [
{ name: 'accountNumbers', type: 'uint256[]' },
{
name: 'actions',
type: 'tuple[]',
components: [
{ name: 'actionType', type: 'uint8' },
{ name: 'accountId', type: 'uint256' },
{ name: 'marketId', type: 'uint256' },
{ name: 'conversionRateNumerator', type: 'uint256' },
{ name: 'conversionRateDenominator', type: 'uint256' },
],
},
],
},
]);
const callBridgeTransferFrom = async (
from: string,
to: string,
amount: BigNumber,
bridgeData: BridgeData,
sender: string,
): Promise<string> => {
const returnValue = await testContract
.bridgeTransferFrom(
constants.NULL_ADDRESS,
from,
to,
new BigNumber(1),
bridgeDataEncoder.encode(bridgeData),
)
.bridgeTransferFrom(constants.NULL_ADDRESS, from, to, amount, bridgeDataEncoder.encode({ bridgeData }))
.callAsync({ from: sender });
return returnValue;
};
const callBridgeTransferFromAndVerifyEvents = async (
actionType: number,
actionAddress: string,
from: string,
to: string,
amount: BigNumber,
bridgeData: BridgeData,
sender: string,
): Promise<void> => {
// Execute transaction.
const txReceipt = await testContract
.bridgeTransferFrom(
constants.NULL_ADDRESS,
from,
to,
new BigNumber(1),
bridgeDataEncoder.encode(bridgeData),
)
.bridgeTransferFrom(constants.NULL_ADDRESS, from, to, amount, bridgeDataEncoder.encode({ bridgeData }))
.awaitTransactionSuccessAsync({ from: sender });
// Verify `OperateAccount` event.
verifyEventsFromLogs(
txReceipt.logs,
[
{
const expectedOperateAccountEvents = [];
for (const accountNumber of bridgeData.accountNumbers) {
expectedOperateAccountEvents.push({
owner: accountOwner,
number: accountNumber,
},
],
TestDydxBridgeEvents.OperateAccount,
);
});
}
verifyEventsFromLogs(txReceipt.logs, expectedOperateAccountEvents, TestDydxBridgeEvents.OperateAccount);
// Verify `OperateAction` event.
const accountId = new BigNumber(0);
const positiveAmountSign = true;
const weiDenomination = 0;
const absoluteAmountRef = 1;
verifyEventsFromLogs(
txReceipt.logs,
[
{
actionType,
accountId,
const expectedOperateActionEvents = [];
for (const action of bridgeData.actions) {
expectedOperateActionEvents.push({
actionType: action.actionType as number,
accountId: action.accountId,
amountSign: positiveAmountSign,
amountDenomination: weiDenomination,
amountRef: absoluteAmountRef,
amountValue: new BigNumber(1),
amountValue: action.conversionRateDenominator.gt(0)
? amount.times(action.conversionRateNumerator).div(action.conversionRateDenominator)
: amount,
primaryMarketId: marketId,
secondaryMarketId: constants.ZERO_AMOUNT,
otherAddress: actionAddress,
otherAddress: action.actionType === BridgeActionType.Deposit ? from : to,
otherAccountId: constants.ZERO_AMOUNT,
data: '0x',
});
}
verifyEventsFromLogs(txReceipt.logs, expectedOperateActionEvents, TestDydxBridgeEvents.OperateAction);
};
it('succeeds when calling `operate` with the `deposit` action and a single account', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultDepositAction],
};
await callBridgeTransferFromAndVerifyEvents(accountOwner, receiver, defaultAmount, bridgeData, authorized);
});
it('succeeds when calling `operate` with the `deposit` action and multiple accounts', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber, defaultAccountNumber.plus(1)],
actions: [defaultDepositAction],
};
await callBridgeTransferFromAndVerifyEvents(accountOwner, receiver, defaultAmount, bridgeData, authorized);
});
it('succeeds when calling `operate` with the `withdraw` action and a single accuont', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultWithdrawAction],
};
await callBridgeTransferFromAndVerifyEvents(accountOwner, receiver, defaultAmount, bridgeData, authorized);
});
it('succeeds when calling `operate` with the `withdraw` action and multiple accounts', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber, defaultAccountNumber.plus(1)],
actions: [defaultWithdrawAction],
};
await callBridgeTransferFromAndVerifyEvents(accountOwner, receiver, defaultAmount, bridgeData, authorized);
});
it('succeeds when calling `operate` with the `deposit` action and multiple accounts', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber, defaultAccountNumber.plus(1)],
actions: [defaultWithdrawAction, defaultDepositAction],
};
await callBridgeTransferFromAndVerifyEvents(accountOwner, receiver, defaultAmount, bridgeData, authorized);
});
it('succeeds when calling `operate` with multiple actions under a single account', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultWithdrawAction, defaultDepositAction],
};
await callBridgeTransferFromAndVerifyEvents(accountOwner, receiver, defaultAmount, bridgeData, authorized);
});
it('succeeds when scaling the `amount` to deposit', async () => {
const conversionRateNumerator = new BigNumber(1);
const conversionRateDenominator = new BigNumber(2);
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [
defaultWithdrawAction,
{
...defaultDepositAction,
conversionRateNumerator,
conversionRateDenominator,
},
],
TestDydxBridgeEvents.OperateAction,
);
};
before(async () => {
// Construct default bridge data
defaultBridgeData = {
action: DydxBridgeActions.Deposit as number,
accountNumber,
marketId,
};
// Create encoder for bridge data
bridgeDataEncoder = AbiEncoder.create([
{ name: 'action', type: 'uint8' },
{ name: 'accountNumber', type: 'uint256' },
{ name: 'marketId', type: 'uint256' },
]);
await callBridgeTransferFromAndVerifyEvents(accountOwner, receiver, defaultAmount, bridgeData, authorized);
});
it('succeeds when calling `operate` with the `deposit` action', async () => {
const depositAction = 0;
it('succeeds when scaling the `amount` to withdraw', async () => {
const conversionRateNumerator = new BigNumber(1);
const conversionRateDenominator = new BigNumber(2);
const bridgeData = {
...defaultBridgeData,
action: depositAction,
accountNumbers: [defaultAccountNumber],
actions: [
defaultDepositAction,
{
...defaultWithdrawAction,
conversionRateNumerator,
conversionRateDenominator,
},
],
};
await callBridgeTransferFromAndVerifyEvents(
depositAction,
accountOwner,
receiver,
accountOwner,
bridgeData,
authorized,
);
});
it('succeeds when calling `operate` with the `withdraw` action', async () => {
const withdrawAction = 1;
const bridgeData = {
...defaultBridgeData,
action: withdrawAction,
};
await callBridgeTransferFromAndVerifyEvents(
withdrawAction,
receiver,
accountOwner,
receiver,
bridgeData,
authorized,
);
await callBridgeTransferFromAndVerifyEvents(accountOwner, receiver, defaultAmount, bridgeData, authorized);
});
it('reverts if not called by the ERC20 Bridge Proxy', async () => {
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultDepositAction],
};
const callBridgeTransferFromPromise = callBridgeTransferFrom(
accountOwner,
receiver,
defaultBridgeData,
defaultAmount,
bridgeData,
notAuthorized,
);
const expectedError = RevertReason.DydxBridgeOnlyCallableByErc20BridgeProxy;
return expect(callBridgeTransferFromPromise).to.revertWith(expectedError);
});
it('should return magic bytes if call succeeds', async () => {
const returnValue = await callBridgeTransferFrom(accountOwner, receiver, defaultBridgeData, authorized);
const bridgeData = {
accountNumbers: [defaultAccountNumber],
actions: [defaultDepositAction],
};
const returnValue = await callBridgeTransferFrom(
accountOwner,
receiver,
defaultAmount,
bridgeData,
authorized,
);
expect(returnValue).to.equal(AssetProxyId.ERC20Bridge);
});
});

185
yarn.lock
View File

@@ -678,7 +678,7 @@
lodash "^4.17.11"
valid-url "^1.0.9"
"@0x/base-contract@^5.5.0-beta.3", "@0x/base-contract@^5.5.0-beta.4":
"@0x/base-contract@^5.5.0-beta.3":
version "5.5.0-beta.4"
resolved "https://registry.yarnpkg.com/@0x/base-contract/-/base-contract-5.5.0-beta.4.tgz#eb26473e033e1a305a9fa87ab9e26325c9face59"
dependencies:
@@ -694,79 +694,26 @@
js-sha3 "^0.7.0"
uuid "^3.3.2"
"@0x/contract-addresses@3.3.0-beta.4":
version "3.3.0-beta.4"
resolved "https://registry.yarnpkg.com/@0x/contract-addresses/-/contract-addresses-3.3.0-beta.4.tgz#eec4492702b2e707bcace6ac274f9826761e08a4"
dependencies:
lodash "^4.17.11"
"@0x/contract-addresses@^3.3.0-beta.4", "@0x/contract-addresses@^3.3.0-beta.5":
"@0x/contract-addresses@^3.3.0-beta.4":
version "3.3.0-beta.5"
resolved "https://registry.yarnpkg.com/@0x/contract-addresses/-/contract-addresses-3.3.0-beta.5.tgz#9d5f80a258f1d103b127159c237f9bcdad182e80"
dependencies:
lodash "^4.17.11"
"@0x/contract-artifacts@^2.3.0-beta.3":
version "2.3.0-beta.4"
resolved "https://registry.yarnpkg.com/@0x/contract-artifacts/-/contract-artifacts-2.3.0-beta.4.tgz#ca056885be387344aaccf5c69fe80aec248df37d"
"@0x/contract-wrappers@12.2.0-beta.3":
version "12.2.0-beta.3"
resolved "https://registry.yarnpkg.com/@0x/contract-wrappers/-/contract-wrappers-12.2.0-beta.3.tgz#e85a7e42170e98244ab57a1089f8831cf10e3f2d"
"@0x/coordinator-server@^1.0.5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@0x/coordinator-server/-/coordinator-server-1.0.5.tgz#3fda0d5f2af45f0baa7663ad0a5e8465b4161081"
integrity sha512-tR9OHa5QPejezSfjO++CorNF72jTKROGxqjSJ+7/Yk3w/RJFItUcAEJKgSQLMJpjJPKG7vbLkl53lzd9xuN+yw==
dependencies:
"@0x/abi-gen-wrappers" "^5.4.0-beta.3"
"@0x/base-contract" "^5.5.0-beta.3"
"@0x/contract-addresses" "^3.3.0-beta.4"
"@0x/contract-artifacts" "^2.3.0-beta.3"
"@0x/order-utils" "^8.5.0-beta.3"
ethers "~4.0.4"
http-status-codes "^1.3.2"
"@0x/contract-wrappers@^12.2.0-beta.4":
version "12.2.0-beta.4"
resolved "https://registry.npmjs.org/@0x/contract-wrappers/-/contract-wrappers-12.2.0-beta.4.tgz#7a7301dd50c28887879df4d385e80a49e040748d"
integrity sha512-JVoYG3Rd430fZw9ogBSqeLOaJXkqp9N7g614X5/bzzuG/dSDdwXl48X02m66aGFWcNofx/iMsT4tpOZrJ2bDBg==
dependencies:
"@0x/assert" "^2.2.0-beta.3"
"@0x/base-contract" "^5.5.0-beta.4"
"@0x/contract-addresses" "^3.3.0-beta.5"
"@0x/json-schemas" "^4.1.0-beta.3"
"@0x/types" "^2.5.0-beta.3"
"@0x/utils" "^4.6.0-beta.3"
"@0x/web3-wrapper" "^6.1.0-beta.3"
ethereum-types "^2.2.0-beta.2"
ethers "~4.0.4"
"@0x/contracts-dev-utils@^0.1.0-beta.3":
version "0.1.0-beta.4"
resolved "https://registry.yarnpkg.com/@0x/contracts-dev-utils/-/contracts-dev-utils-0.1.0-beta.4.tgz#87f51a7ed778b619beb8b32bf08ea6b3e4495d4e"
dependencies:
"@0x/base-contract" "^5.5.0-beta.4"
"@0x/contracts-erc20@2.3.0-beta.3":
version "2.3.0-beta.3"
resolved "https://registry.yarnpkg.com/@0x/contracts-erc20/-/contracts-erc20-2.3.0-beta.3.tgz#744f911d340576a27253b5961d52b09bb8659a98"
dependencies:
"@0x/base-contract" "^5.5.0-beta.3"
"@0x/types" "^2.5.0-beta.2"
"@0x/typescript-typings" "^4.4.0-beta.2"
ethereum-types "^2.2.0-beta.2"
"@0x/coordinator-server@^1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@0x/coordinator-server/-/coordinator-server-1.0.4.tgz#9729ce789fb772a5ae0a8dcdf5928de9e80ac1af"
dependencies:
"@0x/assert" "2.2.0-beta.2"
"@0x/contract-addresses" "3.3.0-beta.4"
"@0x/contract-wrappers" "12.2.0-beta.3"
"@0x/contracts-erc20" "2.3.0-beta.3"
"@0x/json-schemas" "4.1.0-beta.2"
"@0x/order-utils" "8.5.0-beta.3"
"@0x/subproviders" "5.1.0-beta.2"
"@0x/types" "2.5.0-beta.2"
"@0x/typescript-typings" "4.4.0-beta.2"
"@0x/utils" "4.6.0-beta.2"
"@0x/web3-wrapper" "6.1.0-beta.2"
"@0x/assert" "^3.0.1"
"@0x/contract-addresses" "^4.0.0"
"@0x/contract-wrappers" "^13.1.0"
"@0x/json-schemas" "^5.0.1"
"@0x/order-utils" "^10.0.0"
"@0x/subproviders" "^6.0.1"
"@0x/types" "^3.1.0"
"@0x/typescript-typings" "^5.0.0"
"@0x/utils" "^5.1.0"
"@babel/polyfill" "^7.0.0"
body-parser "^1.18.3"
cors "^2.8.5"
@@ -781,15 +728,6 @@
typeorm "0.2.7"
websocket "^1.0.25"
"@0x/json-schemas@4.1.0-beta.2":
version "4.1.0-beta.2"
resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-4.1.0-beta.2.tgz#79d05d0c91525e2356f783dae5e572dd3624969f"
dependencies:
"@0x/typescript-typings" "^4.4.0-beta.2"
"@types/node" "*"
jsonschema "^1.2.0"
lodash.values "^4.3.0"
"@0x/json-schemas@^4.1.0-beta.2", "@0x/json-schemas@^4.1.0-beta.3":
version "4.1.0-beta.3"
resolved "https://registry.npmjs.org/@0x/json-schemas/-/json-schemas-4.1.0-beta.3.tgz#af70a35691108ea162140640bae93a7fc84ca6ee"
@@ -813,68 +751,6 @@
uuid "^3.3.2"
websocket "^1.0.29"
"@0x/order-utils@8.5.0-beta.3":
version "8.5.0-beta.3"
resolved "https://registry.yarnpkg.com/@0x/order-utils/-/order-utils-8.5.0-beta.3.tgz#67bc733cf64cb7cc5653a913e986c5f211b1b7d2"
dependencies:
"@0x/abi-gen-wrappers" "^5.4.0-beta.3"
"@0x/assert" "^2.2.0-beta.2"
"@0x/contract-addresses" "^3.3.0-beta.4"
"@0x/contract-artifacts" "^2.3.0-beta.3"
"@0x/contracts-dev-utils" "^0.1.0-beta.3"
"@0x/json-schemas" "^4.1.0-beta.2"
"@0x/types" "^2.5.0-beta.2"
"@0x/typescript-typings" "^4.4.0-beta.2"
"@0x/utils" "^4.6.0-beta.2"
"@0x/web3-wrapper" "^6.1.0-beta.2"
"@types/node" "*"
bn.js "^4.11.8"
ethereum-types "^2.2.0-beta.2"
ethereumjs-abi "0.6.5"
ethereumjs-util "^5.1.1"
ethers "~4.0.4"
lodash "^4.17.11"
"@0x/order-utils@^8.5.0-beta.3":
version "8.5.0-beta.4"
resolved "https://registry.yarnpkg.com/@0x/order-utils/-/order-utils-8.5.0-beta.4.tgz#900387631008cc9dc9ece125d28450d2beaea462"
dependencies:
"@0x/assert" "^2.2.0-beta.3"
"@0x/contract-wrappers" "^12.2.0-beta.4"
"@0x/json-schemas" "^4.1.0-beta.3"
"@0x/utils" "^4.6.0-beta.3"
"@0x/web3-wrapper" "^6.1.0-beta.3"
ethereumjs-util "^5.1.1"
ethers "~4.0.4"
lodash "^4.17.11"
"@0x/subproviders@5.1.0-beta.2":
version "5.1.0-beta.2"
resolved "https://registry.yarnpkg.com/@0x/subproviders/-/subproviders-5.1.0-beta.2.tgz#020369711330755448397b3b8cecf2868ae7c54c"
dependencies:
"@0x/assert" "^2.2.0-beta.2"
"@0x/types" "^2.5.0-beta.2"
"@0x/typescript-typings" "^4.4.0-beta.2"
"@0x/utils" "^4.6.0-beta.2"
"@0x/web3-wrapper" "^6.1.0-beta.2"
"@ledgerhq/hw-app-eth" "^4.3.0"
"@ledgerhq/hw-transport-u2f" "4.24.0"
"@types/hdkey" "^0.7.0"
"@types/web3-provider-engine" "^14.0.0"
bip39 "^2.5.0"
bn.js "^4.11.8"
ethereum-types "^2.2.0-beta.2"
ethereumjs-tx "^1.3.5"
ethereumjs-util "^5.1.1"
ganache-core "^2.6.0"
hdkey "^0.7.1"
json-rpc-error "2.0.0"
lodash "^4.17.11"
semaphore-async-await "^1.5.1"
web3-provider-engine "14.0.6"
optionalDependencies:
"@ledgerhq/hw-transport-node-hid" "^4.3.0"
"@0x/ts-doc-gen@^0.0.22":
version "0.0.22"
resolved "https://registry.yarnpkg.com/@0x/ts-doc-gen/-/ts-doc-gen-0.0.22.tgz#c9c215899695dcd4320a1711291be40050ddbc0e"
@@ -934,24 +810,6 @@
ethereum-types "^2.1.6"
popper.js "1.14.3"
"@0x/utils@4.6.0-beta.2":
version "4.6.0-beta.2"
resolved "https://registry.yarnpkg.com/@0x/utils/-/utils-4.6.0-beta.2.tgz#ffa70f05736a74ac8d7ca5debe01bff7e6d8f073"
dependencies:
"@0x/types" "^2.5.0-beta.2"
"@0x/typescript-typings" "^4.4.0-beta.2"
"@types/node" "*"
abortcontroller-polyfill "^1.1.9"
bignumber.js "~9.0.0"
chalk "^2.3.0"
detect-node "2.0.3"
ethereum-types "^2.2.0-beta.2"
ethereumjs-util "^5.1.1"
ethers "~4.0.4"
isomorphic-fetch "2.2.1"
js-sha3 "^0.7.0"
lodash "^4.17.11"
"@0x/utils@^4.3.3":
version "4.5.2"
resolved "https://registry.npmjs.org/@0x/utils/-/utils-4.5.2.tgz#6cc89f2d0dda341e0fb4e76049a35abfb67a4ac5"
@@ -1005,19 +863,6 @@
websocket "^1.0.28"
xhr2-cookies "1.1.0"
"@0x/web3-wrapper@6.1.0-beta.2":
version "6.1.0-beta.2"
resolved "https://registry.yarnpkg.com/@0x/web3-wrapper/-/web3-wrapper-6.1.0-beta.2.tgz#24aae8a0063057ebb6d3a7893a01d0abac8cd19c"
dependencies:
"@0x/assert" "^2.2.0-beta.2"
"@0x/json-schemas" "^4.1.0-beta.2"
"@0x/typescript-typings" "^4.4.0-beta.2"
"@0x/utils" "^4.6.0-beta.2"
ethereum-types "^2.2.0-beta.2"
ethereumjs-util "^5.1.1"
ethers "~4.0.4"
lodash "^4.17.11"
"@0x/web3-wrapper@^6.1.0-beta.2", "@0x/web3-wrapper@^6.1.0-beta.3":
version "6.1.0-beta.3"
resolved "https://registry.npmjs.org/@0x/web3-wrapper/-/web3-wrapper-6.1.0-beta.3.tgz#82161147e9283391e0c7cd6027c971749c5a2f77"