Created
October 15, 2020 11:59
-
-
Save kendricktan/c8363a4572d4d7c857ee2f89daf0a2de to your computer and use it in GitHub Desktop.
shortdai solc-input.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"language": "Solidity", | |
"sources": { | |
"contracts/CloseShortDAI.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.7.0;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./weth/WETH.sol\";\n\nimport \"./dydx/DydxFlashloanBase.sol\";\nimport \"./dydx/IDydx.sol\";\n\nimport \"./maker/IDssCdpManager.sol\";\nimport \"./maker/IDssProxyActions.sol\";\nimport \"./maker/DssActionsBase.sol\";\n\nimport \"./curve/ICurveFiCurve.sol\";\n\nimport \"./Constants.sol\";\n\ncontract CloseShortDAI is ICallee, DydxFlashloanBase, DssActionsBase {\n struct CSDParams {\n uint256 cdpId; // CdpId to close\n address curvePool; // Which curve pool to use\n uint256 mintAmountDAI; // Amount of DAI to mint\n uint256 withdrawAmountUSDC; // Amount of USDC to withdraw from vault\n uint256 flashloanAmountWETH; // Amount of WETH flashloaned\n }\n\n function callFunction(\n address sender,\n Account.Info memory account,\n bytes memory data\n ) public override {\n CSDParams memory csdp = abi.decode(data, (CSDParams));\n\n // Step 1. Have Flashloaned WETH\n // Open WETH CDP in Maker, then Mint out some DAI\n uint256 wethCdp = _openLockGemAndDraw(\n Constants.MCD_JOIN_ETH_A,\n Constants.ETH_A_ILK,\n csdp.flashloanAmountWETH,\n csdp.mintAmountDAI\n );\n\n // Step 2.\n // Use flashloaned DAI to repay entire vault and withdraw USDC\n _wipeAllAndFreeGem(\n Constants.MCD_JOIN_USDC_A,\n csdp.cdpId,\n csdp.withdrawAmountUSDC\n );\n\n // Step 3.\n // Converts USDC to DAI on CurveFi (To repay loan)\n // DAI = 0 index, USDC = 1 index\n ICurveFiCurve curve = ICurveFiCurve(csdp.curvePool);\n // Calculate amount of USDC needed to exchange to repay flashloaned DAI\n // Allow max of 5% slippage (otherwise no profits lmao)\n uint256 usdcBal = IERC20(Constants.USDC).balanceOf(address(this));\n require(\n IERC20(Constants.USDC).approve(address(curve), usdcBal),\n \"erc20-approve-curvepool-failed\"\n );\n curve.exchange_underlying(int128(1), int128(0), usdcBal, 0);\n\n // Step 4.\n // Repay DAI loan back to WETH CDP and FREE WETH\n _wipeAllAndFreeGem(\n Constants.MCD_JOIN_ETH_A,\n wethCdp,\n csdp.flashloanAmountWETH\n );\n }\n\n function flashloanAndClose(\n address _sender,\n address _solo,\n address _curvePool,\n uint256 _cdpId,\n uint256 _ethUsdRatio18 // 1 ETH = <X> DAI?\n ) external payable {\n require(msg.value == 2, \"!fee\");\n\n ISoloMargin solo = ISoloMargin(_solo);\n\n uint256 marketId = _getMarketIdFromTokenAddress(_solo, Constants.WETH);\n\n // Supplied = How much we want to withdraw\n // Borrowed = How much we want to loan\n (\n uint256 withdrawAmountUSDC,\n uint256 mintAmountDAI\n ) = _getSuppliedAndBorrow(Constants.MCD_JOIN_USDC_A, _cdpId);\n\n // Given, ETH price, calculate how much WETH we need to flashloan\n // Dividing by 2 to gives us 200% col ratio\n uint256 flashloanAmountWETH = mintAmountDAI.mul(1 ether).div(\n _ethUsdRatio18.div(2)\n );\n\n require(\n IERC20(Constants.WETH).balanceOf(_solo) >= flashloanAmountWETH,\n \"!weth-supply\"\n );\n\n // Wrap ETH into WETH\n WETH(Constants.WETH).deposit{value: msg.value}();\n WETH(Constants.WETH).approve(_solo, flashloanAmountWETH.add(msg.value));\n\n Actions.ActionArgs[] memory operations = new Actions.ActionArgs[](3);\n\n operations[0] = _getWithdrawAction(marketId, flashloanAmountWETH);\n operations[1] = _getCallAction(\n abi.encode(\n CSDParams({\n mintAmountDAI: mintAmountDAI,\n withdrawAmountUSDC: withdrawAmountUSDC,\n flashloanAmountWETH: flashloanAmountWETH,\n cdpId: _cdpId,\n curvePool: _curvePool\n })\n )\n );\n operations[2] = _getDepositAction(\n marketId,\n flashloanAmountWETH.add(msg.value)\n );\n\n Account.Info[] memory accountInfos = new Account.Info[](1);\n accountInfos[0] = _getAccountInfo();\n\n solo.operate(accountInfos, operations);\n\n // Convert DAI leftovers to USDC\n uint256 daiBal = IERC20(Constants.DAI).balanceOf(address(this));\n require(\n IERC20(Constants.DAI).approve(_curvePool, daiBal),\n \"erc20-approve-curvepool-failed\"\n );\n ICurveFiCurve(_curvePool).exchange_underlying(\n int128(0),\n int128(1),\n daiBal,\n 0\n );\n\n // Refund leftovers\n IERC20(Constants.USDC).transfer(\n _sender,\n IERC20(Constants.USDC).balanceOf(address(this))\n );\n }\n}\n" | |
}, | |
"@openzeppelin/contracts/math/SafeMath.sol": { | |
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMath: subtraction overflow\");\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMath: division by zero\");\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMath: modulo by zero\");\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts with custom message when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n return a % b;\n }\n}\n" | |
}, | |
"contracts/weth/WETH.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.2;\n\ninterface WETH {\n function deposit() external payable;\n\n function withdraw(uint256 wad) external;\n\n function approve(address guy, uint256 wad) external returns (bool);\n\n function transfer(address dst, uint256 wad) external returns (bool);\n}\n" | |
}, | |
"contracts/dydx/DydxFlashloanBase.sol": { | |
"content": "// SPDX-License-Identifier:\npragma solidity >=0.6.0 <0.7.0;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IDydx.sol\";\n\ncontract DydxFlashloanBase {\n using SafeMath for uint256;\n\n // -- Internal Helper functions -- //\n\n function _getMarketIdFromTokenAddress(address _solo, address token)\n internal\n view\n returns (uint256)\n {\n ISoloMargin solo = ISoloMargin(_solo);\n\n uint256 numMarkets = solo.getNumMarkets();\n\n address curToken;\n for (uint256 i = 0; i < numMarkets; i++) {\n curToken = solo.getMarketTokenAddress(i);\n\n if (curToken == token) {\n return i;\n }\n }\n\n revert(\"No marketId found for provided token\");\n }\n\n function _getRepaymentAmount() internal pure returns (uint256) {\n // Needs to be overcollateralize\n // Needs to provide +2 wei to be safe\n return 2;\n }\n\n function _getAccountInfo() internal view returns (Account.Info memory) {\n return Account.Info({owner: address(this), number: 1});\n }\n\n function _getWithdrawAction(uint256 marketId, uint256 amount)\n internal\n view\n returns (Actions.ActionArgs memory)\n {\n return\n Actions.ActionArgs({\n actionType: Actions.ActionType.Withdraw,\n accountId: 0,\n amount: Types.AssetAmount({\n sign: false,\n denomination: Types.AssetDenomination.Wei,\n ref: Types.AssetReference.Delta,\n value: amount\n }),\n primaryMarketId: marketId,\n secondaryMarketId: 0,\n otherAddress: address(this),\n otherAccountId: 0,\n data: \"\"\n });\n }\n\n function _getCallAction(bytes memory data)\n internal\n view\n returns (Actions.ActionArgs memory)\n {\n return\n Actions.ActionArgs({\n actionType: Actions.ActionType.Call,\n accountId: 0,\n amount: Types.AssetAmount({\n sign: false,\n denomination: Types.AssetDenomination.Wei,\n ref: Types.AssetReference.Delta,\n value: 0\n }),\n primaryMarketId: 0,\n secondaryMarketId: 0,\n otherAddress: address(this),\n otherAccountId: 0,\n data: data\n });\n }\n\n function _getDepositAction(uint256 marketId, uint256 amount)\n internal\n view\n returns (Actions.ActionArgs memory)\n {\n return\n Actions.ActionArgs({\n actionType: Actions.ActionType.Deposit,\n accountId: 0,\n amount: Types.AssetAmount({\n sign: true,\n denomination: Types.AssetDenomination.Wei,\n ref: Types.AssetReference.Delta,\n value: amount\n }),\n primaryMarketId: marketId,\n secondaryMarketId: 0,\n otherAddress: address(this),\n otherAccountId: 0,\n data: \"\"\n });\n }\n}\n" | |
}, | |
"@openzeppelin/contracts/token/ERC20/IERC20.sol": { | |
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" | |
}, | |
"contracts/dydx/IDydx.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.7.0;\npragma experimental ABIEncoderV2;\n\nlibrary Account {\n enum Status {Normal, Liquid, Vapor}\n struct Info {\n address owner; // The address that owns the account\n uint256 number; // A nonce that allows a single address to control many accounts\n }\n struct Storage {\n mapping(uint256 => Types.Par) balances; // Mapping from marketId to principal\n Status status;\n }\n}\n\nlibrary Actions {\n enum ActionType {\n Deposit, // supply tokens\n Withdraw, // borrow tokens\n Transfer, // transfer balance between accounts\n Buy, // buy an amount of some token (externally)\n Sell, // sell an amount of some token (externally)\n Trade, // trade tokens against another account\n Liquidate, // liquidate an undercollateralized or expiring account\n Vaporize, // use excess tokens to zero-out a completely negative account\n Call // send arbitrary data to an address\n }\n\n struct ActionArgs {\n ActionType actionType;\n uint256 accountId;\n Types.AssetAmount amount;\n uint256 primaryMarketId;\n uint256 secondaryMarketId;\n address otherAddress;\n uint256 otherAccountId;\n bytes data;\n }\n\n struct DepositArgs {\n Types.AssetAmount amount;\n Account.Info account;\n uint256 market;\n address from;\n }\n\n struct WithdrawArgs {\n Types.AssetAmount amount;\n Account.Info account;\n uint256 market;\n address to;\n }\n\n struct CallArgs {\n Account.Info account;\n address callee;\n bytes data;\n }\n}\n\nlibrary Decimal {\n struct D256 {\n uint256 value;\n }\n}\n\nlibrary Types {\n enum AssetDenomination {\n Wei, // the amount is denominated in wei\n Par // the amount is denominated in par\n }\n\n enum AssetReference {\n Delta, // the amount is given as a delta from the current value\n Target // the amount is given as an exact number to end up at\n }\n\n struct AssetAmount {\n bool sign; // true if positive\n AssetDenomination denomination;\n AssetReference ref;\n uint256 value;\n }\n\n struct TotalPar {\n uint128 borrow;\n uint128 supply;\n }\n\n struct Par {\n bool sign; // true if positive\n uint128 value;\n }\n\n struct Wei {\n bool sign; // true if positive\n uint256 value;\n }\n}\n\ninterface ISoloMargin {\n function getMarketTokenAddress(uint256 marketId)\n external\n view\n returns (address);\n\n function getNumMarkets() external view returns (uint256);\n\n function operate(\n Account.Info[] calldata accounts,\n Actions.ActionArgs[] calldata actions\n ) external;\n}\n\ninterface ICallee {\n // ============ external Functions ============\n\n /**\n * Allows users to send this contract arbitrary data.\n *\n * @param sender The msg.sender to Solo\n * @param accountInfo The account from which the data is being sent\n * @param data Arbitrary data given by the sender\n */\n function callFunction(\n address sender,\n Account.Info calldata accountInfo,\n bytes calldata data\n ) external;\n}\n" | |
}, | |
"contracts/maker/IDssCdpManager.sol": { | |
"content": "// SPDX-License-Identifier: MIT\n// Address: 0x5ef30b9986345249bc32d8928B7ee64DE9435E39\npragma solidity >=0.6.0 <0.7.0;\n\ninterface IDssCdpManager {\n function cdpAllow(\n uint256 cdp,\n address usr,\n uint256 ok\n ) external;\n\n function cdpCan(\n address,\n uint256,\n address\n ) external view returns (uint256);\n\n function cdpi() external view returns (uint256);\n\n function count(address) external view returns (uint256);\n\n function enter(address src, uint256 cdp) external;\n\n function first(address) external view returns (uint256);\n\n function flux(\n bytes32 ilk,\n uint256 cdp,\n address dst,\n uint256 wad\n ) external;\n\n function flux(\n uint256 cdp,\n address dst,\n uint256 wad\n ) external;\n\n function frob(\n uint256 cdp,\n int256 dink,\n int256 dart\n ) external;\n\n function give(uint256 cdp, address dst) external;\n\n function ilks(uint256) external view returns (bytes32);\n\n function last(address) external view returns (uint256);\n\n function list(uint256) external view returns (uint256 prev, uint256 next);\n\n function move(\n uint256 cdp,\n address dst,\n uint256 rad\n ) external;\n\n function open(bytes32 ilk, address usr) external returns (uint256);\n\n function owns(uint256) external view returns (address);\n\n function quit(uint256 cdp, address dst) external;\n\n function shift(uint256 cdpSrc, uint256 cdpDst) external;\n\n function urnAllow(address usr, uint256 ok) external;\n\n function urnCan(address, address) external view returns (uint256);\n\n function urns(uint256) external view returns (address);\n\n function vat() external view returns (address);\n}\n" | |
}, | |
"contracts/maker/IDssProxyActions.sol": { | |
"content": "// SPDX-License-Identifier: MIT\n// Address: 0x82ecD135Dce65Fbc6DbdD0e4237E0AF93FFD5038\npragma solidity >=0.6.0 <0.7.0;\n\ninterface IDssProxyActions {\n function cdpAllow(\n address manager,\n uint256 cdp,\n address usr,\n uint256 ok\n ) external;\n\n function daiJoin_join(\n address apt,\n address urn,\n uint256 wad\n ) external;\n\n function draw(\n address manager,\n address jug,\n address daiJoin,\n uint256 cdp,\n uint256 wad\n ) external;\n\n function enter(\n address manager,\n address src,\n uint256 cdp\n ) external;\n\n function ethJoin_join(address apt, address urn) external payable;\n\n function exitETH(\n address manager,\n address ethJoin,\n uint256 cdp,\n uint256 wad\n ) external;\n\n function exitGem(\n address manager,\n address gemJoin,\n uint256 cdp,\n uint256 amt\n ) external;\n\n function flux(\n address manager,\n uint256 cdp,\n address dst,\n uint256 wad\n ) external;\n\n function freeETH(\n address manager,\n address ethJoin,\n uint256 cdp,\n uint256 wad\n ) external;\n\n function freeGem(\n address manager,\n address gemJoin,\n uint256 cdp,\n uint256 amt\n ) external;\n\n function frob(\n address manager,\n uint256 cdp,\n int256 dink,\n int256 dart\n ) external;\n\n function gemJoin_join(\n address apt,\n address urn,\n uint256 amt,\n bool transferFrom\n ) external;\n\n function give(\n address manager,\n uint256 cdp,\n address usr\n ) external;\n\n function giveToProxy(\n address proxyRegistry,\n address manager,\n uint256 cdp,\n address dst\n ) external;\n\n function hope(address obj, address usr) external;\n\n function lockETH(\n address manager,\n address ethJoin,\n uint256 cdp\n ) external payable;\n\n function lockETHAndDraw(\n address manager,\n address jug,\n address ethJoin,\n address daiJoin,\n uint256 cdp,\n uint256 wadD\n ) external payable;\n\n function lockGem(\n address manager,\n address gemJoin,\n uint256 cdp,\n uint256 amt,\n bool transferFrom\n ) external;\n\n function lockGemAndDraw(\n address manager,\n address jug,\n address gemJoin,\n address daiJoin,\n uint256 cdp,\n uint256 amtC,\n uint256 wadD,\n bool transferFrom\n ) external;\n\n function makeGemBag(address gemJoin) external returns (address bag);\n\n function move(\n address manager,\n uint256 cdp,\n address dst,\n uint256 rad\n ) external;\n\n function nope(address obj, address usr) external;\n\n function open(\n address manager,\n bytes32 ilk,\n address usr\n ) external returns (uint256 cdp);\n\n function openLockETHAndDraw(\n address manager,\n address jug,\n address ethJoin,\n address daiJoin,\n bytes32 ilk,\n uint256 wadD\n ) external payable returns (uint256 cdp);\n\n function openLockGNTAndDraw(\n address manager,\n address jug,\n address gntJoin,\n address daiJoin,\n bytes32 ilk,\n uint256 amtC,\n uint256 wadD\n ) external returns (address bag, uint256 cdp);\n\n function openLockGemAndDraw(\n address manager,\n address jug,\n address gemJoin,\n address daiJoin,\n bytes32 ilk,\n uint256 amtC,\n uint256 wadD,\n bool transferFrom\n ) external returns (uint256 cdp);\n\n function quit(\n address manager,\n uint256 cdp,\n address dst\n ) external;\n\n function safeLockETH(\n address manager,\n address ethJoin,\n uint256 cdp,\n address owner\n ) external payable;\n\n function safeLockGem(\n address manager,\n address gemJoin,\n uint256 cdp,\n uint256 amt,\n bool transferFrom,\n address owner\n ) external;\n\n function safeWipe(\n address manager,\n address daiJoin,\n uint256 cdp,\n uint256 wad,\n address owner\n ) external;\n\n function safeWipeAll(\n address manager,\n address daiJoin,\n uint256 cdp,\n address owner\n ) external;\n\n function shift(\n address manager,\n uint256 cdpSrc,\n uint256 cdpOrg\n ) external;\n\n function transfer(\n address gem,\n address dst,\n uint256 amt\n ) external;\n\n function urnAllow(\n address manager,\n address usr,\n uint256 ok\n ) external;\n\n function wipe(\n address manager,\n address daiJoin,\n uint256 cdp,\n uint256 wad\n ) external;\n\n function wipeAll(\n address manager,\n address daiJoin,\n uint256 cdp\n ) external;\n\n function wipeAllAndFreeETH(\n address manager,\n address ethJoin,\n address daiJoin,\n uint256 cdp,\n uint256 wadC\n ) external;\n\n function wipeAllAndFreeGem(\n address manager,\n address gemJoin,\n address daiJoin,\n uint256 cdp,\n uint256 amtC\n ) external;\n\n function wipeAndFreeETH(\n address manager,\n address ethJoin,\n address daiJoin,\n uint256 cdp,\n uint256 wadC,\n uint256 wadD\n ) external;\n\n function wipeAndFreeGem(\n address manager,\n address gemJoin,\n address daiJoin,\n uint256 cdp,\n uint256 amtC,\n uint256 wadD\n ) external;\n}\n" | |
}, | |
"contracts/maker/DssActionsBase.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.7.0;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"../Constants.sol\";\nimport \"./IDssCdpManager.sol\";\n\ninterface GemLike {\n function approve(address, uint256) external;\n\n function transfer(address, uint256) external;\n\n function transferFrom(\n address,\n address,\n uint256\n ) external;\n\n function deposit() external payable;\n\n function withdraw(uint256) external;\n}\n\ninterface GemJoinLike {\n function dec() external returns (uint256);\n\n function gem() external returns (address);\n\n function join(address, uint256) external payable;\n\n function exit(address, uint256) external;\n}\n\ninterface VatLike {\n function can(address, address) external view returns (uint256);\n\n function ilks(bytes32)\n external\n view\n returns (\n uint256,\n uint256,\n uint256,\n uint256,\n uint256\n );\n\n function dai(address) external view returns (uint256);\n\n function urns(bytes32, address) external view returns (uint256, uint256);\n\n function frob(\n bytes32,\n address,\n address,\n address,\n int256,\n int256\n ) external;\n\n function hope(address) external;\n\n function move(\n address,\n address,\n uint256\n ) external;\n}\n\ninterface JugLike {\n function drip(bytes32) external returns (uint256);\n\n function ilks(bytes32) external view returns (uint256, uint256);\n}\n\ninterface DaiJoinLike {\n function vat() external returns (VatLike);\n\n function dai() external returns (GemLike);\n\n function join(address, uint256) external payable;\n\n function exit(address, uint256) external;\n}\n\ncontract DssActionsBase {\n uint256 constant RAY = 10**27;\n\n using SafeMath for uint256;\n\n function _convertTo18(address gemJoin, uint256 amt)\n internal\n returns (uint256 wad)\n {\n // For those collaterals that have less than 18 decimals precision we need to do the conversion before passing to frob function\n // Adapters will automatically handle the difference of precision\n wad = amt.mul(10**(18 - GemJoinLike(gemJoin).dec()));\n }\n\n function _toInt(uint256 x) internal pure returns (int256 y) {\n y = int256(x);\n require(y >= 0, \"int-overflow\");\n }\n\n function _toRad(uint256 wad) internal pure returns (uint256 rad) {\n rad = wad.mul(10**27);\n }\n\n function _gemJoin_join(\n address apt,\n address urn,\n uint256 wad,\n bool transferFrom\n ) internal {\n // Only executes for tokens that have approval/transferFrom implementation\n if (transferFrom) {\n // Tokens already in address(this)\n // GemLike(GemJoinLike(apt).gem()).transferFrom(msg.sender, address(this), wad);\n // Approves adapter to take the token amount\n GemLike(GemJoinLike(apt).gem()).approve(apt, wad);\n }\n // Joins token collateral into the vat\n GemJoinLike(apt).join(urn, wad);\n }\n\n function _daiJoin_join(\n address apt,\n address urn,\n uint256 wad\n ) internal {\n // Contract already has tokens\n // Gets DAI from the user's wallet\n // DaiJoinLike(apt).dai().transferFrom(msg.sender, address(this), wad);\n // Approves adapter to take the DAI amount\n DaiJoinLike(apt).dai().approve(apt, wad);\n // Joins DAI into the vat\n DaiJoinLike(apt).join(urn, wad);\n }\n\n function _getDrawDart(\n address vat,\n address jug,\n address urn,\n bytes32 ilk,\n uint256 wad\n ) internal returns (int256 dart) {\n // Updates stability fee rate\n uint256 rate = JugLike(jug).drip(ilk);\n\n // Gets DAI balance of the urn in the vat\n uint256 dai = VatLike(vat).dai(urn);\n\n // If there was already enough DAI in the vat balance, just exits it without adding more debt\n if (dai < wad.mul(RAY)) {\n // Calculates the needed dart so together with the existing dai in the vat is enough to exit wad amount of DAI tokens\n dart = _toInt(wad.mul(RAY).sub(dai) / rate);\n // This is neeeded due lack of precision. It might need to sum an extra dart wei (for the given DAI wad amount)\n dart = uint256(dart).mul(rate) < wad.mul(RAY) ? dart + 1 : dart;\n }\n }\n\n function _getWipeDart(\n address vat,\n uint256 dai,\n address urn,\n bytes32 ilk\n ) internal view returns (int256 dart) {\n // Gets actual rate from the vat\n (, uint256 rate, , , ) = VatLike(vat).ilks(ilk);\n // Gets actual art value of the urn\n (, uint256 art) = VatLike(vat).urns(ilk, urn);\n\n // Uses the whole dai balance in the vat to reduce the debt\n dart = _toInt(dai / rate);\n // Checks the calculated dart is not higher than urn.art (total debt), otherwise uses its value\n dart = uint256(dart) <= art ? -dart : -_toInt(art);\n }\n\n function _getWipeAllWad(\n address vat,\n address usr,\n address urn,\n bytes32 ilk\n ) internal view returns (uint256 wad) {\n // Gets actual rate from the vat\n (, uint256 rate, , , ) = VatLike(vat).ilks(ilk);\n // Gets actual art value of the urn\n (, uint256 art) = VatLike(vat).urns(ilk, urn);\n // Gets actual dai amount in the urn\n uint256 dai = VatLike(vat).dai(usr);\n\n uint256 rad = art.mul(rate).sub(dai);\n wad = rad / RAY;\n\n // If the rad precision has some dust, it will need to request for 1 extra wad wei\n wad = wad.mul(RAY) < rad ? wad + 1 : wad;\n }\n\n function _getSuppliedAndBorrow(address gemJoin, uint256 cdp)\n internal\n returns (uint256, uint256)\n {\n IDssCdpManager manager = IDssCdpManager(Constants.CDP_MANAGER);\n\n address vat = manager.vat();\n bytes32 ilk = manager.ilks(cdp);\n\n // Gets actual rate from the vat\n (, uint256 rate, , , ) = VatLike(vat).ilks(ilk);\n // Gets actual art value of the urn\n (uint256 supplied, uint256 art) = VatLike(vat).urns(\n ilk,\n manager.urns(cdp)\n );\n // Gets actual dai amount in the urn\n uint256 dai = VatLike(vat).dai(manager.owns(cdp));\n\n uint256 rad = art.mul(rate).sub(dai);\n uint256 wad = rad / RAY;\n\n // If the rad precision has some dust, it will need to request for 1 extra wad wei\n uint256 borrowed = wad.mul(RAY) < rad ? wad + 1 : wad;\n\n // Convert back to native units\n supplied = supplied.div(10**(18 - GemJoinLike(gemJoin).dec()));\n\n return (supplied, borrowed);\n }\n\n function _lockGemAndDraw(\n address gemJoin,\n uint256 cdp,\n uint256 wadC,\n uint256 wadD\n ) internal {\n IDssCdpManager manager = IDssCdpManager(Constants.CDP_MANAGER);\n\n address urn = manager.urns(cdp);\n address vat = manager.vat();\n bytes32 ilk = manager.ilks(cdp);\n\n // Receives ETH amount, converts it to WETH and joins it into the vat\n _gemJoin_join(gemJoin, urn, wadC, true);\n\n // Locks GEM amount into the CDP and generates debt\n manager.frob(\n cdp,\n _toInt(_convertTo18(gemJoin, wadC)),\n _getDrawDart(vat, Constants.MCD_JUG, urn, ilk, wadD)\n );\n\n // Moves the DAI amount (balance in the vat in rad) to proxy's address\n manager.move(cdp, address(this), _toRad(wadD));\n\n // Allows adapter to access to proxy's DAI balance in the vat\n if (\n VatLike(vat).can(address(this), address(Constants.MCD_JOIN_DAI)) ==\n 0\n ) {\n VatLike(vat).hope(Constants.MCD_JOIN_DAI);\n }\n // Exits DAI to the user's wallet as a token\n DaiJoinLike(Constants.MCD_JOIN_DAI).exit(address(this), wadD);\n }\n\n function _wipeAllAndFreeGem(\n address gemJoin,\n uint256 cdp,\n uint256 amtC\n ) internal {\n IDssCdpManager manager = IDssCdpManager(Constants.CDP_MANAGER);\n\n address vat = manager.vat();\n address urn = manager.urns(cdp);\n bytes32 ilk = manager.ilks(cdp);\n (, uint256 art) = VatLike(vat).urns(ilk, urn);\n\n // Joins DAI amount into the vat\n _daiJoin_join(\n Constants.MCD_JOIN_DAI,\n urn,\n _getWipeAllWad(vat, urn, urn, ilk)\n );\n uint256 wadC = _convertTo18(gemJoin, amtC);\n // Paybacks debt to the CDP and unlocks token amount from it\n manager.frob(cdp, -_toInt(wadC), -int256(art));\n // Moves the amount from the CDP urn to proxy's address\n manager.flux(cdp, address(this), wadC);\n // Exits token amount to the user's wallet as a token\n GemJoinLike(gemJoin).exit(address(this), amtC);\n }\n\n function _openLockGemAndDraw(\n address gemJoin,\n bytes32 ilk,\n uint256 amtC,\n uint256 wadD\n ) internal returns (uint256 cdp) {\n cdp = IDssCdpManager(Constants.CDP_MANAGER).open(ilk, address(this));\n _lockGemAndDraw(gemJoin, cdp, amtC, wadD);\n }\n}\n" | |
}, | |
"contracts/Constants.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.7.0;\n\nlibrary Constants {\n address constant CDP_MANAGER = 0x5ef30b9986345249bc32d8928B7ee64DE9435E39;\n address constant PROXY_ACTIONS = 0x82ecD135Dce65Fbc6DbdD0e4237E0AF93FFD5038;\n address constant MCD_JOIN_ETH_A = 0x2F0b23f53734252Bda2277357e97e1517d6B042A;\n address constant MCD_JOIN_USDC_A = 0xA191e578a6736167326d05c119CE0c90849E84B7;\n address constant MCD_JOIN_DAI = 0x9759A6Ac90977b93B58547b4A71c78317f391A28;\n address constant MCD_JUG = 0x19c0976f590D67707E62397C87829d896Dc0f1F1;\n address constant MCD_END = 0xaB14d3CE3F733CACB76eC2AbE7d2fcb00c99F3d5;\n\n address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;\n address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;\n address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;\n\n address constant UNISWAPV2_ROUTER2 = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;\n\n bytes32 constant USDC_A_ILK = bytes32(\"USDC-A\");\n bytes32 constant ETH_A_ILK = bytes32(\"ETH-A\");\n\n // OneSplit Flags\n uint256 constant ONE_SPLIT_CURVE_ONLY_FLAGS = 3758411776;\n uint256 constant ONE_SPLIT_PARTS = 10;\n}\n" | |
}, | |
"contracts/curve/ICurveFiCurve.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.7.0;\n\ninterface ICurveFiCurve {\n function get_virtual_price() external view returns (uint256 out);\n\n function add_liquidity(uint256[2] calldata amounts, uint256 deadline)\n external;\n\n function get_dy(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256 out);\n\n function get_dy_underlying(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256 out);\n\n function exchange(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy\n ) external;\n\n function exchange(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n uint256 deadline\n ) external;\n\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy\n ) external;\n\n function exchange_underlying(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy,\n uint256 deadline\n ) external;\n\n function remove_liquidity(\n uint256 _amount,\n uint256 deadline,\n uint256[2] calldata min_amounts\n ) external;\n\n function remove_liquidity_imbalance(\n uint256[2] calldata amounts,\n uint256 deadline\n ) external;\n\n function commit_new_parameters(\n int128 amplification,\n int128 new_fee,\n int128 new_admin_fee\n ) external;\n\n function apply_new_parameters() external;\n\n function revert_new_parameters() external;\n\n function commit_transfer_ownership(address _owner) external;\n\n function apply_transfer_ownership() external;\n\n function revert_transfer_ownership() external;\n\n function withdraw_admin_fees() external;\n\n function coins(int128 arg0) external returns (address out);\n\n function underlying_coins(int128 arg0) external returns (address out);\n\n function balances(int128 arg0) external returns (uint256 out);\n\n function A() external returns (int128 out);\n\n function fee() external returns (int128 out);\n\n function admin_fee() external returns (int128 out);\n\n function owner() external returns (address out);\n\n function admin_actions_deadline() external returns (uint256 out);\n\n function transfer_ownership_deadline() external returns (uint256 out);\n\n function future_A() external returns (int128 out);\n\n function future_fee() external returns (int128 out);\n\n function future_admin_fee() external returns (int128 out);\n\n function future_owner() external returns (address out);\n}\n" | |
}, | |
"contracts/maker/IDSProxy.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.7.0;\n\ninterface IDSProxy {\n function authority() external view returns (address);\n\n function cache() external view returns (address);\n\n function execute(address _target, bytes calldata _data)\n external\n payable\n returns (bytes memory response);\n\n function execute(bytes calldata _code, bytes calldata _data)\n external\n payable\n returns (address target, bytes memory response);\n\n function owner() external view returns (address);\n\n function setAuthority(address authority_) external;\n\n function setCache(address _cacheAddr) external returns (bool);\n\n function setOwner(address owner_) external;\n}\n" | |
}, | |
"contracts/maker/IGetCdps.sol": { | |
"content": "// SPDX-License-Identifier: MIT\n// Address: 0x36a724Bd100c39f0Ea4D3A20F7097eE01A8Ff573\npragma solidity >=0.6.0 <0.7.0;\n\ninterface IGetCdps {\n function getCdpsAsc(address manager, address guy)\n external\n view\n returns (\n uint256[] memory ids,\n address[] memory urns,\n bytes32[] memory ilks\n );\n\n function getCdpsDesc(address manager, address guy)\n external\n view\n returns (\n uint256[] memory ids,\n address[] memory urns,\n bytes32[] memory ilks\n );\n}\n" | |
}, | |
"contracts/maker/IProxyRegistry.sol": { | |
"content": "// SPDX-License-Identifier: MIT\n// Address: 0x4678f0a6958e4D2Bc4F1BAF7Bc52E8F3564f3fE4\npragma solidity >=0.6.0 <0.7.0;\n\ninterface IProxyRegistry {\n function build() external returns (address proxy);\n\n function proxies(address) external view returns (address);\n\n function build(address owner) external returns (address proxy);\n}\n" | |
}, | |
"contracts/Migrations.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.21 <0.7.0;\n\ncontract Migrations {\n address public owner;\n uint public last_completed_migration;\n\n constructor() public {\n owner = msg.sender;\n }\n\n modifier restricted() {\n if (msg.sender == owner) _;\n }\n\n function setCompleted(uint completed) public restricted {\n last_completed_migration = completed;\n }\n}\n" | |
}, | |
"contracts/onesplit/IOneSplit.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.7.0;\n\ninterface IOneSplit {\n function getExpectedReturn(\n address fromToken,\n address destToken,\n uint256 amount,\n uint256 parts,\n uint256 flags // See constants in IOneSplit.sol\n )\n external\n view\n returns (uint256 returnAmount, uint256[] memory distribution);\n\n function swap(\n address fromToken,\n address destToken,\n uint256 amount,\n uint256 minReturn,\n uint256[] calldata distribution,\n uint256 flags\n ) external payable returns (uint256 returnAmount);\n}\n" | |
}, | |
"contracts/OpenShortDAI.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.7.0;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./onesplit/IOneSplit.sol\";\n\nimport \"./weth/WETH.sol\";\n\nimport \"./dydx/DydxFlashloanBase.sol\";\nimport \"./dydx/IDydx.sol\";\n\nimport \"./maker/IDssCdpManager.sol\";\nimport \"./maker/IDssProxyActions.sol\";\nimport \"./maker/DssActionsBase.sol\";\n\nimport \"./curve/ICurveFiCurve.sol\";\n\nimport \"./Constants.sol\";\n\ncontract OpenShortDAI is ICallee, DydxFlashloanBase, DssActionsBase {\n // LeveragedShortDAI Params\n struct OSDParams {\n uint256 cdpId; // CDP Id to leverage\n uint256 mintAmountDAI; // Amount of DAI to mint\n uint256 flashloanAmountWETH; // Amount of WETH flashloaned\n address curvePool;\n }\n\n function callFunction(\n address sender,\n Account.Info memory account,\n bytes memory data\n ) public override {\n OSDParams memory osdp = abi.decode(data, (OSDParams));\n\n // Step 1. Have Flashloaned WETH\n // Open WETH CDP in Maker, then Mint out some DAI\n uint256 wethCdp = _openLockGemAndDraw(\n Constants.MCD_JOIN_ETH_A,\n Constants.ETH_A_ILK,\n osdp.flashloanAmountWETH,\n osdp.mintAmountDAI\n );\n\n // Step 2.\n // Converts Flashloaned DAI to USDC on CurveFi\n // DAI = 0 index, USDC = 1 index\n // require(\n // IERC20(Constants.DAI).approve(osdp.curvePool, osdp.mintAmountDAI),\n // \"!curvepool-approved\"\n // );\n // ICurveFiCurve(osdp.curvePool).exchange_underlying(\n // int128(0),\n // int128(1),\n // osdp.mintAmountDAI,\n // 0\n // );\n IOneSplit oneSplit = IOneSplit(\n 0xC586BeF4a0992C495Cf22e1aeEE4E446CECDee0E\n );\n (uint256 returnAmount, uint256[] memory distribution) = oneSplit\n .getExpectedReturn(\n Constants.DAI,\n Constants.USDC,\n osdp.mintAmountDAI,\n Constants.ONE_SPLIT_PARTS,\n Constants.ONE_SPLIT_CURVE_ONLY_FLAGS\n );\n oneSplit.swap(\n Constants.DAI,\n Constants.USDC,\n osdp.mintAmountDAI,\n 0,\n distribution,\n Constants.ONE_SPLIT_CURVE_ONLY_FLAGS\n );\n\n // Step 3.\n // Locks up USDC and borrow just enough DAI to repay WETH CDP\n uint256 supplyAmount = IERC20(Constants.USDC).balanceOf(address(this));\n _lockGemAndDraw(\n Constants.MCD_JOIN_USDC_A,\n osdp.cdpId,\n supplyAmount,\n osdp.mintAmountDAI\n );\n\n // Step 4.\n // Repay DAI loan back to WETH CDP and FREE WETH\n _wipeAllAndFreeGem(\n Constants.MCD_JOIN_ETH_A,\n wethCdp,\n osdp.flashloanAmountWETH\n );\n }\n\n function flashloanAndOpen(\n address _sender,\n address _solo,\n address _curvePool,\n uint256 _cdpId,\n uint256 _initialMarginUSDC,\n uint256 _mintAmountDAI,\n uint256 _flashloanAmountWETH\n ) external payable {\n require(msg.value == 2, \"!fee\");\n\n require(\n IERC20(Constants.WETH).balanceOf(_solo) >= _flashloanAmountWETH,\n \"!weth-supply\"\n );\n\n // Gets USDC\n require(\n IERC20(Constants.USDC).transferFrom(\n msg.sender,\n address(this),\n _initialMarginUSDC\n ),\n \"initial-margin-transferFrom-failed\"\n );\n\n ISoloMargin solo = ISoloMargin(_solo);\n\n // Get marketId from token address\n uint256 marketId = _getMarketIdFromTokenAddress(_solo, Constants.WETH);\n\n // Wrap ETH into WETH\n WETH(Constants.WETH).deposit{value: msg.value}();\n WETH(Constants.WETH).approve(\n _solo,\n _flashloanAmountWETH.add(msg.value)\n );\n\n // 1. Withdraw $\n // 2. Call callFunction(...)\n // 3. Deposit back $\n Actions.ActionArgs[] memory operations = new Actions.ActionArgs[](3);\n\n operations[0] = _getWithdrawAction(marketId, _flashloanAmountWETH);\n operations[1] = _getCallAction(\n // Encode OSDParams for callFunction\n abi.encode(\n OSDParams({\n mintAmountDAI: _mintAmountDAI,\n flashloanAmountWETH: _flashloanAmountWETH,\n cdpId: _cdpId,\n curvePool: _curvePool\n })\n )\n );\n operations[2] = _getDepositAction(\n marketId,\n _flashloanAmountWETH.add(msg.value)\n );\n\n Account.Info[] memory accountInfos = new Account.Info[](1);\n accountInfos[0] = _getAccountInfo();\n\n solo.operate(accountInfos, operations);\n\n // Refund user any ERC20 leftover\n IERC20(Constants.DAI).transfer(\n _sender,\n IERC20(Constants.DAI).balanceOf(address(this))\n );\n IERC20(Constants.USDC).transfer(\n _sender,\n IERC20(Constants.USDC).balanceOf(address(this))\n );\n }\n}\n" | |
}, | |
"contracts/ShortDAIActions.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.7.0;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./dydx/DydxFlashloanBase.sol\";\nimport \"./dydx/IDydx.sol\";\n\nimport \"./maker/IDssCdpManager.sol\";\nimport \"./maker/IDssProxyActions.sol\";\nimport \"./maker/DssActionsBase.sol\";\n\nimport \"./OpenShortDAI.sol\";\nimport \"./CloseShortDAI.sol\";\nimport \"./VaultStats.sol\";\n\nimport \"./curve/ICurveFiCurve.sol\";\n\nimport \"./Constants.sol\";\n\ncontract ShortDAIActions {\n using SafeMath for uint256;\n\n function _openUSDCACdp() internal returns (uint256) {\n return\n IDssCdpManager(Constants.CDP_MANAGER).open(\n bytes32(\"USDC-A\"),\n address(this)\n );\n }\n\n // Entry point for proxy contracts\n function flashloanAndOpen(\n address _osd,\n address _solo,\n address _curvePool,\n uint256 _cdpId, // Set 0 for new vault\n uint256 _initialMarginUSDC, // Initial USDC margin\n uint256 _mintAmountDAI, // Amount of DAI to mint\n uint256 _flashloanAmountWETH, // Amount of WETH to flashloan\n address _vaultStats,\n uint256 _daiUsdcRatio6\n ) external payable {\n require(msg.value == 2, \"!fee\");\n\n // Tries and get USDC from msg.sender to proxy\n require(\n IERC20(Constants.USDC).transferFrom(\n msg.sender,\n address(this),\n _initialMarginUSDC\n ),\n \"initial-margin-transferFrom-failed\"\n );\n\n uint256 cdpId = _cdpId;\n\n // Opens a new USDC vault for the user if unspecified\n if (cdpId == 0) {\n cdpId = _openUSDCACdp();\n }\n\n // Allows LSD contract to manage vault on behalf of user\n IDssCdpManager(Constants.CDP_MANAGER).cdpAllow(cdpId, _osd, 1);\n\n // Approve OpenShortDAI Contract to use USDC funds\n require(\n IERC20(Constants.USDC).approve(_osd, _initialMarginUSDC),\n \"initial-margin-approve-failed\"\n );\n // Flashloan and shorts DAI\n OpenShortDAI(_osd).flashloanAndOpen{value: msg.value}(\n msg.sender,\n _solo,\n _curvePool,\n cdpId,\n _initialMarginUSDC,\n _mintAmountDAI,\n _flashloanAmountWETH\n );\n\n // Forbids LSD contract to manage vault on behalf of user\n IDssCdpManager(Constants.CDP_MANAGER).cdpAllow(cdpId, _osd, 0);\n\n // Save stats\n VaultStats(_vaultStats).setDaiUsdcRatio6(cdpId, _daiUsdcRatio6);\n }\n\n function flashloanAndClose(\n address _csd,\n address _solo,\n address _curvePool,\n uint256 _cdpId,\n uint256 _ethUsdRatio18\n ) external payable {\n require(msg.value == 2, \"!fee\");\n\n IDssCdpManager(Constants.CDP_MANAGER).cdpAllow(_cdpId, _csd, 1);\n\n CloseShortDAI(_csd).flashloanAndClose{value: msg.value}(\n msg.sender,\n _solo,\n _curvePool,\n _cdpId,\n _ethUsdRatio18\n );\n\n IDssCdpManager(Constants.CDP_MANAGER).cdpAllow(_cdpId, _csd, 0);\n IDssCdpManager(Constants.CDP_MANAGER).give(_cdpId, address(1));\n }\n\n function cdpAllow(\n uint256 cdp,\n address usr,\n uint256 ok\n ) public {\n IDssCdpManager(Constants.CDP_MANAGER).cdpAllow(cdp, usr, ok);\n }\n}\n" | |
}, | |
"contracts/VaultStats.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.7.0;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport \"./maker/IDssCdpManager.sol\";\nimport \"./maker/IDssProxyActions.sol\";\nimport \"./maker/DssActionsBase.sol\";\n\nimport \"./Constants.sol\";\n\ncontract VaultStats {\n uint256 constant RAY = 10**27;\n\n using SafeMath for uint256;\n\n // CDP ID => DAI/USDC Ratio in 6 decimals\n // i.e. What was DAI/USDC ratio when CDP was opened\n mapping(uint256 => uint256) public daiUsdcRatio6;\n\n //** View functions for stats ** //\n\n function _getCdpSuppliedAndBorrowed(\n address vat,\n address usr,\n address urn,\n bytes32 ilk\n ) internal view returns (uint256, uint256) {\n // Gets actual rate from the vat\n (, uint256 rate, , , ) = VatLike(vat).ilks(ilk);\n // Gets actual art value of the urn\n (uint256 supplied, uint256 art) = VatLike(vat).urns(ilk, urn);\n // Gets actual dai amount in the urn\n uint256 dai = VatLike(vat).dai(usr);\n\n uint256 rad = art.mul(rate).sub(dai);\n uint256 wad = rad / RAY;\n\n // If the rad precision has some dust, it will need to request for 1 extra wad wei\n uint256 borrowed = wad.mul(RAY) < rad ? wad + 1 : wad;\n\n // Note that supplied is in 18 decimals, so you'll need to convert it back\n // i.e. supplied = supplied / 10 ** (18 - decimals)\n\n return (supplied, borrowed);\n }\n\n // Get DAI borrow / supply stats\n function getCdpStats(uint256 cdp)\n public\n view\n returns (\n uint256,\n uint256,\n uint256\n )\n {\n address vat = IDssCdpManager(Constants.CDP_MANAGER).vat();\n address urn = IDssCdpManager(Constants.CDP_MANAGER).urns(cdp);\n bytes32 ilk = IDssCdpManager(Constants.CDP_MANAGER).ilks(cdp);\n address usr = IDssCdpManager(Constants.CDP_MANAGER).owns(cdp);\n\n (uint256 supplied, uint256 borrowed) = _getCdpSuppliedAndBorrowed(\n vat,\n usr,\n urn,\n ilk\n );\n\n uint256 ratio = daiUsdcRatio6[cdp];\n\n // Note that supplied and borrowed are in 18 decimals\n // while DAI USDC ratio is in 6 decimals\n return (supplied, borrowed, ratio);\n }\n\n function setDaiUsdcRatio6(uint256 _cdp, uint256 _daiUsdcRatio6) public {\n IDssCdpManager manager = IDssCdpManager(Constants.CDP_MANAGER);\n address owner = manager.owns(_cdp);\n\n require(\n owner == msg.sender || manager.cdpCan(owner, _cdp, msg.sender) == 1,\n \"cdp-not-allowed\"\n );\n\n daiUsdcRatio6[_cdp] = _daiUsdcRatio6;\n }\n}\n" | |
}, | |
"contracts/uniswapv2/UniswapRouterV2.sol": { | |
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.2;\n\ninterface UniswapRouterV2 {\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n );\n\n function removeLiquidity(\n address tokenA,\n address tokenB,\n uint256 liquidity,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n ) external returns (uint256 amountA, uint256 amountB);\n\n function getAmountsOut(uint256 amountIn, address[] calldata path)\n external\n view\n returns (uint256[] memory amounts);\n\n function getAmountsIn(uint256 amountOut, address[] calldata path)\n external\n view\n returns (uint256[] memory amounts);\n\n function swapETHForExactTokens(\n uint256 amountOut,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external payable returns (uint256[] memory amounts);\n}\n\ninterface UniswapPair {\n function getReserves()\n external\n view\n returns (\n uint112 reserve0,\n uint112 reserve1,\n uint32 blockTimestamp\n );\n}\n" | |
} | |
}, | |
"settings": { | |
"metadata": { | |
"useLiteralContent": true | |
}, | |
"optimizer": { | |
"enabled": true, | |
"runs": 200 | |
}, | |
"outputSelection": { | |
"*": { | |
"*": [ | |
"abi", | |
"evm.bytecode", | |
"evm.deployedBytecode", | |
"evm.methodIdentifiers" | |
], | |
"": [ | |
"id", | |
"ast" | |
] | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment