Updating bridge to work w/o MultiAssetProxy
This commit is contained in:
		@@ -21,6 +21,7 @@ pragma experimental ABIEncoderV2;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
					import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
 | 
				
			||||||
import "@0x/contracts-utils/contracts/src/Authorizable.sol";
 | 
					import "@0x/contracts-utils/contracts/src/Authorizable.sol";
 | 
				
			||||||
 | 
					import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
 | 
				
			||||||
import "../interfaces/IERC20Bridge.sol";
 | 
					import "../interfaces/IERC20Bridge.sol";
 | 
				
			||||||
import "../interfaces/IDydxBridge.sol";
 | 
					import "../interfaces/IDydxBridge.sol";
 | 
				
			||||||
import "../interfaces/IDydx.sol";
 | 
					import "../interfaces/IDydx.sol";
 | 
				
			||||||
@@ -33,15 +34,15 @@ contract DydxBridge is
 | 
				
			|||||||
    Authorizable
 | 
					    Authorizable
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using LibSafeMath for uint256;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// @dev Callback for `IERC20Bridge`. Deposits or withdraws tokens from a dydx account.
 | 
					    /// @dev Callback for `IERC20Bridge`. Deposits or withdraws tokens from a dydx account.
 | 
				
			||||||
    ///      Notes:
 | 
					    ///      Notes:
 | 
				
			||||||
    ///         1. This bridge must be set as an operator of the dydx account that is being operated on.
 | 
					    ///         1. This bridge must be set as an operator of the dydx account that is being operated on.
 | 
				
			||||||
    ///         2. This function may only be called in the context of the 0x Exchange executing an order
 | 
					    ///         2. This function may only be called in the context of the 0x Exchange executing an order
 | 
				
			||||||
    ///            (ERC20Bridge is authorized).
 | 
					    ///            (ERC20Bridge is authorized).
 | 
				
			||||||
    ///         3. The order must be signed by the owner or an operator of the dydx account.
 | 
					    ///         3. The `from` address must be the maker and owner of the dydx account.
 | 
				
			||||||
    ///            This signature validated by the 0x Exchange.
 | 
					    ///            This signature is validated by the 0x Exchange.
 | 
				
			||||||
    ///         4. The `from` address must be the maker (and hence is the owner or operator of the dydx account).
 | 
					 | 
				
			||||||
    ///            This is asserted during execution of this function.
 | 
					 | 
				
			||||||
    /// @param from The sender of the tokens.
 | 
					    /// @param from The sender of the tokens.
 | 
				
			||||||
    /// @param to The recipient of the tokens.
 | 
					    /// @param to The recipient of the tokens.
 | 
				
			||||||
    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
					    /// @param amount Minimum amount of `toTokenAddress` tokens to buy.
 | 
				
			||||||
