Merge pull request #2464 from 0xProject/feat/contracts/dev-utils/public-libraries-refactor
DevUtils refactor into public libraries
This commit is contained in:
commit
0cb7b75214
@ -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,
|
||||
"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;
|
||||
|
||||
import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol";
|
||||
@ -24,27 +24,29 @@ import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibEIP712.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
import "./Addresses.sol";
|
||||
import "./OrderValidationUtils.sol";
|
||||
import "./OrderTransferSimulationUtils.sol";
|
||||
import "./EthBalanceChecker.sol";
|
||||
import "./ExternalFunctions.sol";
|
||||
|
||||
|
||||
// solhint-disable no-empty-blocks
|
||||
contract DevUtils is
|
||||
Addresses,
|
||||
OrderValidationUtils,
|
||||
LibEIP712ExchangeDomain,
|
||||
EthBalanceChecker
|
||||
EthBalanceChecker,
|
||||
ExternalFunctions
|
||||
{
|
||||
constructor (
|
||||
address _exchange,
|
||||
address _chaiBridge
|
||||
address exchange_,
|
||||
address chaiBridge_
|
||||
)
|
||||
public
|
||||
OrderValidationUtils(
|
||||
_exchange,
|
||||
_chaiBridge
|
||||
Addresses(
|
||||
exchange_,
|
||||
chaiBridge_
|
||||
)
|
||||
OrderTransferSimulationUtils(_exchange)
|
||||
LibEIP712ExchangeDomain(uint256(0), address(0)) // null args because because we only use constants
|
||||
{}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.5;
|
||||
pragma solidity ^0.5.16;
|
||||
|
||||
|
||||
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;
|
||||
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
|
||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol";
|
||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
|
||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
|
||||
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol";
|
||||
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IChai.sol";
|
||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
|
||||
|
||||
|
||||
contract LibAssetData is
|
||||
DeploymentConstants
|
||||
{
|
||||
// 2^256 - 1
|
||||
uint256 constant internal _MAX_UINT256 = uint256(-1);
|
||||
library LibAssetData {
|
||||
|
||||
using LibBytes for bytes;
|
||||
|
||||
// solhint-disable var-name-mixedcase
|
||||
IExchange internal _EXCHANGE;
|
||||
address internal _ERC20_PROXY_ADDRESS;
|
||||
address internal _ERC721_PROXY_ADDRESS;
|
||||
address internal _ERC1155_PROXY_ADDRESS;
|
||||
address internal _STATIC_CALL_PROXY_ADDRESS;
|
||||
address internal _CHAI_BRIDGE_ADDRESS;
|
||||
// solhint-enable var-name-mixedcase
|
||||
|
||||
constructor (
|
||||
address _exchange,
|
||||
address _chaiBridge
|
||||
)
|
||||
public
|
||||
{
|
||||
_EXCHANGE = IExchange(_exchange);
|
||||
_ERC20_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC20Token.selector);
|
||||
_ERC721_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC721Token.selector);
|
||||
_ERC1155_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC1155Assets.selector);
|
||||
_STATIC_CALL_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).StaticCall.selector);
|
||||
_CHAI_BRIDGE_ADDRESS = _chaiBridge;
|
||||
}
|
||||
|
||||
/// @dev Returns the owner's balance of the assets(s) specified in
|
||||
/// assetData. When the asset data contains multiple assets (eg in
|
||||
/// ERC1155 or Multi-Asset), the return value indicates how many
|
||||
/// complete "baskets" of those assets are owned by owner.
|
||||
/// @param ownerAddress Owner of the assets specified by assetData.
|
||||
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
|
||||
/// @return Number of assets (or asset baskets) held by owner.
|
||||
function getBalance(address ownerAddress, bytes memory assetData)
|
||||
public
|
||||
returns (uint256 balance)
|
||||
{
|
||||
// Get id of AssetProxy contract
|
||||
bytes4 assetProxyId = assetData.readBytes4(0);
|
||||
|
||||
if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
|
||||
// Get ERC20 token address
|
||||
address tokenAddress = assetData.readAddress(16);
|
||||
balance = _erc20BalanceOf(tokenAddress, ownerAddress);
|
||||
|
||||
} else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
|
||||
// Get ERC721 token address and id
|
||||
(, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
|
||||
|
||||
// Check if id is owned by ownerAddress
|
||||
bytes memory ownerOfCalldata = abi.encodeWithSelector(
|
||||
IERC721Token(address(0)).ownerOf.selector,
|
||||
tokenId
|
||||
);
|
||||
|
||||
(bool success, bytes memory returnData) = tokenAddress.staticcall(ownerOfCalldata);
|
||||
address currentOwnerAddress = (success && returnData.length == 32) ? returnData.readAddress(12) : address(0);
|
||||
balance = currentOwnerAddress == ownerAddress ? 1 : 0;
|
||||
|
||||
} else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
|
||||
// Get ERC1155 token address, array of ids, and array of values
|
||||
(, address tokenAddress, uint256[] memory tokenIds, uint256[] memory tokenValues,) = decodeERC1155AssetData(assetData);
|
||||
|
||||
uint256 length = tokenIds.length;
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
// Skip over the token if the corresponding value is 0.
|
||||
if (tokenValues[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Encode data for `balanceOf(ownerAddress, tokenIds[i])
|
||||
bytes memory balanceOfData = abi.encodeWithSelector(
|
||||
IERC1155(address(0)).balanceOf.selector,
|
||||
ownerAddress,
|
||||
tokenIds[i]
|
||||
);
|
||||
|
||||
// Query balance
|
||||
(bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
|
||||
uint256 totalBalance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
|
||||
|
||||
// Scale total balance down by corresponding value in assetData
|
||||
uint256 scaledBalance = totalBalance / tokenValues[i];
|
||||
if (scaledBalance == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (scaledBalance < balance || balance == 0) {
|
||||
balance = scaledBalance;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
|
||||
// Encode data for `staticCallProxy.transferFrom(assetData,...)`
|
||||
bytes memory transferFromData = abi.encodeWithSelector(
|
||||
IAssetProxy(address(0)).transferFrom.selector,
|
||||
assetData,
|
||||
address(0), // `from` address is not used
|
||||
address(0), // `to` address is not used
|
||||
0 // `amount` is not used
|
||||
);
|
||||
|
||||
// Check if staticcall would be successful
|
||||
(bool success,) = _STATIC_CALL_PROXY_ADDRESS.staticcall(transferFromData);
|
||||
|
||||
// Success means that the staticcall can be made an unlimited amount of times
|
||||
balance = success ? _MAX_UINT256 : 0;
|
||||
|
||||
} else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
|
||||
// Get address of ERC20 token and bridge contract
|
||||
(, address tokenAddress, address bridgeAddress,) = decodeERC20BridgeAssetData(assetData);
|
||||
if (tokenAddress == _getDaiAddress() && bridgeAddress == _CHAI_BRIDGE_ADDRESS) {
|
||||
uint256 chaiBalance = _erc20BalanceOf(_getChaiAddress(), ownerAddress);
|
||||
// Calculate Dai balance
|
||||
balance = _convertChaiToDaiAmount(chaiBalance);
|
||||
}
|
||||
// Balance will be 0 if bridge is not supported
|
||||
|
||||
} else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
|
||||
// Get array of values and array of assetDatas
|
||||
(, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
|
||||
|
||||
uint256 length = nestedAssetData.length;
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
// Skip over the asset if the corresponding amount is 0.
|
||||
if (assetAmounts[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Query balance of individual assetData
|
||||
uint256 totalBalance = getBalance(ownerAddress, nestedAssetData[i]);
|
||||
|
||||
// Scale total balance down by corresponding value in assetData
|
||||
uint256 scaledBalance = totalBalance / assetAmounts[i];
|
||||
if (scaledBalance == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (scaledBalance < balance || balance == 0) {
|
||||
balance = scaledBalance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Balance will be 0 if assetProxyId is unknown
|
||||
return balance;
|
||||
}
|
||||
|
||||
/// @dev Calls getBalance() for each element of assetData.
|
||||
/// @param ownerAddress Owner of the assets specified by assetData.
|
||||
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
|
||||
/// @return Array of asset balances from getBalance(), with each element
|
||||
/// corresponding to the same-indexed element in the assetData input.
|
||||
function getBatchBalances(address ownerAddress, bytes[] memory assetData)
|
||||
public
|
||||
returns (uint256[] memory balances)
|
||||
{
|
||||
uint256 length = assetData.length;
|
||||
balances = new uint256[](length);
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
balances[i] = getBalance(ownerAddress, assetData[i]);
|
||||
}
|
||||
return balances;
|
||||
}
|
||||
|
||||
/// @dev Returns the number of asset(s) (described by assetData) that
|
||||
/// the corresponding AssetProxy contract is authorized to spend. When the asset data contains
|
||||
/// multiple assets (eg for Multi-Asset), the return value indicates
|
||||
/// how many complete "baskets" of those assets may be spent by all of the corresponding
|
||||
/// AssetProxy contracts.
|
||||
/// @param ownerAddress Owner of the assets specified by assetData.
|
||||
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
|
||||
/// @return Number of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
|
||||
function getAssetProxyAllowance(address ownerAddress, bytes memory assetData)
|
||||
public
|
||||
returns (uint256 allowance)
|
||||
{
|
||||
// Get id of AssetProxy contract
|
||||
bytes4 assetProxyId = assetData.readBytes4(0);
|
||||
|
||||
if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
|
||||
// Get array of values and array of assetDatas
|
||||
(, uint256[] memory amounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
|
||||
|
||||
uint256 length = nestedAssetData.length;
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
// Skip over the asset if the corresponding amount is 0.
|
||||
if (amounts[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Query allowance of individual assetData
|
||||
uint256 totalAllowance = getAssetProxyAllowance(ownerAddress, nestedAssetData[i]);
|
||||
|
||||
// Scale total allowance down by corresponding value in assetData
|
||||
uint256 scaledAllowance = totalAllowance / amounts[i];
|
||||
if (scaledAllowance == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (scaledAllowance < allowance || allowance == 0) {
|
||||
allowance = scaledAllowance;
|
||||
}
|
||||
}
|
||||
return allowance;
|
||||
}
|
||||
|
||||
if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) {
|
||||
// Get ERC20 token address
|
||||
address tokenAddress = assetData.readAddress(16);
|
||||
|
||||
// Encode data for `allowance(ownerAddress, _ERC20_PROXY_ADDRESS)`
|
||||
bytes memory allowanceData = abi.encodeWithSelector(
|
||||
IERC20Token(address(0)).allowance.selector,
|
||||
ownerAddress,
|
||||
_ERC20_PROXY_ADDRESS
|
||||
);
|
||||
|
||||
// Query allowance
|
||||
(bool success, bytes memory returnData) = tokenAddress.staticcall(allowanceData);
|
||||
allowance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
|
||||
|
||||
} else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) {
|
||||
// Get ERC721 token address and id
|
||||
(, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData);
|
||||
|
||||
// Encode data for `isApprovedForAll(ownerAddress, _ERC721_PROXY_ADDRESS)`
|
||||
bytes memory isApprovedForAllData = abi.encodeWithSelector(
|
||||
IERC721Token(address(0)).isApprovedForAll.selector,
|
||||
ownerAddress,
|
||||
_ERC721_PROXY_ADDRESS
|
||||
);
|
||||
|
||||
(bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
|
||||
|
||||
// If not approved for all, call `getApproved(tokenId)`
|
||||
if (!success || returnData.length != 32 || returnData.readUint256(0) != 1) {
|
||||
// Encode data for `getApproved(tokenId)`
|
||||
bytes memory getApprovedData = abi.encodeWithSelector(IERC721Token(address(0)).getApproved.selector, tokenId);
|
||||
(success, returnData) = tokenAddress.staticcall(getApprovedData);
|
||||
|
||||
// Allowance is 1 if successful and the approved address is the ERC721Proxy
|
||||
allowance = success && returnData.length == 32 && returnData.readAddress(12) == _ERC721_PROXY_ADDRESS ? 1 : 0;
|
||||
} else {
|
||||
// Allowance is 2^256 - 1 if `isApprovedForAll` returned true
|
||||
allowance = _MAX_UINT256;
|
||||
}
|
||||
|
||||
} else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) {
|
||||
// Get ERC1155 token address
|
||||
(, address tokenAddress, , , ) = decodeERC1155AssetData(assetData);
|
||||
|
||||
// Encode data for `isApprovedForAll(ownerAddress, _ERC1155_PROXY_ADDRESS)`
|
||||
bytes memory isApprovedForAllData = abi.encodeWithSelector(
|
||||
IERC1155(address(0)).isApprovedForAll.selector,
|
||||
ownerAddress,
|
||||
_ERC1155_PROXY_ADDRESS
|
||||
);
|
||||
|
||||
// Query allowance
|
||||
(bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData);
|
||||
allowance = success && returnData.length == 32 && returnData.readUint256(0) == 1 ? _MAX_UINT256 : 0;
|
||||
|
||||
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
|
||||
// The StaticCallProxy does not require any approvals
|
||||
allowance = _MAX_UINT256;
|
||||
|
||||
} else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
|
||||
// Get address of ERC20 token and bridge contract
|
||||
(, address tokenAddress, address bridgeAddress,) = decodeERC20BridgeAssetData(assetData);
|
||||
if (tokenAddress == _getDaiAddress() && bridgeAddress == _CHAI_BRIDGE_ADDRESS) {
|
||||
bytes memory allowanceData = abi.encodeWithSelector(
|
||||
IERC20Token(address(0)).allowance.selector,
|
||||
ownerAddress,
|
||||
_CHAI_BRIDGE_ADDRESS
|
||||
);
|
||||
(bool success, bytes memory returnData) = _getChaiAddress().staticcall(allowanceData);
|
||||
uint256 chaiAllowance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
|
||||
// Dai allowance is unlimited if Chai allowance is unlimited
|
||||
allowance = chaiAllowance == _MAX_UINT256 ? _MAX_UINT256 : _convertChaiToDaiAmount(chaiAllowance);
|
||||
}
|
||||
// Allowance will be 0 if bridge is not supported
|
||||
}
|
||||
|
||||
// Allowance will be 0 if the assetProxyId is unknown
|
||||
return allowance;
|
||||
}
|
||||
|
||||
/// @dev Calls getAssetProxyAllowance() for each element of assetData.
|
||||
/// @param ownerAddress Owner of the assets specified by assetData.
|
||||
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
|
||||
/// @return An array of asset allowances from getAllowance(), with each
|
||||
/// element corresponding to the same-indexed element in the assetData input.
|
||||
function getBatchAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
|
||||
public
|
||||
returns (uint256[] memory allowances)
|
||||
{
|
||||
uint256 length = assetData.length;
|
||||
allowances = new uint256[](length);
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
allowances[i] = getAssetProxyAllowance(ownerAddress, assetData[i]);
|
||||
}
|
||||
return allowances;
|
||||
}
|
||||
|
||||
/// @dev Calls getBalance() and getAllowance() for assetData.
|
||||
/// @param ownerAddress Owner of the assets specified by assetData.
|
||||
/// @param assetData Details of asset, encoded per the AssetProxy contract specification.
|
||||
/// @return Number of assets (or asset baskets) held by owner, and number
|
||||
/// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
|
||||
function getBalanceAndAssetProxyAllowance(address ownerAddress, bytes memory assetData)
|
||||
public
|
||||
returns (uint256 balance, uint256 allowance)
|
||||
{
|
||||
balance = getBalance(ownerAddress, assetData);
|
||||
allowance = getAssetProxyAllowance(ownerAddress, assetData);
|
||||
return (balance, allowance);
|
||||
}
|
||||
|
||||
/// @dev Calls getBatchBalances() and getBatchAllowances() for each element of assetData.
|
||||
/// @param ownerAddress Owner of the assets specified by assetData.
|
||||
/// @param assetData Array of asset details, each encoded per the AssetProxy contract specification.
|
||||
/// @return An array of asset balances from getBalance(), and an array of
|
||||
/// asset allowances from getAllowance(), with each element
|
||||
/// corresponding to the same-indexed element in the assetData input.
|
||||
function getBatchBalancesAndAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
|
||||
public
|
||||
returns (uint256[] memory balances, uint256[] memory allowances)
|
||||
{
|
||||
balances = getBatchBalances(ownerAddress, assetData);
|
||||
allowances = getBatchAssetProxyAllowances(ownerAddress, assetData);
|
||||
return (balances, allowances);
|
||||
}
|
||||
|
||||
/// @dev Decode AssetProxy identifier
|
||||
/// @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC-721, ERC1155, or MultiAsset asset.
|
||||
/// @return The AssetProxy identifier
|
||||
@ -691,44 +351,4 @@ contract LibAssetData is
|
||||
revert("WRONG_PROXY_ID");
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Queries balance of an ERC20 token. Returns 0 if call was unsuccessful.
|
||||
/// @param tokenAddress Address of ERC20 token.
|
||||
/// @param ownerAddress Address of owner of ERC20 token.
|
||||
/// @return balance ERC20 token balance of owner.
|
||||
function _erc20BalanceOf(
|
||||
address tokenAddress,
|
||||
address ownerAddress
|
||||
)
|
||||
internal
|
||||
view
|
||||
returns (uint256 balance)
|
||||
{
|
||||
// Encode data for `balanceOf(ownerAddress)`
|
||||
bytes memory balanceOfData = abi.encodeWithSelector(
|
||||
IERC20Token(address(0)).balanceOf.selector,
|
||||
ownerAddress
|
||||
);
|
||||
|
||||
// Query balance
|
||||
(bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData);
|
||||
balance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
|
||||
return balance;
|
||||
}
|
||||
|
||||
/// @dev Converts an amount of Chai into its equivalent Dai amount.
|
||||
/// Also accumulates Dai from DSR if called after the last time it was collected.
|
||||
/// @param chaiAmount Amount of Chai to converts.
|
||||
function _convertChaiToDaiAmount(uint256 chaiAmount)
|
||||
internal
|
||||
returns (uint256 daiAmount)
|
||||
{
|
||||
PotLike pot = IChai(_getChaiAddress()).pot();
|
||||
// Accumulate savings if called after last time savings were collected
|
||||
uint256 chiMultiplier = (now > pot.rho())
|
||||
? pot.drip()
|
||||
: pot.chi();
|
||||
daiAmount = LibMath.getPartialAmountFloor(chiMultiplier, 10**27, chaiAmount);
|
||||
return daiAmount;
|
||||
}
|
||||
}
|
||||
|
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;
|
||||
|
||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
|
||||
@ -24,7 +24,7 @@ import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
|
||||
|
||||
contract LibTransactionDecoder {
|
||||
library LibTransactionDecoder {
|
||||
|
||||
using LibBytes for bytes;
|
||||
|
||||
|
@ -16,36 +16,26 @@
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.5.9;
|
||||
pragma solidity ^0.5.16;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
|
||||
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
|
||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
|
||||
import "./Addresses.sol";
|
||||
import "./AssetBalance.sol";
|
||||
import "./LibAssetData.sol";
|
||||
import "./OrderTransferSimulationUtils.sol";
|
||||
import "./LibOrderTransferSimulation.sol";
|
||||
|
||||
|
||||
contract OrderValidationUtils is
|
||||
LibAssetData,
|
||||
OrderTransferSimulationUtils
|
||||
Addresses,
|
||||
AssetBalance
|
||||
{
|
||||
using LibBytes for bytes;
|
||||
using LibSafeMath for uint256;
|
||||
|
||||
constructor (
|
||||
address _exchange,
|
||||
address _chaiBridge
|
||||
)
|
||||
public
|
||||
LibAssetData(
|
||||
_exchange,
|
||||
_chaiBridge
|
||||
)
|
||||
{}
|
||||
|
||||
/// @dev Fetches all order-relevant information needed to validate if the supplied order is fillable.
|
||||
/// @param order The order structure.
|
||||
/// @param signature Signature provided by maker that proves the order's authenticity.
|
||||
@ -65,23 +55,22 @@ contract OrderValidationUtils is
|
||||
)
|
||||
{
|
||||
// Get info specific to order
|
||||
orderInfo = _EXCHANGE.getOrderInfo(order);
|
||||
orderInfo = IExchange(exchangeAddress).getOrderInfo(order);
|
||||
|
||||
// Validate the maker's signature
|
||||
address makerAddress = order.makerAddress;
|
||||
isValidSignature = _EXCHANGE.isValidOrderSignature(
|
||||
isValidSignature = IExchange(exchangeAddress).isValidOrderSignature(
|
||||
order,
|
||||
signature
|
||||
);
|
||||
|
||||
// Get the transferable amount of the `makerAsset`
|
||||
uint256 transferableMakerAssetAmount = getTransferableAssetAmount(makerAddress, order.makerAssetData);
|
||||
uint256 transferableMakerAssetAmount = _getTransferableConvertedMakerAssetAmount(
|
||||
order
|
||||
);
|
||||
|
||||
// Assign to stack variables to reduce redundant mloads/sloads
|
||||
uint256 takerAssetAmount = order.takerAssetAmount;
|
||||
uint256 makerFee = order.makerFee;
|
||||
|
||||
// Get the amount of `takerAsset` that is transferable to maker given the transferability of `makerAsset`, `makerFeeAsset`,
|
||||
// Get the amount of `takerAsset` that is transferable to maker given the
|
||||
// transferability of `makerAsset`, `makerFeeAsset`,
|
||||
// and the total amounts specified in the order
|
||||
uint256 transferableTakerAssetAmount;
|
||||
if (order.makerAssetData.equals(order.makerFeeAssetData)) {
|
||||
@ -89,32 +78,35 @@ contract OrderValidationUtils is
|
||||
// transferableMakerAssetAmount / (makerAssetAmount + makerFee)
|
||||
transferableTakerAssetAmount = LibMath.getPartialAmountFloor(
|
||||
transferableMakerAssetAmount,
|
||||
order.makerAssetAmount.safeAdd(makerFee),
|
||||
takerAssetAmount
|
||||
order.makerAssetAmount.safeAdd(order.makerFee),
|
||||
order.takerAssetAmount
|
||||
);
|
||||
} else {
|
||||
// If `makerFee` is 0, the % that can be filled is (transferableMakerAssetAmount / makerAssetAmount)
|
||||
if (makerFee == 0) {
|
||||
if (order.makerFee == 0) {
|
||||
transferableTakerAssetAmount = LibMath.getPartialAmountFloor(
|
||||
transferableMakerAssetAmount,
|
||||
order.makerAssetAmount,
|
||||
takerAssetAmount
|
||||
order.takerAssetAmount
|
||||
);
|
||||
|
||||
// If `makerAsset` does not equal `makerFeeAsset`, the % that can be filled is the lower of
|
||||
// (transferableMakerAssetAmount / makerAssetAmount) and (transferableMakerAssetFeeAmount / makerFee)
|
||||
} else {
|
||||
// Get the transferable amount of the `makerFeeAsset`
|
||||
uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount(makerAddress, order.makerFeeAssetData);
|
||||
uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount(
|
||||
makerAddress,
|
||||
order.makerFeeAssetData
|
||||
);
|
||||
uint256 transferableMakerToTakerAmount = LibMath.getPartialAmountFloor(
|
||||
transferableMakerAssetAmount,
|
||||
order.makerAssetAmount,
|
||||
takerAssetAmount
|
||||
order.takerAssetAmount
|
||||
);
|
||||
uint256 transferableMakerFeeToTakerAmount = LibMath.getPartialAmountFloor(
|
||||
transferableMakerFeeAssetAmount,
|
||||
makerFee,
|
||||
takerAssetAmount
|
||||
order.makerFee,
|
||||
order.takerAssetAmount
|
||||
);
|
||||
transferableTakerAssetAmount = LibSafeMath.min256(transferableMakerToTakerAmount, transferableMakerFeeToTakerAmount);
|
||||
}
|
||||
@ -122,16 +114,17 @@ contract OrderValidationUtils is
|
||||
|
||||
// `fillableTakerAssetAmount` is the lower of the order's remaining `takerAssetAmount` and the `transferableTakerAssetAmount`
|
||||
fillableTakerAssetAmount = LibSafeMath.min256(
|
||||
takerAssetAmount.safeSub(orderInfo.orderTakerAssetFilledAmount),
|
||||
order.takerAssetAmount.safeSub(orderInfo.orderTakerAssetFilledAmount),
|
||||
transferableTakerAssetAmount
|
||||
);
|
||||
|
||||
// Execute the maker transfers.
|
||||
fillableTakerAssetAmount = getSimulatedOrderMakerTransferResults(
|
||||
fillableTakerAssetAmount = LibOrderTransferSimulation.getSimulatedOrderMakerTransferResults(
|
||||
exchangeAddress,
|
||||
order,
|
||||
order.takerAddress,
|
||||
fillableTakerAssetAmount
|
||||
) == OrderTransferResults.TransfersSuccessful ? fillableTakerAssetAmount : 0;
|
||||
) == LibOrderTransferSimulation.OrderTransferResults.TransfersSuccessful ? fillableTakerAssetAmount : 0;
|
||||
|
||||
if (!_isAssetDataValid(order.takerAssetData)) {
|
||||
fillableTakerAssetAmount = 0;
|
||||
@ -181,7 +174,7 @@ contract OrderValidationUtils is
|
||||
return (ordersInfo, fillableTakerAssetAmounts, isValidSignature);
|
||||
}
|
||||
|
||||
/// @dev Gets the amount of an asset transferable by the owner.
|
||||
/// @dev Gets the amount of an asset transferable by the maker of an order.
|
||||
/// @param ownerAddress Address of the owner of the asset.
|
||||
/// @param assetData Description of tokens, per the AssetProxy contract specification.
|
||||
/// @return The amount of the asset tranferable by the owner.
|
||||
@ -193,7 +186,26 @@ contract OrderValidationUtils is
|
||||
public
|
||||
returns (uint256 transferableAssetAmount)
|
||||
{
|
||||
(uint256 balance, uint256 allowance) = getBalanceAndAssetProxyAllowance(ownerAddress, assetData);
|
||||
(uint256 balance, uint256 allowance) = getBalanceAndAssetProxyAllowance(
|
||||
ownerAddress,
|
||||
assetData
|
||||
);
|
||||
transferableAssetAmount = LibSafeMath.min256(balance, allowance);
|
||||
return transferableAssetAmount;
|
||||
}
|
||||
|
||||
/// @dev Gets the amount of an asset transferable by the maker of an order.
|
||||
/// Similar to `getTransferableAssetAmount()`, but can handle maker asset
|
||||
/// types that depend on taker assets being transferred first (e.g., Dydx bridge).
|
||||
/// @param order The order.
|
||||
/// @return transferableAssetAmount Amount of maker asset that can be transferred.
|
||||
function _getTransferableConvertedMakerAssetAmount(
|
||||
LibOrder.Order memory order
|
||||
)
|
||||
internal
|
||||
returns (uint256 transferableAssetAmount)
|
||||
{
|
||||
(uint256 balance, uint256 allowance) = _getConvertibleMakerBalanceAndAssetProxyAllowance(order);
|
||||
transferableAssetAmount = LibSafeMath.min256(balance, allowance);
|
||||
return transferableAssetAmount;
|
||||
}
|
||||
@ -221,7 +233,8 @@ contract OrderValidationUtils is
|
||||
}
|
||||
|
||||
// Get array of values and array of assetDatas
|
||||
(, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
|
||||
(, , bytes[] memory nestedAssetData) =
|
||||
LibAssetData.decodeMultiAssetData(assetData);
|
||||
|
||||
uint256 length = nestedAssetData.length;
|
||||
for (uint256 i = 0; i != length; i++) {
|
||||
|
@ -8,7 +8,7 @@
|
||||
"main": "lib/src/index.js",
|
||||
"scripts": {
|
||||
"build": "yarn pre_build && tsc -b",
|
||||
"test": "yarn assert_deployable && echo !!! Tests are run via @0x/contracts-integrations !!!",
|
||||
"test": "yarn assert_deployable",
|
||||
"assert_deployable": "node -e \"const bytecodeLen = (require('./generated-artifacts/DevUtils.json').compilerOutput.evm.bytecode.object.length-2)/2; assert(bytecodeLen<=0x6000,'DevUtils contract is too big to deploy, per EIP-170. '+bytecodeLen+'>'+0x6000)\"",
|
||||
"build:ci": "yarn build",
|
||||
"pre_build": "run-s compile quantify_bytecode contracts:gen generate_contract_wrappers contracts:copy",
|
||||
@ -27,8 +27,8 @@
|
||||
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
|
||||
},
|
||||
"config": {
|
||||
"publicInterfaceContracts": "DevUtils,LibAssetData,LibTransactionDecoder",
|
||||
"abis": "./test/generated-artifacts/@(DevUtils|EthBalanceChecker|LibAssetData|LibTransactionDecoder|OrderTransferSimulationUtils|OrderValidationUtils).json",
|
||||
"publicInterfaceContracts": "DevUtils,LibAssetData,LibOrderTransferSimulation,LibTransactionDecoder",
|
||||
"abis": "./test/generated-artifacts/@(Addresses|AssetBalance|DevUtils|EthBalanceChecker|ExternalFunctions|LibAssetData|LibOrderTransferSimulation|LibTransactionDecoder|OrderTransferSimulationUtils|OrderValidationUtils).json",
|
||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
|
||||
},
|
||||
"repository": {
|
||||
@ -41,12 +41,17 @@
|
||||
},
|
||||
"homepage": "https://github.com/0xProject/0x-monorepo/contracts/dev-utils/README.md",
|
||||
"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/assert": "^3.0.5",
|
||||
"@0x/contracts-gen": "^2.0.6",
|
||||
"@0x/sol-compiler": "^4.0.6",
|
||||
"@0x/ts-doc-gen": "^0.0.22",
|
||||
"@0x/tslint-config": "^4.0.0",
|
||||
"@0x/utils": "^5.2.0",
|
||||
"@types/node": "*",
|
||||
"ethereum-types": "^3.0.0",
|
||||
"ethers": "~4.0.4",
|
||||
|
@ -7,9 +7,11 @@ import { ContractArtifact } from 'ethereum-types';
|
||||
|
||||
import * as DevUtils from '../generated-artifacts/DevUtils.json';
|
||||
import * as LibAssetData from '../generated-artifacts/LibAssetData.json';
|
||||
import * as LibOrderTransferSimulation from '../generated-artifacts/LibOrderTransferSimulation.json';
|
||||
import * as LibTransactionDecoder from '../generated-artifacts/LibTransactionDecoder.json';
|
||||
export const artifacts = {
|
||||
DevUtils: DevUtils as ContractArtifact,
|
||||
LibAssetData: LibAssetData as ContractArtifact,
|
||||
LibOrderTransferSimulation: LibOrderTransferSimulation as ContractArtifact,
|
||||
LibTransactionDecoder: LibTransactionDecoder as ContractArtifact,
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
export { artifacts } from './artifacts';
|
||||
export { DevUtilsContract, LibAssetDataContract, LibTransactionDecoderContract } from './wrappers';
|
||||
export { DevUtilsContract } from './wrappers';
|
||||
export {
|
||||
ContractArtifact,
|
||||
ContractChains,
|
||||
|
@ -5,4 +5,5 @@
|
||||
*/
|
||||
export * from '../generated-wrappers/dev_utils';
|
||||
export * from '../generated-wrappers/lib_asset_data';
|
||||
export * from '../generated-wrappers/lib_order_transfer_simulation';
|
||||
export * from '../generated-wrappers/lib_transaction_decoder';
|
||||
|
@ -5,16 +5,24 @@
|
||||
*/
|
||||
import { ContractArtifact } from 'ethereum-types';
|
||||
|
||||
import * as Addresses from '../test/generated-artifacts/Addresses.json';
|
||||
import * as AssetBalance from '../test/generated-artifacts/AssetBalance.json';
|
||||
import * as DevUtils from '../test/generated-artifacts/DevUtils.json';
|
||||
import * as EthBalanceChecker from '../test/generated-artifacts/EthBalanceChecker.json';
|
||||
import * as ExternalFunctions from '../test/generated-artifacts/ExternalFunctions.json';
|
||||
import * as LibAssetData from '../test/generated-artifacts/LibAssetData.json';
|
||||
import * as LibOrderTransferSimulation from '../test/generated-artifacts/LibOrderTransferSimulation.json';
|
||||
import * as LibTransactionDecoder from '../test/generated-artifacts/LibTransactionDecoder.json';
|
||||
import * as OrderTransferSimulationUtils from '../test/generated-artifacts/OrderTransferSimulationUtils.json';
|
||||
import * as OrderValidationUtils from '../test/generated-artifacts/OrderValidationUtils.json';
|
||||
export const artifacts = {
|
||||
Addresses: Addresses as ContractArtifact,
|
||||
AssetBalance: AssetBalance as ContractArtifact,
|
||||
DevUtils: DevUtils as ContractArtifact,
|
||||
EthBalanceChecker: EthBalanceChecker as ContractArtifact,
|
||||
ExternalFunctions: ExternalFunctions as ContractArtifact,
|
||||
LibAssetData: LibAssetData as ContractArtifact,
|
||||
LibOrderTransferSimulation: LibOrderTransferSimulation as ContractArtifact,
|
||||
LibTransactionDecoder: LibTransactionDecoder as ContractArtifact,
|
||||
OrderTransferSimulationUtils: OrderTransferSimulationUtils as ContractArtifact,
|
||||
OrderValidationUtils: OrderValidationUtils as ContractArtifact,
|
||||
|
@ -3,9 +3,13 @@
|
||||
* Warning: This file is auto-generated by contracts-gen. Don't edit manually.
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
export * from '../test/generated-wrappers/addresses';
|
||||
export * from '../test/generated-wrappers/asset_balance';
|
||||
export * from '../test/generated-wrappers/dev_utils';
|
||||
export * from '../test/generated-wrappers/eth_balance_checker';
|
||||
export * from '../test/generated-wrappers/external_functions';
|
||||
export * from '../test/generated-wrappers/lib_asset_data';
|
||||
export * from '../test/generated-wrappers/lib_order_transfer_simulation';
|
||||
export * from '../test/generated-wrappers/lib_transaction_decoder';
|
||||
export * from '../test/generated-wrappers/order_transfer_simulation_utils';
|
||||
export * from '../test/generated-wrappers/order_validation_utils';
|
||||
|
@ -5,10 +5,15 @@
|
||||
"files": [
|
||||
"generated-artifacts/DevUtils.json",
|
||||
"generated-artifacts/LibAssetData.json",
|
||||
"generated-artifacts/LibOrderTransferSimulation.json",
|
||||
"generated-artifacts/LibTransactionDecoder.json",
|
||||
"test/generated-artifacts/Addresses.json",
|
||||
"test/generated-artifacts/AssetBalance.json",
|
||||
"test/generated-artifacts/DevUtils.json",
|
||||
"test/generated-artifacts/EthBalanceChecker.json",
|
||||
"test/generated-artifacts/ExternalFunctions.json",
|
||||
"test/generated-artifacts/LibAssetData.json",
|
||||
"test/generated-artifacts/LibOrderTransferSimulation.json",
|
||||
"test/generated-artifacts/LibTransactionDecoder.json",
|
||||
"test/generated-artifacts/OrderTransferSimulationUtils.json",
|
||||
"test/generated-artifacts/OrderValidationUtils.json"
|
||||
|
@ -4,11 +4,11 @@
|
||||
"changes": [
|
||||
{
|
||||
"note": "Add `allowance()` and `balanceOf()` to `LibERC20Token`",
|
||||
"pr": 2462
|
||||
"pr": 2464
|
||||
},
|
||||
{
|
||||
"note": "Fix broken tests",
|
||||
"pr": 2462
|
||||
"pr": 2456
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -94,7 +94,8 @@ library LibERC20Token {
|
||||
|
||||
/// @dev Retrieves the number of decimals for a token.
|
||||
/// Returns `18` if the call reverts.
|
||||
/// @return The number of decimals places for the token.
|
||||
/// @param token The address of the token contract.
|
||||
/// @return tokenDecimals The number of decimals places for the token.
|
||||
function decimals(address token)
|
||||
internal
|
||||
view
|
||||
@ -107,6 +108,50 @@ library LibERC20Token {
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Retrieves the allowance for a token, owner, and spender.
|
||||
/// Returns `0` if the call reverts.
|
||||
/// @param token The address of the token contract.
|
||||
/// @param owner The owner of the tokens.
|
||||
/// @param spender The address the spender.
|
||||
/// @return allowance The allowance for a token, owner, and spender.
|
||||
function allowance(address token, address owner, address spender)
|
||||
internal
|
||||
view
|
||||
returns (uint256 allowance_)
|
||||
{
|
||||
(bool didSucceed, bytes memory resultData) = token.staticcall(
|
||||
abi.encodeWithSelector(
|
||||
IERC20Token(0).allowance.selector,
|
||||
owner,
|
||||
spender
|
||||
)
|
||||
);
|
||||
if (didSucceed && resultData.length == 32) {
|
||||
allowance_ = LibBytes.readUint256(resultData, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Retrieves the balance for a token owner.
|
||||
/// Returns `0` if the call reverts.
|
||||
/// @param token The address of the token contract.
|
||||
/// @param owner The owner of the tokens.
|
||||
/// @return balance The token balance of an owner.
|
||||
function balanceOf(address token, address owner)
|
||||
internal
|
||||
view
|
||||
returns (uint256 balance)
|
||||
{
|
||||
(bool didSucceed, bytes memory resultData) = token.staticcall(
|
||||
abi.encodeWithSelector(
|
||||
IERC20Token(0).balanceOf.selector,
|
||||
owner
|
||||
)
|
||||
);
|
||||
if (didSucceed && resultData.length == 32) {
|
||||
balance = LibBytes.readUint256(resultData, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Executes a call on address `target` with calldata `callData`
|
||||
/// and asserts that either nothing was returned or a single boolean
|
||||
/// was returned equal to `true`.
|
||||
|
@ -5,6 +5,10 @@
|
||||
{
|
||||
"note": "Remove dependency on `DevUtils` for asset data encoding/decoding",
|
||||
"pr": 2462
|
||||
},
|
||||
{
|
||||
"note": "Update tests for refactored `DevUtils`",
|
||||
"pr": 2464
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -26,8 +26,9 @@ blockchainTests.fork.resets('DevUtils mainnet tests', env => {
|
||||
|
||||
before(async () => {
|
||||
[noDaiAddress] = await env.getAccountAddressesAsync();
|
||||
devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
|
||||
devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||
devUtilsArtifacts.DevUtils,
|
||||
devUtilsArtifacts,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
devUtilsArtifacts,
|
||||
|
@ -19,8 +19,9 @@ blockchainTests('DevUtils.getOrderHash', env => {
|
||||
exchangeArtifacts,
|
||||
new BigNumber(chainId),
|
||||
);
|
||||
devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
|
||||
devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||
artifacts.DevUtils,
|
||||
artifacts,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
|
@ -1,13 +1,13 @@
|
||||
import * as crypto from 'crypto';
|
||||
|
||||
import { artifacts as proxyArtifacts, TestStaticCallTargetContract } from '@0x/contracts-asset-proxy';
|
||||
import { artifacts, LibAssetDataContract } from '@0x/contracts-dev-utils';
|
||||
import { artifacts, DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||
import { ERC1155MintableContract } from '@0x/contracts-erc1155';
|
||||
import { DummyERC20TokenContract } from '@0x/contracts-erc20';
|
||||
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
|
||||
import { AssetProxyId } from '@0x/types';
|
||||
import { BigNumber, hexUtils, LibBytesRevertErrors, StringRevertError } from '@0x/utils';
|
||||
import { BigNumber, hexUtils, LibBytesRevertErrors } from '@0x/utils';
|
||||
|
||||
import { Actor } from '../framework/actors/base';
|
||||
import { DeploymentManager } from '../framework/deployment_manager';
|
||||
@ -53,7 +53,7 @@ const KNOWN_STATIC_CALL_ENCODING = {
|
||||
blockchainTests.resets('LibAssetData', env => {
|
||||
let deployment: DeploymentManager;
|
||||
let staticCallTarget: TestStaticCallTargetContract;
|
||||
let libAssetData: LibAssetDataContract;
|
||||
let devUtils: DevUtilsContract;
|
||||
|
||||
let tokenOwner: Actor;
|
||||
|
||||
@ -73,8 +73,9 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
});
|
||||
tokenOwner = new Actor({ name: 'Token Owner', deployment });
|
||||
|
||||
libAssetData = await LibAssetDataContract.deployFrom0xArtifactAsync(
|
||||
artifacts.LibAssetData,
|
||||
devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||
artifacts.DevUtils,
|
||||
artifacts,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
@ -104,7 +105,7 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
});
|
||||
|
||||
it('should have a deployed-to address', () => {
|
||||
expect(libAssetData.address.slice(0, 2)).to.equal('0x');
|
||||
expect(devUtils.address.slice(0, 2)).to.equal('0x');
|
||||
});
|
||||
|
||||
describe('encoding and decoding', () => {
|
||||
@ -117,17 +118,17 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
];
|
||||
|
||||
for (const [assetData, proxyId] of assetDataScenarios) {
|
||||
expect(await libAssetData.decodeAssetProxyId(assetData).callAsync()).to.equal(proxyId);
|
||||
expect(await devUtils.decodeAssetProxyId(assetData).callAsync()).to.equal(proxyId);
|
||||
}
|
||||
});
|
||||
it('should encode ERC20 asset data', async () => {
|
||||
expect(await libAssetData.encodeERC20AssetData(KNOWN_ERC20_ENCODING.address).callAsync()).to.equal(
|
||||
expect(await devUtils.encodeERC20AssetData(KNOWN_ERC20_ENCODING.address).callAsync()).to.equal(
|
||||
KNOWN_ERC20_ENCODING.assetData,
|
||||
);
|
||||
});
|
||||
|
||||
it('should decode ERC20 asset data', async () => {
|
||||
expect(await libAssetData.decodeERC20AssetData(KNOWN_ERC20_ENCODING.assetData).callAsync()).to.deep.equal([
|
||||
expect(await devUtils.decodeERC20AssetData(KNOWN_ERC20_ENCODING.assetData).callAsync()).to.deep.equal([
|
||||
AssetProxyId.ERC20,
|
||||
KNOWN_ERC20_ENCODING.address,
|
||||
]);
|
||||
@ -135,21 +136,23 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
|
||||
it('should encode ERC721 asset data', async () => {
|
||||
expect(
|
||||
await libAssetData
|
||||
await devUtils
|
||||
.encodeERC721AssetData(KNOWN_ERC721_ENCODING.address, KNOWN_ERC721_ENCODING.tokenId)
|
||||
.callAsync(),
|
||||
).to.equal(KNOWN_ERC721_ENCODING.assetData);
|
||||
});
|
||||
|
||||
it('should decode ERC721 asset data', async () => {
|
||||
expect(await libAssetData.decodeERC721AssetData(KNOWN_ERC721_ENCODING.assetData).callAsync()).to.deep.equal(
|
||||
[AssetProxyId.ERC721, KNOWN_ERC721_ENCODING.address, KNOWN_ERC721_ENCODING.tokenId],
|
||||
);
|
||||
expect(await devUtils.decodeERC721AssetData(KNOWN_ERC721_ENCODING.assetData).callAsync()).to.deep.equal([
|
||||
AssetProxyId.ERC721,
|
||||
KNOWN_ERC721_ENCODING.address,
|
||||
KNOWN_ERC721_ENCODING.tokenId,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should encode ERC1155 asset data', async () => {
|
||||
expect(
|
||||
await libAssetData
|
||||
await devUtils
|
||||
.encodeERC1155AssetData(
|
||||
KNOWN_ERC1155_ENCODING.tokenAddress,
|
||||
KNOWN_ERC1155_ENCODING.tokenIds,
|
||||
@ -161,9 +164,7 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
});
|
||||
|
||||
it('should decode ERC1155 asset data', async () => {
|
||||
expect(
|
||||
await libAssetData.decodeERC1155AssetData(KNOWN_ERC1155_ENCODING.assetData).callAsync(),
|
||||
).to.deep.equal([
|
||||
expect(await devUtils.decodeERC1155AssetData(KNOWN_ERC1155_ENCODING.assetData).callAsync()).to.deep.equal([
|
||||
AssetProxyId.ERC1155,
|
||||
KNOWN_ERC1155_ENCODING.tokenAddress,
|
||||
KNOWN_ERC1155_ENCODING.tokenIds,
|
||||
@ -174,7 +175,7 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
|
||||
it('should encode multiasset data', async () => {
|
||||
expect(
|
||||
await libAssetData
|
||||
await devUtils
|
||||
.encodeMultiAssetData(
|
||||
KNOWN_MULTI_ASSET_ENCODING.amounts,
|
||||
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
|
||||
@ -184,18 +185,18 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
});
|
||||
|
||||
it('should decode multiasset data', async () => {
|
||||
expect(
|
||||
await libAssetData.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData).callAsync(),
|
||||
).to.deep.equal([
|
||||
expect(await devUtils.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData).callAsync()).to.deep.equal(
|
||||
[
|
||||
AssetProxyId.MultiAsset,
|
||||
KNOWN_MULTI_ASSET_ENCODING.amounts,
|
||||
KNOWN_MULTI_ASSET_ENCODING.nestedAssetData,
|
||||
]);
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
it('should encode StaticCall data', async () => {
|
||||
expect(
|
||||
await libAssetData
|
||||
await devUtils
|
||||
.encodeStaticCallAssetData(
|
||||
KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress,
|
||||
KNOWN_STATIC_CALL_ENCODING.staticCallData,
|
||||
@ -207,7 +208,7 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
|
||||
it('should decode StaticCall data', async () => {
|
||||
expect(
|
||||
await libAssetData.decodeStaticCallAssetData(KNOWN_STATIC_CALL_ENCODING.assetData).callAsync(),
|
||||
await devUtils.decodeStaticCallAssetData(KNOWN_STATIC_CALL_ENCODING.assetData).callAsync(),
|
||||
).to.deep.equal([
|
||||
AssetProxyId.StaticCall,
|
||||
KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress,
|
||||
@ -227,16 +228,14 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
];
|
||||
|
||||
for (const data of assetData) {
|
||||
await libAssetData.revertIfInvalidAssetData(data).callAsync();
|
||||
await devUtils.revertIfInvalidAssetData(data).callAsync();
|
||||
}
|
||||
return;
|
||||
});
|
||||
|
||||
it('should revert for invalid assetProxyId', async () => {
|
||||
const badAssetData = `0x${crypto.randomBytes(4).toString('hex')}${constants.NULL_ADDRESS}`;
|
||||
await expect(libAssetData.revertIfInvalidAssetData(badAssetData).callAsync()).to.eventually.be.rejectedWith(
|
||||
StringRevertError,
|
||||
);
|
||||
await expect(devUtils.revertIfInvalidAssetData(badAssetData).callAsync()).to.revertWith('WRONG_PROXY_ID');
|
||||
});
|
||||
|
||||
it('should revert for invalid assetData with valid assetProxyId', async () => {
|
||||
@ -245,8 +244,8 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
|
||||
for (const data of assetData) {
|
||||
const badData = data.substring(0, data.length - 2); // drop one byte but retain assetProxyId
|
||||
await expect(libAssetData.revertIfInvalidAssetData(badData).callAsync()).to.eventually.be.rejectedWith(
|
||||
LibBytesRevertErrors.InvalidByteOperationError,
|
||||
await expect(devUtils.revertIfInvalidAssetData(badData).callAsync()).to.revertWith(
|
||||
new LibBytesRevertErrors.InvalidByteOperationError(),
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -254,33 +253,31 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
|
||||
describe('getBalance', () => {
|
||||
it('should query ERC20 balance by asset data', async () => {
|
||||
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||
const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||
constants.INITIAL_ERC20_BALANCE,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return 0 if ERC20 token does not exist', async () => {
|
||||
const assetData = await libAssetData.encodeERC20AssetData(constants.NULL_ADDRESS).callAsync();
|
||||
const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync();
|
||||
const assetData = await devUtils.encodeERC20AssetData(constants.NULL_ADDRESS).callAsync();
|
||||
const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync();
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should query ERC721 balance by asset data', async () => {
|
||||
const assetData = await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
|
||||
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
|
||||
const assetData = await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
|
||||
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should return 0 if ERC721 token does not exist', async () => {
|
||||
const assetData = await libAssetData
|
||||
.encodeERC721AssetData(constants.NULL_ADDRESS, erc721TokenId)
|
||||
.callAsync();
|
||||
const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync();
|
||||
const assetData = await devUtils.encodeERC721AssetData(constants.NULL_ADDRESS, erc721TokenId).callAsync();
|
||||
const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync();
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should query ERC1155 balances by asset data', async () => {
|
||||
const assetData = await libAssetData
|
||||
const assetData = await devUtils
|
||||
.encodeERC1155AssetData(
|
||||
erc1155Token.address,
|
||||
[erc1155TokenId],
|
||||
@ -288,11 +285,11 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
constants.NULL_BYTES,
|
||||
)
|
||||
.callAsync();
|
||||
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
|
||||
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should return 0 if ERC1155 token does not exist', async () => {
|
||||
const assetData = await libAssetData
|
||||
const assetData = await devUtils
|
||||
.encodeERC1155AssetData(
|
||||
constants.NULL_ADDRESS,
|
||||
[erc1155TokenId],
|
||||
@ -300,84 +297,84 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
constants.NULL_BYTES,
|
||||
)
|
||||
.callAsync();
|
||||
const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync();
|
||||
const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync();
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should query multi-asset batch balance by asset data', async () => {
|
||||
const assetData = await libAssetData
|
||||
const assetData = await devUtils
|
||||
.encodeMultiAssetData(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[
|
||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
||||
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
||||
],
|
||||
)
|
||||
.callAsync();
|
||||
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
|
||||
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should query multi-asset batch balance by asset data, skipping over a nested asset if its amount == 0', async () => {
|
||||
const assetData = await libAssetData
|
||||
const assetData = await devUtils
|
||||
.encodeMultiAssetData(
|
||||
[constants.ZERO_AMOUNT, new BigNumber(1)],
|
||||
[
|
||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
||||
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
||||
],
|
||||
)
|
||||
.callAsync();
|
||||
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
|
||||
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1);
|
||||
});
|
||||
|
||||
it('should return a balance of 0 if the balance for a nested asset is 0', async () => {
|
||||
const assetData = await libAssetData
|
||||
const assetData = await devUtils
|
||||
.encodeMultiAssetData(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[
|
||||
await libAssetData.encodeERC20AssetData(secondErc20Token.address).callAsync(),
|
||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
await devUtils.encodeERC20AssetData(secondErc20Token.address).callAsync(),
|
||||
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
],
|
||||
)
|
||||
.callAsync();
|
||||
expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||
expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||
constants.ZERO_AMOUNT,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return a balance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
|
||||
const fakeAssetData = '0x01020304';
|
||||
const balance = await libAssetData.getBalance(tokenOwner.address, fakeAssetData).callAsync();
|
||||
const balance = await devUtils.getBalance(tokenOwner.address, fakeAssetData).callAsync();
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should return a balance of MAX_UINT256 if the the StaticCallProxy assetData contains data for a successful staticcall', async () => {
|
||||
const staticCallData = staticCallTarget.isOddNumber(new BigNumber(1)).getABIEncodedTransactionData();
|
||||
const expectedResultHash = hexUtils.hash(hexUtils.leftPad(1));
|
||||
const assetData = await libAssetData
|
||||
const assetData = await devUtils
|
||||
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
|
||||
.callAsync();
|
||||
const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync();
|
||||
const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync();
|
||||
expect(balance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
|
||||
it('should return a balance of 0 if the the StaticCallProxy assetData contains data for an unsuccessful staticcall', async () => {
|
||||
const staticCallData = staticCallTarget.isOddNumber(new BigNumber(0)).getABIEncodedTransactionData();
|
||||
const expectedResultHash = hexUtils.hash(hexUtils.leftPad(1));
|
||||
const assetData = await libAssetData
|
||||
const assetData = await devUtils
|
||||
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash)
|
||||
.callAsync();
|
||||
const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync();
|
||||
const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync();
|
||||
expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAssetProxyAllowance', () => {
|
||||
it('should query ERC20 allowances by asset data', async () => {
|
||||
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
||||
).to.bignumber.equal(constants.MAX_UINT256);
|
||||
const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||
constants.MAX_UINT256,
|
||||
);
|
||||
});
|
||||
|
||||
it('should query ERC721 approval by asset data', async () => {
|
||||
@ -390,21 +387,21 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
.awaitTransactionSuccessAsync({
|
||||
from: tokenOwner.address,
|
||||
});
|
||||
const assetData = await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
||||
).to.bignumber.equal(1);
|
||||
const assetData = await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
|
||||
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||
1,
|
||||
);
|
||||
});
|
||||
|
||||
it('should query ERC721 approvalForAll by assetData', async () => {
|
||||
const assetData = await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
||||
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
const assetData = await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync();
|
||||
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||
constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||
);
|
||||
});
|
||||
|
||||
it('should query ERC1155 allowances by asset data', async () => {
|
||||
const assetData = await libAssetData
|
||||
const assetData = await devUtils
|
||||
.encodeERC1155AssetData(
|
||||
erc1155Token.address,
|
||||
[erc1155TokenId],
|
||||
@ -412,9 +409,9 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
constants.NULL_BYTES,
|
||||
)
|
||||
.callAsync();
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
||||
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||
constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||
);
|
||||
});
|
||||
|
||||
it('should query multi-asset allowances by asset data', async () => {
|
||||
@ -424,18 +421,18 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
.awaitTransactionSuccessAsync({
|
||||
from: tokenOwner.address,
|
||||
});
|
||||
const assetData = await libAssetData
|
||||
const assetData = await devUtils
|
||||
.encodeMultiAssetData(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[
|
||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
||||
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
||||
],
|
||||
)
|
||||
.callAsync();
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
||||
).to.bignumber.equal(1);
|
||||
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||
1,
|
||||
);
|
||||
return;
|
||||
});
|
||||
|
||||
@ -446,60 +443,60 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
.awaitTransactionSuccessAsync({
|
||||
from: tokenOwner.address,
|
||||
});
|
||||
const assetData = await libAssetData
|
||||
const assetData = await devUtils
|
||||
.encodeMultiAssetData(
|
||||
[constants.ZERO_AMOUNT, new BigNumber(1)],
|
||||
[
|
||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
||||
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(),
|
||||
],
|
||||
)
|
||||
.callAsync();
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
||||
).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||
constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS,
|
||||
);
|
||||
return;
|
||||
});
|
||||
|
||||
it('should return an allowance of 0 if the allowance for a nested asset is 0', async () => {
|
||||
const assetData = await libAssetData
|
||||
const assetData = await devUtils
|
||||
.encodeMultiAssetData(
|
||||
[new BigNumber(1), new BigNumber(1)],
|
||||
[
|
||||
await libAssetData.encodeERC20AssetData(secondErc20Token.address).callAsync(),
|
||||
await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
await devUtils.encodeERC20AssetData(secondErc20Token.address).callAsync(),
|
||||
await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(),
|
||||
],
|
||||
)
|
||||
.callAsync();
|
||||
expect(
|
||||
await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
||||
).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(
|
||||
constants.ZERO_AMOUNT,
|
||||
);
|
||||
});
|
||||
|
||||
it('should return an allowance of 0 if the assetData does not correspond to an AssetProxy contract', async () => {
|
||||
const fakeAssetData = '0x01020304';
|
||||
const allowance = await libAssetData.getAssetProxyAllowance(tokenOwner.address, fakeAssetData).callAsync();
|
||||
const allowance = await devUtils.getAssetProxyAllowance(tokenOwner.address, fakeAssetData).callAsync();
|
||||
expect(allowance).to.bignumber.equal(constants.ZERO_AMOUNT);
|
||||
});
|
||||
|
||||
it('should return an allowance of MAX_UINT256 for any staticCallAssetData', async () => {
|
||||
const staticCallData = AssetProxyId.StaticCall;
|
||||
const assetData = await libAssetData
|
||||
const assetData = await devUtils
|
||||
.encodeStaticCallAssetData(staticCallTarget.address, staticCallData, constants.KECCAK256_NULL)
|
||||
.callAsync();
|
||||
const allowance = await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync();
|
||||
const allowance = await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync();
|
||||
expect(allowance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBatchBalances', () => {
|
||||
it('should query balances for a batch of asset data strings', async () => {
|
||||
const erc20AssetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
const erc721AssetData = await libAssetData
|
||||
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
const erc721AssetData = await devUtils
|
||||
.encodeERC721AssetData(erc721Token.address, erc721TokenId)
|
||||
.callAsync();
|
||||
expect(
|
||||
await libAssetData.getBatchBalances(tokenOwner.address, [erc20AssetData, erc721AssetData]).callAsync(),
|
||||
await devUtils.getBatchBalances(tokenOwner.address, [erc20AssetData, erc721AssetData]).callAsync(),
|
||||
).to.deep.equal([new BigNumber(constants.INITIAL_ERC20_BALANCE), new BigNumber(1)]);
|
||||
});
|
||||
});
|
||||
@ -512,9 +509,9 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
.awaitTransactionSuccessAsync({
|
||||
from: tokenOwner.address,
|
||||
});
|
||||
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
expect(
|
||||
await libAssetData.getBalanceAndAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
||||
await devUtils.getBalanceAndAssetProxyAllowance(tokenOwner.address, assetData).callAsync(),
|
||||
).to.deep.equal([new BigNumber(constants.INITIAL_ERC20_BALANCE), allowance]);
|
||||
});
|
||||
});
|
||||
@ -526,9 +523,9 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
.awaitTransactionSuccessAsync({
|
||||
from: tokenOwner.address,
|
||||
});
|
||||
const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
expect(
|
||||
await libAssetData.getBatchBalancesAndAssetProxyAllowances(tokenOwner.address, [assetData]).callAsync(),
|
||||
await devUtils.getBatchBalancesAndAssetProxyAllowances(tokenOwner.address, [assetData]).callAsync(),
|
||||
).to.deep.equal([[new BigNumber(constants.INITIAL_ERC20_BALANCE)], [allowance]]);
|
||||
});
|
||||
});
|
||||
@ -541,12 +538,12 @@ blockchainTests.resets('LibAssetData', env => {
|
||||
.awaitTransactionSuccessAsync({
|
||||
from: tokenOwner.address,
|
||||
});
|
||||
const erc20AssetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
const erc721AssetData = await libAssetData
|
||||
const erc20AssetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync();
|
||||
const erc721AssetData = await devUtils
|
||||
.encodeERC721AssetData(erc721Token.address, erc721TokenId)
|
||||
.callAsync();
|
||||
expect(
|
||||
await libAssetData
|
||||
await devUtils
|
||||
.getBatchAssetProxyAllowances(tokenOwner.address, [erc20AssetData, erc721AssetData])
|
||||
.callAsync(),
|
||||
).to.deep.equal([allowance, constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS]);
|
||||
|
@ -1,14 +1,8 @@
|
||||
import { ExchangeContract } from '@0x/contracts-exchange';
|
||||
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
|
||||
import { BlockchainLifecycle } from '@0x/dev-utils';
|
||||
import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange';
|
||||
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
|
||||
import { BigNumber } from '@0x/utils';
|
||||
import * as chai from 'chai';
|
||||
|
||||
import { artifacts, LibTransactionDecoderContract } from '@0x/contracts-dev-utils';
|
||||
|
||||
chaiSetup.configure();
|
||||
const expect = chai.expect;
|
||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
|
||||
import { artifacts, DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||
|
||||
const order = {
|
||||
makerAddress: '0xe36ea790bc9d7ab70c55260c66d52b1eca985f84',
|
||||
@ -30,25 +24,31 @@ const takerAssetFillAmount = new BigNumber('100000000000000000000');
|
||||
const signature =
|
||||
'0x1ce8e3c600d933423172b5021158a6be2e818613ff8e762d70ef490c752fd98a626a215f09f169668990414de75a53da221c294a3002f796d004827258b641876e03';
|
||||
|
||||
describe('LibTransactionDecoder', () => {
|
||||
let libTxDecoder: LibTransactionDecoderContract;
|
||||
const exchangeInterface = new ExchangeContract(constants.NULL_ADDRESS, provider, txDefaults);
|
||||
blockchainTests('LibTransactionDecoder', env => {
|
||||
let devUtils: DevUtilsContract;
|
||||
const exchangeInterface = new ExchangeContract(constants.NULL_ADDRESS, { isEIP1193: true } as any);
|
||||
before(async () => {
|
||||
await blockchainLifecycle.startAsync();
|
||||
libTxDecoder = await LibTransactionDecoderContract.deployFrom0xArtifactAsync(
|
||||
artifacts.LibTransactionDecoder,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||
exchangeArtifacts.Exchange,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
exchangeArtifacts,
|
||||
new BigNumber(1),
|
||||
);
|
||||
devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||
artifacts.DevUtils,
|
||||
artifacts,
|
||||
env.provider,
|
||||
env.txDefaults,
|
||||
artifacts,
|
||||
exchange.address,
|
||||
constants.NULL_ADDRESS,
|
||||
);
|
||||
});
|
||||
after(async () => {
|
||||
await blockchainLifecycle.revertAsync();
|
||||
});
|
||||
|
||||
it('should decode an Exchange.batchCancelOrders() transaction', async () => {
|
||||
const input = exchangeInterface.batchCancelOrders([order, order]).getABIEncodedTransactionData();
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
'batchCancelOrders',
|
||||
[order, order],
|
||||
[],
|
||||
@ -61,7 +61,7 @@ describe('LibTransactionDecoder', () => {
|
||||
[func]([order, order], [takerAssetFillAmount, takerAssetFillAmount], [signature, signature])
|
||||
.getABIEncodedTransactionData();
|
||||
it(`should decode an Exchange.${func}() transaction`, async () => {
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
func,
|
||||
[order, order],
|
||||
[takerAssetFillAmount, takerAssetFillAmount],
|
||||
@ -72,7 +72,7 @@ describe('LibTransactionDecoder', () => {
|
||||
|
||||
it('should decode an Exchange.cancelOrder() transaction', async () => {
|
||||
const input = exchangeInterface.cancelOrder(order).getABIEncodedTransactionData();
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
'cancelOrder',
|
||||
[order],
|
||||
[],
|
||||
@ -85,7 +85,7 @@ describe('LibTransactionDecoder', () => {
|
||||
[func](order, takerAssetFillAmount, signature)
|
||||
.getABIEncodedTransactionData();
|
||||
it(`should decode an Exchange.${func}() transaction`, async () => {
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
func,
|
||||
[order],
|
||||
[takerAssetFillAmount],
|
||||
@ -104,7 +104,7 @@ describe('LibTransactionDecoder', () => {
|
||||
[func]([order, order], takerAssetFillAmount, [signature, signature])
|
||||
.getABIEncodedTransactionData();
|
||||
it(`should decode an Exchange.${func}() transaction`, async () => {
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
func,
|
||||
[order, order],
|
||||
[takerAssetFillAmount],
|
||||
@ -130,7 +130,7 @@ describe('LibTransactionDecoder', () => {
|
||||
const input = exchangeInterface
|
||||
.matchOrders(order, complementaryOrder, signature, signature)
|
||||
.getABIEncodedTransactionData();
|
||||
expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([
|
||||
'matchOrders',
|
||||
[order, complementaryOrder],
|
||||
[order.takerAssetAmount, complementaryOrder.takerAssetAmount],
|
||||
|
@ -195,8 +195,9 @@ export class DeploymentManager {
|
||||
exchange,
|
||||
staking.stakingProxy,
|
||||
]);
|
||||
const devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
|
||||
const devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||
devUtilsArtifacts.DevUtils,
|
||||
devUtilsArtifacts,
|
||||
environment.provider,
|
||||
environment.txDefaults,
|
||||
devUtilsArtifacts,
|
||||
|
@ -55,6 +55,7 @@ export enum {{contractName}}Events {
|
||||
{{/if}}
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class {{contractName}}Contract extends BaseContract {
|
||||
|
@ -53,6 +53,7 @@ export interface AbiGenDummyWithdrawalEventArgs extends DecodedLogArgs {
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class AbiGenDummyContract extends BaseContract {
|
||||
|
@ -34,6 +34,7 @@ import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class LibDummyContract extends BaseContract {
|
||||
|
@ -34,6 +34,7 @@ import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class TestLibDummyContract extends BaseContract {
|
||||
|
@ -18,6 +18,14 @@
|
||||
{
|
||||
"note": "Update `ERC20BridgeSampler` on mainnet and kovan.",
|
||||
"pr": 2459
|
||||
},
|
||||
{
|
||||
"note": "Remove `libTransactionDecoder`",
|
||||
"pr": 2456
|
||||
},
|
||||
{
|
||||
"note": "Update snapshot addresses",
|
||||
"pr": 2464
|
||||
}
|
||||
],
|
||||
"timestamp": 1580811564
|
||||
|
@ -13,7 +13,6 @@
|
||||
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||
"coordinatorRegistry": "0x45797531b873fd5e519477a070a955764c1a5b07",
|
||||
"coordinator": "0x38a795580d0f687e399913a00ddef6a17612c722",
|
||||
"libTransactionDecoder": "0x5f20e82643ce007d87692eb1b3d3fc059588b224",
|
||||
"multiAssetProxy": "0xef701d5389ae74503d633396c4d654eabedc9d78",
|
||||
"staticCallProxy": "0x3517b88c19508c08650616019062b898ab65ed29",
|
||||
"erc1155Proxy": "0x7eefbd48fd63d441ec7435d024ec7c5131019add",
|
||||
@ -43,7 +42,6 @@
|
||||
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||
"coordinatorRegistry": "0x403cc23e88c17c4652fb904784d1af640a6722d9",
|
||||
"coordinator": "0x6ff734d96104965c9c1b0108f83abc46e6e501df",
|
||||
"libTransactionDecoder": "0xb20f3b07afb0e38b6151b9be4f53218bdd7dc231",
|
||||
"multiAssetProxy": "0xab8fbd189c569ccdee3a4d929bb7f557be4028f6",
|
||||
"staticCallProxy": "0xe1b97e47aa3796276033a5341e884d2ba46b6ac1",
|
||||
"erc1155Proxy": "0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d",
|
||||
@ -69,7 +67,6 @@
|
||||
"assetProxyOwner": "0x0000000000000000000000000000000000000000",
|
||||
"zeroExGovernor": "0x3f46b98061a3e1e1f41dff296ec19402c298f8a9",
|
||||
"forwarder": "0xd67f2f346f6e85db70632d9f18f50e04192ab54d",
|
||||
"libTransactionDecoder": "0x34b37611db8190469b735fb2a007d8236c29eb88",
|
||||
"orderValidator": "0x0000000000000000000000000000000000000000",
|
||||
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||
"coordinatorRegistry": "0x1084b6a398e47907bae43fec3ff4b677db6e4fee",
|
||||
@ -100,7 +97,6 @@
|
||||
"zeroExGovernor": "0x6ff734d96104965c9c1b0108f83abc46e6e501df",
|
||||
"forwarder": "0x2759a4c639fa4882d6d64973630ef81faf901d27",
|
||||
"orderValidator": "0x0000000000000000000000000000000000000000",
|
||||
"libTransactionDecoder": "0x067b5997c9058eade0bb03d8fb5e6db7feda80a3",
|
||||
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||
"coordinatorRegistry": "0x09fb99968c016a3ff537bf58fb3d9fe55a7975d5",
|
||||
"coordinator": "0xd29e59e51e8ab5f94121efaeebd935ca4214e257",
|
||||
@ -127,21 +123,20 @@
|
||||
"etherToken": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082",
|
||||
"exchange": "0x48bacb9266a570d521063ef5dd96e61686dbe788",
|
||||
"assetProxyOwner": "0x0000000000000000000000000000000000000000",
|
||||
"erc20BridgeProxy": "0x8ea76477cfaca8f7ea06477fd3c09a740ac6012a",
|
||||
"erc20BridgeProxy": "0x038f9b392fb9a9676dbaddf78ea5fdbf6c7d9710",
|
||||
"zeroExGovernor": "0x0000000000000000000000000000000000000000",
|
||||
"libTransactionDecoder": "0xb48e1b16829c7f5bd62b76cb878a6bb1c4625d7a",
|
||||
"forwarder": "0x5d3ad3561a1235273cbcb4e82fce63a0073d19be",
|
||||
"forwarder": "0xe704967449b57b2382b7fa482718748c13c63190",
|
||||
"orderValidator": "0x0000000000000000000000000000000000000000",
|
||||
"dutchAuction": "0x0000000000000000000000000000000000000000",
|
||||
"coordinatorRegistry": "0xaa86dda78e9434aca114b6676fc742a18d15a1cc",
|
||||
"coordinator": "0x4d3d5c850dd5bd9d6f4adda3dd039a3c8054ca29",
|
||||
"multiAssetProxy": "0xcfc18cec799fbd1793b5c43e773c98d4d61cc2db",
|
||||
"staticCallProxy": "0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f",
|
||||
"devUtils": "0xa31e64ea55b9b6bbb9d6a676738e9a5b23149f84",
|
||||
"devUtils": "0x74341e87b1c4db7d5ed95f92b37509f2525a7a90",
|
||||
"exchangeV2": "0x48bacb9266a570d521063ef5dd96e61686dbe788",
|
||||
"zrxVault": "0x1941ff73d1154774d87521d2d0aaad5d19c8df60",
|
||||
"staking": "0x0d8b0dd11f5d34ed41d556def5f841900d5b1c6b",
|
||||
"stakingProxy": "0x38ef19fdf8e8415f18c307ed71967e19aac28ba1",
|
||||
"zrxVault": "0xc4df27466183c0fe2a5924d6ea56e334deff146a",
|
||||
"staking": "0xf23276778860e420acfc18ebeebf7e829b06965c",
|
||||
"stakingProxy": "0x8a063452f7df2614db1bca3a85ef35da40cf0835",
|
||||
"uniswapBridge": "0x0000000000000000000000000000000000000000",
|
||||
"eth2DaiBridge": "0x0000000000000000000000000000000000000000",
|
||||
"erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
|
||||
|
@ -14,7 +14,6 @@ export interface ContractAddresses {
|
||||
forwarder: string;
|
||||
coordinatorRegistry: string;
|
||||
coordinator: string;
|
||||
libTransactionDecoder: string;
|
||||
multiAssetProxy: string;
|
||||
staticCallProxy: 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,
|
||||
"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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
74
packages/contract-artifacts/artifacts/Forwarder.json
generated
74
packages/contract-artifacts/artifacts/Forwarder.json
generated
File diff suppressed because one or more lines are too long
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 IValidator from '../artifacts/IValidator.json';
|
||||
import * as IWallet from '../artifacts/IWallet.json';
|
||||
import * as LibTransactionDecoder from '../artifacts/LibTransactionDecoder.json';
|
||||
import * as MultiAssetProxy from '../artifacts/MultiAssetProxy.json';
|
||||
import * as Staking from '../artifacts/Staking.json';
|
||||
import * as StakingProxy from '../artifacts/StakingProxy.json';
|
||||
@ -43,7 +42,6 @@ export {
|
||||
IAssetProxy,
|
||||
IValidator,
|
||||
IWallet,
|
||||
LibTransactionDecoder,
|
||||
MultiAssetProxy,
|
||||
StaticCallProxy,
|
||||
WETH9,
|
||||
|
@ -19,7 +19,6 @@
|
||||
"./artifacts/ERC721Token.json",
|
||||
"./artifacts/Exchange.json",
|
||||
"./artifacts/Forwarder.json",
|
||||
"./artifacts/LibTransactionDecoder.json",
|
||||
"./artifacts/IAssetProxy.json",
|
||||
"./artifacts/IValidator.json",
|
||||
"./artifacts/IWallet.json",
|
||||
|
@ -3,8 +3,12 @@
|
||||
"version": "13.5.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "export `evmbytecodeoutputlinkreferences` type.",
|
||||
"note": "Export `EvmBytecodeOutputLinkReferences` type.",
|
||||
"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 { ExchangeContract } from './generated-wrappers/exchange';
|
||||
import { ForwarderContract } from './generated-wrappers/forwarder';
|
||||
import { LibTransactionDecoderContract } from './generated-wrappers/lib_transaction_decoder';
|
||||
import { StakingContract } from './generated-wrappers/staking';
|
||||
import { WETH9Contract } from './generated-wrappers/weth9';
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
/**
|
||||
@ -78,7 +73,6 @@ export class ContractWrappers {
|
||||
ForwarderContract,
|
||||
StakingContract,
|
||||
WETH9Contract,
|
||||
LibTransactionDecoderContract,
|
||||
];
|
||||
contractsArray.forEach(contract => {
|
||||
this._web3Wrapper.abiDecoder.addABI(contract.ABI(), contract.contractName);
|
||||
@ -93,10 +87,6 @@ export class ContractWrappers {
|
||||
this.staking = new StakingContract(contractAddresses.stakingProxy, this.getProvider());
|
||||
this.devUtils = new DevUtilsContract(contractAddresses.devUtils, this.getProvider());
|
||||
this.coordinator = new CoordinatorContract(contractAddresses.coordinator, this.getProvider());
|
||||
this.libTransactionDecoder = new LibTransactionDecoderContract(
|
||||
contractAddresses.libTransactionDecoder,
|
||||
this.getProvider(),
|
||||
);
|
||||
this.contractAddresses = contractAddresses;
|
||||
}
|
||||
/**
|
||||
|
@ -34,6 +34,7 @@ import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class CoordinatorContract extends BaseContract {
|
||||
|
File diff suppressed because one or more lines are too long
@ -55,6 +55,7 @@ export interface ERC20TokenTransferEventArgs extends DecodedLogArgs {
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class ERC20TokenContract extends BaseContract {
|
||||
|
@ -65,6 +65,7 @@ export interface ERC721TokenTransferEventArgs extends DecodedLogArgs {
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class ERC721TokenContract extends BaseContract {
|
||||
|
@ -121,6 +121,7 @@ export interface ExchangeTransactionExecutionEventArgs extends DecodedLogArgs {
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class ExchangeContract extends BaseContract {
|
||||
|
@ -47,6 +47,7 @@ export interface ForwarderOwnershipTransferredEventArgs extends DecodedLogArgs {
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class ForwarderContract extends BaseContract {
|
||||
@ -238,6 +239,34 @@ export class ForwarderContract extends BaseContract {
|
||||
stateMutability: 'payable',
|
||||
type: 'fallback',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'ERC1155_BATCH_RECEIVED',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bytes4',
|
||||
},
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
name: 'ERC1155_RECEIVED',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bytes4',
|
||||
},
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'view',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
@ -456,6 +485,76 @@ export class ForwarderContract extends BaseContract {
|
||||
stateMutability: 'payable',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: false,
|
||||
inputs: [
|
||||
{
|
||||
name: 'operator',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
name: 'from',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
name: 'ids',
|
||||
type: 'uint256[]',
|
||||
},
|
||||
{
|
||||
name: 'values',
|
||||
type: 'uint256[]',
|
||||
},
|
||||
{
|
||||
name: 'data',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
name: 'onERC1155BatchReceived',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bytes4',
|
||||
},
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: false,
|
||||
inputs: [
|
||||
{
|
||||
name: 'operator',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
name: 'from',
|
||||
type: 'address',
|
||||
},
|
||||
{
|
||||
name: 'id',
|
||||
type: 'uint256',
|
||||
},
|
||||
{
|
||||
name: 'value',
|
||||
type: 'uint256',
|
||||
},
|
||||
{
|
||||
name: 'data',
|
||||
type: 'bytes',
|
||||
},
|
||||
],
|
||||
name: 'onERC1155Received',
|
||||
outputs: [
|
||||
{
|
||||
name: '',
|
||||
type: 'bytes4',
|
||||
},
|
||||
],
|
||||
payable: false,
|
||||
stateMutability: 'nonpayable',
|
||||
type: 'function',
|
||||
},
|
||||
{
|
||||
constant: true,
|
||||
inputs: [],
|
||||
@ -581,6 +680,46 @@ export class ForwarderContract extends BaseContract {
|
||||
return abiEncoder.getSelector();
|
||||
}
|
||||
|
||||
public ERC1155_BATCH_RECEIVED(): ContractFunctionObj<string> {
|
||||
const self = (this as any) as ForwarderContract;
|
||||
const functionSignature = 'ERC1155_BATCH_RECEIVED()';
|
||||
|
||||
return {
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
|
||||
BaseContract._assertCallParams(callData, defaultBlock);
|
||||
const rawCallResult = await self._performCallAsync(
|
||||
{ ...callData, data: this.getABIEncodedTransactionData() },
|
||||
defaultBlock,
|
||||
);
|
||||
const abiEncoder = self._lookupAbiEncoder(functionSignature);
|
||||
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
|
||||
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
|
||||
},
|
||||
getABIEncodedTransactionData(): string {
|
||||
return self._strictEncodeArguments(functionSignature, []);
|
||||
},
|
||||
};
|
||||
}
|
||||
public ERC1155_RECEIVED(): ContractFunctionObj<string> {
|
||||
const self = (this as any) as ForwarderContract;
|
||||
const functionSignature = 'ERC1155_RECEIVED()';
|
||||
|
||||
return {
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
|
||||
BaseContract._assertCallParams(callData, defaultBlock);
|
||||
const rawCallResult = await self._performCallAsync(
|
||||
{ ...callData, data: this.getABIEncodedTransactionData() },
|
||||
defaultBlock,
|
||||
);
|
||||
const abiEncoder = self._lookupAbiEncoder(functionSignature);
|
||||
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
|
||||
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
|
||||
},
|
||||
getABIEncodedTransactionData(): string {
|
||||
return self._strictEncodeArguments(functionSignature, []);
|
||||
},
|
||||
};
|
||||
}
|
||||
public EXCHANGE_V2_ORDER_ID(): ContractFunctionObj<string> {
|
||||
const self = (this as any) as ForwarderContract;
|
||||
const functionSignature = 'EXCHANGE_V2_ORDER_ID()';
|
||||
@ -842,6 +981,150 @@ export class ForwarderContract extends BaseContract {
|
||||
},
|
||||
};
|
||||
}
|
||||
/**
|
||||
* The smart contract calls this function on the recipient after a `safeTransferFrom`. This function MAY throw to revert and reject the transfer. Return of other than the magic value MUST result in the transaction being reverted Note: the contract address is always the message sender
|
||||
* @param operator The address which called `safeTransferFrom` function
|
||||
* @param from The address which previously owned the token
|
||||
* @param ids An array containing ids of each token being transferred
|
||||
* @param values An array containing amounts of each token being transferred
|
||||
* @param data Additional data with no specified format
|
||||
* @returns `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
|
||||
*/
|
||||
public onERC1155BatchReceived(
|
||||
operator: string,
|
||||
from: string,
|
||||
ids: BigNumber[],
|
||||
values: BigNumber[],
|
||||
data: string,
|
||||
): ContractTxFunctionObj<string> {
|
||||
const self = (this as any) as ForwarderContract;
|
||||
assert.isString('operator', operator);
|
||||
assert.isString('from', from);
|
||||
assert.isArray('ids', ids);
|
||||
assert.isArray('values', values);
|
||||
assert.isString('data', data);
|
||||
const functionSignature = 'onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)';
|
||||
|
||||
return {
|
||||
async sendTransactionAsync(
|
||||
txData?: Partial<TxData> | undefined,
|
||||
opts: SendTransactionOpts = { shouldValidate: true },
|
||||
): Promise<string> {
|
||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
||||
{ ...txData, data: this.getABIEncodedTransactionData() },
|
||||
this.estimateGasAsync.bind(this),
|
||||
);
|
||||
if (opts.shouldValidate !== false) {
|
||||
await this.callAsync(txDataWithDefaults);
|
||||
}
|
||||
return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
},
|
||||
awaitTransactionSuccessAsync(
|
||||
txData?: Partial<TxData>,
|
||||
opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
|
||||
): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
|
||||
return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
|
||||
},
|
||||
async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
|
||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
|
||||
...txData,
|
||||
data: this.getABIEncodedTransactionData(),
|
||||
});
|
||||
return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||
},
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
|
||||
BaseContract._assertCallParams(callData, defaultBlock);
|
||||
const rawCallResult = await self._performCallAsync(
|
||||
{ ...callData, data: this.getABIEncodedTransactionData() },
|
||||
defaultBlock,
|
||||
);
|
||||
const abiEncoder = self._lookupAbiEncoder(functionSignature);
|
||||
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
|
||||
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
|
||||
},
|
||||
getABIEncodedTransactionData(): string {
|
||||
return self._strictEncodeArguments(functionSignature, [
|
||||
operator.toLowerCase(),
|
||||
from.toLowerCase(),
|
||||
ids,
|
||||
values,
|
||||
data,
|
||||
]);
|
||||
},
|
||||
};
|
||||
}
|
||||
/**
|
||||
* The smart contract calls this function on the recipient after a `safeTransferFrom`. This function MAY throw to revert and reject the transfer. Return of other than the magic value MUST result in the transaction being reverted Note: the contract address is always the message sender
|
||||
* @param operator The address which called `safeTransferFrom` function
|
||||
* @param from The address which previously owned the token
|
||||
* @param id An array containing the ids of the token being transferred
|
||||
* @param value An array containing the amount of tokens being transferred
|
||||
* @param data Additional data with no specified format
|
||||
* @returns `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
|
||||
*/
|
||||
public onERC1155Received(
|
||||
operator: string,
|
||||
from: string,
|
||||
id: BigNumber,
|
||||
value: BigNumber,
|
||||
data: string,
|
||||
): ContractTxFunctionObj<string> {
|
||||
const self = (this as any) as ForwarderContract;
|
||||
assert.isString('operator', operator);
|
||||
assert.isString('from', from);
|
||||
assert.isBigNumber('id', id);
|
||||
assert.isBigNumber('value', value);
|
||||
assert.isString('data', data);
|
||||
const functionSignature = 'onERC1155Received(address,address,uint256,uint256,bytes)';
|
||||
|
||||
return {
|
||||
async sendTransactionAsync(
|
||||
txData?: Partial<TxData> | undefined,
|
||||
opts: SendTransactionOpts = { shouldValidate: true },
|
||||
): Promise<string> {
|
||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
||||
{ ...txData, data: this.getABIEncodedTransactionData() },
|
||||
this.estimateGasAsync.bind(this),
|
||||
);
|
||||
if (opts.shouldValidate !== false) {
|
||||
await this.callAsync(txDataWithDefaults);
|
||||
}
|
||||
return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||
},
|
||||
awaitTransactionSuccessAsync(
|
||||
txData?: Partial<TxData>,
|
||||
opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
|
||||
): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
|
||||
return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
|
||||
},
|
||||
async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
|
||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
|
||||
...txData,
|
||||
data: this.getABIEncodedTransactionData(),
|
||||
});
|
||||
return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||
},
|
||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
|
||||
BaseContract._assertCallParams(callData, defaultBlock);
|
||||
const rawCallResult = await self._performCallAsync(
|
||||
{ ...callData, data: this.getABIEncodedTransactionData() },
|
||||
defaultBlock,
|
||||
);
|
||||
const abiEncoder = self._lookupAbiEncoder(functionSignature);
|
||||
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
|
||||
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
|
||||
},
|
||||
getABIEncodedTransactionData(): string {
|
||||
return self._strictEncodeArguments(functionSignature, [
|
||||
operator.toLowerCase(),
|
||||
from.toLowerCase(),
|
||||
id,
|
||||
value,
|
||||
data,
|
||||
]);
|
||||
},
|
||||
};
|
||||
}
|
||||
public owner(): ContractFunctionObj<string> {
|
||||
const self = (this as any) as ForwarderContract;
|
||||
const functionSignature = 'owner()';
|
||||
|
@ -34,6 +34,7 @@ import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class IAssetDataContract extends BaseContract {
|
||||
|
@ -34,6 +34,7 @@ import * as ethers from 'ethers';
|
||||
// tslint:enable:no-unused-variable
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class IERC20BridgeSamplerContract extends BaseContract {
|
||||
@ -952,7 +953,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
|
||||
* @returns ordersAndSamples How much taker asset can be filled by each order in `orders`. Taker amounts sold for each source at each maker token amount. First indexed by source index, then sample index
|
||||
*/
|
||||
public queryBatchOrdersAndSampleBuys(
|
||||
orders: Array<Array<{
|
||||
orders: Array<{
|
||||
makerAddress: string;
|
||||
takerAddress: string;
|
||||
feeRecipientAddress: string;
|
||||
@ -967,7 +968,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
|
||||
takerAssetData: string;
|
||||
makerFeeAssetData: string;
|
||||
takerFeeAssetData: string;
|
||||
}>>,
|
||||
}>[],
|
||||
orderSignatures: string[][],
|
||||
sources: string[],
|
||||
makerTokenAmounts: BigNumber[][],
|
||||
@ -1017,7 +1018,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
|
||||
* @returns ordersAndSamples How much taker asset can be filled by each order in `orders`. Maker amounts bought for each source at each taker token amount. First indexed by source index, then sample index.
|
||||
*/
|
||||
public queryBatchOrdersAndSampleSells(
|
||||
orders: Array<Array<{
|
||||
orders: Array<{
|
||||
makerAddress: string;
|
||||
takerAddress: string;
|
||||
feeRecipientAddress: string;
|
||||
@ -1032,7 +1033,7 @@ export class IERC20BridgeSamplerContract extends BaseContract {
|
||||
takerAssetData: string;
|
||||
makerFeeAssetData: string;
|
||||
takerFeeAssetData: string;
|
||||
}>>,
|
||||
}>[],
|
||||
orderSignatures: string[][],
|
||||
sources: string[],
|
||||
takerTokenAmounts: BigNumber[][],
|
||||
|
File diff suppressed because one or more lines are too long
@ -166,6 +166,7 @@ export interface StakingUnstakeEventArgs extends DecodedLogArgs {
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class StakingContract extends BaseContract {
|
||||
|
@ -72,6 +72,7 @@ export interface StakingProxyStakingContractAttachedToProxyEventArgs extends Dec
|
||||
export interface StakingProxyStakingContractDetachedFromProxyEventArgs extends DecodedLogArgs {}
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class StakingProxyContract extends BaseContract {
|
||||
|
@ -71,6 +71,7 @@ export interface WETH9WithdrawalEventArgs extends DecodedLogArgs {
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
// tslint:disable:array-type
|
||||
// tslint:disable:no-parameter-reassignment
|
||||
// tslint:disable-next-line:class-name
|
||||
export class WETH9Contract extends BaseContract {
|
||||
|
@ -81,7 +81,6 @@ export {
|
||||
StakingProxyStakingContractAttachedToProxyEventArgs,
|
||||
StakingProxyStakingContractDetachedFromProxyEventArgs,
|
||||
} from './generated-wrappers/staking_proxy';
|
||||
export { LibTransactionDecoderContract } from './generated-wrappers/lib_transaction_decoder';
|
||||
export {
|
||||
BlockRange,
|
||||
SupportedProvider,
|
||||
|
@ -1,4 +1,13 @@
|
||||
[
|
||||
{
|
||||
"version": "3.2.0",
|
||||
"changes": [
|
||||
{
|
||||
"note": "Refactor into public libraries.",
|
||||
"pr": 2464
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"timestamp": 1580988106,
|
||||
"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,
|
||||
"version": "6.0.2",
|
||||
|
@ -63,7 +63,6 @@
|
||||
"dependencies": {
|
||||
"@0x/base-contract": "^6.1.2",
|
||||
"@0x/contract-addresses": "^4.4.0",
|
||||
"@0x/contract-artifacts": "^3.4.1",
|
||||
"@0x/contract-wrappers": "^13.4.2",
|
||||
"@0x/contracts-asset-proxy": "^3.1.3",
|
||||
"@0x/contracts-coordinator": "^3.0.6",
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
|
||||
import * as artifacts from '@0x/contract-artifacts';
|
||||
import { ForwarderContract } from '@0x/contract-wrappers';
|
||||
import {
|
||||
artifacts as assetProxyArtifacts,
|
||||
ERC1155ProxyContract,
|
||||
ERC20BridgeProxyContract,
|
||||
ERC20ProxyContract,
|
||||
@ -9,12 +8,17 @@ import {
|
||||
MultiAssetProxyContract,
|
||||
StaticCallProxyContract,
|
||||
} from '@0x/contracts-asset-proxy';
|
||||
import { CoordinatorContract, CoordinatorRegistryContract } from '@0x/contracts-coordinator';
|
||||
import { DevUtilsContract, LibTransactionDecoderContract } from '@0x/contracts-dev-utils';
|
||||
import { ERC1155MintableContract } from '@0x/contracts-erc1155';
|
||||
import { DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20';
|
||||
import { DummyERC721TokenContract } from '@0x/contracts-erc721';
|
||||
import { ExchangeContract } from '@0x/contracts-exchange';
|
||||
import {
|
||||
artifacts as coordinatorArtifacts,
|
||||
CoordinatorContract,
|
||||
CoordinatorRegistryContract,
|
||||
} from '@0x/contracts-coordinator';
|
||||
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 {
|
||||
artifacts as stakingArtifacts,
|
||||
StakingProxyContract,
|
||||
@ -28,6 +32,18 @@ import { SupportedProvider, TxData } from 'ethereum-types';
|
||||
import { constants } from './utils/constants';
|
||||
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
|
||||
* version of the 0x protocol.
|
||||
@ -44,24 +60,24 @@ export async function runMigrationsAsync(
|
||||
|
||||
// Proxies
|
||||
const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync(
|
||||
artifacts.ERC20Proxy,
|
||||
assetProxyArtifacts.ERC20Proxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
);
|
||||
const erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync(
|
||||
artifacts.ERC721Proxy,
|
||||
assetProxyArtifacts.ERC721Proxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
);
|
||||
|
||||
// ZRX
|
||||
const zrxToken = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
|
||||
artifacts.DummyERC20Token,
|
||||
erc20Artifacts.DummyERC20Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
'0x Protocol Token',
|
||||
'ZRX',
|
||||
new BigNumber(18),
|
||||
@ -69,14 +85,19 @@ export async function runMigrationsAsync(
|
||||
);
|
||||
|
||||
// Ether token
|
||||
const etherToken = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.WETH9, provider, txDefaults, artifacts);
|
||||
const etherToken = await WETH9Contract.deployFrom0xArtifactAsync(
|
||||
erc20Artifacts.WETH9,
|
||||
provider,
|
||||
txDefaults,
|
||||
allArtifacts,
|
||||
);
|
||||
|
||||
// Exchange
|
||||
const exchange = await ExchangeContract.deployFrom0xArtifactAsync(
|
||||
artifacts.Exchange,
|
||||
exchangeArtifacts.Exchange,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
chainId,
|
||||
);
|
||||
|
||||
@ -85,10 +106,10 @@ export async function runMigrationsAsync(
|
||||
const totalSupply = new BigNumber(1000000000000000000000000000);
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
const dummyErc20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
|
||||
artifacts.DummyERC20Token,
|
||||
erc20Artifacts.DummyERC20Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
token.name,
|
||||
token.symbol,
|
||||
token.decimals,
|
||||
@ -99,34 +120,34 @@ export async function runMigrationsAsync(
|
||||
// ERC721
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
const cryptoKittieToken = await DummyERC721TokenContract.deployFrom0xArtifactAsync(
|
||||
artifacts.DummyERC721Token,
|
||||
erc721Artifacts.DummyERC721Token,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
erc721TokenInfo[0].name,
|
||||
erc721TokenInfo[0].symbol,
|
||||
);
|
||||
|
||||
// 1155 Asset Proxy
|
||||
const erc1155Proxy = await ERC1155ProxyContract.deployFrom0xArtifactAsync(
|
||||
artifacts.ERC1155Proxy,
|
||||
assetProxyArtifacts.ERC1155Proxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
);
|
||||
|
||||
const staticCallProxy = await StaticCallProxyContract.deployFrom0xArtifactAsync(
|
||||
artifacts.StaticCallProxy,
|
||||
assetProxyArtifacts.StaticCallProxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
);
|
||||
|
||||
const multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync(
|
||||
artifacts.MultiAssetProxy,
|
||||
assetProxyArtifacts.MultiAssetProxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
);
|
||||
|
||||
await erc20Proxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults);
|
||||
@ -152,45 +173,46 @@ export async function runMigrationsAsync(
|
||||
|
||||
// CoordinatorRegistry
|
||||
const coordinatorRegistry = await CoordinatorRegistryContract.deployFrom0xArtifactAsync(
|
||||
artifacts.CoordinatorRegistry,
|
||||
coordinatorArtifacts.CoordinatorRegistry,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
);
|
||||
|
||||
// Coordinator
|
||||
const coordinator = await CoordinatorContract.deployFrom0xArtifactAsync(
|
||||
artifacts.Coordinator,
|
||||
coordinatorArtifacts.Coordinator,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
exchange.address,
|
||||
chainId,
|
||||
);
|
||||
|
||||
// Dev Utils
|
||||
const devUtils = await DevUtilsContract.deployFrom0xArtifactAsync(
|
||||
artifacts.DevUtils,
|
||||
const devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||
devUtilsArtifacts.DevUtils,
|
||||
devUtilsArtifacts,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
exchange.address,
|
||||
constants.NULL_ADDRESS,
|
||||
);
|
||||
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
const erc1155DummyToken = await ERC1155MintableContract.deployFrom0xArtifactAsync(
|
||||
artifacts.ERC1155Mintable,
|
||||
erc1155Artifacts.ERC1155Mintable,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
);
|
||||
|
||||
const erc20BridgeProxy = await ERC20BridgeProxyContract.deployFrom0xArtifactAsync(
|
||||
artifacts.ERC20BridgeProxy,
|
||||
assetProxyArtifacts.ERC20BridgeProxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
{},
|
||||
allArtifacts,
|
||||
);
|
||||
await exchange.registerAssetProxy(erc20BridgeProxy.address).awaitTransactionSuccessAsync(txDefaults);
|
||||
await erc20BridgeProxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults);
|
||||
@ -199,10 +221,10 @@ export async function runMigrationsAsync(
|
||||
|
||||
const zrxProxy = erc20Proxy.address;
|
||||
const zrxVault = await ZrxVaultContract.deployFrom0xArtifactAsync(
|
||||
artifacts.ZrxVault,
|
||||
stakingArtifacts.ZrxVault,
|
||||
provider,
|
||||
txDefaults,
|
||||
{},
|
||||
allArtifacts,
|
||||
zrxProxy,
|
||||
zrxToken.address,
|
||||
);
|
||||
@ -213,16 +235,16 @@ export async function runMigrationsAsync(
|
||||
stakingArtifacts.TestStaking,
|
||||
provider,
|
||||
txDefaults,
|
||||
{},
|
||||
allArtifacts,
|
||||
etherToken.address,
|
||||
zrxVault.address,
|
||||
);
|
||||
|
||||
const stakingProxy = await StakingProxyContract.deployFrom0xArtifactAsync(
|
||||
artifacts.StakingProxy,
|
||||
stakingArtifacts.StakingProxy,
|
||||
provider,
|
||||
txDefaults,
|
||||
{},
|
||||
allArtifacts,
|
||||
stakingLogic.address,
|
||||
);
|
||||
|
||||
@ -245,23 +267,15 @@ export async function runMigrationsAsync(
|
||||
// in the constructor
|
||||
const { exchangeV2: exchangeV2Address } = getContractAddressesForChainOrThrow(chainId.toNumber());
|
||||
const forwarder = await ForwarderContract.deployFrom0xArtifactAsync(
|
||||
artifacts.Forwarder,
|
||||
forwarderArtifacts.Forwarder,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
allArtifacts,
|
||||
exchange.address,
|
||||
exchangeV2Address || constants.NULL_ADDRESS,
|
||||
etherToken.address,
|
||||
);
|
||||
|
||||
// LibTransactionDecoder
|
||||
const libTransactionDecoder = await LibTransactionDecoderContract.deployFrom0xArtifactAsync(
|
||||
artifacts.LibTransactionDecoder,
|
||||
provider,
|
||||
txDefaults,
|
||||
artifacts,
|
||||
);
|
||||
|
||||
const contractAddresses = {
|
||||
erc20Proxy: erc20Proxy.address,
|
||||
erc721Proxy: erc721Proxy.address,
|
||||
@ -273,7 +287,6 @@ export async function runMigrationsAsync(
|
||||
erc20BridgeProxy: erc20BridgeProxy.address,
|
||||
zeroExGovernor: constants.NULL_ADDRESS,
|
||||
forwarder: forwarder.address,
|
||||
libTransactionDecoder: libTransactionDecoder.address,
|
||||
orderValidator: constants.NULL_ADDRESS,
|
||||
dutchAuction: constants.NULL_ADDRESS,
|
||||
coordinatorRegistry: coordinatorRegistry.address,
|
||||
|
@ -9,11 +9,7 @@ import {
|
||||
UniswapBridgeContract,
|
||||
} from '@0x/contracts-asset-proxy';
|
||||
import { artifacts as coordinatorArtifacts, CoordinatorContract } from '@0x/contracts-coordinator';
|
||||
import {
|
||||
artifacts as devUtilsArtifacts,
|
||||
DevUtilsContract,
|
||||
LibTransactionDecoderContract,
|
||||
} from '@0x/contracts-dev-utils';
|
||||
import { artifacts as devUtilsArtifacts, DevUtilsContract } from '@0x/contracts-dev-utils';
|
||||
import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange';
|
||||
import { artifacts as forwarderArtifacts, ForwarderContract } from '@0x/contracts-exchange-forwarder';
|
||||
import {
|
||||
@ -249,8 +245,9 @@ export async function runMigrationsAsync(supportedProvider: SupportedProvider, t
|
||||
]);
|
||||
await submitAndExecuteTransactionAsync(governor, governor.address, batchTransactionData);
|
||||
|
||||
await DevUtilsContract.deployFrom0xArtifactAsync(
|
||||
await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync(
|
||||
devUtilsArtifacts.DevUtils,
|
||||
devUtilsArtifacts,
|
||||
provider,
|
||||
txDefaults,
|
||||
devUtilsArtifacts,
|
||||
@ -276,13 +273,6 @@ export async function runMigrationsAsync(supportedProvider: SupportedProvider, t
|
||||
deployedAddresses.exchangeV2,
|
||||
deployedAddresses.etherToken,
|
||||
);
|
||||
|
||||
await LibTransactionDecoderContract.deployFrom0xArtifactAsync(
|
||||
devUtilsArtifacts.LibTransactionDecoder,
|
||||
provider,
|
||||
txDefaults,
|
||||
devUtilsArtifacts,
|
||||
);
|
||||
}
|
||||
|
||||
(async () => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user