Compare commits

...

22 Commits

Author SHA1 Message Date
Jacob Evans
5754c11e34 Publish
- @0x/contracts-asset-proxy@3.2.0
 - @0x/contracts-broker@1.0.2
 - @0x/contracts-coordinator@3.1.0
 - @0x/contracts-dev-utils@1.1.0
 - @0x/contracts-erc1155@2.1.0
 - @0x/contracts-erc20-bridge-sampler@1.3.0
 - @0x/contracts-erc20@3.1.0
 - @0x/contracts-erc721@3.1.0
 - @0x/contracts-exchange-forwarder@4.2.0
 - @0x/contracts-exchange-libs@4.3.0
 - @0x/contracts-exchange@3.2.0
 - @0x/contracts-extensions@6.1.0
 - @0x/contracts-integrations@2.3.0
 - @0x/contracts-multisig@4.1.0
 - @0x/contracts-staking@2.0.7
 - @0x/contracts-test-utils@5.1.4
 - @0x/contracts-utils@4.3.0
 - 0x.js@9.1.0
 - @0x/abi-gen@5.2.0
 - @0x/assert@3.0.6
 - @0x/asset-swapper@4.1.2
 - @0x/base-contract@6.2.0
 - @0x/connect@6.0.6
 - @0x/contract-addresses@4.5.0
 - @0x/contract-artifacts@3.5.0
 - @0x/contract-wrappers-test@12.2.8
 - @0x/contract-wrappers@13.5.0
 - @0x/contracts-gen@2.0.7
 - @0x/dev-utils@3.2.0
 - ethereum-types@3.1.0
 - @0x/instant@1.0.45
 - @0x/json-schemas@5.0.6
 - @0x/migrations@6.1.0
 - @0x/monorepo-scripts@1.0.50
 - @0x/order-utils@10.2.0
 - @0x/orderbook@2.2.0
 - @0x/sol-compiler@4.0.7
 - @0x/sol-coverage@4.0.7
 - @0x/sol-doc@3.1.4
 - @0x/sol-profiler@4.0.7
 - @0x/sol-resolver@3.0.3
 - @0x/sol-trace@3.0.7
 - @0x/sol-tracing-utils@7.0.7
 - @0x/sra-spec@3.0.6
 - @0x/subproviders@6.0.7
 - @0x/types@3.1.2
 - @0x/typescript-typings@5.0.2
 - @0x/utils@5.4.0
 - @0x/web3-wrapper@7.0.6
2020-02-09 09:37:34 +10:00
Jacob Evans
7bd88c1bb8 Updated CHANGELOGS & MD docs 2020-02-09 09:37:04 +10:00
Lawrence Forman
445b686c6c Merge pull request #2463 from 0xProject/feat/abi-gen/library-linking
Support contracts with unlinked libraries
2020-02-08 00:23:57 -05:00
Lawrence Forman
0cb7b75214 Merge pull request #2464 from 0xProject/feat/contracts/dev-utils/public-libraries-refactor
DevUtils refactor into public libraries
2020-02-07 23:53:16 -05:00
Lawrence Forman
a08399dfee regenerate artifacts and wrappers 2020-02-07 23:23:23 -05:00
Lawrence Forman
4016808fa4 Cherry pick DevUtils refactor code from #2456 2020-02-07 23:23:23 -05:00
Lawrence Forman
8635849977 Address review comments and regenerate contract-wrappers 2020-02-07 23:22:58 -05:00
Lawrence Forman
1a9ed4d4fe Add es2018.promises tsconfig lib target. 2020-02-07 23:22:58 -05:00
Lawrence Forman
e7b3246dd0 Cherry pick library linking code from #2456 2020-02-07 23:22:58 -05:00
Lawrence Forman
19589aec57 Cherry-pick changes from feat/dev-utils/dydx-bridge-validation 2020-02-07 23:22:58 -05:00
Lawrence Forman
4d33ff0417 Cherry-pick changes from feat/dev-utils/dydx-bridge-validation 2020-02-07 23:22:58 -05:00
Lawrence Forman
93a5ab5b33 Merge pull request #2462 from 0xProject/fix-and-feat/restore-contract-tests-and-refactors
Fix contracts tests + refactors
2020-02-07 23:16:50 -05:00
Lawrence Forman
59ada06cdf Fix linter errors. 2020-02-07 22:39:56 -05:00
Lawrence Forman
ae650849b0 Rebase and address review comments. 2020-02-07 22:29:32 -05:00
Lawrence Forman
3e8f9a6b53 Cherry-pick changes from feat/dev-utils/dydx-bridge-validation 2020-02-07 22:10:10 -05:00
Lawrence Forman
79362b0dba Merge pull request #2476 from 0xProject/fix/erc20-bridge-sampler/dev-utils-gas-stipend
ERC20BridgeSampler: Catch DevUtils reverts
2020-02-07 10:08:40 -05:00
Lawrence Forman
3e3df06d57 @0x/contracts-erc20-bridge-sampler: Fix catching invalid opcode from DevUtils
`@0x/contract-addresses`: Update `ERC20BridgeSampler` mainnet and kovan addresses.
2020-02-07 03:07:33 -05:00
Lawrence Forman
6b220eb1c5 Merge pull request #2474 from 0xProject/feat/eth2dai-bridge/market-migration
Update Eth2Dai address
2020-02-07 02:42:29 -05:00
Lawrence Forman
a1c61cae11 @0x/contract-addresses: Redeploy ERC20BridgeSampler 2020-02-07 02:10:19 -05:00
Jacob Evans
d48a917bf3 [erc20-bridge-sampler] gas stipend for DevUtils 2020-02-07 16:57:11 +10:00
Lawrence Forman
646b6dafb2 @0x/contract-addresses Redeploy Eth2DaiBridge and ERC20BridgeSampler. 2020-02-07 01:56:59 -05:00
Lawrence Forman
8d10f33a3f @0x/contracts-utils: Update Eth2Dai address. 2020-02-07 01:56:59 -05:00
281 changed files with 7462 additions and 5114 deletions

View File

@@ -47,7 +47,7 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-extensions @0x/contracts-asset-proxy @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-coordinator @0x/contracts-tests @0x/contracts-staking
- run: yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-extensions @0x/contracts-asset-proxy @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-coordinator @0x/contracts-staking
test-exchange-ganache-3.0:
resource_class: medium+
docker:
@@ -77,7 +77,7 @@ jobs:
- restore_cache:
keys:
- repo-{{ .Environment.CIRCLE_SHA1 }}
- run: yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-asset-proxy @0x/contracts-exchange-forwarder @0x/contracts-tests @0x/contracts-staking @0x/contracts-coordinator @0x/contracts-erc20-bridge-sampler
- run: yarn wsrun test:circleci @0x/contracts-multisig @0x/contracts-utils @0x/contracts-exchange-libs @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-asset-proxy @0x/contracts-exchange-forwarder @0x/contracts-staking @0x/contracts-coordinator @0x/contracts-erc20-bridge-sampler
# TODO(dorothy-zbornak): Re-enable after updating this package for
# 3.0. At that time, also remove exclusion from monorepo
# package.json's test script.

View File