@@ -58,48 +59,62 @@ contract DydxBridge is
 | 
				
			|||||||
        onlyAuthorized
 | 
					        onlyAuthorized
 | 
				
			||||||
        returns (bytes4 success)
 | 
					        returns (bytes4 success)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        // Ensure that only the `ERC20BridgeProxy` can call this function.
 | 
				
			||||||
 | 
					        require(
 | 
				
			||||||
 | 
					            msg.sender == _getERC20BridgeProxyAddress(),
 | 
				
			||||||
 | 
					            "DydxBridge/ONLY_CALLABLE_BY_ERC20_BRIDGE_PROXY"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Decode bridge data.
 | 
					        // Decode bridge data.
 | 
				
			||||||
        (BridgeData memory bridgeData) = abi.decode(encodedBridgeData, (BridgeData));
 | 
					        (BridgeData memory bridgeData) = abi.decode(encodedBridgeData, (BridgeData));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Cache dydx contract.
 | 
					        // Cache dydx contract.
 | 
				
			||||||
        IDydx dydx = IDydx(_getDydxAddress());
 | 
					        IDydx dydx = IDydx(_getDydxAddress());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Assert that `from` is the owner or an operator of the dydx account.
 | 
					 | 
				
			||||||
        require(
 | 
					 | 
				
			||||||
            from == bridgeData.accountOwner || dydx.getIsLocalOperator(bridgeData.accountOwner, from),
 | 
					 | 
				
			||||||
            "INVALID_DYDX_OWNER_OR_OPERATOR"
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Construct dydx account info.
 | 
					        // Construct dydx account info.
 | 
				
			||||||
        IDydx.AccountInfo[] memory accounts = new IDydx.AccountInfo[](1);
 | 
					        IDydx.AccountInfo[] memory dydxAccounts = new IDydx.AccountInfo[](1);
 | 
				
			||||||
        accounts[0] = IDydx.AccountInfo({
 | 
					        dydxAccounts[0] = IDydx.AccountInfo({
 | 
				
			||||||
            owner: bridgeData.accountOwner,
 | 
					            owner: from,
 | 
				
			||||||
            number: bridgeData.accountNumber
 | 
					            number: bridgeData.accountNumber
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Create dydx action.
 | 
					        // Create dydx action.
 | 
				
			||||||
        IDydx.ActionArgs[] memory actions = new IDydx.ActionArgs[](1);
 | 
					        IDydx.ActionArgs[] memory dydxActions = new IDydx.ActionArgs[](bridgeData.actions.length);
 | 
				
			||||||
        if (bridgeData.action == BridgeAction.Deposit) {
 | 
					        for (uint256 i = 0; i < dydxActions.length; ++i) {
 | 
				
			||||||
            actions[0] = _createDepositAction(
 | 
					            BridgeAction bridgeAction = bridgeData.actions[i];
 | 
				
			||||||
                from,
 | 
					            if (bridgeAction == BridgeAction.Deposit) {
 | 
				
			||||||
                amount,
 | 
					                // Compute the amount to deposit. The `amount` parameter is the amount to be withdrawn.
 | 
				
			||||||
                bridgeData
 | 
					                // It is computed by the Exchange as:
 | 
				
			||||||
            );
 | 
					                //  amount = floor[(takerFillAmount * makerAssetAmount) / takerAssetAmount]
 | 
				
			||||||
        } else if (bridgeData.action == BridgeAction.Withdraw) {
 | 
					                // The amount to deposit is equal to to `takerFillAmount`, which we compute below as:
 | 
				
			||||||
            actions[0] = _createWithdrawAction(
 | 
					                //  takerFillAmount ~= floor[(amount * takerAssetAmount) / makerAssetAmount]
 | 
				
			||||||
                to,
 | 
					                //                   = floor[(amount * conversionRateNumerator) / conversionRateDenominator]
 | 
				
			||||||
                amount,
 | 
					                // Note that we can only approximate the original value of `takerFillAmount`. If we were to use
 | 
				
			||||||
                bridgeData
 | 
					                // `ceil` then we would risk overestimating the value.
 | 
				
			||||||
            );
 | 
					                uint256 amountToDeposit = amount
 | 
				
			||||||
        } else {
 | 
					                    .mul(bridgeData.conversionRateNumerator)
 | 
				
			||||||
            // If all values in the `Action` enum are handled then this
 | 
					                    .div(bridgeData.conversionRateDenominator);
 | 
				
			||||||
            // revert is unreachable: Solidity will revert when casting
 | 
					                dydxActions[i] = _createDepositAction(
 | 
				
			||||||
            // from `uint8` to `Action`.
 | 
					                    from,
 | 
				
			||||||
            revert("UNRECOGNIZED_ACTION");
 | 
					                    amount,
 | 
				
			||||||
 | 
					                    bridgeData
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            } else if (bridgeAction == BridgeAction.Withdraw) {
 | 
				
			||||||
 | 
					                dydxActions[i] = _createWithdrawAction(
 | 
				
			||||||
 | 
					                    to,
 | 
				
			||||||
 | 
					                    amount,
 | 
				
			||||||
 | 
					                    bridgeData
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                // If all values in the `Action` enum are handled then this
 | 
				
			||||||
 | 
					                // revert is unreachable: Solidity will revert when casting
 | 
				
			||||||
 | 
					                // from `uint8` to `Action`.
 | 
				
			||||||
 | 
					                revert("DydxBridge/UNRECOGNIZED_BRIDGE_ACTION");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Run operation. This will revert on failure.
 | 
					        // Run operation. This will revert on failure.
 | 
				
			||||||
        dydx.operate(accounts, actions);
 | 
					        dydx.operate(dydxAccounts, dydxActions);
 | 
				
			||||||
        return BRIDGE_SUCCESS;
 | 
					        return BRIDGE_SUCCESS;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -117,7 +132,7 @@ contract DydxBridge is
 | 
				
			|||||||
        returns (IDydx.ActionArgs memory)
 | 
					        returns (IDydx.ActionArgs memory)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Create dydx amount.
 | 
					        // Create dydx amount.
 | 
				
			||||||
        IDydx.AssetAmount memory amountToDeposit = IDydx.AssetAmount({
 | 
					        IDydx.AssetAmount memory dydxAmount = IDydx.AssetAmount({
 | 
				
			||||||
            sign: true,                                 // true if positive.
 | 
					            sign: true,                                 // true if positive.
 | 
				
			||||||
            denomination: IDydx.AssetDenomination.Wei,  // Wei => actual token amount held in account.
 | 
					            denomination: IDydx.AssetDenomination.Wei,  // Wei => actual token amount held in account.
 | 
				
			||||||
            ref: IDydx.AssetReference.Target,           // Target => an absolute amount.
 | 
					            ref: IDydx.AssetReference.Target,           // Target => an absolute amount.
 | 
				
			||||||
@@ -127,7 +142,7 @@ contract DydxBridge is
 | 
				
			|||||||
        // Create dydx deposit action.
 | 
					        // Create dydx deposit action.
 | 
				
			||||||
        IDydx.ActionArgs memory depositAction = IDydx.ActionArgs({
 | 
					        IDydx.ActionArgs memory depositAction = IDydx.ActionArgs({
 | 
				
			||||||
            actionType: IDydx.ActionType.Deposit,           // deposit tokens.
 | 
					            actionType: IDydx.ActionType.Deposit,           // deposit tokens.
 | 
				
			||||||
            amount: amountToDeposit,                        // amount to deposit.
 | 
					            amount: dydxAmount,                             // amount to deposit.
 | 
				
			||||||
            accountId: 0,                                   // index in the `accounts` when calling `operate`.
 | 
					            accountId: 0,                                   // index in the `accounts` when calling `operate`.
 | 
				
			||||||
            primaryMarketId: bridgeData.marketId,           // indicates which token to deposit.
 | 
					            primaryMarketId: bridgeData.marketId,           // indicates which token to deposit.
 | 
				
			||||||
            otherAddress: depositFrom,                      // deposit from this address.
 | 
					            otherAddress: depositFrom,                      // deposit from this address.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,9 +27,10 @@ interface IDydxBridge {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct BridgeData {
 | 
					    struct BridgeData {
 | 
				
			||||||
        BridgeAction action;        // Action to run on dydx account.
 | 
					        BridgeAction[] actions;                 // Action to run on dydx account.
 | 
				
			||||||
        address accountOwner;       // The owner of the dydx account.
 | 
					        uint256 accountNumber;                  // Account number used to identify the owner's specific account.
 | 
				
			||||||
        uint256 accountNumber;      // Account number used to identify the owner's specific account.
 | 
					        uint256 marketId;                       // Market to operate on.
 | 
				
			||||||
        uint256 marketId;           // Market to operate on.
 | 
					        uint256 conversionRateNumerator;        //
 | 
				
			||||||
 | 
					        uint256 conversionRateDenominator;      //
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -43,8 +43,12 @@
 | 
				
			|||||||
        "abis": "./test/generated-artifacts/@(ChaiBridge|DyDxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IChai|IDyDx|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestChaiBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
 | 
					        "abis": "./test/generated-artifacts/@(ChaiBridge|DyDxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IChai|IDyDx|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestChaiBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
 | 
				
			||||||
=======
 | 
					=======
 | 
				
			||||||
        "publicInterfaceContracts": "ERC1155Proxy,ERC20Proxy,ERC721Proxy,MultiAssetProxy,StaticCallProxy,ERC20BridgeProxy,Eth2DaiBridge,IAssetData,IAssetProxy,UniswapBridge,KyberBridge,TestStaticCallTarget",
 | 
					        "publicInterfaceContracts": "ERC1155Proxy,ERC20Proxy,ERC721Proxy,MultiAssetProxy,StaticCallProxy,ERC20BridgeProxy,Eth2DaiBridge,IAssetData,IAssetProxy,UniswapBridge,KyberBridge,TestStaticCallTarget",
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
        "abis": "./test/generated-artifacts/@(DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IDydx|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
 | 
					        "abis": "./test/generated-artifacts/@(DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IDydx|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
 | 
				
			||||||
>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					        "abis": "./test/generated-artifacts/@(DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MultiAssetProxy|Ownable|StaticCallProxy|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|UniswapBridge).json",
 | 
				
			||||||
 | 
					>>>>>>> 5e2de489d... Updating bridge to work w/o MAP
 | 
				
			||||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
					        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "repository": {
 | 
					    "repository": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,7 +25,11 @@ import * as IChai from '../test/generated-artifacts/IChai.json';
 | 
				
			|||||||
import * as IDyDx from '../test/generated-artifacts/IDyDx.json';
 | 
					import * as IDyDx from '../test/generated-artifacts/IDyDx.json';
 | 
				
			||||||
=======
 | 
					=======
 | 
				
			||||||
import * as IDydx from '../test/generated-artifacts/IDydx.json';
 | 
					import * as IDydx from '../test/generated-artifacts/IDydx.json';
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					import * as IDydxBridge from '../test/generated-artifacts/IDydxBridge.json';
 | 
				
			||||||
 | 
					>>>>>>> 5e2de489d... Updating bridge to work w/o MAP
 | 
				
			||||||
import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json';
 | 
					import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json';
 | 
				
			||||||
import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
 | 
					import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json';
 | 
				
			||||||
import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json';
 | 
					import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json';
 | 
				
			||||||
@@ -72,7 +76,11 @@ export const artifacts = {
 | 
				
			|||||||
    IDyDx: IDyDx as ContractArtifact,
 | 
					    IDyDx: IDyDx as ContractArtifact,
 | 
				
			||||||
=======
 | 
					=======
 | 
				
			||||||
    IDydx: IDydx as ContractArtifact,
 | 
					    IDydx: IDydx as ContractArtifact,
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					    IDydxBridge: IDydxBridge as ContractArtifact,
 | 
				
			||||||
 | 
					>>>>>>> 5e2de489d... Updating bridge to work w/o MAP
 | 
				
			||||||
    IERC20Bridge: IERC20Bridge as ContractArtifact,
 | 
					    IERC20Bridge: IERC20Bridge as ContractArtifact,
 | 
				
			||||||
    IEth2Dai: IEth2Dai as ContractArtifact,
 | 
					    IEth2Dai: IEth2Dai as ContractArtifact,
 | 
				
			||||||
    IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
 | 
					    IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,11 @@ export * from '../test/generated-wrappers/i_chai';
 | 
				
			|||||||
export * from '../test/generated-wrappers/i_dy_dx';
 | 
					export * from '../test/generated-wrappers/i_dy_dx';
 | 
				
			||||||
=======
 | 
					=======
 | 
				
			||||||
export * from '../test/generated-wrappers/i_dydx';
 | 
					export * from '../test/generated-wrappers/i_dydx';
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					export * from '../test/generated-wrappers/i_dydx_bridge';
 | 
				
			||||||
 | 
					>>>>>>> 5e2de489d... Updating bridge to work w/o MAP
 | 
				
			||||||
export * from '../test/generated-wrappers/i_erc20_bridge';
 | 
					export * from '../test/generated-wrappers/i_erc20_bridge';
 | 
				
			||||||
export * from '../test/generated-wrappers/i_eth2_dai';
 | 
					export * from '../test/generated-wrappers/i_eth2_dai';
 | 
				
			||||||
export * from '../test/generated-wrappers/i_kyber_network_proxy';
 | 
					export * from '../test/generated-wrappers/i_kyber_network_proxy';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,7 +36,11 @@
 | 
				
			|||||||
        "test/generated-artifacts/IDyDx.json",
 | 
					        "test/generated-artifacts/IDyDx.json",
 | 
				
			||||||
=======
 | 
					=======
 | 
				
			||||||
        "test/generated-artifacts/IDydx.json",
 | 
					        "test/generated-artifacts/IDydx.json",
 | 
				
			||||||
 | 
					<<<<<<< HEAD
 | 
				
			||||||
>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
					>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					        "test/generated-artifacts/IDydxBridge.json",
 | 
				
			||||||
 | 
					>>>>>>> 5e2de489d... Updating bridge to work w/o MAP
 | 
				
			||||||
        "test/generated-artifacts/IERC20Bridge.json",
 | 
					        "test/generated-artifacts/IERC20Bridge.json",
 | 
				
			||||||
        "test/generated-artifacts/IEth2Dai.json",
 | 
					        "test/generated-artifacts/IEth2Dai.json",
 | 
				
			||||||
        "test/generated-artifacts/IKyberNetworkProxy.json",
 | 
					        "test/generated-artifacts/IKyberNetworkProxy.json",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user