Cherry pick DevUtils
refactor code from #2456
This commit is contained in:
parent
8635849977
commit
4016808fa4
@ -1,4 +1,17 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "1.1.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Refactor mixins into public libraries.",
|
||||||
|
"pr": 2464
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Remove `LibTransactionDecoder` export",
|
||||||
|
"pr": 2464
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1580988106,
|
"timestamp": 1580988106,
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
|
51
contracts/dev-utils/contracts/src/Addresses.sol
Normal file
51
contracts/dev-utils/contracts/src/Addresses.sol
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
374
contracts/dev-utils/contracts/src/AssetBalance.sol
Normal file
374
contracts/dev-utils/contracts/src/AssetBalance.sol
Normal 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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pragma solidity ^0.5.5;
|
pragma solidity ^0.5.16;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol";
|
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-exchange-libs/contracts/src/LibZeroExTransaction.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/LibEIP712.sol";
|
import "@0x/contracts-utils/contracts/src/LibEIP712.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||||
|
import "./Addresses.sol";
|
||||||
import "./OrderValidationUtils.sol";
|
import "./OrderValidationUtils.sol";
|
||||||
import "./OrderTransferSimulationUtils.sol";
|
|
||||||
import "./EthBalanceChecker.sol";
|
import "./EthBalanceChecker.sol";
|
||||||
|
import "./ExternalFunctions.sol";
|
||||||
|
|
||||||
|
|
||||||
// solhint-disable no-empty-blocks
|
// solhint-disable no-empty-blocks
|
||||||
contract DevUtils is
|
contract DevUtils is
|
||||||
|
Addresses,
|
||||||
OrderValidationUtils,
|
OrderValidationUtils,
|
||||||
LibEIP712ExchangeDomain,
|
LibEIP712ExchangeDomain,
|
||||||
EthBalanceChecker
|
EthBalanceChecker,
|
||||||
|
ExternalFunctions
|
||||||
{
|
{
|
||||||
constructor (
|
constructor (
|
||||||
address _exchange,
|
address exchange_,
|
||||||
address _chaiBridge
|
address chaiBridge_
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
OrderValidationUtils(
|
Addresses(
|
||||||
_exchange,
|
exchange_,
|
||||||
_chaiBridge
|
chaiBridge_
|
||||||
)
|
)
|
||||||
OrderTransferSimulationUtils(_exchange)
|
|
||||||
LibEIP712ExchangeDomain(uint256(0), address(0)) // null args because because we only use constants
|
LibEIP712ExchangeDomain(uint256(0), address(0)) // null args because because we only use constants
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pragma solidity ^0.5.5;
|
pragma solidity ^0.5.16;
|
||||||
|
|
||||||
|
|
||||||
contract EthBalanceChecker {
|
contract EthBalanceChecker {
|
||||||
|
322
contracts/dev-utils/contracts/src/ExternalFunctions.sol
Normal file
322
contracts/dev-utils/contracts/src/ExternalFunctions.sol
Normal 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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -16,357 +16,17 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pragma solidity ^0.5.5;
|
pragma solidity ^0.5.16;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
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/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
|
library LibAssetData {
|
||||||
DeploymentConstants
|
|
||||||
{
|
|
||||||
// 2^256 - 1
|
|
||||||
uint256 constant internal _MAX_UINT256 = uint256(-1);
|
|
||||||
|
|
||||||
using LibBytes for bytes;
|
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
|
/// @dev Decode AssetProxy identifier
|
||||||
/// @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC-721, ERC1155, or MultiAsset asset.
|
/// @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC-721, ERC1155, or MultiAsset asset.
|
||||||
/// @return The AssetProxy identifier
|
/// @return The AssetProxy identifier
|
||||||
@ -691,44 +351,4 @@ contract LibAssetData is
|
|||||||
revert("WRONG_PROXY_ID");
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
227
contracts/dev-utils/contracts/src/LibOrderTransferSimulation.sol
Normal file
227
contracts/dev-utils/contracts/src/LibOrderTransferSimulation.sol
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pragma solidity ^0.5.5;
|
pragma solidity ^0.5.16;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
|
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";
|
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||||
|
|
||||||
|
|
||||||
contract LibTransactionDecoder {
|
library LibTransactionDecoder {
|
||||||
|
|
||||||
using LibBytes for bytes;
|
using LibBytes for bytes;
|
||||||
|
|
||||||
|
@ -16,36 +16,26 @@
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pragma solidity ^0.5.9;
|
pragma solidity ^0.5.16;
|
||||||
pragma experimental ABIEncoderV2;
|
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/LibOrder.sol";
|
||||||
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
|
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||||
|
import "./Addresses.sol";
|
||||||
|
import "./AssetBalance.sol";
|
||||||
import "./LibAssetData.sol";
|
import "./LibAssetData.sol";
|
||||||
import "./OrderTransferSimulationUtils.sol";
|
import "./LibOrderTransferSimulation.sol";
|
||||||
|
|
||||||
|
|
||||||
contract OrderValidationUtils is
|
contract OrderValidationUtils is
|
||||||
LibAssetData,
|
Addresses,
|
||||||
OrderTransferSimulationUtils
|
AssetBalance
|
||||||
{
|
{
|
||||||
using LibBytes for bytes;
|
using LibBytes for bytes;
|
||||||
using LibSafeMath for uint256;
|
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.
|
/// @dev Fetches all order-relevant information needed to validate if the supplied order is fillable.
|
||||||
/// @param order The order structure.
|
/// @param order The order structure.
|
||||||
/// @param signature Signature provided by maker that proves the order's authenticity.
|
/// @param signature Signature provided by maker that proves the order's authenticity.
|
||||||
@ -65,23 +55,22 @@ contract OrderValidationUtils is
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Get info specific to order
|
// Get info specific to order
|
||||||
orderInfo = _EXCHANGE.getOrderInfo(order);
|
orderInfo = IExchange(exchangeAddress).getOrderInfo(order);
|
||||||
|
|
||||||
// Validate the maker's signature
|
// Validate the maker's signature
|
||||||
address makerAddress = order.makerAddress;
|
address makerAddress = order.makerAddress;
|
||||||
isValidSignature = _EXCHANGE.isValidOrderSignature(
|
isValidSignature = IExchange(exchangeAddress).isValidOrderSignature(
|
||||||
order,
|
order,
|
||||||
signature
|
signature
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get the transferable amount of the `makerAsset`
|
// 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
|
// Get the amount of `takerAsset` that is transferable to maker given the
|
||||||
uint256 takerAssetAmount = order.takerAssetAmount;
|
// transferability of `makerAsset`, `makerFeeAsset`,
|
||||||
uint256 makerFee = order.makerFee;
|
|
||||||
|
|
||||||
// Get the amount of `takerAsset` that is transferable to maker given the transferability of `makerAsset`, `makerFeeAsset`,
|
|
||||||
// and the total amounts specified in the order
|
// and the total amounts specified in the order
|
||||||
uint256 transferableTakerAssetAmount;
|
uint256 transferableTakerAssetAmount;
|
||||||
if (order.makerAssetData.equals(order.makerFeeAssetData)) {
|
if (order.makerAssetData.equals(order.makerFeeAssetData)) {
|
||||||
@ -89,32 +78,35 @@ contract OrderValidationUtils is
|
|||||||
// transferableMakerAssetAmount / (makerAssetAmount + makerFee)
|
// transferableMakerAssetAmount / (makerAssetAmount + makerFee)
|
||||||
transferableTakerAssetAmount = LibMath.getPartialAmountFloor(
|
transferableTakerAssetAmount = LibMath.getPartialAmountFloor(
|
||||||
transferableMakerAssetAmount,
|
transferableMakerAssetAmount,
|
||||||
order.makerAssetAmount.safeAdd(makerFee),
|
order.makerAssetAmount.safeAdd(order.makerFee),
|
||||||
takerAssetAmount
|
order.takerAssetAmount
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// If `makerFee` is 0, the % that can be filled is (transferableMakerAssetAmount / makerAssetAmount)
|
// If `makerFee` is 0, the % that can be filled is (transferableMakerAssetAmount / makerAssetAmount)
|
||||||
if (makerFee == 0) {
|
if (order.makerFee == 0) {
|
||||||
transferableTakerAssetAmount = LibMath.getPartialAmountFloor(
|
transferableTakerAssetAmount = LibMath.getPartialAmountFloor(
|
||||||
transferableMakerAssetAmount,
|
transferableMakerAssetAmount,
|
||||||
order.makerAssetAmount,
|
order.makerAssetAmount,
|
||||||
takerAssetAmount
|
order.takerAssetAmount
|
||||||
);
|
);
|
||||||
|
|
||||||
// If `makerAsset` does not equal `makerFeeAsset`, the % that can be filled is the lower of
|
// If `makerAsset` does not equal `makerFeeAsset`, the % that can be filled is the lower of
|
||||||
// (transferableMakerAssetAmount / makerAssetAmount) and (transferableMakerAssetFeeAmount / makerFee)
|
// (transferableMakerAssetAmount / makerAssetAmount) and (transferableMakerAssetFeeAmount / makerFee)
|
||||||
} else {
|
} else {
|
||||||
// Get the transferable amount of the `makerFeeAsset`
|
// Get the transferable amount of the `makerFeeAsset`
|
||||||
uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount(makerAddress, order.makerFeeAssetData);
|
uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount(
|
||||||
|
makerAddress,
|
||||||
|
order.makerFeeAssetData
|
||||||
|
);
|
||||||
uint256 transferableMakerToTakerAmount = LibMath.getPartialAmountFloor(
|
uint256 transferableMakerToTakerAmount = LibMath.getPartialAmountFloor(
|
||||||
transferableMakerAssetAmount,
|
transferableMakerAssetAmount,
|
||||||
order.makerAssetAmount,
|
order.makerAssetAmount,
|
||||||
takerAssetAmount
|
order.takerAssetAmount
|
||||||
);
|
);
|
||||||
uint256 transferableMakerFeeToTakerAmount = LibMath.getPartialAmountFloor(
|
uint256 transferableMakerFeeToTakerAmount = LibMath.getPartialAmountFloor(
|
||||||
transferableMakerFeeAssetAmount,
|
transferableMakerFeeAssetAmount,
|
||||||
makerFee,
|
order.makerFee,
|
||||||
takerAssetAmount
|
order.takerAssetAmount
|
||||||
);
|
);
|
||||||
transferableTakerAssetAmount = LibSafeMath.min256(transferableMakerToTakerAmount, transferableMakerFeeToTakerAmount);
|
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` is the lower of the order's remaining `takerAssetAmount` and the `transferableTakerAssetAmount`
|
||||||
fillableTakerAssetAmount = LibSafeMath.min256(
|
fillableTakerAssetAmount = LibSafeMath.min256(
|
||||||
takerAssetAmount.safeSub(orderInfo.orderTakerAssetFilledAmount),
|
order.takerAssetAmount.safeSub(orderInfo.orderTakerAssetFilledAmount),
|
||||||
transferableTakerAssetAmount
|
transferableTakerAssetAmount
|
||||||
);
|
);
|
||||||
|
|
||||||
// Execute the maker transfers.
|
// Execute the maker transfers.
|
||||||
fillableTakerAssetAmount = getSimulatedOrderMakerTransferResults(
|
fillableTakerAssetAmount = LibOrderTransferSimulation.getSimulatedOrderMakerTransferResults(
|
||||||
|
exchangeAddress,
|
||||||
order,
|
order,
|
||||||
order.takerAddress,
|
order.takerAddress,
|
||||||
fillableTakerAssetAmount
|
fillableTakerAssetAmount
|
||||||
) == OrderTransferResults.TransfersSuccessful ? fillableTakerAssetAmount : 0;
|
) == LibOrderTransferSimulation.OrderTransferResults.TransfersSuccessful ? fillableTakerAssetAmount : 0;
|
||||||
|
|
||||||
if (!_isAssetDataValid(order.takerAssetData)) {
|
if (!_isAssetDataValid(order.takerAssetData)) {
|
||||||
fillableTakerAssetAmount = 0;
|
fillableTakerAssetAmount = 0;
|
||||||
@ -181,7 +174,7 @@ contract OrderValidationUtils is
|
|||||||
return (ordersInfo, fillableTakerAssetAmounts, isValidSignature);
|
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 ownerAddress Address of the owner of the asset.
|
||||||
/// @param assetData Description of tokens, per the AssetProxy contract specification.
|
/// @param assetData Description of tokens, per the AssetProxy contract specification.
|
||||||
/// @return The amount of the asset tranferable by the owner.
|
/// @return The amount of the asset tranferable by the owner.
|
||||||
@ -193,7 +186,26 @@ contract OrderValidationUtils is
|
|||||||
public
|
public
|
||||||
returns (uint256 transferableAssetAmount)
|
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);
|
transferableAssetAmount = LibSafeMath.min256(balance, allowance);
|
||||||
return transferableAssetAmount;
|
return transferableAssetAmount;
|
||||||
}
|
}
|
||||||
@ -221,7 +233,8 @@ contract OrderValidationUtils is
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get array of values and array of assetDatas
|
// 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;
|
uint256 length = nestedAssetData.length;
|
||||||
for (uint256 i = 0; i != length; i++) {
|
for (uint256 i = 0; i != length; i++) {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"main": "lib/src/index.js",
|
"main": "lib/src/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn pre_build && tsc -b",
|
"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)\"",
|
"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",
|
"build:ci": "yarn build",
|
||||||
"pre_build": "run-s compile quantify_bytecode contracts:gen generate_contract_wrappers contracts:copy",
|
"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"
|
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "DevUtils,LibAssetData,LibTransactionDecoder",
|
"publicInterfaceContracts": "DevUtils,LibAssetData,LibOrderTransferSimulation,LibTransactionDecoder",
|
||||||
"abis": "./test/generated-artifacts/@(DevUtils|EthBalanceChecker|LibAssetData|LibTransactionDecoder|OrderTransferSimulationUtils|OrderValidationUtils).json",
|
"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."
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@ -41,12 +41,17 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/dev-utils/README.md",
|
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/dev-utils/README.md",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@0x/contracts-asset-proxy": "^3.1.3",
|
||||||
|
"@0x/contracts-erc20": "^3.0.6",
|
||||||
|
"@0x/contracts-test-utils": "^5.1.3",
|
||||||
|
"@0x/types": "^3.1.1",
|
||||||
"@0x/abi-gen": "^5.1.2",
|
"@0x/abi-gen": "^5.1.2",
|
||||||
"@0x/assert": "^3.0.5",
|
"@0x/assert": "^3.0.5",
|
||||||
"@0x/contracts-gen": "^2.0.6",
|
"@0x/contracts-gen": "^2.0.6",
|
||||||
"@0x/sol-compiler": "^4.0.6",
|
"@0x/sol-compiler": "^4.0.6",
|
||||||
"@0x/ts-doc-gen": "^0.0.22",
|
"@0x/ts-doc-gen": "^0.0.22",
|
||||||
"@0x/tslint-config": "^4.0.0",
|
"@0x/tslint-config": "^4.0.0",
|
||||||
|
"@0x/utils": "^5.2.0",
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"ethereum-types": "^3.0.0",
|
"ethereum-types": "^3.0.0",
|
||||||
"ethers": "~4.0.4",
|
"ethers": "~4.0.4",
|
||||||
|
@ -7,9 +7,11 @@ import { ContractArtifact } from 'ethereum-types';
|
|||||||
|
|
||||||
import * as DevUtils from '../generated-artifacts/DevUtils.json';
|
import * as DevUtils from '../generated-artifacts/DevUtils.json';
|
||||||
import * as LibAssetData from '../generated-artifacts/LibAssetData.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';
|
import * as LibTransactionDecoder from '../generated-artifacts/LibTransactionDecoder.json';
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
DevUtils: DevUtils as ContractArtifact,
|
DevUtils: DevUtils as ContractArtifact,
|
||||||
LibAssetData: LibAssetData as ContractArtifact,
|
LibAssetData: LibAssetData as ContractArtifact,
|
||||||
|
LibOrderTransferSimulation: LibOrderTransferSimulation as ContractArtifact,
|
||||||
LibTransactionDecoder: LibTransactionDecoder as ContractArtifact,
|
LibTransactionDecoder: LibTransactionDecoder as ContractArtifact,
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
export { artifacts } from './artifacts';
|
export { artifacts } from './artifacts';
|
||||||
export { DevUtilsContract, LibAssetDataContract, LibTransactionDecoderContract } from './wrappers';
|
export { DevUtilsContract } from './wrappers';
|
||||||
export {
|
export {
|
||||||
ContractArtifact,
|
ContractArtifact,
|
||||||
ContractChains,
|
ContractChains,
|
||||||
|
@ -5,4 +5,5 @@
|
|||||||
*/
|
*/
|
||||||
export * from '../generated-wrappers/dev_utils';
|
export * from '../generated-wrappers/dev_utils';
|
||||||
export * from '../generated-wrappers/lib_asset_data';
|
export * from '../generated-wrappers/lib_asset_data';
|
||||||
|
export * from '../generated-wrappers/lib_order_transfer_simulation';
|
||||||
export * from '../generated-wrappers/lib_transaction_decoder';
|
export * from '../generated-wrappers/lib_transaction_decoder';
|
||||||
|
@ -5,16 +5,24 @@
|
|||||||
*/
|
*/
|
||||||
import { ContractArtifact } from 'ethereum-types';
|
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 DevUtils from '../test/generated-artifacts/DevUtils.json';
|
||||||
import * as EthBalanceChecker from '../test/generated-artifacts/EthBalanceChecker.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 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 LibTransactionDecoder from '../test/generated-artifacts/LibTransactionDecoder.json';
|
||||||
import * as OrderTransferSimulationUtils from '../test/generated-artifacts/OrderTransferSimulationUtils.json';
|
import * as OrderTransferSimulationUtils from '../test/generated-artifacts/OrderTransferSimulationUtils.json';
|
||||||
import * as OrderValidationUtils from '../test/generated-artifacts/OrderValidationUtils.json';
|
import * as OrderValidationUtils from '../test/generated-artifacts/OrderValidationUtils.json';
|
||||||
export const artifacts = {
|
export const artifacts = {
|
||||||
|
Addresses: Addresses as ContractArtifact,
|
||||||
|
AssetBalance: AssetBalance as ContractArtifact,
|
||||||
DevUtils: DevUtils as ContractArtifact,
|
DevUtils: DevUtils as ContractArtifact,
|
||||||
EthBalanceChecker: EthBalanceChecker as ContractArtifact,
|
EthBalanceChecker: EthBalanceChecker as ContractArtifact,
|
||||||
|
ExternalFunctions: ExternalFunctions as ContractArtifact,
|
||||||
LibAssetData: LibAssetData as ContractArtifact,
|
LibAssetData: LibAssetData as ContractArtifact,
|
||||||
|
LibOrderTransferSimulation: LibOrderTransferSimulation as ContractArtifact,
|
||||||
LibTransactionDecoder: LibTransactionDecoder as ContractArtifact,
|
LibTransactionDecoder: LibTransactionDecoder as ContractArtifact,
|
||||||
OrderTransferSimulationUtils: OrderTransferSimulationUtils as ContractArtifact,
|
OrderTransferSimulationUtils: OrderTransferSimulationUtils as ContractArtifact,
|
||||||
OrderValidationUtils: OrderValidationUtils as ContractArtifact,
|
OrderValidationUtils: OrderValidationUtils as ContractArtifact,
|
||||||
|
@ -3,9 +3,13 @@
|
|||||||
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
* 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/dev_utils';
|
||||||
export * from '../test/generated-wrappers/eth_balance_checker';
|
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_asset_data';
|
||||||
|
export * from '../test/generated-wrappers/lib_order_transfer_simulation';
|
||||||
export * from '../test/generated-wrappers/lib_transaction_decoder';
|
export * from '../test/generated-wrappers/lib_transaction_decoder';
|
||||||
export * from '../test/generated-wrappers/order_transfer_simulation_utils';
|
export * from '../test/generated-wrappers/order_transfer_simulation_utils';
|
||||||
export * from '../test/generated-wrappers/order_validation_utils';
|
export * from '../test/generated-wrappers/order_validation_utils';
|
||||||
|
@ -5,10 +5,15 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"generated-artifacts/DevUtils.json",
|
"generated-artifacts/DevUtils.json",
|
||||||
"generated-artifacts/LibAssetData.json",
|
"generated-artifacts/LibAssetData.json",
|
||||||
|
"generated-artifacts/LibOrderTransferSimulation.json",
|
||||||
"generated-artifacts/LibTransactionDecoder.json",
|
"generated-artifacts/LibTransactionDecoder.json",
|
||||||
|
"test/generated-artifacts/Addresses.json",
|
||||||
|
"test/generated-artifacts/AssetBalance.json",
|
||||||
"test/generated-artifacts/DevUtils.json",
|
"test/generated-artifacts/DevUtils.json",
|
||||||
"test/generated-artifacts/EthBalanceChecker.json",
|
"test/generated-artifacts/EthBalanceChecker.json",
|
||||||
|
"test/generated-artifacts/ExternalFunctions.json",
|
||||||
"test/generated-artifacts/LibAssetData.json",
|
"test/generated-artifacts/LibAssetData.json",
|
||||||
|
"test/generated-artifacts/LibOrderTransferSimulation.json",
|
||||||
"test/generated-artifacts/LibTransactionDecoder.json",
|
"test/generated-artifacts/LibTransactionDecoder.json",
|
||||||
"test/generated-artifacts/OrderTransferSimulationUtils.json",
|
"test/generated-artifacts/OrderTransferSimulationUtils.json",
|
||||||
"test/generated-artifacts/OrderValidationUtils.json"
|
"test/generated-artifacts/OrderValidationUtils.json"
|
||||||
|
@ -4,11 +4,11 @@
|
|||||||
"changes": [
|
"changes": [
|
||||||
{
|
{
|
||||||
"note": "Add `allowance()` and `balanceOf()` to `LibERC20Token`",
|
"note": "Add `allowance()` and `balanceOf()` to `LibERC20Token`",
|
||||||
"pr": 2462
|
"pr": 2464
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"note": "Fix broken tests",
|
"note": "Fix broken tests",
|
||||||
"pr": 2462
|
"pr": 2456
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -94,7 +94,8 @@ library LibERC20Token {
|
|||||||
|
|
||||||
/// @dev Retrieves the number of decimals for a token.
|
/// @dev Retrieves the number of decimals for a token.
|
||||||
/// Returns `18` if the call reverts.
|
/// 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)
|
function decimals(address token)
|
||||||
internal
|
internal
|
||||||
view
|
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`
|
/// @dev Executes a call on address `target` with calldata `callData`
|
||||||
/// and asserts that either nothing was returned or a single boolean
|
/// and asserts that either nothing was returned or a single boolean
|
||||||
/// was returned equal to `true`.
|
/// was returned equal to `true`.
|
||||||
|
@ -5,6 +5,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Remove dependency on `DevUtils` for asset data encoding/decoding",
|
"note": "Remove dependency on `DevUtils` for asset data encoding/decoding",
|
||||||
"pr": 2462
|
"pr": 2462
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Update tests for refactored `DevUtils`",
|
||||||
|
"pr": 2464
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -26,8 +26,9 @@ blockchainTests.fork.resets('DevUtils mainnet tests', env => {
|
|||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
[noDaiAddress] = await env.getAccountAddressesAsync();
|
[noDaiAddress] = await env.getAccountAddressesAsync();
|
||||||
devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
|
devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||||
devUtilsArtifacts.DevUtils,
|
devUtilsArtifacts.DevUtils,
|
||||||
|
devUtilsArtifacts,
|
||||||
env.provider,
|
env.provider,
|
||||||
env.txDefaults,
|
env.txDefaults,
|
||||||
devUtilsArtifacts,
|
devUtilsArtifacts,
|
||||||
|
@ -19,8 +19,9 @@ blockchainTests('DevUtils.getOrderHash', env => {
|
|||||||
exchangeArtifacts,
|
exchangeArtifacts,
|
||||||
new BigNumber(chainId),
|
new BigNumber(chainId),
|
||||||
);
|
);
|
||||||
devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
|
devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||||
artifacts.DevUtils,
|
artifacts.DevUtils,
|
||||||
|
artifacts,
|
||||||
env.provider,
|
env.provider,
|
||||||
env.txDefaults,
|
env.txDefaults,
|
||||||
artifacts,
|
artifacts,
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import * as crypto from 'crypto';
|
import * as crypto from 'crypto';
|
||||||
|
|
||||||
import { artifacts as proxyArtifacts, TestStaticCallTargetContract } from '@0x/contracts-asset-proxy';
|
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 { ERC1155MintableContract } from '@0x/contracts-erc1155';
|
||||||
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
|
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
|
||||||
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||||
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
|
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
|
||||||
import { AssetProxyId } from '@0x/types';
|
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 { Actor } from '../framework/actors/base';
|
||||||
import { DeploymentManager } from '../framework/deployment_manager';
|
import { DeploymentManager } from '../framework/deployment_manager';
|
||||||
@ -53,7 +53,7 @@ const KNOWN_STATIC_CALL_ENCODING = {
|
|||||||
blockchainTests.resets('LibAssetData', env => {
|
blockchainTests.resets('LibAssetData', env => {
|
||||||
let deployment: DeploymentManager;
|
let deployment: DeploymentManager;
|
||||||
let staticCallTarget: TestStaticCallTargetContract;
|
let staticCallTarget: TestStaticCallTargetContract;
|
||||||
let libAssetData: LibAssetDataContract;
|
let devUtils: DevUtilsContract;
|
||||||
|
|
||||||
let tokenOwner: Actor;
|
let tokenOwner: Actor;
|
||||||
|
|
||||||
@ -73,8 +73,9 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
});
|
});
|
||||||
tokenOwner = new Actor({ name: 'Token Owner', deployment });
|
tokenOwner = new Actor({ name: 'Token Owner', deployment });
|
||||||
|
|
||||||
libAssetData = await LibAssetDataContract.deployFrom0xArtifactAsync(
|
devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||||
artifacts.LibAssetData,
|
artifacts.DevUtils,
|
||||||
|
artifacts,
|
||||||
env.provider,
|
env.provider,
|
||||||
env.txDefaults,
|
env.txDefaults,
|
||||||
artifacts,
|
artifacts,
|
||||||
@ -104,7 +105,7 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should have a deployed-to address', () => {
|
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', () => {
|
describe('encoding and decoding', () => {
|
||||||
@ -117,17 +118,17 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (const [assetData, proxyId] of assetDataScenarios) {
|
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 () => {
|
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,
|
KNOWN_ERC20_ENCODING.assetData,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should decode ERC20 asset data', async () => {
|
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,
|
AssetProxyId.ERC20,
|
||||||
KNOWN_ERC20_ENCODING.address,
|
KNOWN_ERC20_ENCODING.address,
|
||||||
]);
|
]);
|
||||||
@ -135,21 +136,23 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
|
|
||||||
it('should encode ERC721 asset data', async () => {
|
it('should encode ERC721 asset data', async () => {
|
||||||
expect(
|
expect(
|
||||||
await libAssetData
|
await devUtils
|
||||||
.encodeERC721AssetData(KNOWN_ERC721_ENCODING.address, KNOWN_ERC721_ENCODING.tokenId)
|
.encodeERC721AssetData(KNOWN_ERC721_ENCODING.address, KNOWN_ERC721_ENCODING.tokenId)
|
||||||
.callAsync(),
|
.callAsync(),
|
||||||
).to.equal(KNOWN_ERC721_ENCODING.assetData);
|
).to.equal(KNOWN_ERC721_ENCODING.assetData);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should decode ERC721 asset data', async () => {
|
it('should decode ERC721 asset data', async () => {
|
||||||
expect(await libAssetData.decodeERC721AssetData(KNOWN_ERC721_ENCODING.assetData).callAsync()).to.deep.equal(
|
expect(await devUtils.decodeERC721AssetData(KNOWN_ERC721_ENCODING.assetData).callAsync()).to.deep.equal([
|
||||||
[AssetProxyId.ERC721, KNOWN_ERC721_ENCODING.address, KNOWN_ERC721_ENCODING.tokenId],
|
AssetProxyId.ERC721,
|
||||||
);
|
KNOWN_ERC721_ENCODING.address,
|
||||||
|
KNOWN_ERC721_ENCODING.tokenId,
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should encode ERC1155 asset data', async () => {
|
it('should encode ERC1155 asset data', async () => {
|
||||||
expect(
|
expect(
|
||||||
await libAssetData
|
await devUtils
|
||||||
.encodeERC1155AssetData(
|
.encodeERC1155AssetData(
|
||||||
KNOWN_ERC1155_ENCODING.tokenAddress,
|
KNOWN_ERC1155_ENCODING.tokenAddress,
|
||||||
KNOWN_ERC1155_ENCODING.tokenIds,
|
KNOWN_ERC1155_ENCODING.tokenIds,
|
||||||
@ -161,9 +164,7 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should decode ERC1155 asset data', async () => {
|
it('should decode ERC1155 asset data', async () => {
|
||||||
expect(
|
expect(await devUtils.decodeERC1155AssetData(KNOWN_ERC1155_ENCODING.assetData).callAsync()).to.deep.equal([
|
||||||
await libAssetData.decodeERC1155AssetData(KNOWN_ERC1155_ENCODING.assetData).callAsync(),
|
|
||||||
).to.deep.equal([
|
|
||||||
AssetProxyId.ERC1155,
|
AssetProxyId.ERC1155,
|
||||||
KNOWN_ERC1155_ENCODING.tokenAddress,
|
KNOWN_ERC1155_ENCODING.tokenAddress,
|
||||||
KNOWN_ERC1155_ENCODING.tokenIds,
|
KNOWN_ERC1155_ENCODING.tokenIds,
|
||||||
@ -174,7 +175,7 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
|
|
||||||
it('should encode multiasset data', async () => {
|
it('should encode multiasset data', async () => {
|
||||||
expect(
|
expect(
|
||||||
await libAssetData
|
await devUtils
|
||||||
.encodeMultiAssetData(
|
.encodeMultiAssetData(
|
||||||
KNOWN_MULTI_ASSET_ENCODING.amounts,
|
KNOWN_MULTI_ASSET_ENCODING.amounts,
|
||||||
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
|
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
|
||||||
@ -184,18 +185,18 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should decode multiasset data', async () => {
|
it('should decode multiasset data', async () => {
|
||||||
expect(
|
expect(await devUtils.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData).callAsync()).to.deep.equal(
|
||||||
await libAssetData.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData).callAsync(),
|
[
|
||||||
).to.deep.equal([
|
|
||||||
AssetProxyId.MultiAsset,
|
AssetProxyId.MultiAsset,
|
||||||
KNOWN_MULTI_ASSET_ENCODING.amounts,
|
KNOWN_MULTI_ASSET_ENCODING.amounts,
|
||||||
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
|
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
|
||||||
]);
|
],
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should encode StaticCall data', async () => {
|
it('should encode StaticCall data', async () => {
|
||||||
expect(
|
expect(
|
||||||
await libAssetData
|
await devUtils
|
||||||
.encodeStaticCallAssetData(
|
.encodeStaticCallAssetData(
|
||||||
KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress,
|
KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress,
|
||||||
KNOWN_STATIC_CALL_ENCODING.staticCallData,
|
KNOWN_STATIC_CALL_ENCODING.staticCallData,
|
||||||
@ -207,7 +208,7 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
|
|
||||||
it('should decode StaticCall data', async () => {
|
it('should decode StaticCall data', async () => {
|
||||||
expect(
|
expect(
|
||||||
await libAssetData.decodeStaticCallAssetData(KNOWN_STATIC_CALL_ENCODING.assetData).callAsync(),
|
await devUtils.decodeStaticCallAssetData(KNOWN_STATIC_CALL_ENCODING.assetData).callAsync(),
|
||||||
).to.deep.equal([
|
).to.deep.equal([
|
||||||
AssetProxyId.StaticCall,
|
AssetProxyId.StaticCall,
|
||||||
KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress,
|
KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress,
|
||||||
@ -227,16 +228,14 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (const data of assetData) {
|
for (const data of assetData) {
|
||||||
await libAssetData.revertIfInvalidAssetData(data).callAsync();
|
await devUtils.revertIfInvalidAssetData(data).callAsync();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should revert for invalid assetProxyId', async () => {
|
it('should revert for invalid assetProxyId', async () => {
|
||||||
const badAssetData = `0x${crypto.randomBytes(4).toString('hex')}${constants.NULL_ADDRESS}`;
|
const badAssetData = `0x${crypto.randomBytes(4).toString('hex')}${constants.NULL_ADDRESS}`;
|
||||||
await expect(libAssetData.revertIfInvalidAssetData(badAssetData).callAsync()).to.eventually.be.rejectedWith(
|
await expect(devUtils.revertIfInvalidAssetData(badAssetData).callAsync()).to.revertWith('WRONG_PROXY_ID');
|
||||||
StringRevertError,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should revert for invalid assetData with valid assetProxyId', async () => {
|
it('should revert for invalid assetData with valid assetProxyId', async () => {
|
||||||
@ -245,8 +244,8 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
|
|
||||||
for (const data of assetData) {
|
for (const data of assetData) {
|
||||||
const badData = data.substring(0, data.length - 2); // drop one byte but retain assetProxyId
|
const badData = data.substring(0, data.length - 2); // drop one byte but retain assetProxyId
|
||||||
await expect(libAssetData.revertIfInvalidAssetData(badData).callAsync()).to.eventually.be.rejectedWith(
|
await expect(devUtils.revertIfInvalidAssetData(badData).callAsync()).to.revertWith(
|
||||||
LibBytesRevertErrors.InvalidByteOperationError,
|
new LibBytesRevertErrors.InvalidByteOperationError(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -254,33 +253,31 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
|
|
||||||
describe('getBalance', () => {
|
describe('getBalance', () => {
|
||||||
it('should query ERC20 balance by asset data', async () => {
|
it('should query ERC20 balance by asset data', async () => {
|
||||||
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||||
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||||
constants.INITIAL_ERC20_BALANCE,
|
constants.INITIAL_ERC20_BALANCE,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 0 if ERC20 token does not exist', async () => {
|
it('should return 0 if ERC20 token does not exist', async () => {
|
||||||
const assetData = await libAssetData.encodeERC20AssetData(constants.NULL_ADDRESS).callAsync();
|
const assetData = await devUtils.encodeERC20AssetData(constants.NULL_ADDRESS).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);
|
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should query ERC721 balance by asset data', async () => {
|
it('should query ERC721 balance by asset data', async () => {
|
||||||
const assetData = await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
|
const assetData = await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).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 ERC721 token does not exist', async () => {
|
it('should return 0 if ERC721 token does not exist', async () => {
|
||||||
const assetData = await libAssetData
|
const assetData = await devUtils.encodeERC721AssetData(constants.NULL_ADDRESS, erc721TokenId).callAsync();
|
||||||
.encodeERC721AssetData(constants.NULL_ADDRESS, erc721TokenId)
|
const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync();
|
||||||
.callAsync();
|
|
||||||
const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync();
|
|
||||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should query ERC1155 balances by asset data', async () => {
|
it('should query ERC1155 balances by asset data', async () => {
|
||||||
const assetData = await libAssetData
|
const assetData = await devUtils
|
||||||
.encodeERC1155AssetData(
|
.encodeERC1155AssetData(
|
||||||
erc1155Token.address,
|
erc1155Token.address,
|
||||||
[erc1155TokenId],
|
[erc1155TokenId],
|
||||||
@ -288,11 +285,11 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
constants.NULL_BYTES,
|
constants.NULL_BYTES,
|
||||||
)
|
)
|
||||||
.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 0 if ERC1155 token does not exist', async () => {
|
it('should return 0 if ERC1155 token does not exist', async () => {
|
||||||
const assetData = await libAssetData
|
const assetData = await devUtils
|
||||||
.encodeERC1155AssetData(
|
.encodeERC1155AssetData(
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
[erc1155TokenId],
|
[erc1155TokenId],
|
||||||
@ -300,84 +297,84 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
constants.NULL_BYTES,
|
constants.NULL_BYTES,
|
||||||
)
|
)
|
||||||
.callAsync();
|
.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);
|
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should query multi-asset batch balance by asset data', async () => {
|
it('should query multi-asset batch balance by asset data', async () => {
|
||||||
const assetData = await libAssetData
|
const assetData = await devUtils
|
||||||
.encodeMultiAssetData(
|
.encodeMultiAssetData(
|
||||||
[new BigNumber(1), new BigNumber(1)],
|
[new BigNumber(1), new BigNumber(1)],
|
||||||
[
|
[
|
||||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||||
await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.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 () => {
|
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(
|
.encodeMultiAssetData(
|
||||||
[constants.ZERO_AMOUNT, new BigNumber(1)],
|
[constants.ZERO_AMOUNT, new BigNumber(1)],
|
||||||
[
|
[
|
||||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||||
await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.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 () => {
|
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(
|
.encodeMultiAssetData(
|
||||||
[new BigNumber(1), new BigNumber(1)],
|
[new BigNumber(1), new BigNumber(1)],
|
||||||
[
|
[
|
||||||
await libAssetData.encodeERC20AssetData(secondErc20Token.address).callAsync(),
|
await devUtils.encodeERC20AssetData(secondErc20Token.address).callAsync(),
|
||||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.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,
|
constants.ZERO_AMOUNT,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a balance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
|
it('should return a balance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
|
||||||
const fakeAssetData = '0x01020304';
|
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);
|
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 () => {
|
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 staticCallData = staticCallTarget.isOddNumber(new BigNumber(1)).getABIEncodedTransactionData();
|
||||||
const expectedResultHash = hexUtils.hash(hexUtils.leftPad(1));
|
const expectedResultHash = hexUtils.hash(hexUtils.leftPad(1));
|
||||||
const assetData = await libAssetData
|
const assetData = await devUtils
|
||||||
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
|
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
|
||||||
.callAsync();
|
.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);
|
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 () => {
|
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 staticCallData = staticCallTarget.isOddNumber(new BigNumber(0)).getABIEncodedTransactionData();
|
||||||
const expectedResultHash = hexUtils.hash(hexUtils.leftPad(1));
|
const expectedResultHash = hexUtils.hash(hexUtils.leftPad(1));
|
||||||
const assetData = await libAssetData
|
const assetData = await devUtils
|
||||||
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
|
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
|
||||||
.callAsync();
|
.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);
|
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getAssetProxyAllowance', () => {
|
describe('getAssetProxyAllowance', () => {
|
||||||
it('should query ERC20 allowances by asset data', async () => {
|
it('should query ERC20 allowances by asset data', async () => {
|
||||||
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||||
expect(
|
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
constants.MAX_UINT256,
|
||||||
).to.bignumber.equal(constants.MAX_UINT256);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should query ERC721 approval by asset data', async () => {
|
it('should query ERC721 approval by asset data', async () => {
|
||||||
@ -390,21 +387,21 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
.awaitTransactionSuccessAsync({
|
.awaitTransactionSuccessAsync({
|
||||||
from: tokenOwner.address,
|
from: tokenOwner.address,
|
||||||
});
|
});
|
||||||
const assetData = await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
|
const assetData = await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
|
||||||
expect(
|
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
1,
|
||||||
).to.bignumber.equal(1);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should query ERC721 approvalForAll by assetData', async () => {
|
it('should query ERC721 approvalForAll by assetData', async () => {
|
||||||
const assetData = await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
|
const assetData = await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
|
||||||
expect(
|
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||||
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should query ERC1155 allowances by asset data', async () => {
|
it('should query ERC1155 allowances by asset data', async () => {
|
||||||
const assetData = await libAssetData
|
const assetData = await devUtils
|
||||||
.encodeERC1155AssetData(
|
.encodeERC1155AssetData(
|
||||||
erc1155Token.address,
|
erc1155Token.address,
|
||||||
[erc1155TokenId],
|
[erc1155TokenId],
|
||||||
@ -412,9 +409,9 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
constants.NULL_BYTES,
|
constants.NULL_BYTES,
|
||||||
)
|
)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(
|
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||||
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should query multi-asset allowances by asset data', async () => {
|
it('should query multi-asset allowances by asset data', async () => {
|
||||||
@ -424,18 +421,18 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
.awaitTransactionSuccessAsync({
|
.awaitTransactionSuccessAsync({
|
||||||
from: tokenOwner.address,
|
from: tokenOwner.address,
|
||||||
});
|
});
|
||||||
const assetData = await libAssetData
|
const assetData = await devUtils
|
||||||
.encodeMultiAssetData(
|
.encodeMultiAssetData(
|
||||||
[new BigNumber(1), new BigNumber(1)],
|
[new BigNumber(1), new BigNumber(1)],
|
||||||
[
|
[
|
||||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||||
await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(
|
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
1,
|
||||||
).to.bignumber.equal(1);
|
);
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -446,60 +443,60 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
.awaitTransactionSuccessAsync({
|
.awaitTransactionSuccessAsync({
|
||||||
from: tokenOwner.address,
|
from: tokenOwner.address,
|
||||||
});
|
});
|
||||||
const assetData = await libAssetData
|
const assetData = await devUtils
|
||||||
.encodeMultiAssetData(
|
.encodeMultiAssetData(
|
||||||
[constants.ZERO_AMOUNT, new BigNumber(1)],
|
[constants.ZERO_AMOUNT, new BigNumber(1)],
|
||||||
[
|
[
|
||||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||||
await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(
|
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||||
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
);
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return an allowance of 0 if the allowance for a nested asset is 0', async () => {
|
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(
|
.encodeMultiAssetData(
|
||||||
[new BigNumber(1), new BigNumber(1)],
|
[new BigNumber(1), new BigNumber(1)],
|
||||||
[
|
[
|
||||||
await libAssetData.encodeERC20AssetData(secondErc20Token.address).callAsync(),
|
await devUtils.encodeERC20AssetData(secondErc20Token.address).callAsync(),
|
||||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(
|
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
constants.ZERO_AMOUNT,
|
||||||
).to.bignumber.equal(constants.ZERO_AMOUNT);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return an allowance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
|
it('should return an allowance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
|
||||||
const fakeAssetData = '0x01020304';
|
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);
|
expect(allowance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return an allowance of MAX_UINT256 for any staticCallAssetData', async () => {
|
it('should return an allowance of MAX_UINT256 for any staticCallAssetData', async () => {
|
||||||
const staticCallData = AssetProxyId.StaticCall;
|
const staticCallData = AssetProxyId.StaticCall;
|
||||||
const assetData = await libAssetData
|
const assetData = await devUtils
|
||||||
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, constants.KECCAK256_NULL)
|
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, constants.KECCAK256_NULL)
|
||||||
.callAsync();
|
.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);
|
expect(allowance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getBatchBalances', () => {
|
describe('getBatchBalances', () => {
|
||||||
it('should query balances for a batch of asset data strings', async () => {
|
it('should query balances for a batch of asset data strings', async () => {
|
||||||
const erc20AssetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||||
const erc721AssetData = await libAssetData
|
const erc721AssetData = await devUtils
|
||||||
.encodeERC721AssetData(erc721Token.address, erc721TokenId)
|
.encodeERC721AssetData(erc721Token.address, erc721TokenId)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(
|
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)]);
|
).to.deep.equal([new BigNumber(constants.INITIAL_ERC20_BALANCE), new BigNumber(1)]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -512,9 +509,9 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
.awaitTransactionSuccessAsync({
|
.awaitTransactionSuccessAsync({
|
||||||
from: tokenOwner.address,
|
from: tokenOwner.address,
|
||||||
});
|
});
|
||||||
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||||
expect(
|
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]);
|
).to.deep.equal([new BigNumber(constants.INITIAL_ERC20_BALANCE), allowance]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -526,9 +523,9 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
.awaitTransactionSuccessAsync({
|
.awaitTransactionSuccessAsync({
|
||||||
from: tokenOwner.address,
|
from: tokenOwner.address,
|
||||||
});
|
});
|
||||||
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||||
expect(
|
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]]);
|
).to.deep.equal([[new BigNumber(constants.INITIAL_ERC20_BALANCE)], [allowance]]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -541,12 +538,12 @@ blockchainTests.resets('LibAssetData', env => {
|
|||||||
.awaitTransactionSuccessAsync({
|
.awaitTransactionSuccessAsync({
|
||||||
from: tokenOwner.address,
|
from: tokenOwner.address,
|
||||||
});
|
});
|
||||||
const erc20AssetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||||
const erc721AssetData = await libAssetData
|
const erc721AssetData = await devUtils
|
||||||
.encodeERC721AssetData(erc721Token.address, erc721TokenId)
|
.encodeERC721AssetData(erc721Token.address, erc721TokenId)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(
|
expect(
|
||||||
await libAssetData
|
await devUtils
|
||||||
.getBatchAssetProxyAllowances(tokenOwner.address, [erc20AssetData, erc721AssetData])
|
.getBatchAssetProxyAllowances(tokenOwner.address, [erc20AssetData, erc721AssetData])
|
||||||
.callAsync(),
|
.callAsync(),
|
||||||
).to.deep.equal([allowance, constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS]);
|
).to.deep.equal([allowance, constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS]);
|
||||||
|
@ -1,14 +1,8 @@
|
|||||||
import { ExchangeContract } from '@0x/contracts-exchange';
|
import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange';
|
||||||
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
|
||||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
|
||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
import * as chai from 'chai';
|
|
||||||
|
|
||||||
import { artifacts, LibTransactionDecoderContract } from '@0x/contracts-dev-utils';
|
import { artifacts, DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||||
|
|
||||||
chaiSetup.configure();
|
|
||||||
const expect = chai.expect;
|
|
||||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
|
||||||
|
|
||||||
const order = {
|
const order = {
|
||||||
makerAddress: '0xe36ea790bc9d7ab70c55260c66d52b1eca985f84',
|
makerAddress: '0xe36ea790bc9d7ab70c55260c66d52b1eca985f84',
|
||||||
@ -30,25 +24,31 @@ const takerAssetFillAmount = new BigNumber('100000000000000000000');
|
|||||||
const signature =
|
const signature =
|
||||||
'0x1ce8e3c600d933423172b5021158a6be2e818613ff8e762d70ef490c752fd98a626a215f09f169668990414de75a53da221c294a3002f796d004827258b641876e03';
|
'0x1ce8e3c600d933423172b5021158a6be2e818613ff8e762d70ef490c752fd98a626a215f09f169668990414de75a53da221c294a3002f796d004827258b641876e03';
|
||||||
|
|
||||||
describe('LibTransactionDecoder', () => {
|
blockchainTests('LibTransactionDecoder', env => {
|
||||||
let libTxDecoder: LibTransactionDecoderContract;
|
let devUtils: DevUtilsContract;
|
||||||
const exchangeInterface = new ExchangeContract(constants.NULL_ADDRESS, provider, txDefaults);
|
const exchangeInterface = new ExchangeContract(constants.NULL_ADDRESS, { isEIP1193: true } as any);
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await blockchainLifecycle.startAsync();
|
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||||
libTxDecoder = await LibTransactionDecoderContract.deployFrom0xArtifactAsync(
|
exchangeArtifacts.Exchange,
|
||||||
artifacts.LibTransactionDecoder,
|
env.provider,
|
||||||
provider,
|
env.txDefaults,
|
||||||
txDefaults,
|
exchangeArtifacts,
|
||||||
artifacts,
|
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 () => {
|
it('should decode an Exchange.batchCancelOrders() transaction', async () => {
|
||||||
const input = exchangeInterface.batchCancelOrders([order, order]).getABIEncodedTransactionData();
|
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',
|
'batchCancelOrders',
|
||||||
[order, order],
|
[order, order],
|
||||||
[],
|
[],
|
||||||
@ -61,7 +61,7 @@ describe('LibTransactionDecoder', () => {
|
|||||||
[func]([order, order], [takerAssetFillAmount, takerAssetFillAmount], [signature, signature])
|
[func]([order, order], [takerAssetFillAmount, takerAssetFillAmount], [signature, signature])
|
||||||
.getABIEncodedTransactionData();
|
.getABIEncodedTransactionData();
|
||||||
it(`should decode an Exchange.${func}() transaction`, async () => {
|
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,
|
func,
|
||||||
[order, order],
|
[order, order],
|
||||||
[takerAssetFillAmount, takerAssetFillAmount],
|
[takerAssetFillAmount, takerAssetFillAmount],
|
||||||
@ -72,7 +72,7 @@ describe('LibTransactionDecoder', () => {
|
|||||||
|
|
||||||
it('should decode an Exchange.cancelOrder() transaction', async () => {
|
it('should decode an Exchange.cancelOrder() transaction', async () => {
|
||||||
const input = exchangeInterface.cancelOrder(order).getABIEncodedTransactionData();
|
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',
|
'cancelOrder',
|
||||||
[order],
|
[order],
|
||||||
[],
|
[],
|
||||||
@ -85,7 +85,7 @@ describe('LibTransactionDecoder', () => {
|
|||||||
[func](order, takerAssetFillAmount, signature)
|
[func](order, takerAssetFillAmount, signature)
|
||||||
.getABIEncodedTransactionData();
|
.getABIEncodedTransactionData();
|
||||||
it(`should decode an Exchange.${func}() transaction`, async () => {
|
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,
|
func,
|
||||||
[order],
|
[order],
|
||||||
[takerAssetFillAmount],
|
[takerAssetFillAmount],
|
||||||
@ -104,7 +104,7 @@ describe('LibTransactionDecoder', () => {
|
|||||||
[func]([order, order], takerAssetFillAmount, [signature, signature])
|
[func]([order, order], takerAssetFillAmount, [signature, signature])
|
||||||
.getABIEncodedTransactionData();
|
.getABIEncodedTransactionData();
|
||||||
it(`should decode an Exchange.${func}() transaction`, async () => {
|
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,
|
func,
|
||||||
[order, order],
|
[order, order],
|
||||||
[takerAssetFillAmount],
|
[takerAssetFillAmount],
|
||||||
@ -130,7 +130,7 @@ describe('LibTransactionDecoder', () => {
|
|||||||
const input = exchangeInterface
|
const input = exchangeInterface
|
||||||
.matchOrders(order, complementaryOrder, signature, signature)
|
.matchOrders(order, complementaryOrder, signature, signature)
|
||||||
.getABIEncodedTransactionData();
|
.getABIEncodedTransactionData();
|
||||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||||
'matchOrders',
|
'matchOrders',
|
||||||
[order, complementaryOrder],
|
[order, complementaryOrder],
|
||||||
[order.takerAssetAmount, complementaryOrder.takerAssetAmount],
|
[order.takerAssetAmount, complementaryOrder.takerAssetAmount],
|
||||||
|
@ -195,8 +195,9 @@ export class DeploymentManager {
|
|||||||
exchange,
|
exchange,
|
||||||
staking.stakingProxy,
|
staking.stakingProxy,
|
||||||
]);
|
]);
|
||||||
const devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
|
const devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||||
devUtilsArtifacts.DevUtils,
|
devUtilsArtifacts.DevUtils,
|
||||||
|
devUtilsArtifacts,
|
||||||
environment.provider,
|
environment.provider,
|
||||||
environment.txDefaults,
|
environment.txDefaults,
|
||||||
devUtilsArtifacts,
|
devUtilsArtifacts,
|
||||||
|
@ -55,6 +55,7 @@ export enum {{contractName}}Events {
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
|
// tslint:disable:array-type
|
||||||
// tslint:disable:no-parameter-reassignment
|
// tslint:disable:no-parameter-reassignment
|
||||||
// tslint:disable-next-line:class-name
|
// tslint:disable-next-line:class-name
|
||||||
export class {{contractName}}Contract extends BaseContract {
|
export class {{contractName}}Contract extends BaseContract {
|
||||||
|
@ -18,6 +18,14 @@
|
|||||||
{
|
{
|
||||||
"note": "Update `ERC20BridgeSampler` on mainnet and kovan.",
|
"note": "Update `ERC20BridgeSampler` on mainnet and kovan.",
|
||||||
"pr": 2459
|
"pr": 2459
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Remove `libTransactionDecoder`",
|
||||||
|
"pr": 2456
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Update snapshot addresses",
|
||||||
|
"pr": 2464
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"timestamp": 1580811564
|
"timestamp": 1580811564
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||||
"coordinatorRegistry": "0x45797531b873fd5e519477a070a955764c1a5b07",
|
"coordinatorRegistry": "0x45797531b873fd5e519477a070a955764c1a5b07",
|
||||||
"coordinator": "0x38a795580d0f687e399913a00ddef6a17612c722",
|
"coordinator": "0x38a795580d0f687e399913a00ddef6a17612c722",
|
||||||
"libTransactionDecoder": "0x5f20e82643ce007d87692eb1b3d3fc059588b224",
|
|
||||||
"multiAssetProxy": "0xef701d5389ae74503d633396c4d654eabedc9d78",
|
"multiAssetProxy": "0xef701d5389ae74503d633396c4d654eabedc9d78",
|
||||||
"staticCallProxy": "0x3517b88c19508c08650616019062b898ab65ed29",
|
"staticCallProxy": "0x3517b88c19508c08650616019062b898ab65ed29",
|
||||||
"erc1155Proxy": "0x7eefbd48fd63d441ec7435d024ec7c5131019add",
|
"erc1155Proxy": "0x7eefbd48fd63d441ec7435d024ec7c5131019add",
|
||||||
@ -43,7 +42,6 @@
|
|||||||
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||||
"coordinatorRegistry": "0x403cc23e88c17c4652fb904784d1af640a6722d9",
|
"coordinatorRegistry": "0x403cc23e88c17c4652fb904784d1af640a6722d9",
|
||||||
"coordinator": "0x6ff734d96104965c9c1b0108f83abc46e6e501df",
|
"coordinator": "0x6ff734d96104965c9c1b0108f83abc46e6e501df",
|
||||||
"libTransactionDecoder": "0xb20f3b07afb0e38b6151b9be4f53218bdd7dc231",
|
|
||||||
"multiAssetProxy": "0xab8fbd189c569ccdee3a4d929bb7f557be4028f6",
|
"multiAssetProxy": "0xab8fbd189c569ccdee3a4d929bb7f557be4028f6",
|
||||||
"staticCallProxy": "0xe1b97e47aa3796276033a5341e884d2ba46b6ac1",
|
"staticCallProxy": "0xe1b97e47aa3796276033a5341e884d2ba46b6ac1",
|
||||||
"erc1155Proxy": "0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d",
|
"erc1155Proxy": "0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d",
|
||||||
@ -69,7 +67,6 @@
|
|||||||
"assetProxyOwner": "0x0000000000000000000000000000000000000000",
|
"assetProxyOwner": "0x0000000000000000000000000000000000000000",
|
||||||
"zeroExGovernor": "0x3f46b98061a3e1e1f41dff296ec19402c298f8a9",
|
"zeroExGovernor": "0x3f46b98061a3e1e1f41dff296ec19402c298f8a9",
|
||||||
"forwarder": "0xd67f2f346f6e85db70632d9f18f50e04192ab54d",
|
"forwarder": "0xd67f2f346f6e85db70632d9f18f50e04192ab54d",
|
||||||
"libTransactionDecoder": "0x34b37611db8190469b735fb2a007d8236c29eb88",
|
|
||||||
"orderValidator": "0x0000000000000000000000000000000000000000",
|
"orderValidator": "0x0000000000000000000000000000000000000000",
|
||||||
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||||
"coordinatorRegistry": "0x1084b6a398e47907bae43fec3ff4b677db6e4fee",
|
"coordinatorRegistry": "0x1084b6a398e47907bae43fec3ff4b677db6e4fee",
|
||||||
@ -100,7 +97,6 @@
|
|||||||
"zeroExGovernor": "0x6ff734d96104965c9c1b0108f83abc46e6e501df",
|
"zeroExGovernor": "0x6ff734d96104965c9c1b0108f83abc46e6e501df",
|
||||||
"forwarder": "0x2759a4c639fa4882d6d64973630ef81faf901d27",
|
"forwarder": "0x2759a4c639fa4882d6d64973630ef81faf901d27",
|
||||||
"orderValidator": "0x0000000000000000000000000000000000000000",
|
"orderValidator": "0x0000000000000000000000000000000000000000",
|
||||||
"libTransactionDecoder": "0x067b5997c9058eade0bb03d8fb5e6db7feda80a3",
|
|
||||||
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||||
"coordinatorRegistry": "0x09fb99968c016a3ff537bf58fb3d9fe55a7975d5",
|
"coordinatorRegistry": "0x09fb99968c016a3ff537bf58fb3d9fe55a7975d5",
|
||||||
"coordinator": "0xd29e59e51e8ab5f94121efaeebd935ca4214e257",
|
"coordinator": "0xd29e59e51e8ab5f94121efaeebd935ca4214e257",
|
||||||
@ -127,21 +123,20 @@
|
|||||||
"etherToken": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082",
|
"etherToken": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082",
|
||||||
"exchange": "0x48bacb9266a570d521063ef5dd96e61686dbe788",
|
"exchange": "0x48bacb9266a570d521063ef5dd96e61686dbe788",
|
||||||
"assetProxyOwner": "0x0000000000000000000000000000000000000000",
|
"assetProxyOwner": "0x0000000000000000000000000000000000000000",
|
||||||
"erc20BridgeProxy": "0x8ea76477cfaca8f7ea06477fd3c09a740ac6012a",
|
"erc20BridgeProxy": "0x038f9b392fb9a9676dbaddf78ea5fdbf6c7d9710",
|
||||||
"zeroExGovernor": "0x0000000000000000000000000000000000000000",
|
"zeroExGovernor": "0x0000000000000000000000000000000000000000",
|
||||||
"libTransactionDecoder": "0xb48e1b16829c7f5bd62b76cb878a6bb1c4625d7a",
|
"forwarder": "0xe704967449b57b2382b7fa482718748c13c63190",
|
||||||
"forwarder": "0x5d3ad3561a1235273cbcb4e82fce63a0073d19be",
|
|
||||||
"orderValidator": "0x0000000000000000000000000000000000000000",
|
"orderValidator": "0x0000000000000000000000000000000000000000",
|
||||||
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||||
"coordinatorRegistry": "0xaa86dda78e9434aca114b6676fc742a18d15a1cc",
|
"coordinatorRegistry": "0xaa86dda78e9434aca114b6676fc742a18d15a1cc",
|
||||||
"coordinator": "0x4d3d5c850dd5bd9d6f4adda3dd039a3c8054ca29",
|
"coordinator": "0x4d3d5c850dd5bd9d6f4adda3dd039a3c8054ca29",
|
||||||
"multiAssetProxy": "0xcfc18cec799fbd1793b5c43e773c98d4d61cc2db",
|
"multiAssetProxy": "0xcfc18cec799fbd1793b5c43e773c98d4d61cc2db",
|
||||||
"staticCallProxy": "0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f",
|
"staticCallProxy": "0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f",
|
||||||
"devUtils": "0xa31e64ea55b9b6bbb9d6a676738e9a5b23149f84",
|
"devUtils": "0x74341e87b1c4db7d5ed95f92b37509f2525a7a90",
|
||||||
"exchangeV2": "0x48bacb9266a570d521063ef5dd96e61686dbe788",
|
"exchangeV2": "0x48bacb9266a570d521063ef5dd96e61686dbe788",
|
||||||
"zrxVault": "0x1941ff73d1154774d87521d2d0aaad5d19c8df60",
|
"zrxVault": "0xc4df27466183c0fe2a5924d6ea56e334deff146a",
|
||||||
"staking": "0x0d8b0dd11f5d34ed41d556def5f841900d5b1c6b",
|
"staking": "0xf23276778860e420acfc18ebeebf7e829b06965c",
|
||||||
"stakingProxy": "0x38ef19fdf8e8415f18c307ed71967e19aac28ba1",
|
"stakingProxy": "0x8a063452f7df2614db1bca3a85ef35da40cf0835",
|
||||||
"uniswapBridge": "0x0000000000000000000000000000000000000000",
|
"uniswapBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"eth2DaiBridge": "0x0000000000000000000000000000000000000000",
|
"eth2DaiBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
|
"erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
|
||||||
|
@ -14,7 +14,6 @@ export interface ContractAddresses {
|
|||||||
forwarder: string;
|
forwarder: string;
|
||||||
coordinatorRegistry: string;
|
coordinatorRegistry: string;
|
||||||
coordinator: string;
|
coordinator: string;
|
||||||
libTransactionDecoder: string;
|
|
||||||
multiAssetProxy: string;
|
multiAssetProxy: string;
|
||||||
staticCallProxy: string;
|
staticCallProxy: string;
|
||||||
erc1155Proxy: string;
|
erc1155Proxy: string;
|
||||||
|
@ -1,4 +1,17 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "3.5.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Update `DevUtils` artifact",
|
||||||
|
"pr": 2464
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Remove `LibTransactionDecoder` artifact",
|
||||||
|
"pr": 2464
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1580988106,
|
"timestamp": 1580988106,
|
||||||
"version": "3.4.1",
|
"version": "3.4.1",
|
||||||
|
365
packages/contract-artifacts/artifacts/DevUtils.json
generated
365
packages/contract-artifacts/artifacts/DevUtils.json
generated
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -15,7 +15,6 @@ import * as Forwarder from '../artifacts/Forwarder.json';
|
|||||||
import * as IAssetProxy from '../artifacts/IAssetProxy.json';
|
import * as IAssetProxy from '../artifacts/IAssetProxy.json';
|
||||||
import * as IValidator from '../artifacts/IValidator.json';
|
import * as IValidator from '../artifacts/IValidator.json';
|
||||||
import * as IWallet from '../artifacts/IWallet.json';
|
import * as IWallet from '../artifacts/IWallet.json';
|
||||||
import * as LibTransactionDecoder from '../artifacts/LibTransactionDecoder.json';
|
|
||||||
import * as MultiAssetProxy from '../artifacts/MultiAssetProxy.json';
|
import * as MultiAssetProxy from '../artifacts/MultiAssetProxy.json';
|
||||||
import * as Staking from '../artifacts/Staking.json';
|
import * as Staking from '../artifacts/Staking.json';
|
||||||
import * as StakingProxy from '../artifacts/StakingProxy.json';
|
import * as StakingProxy from '../artifacts/StakingProxy.json';
|
||||||
@ -43,7 +42,6 @@ export {
|
|||||||
IAssetProxy,
|
IAssetProxy,
|
||||||
IValidator,
|
IValidator,
|
||||||
IWallet,
|
IWallet,
|
||||||
LibTransactionDecoder,
|
|
||||||
MultiAssetProxy,
|
MultiAssetProxy,
|
||||||
StaticCallProxy,
|
StaticCallProxy,
|
||||||
WETH9,
|
WETH9,
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
"./artifacts/ERC721Token.json",
|
"./artifacts/ERC721Token.json",
|
||||||
"./artifacts/Exchange.json",
|
"./artifacts/Exchange.json",
|
||||||
"./artifacts/Forwarder.json",
|
"./artifacts/Forwarder.json",
|
||||||
"./artifacts/LibTransactionDecoder.json",
|
|
||||||
"./artifacts/IAssetProxy.json",
|
"./artifacts/IAssetProxy.json",
|
||||||
"./artifacts/IValidator.json",
|
"./artifacts/IValidator.json",
|
||||||
"./artifacts/IWallet.json",
|
"./artifacts/IWallet.json",
|
||||||
|
@ -3,8 +3,12 @@
|
|||||||
"version": "13.5.0",
|
"version": "13.5.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
{
|
{
|
||||||
"note": "export `evmbytecodeoutputlinkreferences` type.",
|
"note": "Export `EvmBytecodeOutputLinkReferences` type.",
|
||||||
"pr": 2462
|
"pr": 2462
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Remove `LibTransactionDecoder`",
|
||||||
|
"pr": 2464
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -11,7 +11,6 @@ import { ERC20TokenContract } from './generated-wrappers/erc20_token';
|
|||||||
import { ERC721TokenContract } from './generated-wrappers/erc721_token';
|
import { ERC721TokenContract } from './generated-wrappers/erc721_token';
|
||||||
import { ExchangeContract } from './generated-wrappers/exchange';
|
import { ExchangeContract } from './generated-wrappers/exchange';
|
||||||
import { ForwarderContract } from './generated-wrappers/forwarder';
|
import { ForwarderContract } from './generated-wrappers/forwarder';
|
||||||
import { LibTransactionDecoderContract } from './generated-wrappers/lib_transaction_decoder';
|
|
||||||
import { StakingContract } from './generated-wrappers/staking';
|
import { StakingContract } from './generated-wrappers/staking';
|
||||||
import { WETH9Contract } from './generated-wrappers/weth9';
|
import { WETH9Contract } from './generated-wrappers/weth9';
|
||||||
import { ContractWrappersConfig } from './types';
|
import { ContractWrappersConfig } from './types';
|
||||||
@ -50,10 +49,6 @@ export class ContractWrappers {
|
|||||||
* An instance of the StakingContract class containing methods for interacting with the Staking contracts.
|
* An instance of the StakingContract class containing methods for interacting with the Staking contracts.
|
||||||
*/
|
*/
|
||||||
public staking: StakingContract;
|
public staking: StakingContract;
|
||||||
/**
|
|
||||||
* An instance of the LibTransactionDecoder class containing methods for interacting with the LibTransactionDecoder smart contract.
|
|
||||||
*/
|
|
||||||
public libTransactionDecoder: LibTransactionDecoderContract;
|
|
||||||
|
|
||||||
private readonly _web3Wrapper: Web3Wrapper;
|
private readonly _web3Wrapper: Web3Wrapper;
|
||||||
/**
|
/**
|
||||||
@ -78,7 +73,6 @@ export class ContractWrappers {
|
|||||||
ForwarderContract,
|
ForwarderContract,
|
||||||
StakingContract,
|
StakingContract,
|
||||||
WETH9Contract,
|
WETH9Contract,
|
||||||
LibTransactionDecoderContract,
|
|
||||||
];
|
];
|
||||||
contractsArray.forEach(contract => {
|
contractsArray.forEach(contract => {
|
||||||
this._web3Wrapper.abiDecoder.addABI(contract.ABI(), contract.contractName);
|
this._web3Wrapper.abiDecoder.addABI(contract.ABI(), contract.contractName);
|
||||||
@ -93,10 +87,6 @@ export class ContractWrappers {
|
|||||||
this.staking = new StakingContract(contractAddresses.stakingProxy, this.getProvider());
|
this.staking = new StakingContract(contractAddresses.stakingProxy, this.getProvider());
|
||||||
this.devUtils = new DevUtilsContract(contractAddresses.devUtils, this.getProvider());
|
this.devUtils = new DevUtilsContract(contractAddresses.devUtils, this.getProvider());
|
||||||
this.coordinator = new CoordinatorContract(contractAddresses.coordinator, this.getProvider());
|
this.coordinator = new CoordinatorContract(contractAddresses.coordinator, this.getProvider());
|
||||||
this.libTransactionDecoder = new LibTransactionDecoderContract(
|
|
||||||
contractAddresses.libTransactionDecoder,
|
|
||||||
this.getProvider(),
|
|
||||||
);
|
|
||||||
this.contractAddresses = contractAddresses;
|
this.contractAddresses = contractAddresses;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -81,7 +81,6 @@ export {
|
|||||||
StakingProxyStakingContractAttachedToProxyEventArgs,
|
StakingProxyStakingContractAttachedToProxyEventArgs,
|
||||||
StakingProxyStakingContractDetachedFromProxyEventArgs,
|
StakingProxyStakingContractDetachedFromProxyEventArgs,
|
||||||
} from './generated-wrappers/staking_proxy';
|
} from './generated-wrappers/staking_proxy';
|
||||||
export { LibTransactionDecoderContract } from './generated-wrappers/lib_transaction_decoder';
|
|
||||||
export {
|
export {
|
||||||
BlockRange,
|
BlockRange,
|
||||||
SupportedProvider,
|
SupportedProvider,
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "3.2.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Refactor into public libraries.",
|
||||||
|
"pr": 2464
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1580988106,
|
"timestamp": 1580988106,
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
|
@ -1,4 +1,21 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "6.1.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Update `DevUtils` deployment",
|
||||||
|
"pr": 2456
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Remove `LibTransactionDecoder` deployment",
|
||||||
|
"pr": 2456
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Use contract package artifacts in ganache migrations",
|
||||||
|
"pr": 2456
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1580988106,
|
"timestamp": 1580988106,
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
|
@ -63,7 +63,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@0x/base-contract": "^6.1.2",
|
"@0x/base-contract": "^6.1.2",
|
||||||
"@0x/contract-addresses": "^4.4.0",
|
"@0x/contract-addresses": "^4.4.0",
|
||||||
"@0x/contract-artifacts": "^3.4.1",
|
|
||||||
"@0x/contract-wrappers": "^13.4.2",
|
"@0x/contract-wrappers": "^13.4.2",
|
||||||
"@0x/contracts-asset-proxy": "^3.1.3",
|
"@0x/contracts-asset-proxy": "^3.1.3",
|
||||||
"@0x/contracts-coordinator": "^3.0.6",
|
"@0x/contracts-coordinator": "^3.0.6",
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
|
import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
|
||||||
import * as artifacts from '@0x/contract-artifacts';
|
|
||||||
import { ForwarderContract } from '@0x/contract-wrappers';
|
|
||||||
import {
|
import {
|
||||||
|
artifacts as assetProxyArtifacts,
|
||||||
ERC1155ProxyContract,
|
ERC1155ProxyContract,
|
||||||
ERC20BridgeProxyContract,
|
ERC20BridgeProxyContract,
|
||||||
ERC20ProxyContract,
|
ERC20ProxyContract,
|
||||||
@ -9,12 +8,17 @@ import {
|
|||||||
MultiAssetProxyContract,
|
MultiAssetProxyContract,
|
||||||
StaticCallProxyContract,
|
StaticCallProxyContract,
|
||||||
} from '@0x/contracts-asset-proxy';
|
} from '@0x/contracts-asset-proxy';
|
||||||
import { CoordinatorContract, CoordinatorRegistryContract } from '@0x/contracts-coordinator';
|
import {
|
||||||
import { DevUtilsContract, LibTransactionDecoderContract } from '@0x/contracts-dev-utils';
|
artifacts as coordinatorArtifacts,
|
||||||
import { ERC1155MintableContract } from '@0x/contracts-erc1155';
|
CoordinatorContract,
|
||||||
import { DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20';
|
CoordinatorRegistryContract,
|
||||||
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
} from '@0x/contracts-coordinator';
|
||||||
import { ExchangeContract } from '@0x/contracts-exchange';
|
import { artifacts as devUtilsArtifacts, DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||||
|
import { artifacts as erc1155Artifacts, ERC1155MintableContract } from '@0x/contracts-erc1155';
|
||||||
|
import { artifacts as erc20Artifacts, DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20';
|
||||||
|
import { artifacts as erc721Artifacts, DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||||
|
import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange';
|
||||||
|
import { artifacts as forwarderArtifacts, ForwarderContract } from '@0x/contracts-exchange-forwarder';
|
||||||
import {
|
import {
|
||||||
artifacts as stakingArtifacts,
|
artifacts as stakingArtifacts,
|
||||||
StakingProxyContract,
|
StakingProxyContract,
|
||||||
@ -28,6 +32,18 @@ import { SupportedProvider, TxData } from 'ethereum-types';
|
|||||||
import { constants } from './utils/constants';
|
import { constants } from './utils/constants';
|
||||||
import { erc20TokenInfo, erc721TokenInfo } from './utils/token_info';
|
import { erc20TokenInfo, erc721TokenInfo } from './utils/token_info';
|
||||||
|
|
||||||
|
const allArtifacts = {
|
||||||
|
...assetProxyArtifacts,
|
||||||
|
...coordinatorArtifacts,
|
||||||
|
...devUtilsArtifacts,
|
||||||
|
...erc1155Artifacts,
|
||||||
|
...erc20Artifacts,
|
||||||
|
...erc721Artifacts,
|
||||||
|
...exchangeArtifacts,
|
||||||
|
...forwarderArtifacts,
|
||||||
|
...stakingArtifacts,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and deploys all the contracts that are required for the latest
|
* Creates and deploys all the contracts that are required for the latest
|
||||||
* version of the 0x protocol.
|
* version of the 0x protocol.
|
||||||
@ -44,24 +60,24 @@ export async function runMigrationsAsync(
|
|||||||
|
|
||||||
// Proxies
|
// Proxies
|
||||||
const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
|
const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.ERC20Proxy,
|
assetProxyArtifacts.ERC20Proxy,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
);
|
);
|
||||||
const erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync(
|
const erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.ERC721Proxy,
|
assetProxyArtifacts.ERC721Proxy,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
);
|
);
|
||||||
|
|
||||||
// ZRX
|
// ZRX
|
||||||
const zrxToken = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
|
const zrxToken = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.DummyERC20Token,
|
erc20Artifacts.DummyERC20Token,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
'0x Protocol Token',
|
'0x Protocol Token',
|
||||||
'ZRX',
|
'ZRX',
|
||||||
new BigNumber(18),
|
new BigNumber(18),
|
||||||
@ -69,14 +85,19 @@ export async function runMigrationsAsync(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Ether token
|
// Ether token
|
||||||
const etherToken = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.WETH9, provider, txDefaults, artifacts);
|
const etherToken = await WETH9Contract.deployFrom0xArtifactAsync(
|
||||||
|
erc20Artifacts.WETH9,
|
||||||
|
provider,
|
||||||
|
txDefaults,
|
||||||
|
allArtifacts,
|
||||||
|
);
|
||||||
|
|
||||||
// Exchange
|
// Exchange
|
||||||
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
|
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.Exchange,
|
exchangeArtifacts.Exchange,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
chainId,
|
chainId,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -85,10 +106,10 @@ export async function runMigrationsAsync(
|
|||||||
const totalSupply = new BigNumber(1000000000000000000000000000);
|
const totalSupply = new BigNumber(1000000000000000000000000000);
|
||||||
// tslint:disable-next-line:no-unused-variable
|
// tslint:disable-next-line:no-unused-variable
|
||||||
const dummyErc20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
|
const dummyErc20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.DummyERC20Token,
|
erc20Artifacts.DummyERC20Token,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
token.name,
|
token.name,
|
||||||
token.symbol,
|
token.symbol,
|
||||||
token.decimals,
|
token.decimals,
|
||||||
@ -99,34 +120,34 @@ export async function runMigrationsAsync(
|
|||||||
// ERC721
|
// ERC721
|
||||||
// tslint:disable-next-line:no-unused-variable
|
// tslint:disable-next-line:no-unused-variable
|
||||||
const cryptoKittieToken = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
|
const cryptoKittieToken = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.DummyERC721Token,
|
erc721Artifacts.DummyERC721Token,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
erc721TokenInfo[0].name,
|
erc721TokenInfo[0].name,
|
||||||
erc721TokenInfo[0].symbol,
|
erc721TokenInfo[0].symbol,
|
||||||
);
|
);
|
||||||
|
|
||||||
// 1155 Asset Proxy
|
// 1155 Asset Proxy
|
||||||
const erc1155Proxy = await ERC1155ProxyContract.deployFrom0xArtifactAsync(
|
const erc1155Proxy = await ERC1155ProxyContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.ERC1155Proxy,
|
assetProxyArtifacts.ERC1155Proxy,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
);
|
);
|
||||||
|
|
||||||
const staticCallProxy = await StaticCallProxyContract.deployFrom0xArtifactAsync(
|
const staticCallProxy = await StaticCallProxyContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.StaticCallProxy,
|
assetProxyArtifacts.StaticCallProxy,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
);
|
);
|
||||||
|
|
||||||
const multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
|
const multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.MultiAssetProxy,
|
assetProxyArtifacts.MultiAssetProxy,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
);
|
);
|
||||||
|
|
||||||
await erc20Proxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults);
|
await erc20Proxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults);
|
||||||
@ -152,45 +173,46 @@ export async function runMigrationsAsync(
|
|||||||
|
|
||||||
// CoordinatorRegistry
|
// CoordinatorRegistry
|
||||||
const coordinatorRegistry = await CoordinatorRegistryContract.deployFrom0xArtifactAsync(
|
const coordinatorRegistry = await CoordinatorRegistryContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.CoordinatorRegistry,
|
coordinatorArtifacts.CoordinatorRegistry,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Coordinator
|
// Coordinator
|
||||||
const coordinator = await CoordinatorContract.deployFrom0xArtifactAsync(
|
const coordinator = await CoordinatorContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.Coordinator,
|
coordinatorArtifacts.Coordinator,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
exchange.address,
|
exchange.address,
|
||||||
chainId,
|
chainId,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Dev Utils
|
// Dev Utils
|
||||||
const devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
|
const devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||||
artifacts.DevUtils,
|
devUtilsArtifacts.DevUtils,
|
||||||
|
devUtilsArtifacts,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
exchange.address,
|
exchange.address,
|
||||||
constants.NULL_ADDRESS,
|
constants.NULL_ADDRESS,
|
||||||
);
|
);
|
||||||
|
|
||||||
// tslint:disable-next-line:no-unused-variable
|
// tslint:disable-next-line:no-unused-variable
|
||||||
const erc1155DummyToken = await ERC1155MintableContract.deployFrom0xArtifactAsync(
|
const erc1155DummyToken = await ERC1155MintableContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.ERC1155Mintable,
|
erc1155Artifacts.ERC1155Mintable,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
);
|
);
|
||||||
|
|
||||||
const erc20BridgeProxy = await ERC20BridgeProxyContract.deployFrom0xArtifactAsync(
|
const erc20BridgeProxy = await ERC20BridgeProxyContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.ERC20BridgeProxy,
|
assetProxyArtifacts.ERC20BridgeProxy,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
{},
|
allArtifacts,
|
||||||
);
|
);
|
||||||
await exchange.registerAssetProxy(erc20BridgeProxy.address).awaitTransactionSuccessAsync(txDefaults);
|
await exchange.registerAssetProxy(erc20BridgeProxy.address).awaitTransactionSuccessAsync(txDefaults);
|
||||||
await erc20BridgeProxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults);
|
await erc20BridgeProxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults);
|
||||||
@ -199,10 +221,10 @@ export async function runMigrationsAsync(
|
|||||||
|
|
||||||
const zrxProxy = erc20Proxy.address;
|
const zrxProxy = erc20Proxy.address;
|
||||||
const zrxVault = await ZrxVaultContract.deployFrom0xArtifactAsync(
|
const zrxVault = await ZrxVaultContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.ZrxVault,
|
stakingArtifacts.ZrxVault,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
{},
|
allArtifacts,
|
||||||
zrxProxy,
|
zrxProxy,
|
||||||
zrxToken.address,
|
zrxToken.address,
|
||||||
);
|
);
|
||||||
@ -213,16 +235,16 @@ export async function runMigrationsAsync(
|
|||||||
stakingArtifacts.TestStaking,
|
stakingArtifacts.TestStaking,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
{},
|
allArtifacts,
|
||||||
etherToken.address,
|
etherToken.address,
|
||||||
zrxVault.address,
|
zrxVault.address,
|
||||||
);
|
);
|
||||||
|
|
||||||
const stakingProxy = await StakingProxyContract.deployFrom0xArtifactAsync(
|
const stakingProxy = await StakingProxyContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.StakingProxy,
|
stakingArtifacts.StakingProxy,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
{},
|
allArtifacts,
|
||||||
stakingLogic.address,
|
stakingLogic.address,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -245,23 +267,15 @@ export async function runMigrationsAsync(
|
|||||||
// in the constructor
|
// in the constructor
|
||||||
const { exchangeV2: exchangeV2Address } = getContractAddressesForChainOrThrow(chainId.toNumber());
|
const { exchangeV2: exchangeV2Address } = getContractAddressesForChainOrThrow(chainId.toNumber());
|
||||||
const forwarder = await ForwarderContract.deployFrom0xArtifactAsync(
|
const forwarder = await ForwarderContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.Forwarder,
|
forwarderArtifacts.Forwarder,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
allArtifacts,
|
||||||
exchange.address,
|
exchange.address,
|
||||||
exchangeV2Address || constants.NULL_ADDRESS,
|
exchangeV2Address || constants.NULL_ADDRESS,
|
||||||
etherToken.address,
|
etherToken.address,
|
||||||
);
|
);
|
||||||
|
|
||||||
// LibTransactionDecoder
|
|
||||||
const libTransactionDecoder = await LibTransactionDecoderContract.deployFrom0xArtifactAsync(
|
|
||||||
artifacts.LibTransactionDecoder,
|
|
||||||
provider,
|
|
||||||
txDefaults,
|
|
||||||
artifacts,
|
|
||||||
);
|
|
||||||
|
|
||||||
const contractAddresses = {
|
const contractAddresses = {
|
||||||
erc20Proxy: erc20Proxy.address,
|
erc20Proxy: erc20Proxy.address,
|
||||||
erc721Proxy: erc721Proxy.address,
|
erc721Proxy: erc721Proxy.address,
|
||||||
@ -273,7 +287,6 @@ export async function runMigrationsAsync(
|
|||||||
erc20BridgeProxy: erc20BridgeProxy.address,
|
erc20BridgeProxy: erc20BridgeProxy.address,
|
||||||
zeroExGovernor: constants.NULL_ADDRESS,
|
zeroExGovernor: constants.NULL_ADDRESS,
|
||||||
forwarder: forwarder.address,
|
forwarder: forwarder.address,
|
||||||
libTransactionDecoder: libTransactionDecoder.address,
|
|
||||||
orderValidator: constants.NULL_ADDRESS,
|
orderValidator: constants.NULL_ADDRESS,
|
||||||
dutchAuction: constants.NULL_ADDRESS,
|
dutchAuction: constants.NULL_ADDRESS,
|
||||||
coordinatorRegistry: coordinatorRegistry.address,
|
coordinatorRegistry: coordinatorRegistry.address,
|
||||||
|
@ -9,11 +9,7 @@ import {
|
|||||||
UniswapBridgeContract,
|
UniswapBridgeContract,
|
||||||
} from '@0x/contracts-asset-proxy';
|
} from '@0x/contracts-asset-proxy';
|
||||||
import { artifacts as coordinatorArtifacts, CoordinatorContract } from '@0x/contracts-coordinator';
|
import { artifacts as coordinatorArtifacts, CoordinatorContract } from '@0x/contracts-coordinator';
|
||||||
import {
|
import { artifacts as devUtilsArtifacts, DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||||
artifacts as devUtilsArtifacts,
|
|
||||||
DevUtilsContract,
|
|
||||||
LibTransactionDecoderContract,
|
|
||||||
} from '@0x/contracts-dev-utils';
|
|
||||||
import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange';
|
import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange';
|
||||||
import { artifacts as forwarderArtifacts, ForwarderContract } from '@0x/contracts-exchange-forwarder';
|
import { artifacts as forwarderArtifacts, ForwarderContract } from '@0x/contracts-exchange-forwarder';
|
||||||
import {
|
import {
|
||||||
@ -249,8 +245,9 @@ export async function runMigrationsAsync(supportedProvider: SupportedProvider, t
|
|||||||
]);
|
]);
|
||||||
await submitAndExecuteTransactionAsync(governor, governor.address, batchTransactionData);
|
await submitAndExecuteTransactionAsync(governor, governor.address, batchTransactionData);
|
||||||
|
|
||||||
await DevUtilsContract.deployFrom0xArtifactAsync(
|
await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||||
devUtilsArtifacts.DevUtils,
|
devUtilsArtifacts.DevUtils,
|
||||||
|
devUtilsArtifacts,
|
||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
devUtilsArtifacts,
|
devUtilsArtifacts,
|
||||||
@ -276,13 +273,6 @@ export async function runMigrationsAsync(supportedProvider: SupportedProvider, t
|
|||||||
deployedAddresses.exchangeV2,
|
deployedAddresses.exchangeV2,
|
||||||
deployedAddresses.etherToken,
|
deployedAddresses.etherToken,
|
||||||
);
|
);
|
||||||
|
|
||||||
await LibTransactionDecoderContract.deployFrom0xArtifactAsync(
|
|
||||||
devUtilsArtifacts.LibTransactionDecoder,
|
|
||||||
provider,
|
|
||||||
txDefaults,
|
|
||||||
devUtilsArtifacts,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user