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/Authorizable.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "../interfaces/IERC20Bridge.sol";
import "../interfaces/IDydxBridge.sol";
import "../interfaces/IDydx.sol";
@@ -33,15 +34,15 @@ contract DydxBridge is
Authorizable
{
using LibSafeMath for uint256;
/// @dev Callback for `IERC20Bridge`. Deposits or withdraws tokens from a dydx account.
/// Notes:
/// 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
/// (ERC20Bridge is authorized).
/// 3. The order must be signed by the owner or an operator of the dydx account.
/// This signature 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.
/// 3. The `from` address must be the maker and owner of the dydx account.
/// This signature is validated by the 0x Exchange.
/// @param from The sender of the tokens.
/// @param to The recipient of the tokens.
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
@@ -58,48 +59,62 @@ contract DydxBridge is
onlyAuthorized
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.
(BridgeData memory bridgeData) = abi.decode(encodedBridgeData, (BridgeData));
// Cache dydx contract.
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.
IDydx.AccountInfo[] memory accounts = new IDydx.AccountInfo[](1);
accounts[0] = IDydx.AccountInfo({
owner: bridgeData.accountOwner,
IDydx.AccountInfo[] memory dydxAccounts = new IDydx.AccountInfo[](1);
dydxAccounts[0] = IDydx.AccountInfo({
owner: from,
number: bridgeData.accountNumber
});
// Create dydx action.
IDydx.ActionArgs[] memory actions = new IDydx.ActionArgs[](1);
if (bridgeData.action == BridgeAction.Deposit) {
actions[0] = _createDepositAction(
from,
amount,
bridgeData
);
} else if (bridgeData.action == BridgeAction.Withdraw) {
actions[0] = _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("UNRECOGNIZED_ACTION");
IDydx.ActionArgs[] memory dydxActions = new IDydx.ActionArgs[](bridgeData.actions.length);
for (uint256 i = 0; i < dydxActions.length; ++i) {
BridgeAction bridgeAction = bridgeData.actions[i];
if (bridgeAction == BridgeAction.Deposit) {
// Compute the amount to deposit. The `amount` parameter is the amount to be withdrawn.
// It is computed by the Exchange as:
// amount = floor[(takerFillAmount * makerAssetAmount) / takerAssetAmount]
// The amount to deposit is equal to to `takerFillAmount`, which we compute below as:
// takerFillAmount ~= floor[(amount * takerAssetAmount) / makerAssetAmount]
// = floor[(amount * conversionRateNumerator) / conversionRateDenominator]
// Note that we can only approximate the original value of `takerFillAmount`. If we were to use
// `ceil` then we would risk overestimating the value.
uint256 amountToDeposit = amount
.mul(bridgeData.conversionRateNumerator)
.div(bridgeData.conversionRateDenominator);
dydxActions[i] = _createDepositAction(
from,
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.
dydx.operate(accounts, actions);
dydx.operate(dydxAccounts, dydxActions);
return BRIDGE_SUCCESS;
}
@@ -117,7 +132,7 @@ contract DydxBridge is
returns (IDydx.ActionArgs memory)
{
// Create dydx amount.
IDydx.AssetAmount memory amountToDeposit = IDydx.AssetAmount({
IDydx.AssetAmount memory dydxAmount = IDydx.AssetAmount({
sign: true, // true if positive.
denomination: IDydx.AssetDenomination.Wei, // Wei => actual token amount held in account.
ref: IDydx.AssetReference.Target, // Target => an absolute amount.
@@ -127,7 +142,7 @@ contract DydxBridge is
// Create dydx deposit action.
IDydx.ActionArgs memory depositAction = IDydx.ActionArgs({
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`.
primaryMarketId: bridgeData.marketId, // indicates which token to deposit.
otherAddress: depositFrom, // deposit from this address.

View File

@@ -27,9 +27,10 @@ interface IDydxBridge {
}
struct BridgeData {
BridgeAction action; // 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 marketId; // Market to operate on.
BridgeAction[] actions; // Action to run on dydx account.
uint256 accountNumber; // Account number used to identify the owner's specific account.
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",
=======
"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",
>>>>>>> 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."
},
"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';
<<<<<<< HEAD
>>>>>>> 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 IEth2Dai from '../test/generated-artifacts/IEth2Dai.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,
<<<<<<< HEAD
>>>>>>> ee82a0f67... Consistent capitalization for "dydx"`
=======
IDydxBridge: IDydxBridge as ContractArtifact,
>>>>>>> 5e2de489d... Updating bridge to work w/o MAP
IERC20Bridge: IERC20Bridge as ContractArtifact,
IEth2Dai: IEth2Dai 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_dydx';
<<<<<<< HEAD
>>>>>>> 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_eth2_dai';
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",
<<<<<<< HEAD
>>>>>>> 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/IEth2Dai.json",
"test/generated-artifacts/IKyberNetworkProxy.json",