Add ChaiBridge balance checks to DevUtils
This commit is contained in:
parent
969b9814d5
commit
410a3fef18
@ -30,4 +30,11 @@ contract IChai {
|
|||||||
uint256 wad
|
uint256 wad
|
||||||
)
|
)
|
||||||
external;
|
external;
|
||||||
|
|
||||||
|
/// @dev Queries Dai balance of Chai holder.
|
||||||
|
/// @param usr Address of Chai holder.
|
||||||
|
/// @return Dai balance.
|
||||||
|
function dai(address usr)
|
||||||
|
external
|
||||||
|
returns (uint256);
|
||||||
}
|
}
|
||||||
|
@ -37,9 +37,15 @@ contract DevUtils is
|
|||||||
LibEIP712ExchangeDomain,
|
LibEIP712ExchangeDomain,
|
||||||
EthBalanceChecker
|
EthBalanceChecker
|
||||||
{
|
{
|
||||||
constructor (address _exchange)
|
constructor (
|
||||||
|
address _exchange,
|
||||||
|
address _chaiBridge
|
||||||
|
)
|
||||||
public
|
public
|
||||||
OrderValidationUtils(_exchange)
|
OrderValidationUtils(
|
||||||
|
_exchange,
|
||||||
|
_chaiBridge
|
||||||
|
)
|
||||||
OrderTransferSimulationUtils(_exchange)
|
OrderTransferSimulationUtils(_exchange)
|
||||||
LibEIP712ExchangeDomain(uint256(0), address(0)) // null args because because we only use constants
|
LibEIP712ExchangeDomain(uint256(0), address(0)) // null args because because we only use constants
|
||||||
{}
|
{}
|
||||||
|
@ -26,9 +26,13 @@ import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol";
|
|||||||
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||||
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
|
import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol";
|
||||||
import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.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";
|
||||||
|
|
||||||
|
|
||||||
contract LibAssetData {
|
contract LibAssetData is
|
||||||
|
DeploymentConstants
|
||||||
|
{
|
||||||
|
|
||||||
// 2^256 - 1
|
// 2^256 - 1
|
||||||
uint256 constant internal _MAX_UINT256 = uint256(-1);
|
uint256 constant internal _MAX_UINT256 = uint256(-1);
|
||||||
@ -41,9 +45,13 @@ contract LibAssetData {
|
|||||||
address internal _ERC721_PROXY_ADDRESS;
|
address internal _ERC721_PROXY_ADDRESS;
|
||||||
address internal _ERC1155_PROXY_ADDRESS;
|
address internal _ERC1155_PROXY_ADDRESS;
|
||||||
address internal _STATIC_CALL_PROXY_ADDRESS;
|
address internal _STATIC_CALL_PROXY_ADDRESS;
|
||||||
|
address internal _CHAI_BRIDGE_ADDRESS;
|
||||||
// solhint-enable var-name-mixedcase
|
// solhint-enable var-name-mixedcase
|
||||||
|
|
||||||
constructor (address _exchange)
|
constructor (
|
||||||
|
address _exchange,
|
||||||
|
address _chaiBridge
|
||||||
|
)
|
||||||
public
|
public
|
||||||
{
|
{
|
||||||
_EXCHANGE = IExchange(_exchange);
|
_EXCHANGE = IExchange(_exchange);
|
||||||
@ -51,6 +59,7 @@ contract LibAssetData {
|
|||||||
_ERC721_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC721Token.selector);
|
_ERC721_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC721Token.selector);
|
||||||
_ERC1155_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC1155Assets.selector);
|
_ERC1155_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC1155Assets.selector);
|
||||||
_STATIC_CALL_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).StaticCall.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
|
/// @dev Returns the owner's balance of the assets(s) specified in
|
||||||
@ -62,7 +71,6 @@ contract LibAssetData {
|
|||||||
/// @return Number of assets (or asset baskets) held by owner.
|
/// @return Number of assets (or asset baskets) held by owner.
|
||||||
function getBalance(address ownerAddress, bytes memory assetData)
|
function getBalance(address ownerAddress, bytes memory assetData)
|
||||||
public
|
public
|
||||||
view
|
|
||||||
returns (uint256 balance)
|
returns (uint256 balance)
|
||||||
{
|
{
|
||||||
// Get id of AssetProxy contract
|
// Get id of AssetProxy contract
|
||||||
@ -140,6 +148,19 @@ contract LibAssetData {
|
|||||||
|
|
||||||
// Success means that the staticcall can be made an unlimited amount of times
|
// Success means that the staticcall can be made an unlimited amount of times
|
||||||
balance = success ? _MAX_UINT256 : 0;
|
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) {
|
||||||
|
bytes memory chaiDaiCalldata = abi.encodeWithSelector(
|
||||||
|
IChai(address(0)).dai.selector,
|
||||||
|
ownerAddress
|
||||||
|
);
|
||||||
|
// We do not make a STATICCALL because this function can potentially alter state
|
||||||
|
(bool success, bytes memory returnData) = _getChaiAddress().call(chaiDaiCalldata);
|
||||||
|
uint256 chaiBalance = success && returnData.length == 32 ? returnData.readUint256(0) : 0;
|
||||||
|
}
|
||||||
|
// Balance will be 0 if bridge is not supported
|
||||||
} else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
|
} else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) {
|
||||||
// Get array of values and array of assetDatas
|
// Get array of values and array of assetDatas
|
||||||
(, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
|
(, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData);
|
||||||
@ -176,7 +197,6 @@ contract LibAssetData {
|
|||||||
/// corresponding to the same-indexed element in the assetData input.
|
/// corresponding to the same-indexed element in the assetData input.
|
||||||
function getBatchBalances(address ownerAddress, bytes[] memory assetData)
|
function getBatchBalances(address ownerAddress, bytes[] memory assetData)
|
||||||
public
|
public
|
||||||
view
|
|
||||||
returns (uint256[] memory balances)
|
returns (uint256[] memory balances)
|
||||||
{
|
{
|
||||||
uint256 length = assetData.length;
|
uint256 length = assetData.length;
|
||||||
@ -316,7 +336,6 @@ contract LibAssetData {
|
|||||||
/// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
|
/// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend.
|
||||||
function getBalanceAndAssetProxyAllowance(address ownerAddress, bytes memory assetData)
|
function getBalanceAndAssetProxyAllowance(address ownerAddress, bytes memory assetData)
|
||||||
public
|
public
|
||||||
view
|
|
||||||
returns (uint256 balance, uint256 allowance)
|
returns (uint256 balance, uint256 allowance)
|
||||||
{
|
{
|
||||||
balance = getBalance(ownerAddress, assetData);
|
balance = getBalance(ownerAddress, assetData);
|
||||||
@ -332,7 +351,6 @@ contract LibAssetData {
|
|||||||
/// corresponding to the same-indexed element in the assetData input.
|
/// corresponding to the same-indexed element in the assetData input.
|
||||||
function getBatchBalancesAndAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
|
function getBatchBalancesAndAssetProxyAllowances(address ownerAddress, bytes[] memory assetData)
|
||||||
public
|
public
|
||||||
view
|
|
||||||
returns (uint256[] memory balances, uint256[] memory allowances)
|
returns (uint256[] memory balances, uint256[] memory allowances)
|
||||||
{
|
{
|
||||||
balances = getBatchBalances(ownerAddress, assetData);
|
balances = getBatchBalances(ownerAddress, assetData);
|
||||||
@ -613,6 +631,33 @@ contract LibAssetData {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @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
|
||||||
|
)
|
||||||
|
{
|
||||||
|
assetProxyId = assetData.readBytes4(0);
|
||||||
|
|
||||||
|
require(
|
||||||
|
assetProxyId == IAssetData(address(0)).ERC20Bridge.selector,
|
||||||
|
"WRONG_PROXY_ID"
|
||||||
|
);
|
||||||
|
|
||||||
|
(tokenAddress, bridgeAddress, bridgeData) = abi.decode(
|
||||||
|
assetData.slice(4, assetData.length),
|
||||||
|
(address, address, bytes)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function revertIfInvalidAssetData(bytes memory assetData)
|
function revertIfInvalidAssetData(bytes memory assetData)
|
||||||
public
|
public
|
||||||
pure
|
pure
|
||||||
@ -629,6 +674,8 @@ contract LibAssetData {
|
|||||||
decodeMultiAssetData(assetData);
|
decodeMultiAssetData(assetData);
|
||||||
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
|
} else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) {
|
||||||
decodeStaticCallAssetData(assetData);
|
decodeStaticCallAssetData(assetData);
|
||||||
|
} else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) {
|
||||||
|
decodeERC20BridgeAssetData(assetData);
|
||||||
} else {
|
} else {
|
||||||
revert("WRONG_PROXY_ID");
|
revert("WRONG_PROXY_ID");
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,15 @@ contract OrderValidationUtils is
|
|||||||
using LibBytes for bytes;
|
using LibBytes for bytes;
|
||||||
using LibSafeMath for uint256;
|
using LibSafeMath for uint256;
|
||||||
|
|
||||||
constructor (address _exchange)
|
constructor (
|
||||||
|
address _exchange,
|
||||||
|
address _chaiBridge
|
||||||
|
)
|
||||||
public
|
public
|
||||||
LibAssetData(_exchange)
|
LibAssetData(
|
||||||
|
_exchange,
|
||||||
|
_chaiBridge
|
||||||
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/// @dev Fetches all order-relevant information needed to validate if the supplied order is fillable.
|
/// @dev Fetches all order-relevant information needed to validate if the supplied order is fillable.
|
||||||
@ -173,7 +179,6 @@ contract OrderValidationUtils is
|
|||||||
/// the individual asset amounts located within the `assetData`.
|
/// the individual asset amounts located within the `assetData`.
|
||||||
function getTransferableAssetAmount(address ownerAddress, bytes memory assetData)
|
function getTransferableAssetAmount(address ownerAddress, bytes memory assetData)
|
||||||
public
|
public
|
||||||
view
|
|
||||||
returns (uint256 transferableAssetAmount)
|
returns (uint256 transferableAssetAmount)
|
||||||
{
|
{
|
||||||
(uint256 balance, uint256 allowance) = getBalanceAndAssetProxyAllowance(ownerAddress, assetData);
|
(uint256 balance, uint256 allowance) = getBalanceAndAssetProxyAllowance(ownerAddress, assetData);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user