# Protocol Controlled Liquidity - POO testnet ----------------------------------- [TOC] ## Attention: DeadLine: 12-17 ### Execute Strategy Install packages: ``` npm install ``` or ``` yarn ``` rollup the script: ``` npx rollup script/dForceOperator.js -o script/remix.js -m cjs ``` run the task you want by running generated `script/remix.js` in remix **reminder: To rerun the `rollup` to regenerate the runnable script for remix every time after modifications to the original script** eg: to run the `swapAndAddLiquidity` task in the end of file `script/remix.js` ``` // run(task, deploy); // run(task, upgrade); run(task, swapAndAddLiquidity); // run(task, removeLiquidityAndSwap); //# sourceMappingURL=remix.js.map ``` ## Frontend Integration ### The contracts on Rinkeby: | Contract Name | Contract Address | | --------------------- | :----------------------------------------- | | USX | 0xb0b7eC7a4583c7511C8f90715245f08Ce0E111fd | | DF | 0xb5a827CFd5eDcCC3f43f9dBbab174c8289688058 | | MSD Controller | 0xf473550a0987e33394A4868754ec89d18cDa022f | | MockVault | 0xc2e6D757b1A0edFA90BF0Ce412C78321fC21f50b | | vaultDForce | 0xC6d76E0706f3F75a13441Fc66A87D76C17BA6E70 | | DODO Maker | 0xF39A9AC259ef0d83A884Bc01f3a993D47b8Aa155 | | DODO Trader | 0xAB86F7259de3a4D65E4cc79d46d06b9BC58AC18d | | OperatorImpl | 0x6005cA02F96B02501C45e39124026daFb9eAD00A | | Operator | 0x9Fd0b6668933f4FBc6b3897506DC70E147dfcf99 | | Swap Add Liquidity | 0x30aB1041306B11360a72eBDb0e011135AB619486 | | Remove Liquidity Swap | 0x0fb0c39257163B871C6ce191fB07430dD0a347C0 | | DODO Approve | 0xcC8d87A7C747eeE4242045C47Ef25e0A81D56ae3 | | DODO Proxy | 0xba001E96AF87bF9d8D0BDA667067A9921FE6d294 | ### ABIs #### The Debt Ceiling ``` MSDController.mintCaps(USX, MockVault); ``` ``` { "inputs": [ { "internalType": "address", "name": "", "type": "address" }, { "internalType": "address", "name": "", "type": "address" } ], "name": "mintCaps", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, ``` #### Current Debt ``` MockVault.totalMint() ``` ``` { "inputs": [], "name": "totalMint", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "nonpayable", "type": "function" } ``` #### Events - Operator.AddLiquidity - Operator.RemoveLiquidity - Operator.Swap ``` { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "string", "name": "name", "type": "string" }, { "indexed": false, "internalType": "address", "name": "LPAddress", "type": "address" }, { "indexed": false, "internalType": "address", "name": "baseToken", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "baseAmountIn", "type": "uint256" }, { "indexed": false, "internalType": "address", "name": "quoteToken", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "quoteAmountIn", "type": "uint256" }, { "indexed": false, "internalType": "uint256", "name": "shareAmountOut", "type": "uint256" } ], "name": "AddLiquidity", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "string", "name": "name", "type": "string" }, { "indexed": false, "internalType": "address", "name": "LPAddress", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "shareAmountIn", "type": "uint256" }, { "indexed": false, "internalType": "address", "name": "baseToken", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "baseAmountOut", "type": "uint256" }, { "indexed": false, "internalType": "address", "name": "quoteToken", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "quoteAmountOut", "type": "uint256" } ], "name": "RemoveLiquidity", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "internalType": "string", "name": "name", "type": "string" }, { "indexed": false, "internalType": "address", "name": "fromToken", "type": "address" }, { "indexed": false, "internalType": "address", "name": "toToken", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "amountIn", "type": "uint256" }, { "indexed": false, "internalType": "uint256", "name": "amountOut", "type": "uint256" } ], "name": "Swap", "type": "event" }, ``` ## TODO - [x] Extend `vault` into a module for Liqee - [ ] Now only the owner can execute strategy, and the caller can set all the parameters to pass, so if later, this function becomes public that everyone can call it, maybe it is not safe, cause we can not ensure he/she pass the parameters like we want such as the token address(it should be USX, DF rather than any other address) (Skyge) - [x] Pass external addresses as contructor parameters for different networks. Currently such addresses like DODOV2Proxy is hardcoded as constant - [ ] Strategy logic, now such logic is implemented externally only - [ ] Buy DF and add liquidity - [ ] the USX amount to buy - [ ] the amount of USX to buy DF, the minOutAmount of DF - [ ] the amount of USX and DF to add liquidity - [ ] Remove liquidity and sell DF - [ ] the amount of USX and DF to remove liquidity from - [ ] the USX amount to repay - [ ] the requested amount of DF to buy the exact amount of USX - [ ] Paramenters check for maker/trader - [ ] There are chances that the EOA call can pass wrong parameter to strategy/maker/trader - [ ] When try to remove a `maker` which still holds some liquidity - [ ] To `revert` to prevent removing or - [ ] To remove liquidity in `deactivate` for maker - [ ] Test cases - [x] traders, makers, strategies storage - [x] Currently array, should EnumerableSet/Map be used? - [x] to remove traders/makers/strategies - [x] Events - [x] Events for all setters - [x] Events for all actions for external backend service, such as `swap/addLiquidity/removeLiquidity` - [ ] Events for `Borrow/Repay/Deposit/Withdraw` - [x] Access controls - [x] To use OpenZepplin's `delegatecall` library - [ ] Code style clean up ## Overview operator holds DF => mint USX by demands => buy back DF => supply liquidity(USX/DF) (Eg: Uniswap V2 on Mainnet) *liquidity bond*, allow user buy DF by LP or stablecoin with a discount (vDF holder with bigger discount, maybe!) **Reference** - safeMoon Token: https://github.com/safemoonprotocol/Safemoon.sol/blob/main/Safemoon.sol ## Flow Chart ![](https://hackmd.io/_uploads/BJGproNYY.png) ## Operator `Operator` is the main entity to interact with other system, and it holds all funds including `USX` and `DF`. EOA users can trigger `Operator`'s predefined strategies. ## Vault Typically it is a dForce `Vault` which allow `operator` to use its `DF` as credit to borrow `USX`. ## Strategy A series of predefined operations to execute, typically it - borrows `USX` from `vault` - trades `USX` for `DF` via `traders` - adds `USX` and `DF` liquidity via `makers` ## Trader A handler to interact with external trade protocols. Actions: - swapExactTokensForTokens - swapTokensForExactTokens Queries: TBD ## Maker A handler to interact with external liquidity protocols Actions: - addLiquidity - removeLiquidity Queries: TBD