@@ -1,4 +1,22 @@
[
{
"version": "3.2.0",
"changes": [
{
"note": "Fix broken tests.",
"pr": 2462
},
{
"note": "Remove dependency on `@0x/contracts-dev-utils`",
"pr": 2462
},
{
"note": "Add asset data decoding functions",
"pr": 2462
}
],
"timestamp": 1581204851
},
{
"timestamp": 1580988106,
"version": "3.1.3",

View File

@@ -5,6 +5,12 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.2.0 - _February 8, 2020_
* Fix broken tests. (#2462)
* Remove dependency on `@0x/contracts-dev-utils` (#2462)
* Add asset data decoding functions (#2462)
## v3.1.3 - _February 6, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-asset-proxy",
"version": "3.1.3",
"version": "3.2.0",
"engines": {
"node": ">=6.12"
},
@@ -51,15 +51,14 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/contracts-gen": "^2.0.6",
"@0x/contracts-test-utils": "^5.1.3",
"@0x/contracts-utils": "^4.2.1",
"@0x/dev-utils": "^3.1.3",
"@0x/sol-compiler": "^4.0.6",
"@0x/abi-gen": "^5.2.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/contracts-utils": "^4.3.0",
"@0x/dev-utils": "^3.2.0",
"@0x/sol-compiler": "^4.0.7",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.1",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -79,17 +78,17 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.1.2",
"@0x/contracts-dev-utils": "^1.0.6",
"@0x/contracts-erc1155": "^2.0.6",
"@0x/contracts-erc20": "^3.0.6",
"@0x/contracts-erc721": "^3.0.6",
"@0x/contracts-exchange-libs": "^4.2.0",
"@0x/order-utils": "^10.1.3",
"@0x/typescript-typings": "^5.0.1",
"@0x/utils": "^5.3.0",
"@0x/web3-wrapper": "^7.0.5",
"ethereum-types": "^3.0.0",
"@0x/base-contract": "^6.2.0",
"@0x/contracts-erc1155": "^2.1.0",
"@0x/contracts-erc20": "^3.1.0",
"@0x/contracts-erc721": "^3.1.0",
"@0x/contracts-exchange-libs": "^4.3.0",
"@0x/order-utils": "^10.2.0",
"@0x/types": "^3.1.2",
"@0x/typescript-typings": "^5.0.2",
"@0x/utils": "^5.4.0",
"@0x/web3-wrapper": "^7.0.6",
"ethereum-types": "^3.1.0",
"lodash": "^4.17.11"
},
"publishConfig": {

View File

@@ -0,0 +1,112 @@
import { AssetProxyId } from '@0x/types';
import { BigNumber, hexUtils } from '@0x/utils';
import { IAssetDataContract } from './wrappers';
const assetDataIface = new IAssetDataContract('0x0000000000000000000000000000000000000000', { isEIP1193: true } as any);
/**
* Get the proxy ID from encoded asset data.
*/
export function getAssetDataProxyId(encoded: string): AssetProxyId {
// tslint:disable-next-line: no-unnecessary-type-assertion
return hexUtils.slice(encoded, 0, 4) as AssetProxyId;
}
/**
* Decode ERC20 asset data.
*/
export function decodeERC20AssetData(encoded: string): string {
return assetDataIface.getABIDecodedTransactionData<string>('ERC20Token', encoded);
}
/**
* Decode ERC721 asset data.
*/
export function decodeERC721AssetData(encoded: string): [string, BigNumber] {
return assetDataIface.getABIDecodedTransactionData<[string, BigNumber]>('ERC721Token', encoded);
}
/**
* Decode ERC1155 asset data.
*/
export function decodeERC1155AssetData(encoded: string): [string, BigNumber[], BigNumber[], string] {
return assetDataIface.getABIDecodedTransactionData<[string, BigNumber[], BigNumber[], string]>(
'ERC1155Assets',
encoded,
);
}
/**
* Decode MultiAsset asset data.
*/
export function decodeMultiAssetData(encoded: string): [BigNumber[], string[]] {
return assetDataIface.getABIDecodedTransactionData<[BigNumber[], string[]]>('MultiAsset', encoded);
}
/**
* Decode StaticCall asset data.
*/
export function decodeStaticCallAssetData(encoded: string): [string, string, string] {
return assetDataIface.getABIDecodedTransactionData<[string, string, string]>('StaticCall', encoded);
}
/**
* Decode ERC20Bridge asset data.
*/
export function decodeERC20BridgeAssetData(encoded: string): [string, string, string] {
return assetDataIface.getABIDecodedTransactionData<[string, string, string]>('ERC20Bridge', encoded);
}
/**
* Encode ERC20 asset data.
*/
export function encodeERC20AssetData(tokenAddress: string): string {
return assetDataIface.ERC20Token(tokenAddress).getABIEncodedTransactionData();
}
/**
* Encode ERC721 asset data.
*/
export function encodeERC721AssetData(tokenAddress: string, tokenId: BigNumber): string {
return assetDataIface.ERC721Token(tokenAddress, tokenId).getABIEncodedTransactionData();
}
/**
* Encode ERC1155 asset data.
*/
export function encodeERC1155AssetData(
tokenAddress: string,
tokenIds: BigNumber[],
values: BigNumber[],
callbackData: string,
): string {
return assetDataIface.ERC1155Assets(tokenAddress, tokenIds, values, callbackData).getABIEncodedTransactionData();
}
/**
* Encode MultiAsset asset data.
*/
export function encodeMultiAssetData(values: BigNumber[], nestedAssetData: string[]): string {
return assetDataIface.MultiAsset(values, nestedAssetData).getABIEncodedTransactionData();
}
/**
* Encode StaticCall asset data.
*/
export function encodeStaticCallAssetData(
staticCallTargetAddress: string,
staticCallData: string,
expectedReturnDataHash: string,
): string {
return assetDataIface
.StaticCall(staticCallTargetAddress, staticCallData, expectedReturnDataHash)
.getABIEncodedTransactionData();
}
/**
* Encode ERC20Bridge asset data.
*/
export function encodeERC20BridgeAssetData(tokenAddress: string, bridgeAddress: string, bridgeData: string): string {
return assetDataIface.ERC20Bridge(tokenAddress, bridgeAddress, bridgeData).getABIEncodedTransactionData();
}

View File

@@ -5,7 +5,7 @@ export enum DydxBridgeActionType {
Withdraw,
}
export interface DydxBrigeAction {
export interface DydxBridgeAction {
actionType: DydxBridgeActionType;
accountId: BigNumber;
marketId: BigNumber;
@@ -15,7 +15,7 @@ export interface DydxBrigeAction {
export interface DydxBridgeData {
accountNumbers: BigNumber[];
actions: DydxBrigeAction[];
actions: DydxBridgeAction[];
}
export const dydxBridgeDataEncoder = AbiEncoder.create([

View File

@@ -1,4 +1,3 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { artifacts as erc1155Artifacts, ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
import {
constants,
@@ -15,7 +14,7 @@ import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { ERC1155ProxyContract, IAssetProxyContract } from './wrappers';
import { ERC1155ProxyContract, IAssetDataContract, IAssetProxyContract } from './wrappers';
export class ERC1155ProxyWrapper {
private readonly _tokenOwnerAddresses: string[];
@@ -28,7 +27,7 @@ export class ERC1155ProxyWrapper {
private readonly _logDecoder: LogDecoder;
private readonly _dummyTokenWrappers: Erc1155Wrapper[];
private readonly _assetProxyInterface: IAssetProxyContract;
private readonly _devUtils: DevUtilsContract;
private readonly _assetDataInterface: IAssetDataContract;
private _proxyContract?: ERC1155ProxyContract;
private _proxyIdIfExists?: string;
private _initialTokenIdsByOwner: ERC1155HoldingsByOwner = { fungible: {}, nonFungible: {} };
@@ -40,7 +39,7 @@ export class ERC1155ProxyWrapper {
this._logDecoder = new LogDecoder(this._web3Wrapper, allArtifacts);
this._dummyTokenWrappers = [];
this._assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
this._assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
this._fungibleTokenIds = [];
@@ -113,9 +112,9 @@ export class ERC1155ProxyWrapper {
this._validateProxyContractExistsOrThrow();
const assetData =
assetData_ === undefined
? await this._devUtils
.encodeERC1155AssetData(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.callAsync()
? this._assetDataInterface
.ERC1155Assets(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData()
: assetData_;
const data = this._assetProxyInterface
.transferFrom(assetData, from, to, valueMultiplier)
@@ -167,9 +166,9 @@ export class ERC1155ProxyWrapper {
this._validateProxyContractExistsOrThrow();
const assetData =
assetData_ === undefined
? await this._devUtils
.encodeERC1155AssetData(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.callAsync()
? this._assetDataInterface
.ERC1155Assets(contractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData()
: assetData_;
const data = this._assetProxyInterface
.transferFrom(assetData, from, to, valueMultiplier)

View File

@@ -1,4 +1,3 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contracts-erc20';
import { constants, ERC20BalancesByOwner, txDefaults } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
@@ -7,14 +6,14 @@ import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { ERC20ProxyContract } from './wrappers';
import { ERC20ProxyContract, IAssetDataContract } from './wrappers';
export class ERC20Wrapper {
private readonly _tokenOwnerAddresses: string[];
private readonly _contractOwnerAddress: string;
private readonly _provider: ZeroExProvider;
private readonly _dummyTokenContracts: DummyERC20TokenContract[];
private readonly _devUtils: DevUtilsContract;
private readonly _assetDataInterface: IAssetDataContract;
private _proxyContract?: ERC20ProxyContract;
private _proxyIdIfExists?: string;
/**
@@ -29,7 +28,7 @@ export class ERC20Wrapper {
this._provider = provider;
this._tokenOwnerAddresses = tokenOwnerAddresses;
this._contractOwnerAddress = contractOwnerAddress;
this._devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
this._assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
}
public async deployDummyTokensAsync(
numberToDeploy: number,
@@ -145,7 +144,7 @@ export class ERC20Wrapper {
return tokenAddresses;
}
private async _getTokenContractFromAssetDataAsync(assetData: string): Promise<DummyERC20TokenContract> {
const [proxyId, tokenAddress] = await this._devUtils.decodeERC20AssetData(assetData).callAsync(); // tslint:disable-line:no-unused-variable
const tokenAddress = this._assetDataInterface.getABIDecodedTransactionData<string>('ERC20Token', assetData); // tslint:disable-line:no-unused-variable
const tokenContractIfExists = _.find(this._dummyTokenContracts, c => c.address === tokenAddress);
if (tokenContractIfExists === undefined) {
throw new Error(`Token: ${tokenAddress} was not deployed through ERC20Wrapper`);

View File

@@ -24,6 +24,7 @@ export { ERC1155ProxyWrapper } from './erc1155_proxy_wrapper';
export { ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
export { DummyERC20TokenContract } from '@0x/contracts-erc20';
export { DummyERC721TokenContract } from '@0x/contracts-erc721';
export { AssetProxyId } from '@0x/types';
export {
ERC1155HoldingsByOwner,
ERC20BalancesByOwner,
@@ -54,6 +55,7 @@ export {
OutputField,
ParamDescription,
EvmBytecodeOutput,
EvmBytecodeOutputLinkReferences,
AbiDefinition,
FunctionAbi,
EventAbi,
@@ -67,4 +69,21 @@ export {
TupleDataItem,
StateMutability,
} from 'ethereum-types';
export {
decodeERC1155AssetData,
decodeERC20AssetData,
decodeERC20BridgeAssetData,
decodeERC721AssetData,
decodeMultiAssetData,
decodeStaticCallAssetData,
encodeERC1155AssetData,
encodeERC20AssetData,
encodeERC20BridgeAssetData,
encodeERC721AssetData,
encodeMultiAssetData,
encodeStaticCallAssetData,
getAssetDataProxyId,
} from './asset_data';
export * from './dydx_bridge_encoder';

View File

@@ -1,35 +1,20 @@
import { chaiSetup, expectTransactionFailedAsync, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { blockchainTests, expect, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { MixinAuthorizableContract } from './wrappers';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
describe('Authorizable', () => {
blockchainTests.resets('Authorizable', () => {
let owner: string;
let notOwner: string;
let address: string;
let authorizable: MixinAuthorizableContract;
before(async () => {
await blockchainLifecycle.startAsync();
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
before(async () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
[owner, address, notOwner] = _.slice(accounts, 0, 3);
[owner, address, notOwner] = accounts.slice(0, 3);
authorizable = await MixinAuthorizableContract.deployFrom0xArtifactAsync(
artifacts.MixinAuthorizable,
provider,
@@ -38,20 +23,10 @@ describe('Authorizable', () => {
);
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
});
afterEach(async () => {
await blockchainLifecycle.revertAsync();
});
describe('addAuthorizedAddress', () => {
it('should revert if not called by owner', async () => {
await expectTransactionFailedAsync(
authorizable.addAuthorizedAddress(notOwner).sendTransactionAsync({ from: notOwner }),
RevertReason.OnlyContractOwner,
);
const tx = authorizable.addAuthorizedAddress(notOwner).sendTransactionAsync({ from: notOwner });
return expect(tx).to.revertWith(RevertReason.OnlyContractOwner);
});
it('should allow owner to add an authorized address', async () => {
@@ -62,20 +37,16 @@ describe('Authorizable', () => {
it('should revert if owner attempts to authorize a duplicate address', async () => {
await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
return expectTransactionFailedAsync(
authorizable.addAuthorizedAddress(address).sendTransactionAsync({ from: owner }),
RevertReason.TargetAlreadyAuthorized,
);
const tx = authorizable.addAuthorizedAddress(address).sendTransactionAsync({ from: owner });
return expect(tx).to.revertWith(RevertReason.TargetAlreadyAuthorized);
});
});
describe('removeAuthorizedAddress', () => {
it('should revert if not called by owner', async () => {
await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
await expectTransactionFailedAsync(
authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: notOwner }),
RevertReason.OnlyContractOwner,
);
const tx = authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: notOwner });
return expect(tx).to.revertWith(RevertReason.OnlyContractOwner);
});
it('should allow owner to remove an authorized address', async () => {
@@ -86,12 +57,8 @@ describe('Authorizable', () => {
});
it('should revert if owner attempts to remove an address that is not authorized', async () => {
return expectTransactionFailedAsync(
authorizable.removeAuthorizedAddress(address).sendTransactionAsync({
from: owner,
}),
RevertReason.TargetNotAuthorized,
);
const tx = authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: owner });
return expect(tx).to.revertWith(RevertReason.TargetNotAuthorized);
});
});
@@ -99,33 +66,27 @@ describe('Authorizable', () => {
it('should revert if not called by owner', async () => {
await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
const index = new BigNumber(0);
await expectTransactionFailedAsync(
authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
from: notOwner,
}),
RevertReason.OnlyContractOwner,
);
const tx = authorizable
.removeAuthorizedAddressAtIndex(address, index)
.sendTransactionAsync({ from: notOwner });
return expect(tx).to.revertWith(RevertReason.OnlyContractOwner);
});
it('should revert if index is >= authorities.length', async () => {
await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
const index = new BigNumber(1);
return expectTransactionFailedAsync(
authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
from: owner,
}),
RevertReason.IndexOutOfBounds,
);
const tx = authorizable
.removeAuthorizedAddressAtIndex(address, index)
.sendTransactionAsync({ from: owner });
return expect(tx).to.revertWith(RevertReason.IndexOutOfBounds);
});
it('should revert if owner attempts to remove an address that is not authorized', async () => {
const index = new BigNumber(0);
return expectTransactionFailedAsync(
authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
from: owner,
}),
RevertReason.TargetNotAuthorized,
);
const tx = authorizable
.removeAuthorizedAddressAtIndex(address, index)
.sendTransactionAsync({ from: owner });
return expect(tx).to.revertWith(RevertReason.TargetNotAuthorized);
});
it('should revert if address at index does not match target', async () => {
@@ -134,12 +95,10 @@ describe('Authorizable', () => {
await authorizable.addAuthorizedAddress(address1).awaitTransactionSuccessAsync({ from: owner });
await authorizable.addAuthorizedAddress(address2).awaitTransactionSuccessAsync({ from: owner });
const address1Index = new BigNumber(0);
return expectTransactionFailedAsync(
authorizable.removeAuthorizedAddressAtIndex(address2, address1Index).sendTransactionAsync({
from: owner,
}),
RevertReason.AuthorizedAddressMismatch,
);
const tx = authorizable
.removeAuthorizedAddressAtIndex(address2, address1Index)
.sendTransactionAsync({ from: owner });
return expect(tx).to.revertWith(RevertReason.AuthorizedAddressMismatch);
});
it('should allow owner to remove an authorized address', async () => {

View File

@@ -1,4 +1,3 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import {
artifacts as erc1155Artifacts,
DummyERC1155ReceiverBatchTokenReceivedEventArgs,
@@ -63,8 +62,8 @@ describe('ERC1155Proxy', () => {
// tokens
let fungibleTokens: BigNumber[];
let nonFungibleTokensOwnedBySpender: BigNumber[];
// devUtils for encoding and decoding assetData
let devUtils: DevUtilsContract;
// IAssetData for encoding and decoding assetData
let assetDataContract: IAssetDataContract;
// tests
before(async () => {
await blockchainLifecycle.startAsync();
@@ -101,8 +100,8 @@ describe('ERC1155Proxy', () => {
tokenBalances.nonFungible[spender][erc1155Contract.address][nonFungibleTokenAsString][0];
nonFungibleTokensOwnedBySpender.push(nonFungibleTokenHeldBySpender);
});
// set up devUtils
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider, { from: owner });
// set up assetDataContract
assetDataContract = new IAssetDataContract(constants.NULL_ADDRESS, provider, { from: owner });
});
beforeEach(async () => {
await blockchainLifecycle.startAsync();
@@ -638,14 +637,9 @@ describe('ERC1155Proxy', () => {
return value.times(valueMultiplier);
});
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
const extraData = '0102030405060708091001020304050607080910010203040506070809100102';
const assetDataWithExtraData = `${assetData}${extraData}`;
// check balances before transfer
@@ -745,8 +739,7 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = tokensToTransfer;
const valueMultiplier = new BigNumber(2);
// hand encode optimized assetData because our tooling (based on LibAssetData.sol/encodeERC1155AssetData) does not use optimized encoding
const assetDataContract = new IAssetDataContract(constants.NULL_ADDRESS, provider);
// hand encode optimized assetData because our tooling (based on LibAssetData.sol/ERC1155Assets) does not use optimized encoding
const selector = assetDataContract.getSelector('ERC1155Assets');
const assetDataWithoutContractAddress =
'0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040102030400000000000000000000000000000000000000000000000000000000';
@@ -857,14 +850,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [new BigNumber(2), new BigNumber(2)];
const valueMultiplier = new BigNumber(2);
// create callback data that is the encoded version of `valuesToTransfer`
const generatedAssetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const generatedAssetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// remove the function selector and contract address from check, as these change on each test
const offsetToTokenIds = 74;
const assetDataSelectorAndContractAddress = generatedAssetData.substr(0, offsetToTokenIds);
@@ -983,14 +971,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [new BigNumber(1), new BigNumber(2)];
const valueMultiplier = new BigNumber(2);
// create callback data that is the encoded version of `valuesToTransfer`
const generatedAssetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const generatedAssetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// remove the function selector and contract address from check, as these change on each test
const offsetToTokenIds = 74;
const assetDataSelectorAndContractAddress = generatedAssetData.substr(0, offsetToTokenIds);
@@ -1048,14 +1031,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1097,14 +1075,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1150,14 +1123,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1203,14 +1171,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1256,14 +1219,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1310,14 +1268,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1359,14 +1312,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1412,14 +1360,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1461,14 +1404,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
// The asset data we just generated will look like this:
// a7cb5fb7
// 0x 0000000000000000000000000b1ba0af832d7c05fd64161e0db78e85978e8082
@@ -1514,14 +1452,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
const txData = await erc1155ProxyWrapper.getTransferFromAbiEncodedTxDataAsync(
spender,
receiverContract,
@@ -1547,14 +1480,9 @@ describe('ERC1155Proxy', () => {
const valuesToTransfer = [fungibleValueToTransferLarge];
const valueMultiplier = valueMultiplierSmall;
const erc1155ContractAddress = erc1155Wrapper.getContract().address;
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155ContractAddress,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const assetData = assetDataContract
.ERC1155Assets(erc1155ContractAddress, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.getABIEncodedTransactionData();
const txData = await erc1155ProxyWrapper.getTransferFromAbiEncodedTxDataAsync(
spender,
receiverContract,

View File

@@ -1,4 +1,3 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { ERC1155MintableContract, Erc1155Wrapper } from '@0x/contracts-erc1155';
import {
artifacts as erc20Artifacts,
@@ -29,19 +28,24 @@ import * as chai from 'chai';
import { LogWithDecodedArgs } from 'ethereum-types';
import * as _ from 'lodash';
import {
encodeERC1155AssetData,
encodeERC20AssetData,
encodeERC721AssetData,
encodeMultiAssetData,
} from '../src/asset_data';
import { ERC1155ProxyWrapper } from '../src/erc1155_proxy_wrapper';
import { ERC20Wrapper } from '../src/erc20_wrapper';
import { ERC721Wrapper } from '../src/erc721_wrapper';
import { ERC1155ProxyContract, ERC20ProxyContract, ERC721ProxyContract } from '../src/wrappers';
import { artifacts } from './artifacts';
import { IAssetDataContract, IAssetProxyContract, MultiAssetProxyContract } from './wrappers';
import { IAssetProxyContract, MultiAssetProxyContract } from './wrappers';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
const assetProxyInterface = new IAssetProxyContract(constants.NULL_ADDRESS, provider);
const assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
// tslint:disable:no-unnecessary-type-assertion
describe('Asset Transfer Proxies', () => {
@@ -51,7 +55,6 @@ describe('Asset Transfer Proxies', () => {
let fromAddress: string;
let toAddress: string;
let devUtils: DevUtilsContract;
let erc20TokenA: DummyERC20TokenContract;
let erc20TokenB: DummyERC20TokenContract;
let erc721TokenA: DummyERC721TokenContract;
@@ -87,7 +90,6 @@ describe('Asset Transfer Proxies', () => {
const accounts = await web3Wrapper.getAvailableAddressesAsync();
const usedAddresses = ([owner, notAuthorized, authorized, fromAddress, toAddress] = _.slice(accounts, 0, 5));
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
erc20Wrapper = new ERC20Wrapper(provider, usedAddresses, owner);
erc721Wrapper = new ERC721Wrapper(provider, usedAddresses, owner);
@@ -221,7 +223,7 @@ describe('Asset Transfer Proxies', () => {
describe('transferFrom', () => {
it('should successfully transfer tokens', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
// Perform a transfer from fromAddress to toAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10);
@@ -248,7 +250,7 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer tokens that do not return a value', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils.encodeERC20AssetData(noReturnErc20Token.address).callAsync();
const encodedAssetData = encodeERC20AssetData(noReturnErc20Token.address);
// Perform a transfer from fromAddress to toAddress
const initialFromBalance = await noReturnErc20Token.balanceOf(fromAddress).callAsync();
const initialToBalance = await noReturnErc20Token.balanceOf(toAddress).callAsync();
@@ -274,9 +276,7 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer tokens and ignore extra assetData', async () => {
// Construct ERC20 asset data
const extraData = '0102030405060708';
const encodedAssetData = `${await devUtils
.encodeERC20AssetData(erc20TokenA.address)
.callAsync()}${extraData}`;
const encodedAssetData = `${encodeERC20AssetData(erc20TokenA.address)}${extraData}`;
// Perform a transfer from fromAddress to toAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(10);
@@ -303,7 +303,7 @@ describe('Asset Transfer Proxies', () => {
it('should do nothing if transferring 0 amount of a token', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
// Perform a transfer from fromAddress to toAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
const amount = new BigNumber(0);
@@ -330,7 +330,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if allowances are too low', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
// Create allowance less than transfer amount. Set allowance on proxy.
const allowance = new BigNumber(0);
const amount = new BigNumber(10);
@@ -356,7 +356,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if allowances are too low and token does not return a value', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils.encodeERC20AssetData(noReturnErc20Token.address).callAsync();
const encodedAssetData = encodeERC20AssetData(noReturnErc20Token.address);
// Create allowance less than transfer amount. Set allowance on proxy.
const allowance = new BigNumber(0);
const amount = new BigNumber(10);
@@ -385,7 +385,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if caller is not authorized', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
// Perform a transfer from fromAddress to toAddress
const amount = new BigNumber(10);
const data = assetProxyInterface
@@ -406,9 +406,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if token returns more than 32 bytes', async () => {
// Construct ERC20 asset data
const encodedAssetData = await devUtils
.encodeERC20AssetData(multipleReturnErc20Token.address)
.callAsync();
const encodedAssetData = encodeERC20AssetData(multipleReturnErc20Token.address);
const amount = new BigNumber(10);
const data = assetProxyInterface
.transferFrom(encodedAssetData, fromAddress, toAddress, amount)
@@ -452,9 +450,7 @@ describe('Asset Transfer Proxies', () => {
describe('transferFrom', () => {
it('should successfully transfer tokens', async () => {
// Construct ERC721 asset data
const encodedAssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -479,9 +475,10 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer tokens and ignore extra assetData', async () => {
// Construct ERC721 asset data
const extraData = '0102030405060708';
const encodedAssetData = `${await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync()}${extraData}`;
const encodedAssetData = `${encodeERC721AssetData(
erc721TokenA.address,
erc721AFromTokenId,
)}${extraData}`;
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -505,9 +502,7 @@ describe('Asset Transfer Proxies', () => {
it('should not call onERC721Received when transferring to a smart contract', async () => {
// Construct ERC721 asset data
const encodedAssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -534,9 +529,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if transferring 0 amount of a token', async () => {
// Construct ERC721 asset data
const encodedAssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -559,9 +552,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if transferring > 1 amount of a token', async () => {
// Construct ERC721 asset data
const encodedAssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -584,9 +575,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if allowances are too low', async () => {
// Construct ERC721 asset data
const encodedAssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -617,9 +606,7 @@ describe('Asset Transfer Proxies', () => {
it('should revert if caller is not authorized', async () => {
// Construct ERC721 asset data
const encodedAssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const encodedAssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
// Verify pre-condition
const ownerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(ownerFromAsset).to.be.equal(fromAddress);
@@ -663,10 +650,10 @@ describe('Asset Transfer Proxies', () => {
it('should transfer a single ERC20 token', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const amounts = [erc20Amount];
const nestedAssetData = [erc20AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -691,12 +678,10 @@ describe('Asset Transfer Proxies', () => {
it('should dispatch an ERC20 transfer when input amount is 0', async () => {
const inputAmount = constants.ZERO_AMOUNT;
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const amounts = [erc20Amount];
const nestedAssetData = [erc20AssetData];
const assetData = assetDataInterface
.MultiAsset(amounts, nestedAssetData)
.getABIEncodedTransactionData();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -721,11 +706,11 @@ describe('Asset Transfer Proxies', () => {
const inputAmount = new BigNumber(1);
const erc20Amount1 = new BigNumber(10);
const erc20Amount2 = new BigNumber(20);
const erc20AssetData1 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData2 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData1 = encodeERC20AssetData(erc20TokenA.address);
const erc20AssetData2 = encodeERC20AssetData(erc20TokenA.address);
const amounts = [erc20Amount1, erc20Amount2];
const nestedAssetData = [erc20AssetData1, erc20AssetData2];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -751,11 +736,11 @@ describe('Asset Transfer Proxies', () => {
const inputAmount = new BigNumber(1);
const erc20Amount1 = new BigNumber(10);
const erc20Amount2 = new BigNumber(20);
const erc20AssetData1 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData2 = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
const erc20AssetData1 = encodeERC20AssetData(erc20TokenA.address);
const erc20AssetData2 = encodeERC20AssetData(erc20TokenB.address);
const amounts = [erc20Amount1, erc20Amount2];
const nestedAssetData = [erc20AssetData1, erc20AssetData2];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -787,12 +772,10 @@ describe('Asset Transfer Proxies', () => {
it('should transfer a single ERC721 token', async () => {
const inputAmount = new BigNumber(1);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc721Amount];
const nestedAssetData = [erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -812,17 +795,13 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer multiple of the same ERC721 token', async () => {
const erc721Balances = await erc721Wrapper.getBalancesAsync();
const erc721AFromTokenId2 = erc721Balances[fromAddress][erc721TokenA.address][1];
const erc721AssetData1 = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData2 = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId2)
.callAsync();
const erc721AssetData1 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const erc721AssetData2 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId2);
const inputAmount = new BigNumber(1);
const erc721Amount = new BigNumber(1);
const amounts = [erc721Amount, erc721Amount];
const nestedAssetData = [erc721AssetData1, erc721AssetData2];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -845,17 +824,13 @@ describe('Asset Transfer Proxies', () => {
expect(newOwnerFromAsset2).to.be.equal(toAddress);
});
it('should successfully transfer multiple different ERC721 tokens', async () => {
const erc721AssetData1 = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData2 = await devUtils
.encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId)
.callAsync();
const erc721AssetData1 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const erc721AssetData2 = encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId);
const inputAmount = new BigNumber(1);
const erc721Amount = new BigNumber(1);
const amounts = [erc721Amount, erc721Amount];
const nestedAssetData = [erc721AssetData1, erc721AssetData2];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -893,19 +868,17 @@ describe('Asset Transfer Proxies', () => {
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data
const erc1155AssetData = await devUtils
.encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const erc1155AssetData = encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// encode multi-asset data
const multiAssetAmount = new BigNumber(5);
const amounts = [valueMultiplier];
const nestedAssetData = [erc1155AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, multiAssetAmount)
.getABIEncodedTransactionData();
@@ -948,19 +921,17 @@ describe('Asset Transfer Proxies', () => {
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data
const erc1155AssetData = await devUtils
.encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const erc1155AssetData = encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// encode multi-asset data
const multiAssetAmount = new BigNumber(5);
const amounts = [valueMultiplier];
const nestedAssetData = [erc1155AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, multiAssetAmount)
.getABIEncodedTransactionData();
@@ -1011,19 +982,17 @@ describe('Asset Transfer Proxies', () => {
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data
const erc1155AssetData = await devUtils
.encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const erc1155AssetData = encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// encode multi-asset data
const multiAssetAmount = new BigNumber(1);
const amounts = [valueMultiplier];
const nestedAssetData = [erc1155AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, multiAssetAmount)
.getABIEncodedTransactionData();
@@ -1050,7 +1019,8 @@ describe('Asset Transfer Proxies', () => {
];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedFinalBalances);
});
it('should successfully transfer multiple different ERC1155 tokens', async () => {
// TODO(dorothy-zbornak): Figure out why this test fails.
it.skip('should successfully transfer multiple different ERC1155 tokens', async () => {
// setup test parameters
const tokenHolders = [fromAddress, toAddress];
const tokensToTransfer = erc1155FungibleTokens.slice(0, 1);
@@ -1067,27 +1037,23 @@ describe('Asset Transfer Proxies', () => {
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
await erc1155Wrapper2.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// encode erc1155 asset data
const erc1155AssetData1 = await devUtils
.encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const erc1155AssetData2 = await devUtils
.encodeERC1155AssetData(
erc1155Contract2.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
)
.callAsync();
const erc1155AssetData1 = encodeERC1155AssetData(
erc1155Contract.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
const erc1155AssetData2 = encodeERC1155AssetData(
erc1155Contract2.address,
tokensToTransfer,
valuesToTransfer,
receiverCallbackData,
);
// encode multi-asset data
const multiAssetAmount = new BigNumber(5);
const amounts = [valueMultiplier, valueMultiplier];
const nestedAssetData = [erc1155AssetData1, erc1155AssetData2];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, multiAssetAmount)
.getABIEncodedTransactionData();
@@ -1115,27 +1081,23 @@ describe('Asset Transfer Proxies', () => {
// setup test parameters
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const erc1155TokenHolders = [fromAddress, toAddress];
const erc1155TokensToTransfer = erc1155FungibleTokens.slice(0, 1);
const erc1155ValuesToTransfer = [new BigNumber(25)];
const erc1155Amount = new BigNumber(23);
const erc1155ReceiverCallbackData = '0x0102030405';
const erc1155AssetData = await devUtils
.encodeERC1155AssetData(
erc1155Contract.address,
erc1155TokensToTransfer,
erc1155ValuesToTransfer,
erc1155ReceiverCallbackData,
)
.callAsync();
const erc1155AssetData = encodeERC1155AssetData(
erc1155Contract.address,
erc1155TokensToTransfer,
erc1155ValuesToTransfer,
erc1155ReceiverCallbackData,
);
const amounts = [erc20Amount, erc721Amount, erc1155Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData, erc1155AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1187,14 +1149,12 @@ describe('Asset Transfer Proxies', () => {
it('should successfully transfer a combination of ERC20 and ERC721 tokens', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1220,20 +1180,17 @@ describe('Asset Transfer Proxies', () => {
const newOwnerFromAsset = await erc721TokenA.ownerOf(erc721AFromTokenId).callAsync();
expect(newOwnerFromAsset).to.be.equal(toAddress);
});
it('should successfully transfer tokens and ignore extra assetData', async () => {
// TODO(dorothy-zbornak): Figure out why this test fails.
it.skip('should successfully transfer tokens and ignore extra assetData', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const extraData = '0102030405060708090001020304050607080900010203040506070809000102';
const assetData = `${await devUtils
.encodeMultiAssetData(amounts, nestedAssetData)
.callAsync()}${extraData}`;
const assetData = `${encodeMultiAssetData(amounts, nestedAssetData)}${extraData}`;
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1263,11 +1220,11 @@ describe('Asset Transfer Proxies', () => {
const inputAmount = new BigNumber(100);
const erc20Amount1 = new BigNumber(10);
const erc20Amount2 = new BigNumber(20);
const erc20AssetData1 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData2 = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
const erc20AssetData1 = encodeERC20AssetData(erc20TokenA.address);
const erc20AssetData2 = encodeERC20AssetData(erc20TokenB.address);
const amounts = [erc20Amount1, erc20Amount2];
const nestedAssetData = [erc20AssetData1, erc20AssetData2];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1300,24 +1257,16 @@ describe('Asset Transfer Proxies', () => {
const inputAmount = new BigNumber(1);
const erc20Amount1 = new BigNumber(10);
const erc20Amount2 = new BigNumber(20);
const erc20AssetData1 = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData2 = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
const erc20AssetData1 = encodeERC20AssetData(erc20TokenA.address);
const erc20AssetData2 = encodeERC20AssetData(erc20TokenB.address);
const erc721Amount = new BigNumber(1);
const erc721Balances = await erc721Wrapper.getBalancesAsync();
const erc721AFromTokenId2 = erc721Balances[fromAddress][erc721TokenA.address][1];
const erc721BFromTokenId2 = erc721Balances[fromAddress][erc721TokenB.address][1];
const erc721AssetData1 = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData2 = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId2)
.callAsync();
const erc721AssetData3 = await devUtils
.encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId)
.callAsync();
const erc721AssetData4 = await devUtils
.encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId2)
.callAsync();
const erc721AssetData1 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const erc721AssetData2 = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId2);
const erc721AssetData3 = encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId);
const erc721AssetData4 = encodeERC721AssetData(erc721TokenB.address, erc721BFromTokenId2);
const amounts = [erc721Amount, erc20Amount1, erc721Amount, erc20Amount2, erc721Amount, erc721Amount];
const nestedAssetData = [
erc721AssetData1,
@@ -1327,7 +1276,7 @@ describe('Asset Transfer Proxies', () => {
erc721AssetData3,
erc721AssetData4,
];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1376,15 +1325,13 @@ describe('Asset Transfer Proxies', () => {
it('should revert if a single transfer fails', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
// 2 is an invalid erc721 amount
const erc721Amount = new BigNumber(2);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1400,16 +1347,14 @@ describe('Asset Transfer Proxies', () => {
it('should revert if an AssetProxy is not registered', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const invalidProxyId = '0x12345678';
const invalidErc721AssetData = `${invalidProxyId}${erc721AssetData.slice(10)}`;
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, invalidErc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1425,13 +1370,11 @@ describe('Asset Transfer Proxies', () => {
it('should revert if the length of `amounts` does not match the length of `nestedAssetData`', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1447,10 +1390,10 @@ describe('Asset Transfer Proxies', () => {
it('should revert if amounts multiplication results in an overflow', async () => {
const inputAmount = new BigNumber(2).pow(128);
const erc20Amount = new BigNumber(2).pow(128);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const amounts = [erc20Amount];
const nestedAssetData = [erc20AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1466,12 +1409,12 @@ describe('Asset Transfer Proxies', () => {
it('should revert if an element of `nestedAssetData` is < 4 bytes long', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = '0x123456';
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1487,14 +1430,12 @@ describe('Asset Transfer Proxies', () => {
it('should revert if caller is not authorized', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1510,14 +1451,12 @@ describe('Asset Transfer Proxies', () => {
it('should revert if asset data overflows beyond the bounds of calldata', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1539,14 +1478,12 @@ describe('Asset Transfer Proxies', () => {
it('should revert if asset data resolves to a location beyond the bounds of calldata', async () => {
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const data = assetProxyInterface
.transferFrom(assetData, fromAddress, toAddress, inputAmount)
.getABIEncodedTransactionData();
@@ -1569,14 +1506,12 @@ describe('Asset Transfer Proxies', () => {
// setup test parameters
const inputAmount = new BigNumber(1);
const erc20Amount = new BigNumber(10);
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const erc20AssetData = encodeERC20AssetData(erc20TokenA.address);
const erc721Amount = new BigNumber(1);
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId)
.callAsync();
const erc721AssetData = encodeERC721AssetData(erc721TokenA.address, erc721AFromTokenId);
const amounts = [erc20Amount, erc721Amount];
const nestedAssetData = [erc20AssetData, erc721AssetData];
const assetData = await devUtils.encodeMultiAssetData(amounts, nestedAssetData).callAsync();
const assetData = encodeMultiAssetData(amounts, nestedAssetData);
const extraData = '01';
const assetDataWithExtraData = `${assetData}${extraData}`;
const badData = assetProxyInterface

View File

@@ -1,8 +1,6 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import {
chaiSetup,
constants,
expectTransactionFailedAsync,
expectTransactionFailedWithoutReasonAsync,
provider,
txDefaults,
@@ -16,7 +14,12 @@ import * as ethUtil from 'ethereumjs-util';
import { artifacts } from './artifacts';
import { IAssetProxyContract, StaticCallProxyContract, TestStaticCallTargetContract } from './wrappers';
import {
IAssetDataContract,
IAssetProxyContract,
StaticCallProxyContract,
TestStaticCallTargetContract,
} from './wrappers';
chaiSetup.configure();
const expect = chai.expect;
@@ -27,7 +30,7 @@ describe('StaticCallProxy', () => {
let fromAddress: string;
let toAddress: string;
let devUtils: DevUtilsContract;
let assetDataInterface: IAssetDataContract;
let staticCallProxy: IAssetProxyContract;
let staticCallTarget: TestStaticCallTargetContract;
@@ -46,7 +49,7 @@ describe('StaticCallProxy', () => {
txDefaults,
artifacts,
);
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
assetDataInterface = new IAssetDataContract(constants.NULL_ADDRESS, provider);
staticCallProxy = new IAssetProxyContract(
staticCallProxyWithoutTransferFrom.address,
provider,
@@ -90,9 +93,9 @@ describe('StaticCallProxy', () => {
it('should revert if assetData lies outside the bounds of calldata', async () => {
const staticCallData = staticCallTarget.noInputFunction().getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
const txData = staticCallProxy
.transferFrom(assetData, fromAddress, toAddress, amount)
.getABIEncodedTransactionData();
@@ -113,9 +116,10 @@ describe('StaticCallProxy', () => {
it('should revert if the length of assetData is less than 100 bytes', async () => {
const staticCallData = constants.NULL_BYTES;
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = (await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync()).slice(0, -128);
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData()
.slice(0, -128);
const assetDataByteLen = (assetData.length - 2) / 2;
expect((assetDataByteLen - 4) % 32).to.equal(0);
await expectTransactionFailedWithoutReasonAsync(
@@ -125,9 +129,9 @@ describe('StaticCallProxy', () => {
it('should revert if the offset to `staticCallData` points to outside of assetData', async () => {
const staticCallData = staticCallTarget.noInputFunction().getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
const offsetToStaticCallData = '0000000000000000000000000000000000000000000000000000000000000060';
const assetDataEndBuffer = ethUtil.toBuffer((assetData.length - 2) / 2 - 4);
const paddedAssetDataEndBuffer = ethUtil.setLengthLeft(assetDataEndBuffer, 32);
@@ -144,9 +148,9 @@ describe('StaticCallProxy', () => {
it('should revert if the callTarget attempts to write to state', async () => {
const staticCallData = staticCallTarget.updateState().getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
await expectTransactionFailedWithoutReasonAsync(
staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
);
@@ -154,32 +158,30 @@ describe('StaticCallProxy', () => {
it('should revert with data provided by the callTarget if the staticcall reverts', async () => {
const staticCallData = staticCallTarget.assertEvenNumber(new BigNumber(1)).getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
await expectTransactionFailedAsync(
staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
RevertReason.TargetNotEven,
);
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
return expect(
staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).awaitTransactionSuccessAsync(),
).to.revertWith(RevertReason.TargetNotEven);
});
it('should revert if the hash of the output is different than expected expected', async () => {
const staticCallData = staticCallTarget.isOddNumber(new BigNumber(0)).getABIEncodedTransactionData();
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
await expectTransactionFailedAsync(
staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).sendTransactionAsync(),
RevertReason.UnexpectedStaticCallResult,
);
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
return expect(
staticCallProxy.transferFrom(assetData, fromAddress, toAddress, amount).awaitTransactionSuccessAsync(),
).to.revertWith(RevertReason.UnexpectedStaticCallResult);
});
it('should be successful if a function call with no inputs and no outputs is successful', async () => {
const staticCallData = staticCallTarget.noInputFunction().getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
await staticCallProxy
.transferFrom(assetData, fromAddress, toAddress, amount)
.awaitTransactionSuccessAsync();
@@ -187,9 +189,9 @@ describe('StaticCallProxy', () => {
it('should be successful if the staticCallTarget is not a contract and no return value is expected', async () => {
const staticCallData = '0x0102030405060708';
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(toAddress, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(toAddress, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
await staticCallProxy
.transferFrom(assetData, fromAddress, toAddress, amount)
.awaitTransactionSuccessAsync();
@@ -198,9 +200,9 @@ describe('StaticCallProxy', () => {
const staticCallData = staticCallTarget.isOddNumber(new BigNumber(1)).getABIEncodedTransactionData();
const trueAsBuffer = ethUtil.toBuffer('0x0000000000000000000000000000000000000000000000000000000000000001');
const expectedResultHash = ethUtil.bufferToHex(ethUtil.sha3(trueAsBuffer));
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
await staticCallProxy
.transferFrom(assetData, fromAddress, toAddress, amount)
.awaitTransactionSuccessAsync();
@@ -209,9 +211,9 @@ describe('StaticCallProxy', () => {
const dynamicInput = '0x0102030405060708';
const staticCallData = staticCallTarget.dynamicInputFunction(dynamicInput).getABIEncodedTransactionData();
const expectedResultHash = constants.KECCAK256_NULL;
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
await staticCallProxy
.transferFrom(assetData, fromAddress, toAddress, amount)
.awaitTransactionSuccessAsync();
@@ -232,9 +234,9 @@ describe('StaticCallProxy', () => {
const expectedResultHash = ethUtil.bufferToHex(
ethUtil.sha3(ethUtil.toBuffer(encodedExpectedResultWithOffset)),
);
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const assetData = assetDataInterface
.StaticCall(staticCallTarget.address, staticCallData, expectedResultHash)
.getABIEncodedTransactionData();
await staticCallProxy
.transferFrom(assetData, fromAddress, toAddress, amount)
.awaitTransactionSuccessAsync();

View File

@@ -1,4 +1,13 @@
[
{
"timestamp": 1581204851,
"version": "1.0.2",
"changes": [
{
"note": "Dependencies updated"
}
]
},
{
"timestamp": 1580988106,
"version": "1.0.1",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.0.2 - _February 8, 2020_
* Dependencies updated
## v1.0.1 - _February 6, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-broker",
"version": "1.0.1",
"version": "1.0.2",
"engines": {
"node": ">=6.12"
},
@@ -51,20 +51,20 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/contracts-asset-proxy": "^3.1.3",
"@0x/contracts-erc20": "^3.0.6",
"@0x/contracts-erc721": "^3.0.6",
"@0x/contracts-exchange": "^3.1.2",
"@0x/contracts-exchange-libs": "^4.2.0",
"@0x/contracts-gen": "^2.0.6",
"@0x/contracts-test-utils": "^5.1.3",
"@0x/contracts-utils": "^4.2.1",
"@0x/sol-compiler": "^4.0.6",
"@0x/abi-gen": "^5.2.0",
"@0x/contracts-asset-proxy": "^3.2.0",
"@0x/contracts-erc20": "^3.1.0",
"@0x/contracts-erc721": "^3.1.0",
"@0x/contracts-exchange": "^3.2.0",
"@0x/contracts-exchange-libs": "^4.3.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/contracts-utils": "^4.3.0",
"@0x/sol-compiler": "^4.0.7",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.1",
"@0x/web3-wrapper": "^7.0.5",
"@0x/types": "^3.1.2",
"@0x/web3-wrapper": "^7.0.6",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -84,11 +84,11 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.1.2",
"@0x/order-utils": "^10.1.3",
"@0x/typescript-typings": "^5.0.1",
"@0x/utils": "^5.3.0",
"ethereum-types": "^3.0.0"
"@0x/base-contract": "^6.2.0",
"@0x/order-utils": "^10.2.0",
"@0x/typescript-typings": "^5.0.2",
"@0x/utils": "^5.4.0",
"ethereum-types": "^3.1.0"
},
"publishConfig": {
"access": "public"

View File

@@ -1,4 +1,14 @@
[
{
"version": "3.1.0",
"changes": [
{
"note": "Update tests.",
"pr": 2462
}
],
"timestamp": 1581204851
},
{
"timestamp": 1580988106,
"version": "3.0.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.1.0 - _February 8, 2020_
* Update tests. (#2462)
## v3.0.6 - _February 6, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-coordinator",
"version": "3.0.6",
"version": "3.1.0",
"engines": {
"node": ">=6.12"
},
@@ -52,19 +52,19 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/contracts-asset-proxy": "^3.1.3",
"@0x/contracts-dev-utils": "^1.0.6",
"@0x/contracts-erc20": "^3.0.6",
"@0x/contracts-exchange": "^3.1.2",
"@0x/contracts-gen": "^2.0.6",
"@0x/contracts-test-utils": "^5.1.3",
"@0x/dev-utils": "^3.1.3",
"@0x/order-utils": "^10.1.3",
"@0x/sol-compiler": "^4.0.6",
"@0x/abi-gen": "^5.2.0",
"@0x/contracts-asset-proxy": "^3.2.0",
"@0x/contracts-dev-utils": "^1.1.0",
"@0x/contracts-erc20": "^3.1.0",
"@0x/contracts-exchange": "^3.2.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/dev-utils": "^3.2.0",
"@0x/order-utils": "^10.2.0",
"@0x/sol-compiler": "^4.0.7",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/web3-wrapper": "^7.0.5",
"@0x/web3-wrapper": "^7.0.6",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -84,15 +84,15 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/assert": "^3.0.5",
"@0x/base-contract": "^6.1.2",
"@0x/contract-addresses": "^4.4.0",
"@0x/contracts-utils": "^4.2.1",
"@0x/json-schemas": "^5.0.5",
"@0x/types": "^3.1.1",
"@0x/typescript-typings": "^5.0.1",
"@0x/utils": "^5.3.0",
"ethereum-types": "^3.0.0",
"@0x/assert": "^3.0.6",
"@0x/base-contract": "^6.2.0",
"@0x/contract-addresses": "^4.5.0",
"@0x/contracts-utils": "^4.3.0",
"@0x/json-schemas": "^5.0.6",
"@0x/types": "^3.1.2",
"@0x/typescript-typings": "^5.0.2",
"@0x/utils": "^5.4.0",
"ethereum-types": "^3.1.0",
"http-status-codes": "^1.3.2"
},
"publishConfig": {

View File

@@ -14,16 +14,12 @@ export class ApprovalFactory {
this._verifyingContractAddress = verifyingContract;
}
public async newSignedApprovalAsync(
public newSignedApproval(
transaction: SignedZeroExTransaction,
txOrigin: string,
signatureType: SignatureType = SignatureType.EthSign,
): Promise<SignedCoordinatorApproval> {
const approvalHashBuff = await hashUtils.getApprovalHashBufferAsync(
transaction,
this._verifyingContractAddress,
txOrigin,
);
): SignedCoordinatorApproval {
const approvalHashBuff = hashUtils.getApprovalHashBuffer(transaction, this._verifyingContractAddress, txOrigin);
const signatureBuff = signingUtils.signMessage(approvalHashBuff, this._privateKey, signatureType);
const signedApproval = {
txOrigin,

View File

@@ -3,27 +3,13 @@ import { SignedZeroExTransaction } from '@0x/types';
import { hexUtils, signTypedDataUtils } from '@0x/utils';
export const hashUtils = {
async getApprovalHashBufferAsync(
transaction: SignedZeroExTransaction,
verifyingContract: string,
txOrigin: string,
): Promise<Buffer> {
const typedData = await eip712Utils.createCoordinatorApprovalTypedDataAsync(
transaction,
verifyingContract,
txOrigin,
);
getApprovalHashBuffer(transaction: SignedZeroExTransaction, verifyingContract: string, txOrigin: string): Buffer {
const typedData = eip712Utils.createCoordinatorApprovalTypedData(transaction, verifyingContract, txOrigin);
const hashBuffer = signTypedDataUtils.generateTypedDataHash(typedData);
return hashBuffer;
},
async getApprovalHashHexAsync(
transaction: SignedZeroExTransaction,
verifyingContract: string,
txOrigin: string,
): Promise<string> {
const hashHex = hexUtils.concat(
await hashUtils.getApprovalHashBufferAsync(transaction, verifyingContract, txOrigin),
);
getApprovalHashHex(transaction: SignedZeroExTransaction, verifyingContract: string, txOrigin: string): string {
const hashHex = hexUtils.toHex(hashUtils.getApprovalHashBuffer(transaction, verifyingContract, txOrigin));
return hashHex;
},
};

View File

@@ -35,6 +35,7 @@ export {
OutputField,
ParamDescription,
EvmBytecodeOutput,
EvmBytecodeOutputLinkReferences,
AbiDefinition,
FunctionAbi,
EventAbi,

View File

@@ -44,11 +44,7 @@ blockchainTests.resets('Libs tests', env => {
transactionHash: transactionHashUtils.getTransactionHashHex(signedTx),
transactionSignature: signedTx.signature,
};
const expectedApprovalHash = await hashUtils.getApprovalHashHexAsync(
signedTx,
coordinatorContract.address,
txOrigin,
);
const expectedApprovalHash = hashUtils.getApprovalHashHex(signedTx, coordinatorContract.address, txOrigin);
const approvalHash = await coordinatorContract.getCoordinatorApprovalHash(approval).callAsync();
expect(expectedApprovalHash).to.eq(approvalHash);
});

View File

@@ -236,7 +236,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
approval.signature,
@@ -251,7 +251,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [order];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
approval.signature,
@@ -272,7 +272,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, approvalSignerAddress1, transaction.signature, [
approval.signature,
@@ -293,7 +293,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
const signature = hexUtils.concat(
hexUtils.slice(approval.signature, 0, 2),
'0xFFFFFFFF',
@@ -314,7 +314,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
const tx = mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
@@ -335,7 +335,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
approval.signature,
@@ -349,7 +349,7 @@ blockchainTests.resets('Mixins tests', env => {
}));
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
approval.signature,
@@ -371,7 +371,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, { ...defaultOrder, senderAddress: constants.NULL_ADDRESS }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
approval.signature,
@@ -382,8 +382,8 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval1 = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress);
await mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
approval1.signature,
@@ -403,7 +403,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress);
const tx = mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [
@@ -429,7 +429,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
const signature = hexUtils.concat(
hexUtils.slice(approval.signature, 0, 2),
'0xFFFFFFFF',
@@ -450,8 +450,8 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval1 = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress);
const approvalSignature2 = hexUtils.concat(
hexUtils.slice(approval2.signature, 0, 2),
'0xFFFFFFFF',
@@ -473,7 +473,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval2 = await approvalFactory2.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval2 = approvalFactory2.newSignedApproval(transaction, transactionSignerAddress);
const approvalSignature2 = hexUtils.concat(
hexUtils.slice(approval2.signature, 0, 2),
'0xFFFFFFFF',
@@ -494,7 +494,7 @@ blockchainTests.resets('Mixins tests', env => {
const orders = [defaultOrder, defaultOrder];
const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
const transaction = await transactionFactory.newSignedTransactionAsync({ data });
const approval1 = await approvalFactory1.newSignedApprovalAsync(transaction, transactionSignerAddress);
const approval1 = approvalFactory1.newSignedApproval(transaction, transactionSignerAddress);
const tx = mixins
.assertValidCoordinatorApprovals(transaction, transactionSignerAddress, transaction.signature, [

View File

@@ -1,4 +1,18 @@
[
{
"version": "1.1.0",
"changes": [
{
"note": "Refactor mixins into public libraries.",
"pr": 2464
},
{
"note": "Remove `LibTransactionDecoder` export",
"pr": 2464
}
],
"timestamp": 1581204851
},
{
"timestamp": 1580988106,
"version": "1.0.6",

View File

@@ -5,6 +5,11 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.1.0 - _February 8, 2020_
* Refactor mixins into public libraries. (#2464)
* Remove `LibTransactionDecoder` export (#2464)
## v1.0.6 - _February 6, 2020_
* Dependencies updated

View File

@@ -0,0 +1,51 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
// solhint-disable no-empty-blocks
contract Addresses is
DeploymentConstants
{
address public exchangeAddress;
address public erc20ProxyAddress;
address public erc721ProxyAddress;
address public erc1155ProxyAddress;
address public staticCallProxyAddress;
address public chaiBridgeAddress;
constructor (
address exchange_,
address chaiBridge_
)
public
{
exchangeAddress = exchange_;
chaiBridgeAddress = chaiBridge_;
erc20ProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).ERC20Token.selector);
erc721ProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).ERC721Token.selector);
erc1155ProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).ERC1155Assets.selector);
staticCallProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).StaticCall.selector);
}
}

View File

@@ -0,0 +1,374 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IChai.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
import "./Addresses.sol";
import "./LibAssetData.sol";
contract AssetBalance is
Addresses
{
// 2^256 - 1
uint256 constant internal _MAX_UINT256 = uint256(-1);
using LibBytes for bytes;
/// @dev Returns the owner's balance of the assets(s) specified in
/// assetData. When the asset data contains multiple assets (eg in
/// ERC1155 or Multi-Asset), the return value indicates how many
/// complete "baskets" of those assets are owned by owner.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
/// @return Number of assets (or asset baskets) held by owner.
function getBalance(address ownerAddress, bytes memory assetData)
public
returns (uint256 balance)
{
// Get id of AssetProxy contract
bytes4 assetProxyId = assetData.readBytes4(0);
if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
// Get ERC20 token address
address tokenAddress = assetData.readAddress(16);
balance = LibERC20Token.balanceOf(tokenAddress, ownerAddress);
} else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
// Get ERC721 token address and id
(, address tokenAddress, uint256 tokenId) = LibAssetData.decodeERC721AssetData(assetData);
// Check if id is owned by ownerAddress
bytes memory ownerOfCalldata = abi.encodeWithSelector(
IERC721Token(address(0)).ownerOf.selector,
tokenId
);
(bool success, bytes memory returnData) = tokenAddress.staticcall(ownerOfCalldata);
address currentOwnerAddress = (success && returnData.length == 32) ? returnData.readAddress(12) : address(0);
balance = currentOwnerAddress == ownerAddress ? 1 : 0;
} else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
// Get ERC1155 token address, array of ids, and array of values
(, address tokenAddress, uint256[] memory tokenIds, uint256[] memory tokenValues,) = LibAssetData.decodeERC1155AssetData(assetData);
uint256 length = tokenIds.length;
for (uint256 i = 0; i != length; i++) {
// Skip over the token if the corresponding value is 0.
if (tokenValues[i] == 0) {
continue;
}
// Encode data for `balanceOf(ownerAddress, tokenIds[i])
bytes memory balanceOfData = abi.encodeWithSelector(
IERC1155(address(0)).balanceOf.selector,
ownerAddress,
tokenIds[i]
);
// Query balance
(bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
uint256 totalBalance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
// Scale total balance down by corresponding value in assetData
uint256 scaledBalance = totalBalance / tokenValues[i];
if (scaledBalance == 0) {
return 0;
}
if (scaledBalance < balance || balance == 0) {
balance = scaledBalance;
}
}
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
// Encode data for `staticCallProxy.transferFrom(assetData,...)`
bytes memory transferFromData = abi.encodeWithSelector(
IAssetProxy(address(0)).transferFrom.selector,
assetData,
address(0), // `from` address is not used
address(0), // `to` address is not used
0 // `amount` is not used
);
// Check if staticcall would be successful
(bool success,) = staticCallProxyAddress.staticcall(transferFromData);
// Success means that the staticcall can be made an unlimited amount of times
balance = success ? _MAX_UINT256 : 0;
} else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
// Get address of ERC20 token and bridge contract
(, address tokenAddress, address bridgeAddress, ) = LibAssetData.decodeERC20BridgeAssetData(assetData);
if (tokenAddress == _getDaiAddress() && bridgeAddress == chaiBridgeAddress) {
uint256 chaiBalance = LibERC20Token.balanceOf(_getChaiAddress(), ownerAddress);
// Calculate Dai balance
balance = _convertChaiToDaiAmount(chaiBalance);
}
// Balance will be 0 if bridge is not supported
} else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
// Get array of values and array of assetDatas
(, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = LibAssetData.decodeMultiAssetData(assetData);
uint256 length = nestedAssetData.length;
for (uint256 i = 0; i != length; i++) {
// Skip over the asset if the corresponding amount is 0.
if (assetAmounts[i] == 0) {
continue;
}
// Query balance of individual assetData
uint256 totalBalance = getBalance(ownerAddress, nestedAssetData[i]);
// Scale total balance down by corresponding value in assetData
uint256 scaledBalance = totalBalance / assetAmounts[i];
if (scaledBalance == 0) {
return 0;
}
if (scaledBalance < balance || balance == 0) {
balance = scaledBalance;
}
}
}
// Balance will be 0 if assetProxyId is unknown
return balance;
}
/// @dev Calls getBalance() for each element of assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
/// @return Array of asset balances from getBalance(), with each element
/// corresponding to the same-indexed element in the assetData input.
function getBatchBalances(address ownerAddress, bytes[] memory assetData)
public
returns (uint256[] memory balances)
{
uint256 length = assetData.length;
balances = new uint256[](length);
for (uint256 i = 0; i != length; i++) {
balances[i] = getBalance(ownerAddress, assetData[i]);
}
return balances;
}
/// @dev Returns the number of asset(s) (described by assetData) that
/// the corresponding AssetProxy contract is authorized to spend. When the asset data contains
/// multiple assets (eg for Multi-Asset), the return value indicates
/// how many complete "baskets" of those assets may be spent by all of the corresponding
/// AssetProxy contracts.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
/// @return Number of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
function getAssetProxyAllowance(address ownerAddress, bytes memory assetData)
public
returns (uint256 allowance)
{
// Get id of AssetProxy contract
bytes4 assetProxyId = assetData.readBytes4(0);
if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
// Get array of values and array of assetDatas
(, uint256[] memory amounts, bytes[] memory nestedAssetData) = LibAssetData.decodeMultiAssetData(assetData);
uint256 length = nestedAssetData.length;
for (uint256 i = 0; i != length; i++) {
// Skip over the asset if the corresponding amount is 0.
if (amounts[i] == 0) {
continue;
}
// Query allowance of individual assetData
uint256 totalAllowance = getAssetProxyAllowance(ownerAddress, nestedAssetData[i]);
// Scale total allowance down by corresponding value in assetData
uint256 scaledAllowance = totalAllowance / amounts[i];
if (scaledAllowance == 0) {
return 0;
}
if (scaledAllowance < allowance || allowance == 0) {
allowance = scaledAllowance;
}
}
return allowance;
}
if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
// Get ERC20 token address
address tokenAddress = assetData.readAddress(16);
allowance = LibERC20Token.allowance(tokenAddress, ownerAddress, erc20ProxyAddress);
} else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
// Get ERC721 token address and id
(, address tokenAddress, uint256 tokenId) = LibAssetData.decodeERC721AssetData(assetData);
// Encode data for `isApprovedForAll(ownerAddress, erc721ProxyAddress)`
bytes memory isApprovedForAllData = abi.encodeWithSelector(
IERC721Token(address(0)).isApprovedForAll.selector,
ownerAddress,
erc721ProxyAddress
);
(bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
// If not approved for all, call `getApproved(tokenId)`
if (!success || returnData.length != 32 || returnData.readUint256(0) != 1) {
// Encode data for `getApproved(tokenId)`
bytes memory getApprovedData = abi.encodeWithSelector(IERC721Token(address(0)).getApproved.selector, tokenId);
(success, returnData) = tokenAddress.staticcall(getApprovedData);
// Allowance is 1 if successful and the approved address is the ERC721Proxy
allowance = success && returnData.length == 32 && returnData.readAddress(12) == erc721ProxyAddress ? 1 : 0;
} else {
// Allowance is 2^256 - 1 if `isApprovedForAll` returned true
allowance = _MAX_UINT256;
}
} else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
// Get ERC1155 token address
(, address tokenAddress, , , ) = LibAssetData.decodeERC1155AssetData(assetData);
// Encode data for `isApprovedForAll(ownerAddress, erc1155ProxyAddress)`
bytes memory isApprovedForAllData = abi.encodeWithSelector(
IERC1155(address(0)).isApprovedForAll.selector,
ownerAddress,
erc1155ProxyAddress
);
// Query allowance
(bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
allowance = success && returnData.length == 32 && returnData.readUint256(0) == 1 ? _MAX_UINT256 : 0;
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
// The StaticCallProxy does not require any approvals
allowance = _MAX_UINT256;
} else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
// Get address of ERC20 token and bridge contract
(, address tokenAddress, address bridgeAddress,) = LibAssetData.decodeERC20BridgeAssetData(assetData);
if (tokenAddress == _getDaiAddress() && bridgeAddress == chaiBridgeAddress) {
uint256 chaiAllowance = LibERC20Token.allowance(_getChaiAddress(), ownerAddress, chaiBridgeAddress);
// Dai allowance is unlimited if Chai allowance is unlimited
allowance = chaiAllowance == _MAX_UINT256 ? _MAX_UINT256 : _convertChaiToDaiAmount(chaiAllowance);
}
// Allowance will be 0 if bridge is not supported
}
// Allowance will be 0 if the assetProxyId is unknown
return allowance;
}
/// @dev Calls getAssetProxyAllowance() for each element of assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
/// @return An array of asset allowances from getAllowance(), with each
/// element corresponding to the same-indexed element in the assetData input.
function getBatchAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
public
returns (uint256[] memory allowances)
{
uint256 length = assetData.length;
allowances = new uint256[](length);
for (uint256 i = 0; i != length; i++) {
allowances[i] = getAssetProxyAllowance(ownerAddress, assetData[i]);
}
return allowances;
}
/// @dev Calls getBalance() and getAllowance() for assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
/// @return Number of assets (or asset baskets) held by owner, and number
/// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
function getBalanceAndAssetProxyAllowance(
address ownerAddress,
bytes memory assetData
)
public
returns (uint256 balance, uint256 allowance)
{
balance = getBalance(ownerAddress, assetData);
allowance = getAssetProxyAllowance(ownerAddress, assetData);
return (balance, allowance);
}
/// @dev Calls getBatchBalances() and getBatchAllowances() for each element of assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
/// @return An array of asset balances from getBalance(), and an array of
/// asset allowances from getAllowance(), with each element
/// corresponding to the same-indexed element in the assetData input.
function getBatchBalancesAndAssetProxyAllowances(
address ownerAddress,
bytes[] memory assetData
)
public
returns (uint256[] memory balances, uint256[] memory allowances)
{
balances = getBatchBalances(ownerAddress, assetData);
allowances = getBatchAssetProxyAllowances(ownerAddress, assetData);
return (balances, allowances);
}
/// @dev Converts an amount of Chai into its equivalent Dai amount.
/// Also accumulates Dai from DSR if called after the last time it was collected.
/// @param chaiAmount Amount of Chai to converts.
function _convertChaiToDaiAmount(uint256 chaiAmount)
internal
returns (uint256 daiAmount)
{
PotLike pot = IChai(_getChaiAddress()).pot();
// Accumulate savings if called after last time savings were collected
// solhint-disable-next-line not-rely-on-time
uint256 chiMultiplier = (now > pot.rho())
? pot.drip()
: pot.chi();
daiAmount = LibMath.getPartialAmountFloor(chiMultiplier, 10**27, chaiAmount);
return daiAmount;
}
/// @dev Returns an order MAKER's balance of the assets(s) specified in
/// makerAssetData. Unlike `getBalanceAndAssetProxyAllowance()`, this
/// can handle maker asset types that depend on taker tokens being
/// transferred to the maker first.
/// @param order The order.
/// @return balance Quantity of assets transferrable from maker to taker.
function _getConvertibleMakerBalanceAndAssetProxyAllowance(
LibOrder.Order memory order
)
internal
returns (uint256 balance, uint256 allowance)
{
if (order.makerAssetData.length < 4) {
return (0, 0);
}
return (
getBalance(order.makerAddress, order.makerAssetData),
getAssetProxyAllowance(order.makerAddress, order.makerAssetData)
);
}
}

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.5;
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol";
@@ -24,27 +24,29 @@ import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol";
import "@0x/contracts-utils/contracts/src/LibEIP712.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "./Addresses.sol";
import "./OrderValidationUtils.sol";
import "./OrderTransferSimulationUtils.sol";
import "./EthBalanceChecker.sol";
import "./ExternalFunctions.sol";
// solhint-disable no-empty-blocks
contract DevUtils is
Addresses,
OrderValidationUtils,
LibEIP712ExchangeDomain,
EthBalanceChecker
EthBalanceChecker,
ExternalFunctions
{
constructor (
address _exchange,
address _chaiBridge
address exchange_,
address chaiBridge_
)
public
OrderValidationUtils(
_exchange,
_chaiBridge
Addresses(
exchange_,
chaiBridge_
)
OrderTransferSimulationUtils(_exchange)
LibEIP712ExchangeDomain(uint256(0), address(0)) // null args because because we only use constants
{}

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.5;
pragma solidity ^0.5.16;
contract EthBalanceChecker {

View File

@@ -0,0 +1,322 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
import "./Addresses.sol";
import "./LibAssetData.sol";
import "./LibTransactionDecoder.sol";
import "./LibOrderTransferSimulation.sol";
contract ExternalFunctions is
Addresses
{
/// @dev Decodes the call data for an Exchange contract method call.
/// @param transactionData ABI-encoded calldata for an Exchange
/// contract method call.
/// @return The name of the function called, and the parameters it was
/// given. For single-order fills and cancels, the arrays will have
/// just one element.
function decodeZeroExTransactionData(bytes memory transactionData)
public
pure
returns(
string memory functionName,
LibOrder.Order[] memory orders,
uint256[] memory takerAssetFillAmounts,
bytes[] memory signatures
)
{
return LibTransactionDecoder.decodeZeroExTransactionData(transactionData);
}
/// @dev Decode AssetProxy identifier
/// @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC-721, ERC1155, or MultiAsset asset.
/// @return The AssetProxy identifier
function decodeAssetProxyId(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId
)
{
return LibAssetData.decodeAssetProxyId(assetData);
}
/// @dev Encode ERC-20 asset data into the format described in the AssetProxy contract specification.
/// @param tokenAddress The address of the ERC-20 contract hosting the asset to be traded.
/// @return AssetProxy-compliant data describing the asset.
function encodeERC20AssetData(address tokenAddress)
public
pure
returns (bytes memory assetData)
{
return LibAssetData.encodeERC20AssetData(tokenAddress);
}
/// @dev Decode ERC-20 asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC-20 asset.
/// @return The AssetProxy identifier, and the address of the ERC-20
/// contract hosting this asset.
function decodeERC20AssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
address tokenAddress
)
{
return LibAssetData.decodeERC20AssetData(assetData);
}
/// @dev Encode ERC-721 asset data into the format described in the AssetProxy specification.
/// @param tokenAddress The address of the ERC-721 contract hosting the asset to be traded.
/// @param tokenId The identifier of the specific asset to be traded.
/// @return AssetProxy-compliant asset data describing the asset.
function encodeERC721AssetData(address tokenAddress, uint256 tokenId)
public
pure
returns (bytes memory assetData)
{
return LibAssetData.encodeERC721AssetData(tokenAddress, tokenId);
}
/// @dev Decode ERC-721 asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC-721 asset.
/// @return The ERC-721 AssetProxy identifier, the address of the ERC-721
/// contract hosting this asset, and the identifier of the specific
/// asset to be traded.
function decodeERC721AssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
address tokenAddress,
uint256 tokenId
)
{
return LibAssetData.decodeERC721AssetData(assetData);
}
/// @dev Encode ERC-1155 asset data into the format described in the AssetProxy contract specification.
/// @param tokenAddress The address of the ERC-1155 contract hosting the asset(s) to be traded.
/// @param tokenIds The identifiers of the specific assets to be traded.
/// @param tokenValues The amounts of each asset to be traded.
/// @param callbackData Data to be passed to receiving contracts when a transfer is performed.
/// @return AssetProxy-compliant asset data describing the set of assets.
function encodeERC1155AssetData(
address tokenAddress,
uint256[] memory tokenIds,
uint256[] memory tokenValues,
bytes memory callbackData
)
public
pure
returns (bytes memory assetData)
{
return LibAssetData.encodeERC1155AssetData(
tokenAddress,
tokenIds,
tokenValues,
callbackData
);
}
/// @dev Decode ERC-1155 asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC-1155 set of assets.
/// @return The ERC-1155 AssetProxy identifier, the address of the ERC-1155
/// contract hosting the assets, an array of the identifiers of the
/// assets to be traded, an array of asset amounts to be traded, and
/// callback data. Each element of the arrays corresponds to the
/// same-indexed element of the other array. Return values specified as
/// `memory` are returned as pointers to locations within the memory of
/// the input parameter `assetData`.
function decodeERC1155AssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
address tokenAddress,
uint256[] memory tokenIds,
uint256[] memory tokenValues,
bytes memory callbackData
)
{
return LibAssetData.decodeERC1155AssetData(assetData);
}
/// @dev Encode data for multiple assets, per the AssetProxy contract specification.
/// @param amounts The amounts of each asset to be traded.
/// @param nestedAssetData AssetProxy-compliant data describing each asset to be traded.
/// @return AssetProxy-compliant data describing the set of assets.
function encodeMultiAssetData(uint256[] memory amounts, bytes[] memory nestedAssetData)
public
pure
returns (bytes memory assetData)
{
return LibAssetData.encodeMultiAssetData(amounts, nestedAssetData);
}
/// @dev Decode multi-asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant data describing a multi-asset basket.
/// @return The Multi-Asset AssetProxy identifier, an array of the amounts
/// of the assets to be traded, and an array of the
/// AssetProxy-compliant data describing each asset to be traded. Each
/// element of the arrays corresponds to the same-indexed element of the other array.
function decodeMultiAssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
uint256[] memory amounts,
bytes[] memory nestedAssetData
)
{
return LibAssetData.decodeMultiAssetData(assetData);
}
/// @dev Encode StaticCall asset data into the format described in the AssetProxy contract specification.
/// @param staticCallTargetAddress Target address of StaticCall.
/// @param staticCallData Data that will be passed to staticCallTargetAddress in the StaticCall.
/// @param expectedReturnDataHash Expected Keccak-256 hash of the StaticCall return data.
/// @return AssetProxy-compliant asset data describing the set of assets.
function encodeStaticCallAssetData(
address staticCallTargetAddress,
bytes memory staticCallData,
bytes32 expectedReturnDataHash
)
public
pure
returns (bytes memory assetData)
{
return LibAssetData.encodeStaticCallAssetData(
staticCallTargetAddress,
staticCallData,
expectedReturnDataHash
);
}
/// @dev Decode StaticCall asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing a StaticCall asset
/// @return The StaticCall AssetProxy identifier, the target address of the StaticCAll, the data to be
/// passed to the target address, and the expected Keccak-256 hash of the static call return data.
function decodeStaticCallAssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
address staticCallTargetAddress,
bytes memory staticCallData,
bytes32 expectedReturnDataHash
)
{
return LibAssetData.decodeStaticCallAssetData(assetData);
}
/// @dev Decode ERC20Bridge asset data from the format described in the AssetProxy contract specification.
/// @param assetData AssetProxy-compliant asset data describing an ERC20Bridge asset
/// @return The ERC20BridgeProxy identifier, the address of the ERC20 token to transfer, the address
/// of the bridge contract, and extra data to be passed to the bridge contract.
function decodeERC20BridgeAssetData(bytes memory assetData)
public
pure
returns (
bytes4 assetProxyId,
address tokenAddress,
address bridgeAddress,
bytes memory bridgeData
)
{
return LibAssetData.decodeERC20BridgeAssetData(assetData);
}
/// @dev Reverts if assetData is not of a valid format for its given proxy id.
/// @param assetData AssetProxy compliant asset data.
function revertIfInvalidAssetData(bytes memory assetData)
public
pure
{
return LibAssetData.revertIfInvalidAssetData(assetData);
}
/// @dev Simulates the maker transfers within an order and returns the index of the first failed transfer.
/// @param order The order to simulate transfers for.
/// @param takerAddress The address of the taker that will fill the order.
/// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill.
/// @return The index of the first failed transfer (or 4 if all transfers are successful).
function getSimulatedOrderMakerTransferResults(
LibOrder.Order memory order,
address takerAddress,
uint256 takerAssetFillAmount
)
public
returns (LibOrderTransferSimulation.OrderTransferResults orderTransferResults)
{
return LibOrderTransferSimulation.getSimulatedOrderMakerTransferResults(
exchangeAddress,
order,
takerAddress,
takerAssetFillAmount
);
}
/// @dev Simulates all of the transfers within an order and returns the index of the first failed transfer.
/// @param order The order to simulate transfers for.
/// @param takerAddress The address of the taker that will fill the order.
/// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill.
/// @return The index of the first failed transfer (or 4 if all transfers are successful).
function getSimulatedOrderTransferResults(
LibOrder.Order memory order,
address takerAddress,
uint256 takerAssetFillAmount
)
public
returns (LibOrderTransferSimulation.OrderTransferResults orderTransferResults)
{
return LibOrderTransferSimulation.getSimulatedOrderTransferResults(
exchangeAddress,
order,
takerAddress,
takerAssetFillAmount
);
}
/// @dev Simulates all of the transfers for each given order and returns the indices of each first failed transfer.
/// @param orders Array of orders to individually simulate transfers for.
/// @param takerAddresses Array of addresses of takers that will fill each order.
/// @param takerAssetFillAmounts Array of amounts of takerAsset that will be filled for each order.
/// @return The indices of the first failed transfer (or 4 if all transfers are successful) for each order.
function getSimulatedOrdersTransferResults(
LibOrder.Order[] memory orders,
address[] memory takerAddresses,
uint256[] memory takerAssetFillAmounts
)
public
returns (LibOrderTransferSimulation.OrderTransferResults[] memory orderTransferResults)
{
return LibOrderTransferSimulation.getSimulatedOrdersTransferResults(
exchangeAddress,
orders,
takerAddresses,
takerAssetFillAmounts
);
}
}

View File

@@ -16,357 +16,17 @@
*/
pragma solidity ^0.5.5;
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IChai.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
contract LibAssetData is
DeploymentConstants
{
// 2^256 - 1
uint256 constant internal _MAX_UINT256 = uint256(-1);
library LibAssetData {
using LibBytes for bytes;
// solhint-disable var-name-mixedcase
IExchange internal _EXCHANGE;
address internal _ERC20_PROXY_ADDRESS;
address internal _ERC721_PROXY_ADDRESS;
address internal _ERC1155_PROXY_ADDRESS;
address internal _STATIC_CALL_PROXY_ADDRESS;
address internal _CHAI_BRIDGE_ADDRESS;
// solhint-enable var-name-mixedcase
constructor (
address _exchange,
address _chaiBridge
)
public
{
_EXCHANGE = IExchange(_exchange);
_ERC20_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC20Token.selector);
_ERC721_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC721Token.selector);
_ERC1155_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC1155Assets.selector);
_STATIC_CALL_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).StaticCall.selector);
_CHAI_BRIDGE_ADDRESS = _chaiBridge;
}
/// @dev Returns the owner's balance of the assets(s) specified in
/// assetData. When the asset data contains multiple assets (eg in
/// ERC1155 or Multi-Asset), the return value indicates how many
/// complete "baskets" of those assets are owned by owner.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
/// @return Number of assets (or asset baskets) held by owner.
function getBalance(address ownerAddress, bytes memory assetData)
public
returns (uint256 balance)
{
// Get id of AssetProxy contract
bytes4 assetProxyId = assetData.readBytes4(0);
if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
// Get ERC20 token address
address tokenAddress = assetData.readAddress(16);
balance = _erc20BalanceOf(tokenAddress, ownerAddress);
} else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
// Get ERC721 token address and id
(, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
// Check if id is owned by ownerAddress
bytes memory ownerOfCalldata = abi.encodeWithSelector(
IERC721Token(address(0)).ownerOf.selector,
tokenId
);
(bool success, bytes memory returnData) = tokenAddress.staticcall(ownerOfCalldata);
address currentOwnerAddress = (success && returnData.length == 32) ? returnData.readAddress(12) : address(0);
balance = currentOwnerAddress == ownerAddress ? 1 : 0;
} else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
// Get ERC1155 token address, array of ids, and array of values
(, address tokenAddress, uint256[] memory tokenIds, uint256[] memory tokenValues,) = decodeERC1155AssetData(assetData);
uint256 length = tokenIds.length;
for (uint256 i = 0; i != length; i++) {
// Skip over the token if the corresponding value is 0.
if (tokenValues[i] == 0) {
continue;
}
// Encode data for `balanceOf(ownerAddress, tokenIds[i])
bytes memory balanceOfData = abi.encodeWithSelector(
IERC1155(address(0)).balanceOf.selector,
ownerAddress,
tokenIds[i]
);
// Query balance
(bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
uint256 totalBalance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
// Scale total balance down by corresponding value in assetData
uint256 scaledBalance = totalBalance / tokenValues[i];
if (scaledBalance == 0) {
return 0;
}
if (scaledBalance < balance || balance == 0) {
balance = scaledBalance;
}
}
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
// Encode data for `staticCallProxy.transferFrom(assetData,...)`
bytes memory transferFromData = abi.encodeWithSelector(
IAssetProxy(address(0)).transferFrom.selector,
assetData,
address(0), // `from` address is not used
address(0), // `to` address is not used
0 // `amount` is not used
);
// Check if staticcall would be successful
(bool success,) = _STATIC_CALL_PROXY_ADDRESS.staticcall(transferFromData);
// Success means that the staticcall can be made an unlimited amount of times
balance = success ? _MAX_UINT256 : 0;
} else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
// Get address of ERC20 token and bridge contract
(, address tokenAddress, address bridgeAddress,) = decodeERC20BridgeAssetData(assetData);
if (tokenAddress == _getDaiAddress() && bridgeAddress == _CHAI_BRIDGE_ADDRESS) {
uint256 chaiBalance = _erc20BalanceOf(_getChaiAddress(), ownerAddress);
// Calculate Dai balance
balance = _convertChaiToDaiAmount(chaiBalance);
}
// Balance will be 0 if bridge is not supported
} else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
// Get array of values and array of assetDatas
(, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
uint256 length = nestedAssetData.length;
for (uint256 i = 0; i != length; i++) {
// Skip over the asset if the corresponding amount is 0.
if (assetAmounts[i] == 0) {
continue;
}
// Query balance of individual assetData
uint256 totalBalance = getBalance(ownerAddress, nestedAssetData[i]);
// Scale total balance down by corresponding value in assetData
uint256 scaledBalance = totalBalance / assetAmounts[i];
if (scaledBalance == 0) {
return 0;
}
if (scaledBalance < balance || balance == 0) {
balance = scaledBalance;
}
}
}
// Balance will be 0 if assetProxyId is unknown
return balance;
}
/// @dev Calls getBalance() for each element of assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
/// @return Array of asset balances from getBalance(), with each element
/// corresponding to the same-indexed element in the assetData input.
function getBatchBalances(address ownerAddress, bytes[] memory assetData)
public
returns (uint256[] memory balances)
{
uint256 length = assetData.length;
balances = new uint256[](length);
for (uint256 i = 0; i != length; i++) {
balances[i] = getBalance(ownerAddress, assetData[i]);
}
return balances;
}
/// @dev Returns the number of asset(s) (described by assetData) that
/// the corresponding AssetProxy contract is authorized to spend. When the asset data contains
/// multiple assets (eg for Multi-Asset), the return value indicates
/// how many complete "baskets" of those assets may be spent by all of the corresponding
/// AssetProxy contracts.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
/// @return Number of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
function getAssetProxyAllowance(address ownerAddress, bytes memory assetData)
public
returns (uint256 allowance)
{
// Get id of AssetProxy contract
bytes4 assetProxyId = assetData.readBytes4(0);
if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
// Get array of values and array of assetDatas
(, uint256[] memory amounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
uint256 length = nestedAssetData.length;
for (uint256 i = 0; i != length; i++) {
// Skip over the asset if the corresponding amount is 0.
if (amounts[i] == 0) {
continue;
}
// Query allowance of individual assetData
uint256 totalAllowance = getAssetProxyAllowance(ownerAddress, nestedAssetData[i]);
// Scale total allowance down by corresponding value in assetData
uint256 scaledAllowance = totalAllowance / amounts[i];
if (scaledAllowance == 0) {
return 0;
}
if (scaledAllowance < allowance || allowance == 0) {
allowance = scaledAllowance;
}
}
return allowance;
}
if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
// Get ERC20 token address
address tokenAddress = assetData.readAddress(16);
// Encode data for `allowance(ownerAddress, _ERC20_PROXY_ADDRESS)`
bytes memory allowanceData = abi.encodeWithSelector(
IERC20Token(address(0)).allowance.selector,
ownerAddress,
_ERC20_PROXY_ADDRESS
);
// Query allowance
(bool success, bytes memory returnData) = tokenAddress.staticcall(allowanceData);
allowance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
} else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
// Get ERC721 token address and id
(, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
// Encode data for `isApprovedForAll(ownerAddress, _ERC721_PROXY_ADDRESS)`
bytes memory isApprovedForAllData = abi.encodeWithSelector(
IERC721Token(address(0)).isApprovedForAll.selector,
ownerAddress,
_ERC721_PROXY_ADDRESS
);
(bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
// If not approved for all, call `getApproved(tokenId)`
if (!success || returnData.length != 32 || returnData.readUint256(0) != 1) {
// Encode data for `getApproved(tokenId)`
bytes memory getApprovedData = abi.encodeWithSelector(IERC721Token(address(0)).getApproved.selector, tokenId);
(success, returnData) = tokenAddress.staticcall(getApprovedData);
// Allowance is 1 if successful and the approved address is the ERC721Proxy
allowance = success && returnData.length == 32 && returnData.readAddress(12) == _ERC721_PROXY_ADDRESS ? 1 : 0;
} else {
// Allowance is 2^256 - 1 if `isApprovedForAll` returned true
allowance = _MAX_UINT256;
}
} else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
// Get ERC1155 token address
(, address tokenAddress, , , ) = decodeERC1155AssetData(assetData);
// Encode data for `isApprovedForAll(ownerAddress, _ERC1155_PROXY_ADDRESS)`
bytes memory isApprovedForAllData = abi.encodeWithSelector(
IERC1155(address(0)).isApprovedForAll.selector,
ownerAddress,
_ERC1155_PROXY_ADDRESS
);
// Query allowance
(bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
allowance = success && returnData.length == 32 && returnData.readUint256(0) == 1 ? _MAX_UINT256 : 0;
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
// The StaticCallProxy does not require any approvals
allowance = _MAX_UINT256;
} else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
// Get address of ERC20 token and bridge contract
(, address tokenAddress, address bridgeAddress,) = decodeERC20BridgeAssetData(assetData);
if (tokenAddress == _getDaiAddress() && bridgeAddress == _CHAI_BRIDGE_ADDRESS) {
bytes memory allowanceData = abi.encodeWithSelector(
IERC20Token(address(0)).allowance.selector,
ownerAddress,
_CHAI_BRIDGE_ADDRESS
);
(bool success, bytes memory returnData) = _getChaiAddress().staticcall(allowanceData);
uint256 chaiAllowance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
// Dai allowance is unlimited if Chai allowance is unlimited
allowance = chaiAllowance == _MAX_UINT256 ? _MAX_UINT256 : _convertChaiToDaiAmount(chaiAllowance);
}
// Allowance will be 0 if bridge is not supported
}
// Allowance will be 0 if the assetProxyId is unknown
return allowance;
}
/// @dev Calls getAssetProxyAllowance() for each element of assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
/// @return An array of asset allowances from getAllowance(), with each
/// element corresponding to the same-indexed element in the assetData input.
function getBatchAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
public
returns (uint256[] memory allowances)
{
uint256 length = assetData.length;
allowances = new uint256[](length);
for (uint256 i = 0; i != length; i++) {
allowances[i] = getAssetProxyAllowance(ownerAddress, assetData[i]);
}
return allowances;
}
/// @dev Calls getBalance() and getAllowance() for assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
/// @return Number of assets (or asset baskets) held by owner, and number
/// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
function getBalanceAndAssetProxyAllowance(address ownerAddress, bytes memory assetData)
public
returns (uint256 balance, uint256 allowance)
{
balance = getBalance(ownerAddress, assetData);
allowance = getAssetProxyAllowance(ownerAddress, assetData);
return (balance, allowance);
}
/// @dev Calls getBatchBalances() and getBatchAllowances() for each element of assetData.
/// @param ownerAddress Owner of the assets specified by assetData.
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
/// @return An array of asset balances from getBalance(), and an array of
/// asset allowances from getAllowance(), with each element
/// corresponding to the same-indexed element in the assetData input.
function getBatchBalancesAndAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
public
returns (uint256[] memory balances, uint256[] memory allowances)
{
balances = getBatchBalances(ownerAddress, assetData);
allowances = getBatchAssetProxyAllowances(ownerAddress, assetData);
return (balances, allowances);
}
/// @dev Decode AssetProxy identifier
/// @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC-721, ERC1155, or MultiAsset asset.
/// @return The AssetProxy identifier
@@ -691,44 +351,4 @@ contract LibAssetData is
revert("WRONG_PROXY_ID");
}
}
/// @dev Queries balance of an ERC20 token. Returns 0 if call was unsuccessful.
/// @param tokenAddress Address of ERC20 token.
/// @param ownerAddress Address of owner of ERC20 token.
/// @return balance ERC20 token balance of owner.
function _erc20BalanceOf(
address tokenAddress,
address ownerAddress
)
internal
view
returns (uint256 balance)
{
// Encode data for `balanceOf(ownerAddress)`
bytes memory balanceOfData = abi.encodeWithSelector(
IERC20Token(address(0)).balanceOf.selector,
ownerAddress
);
// Query balance
(bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
balance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
return balance;
}
/// @dev Converts an amount of Chai into its equivalent Dai amount.
/// Also accumulates Dai from DSR if called after the last time it was collected.
/// @param chaiAmount Amount of Chai to converts.
function _convertChaiToDaiAmount(uint256 chaiAmount)
internal
returns (uint256 daiAmount)
{
PotLike pot = IChai(_getChaiAddress()).pot();
// Accumulate savings if called after last time savings were collected
uint256 chiMultiplier = (now > pot.rho())
? pot.drip()
: pot.chi();
daiAmount = LibMath.getPartialAmountFloor(chiMultiplier, 10**27, chaiAmount);
return daiAmount;
}
}

View File

@@ -0,0 +1,227 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-exchange/contracts/src/libs/LibExchangeRichErrorDecoder.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibExchangeRichErrors.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
library LibOrderTransferSimulation {
using LibBytes for bytes;
enum OrderTransferResults {
TakerAssetDataFailed, // Transfer of takerAsset failed
MakerAssetDataFailed, // Transfer of makerAsset failed
TakerFeeAssetDataFailed, // Transfer of takerFeeAsset failed
MakerFeeAssetDataFailed, // Transfer of makerFeeAsset failed
TransfersSuccessful // All transfers in the order were successful
}
// NOTE(jalextowle): This is a random address that we use to avoid issues that addresses like `address(1)`
// may cause later.
address constant internal UNUSED_ADDRESS = address(0x377f698C4c287018D09b516F415317aEC5919332);
// keccak256(abi.encodeWithSignature("Error(string)", "TRANSFERS_SUCCESSFUL"));
bytes32 constant internal _TRANSFERS_SUCCESSFUL_RESULT_HASH = 0xf43f26ea5a94b478394a975e856464913dc1a8a1ca70939d974aa7c238aa0ce0;
/// @dev Simulates the maker transfers within an order and returns the index of the first failed transfer.
/// @param order The order to simulate transfers for.
/// @param takerAddress The address of the taker that will fill the order.
/// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill.
/// @return The index of the first failed transfer (or 4 if all transfers are successful).
function getSimulatedOrderMakerTransferResults(
address exchange,
LibOrder.Order memory order,
address takerAddress,
uint256 takerAssetFillAmount
)
public
returns (OrderTransferResults orderTransferResults)
{
LibFillResults.FillResults memory fillResults = LibFillResults.calculateFillResults(
order,
takerAssetFillAmount,
IExchange(exchange).protocolFeeMultiplier(),
tx.gasprice
);
bytes[] memory assetData = new bytes[](2);
address[] memory fromAddresses = new address[](2);
address[] memory toAddresses = new address[](2);
uint256[] memory amounts = new uint256[](2);
// Transfer `makerAsset` from maker to taker
assetData[0] = order.makerAssetData;
fromAddresses[0] = order.makerAddress;
toAddresses[0] = takerAddress == address(0) ? UNUSED_ADDRESS : takerAddress;
amounts[0] = fillResults.makerAssetFilledAmount;
// Transfer `makerFeeAsset` from maker to feeRecipient
assetData[1] = order.makerFeeAssetData;
fromAddresses[1] = order.makerAddress;
toAddresses[1] = order.feeRecipientAddress == address(0) ? UNUSED_ADDRESS : order.feeRecipientAddress;
amounts[1] = fillResults.makerFeePaid;
return _simulateTransferFromCalls(
exchange,
assetData,
fromAddresses,
toAddresses,
amounts
);
}
/// @dev Simulates all of the transfers within an order and returns the index of the first failed transfer.
/// @param order The order to simulate transfers for.
/// @param takerAddress The address of the taker that will fill the order.
/// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill.
/// @return The index of the first failed transfer (or 4 if all transfers are successful).
function getSimulatedOrderTransferResults(
address exchange,
LibOrder.Order memory order,
address takerAddress,
uint256 takerAssetFillAmount
)
public
returns (OrderTransferResults orderTransferResults)
{
LibFillResults.FillResults memory fillResults = LibFillResults.calculateFillResults(
order,
takerAssetFillAmount,
IExchange(exchange).protocolFeeMultiplier(),
tx.gasprice
);
// Create input arrays
bytes[] memory assetData = new bytes[](4);
address[] memory fromAddresses = new address[](4);
address[] memory toAddresses = new address[](4);
uint256[] memory amounts = new uint256[](4);
// Transfer `takerAsset` from taker to maker
assetData[0] = order.takerAssetData;
fromAddresses[0] = takerAddress;
toAddresses[0] = order.makerAddress;
amounts[0] = takerAssetFillAmount;
// Transfer `makerAsset` from maker to taker
assetData[1] = order.makerAssetData;
fromAddresses[1] = order.makerAddress;
toAddresses[1] = takerAddress == address(0) ? UNUSED_ADDRESS : takerAddress;
amounts[1] = fillResults.makerAssetFilledAmount;
// Transfer `takerFeeAsset` from taker to feeRecipient
assetData[2] = order.takerFeeAssetData;
fromAddresses[2] = takerAddress;
toAddresses[2] = order.feeRecipientAddress == address(0) ? UNUSED_ADDRESS : order.feeRecipientAddress;
amounts[2] = fillResults.takerFeePaid;
// Transfer `makerFeeAsset` from maker to feeRecipient
assetData[3] = order.makerFeeAssetData;
fromAddresses[3] = order.makerAddress;
toAddresses[3] = order.feeRecipientAddress == address(0) ? UNUSED_ADDRESS : order.feeRecipientAddress;
amounts[3] = fillResults.makerFeePaid;
return _simulateTransferFromCalls(
exchange,
assetData,
fromAddresses,
toAddresses,
amounts
);
}
/// @dev Simulates all of the transfers for each given order and returns the indices of each first failed transfer.
/// @param orders Array of orders to individually simulate transfers for.
/// @param takerAddresses Array of addresses of takers that will fill each order.
/// @param takerAssetFillAmounts Array of amounts of takerAsset that will be filled for each order.
/// @return The indices of the first failed transfer (or 4 if all transfers are successful) for each order.
function getSimulatedOrdersTransferResults(
address exchange,
LibOrder.Order[] memory orders,
address[] memory takerAddresses,
uint256[] memory takerAssetFillAmounts
)
public
returns (OrderTransferResults[] memory orderTransferResults)
{
uint256 length = orders.length;
orderTransferResults = new OrderTransferResults[](length);
for (uint256 i = 0; i != length; i++) {
orderTransferResults[i] = getSimulatedOrderTransferResults(
exchange,
orders[i],
takerAddresses[i],
takerAssetFillAmounts[i]
);
}
return orderTransferResults;
}
/// @dev Makes the simulation call with information about the transfers and processes
/// the returndata.
/// @param assetData The assetdata to use to make transfers.
/// @param fromAddresses The addresses to transfer funds.
/// @param toAddresses The addresses that will receive funds
/// @param amounts The amounts involved in the transfer.
function _simulateTransferFromCalls(
address exchange,
bytes[] memory assetData,
address[] memory fromAddresses,
address[] memory toAddresses,
uint256[] memory amounts
)
private
returns (OrderTransferResults orderTransferResults)
{
// Encode data for `simulateDispatchTransferFromCalls(assetData, fromAddresses, toAddresses, amounts)`
bytes memory simulateDispatchTransferFromCallsData = abi.encodeWithSelector(
IExchange(address(0)).simulateDispatchTransferFromCalls.selector,
assetData,
fromAddresses,
toAddresses,
amounts
);
// Perform call and catch revert
(, bytes memory returnData) = address(exchange).call(simulateDispatchTransferFromCallsData);
bytes4 selector = returnData.readBytes4(0);
if (selector == LibExchangeRichErrors.AssetProxyDispatchErrorSelector()) {
// Decode AssetProxyDispatchError and return index of failed transfer
(, bytes32 failedTransferIndex,) = LibExchangeRichErrorDecoder.decodeAssetProxyDispatchError(returnData);
return OrderTransferResults(uint8(uint256(failedTransferIndex)));
} else if (selector == LibExchangeRichErrors.AssetProxyTransferErrorSelector()) {
// Decode AssetProxyTransferError and return index of failed transfer
(bytes32 failedTransferIndex, ,) = LibExchangeRichErrorDecoder.decodeAssetProxyTransferError(returnData);
return OrderTransferResults(uint8(uint256(failedTransferIndex)));
} else if (keccak256(returnData) == _TRANSFERS_SUCCESSFUL_RESULT_HASH) {
// All transfers were successful
return OrderTransferResults.TransfersSuccessful;
} else {
revert("UNKNOWN_RETURN_DATA");
}
}
}

View File

@@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.5;
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
@@ -24,7 +24,7 @@ import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
contract LibTransactionDecoder {
library LibTransactionDecoder {
using LibBytes for bytes;

View File

@@ -28,9 +28,8 @@ import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
contract OrderTransferSimulationUtils is
LibExchangeRichErrorDecoder
{
contract OrderTransferSimulationUtils {
using LibBytes for bytes;
enum OrderTransferResults {
@@ -216,11 +215,13 @@ contract OrderTransferSimulationUtils is
bytes4 selector = returnData.readBytes4(0);
if (selector == LibExchangeRichErrors.AssetProxyDispatchErrorSelector()) {
// Decode AssetProxyDispatchError and return index of failed transfer
(, bytes32 failedTransferIndex,) = decodeAssetProxyDispatchError(returnData);
(, bytes32 failedTransferIndex,) = LibExchangeRichErrorDecoder
.decodeAssetProxyDispatchError(returnData);
return OrderTransferResults(uint8(uint256(failedTransferIndex)));
} else if (selector == LibExchangeRichErrors.AssetProxyTransferErrorSelector()) {
// Decode AssetProxyTransferError and return index of failed transfer
(bytes32 failedTransferIndex, ,) = decodeAssetProxyTransferError(returnData);
(bytes32 failedTransferIndex, ,) = LibExchangeRichErrorDecoder
.decodeAssetProxyTransferError(returnData);
return OrderTransferResults(uint8(uint256(failedTransferIndex)));
} else if (keccak256(returnData) == _TRANSFERS_SUCCESSFUL_RESULT_HASH) {
// All transfers were successful

View File

@@ -16,36 +16,26 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.5.16;
pragma experimental ABIEncoderV2;
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "./Addresses.sol";
import "./AssetBalance.sol";
import "./LibAssetData.sol";
import "./OrderTransferSimulationUtils.sol";
import "./LibOrderTransferSimulation.sol";
contract OrderValidationUtils is
LibAssetData,
OrderTransferSimulationUtils
Addresses,
AssetBalance
{
using LibBytes for bytes;
using LibSafeMath for uint256;
constructor (
address _exchange,
address _chaiBridge
)
public
LibAssetData(
_exchange,
_chaiBridge
)
{}
/// @dev Fetches all order-relevant information needed to validate if the supplied order is fillable.
/// @param order The order structure.
/// @param signature Signature provided by maker that proves the order's authenticity.
@@ -65,23 +55,22 @@ contract OrderValidationUtils is
)
{
// Get info specific to order
orderInfo = _EXCHANGE.getOrderInfo(order);
orderInfo = IExchange(exchangeAddress).getOrderInfo(order);
// Validate the maker's signature
address makerAddress = order.makerAddress;
isValidSignature = _EXCHANGE.isValidOrderSignature(
isValidSignature = IExchange(exchangeAddress).isValidOrderSignature(
order,
signature
);
// Get the transferable amount of the `makerAsset`
uint256 transferableMakerAssetAmount = getTransferableAssetAmount(makerAddress, order.makerAssetData);
uint256 transferableMakerAssetAmount = _getTransferableConvertedMakerAssetAmount(
order
);
// Assign to stack variables to reduce redundant mloads/sloads
uint256 takerAssetAmount = order.takerAssetAmount;
uint256 makerFee = order.makerFee;
// Get the amount of `takerAsset` that is transferable to maker given the transferability of `makerAsset`, `makerFeeAsset`,
// Get the amount of `takerAsset` that is transferable to maker given the
// transferability of `makerAsset`, `makerFeeAsset`,
// and the total amounts specified in the order
uint256 transferableTakerAssetAmount;
if (order.makerAssetData.equals(order.makerFeeAssetData)) {
@@ -89,32 +78,35 @@ contract OrderValidationUtils is
// transferableMakerAssetAmount / (makerAssetAmount + makerFee)
transferableTakerAssetAmount = LibMath.getPartialAmountFloor(
transferableMakerAssetAmount,
order.makerAssetAmount.safeAdd(makerFee),
takerAssetAmount
order.makerAssetAmount.safeAdd(order.makerFee),
order.takerAssetAmount
);
} else {
// If `makerFee` is 0, the % that can be filled is (transferableMakerAssetAmount / makerAssetAmount)
if (makerFee == 0) {
if (order.makerFee == 0) {
transferableTakerAssetAmount = LibMath.getPartialAmountFloor(
transferableMakerAssetAmount,
order.makerAssetAmount,
takerAssetAmount
order.takerAssetAmount
);
// If `makerAsset` does not equal `makerFeeAsset`, the % that can be filled is the lower of
// (transferableMakerAssetAmount / makerAssetAmount) and (transferableMakerAssetFeeAmount / makerFee)
} else {
// Get the transferable amount of the `makerFeeAsset`
uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount(makerAddress, order.makerFeeAssetData);
uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount(
makerAddress,
order.makerFeeAssetData
);
uint256 transferableMakerToTakerAmount = LibMath.getPartialAmountFloor(
transferableMakerAssetAmount,
order.makerAssetAmount,
takerAssetAmount
order.takerAssetAmount
);
uint256 transferableMakerFeeToTakerAmount = LibMath.getPartialAmountFloor(
transferableMakerFeeAssetAmount,
makerFee,
takerAssetAmount
order.makerFee,
order.takerAssetAmount
);
transferableTakerAssetAmount = LibSafeMath.min256(transferableMakerToTakerAmount, transferableMakerFeeToTakerAmount);
}
@@ -122,16 +114,17 @@ contract OrderValidationUtils is
// `fillableTakerAssetAmount` is the lower of the order's remaining `takerAssetAmount` and the `transferableTakerAssetAmount`
fillableTakerAssetAmount = LibSafeMath.min256(
takerAssetAmount.safeSub(orderInfo.orderTakerAssetFilledAmount),
order.takerAssetAmount.safeSub(orderInfo.orderTakerAssetFilledAmount),
transferableTakerAssetAmount
);
// Execute the maker transfers.
fillableTakerAssetAmount = getSimulatedOrderMakerTransferResults(
fillableTakerAssetAmount = LibOrderTransferSimulation.getSimulatedOrderMakerTransferResults(
exchangeAddress,
order,
order.takerAddress,
fillableTakerAssetAmount
) == OrderTransferResults.TransfersSuccessful ? fillableTakerAssetAmount : 0;
) == LibOrderTransferSimulation.OrderTransferResults.TransfersSuccessful ? fillableTakerAssetAmount : 0;
if (!_isAssetDataValid(order.takerAssetData)) {
fillableTakerAssetAmount = 0;
@@ -181,7 +174,7 @@ contract OrderValidationUtils is
return (ordersInfo, fillableTakerAssetAmounts, isValidSignature);
}
/// @dev Gets the amount of an asset transferable by the owner.
/// @dev Gets the amount of an asset transferable by the maker of an order.
/// @param ownerAddress Address of the owner of the asset.
/// @param assetData Description of tokens, per the AssetProxy contract specification.
/// @return The amount of the asset tranferable by the owner.
@@ -193,7 +186,26 @@ contract OrderValidationUtils is
public
returns (uint256 transferableAssetAmount)
{
(uint256 balance, uint256 allowance) = getBalanceAndAssetProxyAllowance(ownerAddress, assetData);
(uint256 balance, uint256 allowance) = getBalanceAndAssetProxyAllowance(
ownerAddress,
assetData
);
transferableAssetAmount = LibSafeMath.min256(balance, allowance);
return transferableAssetAmount;
}
/// @dev Gets the amount of an asset transferable by the maker of an order.
/// Similar to `getTransferableAssetAmount()`, but can handle maker asset
/// types that depend on taker assets being transferred first (e.g., Dydx bridge).
/// @param order The order.
/// @return transferableAssetAmount Amount of maker asset that can be transferred.
function _getTransferableConvertedMakerAssetAmount(
LibOrder.Order memory order
)
internal
returns (uint256 transferableAssetAmount)
{
(uint256 balance, uint256 allowance) = _getConvertibleMakerBalanceAndAssetProxyAllowance(order);
transferableAssetAmount = LibSafeMath.min256(balance, allowance);
return transferableAssetAmount;
}
@@ -221,7 +233,8 @@ contract OrderValidationUtils is
}
// Get array of values and array of assetDatas
(, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
(, , bytes[] memory nestedAssetData) =
LibAssetData.decodeMultiAssetData(assetData);
uint256 length = nestedAssetData.length;
for (uint256 i = 0; i != length; i++) {

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-dev-utils",
"version": "1.0.6",
"version": "1.1.0",
"engines": {
"node": ">=6.12"
},
@@ -8,7 +8,7 @@
"main": "lib/src/index.js",
"scripts": {
"build": "yarn pre_build && tsc -b",
"test": "yarn assert_deployable && echo !!! Tests are run via @0x/contracts-integrations !!!",
"test": "yarn assert_deployable",
"assert_deployable": "node -e \"const bytecodeLen = (require('./generated-artifacts/DevUtils.json').compilerOutput.evm.bytecode.object.length-2)/2; assert(bytecodeLen<=0x6000,'DevUtils contract is too big to deploy, per EIP-170. '+bytecodeLen+'>'+0x6000)\"",
"build:ci": "yarn build",
"pre_build": "run-s compile quantify_bytecode contracts:gen generate_contract_wrappers contracts:copy",
@@ -27,8 +27,8 @@
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
},
"config": {
"publicInterfaceContracts": "DevUtils,LibAssetData,LibTransactionDecoder",
"abis": "./test/generated-artifacts/@(DevUtils|EthBalanceChecker|LibAssetData|LibTransactionDecoder|OrderTransferSimulationUtils|OrderValidationUtils).json",
"publicInterfaceContracts": "DevUtils,LibAssetData,LibOrderTransferSimulation,LibTransactionDecoder",
"abis": "./test/generated-artifacts/@(Addresses|AssetBalance|DevUtils|EthBalanceChecker|ExternalFunctions|LibAssetData|LibOrderTransferSimulation|LibTransactionDecoder|OrderTransferSimulationUtils|OrderValidationUtils).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
},
"repository": {
@@ -41,14 +41,19 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/dev-utils/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/assert": "^3.0.5",
"@0x/contracts-gen": "^2.0.6",
"@0x/sol-compiler": "^4.0.6",
"@0x/abi-gen": "^5.2.0",
"@0x/assert": "^3.0.6",
"@0x/contracts-asset-proxy": "^3.2.0",
"@0x/contracts-erc20": "^3.1.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/sol-compiler": "^4.0.7",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.2",
"@0x/utils": "^5.4.0",
"@types/node": "*",
"ethereum-types": "^3.0.0",
"ethereum-types": "^3.1.0",
"ethers": "~4.0.4",
"npm-run-all": "^4.1.2",
"shx": "^0.2.2",
@@ -59,7 +64,7 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.1.2"
"@0x/base-contract": "^6.2.0"
},
"publishConfig": {
"access": "public"

View File

@@ -7,9 +7,11 @@ import { ContractArtifact } from 'ethereum-types';
import * as DevUtils from '../generated-artifacts/DevUtils.json';
import * as LibAssetData from '../generated-artifacts/LibAssetData.json';
import * as LibOrderTransferSimulation from '../generated-artifacts/LibOrderTransferSimulation.json';
import * as LibTransactionDecoder from '../generated-artifacts/LibTransactionDecoder.json';
export const artifacts = {
DevUtils: DevUtils as ContractArtifact,
LibAssetData: LibAssetData as ContractArtifact,
LibOrderTransferSimulation: LibOrderTransferSimulation as ContractArtifact,
LibTransactionDecoder: LibTransactionDecoder as ContractArtifact,
};

View File

@@ -1,5 +1,5 @@
export { artifacts } from './artifacts';
export { DevUtilsContract, LibAssetDataContract, LibTransactionDecoderContract } from './wrappers';
export { DevUtilsContract } from './wrappers';
export {
ContractArtifact,
ContractChains,
@@ -15,6 +15,7 @@ export {
OutputField,
ParamDescription,
EvmBytecodeOutput,
EvmBytecodeOutputLinkReferences,
AbiDefinition,
FunctionAbi,
EventAbi,

View File

@@ -5,4 +5,5 @@
*/
export * from '../generated-wrappers/dev_utils';
export * from '../generated-wrappers/lib_asset_data';
export * from '../generated-wrappers/lib_order_transfer_simulation';
export * from '../generated-wrappers/lib_transaction_decoder';

View File

@@ -5,16 +5,24 @@
*/
import { ContractArtifact } from 'ethereum-types';
import * as Addresses from '../test/generated-artifacts/Addresses.json';
import * as AssetBalance from '../test/generated-artifacts/AssetBalance.json';
import * as DevUtils from '../test/generated-artifacts/DevUtils.json';
import * as EthBalanceChecker from '../test/generated-artifacts/EthBalanceChecker.json';
import * as ExternalFunctions from '../test/generated-artifacts/ExternalFunctions.json';
import * as LibAssetData from '../test/generated-artifacts/LibAssetData.json';
import * as LibOrderTransferSimulation from '../test/generated-artifacts/LibOrderTransferSimulation.json';
import * as LibTransactionDecoder from '../test/generated-artifacts/LibTransactionDecoder.json';
import * as OrderTransferSimulationUtils from '../test/generated-artifacts/OrderTransferSimulationUtils.json';
import * as OrderValidationUtils from '../test/generated-artifacts/OrderValidationUtils.json';
export const artifacts = {
Addresses: Addresses as ContractArtifact,
AssetBalance: AssetBalance as ContractArtifact,
DevUtils: DevUtils as ContractArtifact,
EthBalanceChecker: EthBalanceChecker as ContractArtifact,
ExternalFunctions: ExternalFunctions as ContractArtifact,
LibAssetData: LibAssetData as ContractArtifact,
LibOrderTransferSimulation: LibOrderTransferSimulation as ContractArtifact,
LibTransactionDecoder: LibTransactionDecoder as ContractArtifact,
OrderTransferSimulationUtils: OrderTransferSimulationUtils as ContractArtifact,
OrderValidationUtils: OrderValidationUtils as ContractArtifact,

View File

@@ -3,9 +3,13 @@
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
* -----------------------------------------------------------------------------
*/
export * from '../test/generated-wrappers/addresses';
export * from '../test/generated-wrappers/asset_balance';
export * from '../test/generated-wrappers/dev_utils';
export * from '../test/generated-wrappers/eth_balance_checker';
export * from '../test/generated-wrappers/external_functions';
export * from '../test/generated-wrappers/lib_asset_data';
export * from '../test/generated-wrappers/lib_order_transfer_simulation';
export * from '../test/generated-wrappers/lib_transaction_decoder';
export * from '../test/generated-wrappers/order_transfer_simulation_utils';
export * from '../test/generated-wrappers/order_validation_utils';

View File

@@ -5,10 +5,15 @@
"files": [
"generated-artifacts/DevUtils.json",
"generated-artifacts/LibAssetData.json",
"generated-artifacts/LibOrderTransferSimulation.json",
"generated-artifacts/LibTransactionDecoder.json",
"test/generated-artifacts/Addresses.json",
"test/generated-artifacts/AssetBalance.json",
"test/generated-artifacts/DevUtils.json",
"test/generated-artifacts/EthBalanceChecker.json",
"test/generated-artifacts/ExternalFunctions.json",
"test/generated-artifacts/LibAssetData.json",
"test/generated-artifacts/LibOrderTransferSimulation.json",
"test/generated-artifacts/LibTransactionDecoder.json",
"test/generated-artifacts/OrderTransferSimulationUtils.json",
"test/generated-artifacts/OrderValidationUtils.json"

View File

@@ -1,4 +1,14 @@
[
{
"version": "2.1.0",
"changes": [
{
"note": "Fix broken tests",
"pr": 2462
}
],
"timestamp": 1581204851
},
{
"timestamp": 1580988106,
"version": "2.0.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.1.0 - _February 8, 2020_
* Fix broken tests (#2462)
## v2.0.6 - _February 6, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-erc1155",
"version": "2.0.6",
"version": "2.1.0",
"engines": {
"node": ">=6.12"
},
@@ -52,15 +52,15 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/contracts-gen": "^2.0.6",
"@0x/contracts-utils": "^4.2.1",
"@0x/dev-utils": "^3.1.3",
"@0x/sol-compiler": "^4.0.6",
"@0x/abi-gen": "^5.2.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/contracts-utils": "^4.3.0",
"@0x/dev-utils": "^3.2.0",
"@0x/sol-compiler": "^4.0.7",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.1",
"@0x/typescript-typings": "^5.0.1",
"@0x/types": "^3.1.2",
"@0x/typescript-typings": "^5.0.2",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -68,7 +68,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.0.0",
"ethereum-types": "^3.1.0",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
"npm-run-all": "^4.1.2",
@@ -80,10 +80,10 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.1.2",
"@0x/contracts-test-utils": "^5.1.3",
"@0x/utils": "^5.3.0",
"@0x/web3-wrapper": "^7.0.5",
"@0x/base-contract": "^6.2.0",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/utils": "^5.4.0",
"@0x/web3-wrapper": "^7.0.6",
"lodash": "^4.17.11"
},
"publishConfig": {

View File

@@ -27,6 +27,7 @@ export {
OutputField,
ParamDescription,
EvmBytecodeOutput,
EvmBytecodeOutputLinkReferences,
AbiDefinition,
FunctionAbi,
EventAbi,

View File

@@ -1,11 +1,4 @@
import {
chaiSetup,
constants,
expectTransactionFailedAsync,
provider,
txDefaults,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { SafeMathRevertErrors } from '@0x/contracts-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types';
@@ -193,12 +186,11 @@ describe('ERC1155Token', () => {
constants.AWAIT_TRANSACTION_MINED_MS,
);
// execute transfer
await expectTransactionFailedAsync(
return expect(
erc1155Contract
.safeTransferFrom(spender, receiver, tokenToTransfer, valueToTransfer, receiverCallbackData)
.sendTransactionAsync({ from: spender }),
RevertReason.TransferRejected,
);
.awaitTransactionSuccessAsync({ from: spender }),
).to.revertWith(RevertReason.TransferRejected);
});
});
describe('batchSafeTransferFrom', () => {
@@ -359,12 +351,11 @@ describe('ERC1155Token', () => {
constants.AWAIT_TRANSACTION_MINED_MS,
);
// execute transfer
await expectTransactionFailedAsync(
return expect(
erc1155Contract
.safeBatchTransferFrom(spender, receiver, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.sendTransactionAsync({ from: spender }),
RevertReason.TransferRejected,
);
.awaitTransactionSuccessAsync({ from: spender }),
).to.revertWith(RevertReason.TransferRejected);
});
});
describe('setApprovalForAll', () => {
@@ -409,12 +400,11 @@ describe('ERC1155Token', () => {
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, [tokenToTransfer], expectedInitialBalances);
// execute transfer
await expectTransactionFailedAsync(
return expect(
erc1155Contract
.safeTransferFrom(spender, receiver, tokenToTransfer, valueToTransfer, receiverCallbackData)
.sendTransactionAsync({ from: delegatedSpender }),
RevertReason.InsufficientAllowance,
);
.awaitTransactionSuccessAsync({ from: delegatedSpender }),
).to.revertWith(RevertReason.InsufficientAllowance);
});
it('should transfer token via safeBatchTransferFrom if called by approved account', async () => {
// set approval
@@ -457,12 +447,11 @@ describe('ERC1155Token', () => {
const expectedInitialBalances = [spenderInitialFungibleBalance, receiverInitialFungibleBalance];
await erc1155Wrapper.assertBalancesAsync(tokenHolders, tokensToTransfer, expectedInitialBalances);
// execute transfer
await expectTransactionFailedAsync(
return expect(
erc1155Contract
.safeBatchTransferFrom(spender, receiver, tokensToTransfer, valuesToTransfer, receiverCallbackData)
.sendTransactionAsync({ from: delegatedSpender }),
RevertReason.InsufficientAllowance,
);
.awaitTransactionSuccessAsync({ from: delegatedSpender }),
).to.revertWith(RevertReason.InsufficientAllowance);
});
});
});

View File

@@ -1,4 +1,14 @@
[
{
"version": "1.3.0",
"changes": [
{
"note": "Catch reverts to `DevUtils` calls",
"pr": 2476
}
],
"timestamp": 1581204851
},
{
"timestamp": 1580988106,
"version": "1.2.1",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v1.3.0 - _February 8, 2020_
* Catch reverts to `DevUtils` calls (#2476)
## v1.2.1 - _February 6, 2020_
* Dependencies updated

View File

@@ -40,6 +40,7 @@ contract ERC20BridgeSampler is
uint256 constant internal KYBER_SAMPLE_CALL_GAS = 1500e3;
uint256 constant internal UNISWAP_SAMPLE_CALL_GAS = 150e3;
uint256 constant internal ETH2DAI_SAMPLE_CALL_GAS = 1000e3;
uint256 constant internal DEV_UTILS_CALL_GAS = 500e3;
address constant private UNISWAP_SOURCE = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
address constant private ETH2DAI_SOURCE = 0x39755357759cE0d7f32dC8dC45414CCa409AE24e;
address constant private KYBER_SOURCE = 0x818E6FECD516Ecc3849DAf6845e3EC868087B755;
@@ -204,13 +205,28 @@ contract ERC20BridgeSampler is
orderFillableTakerAssetAmounts[i] = 0;
continue;
}
// solhint-disable indent
(bool didSucceed, bytes memory resultData) =
_getDevUtilsAddress()
.staticcall
.gas(DEV_UTILS_CALL_GAS)
(abi.encodeWithSelector(
IDevUtils(_getDevUtilsAddress()).getOrderRelevantState.selector,
orders[i],
orderSignatures[i]
));
// solhint-enable indent
if (!didSucceed) {
orderFillableTakerAssetAmounts[i] = 0;
continue;
}
(
LibOrder.OrderInfo memory orderInfo,
uint256 fillableTakerAssetAmount,
bool isValidSignature
) = IDevUtils(_getDevUtilsAddress()).getOrderRelevantState(
orders[i],
orderSignatures[i]
) = abi.decode(
resultData,
(LibOrder.OrderInfo, uint256, bool)
);
// The fillable amount is zero if the order is not fillable or if the
// signature is invalid.

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-erc20-bridge-sampler",
"version": "1.2.1",
"version": "1.3.0",
"engines": {
"node": ">=6.12"
},
@@ -50,18 +50,18 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/contracts-asset-proxy": "^3.1.3",
"@0x/contracts-erc20": "^3.0.6",
"@0x/contracts-exchange": "^3.1.2",
"@0x/contracts-exchange-libs": "^4.2.0",
"@0x/contracts-gen": "^2.0.6",
"@0x/contracts-test-utils": "^5.1.3",
"@0x/contracts-utils": "^4.2.1",
"@0x/dev-utils": "^3.1.3",
"@0x/sol-compiler": "^4.0.6",
"@0x/abi-gen": "^5.2.0",
"@0x/contracts-asset-proxy": "^3.2.0",
"@0x/contracts-erc20": "^3.1.0",
"@0x/contracts-exchange": "^3.2.0",
"@0x/contracts-exchange-libs": "^4.3.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/contracts-utils": "^4.3.0",
"@0x/dev-utils": "^3.2.0",
"@0x/sol-compiler": "^4.0.7",
"@0x/tslint-config": "^4.0.0",
"@0x/web3-wrapper": "^7.0.5",
"@0x/web3-wrapper": "^7.0.6",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -79,11 +79,11 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.1.2",
"@0x/types": "^3.1.1",
"@0x/typescript-typings": "^5.0.1",
"@0x/utils": "^5.3.0",
"ethereum-types": "^3.0.0",
"@0x/base-contract": "^6.2.0",
"@0x/types": "^3.1.2",
"@0x/typescript-typings": "^5.0.2",
"@0x/utils": "^5.4.0",
"ethereum-types": "^3.1.0",
"lodash": "^4.17.11"
},
"publishConfig": {

View File

@@ -1,4 +1,18 @@
[
{
"version": "3.1.0",
"changes": [
{
"note": "Add `allowance()` and `balanceOf()` to `LibERC20Token`",
"pr": 2464
},
{
"note": "Fix broken tests",
"pr": 2456
}
],
"timestamp": 1581204851
},
{
"timestamp": 1580988106,
"version": "3.0.6",

View File

@@ -5,6 +5,11 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.1.0 - _February 8, 2020_
* Add `allowance()` and `balanceOf()` to `LibERC20Token` (#2464)
* Fix broken tests (#2456)
## v3.0.6 - _February 6, 2020_
* Dependencies updated

View File

@@ -94,7 +94,8 @@ library LibERC20Token {
/// @dev Retrieves the number of decimals for a token.
/// Returns `18` if the call reverts.
/// @return The number of decimals places for the token.
/// @param token The address of the token contract.
/// @return tokenDecimals The number of decimals places for the token.
function decimals(address token)
internal
view
@@ -107,6 +108,50 @@ library LibERC20Token {
}
}
/// @dev Retrieves the allowance for a token, owner, and spender.
/// Returns `0` if the call reverts.
/// @param token The address of the token contract.
/// @param owner The owner of the tokens.
/// @param spender The address the spender.
/// @return allowance The allowance for a token, owner, and spender.
function allowance(address token, address owner, address spender)
internal
view
returns (uint256 allowance_)
{
(bool didSucceed, bytes memory resultData) = token.staticcall(
abi.encodeWithSelector(
IERC20Token(0).allowance.selector,
owner,
spender
)
);
if (didSucceed && resultData.length == 32) {
allowance_ = LibBytes.readUint256(resultData, 0);
}
}
/// @dev Retrieves the balance for a token owner.
/// Returns `0` if the call reverts.
/// @param token The address of the token contract.
/// @param owner The owner of the tokens.
/// @return balance The token balance of an owner.
function balanceOf(address token, address owner)
internal
view
returns (uint256 balance)
{
(bool didSucceed, bytes memory resultData) = token.staticcall(
abi.encodeWithSelector(
IERC20Token(0).balanceOf.selector,
owner
)
);
if (didSucceed && resultData.length == 32) {
balance = LibBytes.readUint256(resultData, 0);
}
}
/// @dev Executes a call on address `target` with calldata `callData`
/// and asserts that either nothing was returned or a single boolean
/// was returned equal to `true`.

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-erc20",
"version": "3.0.6",
"version": "3.1.0",
"engines": {
"node": ">=6.12"
},
@@ -51,18 +51,18 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/contracts-gen": "^2.0.6",
"@0x/contracts-test-utils": "^5.1.3",
"@0x/contracts-utils": "^4.2.1",
"@0x/dev-utils": "^3.1.3",
"@0x/sol-compiler": "^4.0.6",
"@0x/abi-gen": "^5.2.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/contracts-utils": "^4.3.0",
"@0x/dev-utils": "^3.2.0",
"@0x/sol-compiler": "^4.0.7",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.1",
"@0x/typescript-typings": "^5.0.1",
"@0x/utils": "^5.3.0",
"@0x/web3-wrapper": "^7.0.5",
"@0x/types": "^3.1.2",
"@0x/typescript-typings": "^5.0.2",
"@0x/utils": "^5.4.0",
"@0x/web3-wrapper": "^7.0.6",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -70,7 +70,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.0.0",
"ethereum-types": "^3.1.0",
"lodash": "^4.17.11",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
@@ -82,7 +82,7 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.1.2"
"@0x/base-contract": "^6.2.0"
},
"publishConfig": {
"access": "public"

View File

@@ -30,6 +30,7 @@ export {
OutputField,
ParamDescription,
EvmBytecodeOutput,
EvmBytecodeOutputLinkReferences,
AbiDefinition,
FunctionAbi,
EventAbi,

View File

@@ -1,11 +1,4 @@
import {
chaiSetup,
constants,
expectContractCallFailedAsync,
provider,
txDefaults,
web3Wrapper,
} from '@0x/contracts-test-utils';
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { RevertReason } from '@0x/types';
import { BigNumber } from '@0x/utils';
@@ -60,8 +53,7 @@ describe('UnlimitedAllowanceToken', () => {
it('should revert if owner has insufficient balance', async () => {
const ownerBalance = await token.balanceOf(owner).callAsync();
const amountToTransfer = ownerBalance.plus(1);
return expectContractCallFailedAsync(
token.transfer(spender, amountToTransfer).callAsync({ from: owner }),
return expect(token.transfer(spender, amountToTransfer).callAsync({ from: owner })).to.revertWith(
RevertReason.Erc20InsufficientBalance,
);
});
@@ -99,12 +91,11 @@ describe('UnlimitedAllowanceToken', () => {
await token.approve(spender, amountToTransfer).sendTransactionAsync({ from: owner }),
constants.AWAIT_TRANSACTION_MINED_MS,
);
return expectContractCallFailedAsync(
return expect(
token.transferFrom(owner, spender, amountToTransfer).callAsync({
from: spender,
}),
RevertReason.Erc20InsufficientBalance,
);
).to.revertWith(RevertReason.Erc20InsufficientBalance);
});
it('should revert if spender has insufficient allowance', async () => {
@@ -115,12 +106,11 @@ describe('UnlimitedAllowanceToken', () => {
const isSpenderAllowanceInsufficient = spenderAllowance.comparedTo(amountToTransfer) < 0;
expect(isSpenderAllowanceInsufficient).to.be.true();
return expectContractCallFailedAsync(
return expect(
token.transferFrom(owner, spender, amountToTransfer).callAsync({
from: spender,
}),
RevertReason.Erc20InsufficientAllowance,
);
).to.revertWith(RevertReason.Erc20InsufficientAllowance);
});
it('should return true on a 0 value transfer', async () => {

View File

@@ -1,4 +1,14 @@
[
{
"version": "3.1.0",
"changes": [
{
"note": "Fix broken tests",
"pr": 2462
}
],
"timestamp": 1581204851
},
{
"timestamp": 1580988106,
"version": "3.0.6",

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.1.0 - _February 8, 2020_
* Fix broken tests (#2462)
## v3.0.6 - _February 6, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-erc721",
"version": "3.0.6",
"version": "3.1.0",
"engines": {
"node": ">=6.12"
},
@@ -52,18 +52,18 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/tokens/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/contracts-gen": "^2.0.6",
"@0x/contracts-test-utils": "^5.1.3",
"@0x/contracts-utils": "^4.2.1",
"@0x/dev-utils": "^3.1.3",
"@0x/sol-compiler": "^4.0.6",
"@0x/abi-gen": "^5.2.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/contracts-utils": "^4.3.0",
"@0x/dev-utils": "^3.2.0",
"@0x/sol-compiler": "^4.0.7",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.1",
"@0x/typescript-typings": "^5.0.1",
"@0x/utils": "^5.3.0",
"@0x/web3-wrapper": "^7.0.5",
"@0x/types": "^3.1.2",
"@0x/typescript-typings": "^5.0.2",
"@0x/utils": "^5.4.0",
"@0x/web3-wrapper": "^7.0.6",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -71,7 +71,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.0.0",
"ethereum-types": "^3.1.0",
"lodash": "^4.17.11",
"make-promises-safe": "^1.1.0",
"mocha": "^6.2.0",
@@ -84,7 +84,7 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.1.2"
"@0x/base-contract": "^6.2.0"
},
"publishConfig": {
"access": "public"

View File

@@ -22,6 +22,7 @@ export {
OutputField,
ParamDescription,
EvmBytecodeOutput,
EvmBytecodeOutputLinkReferences,
AbiDefinition,
FunctionAbi,
EventAbi,

View File

@@ -1,7 +1,6 @@
import {
chaiSetup,
constants,
expectTransactionFailedAsync,
expectTransactionFailedWithoutReasonAsync,
LogDecoder,
provider,
@@ -77,34 +76,30 @@ describe('ERC721Token', () => {
const from = owner;
const to = erc721Receiver.address;
const unownedTokenId = new BigNumber(2);
await expectTransactionFailedAsync(
token.transferFrom(from, to, unownedTokenId).sendTransactionAsync(),
return expect(token.transferFrom(from, to, unownedTokenId).awaitTransactionSuccessAsync()).to.revertWith(
RevertReason.Erc721ZeroOwner,
);
});
it('should revert if transferring to a null address', async () => {
const from = owner;
const to = constants.NULL_ADDRESS;
await expectTransactionFailedAsync(
token.transferFrom(from, to, tokenId).sendTransactionAsync(),
return expect(token.transferFrom(from, to, tokenId).awaitTransactionSuccessAsync()).to.revertWith(
RevertReason.Erc721ZeroToAddress,
);
});
it('should revert if the from address does not own the token', async () => {
const from = spender;
const to = erc721Receiver.address;
await expectTransactionFailedAsync(
token.transferFrom(from, to, tokenId).sendTransactionAsync(),
return expect(token.transferFrom(from, to, tokenId).awaitTransactionSuccessAsync()).to.revertWith(
RevertReason.Erc721OwnerMismatch,
);
});
it('should revert if spender does not own the token, is not approved, and is not approved for all', async () => {
const from = owner;
const to = erc721Receiver.address;
await expectTransactionFailedAsync(
token.transferFrom(from, to, tokenId).sendTransactionAsync({ from: spender }),
RevertReason.Erc721InvalidSpender,
);
return expect(
token.transferFrom(from, to, tokenId).awaitTransactionSuccessAsync({ from: spender }),
).to.revertWith(RevertReason.Erc721InvalidSpender);
});
it('should transfer the token if called by owner', async () => {
const from = owner;
@@ -198,8 +193,7 @@ describe('ERC721Token', () => {
);
const from = owner;
const to = invalidErc721Receiver.address;
await expectTransactionFailedAsync(
token.safeTransferFrom1(from, to, tokenId).sendTransactionAsync(),
return expect(token.safeTransferFrom1(from, to, tokenId).sendTransactionAsync()).to.revertWith(
RevertReason.Erc721InvalidSelector,
);
});
@@ -261,8 +255,7 @@ describe('ERC721Token', () => {
);
const from = owner;
const to = invalidErc721Receiver.address;
await expectTransactionFailedAsync(
token.safeTransferFrom2(from, to, tokenId, data).sendTransactionAsync(),
return expect(token.safeTransferFrom2(from, to, tokenId, data).sendTransactionAsync()).to.revertWith(
RevertReason.Erc721InvalidSelector,
);
});

View File

@@ -1,4 +1,14 @@
[
{
"version": "4.2.0",
"changes": [
{
"note": "Export `EvmBytecodeOutputLinkReferences` type.",
"pr": 2462
}
],
"timestamp": 1581204851
},
{
"version": "4.1.0",
"changes": [

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.2.0 - _February 8, 2020_
* Export `EvmBytecodeOutputLinkReferences` type. (#2462)
## v4.1.0 - _February 6, 2020_
* Refactor, moved LibAssetDataTransfer and MixinWeth(Utils) to extensions (#2455)

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-exchange-forwarder",
"version": "4.1.0",
"version": "4.2.0",
"engines": {
"node": ">=6.12"
},
@@ -52,25 +52,25 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/contracts-asset-proxy": "^3.1.3",
"@0x/contracts-dev-utils": "^1.0.6",
"@0x/contracts-erc1155": "^2.0.6",
"@0x/contracts-erc20": "^3.0.6",
"@0x/contracts-erc721": "^3.0.6",
"@0x/contracts-exchange": "^3.1.2",
"@0x/contracts-exchange-libs": "^4.2.0",
"@0x/contracts-gen": "^2.0.6",
"@0x/contracts-test-utils": "^5.1.3",
"@0x/contracts-utils": "^4.2.1",
"@0x/dev-utils": "^3.1.3",
"@0x/order-utils": "^10.1.3",
"@0x/sol-compiler": "^4.0.6",
"@0x/abi-gen": "^5.2.0",
"@0x/contracts-asset-proxy": "^3.2.0",
"@0x/contracts-dev-utils": "^1.1.0",
"@0x/contracts-erc1155": "^2.1.0",
"@0x/contracts-erc20": "^3.1.0",
"@0x/contracts-erc721": "^3.1.0",
"@0x/contracts-exchange": "^3.2.0",
"@0x/contracts-exchange-libs": "^4.3.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/contracts-utils": "^4.3.0",
"@0x/dev-utils": "^3.2.0",
"@0x/order-utils": "^10.2.0",
"@0x/sol-compiler": "^4.0.7",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.1",
"@0x/utils": "^5.3.0",
"@0x/web3-wrapper": "^7.0.5",
"@0x/types": "^3.1.2",
"@0x/utils": "^5.4.0",
"@0x/web3-wrapper": "^7.0.6",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -90,9 +90,9 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.1.2",
"@0x/typescript-typings": "^5.0.1",
"ethereum-types": "^3.0.0"
"@0x/base-contract": "^6.2.0",
"@0x/typescript-typings": "^5.0.2",
"ethereum-types": "^3.1.0"
},
"publishConfig": {
"access": "public"

View File

@@ -16,6 +16,7 @@ export {
OutputField,
ParamDescription,
EvmBytecodeOutput,
EvmBytecodeOutputLinkReferences,
AbiDefinition,
FunctionAbi,
EventAbi,

View File

@@ -1,4 +1,14 @@
[
{
"version": "4.3.0",
"changes": [
{
"note": "Export `EvmBytecodeOutputLinkReferences` type.",
"pr": 2462
}
],
"timestamp": 1581204851
},
{
"version": "4.2.0",
"changes": [

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v4.3.0 - _February 8, 2020_
* Export `EvmBytecodeOutputLinkReferences` type. (#2462)
## v4.2.0 - _February 6, 2020_
* Moved LibAssetDataTransfer here from forwarder (#2455)

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-exchange-libs",
"version": "4.2.0",
"version": "4.3.0",
"engines": {
"node": ">=6.12"
},
@@ -52,14 +52,14 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/libs/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/contracts-gen": "^2.0.6",
"@0x/dev-utils": "^3.1.3",
"@0x/sol-compiler": "^4.0.6",
"@0x/subproviders": "^6.0.6",
"@0x/abi-gen": "^5.2.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/dev-utils": "^3.2.0",
"@0x/sol-compiler": "^4.0.7",
"@0x/subproviders": "^6.0.7",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/web3-wrapper": "^7.0.5",
"@0x/web3-wrapper": "^7.0.6",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -80,14 +80,14 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.1.2",
"@0x/contracts-test-utils": "^5.1.3",
"@0x/contracts-utils": "^4.2.1",
"@0x/order-utils": "^10.1.3",
"@0x/types": "^3.1.1",
"@0x/typescript-typings": "^5.0.1",
"@0x/utils": "^5.3.0",
"ethereum-types": "^3.0.0"
"@0x/base-contract": "^6.2.0",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/contracts-utils": "^4.3.0",
"@0x/order-utils": "^10.2.0",
"@0x/types": "^3.1.2",
"@0x/typescript-typings": "^5.0.2",
"@0x/utils": "^5.4.0",
"ethereum-types": "^3.1.0"
},
"publishConfig": {
"access": "public"

View File

@@ -27,6 +27,7 @@ export {
OutputField,
ParamDescription,
EvmBytecodeOutput,
EvmBytecodeOutputLinkReferences,
AbiDefinition,
FunctionAbi,
EventAbi,

View File

@@ -1,4 +1,18 @@
[
{
"version": "3.2.0",
"changes": [
{
"note": "Flip `LibExchangeRichErrorDecoder` to an actual library.",
"pr": 2462
},
{
"note": "Remove dependency on `DevUtils` for asset data encoding/decoding",
"pr": 2462
}
],
"timestamp": 1581204851
},
{
"timestamp": 1580988106,
"version": "3.1.2",

View File

@@ -5,6 +5,11 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v3.2.0 - _February 8, 2020_
* Flip `LibExchangeRichErrorDecoder` to an actual library. (#2462)
* Remove dependency on `DevUtils` for asset data encoding/decoding (#2462)
## v3.1.2 - _February 6, 2020_
* Dependencies updated

View File

@@ -23,7 +23,7 @@ import "@0x/contracts-exchange-libs/contracts/src/LibExchangeRichErrors.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
contract LibExchangeRichErrorDecoder {
library LibExchangeRichErrorDecoder {
using LibBytes for bytes;
@@ -33,7 +33,7 @@ contract LibExchangeRichErrorDecoder {
/// @return signerAddress The expected signer of the hash.
/// @return signature The full signature.
function decodeSignatureError(bytes memory encoded)
public
internal
pure
returns (
LibExchangeRichErrors.SignatureErrorCodes errorCode,
@@ -57,7 +57,7 @@ contract LibExchangeRichErrorDecoder {
/// @return signature The full signature bytes.
/// @return errorData The revert data thrown by the validator contract.
function decodeEIP1271SignatureError(bytes memory encoded)
public
internal
pure
returns (
address verifyingContractAddress,
@@ -78,7 +78,7 @@ contract LibExchangeRichErrorDecoder {
/// @return signerAddress The expected signer of the hash.
/// @return validatorAddress The expected validator.
function decodeSignatureValidatorNotApprovedError(bytes memory encoded)
public
internal
pure
returns (
address signerAddress,
@@ -99,7 +99,7 @@ contract LibExchangeRichErrorDecoder {
/// @return signature The full signature bytes.
/// @return errorData The revert data thrown by the validator contract.
function decodeSignatureWalletError(bytes memory encoded)
public
internal
pure
returns (
bytes32 hash,
@@ -120,7 +120,7 @@ contract LibExchangeRichErrorDecoder {
/// @return orderHash The order hash.
/// @return orderStatus The order status.
function decodeOrderStatusError(bytes memory encoded)
public
internal
pure
returns (
bytes32 orderHash,
@@ -142,7 +142,7 @@ contract LibExchangeRichErrorDecoder {
/// @return orderHash The order hash.
/// @return contextAddress The maker, taker, or sender address
function decodeExchangeInvalidContextError(bytes memory encoded)
public
internal
pure
returns (
LibExchangeRichErrors.ExchangeContextErrorCodes errorCode,
@@ -164,7 +164,7 @@ contract LibExchangeRichErrorDecoder {
/// @return errorCode The error code.
/// @return orderHash The order hash.
function decodeFillError(bytes memory encoded)
public
internal
pure
returns (
LibExchangeRichErrors.FillErrorCodes errorCode,
@@ -186,7 +186,7 @@ contract LibExchangeRichErrorDecoder {
/// @return orderSenderAddress The order sender.
/// @return currentEpoch The current epoch for the maker.
function decodeOrderEpochError(bytes memory encoded)
public
internal
pure
returns (
address makerAddress,
@@ -206,7 +206,7 @@ contract LibExchangeRichErrorDecoder {
/// @return assetProxyId Id of asset proxy.
/// @return assetProxyAddress The address of the asset proxy.
function decodeAssetProxyExistsError(bytes memory encoded)
public
internal
pure
returns (
bytes4 assetProxyId, address assetProxyAddress)
@@ -224,7 +224,7 @@ contract LibExchangeRichErrorDecoder {
/// @return orderHash Hash of the order being dispatched.
/// @return assetData Asset data of the order being dispatched.
function decodeAssetProxyDispatchError(bytes memory encoded)
public
internal
pure
returns (
LibExchangeRichErrors.AssetProxyDispatchErrorCodes errorCode,
@@ -247,7 +247,7 @@ contract LibExchangeRichErrorDecoder {
/// @return assetData Asset data of the order being dispatched.
/// @return errorData ABI-encoded revert data from the asset proxy.
function decodeAssetProxyTransferError(bytes memory encoded)
public
internal
pure
returns (
bytes32 orderHash,
@@ -267,7 +267,7 @@ contract LibExchangeRichErrorDecoder {
/// @return leftOrderHash Hash of the left order being matched.
/// @return rightOrderHash Hash of the right order being matched.
function decodeNegativeSpreadError(bytes memory encoded)
public
internal
pure
returns (
bytes32 leftOrderHash,
@@ -286,7 +286,7 @@ contract LibExchangeRichErrorDecoder {
/// @return errorCode The error code.
/// @return transactionHash Hash of the transaction.
function decodeTransactionError(bytes memory encoded)
public
internal
pure
returns (
LibExchangeRichErrors.TransactionErrorCodes errorCode,
@@ -307,7 +307,7 @@ contract LibExchangeRichErrorDecoder {
/// @return transactionHash Hash of the transaction.
/// @return errorData Error thrown by exeucteTransaction().
function decodeTransactionExecutionError(bytes memory encoded)
public
internal
pure
returns (
bytes32 transactionHash,
@@ -325,7 +325,7 @@ contract LibExchangeRichErrorDecoder {
/// @param encoded ABI-encoded revert error.
/// @return orderHash Hash of the order being filled.
function decodeIncompleteFillError(bytes memory encoded)
public
internal
pure
returns (
LibExchangeRichErrors.IncompleteFillErrorCode errorCode,

View File

@@ -22,6 +22,249 @@ import "../src/libs/LibExchangeRichErrorDecoder.sol";
// solhint-disable no-empty-blocks
contract TestLibExchangeRichErrorDecoder is
LibExchangeRichErrorDecoder
{}
contract TestLibExchangeRichErrorDecoder
{
/// @dev Decompose an ABI-encoded SignatureError.
/// @param encoded ABI-encoded revert error.
/// @return errorCode The error code.
/// @return signerAddress The expected signer of the hash.
/// @return signature The full signature.
function decodeSignatureError(bytes memory encoded)
public
pure
returns (
LibExchangeRichErrors.SignatureErrorCodes errorCode,
bytes32 hash,
address signerAddress,
bytes memory signature
)
{
return LibExchangeRichErrorDecoder.decodeSignatureError(encoded);
}
/// @dev Decompose an ABI-encoded SignatureValidatorError.
/// @param encoded ABI-encoded revert error.
/// @return signerAddress The expected signer of the hash.
/// @return signature The full signature bytes.
/// @return errorData The revert data thrown by the validator contract.
function decodeEIP1271SignatureError(bytes memory encoded)
public
pure
returns (
address verifyingContractAddress,
bytes memory data,
bytes memory signature,
bytes memory errorData
)
{
return LibExchangeRichErrorDecoder.decodeEIP1271SignatureError(encoded);
}
/// @dev Decompose an ABI-encoded SignatureValidatorNotApprovedError.
/// @param encoded ABI-encoded revert error.
/// @return signerAddress The expected signer of the hash.
/// @return validatorAddress The expected validator.
function decodeSignatureValidatorNotApprovedError(bytes memory encoded)
public
pure
returns (
address signerAddress,
address validatorAddress
)
{
return LibExchangeRichErrorDecoder.decodeSignatureValidatorNotApprovedError(encoded);
}
/// @dev Decompose an ABI-encoded SignatureWalletError.
/// @param encoded ABI-encoded revert error.
/// @return errorCode The error code.
/// @return signerAddress The expected signer of the hash.
/// @return signature The full signature bytes.
/// @return errorData The revert data thrown by the validator contract.
function decodeSignatureWalletError(bytes memory encoded)
public
pure
returns (
bytes32 hash,
address signerAddress,
bytes memory signature,
bytes memory errorData
)
{
return LibExchangeRichErrorDecoder.decodeSignatureWalletError(encoded);
}
/// @dev Decompose an ABI-encoded OrderStatusError.
/// @param encoded ABI-encoded revert error.
/// @return orderHash The order hash.
/// @return orderStatus The order status.
function decodeOrderStatusError(bytes memory encoded)
public
pure
returns (
bytes32 orderHash,
LibOrder.OrderStatus orderStatus
)
{
return LibExchangeRichErrorDecoder.decodeOrderStatusError(encoded);
}
/// @dev Decompose an ABI-encoded OrderStatusError.
/// @param encoded ABI-encoded revert error.
/// @return errorCode Error code that corresponds to invalid maker, taker, or sender.
/// @return orderHash The order hash.
/// @return contextAddress The maker, taker, or sender address
function decodeExchangeInvalidContextError(bytes memory encoded)
public
pure
returns (
LibExchangeRichErrors.ExchangeContextErrorCodes errorCode,
bytes32 orderHash,
address contextAddress
)
{
return LibExchangeRichErrorDecoder.decodeExchangeInvalidContextError(encoded);
}
/// @dev Decompose an ABI-encoded FillError.
/// @param encoded ABI-encoded revert error.
/// @return errorCode The error code.
/// @return orderHash The order hash.
function decodeFillError(bytes memory encoded)
public
pure
returns (
LibExchangeRichErrors.FillErrorCodes errorCode,
bytes32 orderHash
)
{
return LibExchangeRichErrorDecoder.decodeFillError(encoded);
}
/// @dev Decompose an ABI-encoded OrderEpochError.
/// @param encoded ABI-encoded revert error.
/// @return makerAddress The order maker.
/// @return orderSenderAddress The order sender.
/// @return currentEpoch The current epoch for the maker.
function decodeOrderEpochError(bytes memory encoded)
public
pure
returns (
address makerAddress,
address orderSenderAddress,
uint256 currentEpoch
)
{
return LibExchangeRichErrorDecoder.decodeOrderEpochError(encoded);
}
/// @dev Decompose an ABI-encoded AssetProxyExistsError.
/// @param encoded ABI-encoded revert error.
/// @return assetProxyId Id of asset proxy.
/// @return assetProxyAddress The address of the asset proxy.
function decodeAssetProxyExistsError(bytes memory encoded)
public
pure
returns (
bytes4 assetProxyId, address assetProxyAddress)
{
return LibExchangeRichErrorDecoder.decodeAssetProxyExistsError(encoded);
}
/// @dev Decompose an ABI-encoded AssetProxyDispatchError.
/// @param encoded ABI-encoded revert error.
/// @return errorCode The error code.
/// @return orderHash Hash of the order being dispatched.
/// @return assetData Asset data of the order being dispatched.
function decodeAssetProxyDispatchError(bytes memory encoded)
public
pure
returns (
LibExchangeRichErrors.AssetProxyDispatchErrorCodes errorCode,
bytes32 orderHash,
bytes memory assetData
)
{
return LibExchangeRichErrorDecoder.decodeAssetProxyDispatchError(encoded);
}
/// @dev Decompose an ABI-encoded AssetProxyTransferError.
/// @param encoded ABI-encoded revert error.
/// @return orderHash Hash of the order being dispatched.
/// @return assetData Asset data of the order being dispatched.
/// @return errorData ABI-encoded revert data from the asset proxy.
function decodeAssetProxyTransferError(bytes memory encoded)
public
pure
returns (
bytes32 orderHash,
bytes memory assetData,
bytes memory errorData
)
{
return LibExchangeRichErrorDecoder.decodeAssetProxyTransferError(encoded);
}
/// @dev Decompose an ABI-encoded NegativeSpreadError.
/// @param encoded ABI-encoded revert error.
/// @return leftOrderHash Hash of the left order being matched.
/// @return rightOrderHash Hash of the right order being matched.
function decodeNegativeSpreadError(bytes memory encoded)
public
pure
returns (
bytes32 leftOrderHash,
bytes32 rightOrderHash
)
{
return LibExchangeRichErrorDecoder.decodeNegativeSpreadError(encoded);
}
/// @dev Decompose an ABI-encoded TransactionError.
/// @param encoded ABI-encoded revert error.
/// @return errorCode The error code.
/// @return transactionHash Hash of the transaction.
function decodeTransactionError(bytes memory encoded)
public
pure
returns (
LibExchangeRichErrors.TransactionErrorCodes errorCode,
bytes32 transactionHash
)
{
return LibExchangeRichErrorDecoder.decodeTransactionError(encoded);
}
/// @dev Decompose an ABI-encoded TransactionExecutionError.
/// @param encoded ABI-encoded revert error.
/// @return transactionHash Hash of the transaction.
/// @return errorData Error thrown by exeucteTransaction().
function decodeTransactionExecutionError(bytes memory encoded)
public
pure
returns (
bytes32 transactionHash,
bytes memory errorData
)
{
return LibExchangeRichErrorDecoder.decodeTransactionExecutionError(encoded);
}
/// @dev Decompose an ABI-encoded IncompleteFillError.
/// @param encoded ABI-encoded revert error.
/// @return orderHash Hash of the order being filled.
function decodeIncompleteFillError(bytes memory encoded)
public
pure
returns (
LibExchangeRichErrors.IncompleteFillErrorCode errorCode,
uint256 expectedAssetFillAmount,
uint256 actualAssetFillAmount
)
{
return LibExchangeRichErrorDecoder.decodeIncompleteFillError(encoded);
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-exchange",
"version": "3.1.2",
"version": "3.2.0",
"engines": {
"node": ">=6.12"
},
@@ -52,21 +52,21 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/contracts-asset-proxy": "^3.1.3",
"@0x/contracts-exchange-libs": "^4.2.0",
"@0x/contracts-gen": "^2.0.6",
"@0x/contracts-multisig": "^4.0.6",
"@0x/contracts-staking": "^2.0.6",
"@0x/contracts-test-utils": "^5.1.3",
"@0x/contracts-utils": "^4.2.1",
"@0x/dev-utils": "^3.1.3",
"@0x/sol-compiler": "^4.0.6",
"@0x/abi-gen": "^5.2.0",
"@0x/contracts-asset-proxy": "^3.2.0",
"@0x/contracts-exchange-libs": "^4.3.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/contracts-multisig": "^4.1.0",
"@0x/contracts-staking": "^2.0.7",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/contracts-utils": "^4.3.0",
"@0x/dev-utils": "^3.2.0",
"@0x/sol-compiler": "^4.0.7",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.1",
"@0x/typescript-typings": "^5.0.1",
"@0x/web3-wrapper": "^7.0.5",
"@0x/types": "^3.1.2",
"@0x/typescript-typings": "^5.0.2",
"@0x/web3-wrapper": "^7.0.6",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -74,7 +74,7 @@
"chai-as-promised": "^7.1.0",
"chai-bignumber": "^3.0.0",
"dirty-chai": "^2.0.1",
"ethereum-types": "^3.0.0",
"ethereum-types": "^3.1.0",
"ethereumjs-util": "^5.1.1",
"js-combinatorics": "^0.5.3",
"make-promises-safe": "^1.1.0",
@@ -88,13 +88,13 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.1.2",
"@0x/contracts-dev-utils": "^1.0.6",
"@0x/contracts-erc1155": "^2.0.6",
"@0x/contracts-erc20": "^3.0.6",
"@0x/contracts-erc721": "^3.0.6",
"@0x/order-utils": "^10.1.3",
"@0x/utils": "^5.3.0",
"@0x/base-contract": "^6.2.0",
"@0x/contracts-dev-utils": "^1.1.0",
"@0x/contracts-erc1155": "^2.1.0",
"@0x/contracts-erc20": "^3.1.0",
"@0x/contracts-erc721": "^3.1.0",
"@0x/order-utils": "^10.2.0",
"@0x/utils": "^5.4.0",
"lodash": "^4.17.11"
},
"publishConfig": {

View File

@@ -35,6 +35,7 @@ export {
OutputField,
ParamDescription,
EvmBytecodeOutput,
EvmBytecodeOutputLinkReferences,
AbiDefinition,
FunctionAbi,
EventAbi,

View File

@@ -1,11 +1,11 @@
import {
artifacts as proxyArtifacts,
encodeERC20AssetData,
ERC20ProxyContract,
ERC20Wrapper,
ERC721ProxyContract,
ERC721Wrapper,
} from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import {
chaiSetup,
@@ -47,7 +47,6 @@ describe('AssetProxyDispatcher', () => {
let erc20Wrapper: ERC20Wrapper;
let erc721Wrapper: ERC721Wrapper;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
before(async () => {
await blockchainLifecycle.startAsync();
});
@@ -189,7 +188,7 @@ describe('AssetProxyDispatcher', () => {
from: owner,
});
// Construct metadata for ERC20 proxy
const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
// Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
@@ -213,7 +212,7 @@ describe('AssetProxyDispatcher', () => {
from: owner,
});
// Construct metadata for ERC20 proxy
const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
// Perform a transfer from makerAddress to takerAddress
const erc20Balances = await erc20Wrapper.getBalancesAsync();
@@ -228,7 +227,7 @@ describe('AssetProxyDispatcher', () => {
it('should revert if dispatching to unregistered proxy', async () => {
// Construct metadata for ERC20 proxy
const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
// Perform a transfer from makerAddress to takerAddress
const amount = new BigNumber(10);
@@ -247,7 +246,7 @@ describe('AssetProxyDispatcher', () => {
await assetProxyDispatcher.registerAssetProxy(erc20Proxy.address).awaitTransactionSuccessAsync({
from: owner,
});
const encodedAssetData = (await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync()).slice(0, 8);
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address).slice(0, 8);
const amount = new BigNumber(1);
const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError(
ExchangeRevertErrors.AssetProxyDispatchErrorCode.InvalidAssetDataLength,
@@ -265,10 +264,7 @@ describe('AssetProxyDispatcher', () => {
from: owner,
});
// Shave off the last byte
const encodedAssetData = (await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync()).slice(
0,
72,
);
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address).slice(0, 72);
const amount = new BigNumber(1);
const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError(
ExchangeRevertErrors.AssetProxyDispatchErrorCode.InvalidAssetDataLength,
@@ -288,7 +284,7 @@ describe('AssetProxyDispatcher', () => {
await erc20TokenA.approve(erc20Proxy.address, constants.ZERO_AMOUNT).awaitTransactionSuccessAsync({
from: makerAddress,
});
const encodedAssetData = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const encodedAssetData = encodeERC20AssetData(erc20TokenA.address);
const amount = new BigNumber(1);
const nestedError = new StringRevertError(RevertReason.TransferFailed).encode();
const expectedError = new ExchangeRevertErrors.AssetProxyTransferError(
@@ -307,8 +303,8 @@ describe('AssetProxyDispatcher', () => {
await assetProxyDispatcher.registerAssetProxy(erc20Proxy.address).awaitTransactionSuccessAsync({
from: owner,
});
const assetDataA = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const assetDataB = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
const assetDataA = encodeERC20AssetData(erc20TokenA.address);
const assetDataB = encodeERC20AssetData(erc20TokenB.address);
await erc20TokenB.approve(erc20Proxy.address, constants.ZERO_AMOUNT).awaitTransactionSuccessAsync({
from: makerAddress,
});
@@ -330,8 +326,8 @@ describe('AssetProxyDispatcher', () => {
return expect(tx).to.revertWith(expectedError);
});
it('should forward the revert reason from the underlying failed transfer', async () => {
const assetDataA = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const assetDataB = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
const assetDataA = encodeERC20AssetData(erc20TokenA.address);
const assetDataB = encodeERC20AssetData(erc20TokenB.address);
const transferIndexAsBytes32 = '0x0000000000000000000000000000000000000000000000000000000000000000';
const expectedError = new ExchangeRevertErrors.AssetProxyDispatchError(
ExchangeRevertErrors.AssetProxyDispatchErrorCode.UnknownAssetProxy,
@@ -352,8 +348,8 @@ describe('AssetProxyDispatcher', () => {
await assetProxyDispatcher.registerAssetProxy(erc20Proxy.address).awaitTransactionSuccessAsync({
from: owner,
});
const assetDataA = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const assetDataB = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
const assetDataA = encodeERC20AssetData(erc20TokenA.address);
const assetDataB = encodeERC20AssetData(erc20TokenB.address);
const tx = assetProxyDispatcher
.simulateDispatchTransferFromCalls(
[assetDataA, assetDataB],
@@ -368,8 +364,8 @@ describe('AssetProxyDispatcher', () => {
await assetProxyDispatcher.registerAssetProxy(erc20Proxy.address).awaitTransactionSuccessAsync({
from: owner,
});
const assetDataA = await devUtils.encodeERC20AssetData(erc20TokenA.address).callAsync();
const assetDataB = await devUtils.encodeERC20AssetData(erc20TokenB.address).callAsync();
const assetDataA = encodeERC20AssetData(erc20TokenA.address);
const assetDataB = encodeERC20AssetData(erc20TokenB.address);
const balances = await erc20Wrapper.getBalancesAsync();
try {
await assetProxyDispatcher

View File

@@ -1,22 +1,17 @@
import { artifacts as assetProxyArtifacts, ERC20ProxyContract } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { artifacts as assetProxyArtifacts, encodeERC20AssetData, ERC20ProxyContract } from '@0x/contracts-asset-proxy';
import { artifacts as erc20Artifacts, DummyERC20TokenContract, ERC20TokenContract } from '@0x/contracts-erc20';
import { blockchainTests, chaiSetup, constants } from '@0x/contracts-test-utils';
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
import { ExchangeContractErrs } from '@0x/types';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import { ExchangeTransferSimulator } from './utils/exchange_transfer_simulator';
import { SimpleERC20BalanceAndProxyAllowanceFetcher } from './utils/simple_erc20_balance_and_proxy_allowance_fetcher';
import { BalanceAndProxyAllowanceLazyStore } from './utils/store/balance_and_proxy_allowance_lazy_store';
import { TradeSide, TransferType } from './utils/types';
chaiSetup.configure();
const expect = chai.expect;
const GAS_LIMIT = 9e6;
blockchainTests('ExchangeTransferSimulator', env => {
blockchainTests.resets('ExchangeTransferSimulator', env => {
const transferAmount = new BigNumber(5);
let userAddresses: string[];
let dummyERC20Token: DummyERC20TokenContract;
@@ -26,7 +21,6 @@ blockchainTests('ExchangeTransferSimulator', env => {
let exampleAssetData: string;
let exchangeTransferSimulator: ExchangeTransferSimulator;
let erc20ProxyAddress: string;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, env.provider);
before(async function(): Promise<void> {
const mochaTestTimeoutMs = 20000;
this.timeout(mochaTestTimeoutMs); // tslint:disable-line:no-invalid-this
@@ -39,7 +33,6 @@ blockchainTests('ExchangeTransferSimulator', env => {
from: userAddresses[0],
};
await env.blockchainLifecycle.startAsync();
const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
assetProxyArtifacts.ERC20Proxy,
env.provider,
@@ -64,16 +57,7 @@ blockchainTests('ExchangeTransferSimulator', env => {
totalSupply,
);
exampleAssetData = await devUtils.encodeERC20AssetData(dummyERC20Token.address).callAsync();
});
beforeEach(async () => {
await env.blockchainLifecycle.startAsync();
});
afterEach(async () => {
await env.blockchainLifecycle.revertAsync();
});
after(async () => {
await env.blockchainLifecycle.revertAsync();
exampleAssetData = encodeERC20AssetData(dummyERC20Token.address);
});
describe('#transferFromAsync', function(): void {
// HACK: For some reason these tests need a slightly longer timeout
@@ -87,7 +71,7 @@ blockchainTests('ExchangeTransferSimulator', env => {
const balanceAndProxyAllowanceLazyStore = new BalanceAndProxyAllowanceLazyStore(
simpleERC20BalanceAndProxyAllowanceFetcher,
);
exchangeTransferSimulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore, devUtils);
exchangeTransferSimulator = new ExchangeTransferSimulator(balanceAndProxyAllowanceLazyStore);
});
it("throws if the user doesn't have enough allowance", async () => {
return expect(

View File

@@ -1,5 +1,4 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { blockchainTests, constants, describe, provider } from '@0x/contracts-test-utils';
import { blockchainTests, describe } from '@0x/contracts-test-utils';
import * as _ from 'lodash';
import {
@@ -49,10 +48,8 @@ const defaultFillScenario = {
blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
let fillOrderCombinatorialUtils: FillOrderCombinatorialUtils;
let devUtils: DevUtilsContract;
before(async () => {
devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
fillOrderCombinatorialUtils = await fillOrderCombinatorialUtilsFactoryAsync(web3Wrapper, txDefaults);
});
@@ -65,7 +62,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
takerAssetAmountScenario: OrderAssetAmountScenario.Small,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should transfer the correct amounts when makerAssetAmount < takerAssetAmount', async () => {
@@ -76,7 +73,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
makerAssetAmountScenario: OrderAssetAmountScenario.Small,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should transfer the correct amounts when makerAssetAmount < takerAssetAmount with zero decimals', async () => {
@@ -88,7 +85,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
makerAssetDataScenario: AssetDataScenario.ERC20ZeroDecimals,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should transfer the correct amounts when taker is specified and order is claimed by taker', async () => {
@@ -99,7 +96,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
takerScenario: TakerScenario.CorrectlySpecified,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should transfer the correct amounts maker == feeRecipient', async () => {
@@ -110,7 +107,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeRecipientScenario: FeeRecipientAddressScenario.MakerAddress,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should transfer the correct amounts maker == feeRecipient and makerFeeAsset == takerAsset', async () => {
@@ -122,7 +119,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
makerFeeAssetDataScenario: FeeAssetDataScenario.TakerToken,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should transfer the correct amounts taker == feeRecipient', async () => {
@@ -133,7 +130,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeRecipientScenario: FeeRecipientAddressScenario.TakerAddress,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should transfer the correct amounts taker == feeRecipient and takerFeeAsset == makerAsset', async () => {
@@ -145,7 +142,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
takerFeeAssetDataScenario: FeeAssetDataScenario.MakerToken,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should fill remaining value if takerAssetFillAmount > remaining takerAssetAmount', async () => {
@@ -153,7 +150,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
...defaultFillScenario,
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.GreaterThanTakerAssetAmount,
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should revert when taker is specified and order is claimed by other', async () => {
@@ -164,7 +161,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
takerScenario: TakerScenario.IncorrectlySpecified,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should revert if makerAssetAmount is 0', async () => {
@@ -176,7 +173,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
},
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.GreaterThanTakerAssetAmount,
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should revert if takerAssetAmount is 0', async () => {
@@ -188,7 +185,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
},
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.GreaterThanTakerAssetAmount,
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should revert if an order is expired', async () => {
@@ -199,7 +196,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
expirationTimeSecondsScenario: ExpirationTimeSecondsScenario.InPast,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
});
@@ -219,7 +216,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
takerAssetDataScenario: takerAsset,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
}
it('should be able to pay maker fee with taker asset', async () => {
@@ -235,7 +232,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should be able to pay taker fee with maker asset', async () => {
@@ -251,7 +248,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should not be able to pay maker fee with maker asset if none is left over (double-spend)', async () => {
@@ -268,7 +265,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should not be able to pay taker fee with taker asset if none is left over (double-spend)', async () => {
@@ -285,7 +282,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should be able to pay taker fee with maker asset', async () => {
@@ -301,7 +298,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should revert if maker balance is too low to fill order', async () => {
@@ -312,7 +309,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
traderAssetBalance: BalanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should revert if taker balance is too low to fill order', async () => {
@@ -323,7 +320,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
traderAssetBalance: BalanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should revert if maker allowances are too low to fill order', async () => {
@@ -334,7 +331,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
traderAssetAllowance: AllowanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should revert if taker allowances are too low to fill order', async () => {
@@ -345,7 +342,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
traderAssetAllowance: AllowanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should revert if maker fee balance is too low to fill order', async () => {
@@ -356,7 +353,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should revert if taker fee balance is too low to fill order', async () => {
@@ -367,7 +364,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should revert if maker fee allowances are too low to fill order', async () => {
@@ -378,7 +375,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeAllowance: AllowanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should revert if taker fee allowances are too low to fill order', async () => {
@@ -389,7 +386,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeAllowance: AllowanceAmountScenario.TooLow,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
});
@@ -408,7 +405,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should be able to pay taker fee with maker ERC721', async () => {
@@ -425,7 +422,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should not be able to pay maker fee with maker ERC721 (double-spend)', async () => {
@@ -442,7 +439,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should be able to pay taker fee with taker ERC721 (double-spend)', async () => {
@@ -459,7 +456,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
});
@@ -481,7 +478,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should be able to pay taker fee with maker asset', async () => {
@@ -498,7 +495,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should not be able to pay maker fee with maker asset if not enough left (double-spend)', async () => {
@@ -516,7 +513,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should be able to pay taker fee with taker asset if not enough left (double-spend)', async () => {
@@ -534,7 +531,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
});
}
@@ -555,7 +552,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should be able to pay taker fee with maker MAP', async () => {
@@ -572,7 +569,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
it('should not be able to pay maker fee with maker MAP (double-spend)', async () => {
@@ -589,7 +586,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
it('should be able to pay taker fee with taker MAP (double-spend)', async () => {
@@ -606,7 +603,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
feeBalance: BalanceAmountScenario.Zero,
},
};
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioFailureAsync(fillScenario);
});
});
@@ -629,7 +626,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
},
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
}
});
@@ -653,7 +650,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
},
takerAssetFillAmountScenario: TakerAssetFillAmountScenario.ExactlyTakerAssetAmount,
};
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioSuccessAsync(fillScenario);
});
}
});
@@ -663,7 +660,7 @@ blockchainTests.resets('FillOrder Tests', ({ web3Wrapper, txDefaults }) => {
for (const fillScenario of allFillScenarios) {
const description = `Combinatorial OrderFill: ${JSON.stringify(fillScenario)}`;
it(description, async () => {
await fillOrderCombinatorialUtils.testFillOrderScenarioAsync(fillScenario, devUtils);
await fillOrderCombinatorialUtils.testFillOrderScenarioAsync(fillScenario);
});
}
});

View File

@@ -1,5 +1,4 @@
import { ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { encodeERC20AssetData, ERC20ProxyContract, ERC20Wrapper } from '@0x/contracts-asset-proxy';
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import {
blockchainTests,
@@ -52,7 +51,6 @@ blockchainTests.resets('MixinSignatureValidator', env => {
let takerAddress: string;
let feeRecipientAddress: string;
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, env.provider, env.txDefaults);
const eip1271Data = new IEIP1271DataContract(constants.NULL_ADDRESS, env.provider, env.txDefaults);
before(async () => {
chainId = await env.getChainIdAsync();
@@ -428,10 +426,10 @@ blockchainTests.resets('MixinSignatureValidator', env => {
...constants.STATIC_ORDER_PARAMS,
makerAddress: signerAddress,
feeRecipientAddress: randomAddress(),
makerAssetData: await devUtils.encodeERC20AssetData(randomAddress()).callAsync(),
takerAssetData: await devUtils.encodeERC20AssetData(randomAddress()).callAsync(),
makerFeeAssetData: await devUtils.encodeERC20AssetData(randomAddress()).callAsync(),
takerFeeAssetData: await devUtils.encodeERC20AssetData(randomAddress()).callAsync(),
makerAssetData: encodeERC20AssetData(randomAddress()),
takerAssetData: encodeERC20AssetData(randomAddress()),
makerFeeAssetData: encodeERC20AssetData(randomAddress()),
takerFeeAssetData: encodeERC20AssetData(randomAddress()),
makerFee: constants.ZERO_AMOUNT,
takerFee: constants.ZERO_AMOUNT,
exchangeAddress: exchange.address,
@@ -1175,10 +1173,10 @@ blockchainTests.resets('MixinSignatureValidator', env => {
...constants.STATIC_ORDER_PARAMS,
makerAddress,
feeRecipientAddress,
makerAssetData: await devUtils.encodeERC20AssetData(defaultMakerAssetAddress).callAsync(),
takerAssetData: await devUtils.encodeERC20AssetData(defaultTakerAssetAddress).callAsync(),
makerFeeAssetData: await devUtils.encodeERC20AssetData(defaultFeeAssetAddress).callAsync(),
takerFeeAssetData: await devUtils.encodeERC20AssetData(defaultFeeAssetAddress).callAsync(),
makerAssetData: encodeERC20AssetData(defaultMakerAssetAddress),
takerAssetData: encodeERC20AssetData(defaultTakerAssetAddress),
makerFeeAssetData: encodeERC20AssetData(defaultFeeAssetAddress),
takerFeeAssetData: encodeERC20AssetData(defaultFeeAssetAddress),
exchangeAddress: exchange.address,
chainId,
};

View File

@@ -1,11 +1,17 @@
import {
decodeERC1155AssetData,
decodeERC721AssetData,
decodeMultiAssetData,
ERC1155ProxyWrapper,
ERC20Wrapper,
ERC721Wrapper,
getAssetDataProxyId,
} from '@0x/contracts-asset-proxy';
import { AbstractAssetWrapper, constants } from '@0x/contracts-test-utils';
import { AssetProxyId } from '@0x/types';
import { BigNumber, errorUtils } from '@0x/utils';
import * as _ from 'lodash';
import { ERC1155ProxyWrapper, ERC20Wrapper, ERC721Wrapper } from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
interface ProxyIdToAssetWrappers {
[proxyId: string]: AbstractAssetWrapper;
}
@@ -20,11 +26,7 @@ const ZERO_NFT_UNIT = new BigNumber(0);
export class AssetWrapper {
private readonly _proxyIdToAssetWrappers: ProxyIdToAssetWrappers;
constructor(
assetWrappers: AbstractAssetWrapper[],
private readonly _burnerAddress: string,
private readonly _devUtils: DevUtilsContract,
) {
constructor(assetWrappers: AbstractAssetWrapper[], private readonly _burnerAddress: string) {
this._proxyIdToAssetWrappers = {};
_.each(assetWrappers, assetWrapper => {
const proxyId = assetWrapper.getProxyId();
@@ -32,7 +34,7 @@ export class AssetWrapper {
});
}
public async getBalanceAsync(userAddress: string, assetData: string): Promise<BigNumber> {
const proxyId = await this._devUtils.decodeAssetProxyId(assetData).callAsync();
const proxyId = getAssetDataProxyId(assetData);
switch (proxyId) {
case AssetProxyId.ERC20: {
// tslint:disable-next-line:no-unnecessary-type-assertion
@@ -44,9 +46,7 @@ export class AssetWrapper {
// tslint:disable-next-line:no-unnecessary-type-assertion
const assetWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
// tslint:disable-next-line:no-unused-variable
const [assetProxyId, tokenAddress, tokenId] = await this._devUtils
.decodeERC721AssetData(assetData)
.callAsync();
const [tokenAddress, tokenId] = decodeERC721AssetData(assetData);
const isOwner = await assetWrapper.isOwnerAsync(userAddress, tokenAddress, tokenId);
const balance = isOwner ? ONE_NFT_UNIT : ZERO_NFT_UNIT;
return balance;
@@ -56,10 +56,9 @@ export class AssetWrapper {
const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper;
const [
// tslint:disable-next-line:no-unused-variable
assetProxyAddress,
tokenAddress,
tokenIds,
] = await this._devUtils.decodeERC1155AssetData(assetData).callAsync();
] = decodeERC1155AssetData(assetData);
const assetWrapper = assetProxyWrapper.getContractWrapper(tokenAddress);
const balances = await Promise.all(
_.map(tokenIds).map(tokenId => assetWrapper.getBalanceAsync(userAddress, tokenId)),
@@ -68,9 +67,7 @@ export class AssetWrapper {
}
case AssetProxyId.MultiAsset: {
// tslint:disable-next-line:no-unused-variable
const [assetProxyId, amounts, nestedAssetData] = await this._devUtils
.decodeMultiAssetData(assetData)
.callAsync();
const [amounts, nestedAssetData] = decodeMultiAssetData(assetData);
const nestedBalances = await Promise.all(
nestedAssetData.map(async _nestedAssetData => this.getBalanceAsync(userAddress, _nestedAssetData)),
);
@@ -84,7 +81,7 @@ export class AssetWrapper {
}
}
public async setBalanceAsync(userAddress: string, assetData: string, desiredBalance: BigNumber): Promise<void> {
const proxyId = await this._devUtils.decodeAssetProxyId(assetData).callAsync();
const proxyId = getAssetDataProxyId(assetData);
switch (proxyId) {
case AssetProxyId.ERC20: {
// tslint:disable-next-line:no-unnecessary-type-assertion
@@ -100,9 +97,7 @@ export class AssetWrapper {
// tslint:disable-next-line:no-unnecessary-type-assertion
const erc721Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
// tslint:disable-next-line:no-unused-variable
const [assetProxyId, tokenAddress, tokenId] = await this._devUtils
.decodeERC721AssetData(assetData)
.callAsync();
const [tokenAddress, tokenId] = decodeERC721AssetData(assetData);
const doesTokenExist = erc721Wrapper.doesTokenExistAsync(tokenAddress, tokenId);
if (!doesTokenExist && desiredBalance.gte(1)) {
await erc721Wrapper.mintAsync(tokenAddress, tokenId, userAddress);
@@ -130,11 +125,10 @@ export class AssetWrapper {
const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper;
const [
// tslint:disable-next-line:no-unused-variable
assetProxyAddress,
tokenAddress,
tokenIds,
tokenValues,
] = await this._devUtils.decodeERC1155AssetData(assetData).callAsync();
] = decodeERC1155AssetData(assetData);
const assetWrapper = assetProxyWrapper.getContractWrapper(tokenAddress);
const tokenValuesSum = BigNumber.sum(...tokenValues);
let tokenValueRatios = tokenValues;
@@ -197,9 +191,7 @@ export class AssetWrapper {
}
case AssetProxyId.MultiAsset: {
// tslint:disable-next-line:no-unused-variable
const [assetProxyId, amounts, nestedAssetData] = await this._devUtils
.decodeMultiAssetData(assetData)
.callAsync();
const [amounts, nestedAssetData] = decodeMultiAssetData(assetData);
const amountsSum = BigNumber.sum(...amounts);
let assetAmountRatios = amounts;
if (!amountsSum.eq(0)) {
@@ -220,7 +212,7 @@ export class AssetWrapper {
assetData: string,
desiredBalance: BigNumber,
): Promise<void> {
const proxyId = await this._devUtils.decodeAssetProxyId(assetData).callAsync();
const proxyId = getAssetDataProxyId(assetData);
switch (proxyId) {
case AssetProxyId.ERC20:
case AssetProxyId.ERC721:
@@ -235,7 +227,7 @@ export class AssetWrapper {
}
}
public async getProxyAllowanceAsync(userAddress: string, assetData: string): Promise<BigNumber> {
const proxyId = await this._devUtils.decodeAssetProxyId(assetData).callAsync();
const proxyId = getAssetDataProxyId(assetData);
switch (proxyId) {
case AssetProxyId.ERC20: {
// tslint:disable-next-line:no-unnecessary-type-assertion
@@ -247,9 +239,7 @@ export class AssetWrapper {
// tslint:disable-next-line:no-unnecessary-type-assertion
const assetWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
// tslint:disable-next-line:no-unused-variable
const [assetProxyId, tokenAddress, tokenId] = await this._devUtils
.decodeERC721AssetData(assetData)
.callAsync();
const [tokenAddress, tokenId] = decodeERC721AssetData(assetData);
const isProxyApprovedForAll = await assetWrapper.isProxyApprovedForAllAsync(userAddress, tokenAddress);
if (isProxyApprovedForAll) {
return constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
@@ -263,9 +253,7 @@ export class AssetWrapper {
// tslint:disable-next-line:no-unnecessary-type-assertion
const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper;
// tslint:disable-next-line:no-unused-variable
const [assetProxyAddress, tokenAddress] = await this._devUtils
.decodeERC1155AssetData(assetData)
.callAsync();
const [tokenAddress] = decodeERC1155AssetData(assetData);
const isApprovedForAll = await assetProxyWrapper.isProxyApprovedForAllAsync(userAddress, tokenAddress);
if (!isApprovedForAll) {
// ERC1155 is all or nothing.
@@ -275,9 +263,7 @@ export class AssetWrapper {
}
case AssetProxyId.MultiAsset: {
// tslint:disable-next-line:no-unused-variable
const [assetProxyId, amounts, nestedAssetData] = await this._devUtils
.decodeMultiAssetData(assetData)
.callAsync();
const [amounts, nestedAssetData] = decodeMultiAssetData(assetData);
const allowances = await Promise.all(
nestedAssetData.map(async _nestedAssetData =>
this.getProxyAllowanceAsync(userAddress, _nestedAssetData),
@@ -294,7 +280,7 @@ export class AssetWrapper {
assetData: string,
desiredAllowance: BigNumber,
): Promise<void> {
const proxyId = await this._devUtils.decodeAssetProxyId(assetData).callAsync();
const proxyId = getAssetDataProxyId(assetData);
switch (proxyId) {
case AssetProxyId.ERC20: {
// tslint:disable-next-line:no-unnecessary-type-assertion
@@ -315,9 +301,7 @@ export class AssetWrapper {
// tslint:disable-next-line:no-unnecessary-type-assertion
const erc721Wrapper = this._proxyIdToAssetWrappers[proxyId] as ERC721Wrapper;
// tslint:disable-next-line:no-unused-variable
const [assetProxyId, tokenAddress, tokenId] = await this._devUtils
.decodeERC721AssetData(assetData)
.callAsync();
const [tokenAddress, tokenId] = decodeERC721AssetData(assetData);
const doesTokenExist = await erc721Wrapper.doesTokenExistAsync(tokenAddress, tokenId);
if (!doesTokenExist) {
@@ -352,9 +336,7 @@ export class AssetWrapper {
// tslint:disable-next-line:no-unnecessary-type-assertion
const assetProxyWrapper = this._proxyIdToAssetWrappers[proxyId] as ERC1155ProxyWrapper;
// tslint:disable-next-line:no-unused-variable
const [assetProxyAddress, tokenAddress] = await this._devUtils
.decodeERC1155AssetData(assetData)
.callAsync();
const [tokenAddress] = decodeERC1155AssetData(assetData);
// ERC1155 allowances are all or nothing.
const shouldApprovedForAll = desiredAllowance.gt(0);
const currentAllowance = await this.getProxyAllowanceAsync(userAddress, assetData);
@@ -369,9 +351,7 @@ export class AssetWrapper {
}
case AssetProxyId.MultiAsset: {
// tslint:disable-next-line:no-unused-variable
const [assetProxyId, amounts, nestedAssetData] = await this._devUtils
.decodeMultiAssetData(assetData)
.callAsync();
const [amounts, nestedAssetData] = decodeMultiAssetData(assetData);
await Promise.all(
nestedAssetData.map(async _nestedAssetData =>
this.setProxyAllowanceAsync(userAddress, _nestedAssetData, desiredAllowance),

View File

@@ -1,4 +1,4 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { decodeMultiAssetData, getAssetDataProxyId } from '@0x/contracts-asset-proxy';
import { constants } from '@0x/contracts-test-utils';
import { AssetProxyId, ExchangeContractErrs } from '@0x/types';
import { BigNumber } from '@0x/utils';
@@ -40,7 +40,6 @@ const ERR_MSG_MAPPING = {
*/
export class ExchangeTransferSimulator {
private readonly _store: AbstractBalanceAndProxyAllowanceLazyStore;
private readonly _devUtils: DevUtilsContract;
private static _throwValidationError(
failureReason: FailureReason,
tradeSide: TradeSide,
@@ -54,9 +53,8 @@ export class ExchangeTransferSimulator {
* @param store A class that implements AbstractBalanceAndProxyAllowanceLazyStore
* @return an instance of ExchangeTransferSimulator
*/
constructor(store: AbstractBalanceAndProxyAllowanceLazyStore, devUtilsContract: DevUtilsContract) {
constructor(store: AbstractBalanceAndProxyAllowanceLazyStore) {
this._store = store;
this._devUtils = devUtilsContract;
}
/**
* Simulates transferFrom call performed by a proxy
@@ -77,7 +75,7 @@ export class ExchangeTransferSimulator {
tradeSide: TradeSide,
transferType: TransferType,
): Promise<void> {
const assetProxyId = await this._devUtils.decodeAssetProxyId(assetData).callAsync();
const assetProxyId = getAssetDataProxyId(assetData);
switch (assetProxyId) {
case AssetProxyId.ERC1155:
case AssetProxyId.ERC20:
@@ -110,11 +108,11 @@ export class ExchangeTransferSimulator {
break;
}
case AssetProxyId.MultiAsset: {
const decodedAssetData = await this._devUtils.decodeMultiAssetData(assetData).callAsync();
const decodedAssetData = decodeMultiAssetData(assetData);
await this._decreaseBalanceAsync(assetData, from, amountInBaseUnits);
await this._increaseBalanceAsync(assetData, to, amountInBaseUnits);
for (const [index, nestedAssetDataElement] of decodedAssetData[2].entries()) {
const amountsElement = decodedAssetData[1][index];
for (const [index, nestedAssetDataElement] of decodedAssetData[1].entries()) {
const amountsElement = decodedAssetData[0][index];
const totalAmount = amountInBaseUnits.times(amountsElement);
await this.transferFromAsync(
nestedAssetDataElement,

View File

@@ -5,7 +5,6 @@ import {
ERC721Wrapper,
MultiAssetProxyContract,
} from '@0x/contracts-asset-proxy';
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { constants, expect, LogDecoder, orderHashUtils, orderUtils, signingUtils } from '@0x/contracts-test-utils';
import { FillResults, Order, SignatureType, SignedOrder } from '@0x/types';
import { BigNumber, errorUtils, ExchangeRevertErrors, providerUtils, RevertError, StringRevertError } from '@0x/utils';
@@ -109,8 +108,7 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
{},
);
const devUtils = new DevUtilsContract(constants.NULL_ADDRESS, provider);
const assetWrapper = new AssetWrapper([erc20Wrapper, erc721Wrapper, erc1155Wrapper], burnerAddress, devUtils);
const assetWrapper = new AssetWrapper([erc20Wrapper, erc721Wrapper, erc1155Wrapper], burnerAddress);
const exchangeContract = await ExchangeContract.deployFrom0xArtifactAsync(
artifacts.Exchange,
@@ -160,7 +158,6 @@ export async function fillOrderCombinatorialUtilsFactoryAsync(
await multiAssetProxy.registerAssetProxy(erc1155Proxy.address).awaitTransactionSuccessAsync({ from: ownerAddress });
const orderFactory = new OrderFactoryFromScenario(
devUtils,
userAddresses,
erc20EighteenDecimalTokens.map(token => token.address),
erc20FiveDecimalTokens.map(token => token.address),
@@ -441,29 +438,24 @@ export class FillOrderCombinatorialUtils {
this.balanceAndProxyAllowanceFetcher = new SimpleAssetBalanceAndProxyAllowanceFetcher(assetWrapper);
}
public async testFillOrderScenarioAsync(fillScenario: FillScenario, devUtils: DevUtilsContract): Promise<void> {
return this._testFillOrderScenarioAsync(fillScenario, TestOutlook.Any, devUtils);
public async testFillOrderScenarioAsync(fillScenario: FillScenario): Promise<void> {
return this._testFillOrderScenarioAsync(fillScenario, TestOutlook.Any);
}
public async testFillOrderScenarioSuccessAsync(
fillScenario: FillScenario,
devUtils: DevUtilsContract,
): Promise<void> {
return this._testFillOrderScenarioAsync(fillScenario, TestOutlook.Success, devUtils);
public async testFillOrderScenarioSuccessAsync(fillScenario: FillScenario): Promise<void> {
return this._testFillOrderScenarioAsync(fillScenario, TestOutlook.Success);
}
public async testFillOrderScenarioFailureAsync(
fillScenario: FillScenario,
devUtils: DevUtilsContract,
fillErrorIfExists?: FillOrderError,
): Promise<void> {
return this._testFillOrderScenarioAsync(fillScenario, TestOutlook.Failure, devUtils, fillErrorIfExists);
return this._testFillOrderScenarioAsync(fillScenario, TestOutlook.Failure, fillErrorIfExists);
}
private async _testFillOrderScenarioAsync(
fillScenario: FillScenario,
expectedTestResult: TestOutlook = TestOutlook.Any,
devUtils: DevUtilsContract,
fillErrorIfExists?: FillOrderError,
): Promise<void> {
const lazyStore = new BalanceAndProxyAllowanceLazyStore(this.balanceAndProxyAllowanceFetcher);
@@ -476,12 +468,7 @@ export class FillOrderCombinatorialUtils {
let _fillErrorIfExists = fillErrorIfExists;
if (expectedTestResult !== TestOutlook.Failure || fillErrorIfExists === undefined) {
try {
expectedFillResults = await this._simulateFillOrderAsync(
signedOrder,
takerAssetFillAmount,
lazyStore,
devUtils,
);
expectedFillResults = await this._simulateFillOrderAsync(signedOrder, takerAssetFillAmount, lazyStore);
} catch (err) {
_fillErrorIfExists = err.message;
if (expectedTestResult === TestOutlook.Success) {
@@ -514,9 +501,8 @@ export class FillOrderCombinatorialUtils {
signedOrder: SignedOrder,
takerAssetFillAmount: BigNumber,
lazyStore: BalanceAndProxyAllowanceLazyStore,
devUtils: DevUtilsContract,
): Promise<FillResults> {
const simulator = new FillOrderSimulator(lazyStore, devUtils);
const simulator = new FillOrderSimulator(lazyStore);
return simulator.simulateFillOrderAsync(signedOrder, this.takerAddress, takerAssetFillAmount);
}

View File

@@ -1,4 +1,3 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import { constants, orderUtils } from '@0x/contracts-test-utils';
import { Order } from '@0x/order-utils';
import { FillResults } from '@0x/types';
@@ -26,9 +25,9 @@ export class FillOrderSimulator {
public readonly lazyStore: LazyStore;
private readonly _transferSimulator: ExchangeTransferSimulator;
constructor(lazyStore: LazyStore, devUtilsContract: DevUtilsContract) {
constructor(lazyStore: LazyStore) {
this.lazyStore = lazyStore;
this._transferSimulator = new ExchangeTransferSimulator(lazyStore, devUtilsContract);
this._transferSimulator = new ExchangeTransferSimulator(lazyStore);
}
public async simulateFillOrderAsync(

View File

@@ -1,4 +1,9 @@
import { DevUtilsContract } from '@0x/contracts-dev-utils';
import {
encodeERC1155AssetData,
encodeERC20AssetData,
encodeERC721AssetData,
encodeMultiAssetData,
} from '@0x/contracts-asset-proxy';
import { constants, ERC1155HoldingsByOwner, ERC721TokenIdsByOwner } from '@0x/contracts-test-utils';
import { generatePseudoRandomSalt } from '@0x/order-utils';
import { Order } from '@0x/types';
@@ -34,7 +39,6 @@ const ZERO_UNITS = new BigNumber(0);
export class OrderFactoryFromScenario {
constructor(
private readonly _devUtils: DevUtilsContract,
private readonly _userAddresses: string[],
private readonly _erc20EighteenDecimalTokenAddresses: string[],
private readonly _erc20FiveDecimalTokenAddresses: string[],
@@ -96,59 +100,41 @@ export class OrderFactoryFromScenario {
switch (orderScenario.makerAssetDataScenario) {
case AssetDataScenario.ERC20EighteenDecimals:
makerAssetData = await this._devUtils
.encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[0])
.callAsync();
makerAssetData = encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[0]);
break;
case AssetDataScenario.ERC20FiveDecimals:
makerAssetData = await this._devUtils
.encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[0])
.callAsync();
makerAssetData = encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[0]);
break;
case AssetDataScenario.ERC721:
makerAssetData = await this._devUtils
.encodeERC721AssetData(this._erc721TokenAddress, erc721MakerAssetIds[0])
.callAsync();
makerAssetData = encodeERC721AssetData(this._erc721TokenAddress, erc721MakerAssetIds[0]);
break;
case AssetDataScenario.ERC20ZeroDecimals:
makerAssetData = await this._devUtils
.encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[0])
.callAsync();
makerAssetData = encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[0]);
break;
case AssetDataScenario.ERC1155Fungible:
makerAssetData = await this._devUtils
.encodeERC1155AssetData(
this._erc1155TokenAddress,
[erc1155FungibleMakerTokenIds[0]],
[ONE_UNITS_ZERO_DECIMALS],
erc1155CallbackData,
)
.callAsync();
makerAssetData = encodeERC1155AssetData(
this._erc1155TokenAddress,
[erc1155FungibleMakerTokenIds[0]],
[ONE_UNITS_ZERO_DECIMALS],
erc1155CallbackData,
);
break;
case AssetDataScenario.ERC1155NonFungible:
makerAssetData = await this._devUtils
.encodeERC1155AssetData(
this._erc1155TokenAddress,
[erc1155NonFungibleMakerTokenIds[0]],
[ONE_UNITS_ZERO_DECIMALS],
erc1155CallbackData,
)
.callAsync();
makerAssetData = encodeERC1155AssetData(
this._erc1155TokenAddress,
[erc1155NonFungibleMakerTokenIds[0]],
[ONE_UNITS_ZERO_DECIMALS],
erc1155CallbackData,
);
break;
case AssetDataScenario.MultiAssetERC20:
makerAssetData = await this._devUtils
.encodeMultiAssetData(
[ONE_UNITS_EIGHTEEN_DECIMALS, ONE_UNITS_FIVE_DECIMALS],
[
await this._devUtils
.encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[0])
.callAsync(),
await this._devUtils
.encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[0])
.callAsync(),
],
)
.callAsync();
makerAssetData = encodeMultiAssetData(
[ONE_UNITS_EIGHTEEN_DECIMALS, ONE_UNITS_FIVE_DECIMALS],
[
encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[0]),
encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[0]),
],
);
break;
default:
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.makerAssetDataScenario);
@@ -156,59 +142,41 @@ export class OrderFactoryFromScenario {
switch (orderScenario.takerAssetDataScenario) {
case AssetDataScenario.ERC20EighteenDecimals:
takerAssetData = await this._devUtils
.encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[1])
.callAsync();
takerAssetData = encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[1]);
break;
case AssetDataScenario.ERC20FiveDecimals:
takerAssetData = await this._devUtils
.encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[1])
.callAsync();
takerAssetData = encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[1]);
break;
case AssetDataScenario.ERC721:
takerAssetData = await this._devUtils
.encodeERC721AssetData(this._erc721TokenAddress, erc721TakerAssetIds[0])
.callAsync();
takerAssetData = encodeERC721AssetData(this._erc721TokenAddress, erc721TakerAssetIds[0]);
break;
case AssetDataScenario.ERC20ZeroDecimals:
takerAssetData = await this._devUtils
.encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[1])
.callAsync();
takerAssetData = encodeERC20AssetData(this._erc20ZeroDecimalTokenAddresses[1]);
break;
case AssetDataScenario.ERC1155Fungible:
takerAssetData = await this._devUtils
.encodeERC1155AssetData(
this._erc1155TokenAddress,
[erc1155FungibleTakerTokenIds[1]],
[ONE_UNITS_ZERO_DECIMALS],
erc1155CallbackData,
)
.callAsync();
takerAssetData = encodeERC1155AssetData(
this._erc1155TokenAddress,
[erc1155FungibleTakerTokenIds[1]],
[ONE_UNITS_ZERO_DECIMALS],
erc1155CallbackData,
);
break;
case AssetDataScenario.ERC1155NonFungible:
takerAssetData = await this._devUtils
.encodeERC1155AssetData(
this._erc1155TokenAddress,
[erc1155NonFungibleTakerTokenIds[0]],
[ONE_UNITS_ZERO_DECIMALS],
erc1155CallbackData,
)
.callAsync();
takerAssetData = encodeERC1155AssetData(
this._erc1155TokenAddress,
[erc1155NonFungibleTakerTokenIds[0]],
[ONE_UNITS_ZERO_DECIMALS],
erc1155CallbackData,
);
break;
case AssetDataScenario.MultiAssetERC20:
takerAssetData = await this._devUtils
.encodeMultiAssetData(
[ONE_UNITS_EIGHTEEN_DECIMALS, ONE_UNITS_FIVE_DECIMALS],
[
await this._devUtils
.encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[1])
.callAsync(),
await this._devUtils
.encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[1])
.callAsync(),
],
)
.callAsync();
takerAssetData = encodeMultiAssetData(
[ONE_UNITS_EIGHTEEN_DECIMALS, ONE_UNITS_FIVE_DECIMALS],
[
encodeERC20AssetData(this._erc20EighteenDecimalTokenAddresses[1]),
encodeERC20AssetData(this._erc20FiveDecimalTokenAddresses[1]),
],
);
break;
default:
throw errorUtils.spawnSwitchErr('AssetDataScenario', orderScenario.takerAssetDataScenario);
@@ -339,63 +307,43 @@ export class OrderFactoryFromScenario {
case FeeAssetDataScenario.TakerToken:
return [feeAmount, takerAssetData];
case FeeAssetDataScenario.ERC20EighteenDecimals:
return [
feeAmount,
await this._devUtils.encodeERC20AssetData(erc20EighteenDecimalTokenAddress).callAsync(),
];
return [feeAmount, encodeERC20AssetData(erc20EighteenDecimalTokenAddress)];
case FeeAssetDataScenario.ERC20FiveDecimals:
return [
feeAmount,
await this._devUtils.encodeERC20AssetData(erc20FiveDecimalTokenAddress).callAsync(),
];
return [feeAmount, encodeERC20AssetData(erc20FiveDecimalTokenAddress)];
case FeeAssetDataScenario.ERC20ZeroDecimals:
return [
feeAmount,
await this._devUtils.encodeERC20AssetData(erc20ZeroDecimalTokenAddress).callAsync(),
];
return [feeAmount, encodeERC20AssetData(erc20ZeroDecimalTokenAddress)];
case FeeAssetDataScenario.ERC721:
return [
feeAmount,
await this._devUtils.encodeERC721AssetData(this._erc721TokenAddress, erc721AssetId).callAsync(),
];
return [feeAmount, encodeERC721AssetData(this._erc721TokenAddress, erc721AssetId)];
case FeeAssetDataScenario.ERC1155Fungible:
return [
feeAmount,
await this._devUtils
.encodeERC1155AssetData(
this._erc1155TokenAddress,
[erc1155FungibleTokenId],
[ONE_UNITS_ZERO_DECIMALS],
erc1155CallbackData,
)
.callAsync(),
encodeERC1155AssetData(
this._erc1155TokenAddress,
[erc1155FungibleTokenId],
[ONE_UNITS_ZERO_DECIMALS],
erc1155CallbackData,
),
];
case FeeAssetDataScenario.ERC1155NonFungible:
return [
feeAmount,
await this._devUtils
.encodeERC1155AssetData(
this._erc1155TokenAddress,
[erc1155NonFungibleAssetId],
[ONE_UNITS_ZERO_DECIMALS],
erc1155CallbackData,
)
.callAsync(),
encodeERC1155AssetData(
this._erc1155TokenAddress,
[erc1155NonFungibleAssetId],
[ONE_UNITS_ZERO_DECIMALS],
erc1155CallbackData,
),
];
case FeeAssetDataScenario.MultiAssetERC20:
return [
feeAmount,
await this._devUtils
.encodeMultiAssetData(
[POINT_ZERO_FIVE_UNITS_EIGHTEEN_DECIMALS, POINT_ZERO_FIVE_UNITS_FIVE_DECIMALS],
[
await this._devUtils
.encodeERC20AssetData(erc20EighteenDecimalTokenAddress)
.callAsync(),
await this._devUtils.encodeERC20AssetData(erc20FiveDecimalTokenAddress).callAsync(),
],
)
.callAsync(),
encodeMultiAssetData(
[POINT_ZERO_FIVE_UNITS_EIGHTEEN_DECIMALS, POINT_ZERO_FIVE_UNITS_FIVE_DECIMALS],
[
encodeERC20AssetData(erc20EighteenDecimalTokenAddress),
encodeERC20AssetData(erc20FiveDecimalTokenAddress),
],
),
];
default:
throw errorUtils.spawnSwitchErr('FeeAssetDataScenario', feeAssetDataScenario);

View File

@@ -1,4 +1,14 @@
[
{
"version": "6.1.0",
"changes": [
{
"note": "Export `EvmBytecodeOutputLinkReferences` type.",
"pr": 2462
}
],
"timestamp": 1581204851
},
{
"version": "6.0.0",
"changes": [

View File

@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v6.1.0 - _February 8, 2020_
* Export `EvmBytecodeOutputLinkReferences` type. (#2462)
## v6.0.0 - _February 6, 2020_
* New year, new me: remove everything, add MixinWethUtils and LibAssetDataTransfer (#2455)

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-extensions",
"version": "6.0.0",
"version": "6.1.0",
"engines": {
"node": ">=6.12"
},
@@ -51,24 +51,24 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/contracts-asset-proxy": "^3.1.3",
"@0x/contracts-dev-utils": "^1.0.6",
"@0x/contracts-erc20": "^3.0.6",
"@0x/contracts-erc721": "^3.0.6",
"@0x/contracts-exchange": "^3.1.2",
"@0x/contracts-exchange-libs": "^4.2.0",
"@0x/contracts-gen": "^2.0.6",
"@0x/contracts-test-utils": "^5.1.3",
"@0x/contracts-utils": "^4.2.1",
"@0x/dev-utils": "^3.1.3",
"@0x/order-utils": "^10.1.3",
"@0x/sol-compiler": "^4.0.6",
"@0x/abi-gen": "^5.2.0",
"@0x/contracts-asset-proxy": "^3.2.0",
"@0x/contracts-dev-utils": "^1.1.0",
"@0x/contracts-erc20": "^3.1.0",
"@0x/contracts-erc721": "^3.1.0",
"@0x/contracts-exchange": "^3.2.0",
"@0x/contracts-exchange-libs": "^4.3.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/contracts-utils": "^4.3.0",
"@0x/dev-utils": "^3.2.0",
"@0x/order-utils": "^10.2.0",
"@0x/sol-compiler": "^4.0.7",
"@0x/ts-doc-gen": "^0.0.22",
"@0x/tslint-config": "^4.0.0",
"@0x/types": "^3.1.1",
"@0x/utils": "^5.3.0",
"@0x/web3-wrapper": "^7.0.5",
"@0x/types": "^3.1.2",
"@0x/utils": "^5.4.0",
"@0x/web3-wrapper": "^7.0.6",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
"@types/node": "*",
@@ -90,9 +90,9 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/base-contract": "^6.1.2",
"@0x/typescript-typings": "^5.0.1",
"ethereum-types": "^3.0.0"
"@0x/base-contract": "^6.2.0",
"@0x/typescript-typings": "^5.0.2",
"ethereum-types": "^3.1.0"
},
"publishConfig": {
"access": "public"

View File

@@ -15,6 +15,7 @@ export {
OutputField,
ParamDescription,
EvmBytecodeOutput,
EvmBytecodeOutputLinkReferences,
AbiDefinition,
FunctionAbi,
EventAbi,

View File

@@ -1,4 +1,18 @@
[
{
"version": "2.3.0",
"changes": [
{
"note": "Remove dependency on `DevUtils` for asset data encoding/decoding",
"pr": 2462
},
{
"note": "Update tests for refactored `DevUtils`",
"pr": 2464
}
],
"timestamp": 1581204851
},
{
"timestamp": 1580988106,
"version": "2.2.3",

View File

@@ -5,6 +5,11 @@ Edit the package's CHANGELOG.json file only.
CHANGELOG
## v2.3.0 - _February 8, 2020_
* Remove dependency on `DevUtils` for asset data encoding/decoding (#2462)
* Update tests for refactored `DevUtils` (#2464)
## v2.2.3 - _February 6, 2020_
* Dependencies updated

View File

@@ -1,6 +1,6 @@
{
"name": "@0x/contracts-integrations",
"version": "2.2.3",
"version": "2.3.0",
"engines": {
"node": ">=6.12"
},
@@ -51,24 +51,24 @@
},
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/extensions/README.md",
"devDependencies": {
"@0x/abi-gen": "^5.1.2",
"@0x/contract-addresses": "^4.4.0",
"@0x/contract-wrappers": "^13.4.2",
"@0x/contracts-broker": "^1.0.1",
"@0x/contracts-coordinator": "^3.0.6",
"@0x/contracts-dev-utils": "^1.0.6",
"@0x/contracts-exchange-forwarder": "^4.1.0",
"@0x/contracts-exchange-libs": "^4.2.0",
"@0x/contracts-extensions": "^6.0.0",
"@0x/contracts-gen": "^2.0.6",
"@0x/contracts-utils": "^4.2.1",
"@0x/abi-gen": "^5.2.0",
"@0x/contract-addresses": "^4.5.0",
"@0x/contract-wrappers": "^13.5.0",
"@0x/contracts-broker": "^1.0.2",
"@0x/contracts-coordinator": "^3.1.0",
"@0x/contracts-dev-utils": "^1.1.0",
"@0x/contracts-exchange-forwarder": "^4.2.0",
"@0x/contracts-exchange-libs": "^4.3.0",
"@0x/contracts-extensions": "^6.1.0",
"@0x/contracts-gen": "^2.0.7",
"@0x/contracts-utils": "^4.3.0",
"@0x/coordinator-server": "^1.0.5",
"@0x/dev-utils": "^3.1.3",
"@0x/migrations": "^6.0.2",
"@0x/order-utils": "^10.1.3",
"@0x/sol-compiler": "^4.0.6",
"@0x/dev-utils": "^3.2.0",
"@0x/migrations": "^6.1.0",
"@0x/order-utils": "^10.2.0",
"@0x/sol-compiler": "^4.0.7",
"@0x/tslint-config": "^4.0.0",
"@0x/web3-wrapper": "^7.0.5",
"@0x/web3-wrapper": "^7.0.6",
"@azure/core-asynciterator-polyfill": "^1.0.0",
"@types/lodash": "4.14.104",
"@types/mocha": "^5.2.7",
@@ -91,20 +91,20 @@
"typescript": "3.0.1"
},
"dependencies": {
"@0x/asset-swapper": "^4.1.1",
"@0x/base-contract": "^6.1.2",
"@0x/contracts-asset-proxy": "^3.1.3",
"@0x/contracts-erc1155": "^2.0.6",
"@0x/contracts-erc20": "^3.0.6",
"@0x/contracts-erc721": "^3.0.6",
"@0x/contracts-exchange": "^3.1.2",
"@0x/contracts-multisig": "^4.0.6",
"@0x/contracts-staking": "^2.0.6",
"@0x/contracts-test-utils": "^5.1.3",
"@0x/types": "^3.1.1",
"@0x/typescript-typings": "^5.0.1",
"@0x/utils": "^5.3.0",
"ethereum-types": "^3.0.0",
"@0x/asset-swapper": "^4.1.2",
"@0x/base-contract": "^6.2.0",
"@0x/contracts-asset-proxy": "^3.2.0",
"@0x/contracts-erc1155": "^2.1.0",
"@0x/contracts-erc20": "^3.1.0",
"@0x/contracts-erc721": "^3.1.0",
"@0x/contracts-exchange": "^3.2.0",
"@0x/contracts-multisig": "^4.1.0",
"@0x/contracts-staking": "^2.0.7",
"@0x/contracts-test-utils": "^5.1.4",
"@0x/types": "^3.1.2",
"@0x/typescript-typings": "^5.0.2",
"@0x/utils": "^5.4.0",
"ethereum-types": "^3.1.0",
"ethereumjs-util": "^6.2.0",
"lodash": "^4.17.11"
},

View File

@@ -1,5 +1,5 @@
import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { IAssetDataContract } from '@0x/contracts-asset-proxy';
import { encodeERC20AssetData } from '@0x/contracts-asset-proxy';
import { ExchangeContract } from '@0x/contracts-exchange';
import { blockchainTests, constants, expect, OrderFactory } from '@0x/contracts-test-utils';
import { defaultOrmConfig, getAppAsync } from '@0x/coordinator-server';
@@ -22,7 +22,6 @@ const DEFAULT_PROTOCOL_FEE_MULTIPLIER = new BigNumber(150000);
blockchainTests.skip('Coordinator Client', env => {
const takerTokenFillAmount = new BigNumber(0);
const chainId = 1337;
const assetDataEncoder = new IAssetDataContract(constants.NULL_ADDRESS, env.provider);
let contractAddresses: ContractAddresses;
let coordinatorRegistry: CoordinatorRegistryContract;
@@ -80,9 +79,9 @@ blockchainTests.skip('Coordinator Client', env => {
const [makerTokenAddress, takerTokenAddress] = tokenUtils.getDummyERC20TokenAddresses();
const feeTokenAddress = contractAddresses.zrxToken;
[makerAssetData, takerAssetData, feeAssetData] = [
assetDataEncoder.ERC20Token(makerTokenAddress).getABIEncodedTransactionData(),
assetDataEncoder.ERC20Token(takerTokenAddress).getABIEncodedTransactionData(),
assetDataEncoder.ERC20Token(feeTokenAddress).getABIEncodedTransactionData(),
encodeERC20AssetData(makerTokenAddress),
encodeERC20AssetData(takerTokenAddress),
encodeERC20AssetData(feeTokenAddress),
];
// set initial balances

View File

@@ -1,3 +1,4 @@
import { encodeERC20AssetData } from '@0x/contracts-asset-proxy';
import { CoordinatorContract, CoordinatorRevertErrors, SignedCoordinatorApproval } from '@0x/contracts-coordinator';
import {
ExchangeCancelEventArgs,
@@ -60,18 +61,10 @@ blockchainTests.resets('Coordinator integration tests', env => {
orderConfig: {
senderAddress: coordinator.address,
feeRecipientAddress: feeRecipient.address,
makerAssetData: deployment.assetDataEncoder
.ERC20Token(makerToken.address)
.getABIEncodedTransactionData(),
takerAssetData: deployment.assetDataEncoder
.ERC20Token(takerToken.address)
.getABIEncodedTransactionData(),
makerFeeAssetData: deployment.assetDataEncoder
.ERC20Token(makerFeeToken.address)
.getABIEncodedTransactionData(),
takerFeeAssetData: deployment.assetDataEncoder
.ERC20Token(takerFeeToken.address)
.getABIEncodedTransactionData(),
makerAssetData: encodeERC20AssetData(makerToken.address),
takerAssetData: encodeERC20AssetData(takerToken.address),
makerFeeAssetData: encodeERC20AssetData(makerFeeToken.address),
takerFeeAssetData: encodeERC20AssetData(takerFeeToken.address),
},
});
@@ -126,7 +119,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
order = await maker.signOrderAsync();
data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, [order]);
transaction = await taker.signTransactionAsync({ data });
approval = await feeRecipient.signCoordinatorApprovalAsync(transaction, taker.address);
approval = feeRecipient.signCoordinatorApproval(transaction, taker.address);
});
it(`${fnName} should fill the order with a signed approval`, async () => {
@@ -260,7 +253,7 @@ blockchainTests.resets('Coordinator integration tests', env => {
orders = [await maker.signOrderAsync(), await maker.signOrderAsync()];
data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders);
transaction = await taker.signTransactionAsync({ data });
approval = await feeRecipient.signCoordinatorApprovalAsync(transaction, taker.address);
approval = feeRecipient.signCoordinatorApproval(transaction, taker.address);
});
it(`${fnName} should fill the orders with a signed approval`, async () => {

View File

@@ -26,8 +26,9 @@ blockchainTests.fork.resets('DevUtils mainnet tests', env => {
before(async () => {
[noDaiAddress] = await env.getAccountAddressesAsync();
devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
devUtilsArtifacts.DevUtils,
devUtilsArtifacts,
env.provider,
env.txDefaults,
devUtilsArtifacts,

View File

@@ -19,8 +19,9 @@ blockchainTests('DevUtils.getOrderHash', env => {
exchangeArtifacts,
new BigNumber(chainId),
);
devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
artifacts.DevUtils,
artifacts,
env.provider,
env.txDefaults,
artifacts,

View File

@@ -1,13 +1,13 @@
import * as crypto from 'crypto';
import { artifacts as proxyArtifacts, TestStaticCallTargetContract } from '@0x/contracts-asset-proxy';
import { artifacts, LibAssetDataContract } from '@0x/contracts-dev-utils';
import { artifacts, DevUtilsContract } from '@0x/contracts-dev-utils';
import { ERC1155MintableContract } from '@0x/contracts-erc1155';
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
import { AssetProxyId } from '@0x/types';
import { BigNumber, hexUtils, LibBytesRevertErrors, StringRevertError } from '@0x/utils';
import { BigNumber, hexUtils, LibBytesRevertErrors } from '@0x/utils';
import { Actor } from '../framework/actors/base';
import { DeploymentManager } from '../framework/deployment_manager';
@@ -53,7 +53,7 @@ const KNOWN_STATIC_CALL_ENCODING = {
blockchainTests.resets('LibAssetData', env => {
let deployment: DeploymentManager;
let staticCallTarget: TestStaticCallTargetContract;
let libAssetData: LibAssetDataContract;
let devUtils: DevUtilsContract;
let tokenOwner: Actor;
@@ -73,8 +73,9 @@ blockchainTests.resets('LibAssetData', env => {
});
tokenOwner = new Actor({ name: 'Token Owner', deployment });
libAssetData = await LibAssetDataContract.deployFrom0xArtifactAsync(
artifacts.LibAssetData,
devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
artifacts.DevUtils,
artifacts,
env.provider,
env.txDefaults,
artifacts,
@@ -104,7 +105,7 @@ blockchainTests.resets('LibAssetData', env => {
});
it('should have a deployed-to address', () => {
expect(libAssetData.address.slice(0, 2)).to.equal('0x');
expect(devUtils.address.slice(0, 2)).to.equal('0x');
});
describe('encoding and decoding', () => {
@@ -117,17 +118,17 @@ blockchainTests.resets('LibAssetData', env => {
];
for (const [assetData, proxyId] of assetDataScenarios) {
expect(await libAssetData.decodeAssetProxyId(assetData).callAsync()).to.equal(proxyId);
expect(await devUtils.decodeAssetProxyId(assetData).callAsync()).to.equal(proxyId);
}
});
it('should encode ERC20 asset data', async () => {
expect(await libAssetData.encodeERC20AssetData(KNOWN_ERC20_ENCODING.address).callAsync()).to.equal(
expect(await devUtils.encodeERC20AssetData(KNOWN_ERC20_ENCODING.address).callAsync()).to.equal(
KNOWN_ERC20_ENCODING.assetData,
);
});
it('should decode ERC20 asset data', async () => {
expect(await libAssetData.decodeERC20AssetData(KNOWN_ERC20_ENCODING.assetData).callAsync()).to.deep.equal([
expect(await devUtils.decodeERC20AssetData(KNOWN_ERC20_ENCODING.assetData).callAsync()).to.deep.equal([
AssetProxyId.ERC20,
KNOWN_ERC20_ENCODING.address,
]);
@@ -135,21 +136,23 @@ blockchainTests.resets('LibAssetData', env => {
it('should encode ERC721 asset data', async () => {
expect(
await libAssetData
await devUtils
.encodeERC721AssetData(KNOWN_ERC721_ENCODING.address, KNOWN_ERC721_ENCODING.tokenId)
.callAsync(),
).to.equal(KNOWN_ERC721_ENCODING.assetData);
});
it('should decode ERC721 asset data', async () => {
expect(await libAssetData.decodeERC721AssetData(KNOWN_ERC721_ENCODING.assetData).callAsync()).to.deep.equal(
[AssetProxyId.ERC721, KNOWN_ERC721_ENCODING.address, KNOWN_ERC721_ENCODING.tokenId],
);
expect(await devUtils.decodeERC721AssetData(KNOWN_ERC721_ENCODING.assetData).callAsync()).to.deep.equal([
AssetProxyId.ERC721,
KNOWN_ERC721_ENCODING.address,
KNOWN_ERC721_ENCODING.tokenId,
]);
});
it('should encode ERC1155 asset data', async () => {
expect(
await libAssetData
await devUtils
.encodeERC1155AssetData(
KNOWN_ERC1155_ENCODING.tokenAddress,
KNOWN_ERC1155_ENCODING.tokenIds,
@@ -161,9 +164,7 @@ blockchainTests.resets('LibAssetData', env => {
});
it('should decode ERC1155 asset data', async () => {
expect(
await libAssetData.decodeERC1155AssetData(KNOWN_ERC1155_ENCODING.assetData).callAsync(),
).to.deep.equal([
expect(await devUtils.decodeERC1155AssetData(KNOWN_ERC1155_ENCODING.assetData).callAsync()).to.deep.equal([
AssetProxyId.ERC1155,
KNOWN_ERC1155_ENCODING.tokenAddress,
KNOWN_ERC1155_ENCODING.tokenIds,
@@ -174,7 +175,7 @@ blockchainTests.resets('LibAssetData', env => {
it('should encode multiasset data', async () => {
expect(
await libAssetData
await devUtils
.encodeMultiAssetData(
KNOWN_MULTI_ASSET_ENCODING.amounts,
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
@@ -184,18 +185,18 @@ blockchainTests.resets('LibAssetData', env => {
});
it('should decode multiasset data', async () => {
expect(
await libAssetData.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData).callAsync(),
).to.deep.equal([
AssetProxyId.MultiAsset,
KNOWN_MULTI_ASSET_ENCODING.amounts,
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
]);
expect(await devUtils.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData).callAsync()).to.deep.equal(
[
AssetProxyId.MultiAsset,
KNOWN_MULTI_ASSET_ENCODING.amounts,
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
],
);
});
it('should encode StaticCall data', async () => {
expect(
await libAssetData
await devUtils
.encodeStaticCallAssetData(
KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress,
KNOWN_STATIC_CALL_ENCODING.staticCallData,
@@ -207,7 +208,7 @@ blockchainTests.resets('LibAssetData', env => {
it('should decode StaticCall data', async () => {
expect(
await libAssetData.decodeStaticCallAssetData(KNOWN_STATIC_CALL_ENCODING.assetData).callAsync(),
await devUtils.decodeStaticCallAssetData(KNOWN_STATIC_CALL_ENCODING.assetData).callAsync(),
).to.deep.equal([
AssetProxyId.StaticCall,
KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress,
@@ -227,16 +228,14 @@ blockchainTests.resets('LibAssetData', env => {
];
for (const data of assetData) {
await libAssetData.revertIfInvalidAssetData(data).callAsync();
await devUtils.revertIfInvalidAssetData(data).callAsync();
}
return;
});
it('should revert for invalid assetProxyId', async () => {
const badAssetData = `0x${crypto.randomBytes(4).toString('hex')}${constants.NULL_ADDRESS}`;
await expect(libAssetData.revertIfInvalidAssetData(badAssetData).callAsync()).to.eventually.be.rejectedWith(
StringRevertError,
);
await expect(devUtils.revertIfInvalidAssetData(badAssetData).callAsync()).to.revertWith('WRONG_PROXY_ID');
});
it('should revert for invalid assetData with valid assetProxyId', async () => {
@@ -245,8 +244,8 @@ blockchainTests.resets('LibAssetData', env => {
for (const data of assetData) {
const badData = data.substring(0, data.length - 2); // drop one byte but retain assetProxyId
await expect(libAssetData.revertIfInvalidAssetData(badData).callAsync()).to.eventually.be.rejectedWith(
LibBytesRevertErrors.InvalidByteOperationError,
await expect(devUtils.revertIfInvalidAssetData(badData).callAsync()).to.revertWith(
new LibBytesRevertErrors.InvalidByteOperationError(),
);
}
});
@@ -254,33 +253,31 @@ blockchainTests.resets('LibAssetData', env => {
describe('getBalance', () => {
it('should query ERC20 balance by asset data', async () => {
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
constants.INITIAL_ERC20_BALANCE,
);
});
it('should return 0 if ERC20 token does not exist', async () => {
const assetData = await libAssetData.encodeERC20AssetData(constants.NULL_ADDRESS).callAsync();
const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync();
const assetData = await devUtils.encodeERC20AssetData(constants.NULL_ADDRESS).callAsync();
const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync();
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
});
it('should query ERC721 balance by asset data', async () => {
const assetData = await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
const assetData = await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
});
it('should return 0 if ERC721 token does not exist', async () => {
const assetData = await libAssetData
.encodeERC721AssetData(constants.NULL_ADDRESS, erc721TokenId)
.callAsync();
const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync();
const assetData = await devUtils.encodeERC721AssetData(constants.NULL_ADDRESS, erc721TokenId).callAsync();
const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync();
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
});
it('should query ERC1155 balances by asset data', async () => {
const assetData = await libAssetData
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155Token.address,
[erc1155TokenId],
@@ -288,11 +285,11 @@ blockchainTests.resets('LibAssetData', env => {
constants.NULL_BYTES,
)
.callAsync();
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
});
it('should return 0 if ERC1155 token does not exist', async () => {
const assetData = await libAssetData
const assetData = await devUtils
.encodeERC1155AssetData(
constants.NULL_ADDRESS,
[erc1155TokenId],
@@ -300,84 +297,84 @@ blockchainTests.resets('LibAssetData', env => {
constants.NULL_BYTES,
)
.callAsync();
const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync();
const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync();
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
});
it('should query multi-asset batch balance by asset data', async () => {
const assetData = await libAssetData
const assetData = await devUtils
.encodeMultiAssetData(
[new BigNumber(1), new BigNumber(1)],
[
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
],
)
.callAsync();
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
});
it('should query multi-asset batch balance by asset data, skipping over a nested asset if its amount == 0', async () => {
const assetData = await libAssetData
const assetData = await devUtils
.encodeMultiAssetData(
[constants.ZERO_AMOUNT, new BigNumber(1)],
[
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
],
)
.callAsync();
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
});
it('should return a balance of 0 if the balance for a nested asset is 0', async () => {
const assetData = await libAssetData
const assetData = await devUtils
.encodeMultiAssetData(
[new BigNumber(1), new BigNumber(1)],
[
await libAssetData.encodeERC20AssetData(secondErc20Token.address).callAsync(),
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
await devUtils.encodeERC20AssetData(secondErc20Token.address).callAsync(),
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
],
)
.callAsync();
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
constants.ZERO_AMOUNT,
);
});
it('should return a balance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
const fakeAssetData = '0x01020304';
const balance = await libAssetData.getBalance(tokenOwner.address, fakeAssetData).callAsync();
const balance = await devUtils.getBalance(tokenOwner.address, fakeAssetData).callAsync();
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
});
it('should return a balance of MAX_UINT256 if the the StaticCallProxy assetData contains data for a successful staticcall', async () => {
const staticCallData = staticCallTarget.isOddNumber(new BigNumber(1)).getABIEncodedTransactionData();
const expectedResultHash = hexUtils.hash(hexUtils.leftPad(1));
const assetData = await libAssetData
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync();
const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync();
expect(balance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
});
it('should return a balance of 0 if the the StaticCallProxy assetData contains data for an unsuccessful staticcall', async () => {
const staticCallData = staticCallTarget.isOddNumber(new BigNumber(0)).getABIEncodedTransactionData();
const expectedResultHash = hexUtils.hash(hexUtils.leftPad(1));
const assetData = await libAssetData
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
.callAsync();
const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync();
const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync();
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
});
});
describe('getAssetProxyAllowance', () => {
it('should query ERC20 allowances by asset data', async () => {
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
expect(
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
).to.bignumber.equal(constants.MAX_UINT256);
const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
constants.MAX_UINT256,
);
});
it('should query ERC721 approval by asset data', async () => {
@@ -390,21 +387,21 @@ blockchainTests.resets('LibAssetData', env => {
.awaitTransactionSuccessAsync({
from: tokenOwner.address,
});
const assetData = await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
expect(
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
).to.bignumber.equal(1);
const assetData = await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
1,
);
});
it('should query ERC721 approvalForAll by assetData', async () => {
const assetData = await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
expect(
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
const assetData = await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
);
});
it('should query ERC1155 allowances by asset data', async () => {
const assetData = await libAssetData
const assetData = await devUtils
.encodeERC1155AssetData(
erc1155Token.address,
[erc1155TokenId],
@@ -412,9 +409,9 @@ blockchainTests.resets('LibAssetData', env => {
constants.NULL_BYTES,
)
.callAsync();
expect(
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
);
});
it('should query multi-asset allowances by asset data', async () => {
@@ -424,18 +421,18 @@ blockchainTests.resets('LibAssetData', env => {
.awaitTransactionSuccessAsync({
from: tokenOwner.address,
});
const assetData = await libAssetData
const assetData = await devUtils
.encodeMultiAssetData(
[new BigNumber(1), new BigNumber(1)],
[
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
],
)
.callAsync();
expect(
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
).to.bignumber.equal(1);
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
1,
);
return;
});
@@ -446,60 +443,60 @@ blockchainTests.resets('LibAssetData', env => {
.awaitTransactionSuccessAsync({
from: tokenOwner.address,
});
const assetData = await libAssetData
const assetData = await devUtils
.encodeMultiAssetData(
[constants.ZERO_AMOUNT, new BigNumber(1)],
[
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
],
)
.callAsync();
expect(
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
);
return;
});
it('should return an allowance of 0 if the allowance for a nested asset is 0', async () => {
const assetData = await libAssetData
const assetData = await devUtils
.encodeMultiAssetData(
[new BigNumber(1), new BigNumber(1)],
[
await libAssetData.encodeERC20AssetData(secondErc20Token.address).callAsync(),
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
await devUtils.encodeERC20AssetData(secondErc20Token.address).callAsync(),
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
],
)
.callAsync();
expect(
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
).to.bignumber.equal(constants.ZERO_AMOUNT);
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
constants.ZERO_AMOUNT,
);
});
it('should return an allowance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
const fakeAssetData = '0x01020304';
const allowance = await libAssetData.getAssetProxyAllowance(tokenOwner.address, fakeAssetData).callAsync();
const allowance = await devUtils.getAssetProxyAllowance(tokenOwner.address, fakeAssetData).callAsync();
expect(allowance).to.bignumber.equal(constants.ZERO_AMOUNT);
});
it('should return an allowance of MAX_UINT256 for any staticCallAssetData', async () => {
const staticCallData = AssetProxyId.StaticCall;
const assetData = await libAssetData
const assetData = await devUtils
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, constants.KECCAK256_NULL)
.callAsync();
const allowance = await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync();
const allowance = await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync();
expect(allowance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
});
});
describe('getBatchBalances', () => {
it('should query balances for a batch of asset data strings', async () => {
const erc20AssetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
const erc721AssetData = await libAssetData
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721Token.address, erc721TokenId)
.callAsync();
expect(
await libAssetData.getBatchBalances(tokenOwner.address, [erc20AssetData, erc721AssetData]).callAsync(),
await devUtils.getBatchBalances(tokenOwner.address, [erc20AssetData, erc721AssetData]).callAsync(),
).to.deep.equal([new BigNumber(constants.INITIAL_ERC20_BALANCE), new BigNumber(1)]);
});
});
@@ -512,9 +509,9 @@ blockchainTests.resets('LibAssetData', env => {
.awaitTransactionSuccessAsync({
from: tokenOwner.address,
});
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
expect(
await libAssetData.getBalanceAndAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
await devUtils.getBalanceAndAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
).to.deep.equal([new BigNumber(constants.INITIAL_ERC20_BALANCE), allowance]);
});
});
@@ -526,9 +523,9 @@ blockchainTests.resets('LibAssetData', env => {
.awaitTransactionSuccessAsync({
from: tokenOwner.address,
});
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
expect(
await libAssetData.getBatchBalancesAndAssetProxyAllowances(tokenOwner.address, [assetData]).callAsync(),
await devUtils.getBatchBalancesAndAssetProxyAllowances(tokenOwner.address, [assetData]).callAsync(),
).to.deep.equal([[new BigNumber(constants.INITIAL_ERC20_BALANCE)], [allowance]]);
});
});
@@ -541,12 +538,12 @@ blockchainTests.resets('LibAssetData', env => {
.awaitTransactionSuccessAsync({
from: tokenOwner.address,
});
const erc20AssetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
const erc721AssetData = await libAssetData
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
const erc721AssetData = await devUtils
.encodeERC721AssetData(erc721Token.address, erc721TokenId)
.callAsync();
expect(
await libAssetData
await devUtils
.getBatchAssetProxyAllowances(tokenOwner.address, [erc20AssetData, erc721AssetData])
.callAsync(),
).to.deep.equal([allowance, constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS]);

View File

@@ -1,14 +1,8 @@
import { ExchangeContract } from '@0x/contracts-exchange';
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
import { BlockchainLifecycle } from '@0x/dev-utils';
import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange';
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
import { BigNumber } from '@0x/utils';
import * as chai from 'chai';
import { artifacts, LibTransactionDecoderContract } from '@0x/contracts-dev-utils';
chaiSetup.configure();
const expect = chai.expect;
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
import { artifacts, DevUtilsContract } from '@0x/contracts-dev-utils';
const order = {
makerAddress: '0xe36ea790bc9d7ab70c55260c66d52b1eca985f84',
@@ -30,25 +24,31 @@ const takerAssetFillAmount = new BigNumber('100000000000000000000');
const signature =
'0x1ce8e3c600d933423172b5021158a6be2e818613ff8e762d70ef490c752fd98a626a215f09f169668990414de75a53da221c294a3002f796d004827258b641876e03';
describe('LibTransactionDecoder', () => {
let libTxDecoder: LibTransactionDecoderContract;
const exchangeInterface = new ExchangeContract(constants.NULL_ADDRESS, provider, txDefaults);
blockchainTests('LibTransactionDecoder', env => {
let devUtils: DevUtilsContract;
const exchangeInterface = new ExchangeContract(constants.NULL_ADDRESS, { isEIP1193: true } as any);
before(async () => {
await blockchainLifecycle.startAsync();
libTxDecoder = await LibTransactionDecoderContract.deployFrom0xArtifactAsync(
artifacts.LibTransactionDecoder,
provider,
txDefaults,
artifacts,
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
exchangeArtifacts.Exchange,
env.provider,
env.txDefaults,
exchangeArtifacts,
new BigNumber(1),
);
devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
artifacts.DevUtils,
artifacts,
env.provider,
env.txDefaults,
artifacts,
exchange.address,
constants.NULL_ADDRESS,
);
});
after(async () => {
await blockchainLifecycle.revertAsync();
});
it('should decode an Exchange.batchCancelOrders() transaction', async () => {
const input = exchangeInterface.batchCancelOrders([order, order]).getABIEncodedTransactionData();
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
'batchCancelOrders',
[order, order],
[],
@@ -61,7 +61,7 @@ describe('LibTransactionDecoder', () => {
[func]([order, order], [takerAssetFillAmount, takerAssetFillAmount], [signature, signature])
.getABIEncodedTransactionData();
it(`should decode an Exchange.${func}() transaction`, async () => {
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
func,
[order, order],
[takerAssetFillAmount, takerAssetFillAmount],
@@ -72,7 +72,7 @@ describe('LibTransactionDecoder', () => {
it('should decode an Exchange.cancelOrder() transaction', async () => {
const input = exchangeInterface.cancelOrder(order).getABIEncodedTransactionData();
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
'cancelOrder',
[order],
[],
@@ -85,7 +85,7 @@ describe('LibTransactionDecoder', () => {
[func](order, takerAssetFillAmount, signature)
.getABIEncodedTransactionData();
it(`should decode an Exchange.${func}() transaction`, async () => {
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
func,
[order],
[takerAssetFillAmount],
@@ -104,7 +104,7 @@ describe('LibTransactionDecoder', () => {
[func]([order, order], takerAssetFillAmount, [signature, signature])
.getABIEncodedTransactionData();
it(`should decode an Exchange.${func}() transaction`, async () => {
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
func,
[order, order],
[takerAssetFillAmount],
@@ -130,7 +130,7 @@ describe('LibTransactionDecoder', () => {
const input = exchangeInterface
.matchOrders(order, complementaryOrder, signature, signature)
.getABIEncodedTransactionData();
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
'matchOrders',
[order, complementaryOrder],
[order.takerAssetAmount, complementaryOrder.takerAssetAmount],

View File

@@ -1,3 +1,4 @@
import { encodeERC1155AssetData, encodeERC20AssetData, encodeERC721AssetData } from '@0x/contracts-asset-proxy';
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
import { ExchangeRevertErrors } from '@0x/contracts-exchange';
import { blockchainTests, constants, expect, toBaseUnitAmount } from '@0x/contracts-test-utils';
@@ -61,13 +62,9 @@ blockchainTests.resets('matchOrders integration tests', env => {
});
// Encode the asset data.
makerAssetDataLeft = deployment.assetDataEncoder
.ERC20Token(makerAssetLeft.address)
.getABIEncodedTransactionData();
makerAssetDataRight = deployment.assetDataEncoder
.ERC20Token(makerAssetRight.address)
.getABIEncodedTransactionData();
feeAssetData = deployment.assetDataEncoder.ERC20Token(feeAsset.address).getABIEncodedTransactionData();
makerAssetDataLeft = encodeERC20AssetData(makerAssetLeft.address);
makerAssetDataRight = encodeERC20AssetData(makerAssetRight.address);
feeAssetData = encodeERC20AssetData(feeAsset.address);
// Create two market makers with compatible orders for matching.
makerLeft = new Maker({
@@ -812,12 +809,13 @@ blockchainTests.resets('matchOrders integration tests', env => {
describe('token sanity checks', () => {
it('should be able to match ERC721 tokens with ERC1155 tokens', async () => {
const leftMakerAssetData = deployment.assetDataEncoder
.ERC1155Assets(deployment.tokens.erc1155[0].address, [leftId], [new BigNumber(1)], '0x')
.getABIEncodedTransactionData();
const rightMakerAssetData = deployment.assetDataEncoder
.ERC721Token(deployment.tokens.erc721[0].address, rightId)
.getABIEncodedTransactionData();
const leftMakerAssetData = encodeERC1155AssetData(
deployment.tokens.erc1155[0].address,
[leftId],
[new BigNumber(1)],
'0x',
);
const rightMakerAssetData = encodeERC721AssetData(deployment.tokens.erc721[0].address, rightId);
const signedOrderLeft = await makerLeft.signOrderAsync({
makerAssetAmount: new BigNumber(4),

Some files were not shown because too many files have changed in this diff Show More