Updating bridge to work w/o MultiAssetProxy

This commit is contained in:
Greg Hysen
2019-12-03 15:25:07 -08:00
parent 444125a7e1
commit f19f4310f4
6 changed files with 74 additions and 38 deletions

View File

@@ -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.

View File

@@ -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; //
} }
} }

View File

@@ -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": {

View File

@@ -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,

View File

@@ -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';

View File

@@ -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",