mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
285 lines
9.8 KiB
Solidity
285 lines
9.8 KiB
Solidity
pragma solidity ^0.7.0;
|
|
pragma experimental ABIEncoderV2;
|
|
|
|
// import files from common directory
|
|
import { TokenInterface , MemoryInterface } from "../common/interfaces.sol";
|
|
import { Stores } from "../common/stores.sol";
|
|
import { DSMath } from "../common/math.sol";
|
|
|
|
interface SoloMarginContract {
|
|
|
|
struct Info {
|
|
address owner;
|
|
uint256 number;
|
|
}
|
|
|
|
enum ActionType {
|
|
Deposit,
|
|
Withdraw,
|
|
Transfer,
|
|
Buy,
|
|
Sell,
|
|
Trade,
|
|
Liquidate,
|
|
Vaporize,
|
|
Call
|
|
}
|
|
|
|
enum AssetDenomination {
|
|
Wei,
|
|
Par
|
|
}
|
|
|
|
enum AssetReference {
|
|
Delta,
|
|
Target
|
|
}
|
|
|
|
struct AssetAmount {
|
|
bool sign;
|
|
AssetDenomination denomination;
|
|
AssetReference ref;
|
|
uint256 value;
|
|
}
|
|
|
|
struct ActionArgs {
|
|
ActionType actionType;
|
|
uint256 accountId;
|
|
AssetAmount amount;
|
|
uint256 primaryMarketId;
|
|
uint256 secondaryMarketId;
|
|
address otherAddress;
|
|
uint256 otherAccountId;
|
|
bytes data;
|
|
}
|
|
|
|
struct Wei {
|
|
bool sign;
|
|
uint256 value;
|
|
}
|
|
|
|
function operate(Info[] calldata accounts, ActionArgs[] calldata actions) external;
|
|
function getAccountWei(Info calldata account, uint256 marketId) external returns (Wei memory);
|
|
function getNumMarkets() external view returns (uint256);
|
|
function getMarketTokenAddress(uint256 marketId) external view returns (address);
|
|
|
|
}
|
|
|
|
|
|
abstract contract DydxHelpers is DSMath, Stores {
|
|
/**
|
|
* @dev get WETH address
|
|
*/
|
|
function getWETHAddr() public pure returns (address weth) {
|
|
weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
|
|
}
|
|
|
|
/**
|
|
* @dev get Dydx Solo Address
|
|
*/
|
|
function getDydxAddress() public pure returns (address addr) {
|
|
addr = 0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e;
|
|
}
|
|
|
|
/**
|
|
* @dev Get Dydx Actions args.
|
|
*/
|
|
function getActionsArgs(uint256 marketId, uint256 amt, bool sign) internal view returns (SoloMarginContract.ActionArgs[] memory) {
|
|
SoloMarginContract.ActionArgs[] memory actions = new SoloMarginContract.ActionArgs[](1);
|
|
SoloMarginContract.AssetAmount memory amount = SoloMarginContract.AssetAmount(
|
|
sign,
|
|
SoloMarginContract.AssetDenomination.Wei,
|
|
SoloMarginContract.AssetReference.Delta,
|
|
amt
|
|
);
|
|
bytes memory empty;
|
|
SoloMarginContract.ActionType action = sign ? SoloMarginContract.ActionType.Deposit : SoloMarginContract.ActionType.Withdraw;
|
|
actions[0] = SoloMarginContract.ActionArgs(
|
|
action,
|
|
0,
|
|
amount,
|
|
marketId,
|
|
0,
|
|
address(this),
|
|
0,
|
|
empty
|
|
);
|
|
return actions;
|
|
}
|
|
|
|
/**
|
|
* @dev Get Dydx Acccount arg
|
|
*/
|
|
function getAccountArgs() internal view returns (SoloMarginContract.Info[] memory) {
|
|
SoloMarginContract.Info[] memory accounts = new SoloMarginContract.Info[](1);
|
|
accounts[0] = (SoloMarginContract.Info(address(this), 0));
|
|
return accounts;
|
|
}
|
|
|
|
/**
|
|
* @dev Get Dydx Position
|
|
*/
|
|
function getDydxPosition(SoloMarginContract solo, uint256 marketId) internal returns (uint tokenBal, bool tokenSign) {
|
|
SoloMarginContract.Wei memory tokenWeiBal = solo.getAccountWei(getAccountArgs()[0], marketId);
|
|
tokenBal = tokenWeiBal.value;
|
|
tokenSign = tokenWeiBal.sign;
|
|
}
|
|
|
|
/**
|
|
* @dev Get Dydx Market ID from token Address
|
|
*/
|
|
function getMarketId(SoloMarginContract solo, address token) internal view returns (uint _marketId) {
|
|
uint markets = solo.getNumMarkets();
|
|
address _token = token == ethAddr ? getWETHAddr() : token;
|
|
|
|
for (uint i = 0; i < markets; i++) {
|
|
if (_token == solo.getMarketTokenAddress(i)) {
|
|
_marketId = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
abstract contract BasicResolver is DydxHelpers {
|
|
event LogDeposit(address indexed token, uint marketId, uint256 tokenAmt, uint256 getId, uint256 setId);
|
|
event LogWithdraw(address indexed token, uint marketId, uint256 tokenAmt, uint256 getId, uint256 setId);
|
|
event LogBorrow(address indexed token, uint marketId, uint256 tokenAmt, uint256 getId, uint256 setId);
|
|
event LogPayback(address indexed token, uint marketId, uint256 tokenAmt, uint256 getId, uint256 setId);
|
|
|
|
/**
|
|
* @dev Deposit ETH/ERC20_Token.
|
|
* @param token token address to deposit.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
|
* @param amt token amount to deposit.
|
|
* @param getId Get token amount at this ID from `InstaMemory` Contract.
|
|
* @param setId Set token amount at this ID in `InstaMemory` Contract.
|
|
*/
|
|
function deposit(address token, uint amt, uint getId, uint setId) external payable{
|
|
SoloMarginContract dydxContract = SoloMarginContract(getDydxAddress());
|
|
|
|
uint _amt = getUint(getId, amt);
|
|
uint _marketId = getMarketId(dydxContract, token);
|
|
|
|
(uint depositedAmt, bool sign) = getDydxPosition(dydxContract, _marketId);
|
|
require(depositedAmt == 0 || sign, "token-borrowed");
|
|
|
|
if (token == ethAddr) {
|
|
TokenInterface tokenContract = TokenInterface(getWETHAddr());
|
|
_amt = _amt == uint(-1) ? address(this).balance : _amt;
|
|
tokenContract.deposit{value: _amt}();
|
|
tokenContract.approve(getDydxAddress(), _amt);
|
|
} else {
|
|
TokenInterface tokenContract = TokenInterface(token);
|
|
_amt = _amt == uint(-1) ? tokenContract.balanceOf(address(this)) : _amt;
|
|
tokenContract.approve(getDydxAddress(), _amt);
|
|
}
|
|
|
|
dydxContract.operate(getAccountArgs(), getActionsArgs(_marketId, _amt, true));
|
|
setUint(setId, _amt);
|
|
|
|
emit LogDeposit(token, _marketId, _amt, getId, setId);
|
|
}
|
|
|
|
/**
|
|
* @dev Withdraw ETH/ERC20_Token.
|
|
* @param token token address to withdraw.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
|
* @param amt token amount to withdraw.
|
|
* @param getId Get token amount at this ID from `InstaMemory` Contract.
|
|
* @param setId Set token amount at this ID in `InstaMemory` Contract.
|
|
*/
|
|
function withdraw(address token, uint amt, uint getId, uint setId) external payable{
|
|
SoloMarginContract dydxContract = SoloMarginContract(getDydxAddress());
|
|
|
|
uint _amt = getUint(getId, amt);
|
|
uint _marketId = getMarketId(dydxContract, token);
|
|
|
|
(uint depositedAmt, bool sign) = getDydxPosition(dydxContract, _marketId);
|
|
require(sign, "try-payback");
|
|
|
|
_amt = _amt == uint(-1) ? depositedAmt : _amt;
|
|
require(_amt <= depositedAmt, "withdraw-exceeds");
|
|
|
|
dydxContract.operate(getAccountArgs(), getActionsArgs(_marketId, _amt, false));
|
|
|
|
if (token == ethAddr) {
|
|
TokenInterface tokenContract = TokenInterface(getWETHAddr());
|
|
tokenContract.approve(address(tokenContract), _amt);
|
|
tokenContract.withdraw(_amt);
|
|
}
|
|
|
|
setUint(setId, _amt);
|
|
|
|
emit LogWithdraw(token, _marketId, _amt, getId, setId);
|
|
}
|
|
|
|
/**
|
|
* @dev Borrow ETH/ERC20_Token.
|
|
* @param token token address to borrow.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
|
* @param amt token amount to borrow.
|
|
* @param getId Get token amount at this ID from `InstaMemory` Contract.
|
|
* @param setId Set token amount at this ID in `InstaMemory` Contract.
|
|
*/
|
|
function borrow(address token, uint amt, uint getId, uint setId) external payable {
|
|
SoloMarginContract dydxContract = SoloMarginContract(getDydxAddress());
|
|
|
|
uint _amt = getUint(getId, amt);
|
|
uint _marketId = getMarketId(dydxContract, token);
|
|
|
|
(uint borrowedAmt, bool sign) = getDydxPosition(dydxContract, _marketId);
|
|
require(borrowedAmt == 0 || !sign, "token-deposited");
|
|
|
|
dydxContract.operate(getAccountArgs(), getActionsArgs(_marketId, _amt, false));
|
|
|
|
if (token == ethAddr) {
|
|
TokenInterface tokenContract = TokenInterface(getWETHAddr());
|
|
tokenContract.approve(address(tokenContract), _amt);
|
|
tokenContract.withdraw(_amt);
|
|
}
|
|
|
|
setUint(setId, _amt);
|
|
|
|
emit LogBorrow(token, _marketId, _amt, getId, setId);
|
|
}
|
|
|
|
/**
|
|
* @dev Payback borrowed ETH/ERC20_Token.
|
|
* @param token token address to payback.(For ETH: 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)
|
|
* @param amt token amount to payback.
|
|
* @param getId Get token amount at this ID from `InstaMemory` Contract.
|
|
* @param setId Set token amount at this ID in `InstaMemory` Contract.
|
|
*/
|
|
function payback(address token, uint amt, uint getId, uint setId) external payable {
|
|
SoloMarginContract dydxContract = SoloMarginContract(getDydxAddress());
|
|
|
|
uint _amt = getUint(getId, amt);
|
|
uint _marketId = getMarketId(dydxContract, token);
|
|
|
|
(uint borrowedAmt, bool sign) = getDydxPosition(dydxContract, _marketId);
|
|
require(!sign, "try-withdraw");
|
|
|
|
_amt = _amt == uint(-1) ? borrowedAmt : _amt;
|
|
require(_amt <= borrowedAmt, "payback-exceeds");
|
|
|
|
if (token == ethAddr) {
|
|
TokenInterface tokenContract = TokenInterface(getWETHAddr());
|
|
require(address(this).balance >= _amt, "not-enough-eth");
|
|
tokenContract.deposit{value: _amt}();
|
|
tokenContract.approve(getDydxAddress(), _amt);
|
|
} else {
|
|
TokenInterface tokenContract = TokenInterface(token);
|
|
require(tokenContract.balanceOf(address(this)) >= _amt, "not-enough-token");
|
|
tokenContract.approve(getDydxAddress(), _amt);
|
|
}
|
|
|
|
dydxContract.operate(getAccountArgs(), getActionsArgs(_marketId, _amt, true));
|
|
setUint(setId, _amt);
|
|
|
|
emit LogPayback(token, _marketId, _amt, getId, setId);
|
|
}
|
|
}
|
|
|
|
|
|
contract ConnectDydx is BasicResolver {
|
|
string public name = "Dydx-v1";
|
|
} |