├── .gitattributes ├── .gitignore ├── README.md ├── abi ├── controller.json ├── crvdeposit.json ├── ivault.json ├── strategy.json └── vault.json ├── bscpd ├── strategy │ ├── bnb.sol │ ├── busd.sol │ ├── eth.sol │ └── usdt.sol └── vault │ ├── bnb.sol │ ├── busd.sol │ ├── eth.sol │ └── usdt.sol ├── contracts ├── Controller.sol ├── SHRIMP │ ├── GRAPYFIIPool.sol │ └── SHRIMPETHPool.sol ├── crv │ ├── StrategyCRV.sol │ └── yvault.sol ├── crvContract │ ├── bcrvGauge.vy │ ├── cCrvGauge.vy │ ├── scrvGauge.vy │ └── ycrvGauge.vy ├── dforce │ ├── usdtpool.sol │ └── usdxusdclp.sol ├── grap │ ├── GRAPCOMPPool.sol │ ├── GRAPETHPool.sol │ ├── GRAPLENDPool.sol │ ├── GRAPLINKPool.sol │ ├── GRAPSNXPool.sol │ └── GRAPYFIIPool.sol ├── harvest │ ├── gxbyfii.sol │ ├── lafei.sol │ ├── sushi.sol │ ├── timelock1.sol │ ├── vodka.sol │ └── yfiiyearn.sol ├── i │ ├── idepoist.vy │ ├── iswap.vy │ ├── iusd.vy │ ├── readme.md │ ├── ycrv.vy │ ├── ydepoist.vy │ └── yswap.vy ├── readme.md ├── standard │ ├── Controller.sol │ ├── StrategyCRV.sol │ ├── StrategyCRV_COMPLP.sol │ ├── StrategyDForce.sol │ ├── StrategyGrap.sol │ ├── StrategyYFII.sol │ ├── StrategyYam.sol │ ├── StrategyZOMBIE.sol │ ├── YFIIStrategy.sol │ ├── YfiiVault.sol │ ├── config.json │ ├── readme.md │ ├── v2 │ │ ├── StrategyCurveYCRVVoter.sol │ │ ├── apy.json │ │ ├── bsc │ │ │ ├── fordeploy.sol │ │ │ ├── strategyFor.sol │ │ │ ├── strategyForBNB.sol │ │ │ ├── vault.sol │ │ │ └── vaultBNB.sol │ │ ├── bscconfig.json │ │ ├── config.json │ │ ├── mefi-mefilp.sol │ │ ├── mefi-yfiilp.sol │ │ ├── pool4.sol │ │ ├── pool5.sol │ │ ├── readme.md │ │ ├── strategy.sol │ │ ├── strategyCRV_BUSD.sol │ │ ├── strategyCRV_SBTC.sol │ │ ├── strategyDfoorceDAI.sol │ │ ├── strategyDfoorceUSDT.sol │ │ ├── strategyFor.sol │ │ ├── strategyForETH.sol │ │ ├── strategyForHBTC.sol │ │ ├── testinpord.json │ │ ├── vault.sol │ │ └── vaultETH.sol │ └── yvault.sol ├── t │ ├── swap.sol │ └── swap1.sol ├── uniswapHelper.sol ├── yam │ ├── yamContract │ │ ├── YAMAMPLPool.sol │ │ ├── YAMCOMPPool.sol │ │ ├── YAMLENDPool.sol │ │ ├── YAMLINKPool.sol │ │ ├── YAMMKRPool.sol │ │ ├── YAMSNXPool.sol │ │ ├── YAMWETHPool.sol │ │ └── YAMYFIPool.sol │ ├── yamcomp │ │ ├── StrategyCompYam.sol │ │ └── yvault.sol │ ├── yamsnx │ │ ├── StrategySNXYam.sol │ │ └── yvault.sol │ ├── yamstandard │ │ ├── StrategySNXYam.sol │ │ └── yvault.sol │ └── yamweth │ │ ├── StrategyWETHYam.sol │ │ └── yvault.sol ├── yfiiVoterProxy.sol ├── yfiicontract.sol ├── yfiipool1 │ ├── StrategyCurveYfii.sol │ └── yvault.sol └── yfiipool2 │ ├── StrategyYfiiPool2.sol │ ├── readme.md │ └── yvault.sol ├── pd ├── strategies │ ├── Uniswap-ETH-DAI-LP.sol │ ├── Uniswap-ETH-USDC-LP.sol │ ├── Uniswap-ETH-USDT-LP.sol │ ├── Uniswap-ETH-WBTC.sol │ ├── busd.sol │ ├── dai.sol │ ├── eth.sol │ ├── hbtc.sol │ ├── husd3crv.sol │ ├── tusd.sol │ ├── usdc.sol │ ├── usdt.sol │ └── ycrv.sol └── vaults │ ├── i-Uniswap-ETH-DAI-LP.sol │ ├── i-Uniswap-ETH-USDC-LP.sol │ ├── i-Uniswap-ETH-USDT-LP.sol │ ├── i-Uniswap-ETH-WBTC-LP.sol │ ├── idai.sol │ ├── ihusd3crv.sol │ ├── itusd.sol │ ├── iusdt.sol │ └── iycrv.sol ├── py ├── cal.py ├── deploy.py └── getClaimAbleTokens.py ├── sushi ├── hotdot.sol └── sushi.sol └── truffle-config.js /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/solidity,soliditytruffle 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=solidity,soliditytruffle 4 | 5 | ### Solidity ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # TypeScript v1 declaration files 50 | typings/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Microbundle cache 62 | .rpt2_cache/ 63 | .rts2_cache_cjs/ 64 | .rts2_cache_es/ 65 | .rts2_cache_umd/ 66 | 67 | # Optional REPL history 68 | .node_repl_history 69 | 70 | # Output of 'npm pack' 71 | *.tgz 72 | 73 | # Yarn Integrity file 74 | .yarn-integrity 75 | 76 | # dotenv environment variables file 77 | .env 78 | .env.test 79 | 80 | # parcel-bundler cache (https://parceljs.org/) 81 | .cache 82 | 83 | # Next.js build output 84 | .next 85 | 86 | # Nuxt.js build / generate output 87 | .nuxt 88 | dist 89 | 90 | # Gatsby files 91 | .cache/ 92 | # Comment in the public line in if your project uses Gatsby and not Next.js 93 | # https://nextjs.org/blog/next-9-1#public-directory-support 94 | # public 95 | 96 | # vuepress build output 97 | .vuepress/dist 98 | 99 | # Serverless directories 100 | .serverless/ 101 | 102 | # FuseBox cache 103 | .fusebox/ 104 | 105 | # DynamoDB Local files 106 | .dynamodb/ 107 | 108 | # TernJS port file 109 | .tern-port 110 | 111 | # Stores VSCode versions used for testing VSCode extensions 112 | .vscode-test 113 | 114 | ### SolidityTruffle ### 115 | # depedencies 116 | node_modules 117 | 118 | # testing 119 | 120 | # production 121 | build 122 | build_webpack 123 | 124 | # misc 125 | .DS_Store 126 | npm-debug.log 127 | .truffle-solidity-loader 128 | .vagrant/** 129 | blockchain/geth/** 130 | blockchain/keystore/** 131 | blockchain/history 132 | 133 | #truffle 134 | yarn.lock 135 | package-lock.json 136 | 137 | # End of https://www.toptal.com/developers/gitignore/api/solidity,soliditytruffle 138 | 139 | # Created by https://www.toptal.com/developers/gitignore/api/soliditytruffle 140 | # Edit at https://www.toptal.com/developers/gitignore?templates=soliditytruffle 141 | 142 | ### SolidityTruffle ### 143 | # depedencies 144 | node_modules 145 | 146 | # testing 147 | coverage 148 | 149 | # production 150 | build 151 | build_webpack 152 | 153 | # misc 154 | .DS_Store 155 | .env 156 | npm-debug.log 157 | .truffle-solidity-loader 158 | .vagrant/** 159 | blockchain/geth/** 160 | blockchain/keystore/** 161 | blockchain/history 162 | 163 | #truffle 164 | .tern-port 165 | yarn.lock 166 | package-lock.json 167 | 168 | # End of https://www.toptal.com/developers/gitignore/api/soliditytruffle 169 | 170 | # Created by https://www.toptal.com/developers/gitignore/api/solidity 171 | # Edit at https://www.toptal.com/developers/gitignore?templates=solidity 172 | 173 | ### Solidity ### 174 | # Logs 175 | logs 176 | *.log 177 | npm-debug.log* 178 | yarn-debug.log* 179 | yarn-error.log* 180 | lerna-debug.log* 181 | 182 | # Diagnostic reports (https://nodejs.org/api/report.html) 183 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 184 | 185 | # Runtime data 186 | pids 187 | *.pid 188 | *.seed 189 | *.pid.lock 190 | 191 | # Directory for instrumented libs generated by jscoverage/JSCover 192 | lib-cov 193 | 194 | # Coverage directory used by tools like istanbul 195 | coverage 196 | *.lcov 197 | 198 | # nyc test coverage 199 | .nyc_output 200 | 201 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 202 | .grunt 203 | 204 | # Bower dependency directory (https://bower.io/) 205 | bower_components 206 | 207 | # node-waf configuration 208 | .lock-wscript 209 | 210 | # Compiled binary addons (https://nodejs.org/api/addons.html) 211 | build/Release 212 | 213 | # Dependency directories 214 | node_modules/ 215 | jspm_packages/ 216 | 217 | # TypeScript v1 declaration files 218 | typings/ 219 | 220 | # TypeScript cache 221 | *.tsbuildinfo 222 | 223 | # Optional npm cache directory 224 | .npm 225 | 226 | # Optional eslint cache 227 | .eslintcache 228 | 229 | # Microbundle cache 230 | .rpt2_cache/ 231 | .rts2_cache_cjs/ 232 | .rts2_cache_es/ 233 | .rts2_cache_umd/ 234 | 235 | # Optional REPL history 236 | .node_repl_history 237 | 238 | # Output of 'npm pack' 239 | *.tgz 240 | 241 | # Yarn Integrity file 242 | .yarn-integrity 243 | 244 | # dotenv environment variables file 245 | .env 246 | .env.test 247 | 248 | # parcel-bundler cache (https://parceljs.org/) 249 | .cache 250 | 251 | # Next.js build output 252 | .next 253 | 254 | # Nuxt.js build / generate output 255 | .nuxt 256 | dist 257 | 258 | # Gatsby files 259 | .cache/ 260 | # Comment in the public line in if your project uses Gatsby and not Next.js 261 | # https://nextjs.org/blog/next-9-1#public-directory-support 262 | # public 263 | 264 | # vuepress build output 265 | .vuepress/dist 266 | 267 | # Serverless directories 268 | .serverless/ 269 | 270 | # FuseBox cache 271 | .fusebox/ 272 | 273 | # DynamoDB Local files 274 | .dynamodb/ 275 | 276 | # TernJS port file 277 | .tern-port 278 | 279 | # Stores VSCode versions used for testing VSCode extensions 280 | .vscode-test 281 | 282 | # End of https://www.toptal.com/developers/gitignore/api/solidity 283 | 284 | # Created by https://www.toptal.com/developers/gitignore/api/python 285 | # Edit at https://www.toptal.com/developers/gitignore?templates=python 286 | 287 | ### Python ### 288 | # Byte-compiled / optimized / DLL files 289 | __pycache__/ 290 | *.py[cod] 291 | *$py.class 292 | 293 | # C extensions 294 | *.so 295 | 296 | # Distribution / packaging 297 | .Python 298 | build/ 299 | develop-eggs/ 300 | dist/ 301 | downloads/ 302 | eggs/ 303 | .eggs/ 304 | lib/ 305 | lib64/ 306 | parts/ 307 | sdist/ 308 | var/ 309 | wheels/ 310 | pip-wheel-metadata/ 311 | share/python-wheels/ 312 | *.egg-info/ 313 | .installed.cfg 314 | *.egg 315 | MANIFEST 316 | 317 | # PyInstaller 318 | # Usually these files are written by a python script from a template 319 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 320 | *.manifest 321 | *.spec 322 | 323 | # Installer logs 324 | pip-log.txt 325 | pip-delete-this-directory.txt 326 | 327 | # Unit test / coverage reports 328 | htmlcov/ 329 | .tox/ 330 | .nox/ 331 | .coverage 332 | .coverage.* 333 | .cache 334 | nosetests.xml 335 | coverage.xml 336 | *.cover 337 | *.py,cover 338 | .hypothesis/ 339 | .pytest_cache/ 340 | pytestdebug.log 341 | 342 | # Translations 343 | *.mo 344 | *.pot 345 | 346 | # Django stuff: 347 | *.log 348 | local_settings.py 349 | db.sqlite3 350 | db.sqlite3-journal 351 | 352 | # Flask stuff: 353 | instance/ 354 | .webassets-cache 355 | 356 | # Scrapy stuff: 357 | .scrapy 358 | 359 | # Sphinx documentation 360 | docs/_build/ 361 | doc/_build/ 362 | 363 | # PyBuilder 364 | target/ 365 | 366 | # Jupyter Notebook 367 | .ipynb_checkpoints 368 | 369 | # IPython 370 | profile_default/ 371 | ipython_config.py 372 | 373 | # pyenv 374 | .python-version 375 | 376 | # pipenv 377 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 378 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 379 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 380 | # install all needed dependencies. 381 | #Pipfile.lock 382 | 383 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 384 | __pypackages__/ 385 | 386 | # Celery stuff 387 | celerybeat-schedule 388 | celerybeat.pid 389 | 390 | # SageMath parsed files 391 | *.sage.py 392 | 393 | # Environments 394 | .env 395 | .venv 396 | env/ 397 | venv/ 398 | ENV/ 399 | env.bak/ 400 | venv.bak/ 401 | 402 | # Spyder project settings 403 | .spyderproject 404 | .spyproject 405 | 406 | # Rope project settings 407 | .ropeproject 408 | 409 | # mkdocs documentation 410 | /site 411 | 412 | # mypy 413 | .mypy_cache/ 414 | .dmypy.json 415 | dmypy.json 416 | 417 | # Pyre type checker 418 | .pyre/ 419 | 420 | # pytype static type analyzer 421 | .pytype/ 422 | 423 | # End of https://www.toptal.com/developers/gitignore/api/python 424 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## yVault 2 | 3 | 环境... 4 | solc 0.5.15 5 | 6 | ```shell 7 | brew install solidity@5 8 | ``` 9 | 10 | python 3 11 | 12 | `pip install web3` 13 | 14 | [ganache-cli](https://github.com/trufflesuite/ganache-cli) 15 | 16 | 目前生产合约都在 **contracts/standard**下面 17 | 18 | 19 | 20 | 21 | ## 机器池介绍 22 | 23 | 机枪池由3部分组成 24 | 25 | Controller、vault、Strategy 26 | 27 | Controller的作用是设置某个代币对应的vault以及Strategy 28 | 29 | vault的作用是 用户充值,提现,领取奖励 30 | 31 | Strategy的作用是 把用户充值的币接入各种收益率高的地方挖矿(Strategy是可以切换的) 32 | 33 | 生产用的合约在 [合约配置](https://raw.githubusercontent.com/yfii/yvault/master/contracts/standard/config.json) 34 | 35 | abi文件参考 [vault](abi/vault.json) 36 | abi文件参考 [Strategy](abi/strategy.json) 37 | 38 | ## abi 39 | 40 | ### 操作 41 | `function deposit(uint amount)` 用户入金 需要先对vault合约进行代币授权 42 | 43 | `function withdraw(uint amount)` 用户提现 44 | 45 | ### 读 46 | 47 | `function balanceOf(address user) public view returns (uint256)` 查看用户有的iToken数量 48 | 49 | `function getPricePerFullShare() public view returns (uint)` 查看每个iToken换回原来token的比例 50 | 51 | 这边返回的值需要 除以1e18 52 | 53 | 可以换回原来代币的数量为: 用户持有的iToken数量*getPricePerFullShare/1e18 54 | 55 | -------------------------------------------------------------------------------- /abi/controller.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"_rewards","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_strategy","type":"address"}],"name":"approveStrategy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"approvedStrategies","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"converters","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"earn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"parts","type":"uint256"}],"name":"getExpectedReturn","outputs":[{"internalType":"uint256","name":"expected","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"address","name":"_token","type":"address"}],"name":"inCaseStrategyTokenGetStuck","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"inCaseTokensGetStuck","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"max","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"onesplit","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_strategy","type":"address"}],"name":"revokeStrategy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rewards","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_input","type":"address"},{"internalType":"address","name":"_output","type":"address"},{"internalType":"address","name":"_converter","type":"address"}],"name":"setConverter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_governance","type":"address"}],"name":"setGovernance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_onesplit","type":"address"}],"name":"setOneSplit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rewards","type":"address"}],"name":"setRewards","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_split","type":"uint256"}],"name":"setSplit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_strategist","type":"address"}],"name":"setStrategist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_strategy","type":"address"}],"name":"setStrategy","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address","name":"_vault","type":"address"}],"name":"setVault","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"split","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"strategies","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"strategist","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"vaults","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"withdrawAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_strategy","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"parts","type":"uint256"}],"name":"yearn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}] -------------------------------------------------------------------------------- /abi/crvdeposit.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name": "Deposit", 3 | "inputs": [{ 4 | "type": "address", 5 | "name": "provider", 6 | "indexed": true 7 | }, { 8 | "type": "uint256", 9 | "name": "value", 10 | "indexed": false 11 | }], 12 | "anonymous": false, 13 | "type": "event" 14 | }, { 15 | "name": "Withdraw", 16 | "inputs": [{ 17 | "type": "address", 18 | "name": "provider", 19 | "indexed": true 20 | }, { 21 | "type": "uint256", 22 | "name": "value", 23 | "indexed": false 24 | }], 25 | "anonymous": false, 26 | "type": "event" 27 | }, { 28 | "name": "UpdateLiquidityLimit", 29 | "inputs": [{ 30 | "type": "address", 31 | "name": "user", 32 | "indexed": false 33 | }, { 34 | "type": "uint256", 35 | "name": "original_balance", 36 | "indexed": false 37 | }, { 38 | "type": "uint256", 39 | "name": "original_supply", 40 | "indexed": false 41 | }, { 42 | "type": "uint256", 43 | "name": "working_balance", 44 | "indexed": false 45 | }, { 46 | "type": "uint256", 47 | "name": "working_supply", 48 | "indexed": false 49 | }], 50 | "anonymous": false, 51 | "type": "event" 52 | }, { 53 | "outputs": [], 54 | "inputs": [{ 55 | "type": "address", 56 | "name": "lp_addr" 57 | }, { 58 | "type": "address", 59 | "name": "_minter" 60 | }], 61 | "stateMutability": "nonpayable", 62 | "type": "constructor" 63 | }, { 64 | "name": "user_checkpoint", 65 | "outputs": [{ 66 | "type": "bool", 67 | "name": "" 68 | }], 69 | "inputs": [{ 70 | "type": "address", 71 | "name": "addr" 72 | }], 73 | "stateMutability": "nonpayable", 74 | "type": "function", 75 | "gas": 2079152 76 | }, { 77 | "name": "claimable_tokens", 78 | "outputs": [{ 79 | "type": "uint256", 80 | "name": "" 81 | }], 82 | "inputs": [{ 83 | "type": "address", 84 | "name": "addr" 85 | }], 86 | "stateMutability": "view", 87 | "type": "function", 88 | "gas": 1998318 89 | }, { 90 | "name": "kick", 91 | "outputs": [], 92 | "inputs": [{ 93 | "type": "address", 94 | "name": "addr" 95 | }], 96 | "stateMutability": "nonpayable", 97 | "type": "function", 98 | "gas": 2084532 99 | }, { 100 | "name": "set_approve_deposit", 101 | "outputs": [], 102 | "inputs": [{ 103 | "type": "address", 104 | "name": "addr" 105 | }, { 106 | "type": "bool", 107 | "name": "can_deposit" 108 | }], 109 | "stateMutability": "nonpayable", 110 | "type": "function", 111 | "gas": 35766 112 | }, { 113 | "name": "deposit", 114 | "outputs": [], 115 | "inputs": [{ 116 | "type": "uint256", 117 | "name": "_value" 118 | }], 119 | "stateMutability": "nonpayable", 120 | "type": "function" 121 | }, { 122 | "name": "deposit", 123 | "outputs": [], 124 | "inputs": [{ 125 | "type": "uint256", 126 | "name": "_value" 127 | }, { 128 | "type": "address", 129 | "name": "addr" 130 | }], 131 | "stateMutability": "nonpayable", 132 | "type": "function" 133 | }, { 134 | "name": "withdraw", 135 | "outputs": [], 136 | "inputs": [{ 137 | "type": "uint256", 138 | "name": "_value" 139 | }], 140 | "stateMutability": "nonpayable", 141 | "type": "function", 142 | "gas": 2208318 143 | }, { 144 | "name": "integrate_checkpoint", 145 | "outputs": [{ 146 | "type": "uint256", 147 | "name": "" 148 | }], 149 | "inputs": [], 150 | "stateMutability": "view", 151 | "type": "function", 152 | "gas": 2297 153 | }, { 154 | "name": "minter", 155 | "outputs": [{ 156 | "type": "address", 157 | "name": "" 158 | }], 159 | "inputs": [], 160 | "stateMutability": "view", 161 | "type": "function", 162 | "gas": 1421 163 | }, { 164 | "name": "crv_token", 165 | "outputs": [{ 166 | "type": "address", 167 | "name": "" 168 | }], 169 | "inputs": [], 170 | "stateMutability": "view", 171 | "type": "function", 172 | "gas": 1451 173 | }, { 174 | "name": "lp_token", 175 | "outputs": [{ 176 | "type": "address", 177 | "name": "" 178 | }], 179 | "inputs": [], 180 | "stateMutability": "view", 181 | "type": "function", 182 | "gas": 1481 183 | }, { 184 | "name": "controller", 185 | "outputs": [{ 186 | "type": "address", 187 | "name": "" 188 | }], 189 | "inputs": [], 190 | "stateMutability": "view", 191 | "type": "function", 192 | "gas": 1511 193 | }, { 194 | "name": "voting_escrow", 195 | "outputs": [{ 196 | "type": "address", 197 | "name": "" 198 | }], 199 | "inputs": [], 200 | "stateMutability": "view", 201 | "type": "function", 202 | "gas": 1541 203 | }, { 204 | "name": "balanceOf", 205 | "outputs": [{ 206 | "type": "uint256", 207 | "name": "" 208 | }], 209 | "inputs": [{ 210 | "type": "address", 211 | "name": "arg0" 212 | }], 213 | "stateMutability": "view", 214 | "type": "function", 215 | "gas": 1725 216 | }, { 217 | "name": "totalSupply", 218 | "outputs": [{ 219 | "type": "uint256", 220 | "name": "" 221 | }], 222 | "inputs": [], 223 | "stateMutability": "view", 224 | "type": "function", 225 | "gas": 1601 226 | }, { 227 | "name": "future_epoch_time", 228 | "outputs": [{ 229 | "type": "uint256", 230 | "name": "" 231 | }], 232 | "inputs": [], 233 | "stateMutability": "view", 234 | "type": "function", 235 | "gas": 1631 236 | }, { 237 | "name": "approved_to_deposit", 238 | "outputs": [{ 239 | "type": "bool", 240 | "name": "" 241 | }], 242 | "inputs": [{ 243 | "type": "address", 244 | "name": "arg0" 245 | }, { 246 | "type": "address", 247 | "name": "arg1" 248 | }], 249 | "stateMutability": "view", 250 | "type": "function", 251 | "gas": 1969 252 | }, { 253 | "name": "working_balances", 254 | "outputs": [{ 255 | "type": "uint256", 256 | "name": "" 257 | }], 258 | "inputs": [{ 259 | "type": "address", 260 | "name": "arg0" 261 | }], 262 | "stateMutability": "view", 263 | "type": "function", 264 | "gas": 1845 265 | }, { 266 | "name": "working_supply", 267 | "outputs": [{ 268 | "type": "uint256", 269 | "name": "" 270 | }], 271 | "inputs": [], 272 | "stateMutability": "view", 273 | "type": "function", 274 | "gas": 1721 275 | }, { 276 | "name": "period", 277 | "outputs": [{ 278 | "type": "int128", 279 | "name": "" 280 | }], 281 | "inputs": [], 282 | "stateMutability": "view", 283 | "type": "function", 284 | "gas": 1751 285 | }, { 286 | "name": "period_timestamp", 287 | "outputs": [{ 288 | "type": "uint256", 289 | "name": "" 290 | }], 291 | "inputs": [{ 292 | "type": "uint256", 293 | "name": "arg0" 294 | }], 295 | "stateMutability": "view", 296 | "type": "function", 297 | "gas": 1890 298 | }, { 299 | "name": "integrate_inv_supply", 300 | "outputs": [{ 301 | "type": "uint256", 302 | "name": "" 303 | }], 304 | "inputs": [{ 305 | "type": "uint256", 306 | "name": "arg0" 307 | }], 308 | "stateMutability": "view", 309 | "type": "function", 310 | "gas": 1920 311 | }, { 312 | "name": "integrate_inv_supply_of", 313 | "outputs": [{ 314 | "type": "uint256", 315 | "name": "" 316 | }], 317 | "inputs": [{ 318 | "type": "address", 319 | "name": "arg0" 320 | }], 321 | "stateMutability": "view", 322 | "type": "function", 323 | "gas": 1995 324 | }, { 325 | "name": "integrate_checkpoint_of", 326 | "outputs": [{ 327 | "type": "uint256", 328 | "name": "" 329 | }], 330 | "inputs": [{ 331 | "type": "address", 332 | "name": "arg0" 333 | }], 334 | "stateMutability": "view", 335 | "type": "function", 336 | "gas": 2025 337 | }, { 338 | "name": "integrate_fraction", 339 | "outputs": [{ 340 | "type": "uint256", 341 | "name": "" 342 | }], 343 | "inputs": [{ 344 | "type": "address", 345 | "name": "arg0" 346 | }], 347 | "stateMutability": "view", 348 | "type": "function", 349 | "gas": 2055 350 | }, { 351 | "name": "inflation_rate", 352 | "outputs": [{ 353 | "type": "uint256", 354 | "name": "" 355 | }], 356 | "inputs": [], 357 | "stateMutability": "view", 358 | "type": "function", 359 | "gas": 1931 360 | }] -------------------------------------------------------------------------------- /abi/ivault.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "inputs": [{ 3 | "internalType": "address", 4 | "name": "_token", 5 | "type": "address" 6 | }, { 7 | "internalType": "uint256", 8 | "name": "_earnLowerlimit", 9 | "type": "uint256" 10 | }], 11 | "payable": false, 12 | "stateMutability": "nonpayable", 13 | "type": "constructor" 14 | }, { 15 | "anonymous": false, 16 | "inputs": [{ 17 | "indexed": true, 18 | "internalType": "address", 19 | "name": "owner", 20 | "type": "address" 21 | }, { 22 | "indexed": true, 23 | "internalType": "address", 24 | "name": "spender", 25 | "type": "address" 26 | }, { 27 | "indexed": false, 28 | "internalType": "uint256", 29 | "name": "value", 30 | "type": "uint256" 31 | }], 32 | "name": "Approval", 33 | "type": "event" 34 | }, { 35 | "anonymous": false, 36 | "inputs": [{ 37 | "indexed": true, 38 | "internalType": "address", 39 | "name": "from", 40 | "type": "address" 41 | }, { 42 | "indexed": true, 43 | "internalType": "address", 44 | "name": "to", 45 | "type": "address" 46 | }, { 47 | "indexed": false, 48 | "internalType": "uint256", 49 | "name": "value", 50 | "type": "uint256" 51 | }], 52 | "name": "Transfer", 53 | "type": "event" 54 | }, { 55 | "constant": true, 56 | "inputs": [{ 57 | "internalType": "address", 58 | "name": "owner", 59 | "type": "address" 60 | }, { 61 | "internalType": "address", 62 | "name": "spender", 63 | "type": "address" 64 | }], 65 | "name": "allowance", 66 | "outputs": [{ 67 | "internalType": "uint256", 68 | "name": "", 69 | "type": "uint256" 70 | }], 71 | "payable": false, 72 | "stateMutability": "view", 73 | "type": "function" 74 | }, { 75 | "constant": false, 76 | "inputs": [{ 77 | "internalType": "address", 78 | "name": "spender", 79 | "type": "address" 80 | }, { 81 | "internalType": "uint256", 82 | "name": "amount", 83 | "type": "uint256" 84 | }], 85 | "name": "approve", 86 | "outputs": [{ 87 | "internalType": "bool", 88 | "name": "", 89 | "type": "bool" 90 | }], 91 | "payable": false, 92 | "stateMutability": "nonpayable", 93 | "type": "function" 94 | }, { 95 | "constant": true, 96 | "inputs": [], 97 | "name": "available", 98 | "outputs": [{ 99 | "internalType": "uint256", 100 | "name": "", 101 | "type": "uint256" 102 | }], 103 | "payable": false, 104 | "stateMutability": "view", 105 | "type": "function" 106 | }, { 107 | "constant": true, 108 | "inputs": [], 109 | "name": "balance", 110 | "outputs": [{ 111 | "internalType": "uint256", 112 | "name": "", 113 | "type": "uint256" 114 | }], 115 | "payable": false, 116 | "stateMutability": "view", 117 | "type": "function" 118 | }, { 119 | "constant": true, 120 | "inputs": [{ 121 | "internalType": "address", 122 | "name": "account", 123 | "type": "address" 124 | }], 125 | "name": "balanceOf", 126 | "outputs": [{ 127 | "internalType": "uint256", 128 | "name": "", 129 | "type": "uint256" 130 | }], 131 | "payable": false, 132 | "stateMutability": "view", 133 | "type": "function" 134 | }, { 135 | "constant": true, 136 | "inputs": [], 137 | "name": "controller", 138 | "outputs": [{ 139 | "internalType": "address", 140 | "name": "", 141 | "type": "address" 142 | }], 143 | "payable": false, 144 | "stateMutability": "view", 145 | "type": "function" 146 | }, { 147 | "constant": true, 148 | "inputs": [], 149 | "name": "decimals", 150 | "outputs": [{ 151 | "internalType": "uint8", 152 | "name": "", 153 | "type": "uint8" 154 | }], 155 | "payable": false, 156 | "stateMutability": "view", 157 | "type": "function" 158 | }, { 159 | "constant": false, 160 | "inputs": [{ 161 | "internalType": "address", 162 | "name": "spender", 163 | "type": "address" 164 | }, { 165 | "internalType": "uint256", 166 | "name": "subtractedValue", 167 | "type": "uint256" 168 | }], 169 | "name": "decreaseAllowance", 170 | "outputs": [{ 171 | "internalType": "bool", 172 | "name": "", 173 | "type": "bool" 174 | }], 175 | "payable": false, 176 | "stateMutability": "nonpayable", 177 | "type": "function" 178 | }, { 179 | "constant": false, 180 | "inputs": [{ 181 | "internalType": "uint256", 182 | "name": "_amount", 183 | "type": "uint256" 184 | }], 185 | "name": "deposit", 186 | "outputs": [], 187 | "payable": false, 188 | "stateMutability": "nonpayable", 189 | "type": "function" 190 | }, { 191 | "constant": false, 192 | "inputs": [], 193 | "name": "depositAll", 194 | "outputs": [], 195 | "payable": false, 196 | "stateMutability": "nonpayable", 197 | "type": "function" 198 | }, { 199 | "constant": false, 200 | "inputs": [], 201 | "name": "earn", 202 | "outputs": [], 203 | "payable": false, 204 | "stateMutability": "nonpayable", 205 | "type": "function" 206 | }, { 207 | "constant": true, 208 | "inputs": [], 209 | "name": "earnLowerlimit", 210 | "outputs": [{ 211 | "internalType": "uint256", 212 | "name": "", 213 | "type": "uint256" 214 | }], 215 | "payable": false, 216 | "stateMutability": "view", 217 | "type": "function" 218 | }, { 219 | "constant": true, 220 | "inputs": [], 221 | "name": "getPricePerFullShare", 222 | "outputs": [{ 223 | "internalType": "uint256", 224 | "name": "", 225 | "type": "uint256" 226 | }], 227 | "payable": false, 228 | "stateMutability": "view", 229 | "type": "function" 230 | }, { 231 | "constant": true, 232 | "inputs": [], 233 | "name": "governance", 234 | "outputs": [{ 235 | "internalType": "address", 236 | "name": "", 237 | "type": "address" 238 | }], 239 | "payable": false, 240 | "stateMutability": "view", 241 | "type": "function" 242 | }, { 243 | "constant": false, 244 | "inputs": [{ 245 | "internalType": "address", 246 | "name": "spender", 247 | "type": "address" 248 | }, { 249 | "internalType": "uint256", 250 | "name": "addedValue", 251 | "type": "uint256" 252 | }], 253 | "name": "increaseAllowance", 254 | "outputs": [{ 255 | "internalType": "bool", 256 | "name": "", 257 | "type": "bool" 258 | }], 259 | "payable": false, 260 | "stateMutability": "nonpayable", 261 | "type": "function" 262 | }, { 263 | "constant": true, 264 | "inputs": [], 265 | "name": "max", 266 | "outputs": [{ 267 | "internalType": "uint256", 268 | "name": "", 269 | "type": "uint256" 270 | }], 271 | "payable": false, 272 | "stateMutability": "view", 273 | "type": "function" 274 | }, { 275 | "constant": true, 276 | "inputs": [], 277 | "name": "min", 278 | "outputs": [{ 279 | "internalType": "uint256", 280 | "name": "", 281 | "type": "uint256" 282 | }], 283 | "payable": false, 284 | "stateMutability": "view", 285 | "type": "function" 286 | }, { 287 | "constant": true, 288 | "inputs": [], 289 | "name": "name", 290 | "outputs": [{ 291 | "internalType": "string", 292 | "name": "", 293 | "type": "string" 294 | }], 295 | "payable": false, 296 | "stateMutability": "view", 297 | "type": "function" 298 | }, { 299 | "constant": false, 300 | "inputs": [{ 301 | "internalType": "address", 302 | "name": "_controller", 303 | "type": "address" 304 | }], 305 | "name": "setController", 306 | "outputs": [], 307 | "payable": false, 308 | "stateMutability": "nonpayable", 309 | "type": "function" 310 | }, { 311 | "constant": false, 312 | "inputs": [{ 313 | "internalType": "uint256", 314 | "name": "_earnLowerlimit", 315 | "type": "uint256" 316 | }], 317 | "name": "setEarnLowerlimit", 318 | "outputs": [], 319 | "payable": false, 320 | "stateMutability": "nonpayable", 321 | "type": "function" 322 | }, { 323 | "constant": false, 324 | "inputs": [{ 325 | "internalType": "address", 326 | "name": "_governance", 327 | "type": "address" 328 | }], 329 | "name": "setGovernance", 330 | "outputs": [], 331 | "payable": false, 332 | "stateMutability": "nonpayable", 333 | "type": "function" 334 | }, { 335 | "constant": false, 336 | "inputs": [{ 337 | "internalType": "uint256", 338 | "name": "_min", 339 | "type": "uint256" 340 | }], 341 | "name": "setMin", 342 | "outputs": [], 343 | "payable": false, 344 | "stateMutability": "nonpayable", 345 | "type": "function" 346 | }, { 347 | "constant": true, 348 | "inputs": [], 349 | "name": "symbol", 350 | "outputs": [{ 351 | "internalType": "string", 352 | "name": "", 353 | "type": "string" 354 | }], 355 | "payable": false, 356 | "stateMutability": "view", 357 | "type": "function" 358 | }, { 359 | "constant": true, 360 | "inputs": [], 361 | "name": "token", 362 | "outputs": [{ 363 | "internalType": "contract IERC20", 364 | "name": "", 365 | "type": "address" 366 | }], 367 | "payable": false, 368 | "stateMutability": "view", 369 | "type": "function" 370 | }, { 371 | "constant": true, 372 | "inputs": [], 373 | "name": "totalSupply", 374 | "outputs": [{ 375 | "internalType": "uint256", 376 | "name": "", 377 | "type": "uint256" 378 | }], 379 | "payable": false, 380 | "stateMutability": "view", 381 | "type": "function" 382 | }, { 383 | "constant": false, 384 | "inputs": [{ 385 | "internalType": "address", 386 | "name": "recipient", 387 | "type": "address" 388 | }, { 389 | "internalType": "uint256", 390 | "name": "amount", 391 | "type": "uint256" 392 | }], 393 | "name": "transfer", 394 | "outputs": [{ 395 | "internalType": "bool", 396 | "name": "", 397 | "type": "bool" 398 | }], 399 | "payable": false, 400 | "stateMutability": "nonpayable", 401 | "type": "function" 402 | }, { 403 | "constant": false, 404 | "inputs": [{ 405 | "internalType": "address", 406 | "name": "sender", 407 | "type": "address" 408 | }, { 409 | "internalType": "address", 410 | "name": "recipient", 411 | "type": "address" 412 | }, { 413 | "internalType": "uint256", 414 | "name": "amount", 415 | "type": "uint256" 416 | }], 417 | "name": "transferFrom", 418 | "outputs": [{ 419 | "internalType": "bool", 420 | "name": "", 421 | "type": "bool" 422 | }], 423 | "payable": false, 424 | "stateMutability": "nonpayable", 425 | "type": "function" 426 | }, { 427 | "constant": false, 428 | "inputs": [{ 429 | "internalType": "uint256", 430 | "name": "_shares", 431 | "type": "uint256" 432 | }], 433 | "name": "withdraw", 434 | "outputs": [], 435 | "payable": false, 436 | "stateMutability": "nonpayable", 437 | "type": "function" 438 | }, { 439 | "constant": false, 440 | "inputs": [], 441 | "name": "withdrawAll", 442 | "outputs": [], 443 | "payable": false, 444 | "stateMutability": "nonpayable", 445 | "type": "function" 446 | }] -------------------------------------------------------------------------------- /abi/strategy.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_want", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "address", 11 | "name": "_pool", 12 | "type": "address" 13 | } 14 | ], 15 | "payable": false, 16 | "stateMutability": "nonpayable", 17 | "type": "constructor" 18 | }, 19 | { 20 | "constant": true, 21 | "inputs": [], 22 | "name": "balanceOf", 23 | "outputs": [ 24 | { 25 | "internalType": "uint256", 26 | "name": "", 27 | "type": "uint256" 28 | } 29 | ], 30 | "payable": false, 31 | "stateMutability": "view", 32 | "type": "function" 33 | }, 34 | { 35 | "constant": true, 36 | "inputs": [], 37 | "name": "balanceOfPendingReward", 38 | "outputs": [ 39 | { 40 | "internalType": "uint256", 41 | "name": "", 42 | "type": "uint256" 43 | } 44 | ], 45 | "payable": false, 46 | "stateMutability": "view", 47 | "type": "function" 48 | }, 49 | { 50 | "constant": true, 51 | "inputs": [], 52 | "name": "burnfee", 53 | "outputs": [ 54 | { 55 | "internalType": "uint256", 56 | "name": "", 57 | "type": "uint256" 58 | } 59 | ], 60 | "payable": false, 61 | "stateMutability": "view", 62 | "type": "function" 63 | }, 64 | { 65 | "constant": true, 66 | "inputs": [], 67 | "name": "callfee", 68 | "outputs": [ 69 | { 70 | "internalType": "uint256", 71 | "name": "", 72 | "type": "uint256" 73 | } 74 | ], 75 | "payable": false, 76 | "stateMutability": "view", 77 | "type": "function" 78 | }, 79 | { 80 | "constant": true, 81 | "inputs": [], 82 | "name": "controller", 83 | "outputs": [ 84 | { 85 | "internalType": "address", 86 | "name": "", 87 | "type": "address" 88 | } 89 | ], 90 | "payable": false, 91 | "stateMutability": "view", 92 | "type": "function" 93 | }, 94 | { 95 | "constant": true, 96 | "inputs": [], 97 | "name": "curvedeposit", 98 | "outputs": [ 99 | { 100 | "internalType": "address", 101 | "name": "", 102 | "type": "address" 103 | } 104 | ], 105 | "payable": false, 106 | "stateMutability": "view", 107 | "type": "function" 108 | }, 109 | { 110 | "constant": true, 111 | "inputs": [], 112 | "name": "curveminter", 113 | "outputs": [ 114 | { 115 | "internalType": "address", 116 | "name": "", 117 | "type": "address" 118 | } 119 | ], 120 | "payable": false, 121 | "stateMutability": "view", 122 | "type": "function" 123 | }, 124 | { 125 | "constant": false, 126 | "inputs": [], 127 | "name": "deposit", 128 | "outputs": [], 129 | "payable": false, 130 | "stateMutability": "nonpayable", 131 | "type": "function" 132 | }, 133 | { 134 | "constant": true, 135 | "inputs": [], 136 | "name": "fee", 137 | "outputs": [ 138 | { 139 | "internalType": "uint256", 140 | "name": "", 141 | "type": "uint256" 142 | } 143 | ], 144 | "payable": false, 145 | "stateMutability": "view", 146 | "type": "function" 147 | }, 148 | { 149 | "constant": true, 150 | "inputs": [], 151 | "name": "getName", 152 | "outputs": [ 153 | { 154 | "internalType": "string", 155 | "name": "", 156 | "type": "string" 157 | } 158 | ], 159 | "payable": false, 160 | "stateMutability": "view", 161 | "type": "function" 162 | }, 163 | { 164 | "constant": true, 165 | "inputs": [], 166 | "name": "governance", 167 | "outputs": [ 168 | { 169 | "internalType": "address", 170 | "name": "", 171 | "type": "address" 172 | } 173 | ], 174 | "payable": false, 175 | "stateMutability": "view", 176 | "type": "function" 177 | }, 178 | { 179 | "constant": true, 180 | "inputs": [], 181 | "name": "harvertYFII", 182 | "outputs": [ 183 | { 184 | "internalType": "uint256[]", 185 | "name": "amounts", 186 | "type": "uint256[]" 187 | } 188 | ], 189 | "payable": false, 190 | "stateMutability": "view", 191 | "type": "function" 192 | }, 193 | { 194 | "constant": false, 195 | "inputs": [], 196 | "name": "harvest", 197 | "outputs": [], 198 | "payable": false, 199 | "stateMutability": "nonpayable", 200 | "type": "function" 201 | }, 202 | { 203 | "constant": false, 204 | "inputs": [], 205 | "name": "init", 206 | "outputs": [], 207 | "payable": false, 208 | "stateMutability": "nonpayable", 209 | "type": "function" 210 | }, 211 | { 212 | "constant": true, 213 | "inputs": [], 214 | "name": "max", 215 | "outputs": [ 216 | { 217 | "internalType": "uint256", 218 | "name": "", 219 | "type": "uint256" 220 | } 221 | ], 222 | "payable": false, 223 | "stateMutability": "view", 224 | "type": "function" 225 | }, 226 | { 227 | "constant": true, 228 | "inputs": [], 229 | "name": "output", 230 | "outputs": [ 231 | { 232 | "internalType": "address", 233 | "name": "", 234 | "type": "address" 235 | } 236 | ], 237 | "payable": false, 238 | "stateMutability": "view", 239 | "type": "function" 240 | }, 241 | { 242 | "constant": false, 243 | "inputs": [ 244 | { 245 | "internalType": "uint256", 246 | "name": "_fee", 247 | "type": "uint256" 248 | } 249 | ], 250 | "name": "setBurnFee", 251 | "outputs": [], 252 | "payable": false, 253 | "stateMutability": "nonpayable", 254 | "type": "function" 255 | }, 256 | { 257 | "constant": false, 258 | "inputs": [ 259 | { 260 | "internalType": "uint256", 261 | "name": "_fee", 262 | "type": "uint256" 263 | } 264 | ], 265 | "name": "setCallFee", 266 | "outputs": [], 267 | "payable": false, 268 | "stateMutability": "nonpayable", 269 | "type": "function" 270 | }, 271 | { 272 | "constant": false, 273 | "inputs": [ 274 | { 275 | "internalType": "address", 276 | "name": "_controller", 277 | "type": "address" 278 | } 279 | ], 280 | "name": "setController", 281 | "outputs": [], 282 | "payable": false, 283 | "stateMutability": "nonpayable", 284 | "type": "function" 285 | }, 286 | { 287 | "constant": false, 288 | "inputs": [ 289 | { 290 | "internalType": "uint256", 291 | "name": "_fee", 292 | "type": "uint256" 293 | } 294 | ], 295 | "name": "setFee", 296 | "outputs": [], 297 | "payable": false, 298 | "stateMutability": "nonpayable", 299 | "type": "function" 300 | }, 301 | { 302 | "constant": false, 303 | "inputs": [ 304 | { 305 | "internalType": "address", 306 | "name": "_governance", 307 | "type": "address" 308 | } 309 | ], 310 | "name": "setGovernance", 311 | "outputs": [], 312 | "payable": false, 313 | "stateMutability": "nonpayable", 314 | "type": "function" 315 | }, 316 | { 317 | "constant": false, 318 | "inputs": [ 319 | { 320 | "internalType": "address[]", 321 | "name": "_path", 322 | "type": "address[]" 323 | } 324 | ], 325 | "name": "setSwapRouting", 326 | "outputs": [], 327 | "payable": false, 328 | "stateMutability": "nonpayable", 329 | "type": "function" 330 | }, 331 | { 332 | "constant": true, 333 | "inputs": [ 334 | { 335 | "internalType": "uint256", 336 | "name": "", 337 | "type": "uint256" 338 | } 339 | ], 340 | "name": "swapRouting", 341 | "outputs": [ 342 | { 343 | "internalType": "address", 344 | "name": "", 345 | "type": "address" 346 | } 347 | ], 348 | "payable": false, 349 | "stateMutability": "view", 350 | "type": "function" 351 | }, 352 | { 353 | "constant": true, 354 | "inputs": [], 355 | "name": "unirouter", 356 | "outputs": [ 357 | { 358 | "internalType": "address", 359 | "name": "", 360 | "type": "address" 361 | } 362 | ], 363 | "payable": false, 364 | "stateMutability": "view", 365 | "type": "function" 366 | }, 367 | { 368 | "constant": true, 369 | "inputs": [], 370 | "name": "want", 371 | "outputs": [ 372 | { 373 | "internalType": "address", 374 | "name": "", 375 | "type": "address" 376 | } 377 | ], 378 | "payable": false, 379 | "stateMutability": "view", 380 | "type": "function" 381 | }, 382 | { 383 | "constant": true, 384 | "inputs": [], 385 | "name": "weth", 386 | "outputs": [ 387 | { 388 | "internalType": "address", 389 | "name": "", 390 | "type": "address" 391 | } 392 | ], 393 | "payable": false, 394 | "stateMutability": "view", 395 | "type": "function" 396 | }, 397 | { 398 | "constant": false, 399 | "inputs": [ 400 | { 401 | "internalType": "uint256", 402 | "name": "_amount", 403 | "type": "uint256" 404 | } 405 | ], 406 | "name": "withdraw", 407 | "outputs": [], 408 | "payable": false, 409 | "stateMutability": "nonpayable", 410 | "type": "function" 411 | }, 412 | { 413 | "constant": false, 414 | "inputs": [ 415 | { 416 | "internalType": "contract IERC20", 417 | "name": "_asset", 418 | "type": "address" 419 | } 420 | ], 421 | "name": "withdraw", 422 | "outputs": [ 423 | { 424 | "internalType": "uint256", 425 | "name": "balance", 426 | "type": "uint256" 427 | } 428 | ], 429 | "payable": false, 430 | "stateMutability": "nonpayable", 431 | "type": "function" 432 | }, 433 | { 434 | "constant": false, 435 | "inputs": [], 436 | "name": "withdrawAll", 437 | "outputs": [ 438 | { 439 | "internalType": "uint256", 440 | "name": "balance", 441 | "type": "uint256" 442 | } 443 | ], 444 | "payable": false, 445 | "stateMutability": "nonpayable", 446 | "type": "function" 447 | }, 448 | { 449 | "constant": true, 450 | "inputs": [], 451 | "name": "yfii", 452 | "outputs": [ 453 | { 454 | "internalType": "address", 455 | "name": "", 456 | "type": "address" 457 | } 458 | ], 459 | "payable": false, 460 | "stateMutability": "view", 461 | "type": "function" 462 | } 463 | ] -------------------------------------------------------------------------------- /bscpd/strategy/eth.sol: -------------------------------------------------------------------------------- 1 | contract StrategyFortube { 2 | using SafeERC20 for IERC20; 3 | using Address for address; 4 | using SafeMath for uint256; 5 | 6 | address constant public output = address(0x658A109C5900BC6d2357c87549B651670E5b0539); //for 7 | address public unirouter = address(0x039B5818e51dfEC86c1D56A4668787AF0Ed1c068); // unisave 8 | address constant public weth = address(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c); // used for for <> weth <> usdc route 9 | 10 | address constant public yfii = address(0x7F70642d88cf1C4a3a7abb072B53B929b653edA5); 11 | 12 | 13 | address constant public fortube = address(0x0cEA0832e9cdBb5D476040D58Ea07ecfbeBB7672);//主合约. 14 | address public fortube_reward = address(0x55838F18e79cFd3EA22Eea08Bd3Ec18d67f314ed); //领取奖励的合约 15 | 16 | address public want; 17 | 18 | 19 | uint public strategyfee = 100; 20 | uint public fee = 300; 21 | uint public burnfee = 500; 22 | uint public callfee = 100; 23 | uint constant public max = 1000; 24 | 25 | uint public withdrawalFee = 0; 26 | uint constant public withdrawalMax = 10000; 27 | 28 | address public governance; 29 | address public strategyDev; 30 | address public controller; 31 | address public burnAddress = 0xB6af2DabCEBC7d30E440714A33E5BD45CEEd103a; 32 | 33 | string public getName; 34 | 35 | address[] public swap2YFIIRouting; 36 | address[] public swap2TokenRouting; 37 | 38 | 39 | constructor(address _want) public { 40 | want = _want; 41 | governance = tx.origin; 42 | controller = 0x5B916D02A9745C64EC6C0AFe41Ee4893Dd5a01B7; 43 | getName = string( 44 | abi.encodePacked("yfii:Strategy:", 45 | abi.encodePacked(IERC20(want).name(),"The Force Token" 46 | ) 47 | )); 48 | swap2YFIIRouting = [output,weth,yfii]; 49 | swap2TokenRouting = [output,weth,want]; 50 | doApprove(); 51 | strategyDev = tx.origin; 52 | } 53 | 54 | function doApprove () public{ 55 | IERC20(output).safeApprove(unirouter, 0); 56 | IERC20(output).safeApprove(unirouter, uint(-1)); 57 | } 58 | 59 | function setFortubeReward(address _reward) public { 60 | require(msg.sender == governance, "!governance"); 61 | fortube_reward = _reward; 62 | } 63 | function setUnirouter(address _unirouter) public { 64 | require(msg.sender == governance, "!governance"); 65 | unirouter = _unirouter; 66 | } 67 | 68 | 69 | function deposit() public { 70 | uint _want = IERC20(want).balanceOf(address(this)); 71 | address _controller = For(fortube).controller(); 72 | if (_want > 0) { 73 | IERC20(want).safeApprove(_controller, 0); 74 | IERC20(want).safeApprove(_controller, _want); 75 | For(fortube).deposit(want,_want); 76 | } 77 | 78 | } 79 | 80 | // Controller only function for creating additional rewards from dust 81 | function withdraw(IERC20 _asset) external returns (uint balance) { 82 | require(msg.sender == controller, "!controller"); 83 | require(want != address(_asset), "want"); 84 | address _controller = For(fortube).controller(); 85 | require(IBankController(_controller).getFTokeAddress(want) != address(_asset),"fToken"); 86 | balance = _asset.balanceOf(address(this)); 87 | _asset.safeTransfer(controller, balance); 88 | } 89 | 90 | // Withdraw partial funds, normally used with a vault withdrawal 91 | function withdraw(uint _amount) external { 92 | require(msg.sender == controller, "!controller"); 93 | uint _balance = IERC20(want).balanceOf(address(this)); 94 | if (_balance < _amount) { 95 | _amount = _withdrawSome(_amount.sub(_balance)); 96 | _amount = _amount.add(_balance); 97 | } 98 | 99 | uint _fee = 0; 100 | if (withdrawalFee>0){ 101 | _fee = _amount.mul(withdrawalFee).div(withdrawalMax); 102 | IERC20(want).safeTransfer(Controller(controller).rewards(), _fee); 103 | } 104 | 105 | 106 | address _vault = Controller(controller).vaults(address(want)); 107 | require(_vault != address(0), "!vault"); // additional protection so we don't burn the funds 108 | IERC20(want).safeTransfer(_vault, _amount.sub(_fee)); 109 | } 110 | 111 | // Withdraw all funds, normally used when migrating strategies 112 | function withdrawAll() external returns (uint balance) { 113 | require(msg.sender == controller || msg.sender == governance,"!governance"); 114 | _withdrawAll(); 115 | 116 | 117 | balance = IERC20(want).balanceOf(address(this)); 118 | 119 | address _vault = Controller(controller).vaults(address(want)); 120 | require(_vault != address(0), "!vault"); // additional protection so we don't burn the funds 121 | IERC20(want).safeTransfer(_vault, balance); 122 | } 123 | 124 | function _withdrawAll() internal { 125 | address _controller = For(fortube).controller(); 126 | IFToken fToken = IFToken(IBankController(_controller).getFTokeAddress(want)); 127 | uint b = fToken.balanceOf(address(this)); 128 | For(fortube).withdraw(want,b); 129 | } 130 | 131 | function harvest() public { 132 | require(!Address.isContract(msg.sender),"!contract"); 133 | ForReward(fortube_reward).claimReward(); 134 | doswap(); 135 | dosplit();//分yfii 136 | deposit(); 137 | } 138 | 139 | function doswap() internal { 140 | uint256 _2token = IERC20(output).balanceOf(address(this)); //100% 141 | // uint256 _2yfii = IERC20(output).balanceOf(address(this)).mul(10).div(100); //10% 142 | UniswapRouter(unirouter).swapExactTokensForTokens(_2token, 0, swap2TokenRouting, address(this), now.add(1800)); 143 | // UniswapRouter(unirouter).swapExactTokensForTokens(_2yfii, 0, swap2YFIIRouting, address(this), now.add(1800)); 144 | } 145 | function dosplit() internal{ 146 | uint b = IERC20(want).balanceOf(address(this)).mul(10).div(100);//10% want 147 | uint _fee = b.mul(fee).div(max); 148 | uint _callfee = b.mul(callfee).div(max); 149 | uint _burnfee = b.mul(burnfee).div(max); 150 | IERC20(want).safeTransfer(Controller(controller).rewards(), _fee); //3% 3% team 151 | IERC20(want).safeTransfer(msg.sender, _callfee); //call fee 1% 152 | IERC20(want).safeTransfer(burnAddress, _burnfee); //burn fee 5% 153 | 154 | if (strategyfee >0){ 155 | uint _strategyfee = b.mul(strategyfee).div(max); //1% 156 | IERC20(want).safeTransfer(strategyDev, _strategyfee); 157 | } 158 | } 159 | 160 | function _withdrawSome(uint256 _amount) internal returns (uint) { 161 | For(fortube).withdrawUnderlying(want,_amount); 162 | return _amount; 163 | } 164 | 165 | function balanceOfWant() public view returns (uint) { 166 | return IERC20(want).balanceOf(address(this)); 167 | } 168 | 169 | function balanceOfPool() public view returns (uint) { 170 | address _controller = For(fortube).controller(); 171 | IFToken fToken = IFToken(IBankController(_controller).getFTokeAddress(want)); 172 | return fToken.calcBalanceOfUnderlying(address(this)); 173 | } 174 | 175 | 176 | function balanceOf() public view returns (uint) { 177 | return balanceOfWant() 178 | .add(balanceOfPool()); 179 | } 180 | 181 | function setGovernance(address _governance) external { 182 | require(msg.sender == governance, "!governance"); 183 | governance = _governance; 184 | } 185 | 186 | function setController(address _controller) external { 187 | require(msg.sender == governance, "!governance"); 188 | controller = _controller; 189 | } 190 | function setFee(uint256 _fee) external{ 191 | require(msg.sender == governance, "!governance"); 192 | fee = _fee; 193 | } 194 | function setStrategyFee(uint256 _fee) external{ 195 | require(msg.sender == governance, "!governance"); 196 | strategyfee = _fee; 197 | } 198 | function setCallFee(uint256 _fee) external{ 199 | require(msg.sender == governance, "!governance"); 200 | callfee = _fee; 201 | } 202 | function setBurnFee(uint256 _fee) external{ 203 | require(msg.sender == governance, "!governance"); 204 | burnfee = _fee; 205 | } 206 | function setBurnAddress(address _burnAddress) public{ 207 | require(msg.sender == governance, "!governance"); 208 | burnAddress = _burnAddress; 209 | } 210 | 211 | function setWithdrawalFee(uint _withdrawalFee) external { 212 | require(msg.sender == governance, "!governance"); 213 | require(_withdrawalFee <=100,"fee >= 1%"); //max:1% 214 | withdrawalFee = _withdrawalFee; 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /bscpd/vault/eth.sol: -------------------------------------------------------------------------------- 1 | contract iVault is ERC20, ERC20Detailed { 2 | using SafeERC20 for IERC20; 3 | using Address for address; 4 | using SafeMath for uint256; 5 | 6 | IERC20 public token; 7 | 8 | uint public min = 9900; 9 | uint public constant max = 10000; 10 | 11 | address public governance; 12 | address public controller; 13 | 14 | constructor (address _token) public ERC20Detailed( 15 | string(abi.encodePacked("yfii ", ERC20Detailed(_token).name())), 16 | string(abi.encodePacked("i", ERC20Detailed(_token).symbol())), 17 | ERC20Detailed(_token).decimals() 18 | ) { 19 | token = IERC20(_token); 20 | governance = tx.origin; 21 | controller = 0x5B916D02A9745C64EC6C0AFe41Ee4893Dd5a01B7; 22 | } 23 | 24 | function balance() public view returns (uint) { 25 | return token.balanceOf(address(this)) 26 | .add(Controller(controller).balanceOf(address(token))); 27 | } 28 | 29 | function setMin(uint _min) external { 30 | require(msg.sender == governance, "!governance"); 31 | min = _min; 32 | } 33 | 34 | function setGovernance(address _governance) public { 35 | require(msg.sender == governance, "!governance"); 36 | governance = _governance; 37 | } 38 | 39 | function setController(address _controller) public { 40 | require(msg.sender == governance, "!governance"); 41 | controller = _controller; 42 | } 43 | 44 | // Custom logic in here for how much the vault allows to be borrowed 45 | // Sets minimum required on-hand to keep small withdrawals cheap 46 | function available() public view returns (uint) { 47 | return token.balanceOf(address(this)).mul(min).div(max); 48 | } 49 | 50 | function earn() public { 51 | uint _bal = available(); 52 | token.safeTransfer(controller, _bal); 53 | Controller(controller).earn(address(token), _bal); 54 | } 55 | 56 | function depositAll() external { 57 | deposit(token.balanceOf(msg.sender)); 58 | } 59 | 60 | function deposit(uint _amount) public { 61 | uint _pool = balance(); 62 | uint _before = token.balanceOf(address(this)); 63 | token.safeTransferFrom(msg.sender, address(this), _amount); 64 | uint _after = token.balanceOf(address(this)); 65 | _amount = _after.sub(_before); // Additional check for deflationary tokens 66 | uint shares = 0; 67 | if (totalSupply() == 0) { 68 | shares = _amount; 69 | } else { 70 | shares = (_amount.mul(totalSupply())).div(_pool); 71 | } 72 | _mint(msg.sender, shares); 73 | earn(); 74 | } 75 | 76 | function withdrawAll() external { 77 | withdraw(balanceOf(msg.sender)); 78 | } 79 | 80 | 81 | 82 | // No rebalance implementation for lower fees and faster swaps 83 | function withdraw(uint _shares) public { 84 | uint r = (balance().mul(_shares)).div(totalSupply()); 85 | _burn(msg.sender, _shares); 86 | 87 | // Check balance 88 | uint b = token.balanceOf(address(this)); 89 | if (b < r) { 90 | uint _withdraw = r.sub(b); 91 | Controller(controller).withdraw(address(token), _withdraw); 92 | uint _after = token.balanceOf(address(this)); 93 | uint _diff = _after.sub(b); 94 | if (_diff < _withdraw) { 95 | r = b.add(_diff); 96 | } 97 | } 98 | 99 | token.safeTransfer(msg.sender, r); 100 | } 101 | 102 | function getPricePerFullShare() public view returns (uint) { 103 | return balance().mul(1e18).div(totalSupply()); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /contracts/Controller.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at Etherscan.io on 2020-07-26 3 | */ 4 | 5 | // SPDX-License-Identifier: MIT 6 | 7 | pragma solidity ^0.5.15; 8 | 9 | interface IERC20 { 10 | function totalSupply() external view returns (uint256); 11 | function balanceOf(address account) external view returns (uint256); 12 | function transfer(address recipient, uint256 amount) external returns (bool); 13 | function allowance(address owner, address spender) external view returns (uint256); 14 | function approve(address spender, uint256 amount) external returns (bool); 15 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 16 | event Transfer(address indexed from, address indexed to, uint256 value); 17 | event Approval(address indexed owner, address indexed spender, uint256 value); 18 | } 19 | 20 | library SafeMath { 21 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 22 | uint256 c = a + b; 23 | require(c >= a, "SafeMath: addition overflow"); 24 | 25 | return c; 26 | } 27 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 28 | return sub(a, b, "SafeMath: subtraction overflow"); 29 | } 30 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 31 | require(b <= a, errorMessage); 32 | uint256 c = a - b; 33 | 34 | return c; 35 | } 36 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 37 | if (a == 0) { 38 | return 0; 39 | } 40 | 41 | uint256 c = a * b; 42 | require(c / a == b, "SafeMath: multiplication overflow"); 43 | 44 | return c; 45 | } 46 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 47 | return div(a, b, "SafeMath: division by zero"); 48 | } 49 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 50 | // Solidity only automatically asserts when dividing by 0 51 | require(b > 0, errorMessage); 52 | uint256 c = a / b; 53 | 54 | return c; 55 | } 56 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 57 | return mod(a, b, "SafeMath: modulo by zero"); 58 | } 59 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 60 | require(b != 0, errorMessage); 61 | return a % b; 62 | } 63 | } 64 | 65 | library Address { 66 | function isContract(address account) internal view returns (bool) { 67 | bytes32 codehash; 68 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 69 | // solhint-disable-next-line no-inline-assembly 70 | assembly { codehash := extcodehash(account) } 71 | return (codehash != 0x0 && codehash != accountHash); 72 | } 73 | function toPayable(address account) internal pure returns (address payable) { 74 | return address(uint160(account)); 75 | } 76 | function sendValue(address payable recipient, uint256 amount) internal { 77 | require(address(this).balance >= amount, "Address: insufficient balance"); 78 | 79 | // solhint-disable-next-line avoid-call-value 80 | (bool success, ) = recipient.call.value(amount)(""); 81 | require(success, "Address: unable to send value, recipient may have reverted"); 82 | } 83 | } 84 | 85 | library SafeERC20 { 86 | using SafeMath for uint256; 87 | using Address for address; 88 | 89 | function safeTransfer(IERC20 token, address to, uint256 value) internal { 90 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 91 | } 92 | 93 | function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 94 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 95 | } 96 | 97 | function safeApprove(IERC20 token, address spender, uint256 value) internal { 98 | require((value == 0) || (token.allowance(address(this), spender) == 0), 99 | "SafeERC20: approve from non-zero to non-zero allowance" 100 | ); 101 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 102 | } 103 | function callOptionalReturn(IERC20 token, bytes memory data) private { 104 | require(address(token).isContract(), "SafeERC20: call to non-contract"); 105 | 106 | // solhint-disable-next-line avoid-low-level-calls 107 | (bool success, bytes memory returndata) = address(token).call(data); 108 | require(success, "SafeERC20: low-level call failed"); 109 | 110 | if (returndata.length > 0) { // Return data is optional 111 | // solhint-disable-next-line max-line-length 112 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 113 | } 114 | } 115 | } 116 | 117 | interface Strategy { 118 | function want() external view returns (address); 119 | function deposit() external; 120 | function withdraw(address) external; 121 | function withdraw(uint) external; 122 | function withdrawAll() external returns (uint); 123 | function balanceOf() external view returns (uint); 124 | } 125 | 126 | interface Converter { 127 | function convert(address) external returns (uint); 128 | } 129 | 130 | interface OneSplitAudit { 131 | function swap( 132 | address fromToken, 133 | address destToken, 134 | uint256 amount, 135 | uint256 minReturn, 136 | uint256[] calldata distribution, 137 | uint256 flags 138 | ) 139 | external 140 | payable 141 | returns(uint256 returnAmount); 142 | 143 | function getExpectedReturn( 144 | address fromToken, 145 | address destToken, 146 | uint256 amount, 147 | uint256 parts, 148 | uint256 flags // See constants in IOneSplit.sol 149 | ) 150 | external 151 | view 152 | returns( 153 | uint256 returnAmount, 154 | uint256[] memory distribution 155 | ); 156 | } 157 | 158 | contract Controller { 159 | using SafeERC20 for IERC20; 160 | using Address for address; 161 | using SafeMath for uint256; 162 | 163 | address public governance; 164 | address public onesplit; 165 | address public rewards; 166 | address public factory; 167 | mapping(address => address) public vaults; 168 | mapping(address => address) public strategies; 169 | mapping(address => mapping(address => address)) public converters; 170 | 171 | uint public split = 5000; 172 | uint public constant max = 10000; 173 | 174 | 175 | event NewVault(address indexed _token, address indexed _vault); 176 | 177 | 178 | constructor() public { 179 | governance = tx.origin; 180 | onesplit = address(0x50FDA034C0Ce7a8f7EFDAebDA7Aa7cA21CC1267e); 181 | rewards = 0x887F507EaAc58adD20263C6918538A9BdC882d47; 182 | } 183 | 184 | function setFactory(address _factory) public { 185 | require(msg.sender == governance, "!governance"); 186 | factory = _factory; 187 | } 188 | 189 | function setSplit(uint _split) public { 190 | require(msg.sender == governance, "!governance"); 191 | split = _split; 192 | } 193 | 194 | function setOneSplit(address _onesplit) public { 195 | require(msg.sender == governance, "!governance"); 196 | onesplit = _onesplit; 197 | } 198 | 199 | function setGovernance(address _governance) public { 200 | require(msg.sender == governance, "!governance"); 201 | governance = _governance; 202 | } 203 | 204 | function setVault(address _token, address _vault) public { 205 | //TODO:加个Event 添加新的策略了. 206 | require(msg.sender == governance, "!governance"); 207 | vaults[_token] = _vault; 208 | emit NewVault(_token,_vault); 209 | } 210 | 211 | function setConverter(address _input, address _output, address _converter) public { 212 | require(msg.sender == governance, "!governance"); 213 | converters[_input][_output] = _converter; 214 | } 215 | 216 | function setStrategy(address _token, address _strategy) public { 217 | //某个币对应一个策略,比如现在的ycrv就是挖 yfii 218 | require(msg.sender == governance, "!governance"); 219 | address _current = strategies[_token]; 220 | if (_current != address(0)) {//之前的策略存在的话,那么就先提取所有资金 221 | Strategy(_current).withdrawAll(); 222 | } 223 | strategies[_token] = _strategy; 224 | } 225 | 226 | // 227 | function earn(address _token, uint _amount) public { 228 | address _strategy = strategies[_token]; //获取策略的合约地址 229 | address _want = Strategy(_strategy).want();//策略需要的token地址 230 | if (_want != _token) {//如果策略需要的和输入的不一样,需要先转换 231 | address converter = converters[_token][_want];//转换器合约地址. 232 | IERC20(_token).safeTransfer(converter, _amount);//给转换器打钱 233 | _amount = Converter(converter).convert(_strategy);//执行转换... 234 | IERC20(_want).safeTransfer(_strategy, _amount); 235 | } else { 236 | IERC20(_token).safeTransfer(_strategy, _amount); 237 | } 238 | Strategy(_strategy).deposit();//存钱 239 | } 240 | 241 | function balanceOf(address _token) external view returns (uint) { 242 | return Strategy(strategies[_token]).balanceOf(); 243 | } 244 | 245 | function withdrawAll(address _token) public { 246 | require(msg.sender == governance, "!governance"); 247 | Strategy(strategies[_token]).withdrawAll(); 248 | } 249 | 250 | function inCaseTokensGetStuck(address _token, uint _amount) public {//转任意erc20 251 | require(msg.sender == governance, "!governance"); 252 | IERC20(_token).safeTransfer(governance, _amount); 253 | } 254 | 255 | function getExpectedReturn(address _strategy, address _token, uint parts) public view returns (uint expected) { 256 | uint _balance = IERC20(_token).balanceOf(_strategy);//获取策略器 某个代币的余额 257 | address _want = Strategy(_strategy).want();//策略器需要的代币. 258 | (expected,) = OneSplitAudit(onesplit).getExpectedReturn(_token, _want, _balance, parts, 0); 259 | } 260 | 261 | // Only allows to withdraw non-core strategy tokens ~ this is over and above normal yield 262 | function yearn(address _strategy, address _token, uint parts) public { 263 | // This contract should never have value in it, but just incase since this is a public call 264 | uint _before = IERC20(_token).balanceOf(address(this)); 265 | Strategy(_strategy).withdraw(_token); 266 | uint _after = IERC20(_token).balanceOf(address(this)); 267 | if (_after > _before) { 268 | uint _amount = _after.sub(_before); 269 | address _want = Strategy(_strategy).want(); 270 | uint[] memory _distribution; 271 | uint _expected; 272 | _before = IERC20(_want).balanceOf(address(this)); 273 | IERC20(_token).safeApprove(onesplit, 0); 274 | IERC20(_token).safeApprove(onesplit, _amount); 275 | (_expected, _distribution) = OneSplitAudit(onesplit).getExpectedReturn(_token, _want, _amount, parts, 0); 276 | OneSplitAudit(onesplit).swap(_token, _want, _amount, _expected, _distribution, 0); 277 | _after = IERC20(_want).balanceOf(address(this)); 278 | if (_after > _before) { 279 | _amount = _after.sub(_before); 280 | uint _reward = _amount.mul(split).div(max); 281 | earn(_want, _amount.sub(_reward)); 282 | IERC20(_want).safeTransfer(rewards, _reward); 283 | } 284 | } 285 | } 286 | 287 | function withdraw(address _token, uint _amount) public { 288 | require(msg.sender == vaults[_token], "!vault"); 289 | Strategy(strategies[_token]).withdraw(_amount); 290 | } 291 | } -------------------------------------------------------------------------------- /contracts/crvContract/bcrvGauge.vy: -------------------------------------------------------------------------------- 1 | # @version 0.2.4 2 | """ 3 | @title Liquidity Gauge 4 | @author Curve Finance 5 | @license MIT 6 | @notice Used for measuring liquidity and insurance 7 | """ 8 | 9 | from vyper.interfaces import ERC20 10 | 11 | interface CRV20: 12 | def future_epoch_time_write() -> uint256: nonpayable 13 | def rate() -> uint256: view 14 | 15 | interface Controller: 16 | def period() -> int128: view 17 | def period_write() -> int128: nonpayable 18 | def period_timestamp(p: int128) -> uint256: view 19 | def gauge_relative_weight(addr: address, time: uint256) -> uint256: view 20 | def voting_escrow() -> address: view 21 | def checkpoint(): nonpayable 22 | def checkpoint_gauge(addr: address): nonpayable 23 | 24 | interface Minter: 25 | def token() -> address: view 26 | def controller() -> address: view 27 | def minted(user: address, gauge: address) -> uint256: view 28 | 29 | interface VotingEscrow: 30 | def user_point_epoch(addr: address) -> uint256: view 31 | def user_point_history__ts(addr: address, epoch: uint256) -> uint256: view 32 | 33 | 34 | event Deposit: 35 | provider: indexed(address) 36 | value: uint256 37 | 38 | event Withdraw: 39 | provider: indexed(address) 40 | value: uint256 41 | 42 | event UpdateLiquidityLimit: 43 | user: address 44 | original_balance: uint256 45 | original_supply: uint256 46 | working_balance: uint256 47 | working_supply: uint256 48 | 49 | 50 | TOKENLESS_PRODUCTION: constant(uint256) = 40 51 | BOOST_WARMUP: constant(uint256) = 2 * 7 * 86400 52 | WEEK: constant(uint256) = 604800 53 | 54 | minter: public(address) 55 | crv_token: public(address) 56 | lp_token: public(address) 57 | controller: public(address) 58 | voting_escrow: public(address) 59 | balanceOf: public(HashMap[address, uint256]) 60 | totalSupply: public(uint256) 61 | future_epoch_time: public(uint256) 62 | 63 | # caller -> recipient -> can deposit? 64 | approved_to_deposit: public(HashMap[address, HashMap[address, bool]]) 65 | 66 | working_balances: public(HashMap[address, uint256]) 67 | working_supply: public(uint256) 68 | 69 | # The goal is to be able to calculate ∫(rate * balance / totalSupply dt) from 0 till checkpoint 70 | # All values are kept in units of being multiplied by 1e18 71 | period: public(int128) 72 | period_timestamp: public(uint256[100000000000000000000000000000]) 73 | 74 | # 1e18 * ∫(rate(t) / totalSupply(t) dt) from 0 till checkpoint 75 | integrate_inv_supply: public(uint256[100000000000000000000000000000]) # bump epoch when rate() changes 76 | 77 | # 1e18 * ∫(rate(t) / totalSupply(t) dt) from (last_action) till checkpoint 78 | integrate_inv_supply_of: public(HashMap[address, uint256]) 79 | integrate_checkpoint_of: public(HashMap[address, uint256]) 80 | 81 | 82 | # ∫(balance * rate(t) / totalSupply(t) dt) from 0 till checkpoint 83 | # Units: rate * t = already number of coins per address to issue 84 | integrate_fraction: public(HashMap[address, uint256]) 85 | 86 | inflation_rate: public(uint256) 87 | 88 | 89 | @external 90 | def __init__(lp_addr: address, _minter: address): 91 | """ 92 | @notice Contract constructor 93 | @param lp_addr Liquidity Pool contract address 94 | @param _minter Minter contract address 95 | """ 96 | 97 | assert lp_addr != ZERO_ADDRESS 98 | assert _minter != ZERO_ADDRESS 99 | 100 | self.lp_token = lp_addr 101 | self.minter = _minter 102 | crv_addr: address = Minter(_minter).token() 103 | self.crv_token = crv_addr 104 | controller_addr: address = Minter(_minter).controller() 105 | self.controller = controller_addr 106 | self.voting_escrow = Controller(controller_addr).voting_escrow() 107 | self.period_timestamp[0] = block.timestamp 108 | self.inflation_rate = CRV20(crv_addr).rate() 109 | self.future_epoch_time = CRV20(crv_addr).future_epoch_time_write() 110 | 111 | 112 | @internal 113 | def _update_liquidity_limit(addr: address, l: uint256, L: uint256): 114 | """ 115 | @notice Calculate limits which depend on the amount of CRV token per-user. 116 | Effectively it calculates working balances to apply amplification 117 | of CRV production by CRV 118 | @param addr User address 119 | @param l User's amount of liquidity (LP tokens) 120 | @param L Total amount of liquidity (LP tokens) 121 | """ 122 | # To be called after totalSupply is updated 123 | _voting_escrow: address = self.voting_escrow 124 | voting_balance: uint256 = ERC20(_voting_escrow).balanceOf(addr) 125 | voting_total: uint256 = ERC20(_voting_escrow).totalSupply() 126 | 127 | lim: uint256 = l * TOKENLESS_PRODUCTION / 100 128 | if (voting_total > 0) and (block.timestamp > self.period_timestamp[0] + BOOST_WARMUP): 129 | lim += L * voting_balance / voting_total * (100 - TOKENLESS_PRODUCTION) / 100 130 | 131 | lim = min(l, lim) 132 | old_bal: uint256 = self.working_balances[addr] 133 | self.working_balances[addr] = lim 134 | _working_supply: uint256 = self.working_supply + lim - old_bal 135 | self.working_supply = _working_supply 136 | 137 | log UpdateLiquidityLimit(addr, l, L, lim, _working_supply) 138 | 139 | 140 | @internal 141 | def _checkpoint(addr: address): 142 | """ 143 | @notice Checkpoint for a user 144 | @param addr User address 145 | """ 146 | _token: address = self.crv_token 147 | _controller: address = self.controller 148 | _period: int128 = self.period 149 | _period_time: uint256 = self.period_timestamp[_period] 150 | _integrate_inv_supply: uint256 = self.integrate_inv_supply[_period] 151 | rate: uint256 = self.inflation_rate 152 | new_rate: uint256 = rate 153 | prev_future_epoch: uint256 = self.future_epoch_time 154 | if prev_future_epoch >= _period_time: 155 | self.future_epoch_time = CRV20(_token).future_epoch_time_write() 156 | new_rate = CRV20(_token).rate() 157 | self.inflation_rate = new_rate 158 | Controller(_controller).checkpoint_gauge(self) 159 | 160 | _working_balance: uint256 = self.working_balances[addr] 161 | _working_supply: uint256 = self.working_supply 162 | 163 | # Update integral of 1/supply 164 | if block.timestamp > _period_time: 165 | prev_week_time: uint256 = _period_time 166 | week_time: uint256 = min((_period_time + WEEK) / WEEK * WEEK, block.timestamp) 167 | 168 | for i in range(500): 169 | dt: uint256 = week_time - prev_week_time 170 | w: uint256 = Controller(_controller).gauge_relative_weight(self, prev_week_time / WEEK * WEEK) 171 | 172 | if _working_supply > 0: 173 | if prev_future_epoch >= prev_week_time and prev_future_epoch < week_time: 174 | # If we went across one or multiple epochs, apply the rate 175 | # of the first epoch until it ends, and then the rate of 176 | # the last epoch. 177 | # If more than one epoch is crossed - the gauge gets less, 178 | # but that'd meen it wasn't called for more than 1 year 179 | _integrate_inv_supply += rate * w * (prev_future_epoch - prev_week_time) / _working_supply 180 | rate = new_rate 181 | _integrate_inv_supply += rate * w * (week_time - prev_future_epoch) / _working_supply 182 | else: 183 | _integrate_inv_supply += rate * w * dt / _working_supply 184 | # On precisions of the calculation 185 | # rate ~= 10e18 186 | # last_weight > 0.01 * 1e18 = 1e16 (if pool weight is 1%) 187 | # _working_supply ~= TVL * 1e18 ~= 1e26 ($100M for example) 188 | # The largest loss is at dt = 1 189 | # Loss is 1e-9 - acceptable 190 | 191 | if week_time == block.timestamp: 192 | break 193 | prev_week_time = week_time 194 | week_time = min(week_time + WEEK, block.timestamp) 195 | 196 | _period += 1 197 | self.period = _period 198 | self.period_timestamp[_period] = block.timestamp 199 | self.integrate_inv_supply[_period] = _integrate_inv_supply 200 | 201 | # Update user-specific integrals 202 | self.integrate_fraction[addr] += _working_balance * (_integrate_inv_supply - self.integrate_inv_supply_of[addr]) / 10 ** 18 203 | self.integrate_inv_supply_of[addr] = _integrate_inv_supply 204 | self.integrate_checkpoint_of[addr] = block.timestamp 205 | 206 | 207 | @external 208 | def user_checkpoint(addr: address) -> bool: 209 | """ 210 | @notice Record a checkpoint for `addr` 211 | @param addr User address 212 | @return bool success 213 | """ 214 | assert (msg.sender == addr) or (msg.sender == self.minter) # dev: unauthorized 215 | self._checkpoint(addr) 216 | self._update_liquidity_limit(addr, self.balanceOf[addr], self.totalSupply) 217 | return True 218 | 219 | 220 | @external 221 | def claimable_tokens(addr: address) -> uint256: 222 | """ 223 | @notice Get the number of claimable tokens per user 224 | @dev This function should be manually changed to "view" in the ABI 225 | @return uint256 number of claimable tokens per user 226 | """ 227 | self._checkpoint(addr) 228 | return self.integrate_fraction[addr] - Minter(self.minter).minted(addr, self) 229 | 230 | 231 | @external 232 | def kick(addr: address): 233 | """ 234 | @notice Kick `addr` for abusing their boost 235 | @dev Only if either they had another voting event, or their voting escrow lock expired 236 | @param addr Address to kick 237 | """ 238 | _voting_escrow: address = self.voting_escrow 239 | t_last: uint256 = self.integrate_checkpoint_of[addr] 240 | t_ve: uint256 = VotingEscrow(_voting_escrow).user_point_history__ts( 241 | addr, VotingEscrow(_voting_escrow).user_point_epoch(addr) 242 | ) 243 | _balance: uint256 = self.balanceOf[addr] 244 | 245 | assert ERC20(self.voting_escrow).balanceOf(addr) == 0 or t_ve > t_last # dev: kick not allowed 246 | assert self.working_balances[addr] > _balance * TOKENLESS_PRODUCTION / 100 # dev: kick not needed 247 | 248 | self._checkpoint(addr) 249 | self._update_liquidity_limit(addr, self.balanceOf[addr], self.totalSupply) 250 | 251 | 252 | @external 253 | def set_approve_deposit(addr: address, can_deposit: bool): 254 | """ 255 | @notice Set whether `addr` can deposit tokens for `msg.sender` 256 | @param addr Address to set approval on 257 | @param can_deposit bool - can this account deposit for `msg.sender`? 258 | """ 259 | self.approved_to_deposit[addr][msg.sender] = can_deposit 260 | 261 | 262 | @external 263 | @nonreentrant('lock') 264 | def deposit(_value: uint256, addr: address = msg.sender): 265 | """ 266 | @notice Deposit `_value` LP tokens 267 | @param _value Number of tokens to deposit 268 | @param addr Address to deposit for 269 | """ 270 | if addr != msg.sender: 271 | assert self.approved_to_deposit[msg.sender][addr], "Not approved" 272 | 273 | self._checkpoint(addr) 274 | 275 | if _value != 0: 276 | _balance: uint256 = self.balanceOf[addr] + _value 277 | _supply: uint256 = self.totalSupply + _value 278 | self.balanceOf[addr] = _balance 279 | self.totalSupply = _supply 280 | 281 | self._update_liquidity_limit(addr, _balance, _supply) 282 | 283 | assert ERC20(self.lp_token).transferFrom(msg.sender, self, _value) 284 | 285 | log Deposit(addr, _value) 286 | 287 | 288 | @external 289 | @nonreentrant('lock') 290 | def withdraw(_value: uint256): 291 | """ 292 | @notice Withdraw `_value` LP tokens 293 | @param _value Number of tokens to withdraw 294 | """ 295 | self._checkpoint(msg.sender) 296 | 297 | _balance: uint256 = self.balanceOf[msg.sender] - _value 298 | _supply: uint256 = self.totalSupply - _value 299 | self.balanceOf[msg.sender] = _balance 300 | self.totalSupply = _supply 301 | 302 | self._update_liquidity_limit(msg.sender, _balance, _supply) 303 | 304 | assert ERC20(self.lp_token).transfer(msg.sender, _value) 305 | 306 | log Withdraw(msg.sender, _value) 307 | 308 | 309 | @external 310 | @view 311 | def integrate_checkpoint() -> uint256: 312 | return self.period_timestamp[self.period] -------------------------------------------------------------------------------- /contracts/crvContract/cCrvGauge.vy: -------------------------------------------------------------------------------- 1 | # @version 0.2.4 2 | """ 3 | @title Liquidity Gauge 4 | @author Curve Finance 5 | @license MIT 6 | @notice Used for measuring liquidity and insurance 7 | """ 8 | 9 | from vyper.interfaces import ERC20 10 | 11 | interface CRV20: 12 | def future_epoch_time_write() -> uint256: nonpayable 13 | def rate() -> uint256: view 14 | 15 | interface Controller: 16 | def period() -> int128: view 17 | def period_write() -> int128: nonpayable 18 | def period_timestamp(p: int128) -> uint256: view 19 | def gauge_relative_weight(addr: address, time: uint256) -> uint256: view 20 | def voting_escrow() -> address: view 21 | def checkpoint(): nonpayable 22 | def checkpoint_gauge(addr: address): nonpayable 23 | 24 | interface Minter: 25 | def token() -> address: view 26 | def controller() -> address: view 27 | def minted(user: address, gauge: address) -> uint256: view 28 | 29 | interface VotingEscrow: 30 | def user_point_epoch(addr: address) -> uint256: view 31 | def user_point_history__ts(addr: address, epoch: uint256) -> uint256: view 32 | 33 | 34 | event Deposit: 35 | provider: indexed(address) 36 | value: uint256 37 | 38 | event Withdraw: 39 | provider: indexed(address) 40 | value: uint256 41 | 42 | event UpdateLiquidityLimit: 43 | user: address 44 | original_balance: uint256 45 | original_supply: uint256 46 | working_balance: uint256 47 | working_supply: uint256 48 | 49 | 50 | TOKENLESS_PRODUCTION: constant(uint256) = 40 51 | BOOST_WARMUP: constant(uint256) = 2 * 7 * 86400 52 | WEEK: constant(uint256) = 604800 53 | 54 | minter: public(address) 55 | crv_token: public(address) 56 | lp_token: public(address) 57 | controller: public(address) 58 | voting_escrow: public(address) 59 | balanceOf: public(HashMap[address, uint256]) 60 | totalSupply: public(uint256) 61 | future_epoch_time: public(uint256) 62 | 63 | # caller -> recipient -> can deposit? 64 | approved_to_deposit: public(HashMap[address, HashMap[address, bool]]) 65 | 66 | working_balances: public(HashMap[address, uint256]) 67 | working_supply: public(uint256) 68 | 69 | # The goal is to be able to calculate ∫(rate * balance / totalSupply dt) from 0 till checkpoint 70 | # All values are kept in units of being multiplied by 1e18 71 | period: public(int128) 72 | period_timestamp: public(uint256[100000000000000000000000000000]) 73 | 74 | # 1e18 * ∫(rate(t) / totalSupply(t) dt) from 0 till checkpoint 75 | integrate_inv_supply: public(uint256[100000000000000000000000000000]) # bump epoch when rate() changes 76 | 77 | # 1e18 * ∫(rate(t) / totalSupply(t) dt) from (last_action) till checkpoint 78 | integrate_inv_supply_of: public(HashMap[address, uint256]) 79 | integrate_checkpoint_of: public(HashMap[address, uint256]) 80 | 81 | 82 | # ∫(balance * rate(t) / totalSupply(t) dt) from 0 till checkpoint 83 | # Units: rate * t = already number of coins per address to issue 84 | integrate_fraction: public(HashMap[address, uint256]) 85 | 86 | inflation_rate: public(uint256) 87 | 88 | 89 | @external 90 | def __init__(lp_addr: address, _minter: address): 91 | """ 92 | @notice Contract constructor 93 | @param lp_addr Liquidity Pool contract address 94 | @param _minter Minter contract address 95 | """ 96 | 97 | assert lp_addr != ZERO_ADDRESS 98 | assert _minter != ZERO_ADDRESS 99 | 100 | self.lp_token = lp_addr 101 | self.minter = _minter 102 | crv_addr: address = Minter(_minter).token() 103 | self.crv_token = crv_addr 104 | controller_addr: address = Minter(_minter).controller() 105 | self.controller = controller_addr 106 | self.voting_escrow = Controller(controller_addr).voting_escrow() 107 | self.period_timestamp[0] = block.timestamp 108 | self.inflation_rate = CRV20(crv_addr).rate() 109 | self.future_epoch_time = CRV20(crv_addr).future_epoch_time_write() 110 | 111 | 112 | @internal 113 | def _update_liquidity_limit(addr: address, l: uint256, L: uint256): 114 | """ 115 | @notice Calculate limits which depend on the amount of CRV token per-user. 116 | Effectively it calculates working balances to apply amplification 117 | of CRV production by CRV 118 | @param addr User address 119 | @param l User's amount of liquidity (LP tokens) 120 | @param L Total amount of liquidity (LP tokens) 121 | """ 122 | # To be called after totalSupply is updated 123 | _voting_escrow: address = self.voting_escrow 124 | voting_balance: uint256 = ERC20(_voting_escrow).balanceOf(addr) 125 | voting_total: uint256 = ERC20(_voting_escrow).totalSupply() 126 | 127 | lim: uint256 = l * TOKENLESS_PRODUCTION / 100 128 | if (voting_total > 0) and (block.timestamp > self.period_timestamp[0] + BOOST_WARMUP): 129 | lim += L * voting_balance / voting_total * (100 - TOKENLESS_PRODUCTION) / 100 130 | 131 | lim = min(l, lim) 132 | old_bal: uint256 = self.working_balances[addr] 133 | self.working_balances[addr] = lim 134 | _working_supply: uint256 = self.working_supply + lim - old_bal 135 | self.working_supply = _working_supply 136 | 137 | log UpdateLiquidityLimit(addr, l, L, lim, _working_supply) 138 | 139 | 140 | @internal 141 | def _checkpoint(addr: address): 142 | """ 143 | @notice Checkpoint for a user 144 | @param addr User address 145 | """ 146 | _token: address = self.crv_token 147 | _controller: address = self.controller 148 | _period: int128 = self.period 149 | _period_time: uint256 = self.period_timestamp[_period] 150 | _integrate_inv_supply: uint256 = self.integrate_inv_supply[_period] 151 | rate: uint256 = self.inflation_rate 152 | new_rate: uint256 = rate 153 | prev_future_epoch: uint256 = self.future_epoch_time 154 | if prev_future_epoch >= _period_time: 155 | self.future_epoch_time = CRV20(_token).future_epoch_time_write() 156 | new_rate = CRV20(_token).rate() 157 | self.inflation_rate = new_rate 158 | Controller(_controller).checkpoint_gauge(self) 159 | 160 | _working_balance: uint256 = self.working_balances[addr] 161 | _working_supply: uint256 = self.working_supply 162 | 163 | # Update integral of 1/supply 164 | if block.timestamp > _period_time: 165 | prev_week_time: uint256 = _period_time 166 | week_time: uint256 = min((_period_time + WEEK) / WEEK * WEEK, block.timestamp) 167 | 168 | for i in range(500): 169 | dt: uint256 = week_time - prev_week_time 170 | w: uint256 = Controller(_controller).gauge_relative_weight(self, prev_week_time / WEEK * WEEK) 171 | 172 | if _working_supply > 0: 173 | if prev_future_epoch >= prev_week_time and prev_future_epoch < week_time: 174 | # If we went across one or multiple epochs, apply the rate 175 | # of the first epoch until it ends, and then the rate of 176 | # the last epoch. 177 | # If more than one epoch is crossed - the gauge gets less, 178 | # but that'd meen it wasn't called for more than 1 year 179 | _integrate_inv_supply += rate * w * (prev_future_epoch - prev_week_time) / _working_supply 180 | rate = new_rate 181 | _integrate_inv_supply += rate * w * (week_time - prev_future_epoch) / _working_supply 182 | else: 183 | _integrate_inv_supply += rate * w * dt / _working_supply 184 | # On precisions of the calculation 185 | # rate ~= 10e18 186 | # last_weight > 0.01 * 1e18 = 1e16 (if pool weight is 1%) 187 | # _working_supply ~= TVL * 1e18 ~= 1e26 ($100M for example) 188 | # The largest loss is at dt = 1 189 | # Loss is 1e-9 - acceptable 190 | 191 | if week_time == block.timestamp: 192 | break 193 | prev_week_time = week_time 194 | week_time = min(week_time + WEEK, block.timestamp) 195 | 196 | _period += 1 197 | self.period = _period 198 | self.period_timestamp[_period] = block.timestamp 199 | self.integrate_inv_supply[_period] = _integrate_inv_supply 200 | 201 | # Update user-specific integrals 202 | self.integrate_fraction[addr] += _working_balance * (_integrate_inv_supply - self.integrate_inv_supply_of[addr]) / 10 ** 18 203 | self.integrate_inv_supply_of[addr] = _integrate_inv_supply 204 | self.integrate_checkpoint_of[addr] = block.timestamp 205 | 206 | 207 | @external 208 | def user_checkpoint(addr: address) -> bool: 209 | """ 210 | @notice Record a checkpoint for `addr` 211 | @param addr User address 212 | @return bool success 213 | """ 214 | assert (msg.sender == addr) or (msg.sender == self.minter) # dev: unauthorized 215 | self._checkpoint(addr) 216 | self._update_liquidity_limit(addr, self.balanceOf[addr], self.totalSupply) 217 | return True 218 | 219 | 220 | @external 221 | def claimable_tokens(addr: address) -> uint256: 222 | """ 223 | @notice Get the number of claimable tokens per user 224 | @dev This function should be manually changed to "view" in the ABI 225 | @return uint256 number of claimable tokens per user 226 | """ 227 | self._checkpoint(addr) 228 | return self.integrate_fraction[addr] - Minter(self.minter).minted(addr, self) 229 | 230 | 231 | @external 232 | def kick(addr: address): 233 | """ 234 | @notice Kick `addr` for abusing their boost 235 | @dev Only if either they had another voting event, or their voting escrow lock expired 236 | @param addr Address to kick 237 | """ 238 | _voting_escrow: address = self.voting_escrow 239 | t_last: uint256 = self.integrate_checkpoint_of[addr] 240 | t_ve: uint256 = VotingEscrow(_voting_escrow).user_point_history__ts( 241 | addr, VotingEscrow(_voting_escrow).user_point_epoch(addr) 242 | ) 243 | _balance: uint256 = self.balanceOf[addr] 244 | 245 | assert ERC20(self.voting_escrow).balanceOf(addr) == 0 or t_ve > t_last # dev: kick not allowed 246 | assert self.working_balances[addr] > _balance * TOKENLESS_PRODUCTION / 100 # dev: kick not needed 247 | 248 | self._checkpoint(addr) 249 | self._update_liquidity_limit(addr, self.balanceOf[addr], self.totalSupply) 250 | 251 | 252 | @external 253 | def set_approve_deposit(addr: address, can_deposit: bool): 254 | """ 255 | @notice Set whether `addr` can deposit tokens for `msg.sender` 256 | @param addr Address to set approval on 257 | @param can_deposit bool - can this account deposit for `msg.sender`? 258 | """ 259 | self.approved_to_deposit[addr][msg.sender] = can_deposit 260 | 261 | 262 | @external 263 | @nonreentrant('lock') 264 | def deposit(_value: uint256, addr: address = msg.sender): 265 | """ 266 | @notice Deposit `_value` LP tokens 267 | @param _value Number of tokens to deposit 268 | @param addr Address to deposit for 269 | """ 270 | if addr != msg.sender: 271 | assert self.approved_to_deposit[msg.sender][addr], "Not approved" 272 | 273 | self._checkpoint(addr) 274 | 275 | if _value != 0: 276 | _balance: uint256 = self.balanceOf[addr] + _value 277 | _supply: uint256 = self.totalSupply + _value 278 | self.balanceOf[addr] = _balance 279 | self.totalSupply = _supply 280 | 281 | self._update_liquidity_limit(addr, _balance, _supply) 282 | 283 | assert ERC20(self.lp_token).transferFrom(msg.sender, self, _value) 284 | 285 | log Deposit(addr, _value) 286 | 287 | 288 | @external 289 | @nonreentrant('lock') 290 | def withdraw(_value: uint256): 291 | """ 292 | @notice Withdraw `_value` LP tokens 293 | @param _value Number of tokens to withdraw 294 | """ 295 | self._checkpoint(msg.sender) 296 | 297 | _balance: uint256 = self.balanceOf[msg.sender] - _value 298 | _supply: uint256 = self.totalSupply - _value 299 | self.balanceOf[msg.sender] = _balance 300 | self.totalSupply = _supply 301 | 302 | self._update_liquidity_limit(msg.sender, _balance, _supply) 303 | 304 | assert ERC20(self.lp_token).transfer(msg.sender, _value) 305 | 306 | log Withdraw(msg.sender, _value) 307 | 308 | 309 | @external 310 | @view 311 | def integrate_checkpoint() -> uint256: 312 | return self.period_timestamp[self.period] -------------------------------------------------------------------------------- /contracts/crvContract/ycrvGauge.vy: -------------------------------------------------------------------------------- 1 | # @version 0.2.4 2 | """ 3 | @title Liquidity Gauge 4 | @author Curve Finance 5 | @license MIT 6 | @notice Used for measuring liquidity and insurance 7 | """ 8 | 9 | from vyper.interfaces import ERC20 10 | 11 | interface CRV20: 12 | def future_epoch_time_write() -> uint256: nonpayable 13 | def rate() -> uint256: view 14 | 15 | interface Controller: 16 | def period() -> int128: view 17 | def period_write() -> int128: nonpayable 18 | def period_timestamp(p: int128) -> uint256: view 19 | def gauge_relative_weight(addr: address, time: uint256) -> uint256: view 20 | def voting_escrow() -> address: view 21 | def checkpoint(): nonpayable 22 | def checkpoint_gauge(addr: address): nonpayable 23 | 24 | interface Minter: 25 | def token() -> address: view 26 | def controller() -> address: view 27 | def minted(user: address, gauge: address) -> uint256: view 28 | 29 | interface VotingEscrow: 30 | def user_point_epoch(addr: address) -> uint256: view 31 | def user_point_history__ts(addr: address, epoch: uint256) -> uint256: view 32 | 33 | 34 | event Deposit: 35 | provider: indexed(address) 36 | value: uint256 37 | 38 | event Withdraw: 39 | provider: indexed(address) 40 | value: uint256 41 | 42 | event UpdateLiquidityLimit: 43 | user: address 44 | original_balance: uint256 45 | original_supply: uint256 46 | working_balance: uint256 47 | working_supply: uint256 48 | 49 | 50 | TOKENLESS_PRODUCTION: constant(uint256) = 40 51 | BOOST_WARMUP: constant(uint256) = 2 * 7 * 86400 52 | WEEK: constant(uint256) = 604800 53 | 54 | minter: public(address) 55 | crv_token: public(address) 56 | lp_token: public(address) 57 | controller: public(address) 58 | voting_escrow: public(address) 59 | balanceOf: public(HashMap[address, uint256]) 60 | totalSupply: public(uint256) 61 | future_epoch_time: public(uint256) 62 | 63 | # caller -> recipient -> can deposit? 64 | approved_to_deposit: public(HashMap[address, HashMap[address, bool]]) 65 | 66 | working_balances: public(HashMap[address, uint256]) 67 | working_supply: public(uint256) 68 | 69 | # The goal is to be able to calculate ∫(rate * balance / totalSupply dt) from 0 till checkpoint 70 | # All values are kept in units of being multiplied by 1e18 71 | period: public(int128) 72 | period_timestamp: public(uint256[100000000000000000000000000000]) 73 | 74 | # 1e18 * ∫(rate(t) / totalSupply(t) dt) from 0 till checkpoint 75 | integrate_inv_supply: public(uint256[100000000000000000000000000000]) # bump epoch when rate() changes 76 | 77 | # 1e18 * ∫(rate(t) / totalSupply(t) dt) from (last_action) till checkpoint 78 | integrate_inv_supply_of: public(HashMap[address, uint256]) 79 | integrate_checkpoint_of: public(HashMap[address, uint256]) 80 | 81 | 82 | # ∫(balance * rate(t) / totalSupply(t) dt) from 0 till checkpoint 83 | # Units: rate * t = already number of coins per address to issue 84 | integrate_fraction: public(HashMap[address, uint256]) 85 | 86 | inflation_rate: public(uint256) 87 | 88 | 89 | @external 90 | def __init__(lp_addr: address, _minter: address): 91 | """ 92 | @notice Contract constructor 93 | @param lp_addr Liquidity Pool contract address 94 | @param _minter Minter contract address 95 | """ 96 | 97 | assert lp_addr != ZERO_ADDRESS 98 | assert _minter != ZERO_ADDRESS 99 | 100 | self.lp_token = lp_addr 101 | self.minter = _minter 102 | crv_addr: address = Minter(_minter).token() 103 | self.crv_token = crv_addr 104 | controller_addr: address = Minter(_minter).controller() 105 | self.controller = controller_addr 106 | self.voting_escrow = Controller(controller_addr).voting_escrow() 107 | self.period_timestamp[0] = block.timestamp 108 | self.inflation_rate = CRV20(crv_addr).rate() 109 | self.future_epoch_time = CRV20(crv_addr).future_epoch_time_write() 110 | 111 | 112 | @internal 113 | def _update_liquidity_limit(addr: address, l: uint256, L: uint256): 114 | """ 115 | @notice Calculate limits which depend on the amount of CRV token per-user. 116 | Effectively it calculates working balances to apply amplification 117 | of CRV production by CRV 118 | @param addr User address 119 | @param l User's amount of liquidity (LP tokens) 120 | @param L Total amount of liquidity (LP tokens) 121 | """ 122 | # To be called after totalSupply is updated 123 | _voting_escrow: address = self.voting_escrow 124 | voting_balance: uint256 = ERC20(_voting_escrow).balanceOf(addr) 125 | voting_total: uint256 = ERC20(_voting_escrow).totalSupply() 126 | 127 | lim: uint256 = l * TOKENLESS_PRODUCTION / 100 128 | if (voting_total > 0) and (block.timestamp > self.period_timestamp[0] + BOOST_WARMUP): 129 | lim += L * voting_balance / voting_total * (100 - TOKENLESS_PRODUCTION) / 100 130 | 131 | lim = min(l, lim) 132 | old_bal: uint256 = self.working_balances[addr] 133 | self.working_balances[addr] = lim 134 | _working_supply: uint256 = self.working_supply + lim - old_bal 135 | self.working_supply = _working_supply 136 | 137 | log UpdateLiquidityLimit(addr, l, L, lim, _working_supply) 138 | 139 | 140 | @internal 141 | def _checkpoint(addr: address): 142 | """ 143 | @notice Checkpoint for a user 144 | @param addr User address 145 | """ 146 | _token: address = self.crv_token 147 | _controller: address = self.controller 148 | _period: int128 = self.period 149 | _period_time: uint256 = self.period_timestamp[_period] 150 | _integrate_inv_supply: uint256 = self.integrate_inv_supply[_period] 151 | rate: uint256 = self.inflation_rate 152 | new_rate: uint256 = rate 153 | prev_future_epoch: uint256 = self.future_epoch_time 154 | if prev_future_epoch >= _period_time: 155 | self.future_epoch_time = CRV20(_token).future_epoch_time_write() 156 | new_rate = CRV20(_token).rate() 157 | self.inflation_rate = new_rate 158 | Controller(_controller).checkpoint_gauge(self) 159 | 160 | _working_balance: uint256 = self.working_balances[addr] 161 | _working_supply: uint256 = self.working_supply 162 | 163 | # Update integral of 1/supply 164 | if block.timestamp > _period_time: 165 | prev_week_time: uint256 = _period_time 166 | week_time: uint256 = min((_period_time + WEEK) / WEEK * WEEK, block.timestamp) 167 | 168 | for i in range(500): 169 | dt: uint256 = week_time - prev_week_time 170 | w: uint256 = Controller(_controller).gauge_relative_weight(self, prev_week_time / WEEK * WEEK) 171 | 172 | if _working_supply > 0: 173 | if prev_future_epoch >= prev_week_time and prev_future_epoch < week_time: 174 | # If we went across one or multiple epochs, apply the rate 175 | # of the first epoch until it ends, and then the rate of 176 | # the last epoch. 177 | # If more than one epoch is crossed - the gauge gets less, 178 | # but that'd meen it wasn't called for more than 1 year 179 | _integrate_inv_supply += rate * w * (prev_future_epoch - prev_week_time) / _working_supply 180 | rate = new_rate 181 | _integrate_inv_supply += rate * w * (week_time - prev_future_epoch) / _working_supply 182 | else: 183 | _integrate_inv_supply += rate * w * dt / _working_supply 184 | # On precisions of the calculation 185 | # rate ~= 10e18 186 | # last_weight > 0.01 * 1e18 = 1e16 (if pool weight is 1%) 187 | # _working_supply ~= TVL * 1e18 ~= 1e26 ($100M for example) 188 | # The largest loss is at dt = 1 189 | # Loss is 1e-9 - acceptable 190 | 191 | if week_time == block.timestamp: 192 | break 193 | prev_week_time = week_time 194 | week_time = min(week_time + WEEK, block.timestamp) 195 | 196 | _period += 1 197 | self.period = _period 198 | self.period_timestamp[_period] = block.timestamp 199 | self.integrate_inv_supply[_period] = _integrate_inv_supply 200 | 201 | # Update user-specific integrals 202 | self.integrate_fraction[addr] += _working_balance * (_integrate_inv_supply - self.integrate_inv_supply_of[addr]) / 10 ** 18 203 | self.integrate_inv_supply_of[addr] = _integrate_inv_supply 204 | self.integrate_checkpoint_of[addr] = block.timestamp 205 | 206 | 207 | @external 208 | def user_checkpoint(addr: address) -> bool: 209 | """ 210 | @notice Record a checkpoint for `addr` 211 | @param addr User address 212 | @return bool success 213 | """ 214 | assert (msg.sender == addr) or (msg.sender == self.minter) # dev: unauthorized 215 | self._checkpoint(addr) 216 | self._update_liquidity_limit(addr, self.balanceOf[addr], self.totalSupply) 217 | return True 218 | 219 | 220 | @external 221 | def claimable_tokens(addr: address) -> uint256: 222 | """ 223 | @notice Get the number of claimable tokens per user 224 | @dev This function should be manually changed to "view" in the ABI 225 | @return uint256 number of claimable tokens per user 226 | """ 227 | self._checkpoint(addr) 228 | return self.integrate_fraction[addr] - Minter(self.minter).minted(addr, self) 229 | 230 | 231 | @external 232 | def kick(addr: address): 233 | """ 234 | @notice Kick `addr` for abusing their boost 235 | @dev Only if either they had another voting event, or their voting escrow lock expired 236 | @param addr Address to kick 237 | """ 238 | _voting_escrow: address = self.voting_escrow 239 | t_last: uint256 = self.integrate_checkpoint_of[addr] 240 | t_ve: uint256 = VotingEscrow(_voting_escrow).user_point_history__ts( 241 | addr, VotingEscrow(_voting_escrow).user_point_epoch(addr) 242 | ) 243 | _balance: uint256 = self.balanceOf[addr] 244 | 245 | assert ERC20(self.voting_escrow).balanceOf(addr) == 0 or t_ve > t_last # dev: kick not allowed 246 | assert self.working_balances[addr] > _balance * TOKENLESS_PRODUCTION / 100 # dev: kick not needed 247 | 248 | self._checkpoint(addr) 249 | self._update_liquidity_limit(addr, self.balanceOf[addr], self.totalSupply) 250 | 251 | 252 | @external 253 | def set_approve_deposit(addr: address, can_deposit: bool): 254 | """ 255 | @notice Set whether `addr` can deposit tokens for `msg.sender` 256 | @param addr Address to set approval on 257 | @param can_deposit bool - can this account deposit for `msg.sender`? 258 | """ 259 | self.approved_to_deposit[addr][msg.sender] = can_deposit 260 | 261 | 262 | @external 263 | @nonreentrant('lock') 264 | def deposit(_value: uint256, addr: address = msg.sender): 265 | """ 266 | @notice Deposit `_value` LP tokens 267 | @param _value Number of tokens to deposit 268 | @param addr Address to deposit for 269 | """ 270 | if addr != msg.sender: 271 | assert self.approved_to_deposit[msg.sender][addr], "Not approved" 272 | 273 | self._checkpoint(addr) 274 | 275 | if _value != 0: 276 | _balance: uint256 = self.balanceOf[addr] + _value 277 | _supply: uint256 = self.totalSupply + _value 278 | self.balanceOf[addr] = _balance 279 | self.totalSupply = _supply 280 | 281 | self._update_liquidity_limit(addr, _balance, _supply) 282 | 283 | assert ERC20(self.lp_token).transferFrom(msg.sender, self, _value) 284 | 285 | log Deposit(addr, _value) 286 | 287 | 288 | @external 289 | @nonreentrant('lock') 290 | def withdraw(_value: uint256): 291 | """ 292 | @notice Withdraw `_value` LP tokens 293 | @param _value Number of tokens to withdraw 294 | """ 295 | self._checkpoint(msg.sender) 296 | 297 | _balance: uint256 = self.balanceOf[msg.sender] - _value 298 | _supply: uint256 = self.totalSupply - _value 299 | self.balanceOf[msg.sender] = _balance 300 | self.totalSupply = _supply 301 | 302 | self._update_liquidity_limit(msg.sender, _balance, _supply) 303 | 304 | assert ERC20(self.lp_token).transfer(msg.sender, _value) 305 | 306 | log Withdraw(msg.sender, _value) 307 | 308 | 309 | @external 310 | @view 311 | def integrate_checkpoint() -> uint256: 312 | return self.period_timestamp[self.period] -------------------------------------------------------------------------------- /contracts/i/iusd.vy: -------------------------------------------------------------------------------- 1 | # https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md 2 | 3 | from vyper.interfaces import ERC20 4 | 5 | implements: ERC20 6 | 7 | Transfer: event({_from: indexed(address), _to: indexed(address), _value: uint256}) 8 | Approval: event({_owner: indexed(address), _spender: indexed(address), _value: uint256}) 9 | 10 | name: public(string[64]) 11 | symbol: public(string[32]) 12 | decimals: public(uint256) 13 | 14 | # NOTE: By declaring `balanceOf` as public, vyper automatically generates a 'balanceOf()' getter 15 | # method to allow access to account balances. 16 | # The _KeyType will become a required parameter for the getter and it will return _ValueType. 17 | # See: https://vyper.readthedocs.io/en/v0.1.0-beta.8/types.html?highlight=getter#mappings 18 | balanceOf: public(map(address, uint256)) 19 | allowances: map(address, map(address, uint256)) 20 | total_supply: uint256 21 | minter: address 22 | 23 | 24 | @public 25 | def __init__(_name: string[64], _symbol: string[32], _decimals: uint256, _supply: uint256): 26 | init_supply: uint256 = _supply * 10 ** _decimals 27 | self.name = _name 28 | self.symbol = _symbol 29 | self.decimals = _decimals 30 | self.balanceOf[msg.sender] = init_supply 31 | self.total_supply = init_supply 32 | self.minter = msg.sender 33 | log.Transfer(ZERO_ADDRESS, msg.sender, init_supply) 34 | 35 | 36 | @public 37 | def set_minter(_minter: address): 38 | assert msg.sender == self.minter 39 | self.minter = _minter 40 | 41 | 42 | @public 43 | @constant 44 | def totalSupply() -> uint256: 45 | """ 46 | @dev Total number of tokens in existence. 47 | """ 48 | return self.total_supply 49 | 50 | 51 | @public 52 | @constant 53 | def allowance(_owner : address, _spender : address) -> uint256: 54 | """ 55 | @dev Function to check the amount of tokens that an owner allowed to a spender. 56 | @param _owner The address which owns the funds. 57 | @param _spender The address which will spend the funds. 58 | @return An uint256 specifying the amount of tokens still available for the spender. 59 | """ 60 | return self.allowances[_owner][_spender] 61 | 62 | 63 | @public 64 | def transfer(_to : address, _value : uint256) -> bool: 65 | """ 66 | @dev Transfer token for a specified address 67 | @param _to The address to transfer to. 68 | @param _value The amount to be transferred. 69 | """ 70 | # NOTE: vyper does not allow underflows 71 | # so the following subtraction would revert on insufficient balance 72 | self.balanceOf[msg.sender] -= _value 73 | self.balanceOf[_to] += _value 74 | log.Transfer(msg.sender, _to, _value) 75 | return True 76 | 77 | 78 | @public 79 | def transferFrom(_from : address, _to : address, _value : uint256) -> bool: 80 | """ 81 | @dev Transfer tokens from one address to another. 82 | Note that while this function emits a Transfer event, this is not required as per the specification, 83 | and other compliant implementations may not emit the event. 84 | @param _from address The address which you want to send tokens from 85 | @param _to address The address which you want to transfer to 86 | @param _value uint256 the amount of tokens to be transferred 87 | """ 88 | # NOTE: vyper does not allow underflows 89 | # so the following subtraction would revert on insufficient balance 90 | self.balanceOf[_from] -= _value 91 | self.balanceOf[_to] += _value 92 | if msg.sender != self.minter: # minter is allowed to transfer anything 93 | # NOTE: vyper does not allow underflows 94 | # so the following subtraction would revert on insufficient allowance 95 | self.allowances[_from][msg.sender] -= _value 96 | log.Transfer(_from, _to, _value) 97 | return True 98 | 99 | 100 | @public 101 | def approve(_spender : address, _value : uint256) -> bool: 102 | """ 103 | @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 104 | Beware that changing an allowance with this method brings the risk that someone may use both the old 105 | and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 106 | race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 107 | https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 108 | @param _spender The address which will spend the funds. 109 | @param _value The amount of tokens to be spent. 110 | """ 111 | assert _value == 0 or self.allowances[msg.sender][_spender] == 0 112 | self.allowances[msg.sender][_spender] = _value 113 | log.Approval(msg.sender, _spender, _value) 114 | return True 115 | 116 | 117 | @public 118 | def mint(_to: address, _value: uint256): 119 | """ 120 | @dev Mint an amount of the token and assigns it to an account. 121 | This encapsulates the modification of balances such that the 122 | proper events are emitted. 123 | @param _to The account that will receive the created tokens. 124 | @param _value The amount that will be created. 125 | """ 126 | assert msg.sender == self.minter 127 | assert _to != ZERO_ADDRESS 128 | self.total_supply += _value 129 | self.balanceOf[_to] += _value 130 | log.Transfer(ZERO_ADDRESS, _to, _value) 131 | 132 | 133 | @private 134 | def _burn(_to: address, _value: uint256): 135 | """ 136 | @dev Internal function that burns an amount of the token of a given 137 | account. 138 | @param _to The account whose tokens will be burned. 139 | @param _value The amount that will be burned. 140 | """ 141 | assert _to != ZERO_ADDRESS 142 | self.total_supply -= _value 143 | self.balanceOf[_to] -= _value 144 | log.Transfer(_to, ZERO_ADDRESS, _value) 145 | 146 | 147 | @public 148 | def burn(_value: uint256): 149 | """ 150 | @dev Burn an amount of the token of msg.sender. 151 | @param _value The amount that will be burned. 152 | """ 153 | assert msg.sender == self.minter, "Only minter is allowed to burn" 154 | self._burn(msg.sender, _value) 155 | 156 | 157 | @public 158 | def burnFrom(_to: address, _value: uint256): 159 | """ 160 | @dev Burn an amount of the token from a given account. 161 | @param _to The account whose tokens will be burned. 162 | @param _value The amount that will be burned. 163 | """ 164 | assert msg.sender == self.minter, "Only minter is allowed to burn" 165 | self._burn(_to, _value) -------------------------------------------------------------------------------- /contracts/i/readme.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 4 | 5 | ydeposit: 0xbBC81d23Ea2c3ec7e56D39296F0cbB648873a5d3 6 | yswap: 0x45F783CCE6B7FF23B2ab2D70e416cdb7D6055f51 7 | ycrv:0xdF5e0e81Dff6FAF3A7e52BA697820c5e32D806A8 8 | 9 | # 10 | -------------------------------------------------------------------------------- /contracts/i/ycrv.vy: -------------------------------------------------------------------------------- 1 | # https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md 2 | 3 | from vyper.interfaces import ERC20 4 | 5 | implements: ERC20 6 | 7 | Transfer: event({_from: indexed(address), _to: indexed(address), _value: uint256}) 8 | Approval: event({_owner: indexed(address), _spender: indexed(address), _value: uint256}) 9 | 10 | name: public(string[64]) 11 | symbol: public(string[32]) 12 | decimals: public(uint256) 13 | 14 | # NOTE: By declaring `balanceOf` as public, vyper automatically generates a 'balanceOf()' getter 15 | # method to allow access to account balances. 16 | # The _KeyType will become a required parameter for the getter and it will return _ValueType. 17 | # See: https://vyper.readthedocs.io/en/v0.1.0-beta.8/types.html?highlight=getter#mappings 18 | balanceOf: public(map(address, uint256)) 19 | allowances: map(address, map(address, uint256)) 20 | total_supply: uint256 21 | minter: address 22 | 23 | 24 | @public 25 | def __init__(_name: string[64], _symbol: string[32], _decimals: uint256, _supply: uint256): 26 | init_supply: uint256 = _supply * 10 ** _decimals 27 | self.name = _name 28 | self.symbol = _symbol 29 | self.decimals = _decimals 30 | self.balanceOf[msg.sender] = init_supply 31 | self.total_supply = init_supply 32 | self.minter = msg.sender 33 | log.Transfer(ZERO_ADDRESS, msg.sender, init_supply) 34 | 35 | 36 | @public 37 | def set_minter(_minter: address): 38 | assert msg.sender == self.minter 39 | self.minter = _minter 40 | 41 | 42 | @public 43 | @constant 44 | def totalSupply() -> uint256: 45 | """ 46 | @dev Total number of tokens in existence. 47 | """ 48 | return self.total_supply 49 | 50 | 51 | @public 52 | @constant 53 | def allowance(_owner : address, _spender : address) -> uint256: 54 | """ 55 | @dev Function to check the amount of tokens that an owner allowed to a spender. 56 | @param _owner The address which owns the funds. 57 | @param _spender The address which will spend the funds. 58 | @return An uint256 specifying the amount of tokens still available for the spender. 59 | """ 60 | return self.allowances[_owner][_spender] 61 | 62 | 63 | @public 64 | def transfer(_to : address, _value : uint256) -> bool: 65 | """ 66 | @dev Transfer token for a specified address 67 | @param _to The address to transfer to. 68 | @param _value The amount to be transferred. 69 | """ 70 | # NOTE: vyper does not allow underflows 71 | # so the following subtraction would revert on insufficient balance 72 | self.balanceOf[msg.sender] -= _value 73 | self.balanceOf[_to] += _value 74 | log.Transfer(msg.sender, _to, _value) 75 | return True 76 | 77 | 78 | @public 79 | def transferFrom(_from : address, _to : address, _value : uint256) -> bool: 80 | """ 81 | @dev Transfer tokens from one address to another. 82 | Note that while this function emits a Transfer event, this is not required as per the specification, 83 | and other compliant implementations may not emit the event. 84 | @param _from address The address which you want to send tokens from 85 | @param _to address The address which you want to transfer to 86 | @param _value uint256 the amount of tokens to be transferred 87 | """ 88 | # NOTE: vyper does not allow underflows 89 | # so the following subtraction would revert on insufficient balance 90 | self.balanceOf[_from] -= _value 91 | self.balanceOf[_to] += _value 92 | if msg.sender != self.minter: # minter is allowed to transfer anything 93 | # NOTE: vyper does not allow underflows 94 | # so the following subtraction would revert on insufficient allowance 95 | self.allowances[_from][msg.sender] -= _value 96 | log.Transfer(_from, _to, _value) 97 | return True 98 | 99 | 100 | @public 101 | def approve(_spender : address, _value : uint256) -> bool: 102 | """ 103 | @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 104 | Beware that changing an allowance with this method brings the risk that someone may use both the old 105 | and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 106 | race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 107 | https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 108 | @param _spender The address which will spend the funds. 109 | @param _value The amount of tokens to be spent. 110 | """ 111 | assert _value == 0 or self.allowances[msg.sender][_spender] == 0 112 | self.allowances[msg.sender][_spender] = _value 113 | log.Approval(msg.sender, _spender, _value) 114 | return True 115 | 116 | 117 | @public 118 | def mint(_to: address, _value: uint256): 119 | """ 120 | @dev Mint an amount of the token and assigns it to an account. 121 | This encapsulates the modification of balances such that the 122 | proper events are emitted. 123 | @param _to The account that will receive the created tokens. 124 | @param _value The amount that will be created. 125 | """ 126 | assert msg.sender == self.minter 127 | assert _to != ZERO_ADDRESS 128 | self.total_supply += _value 129 | self.balanceOf[_to] += _value 130 | log.Transfer(ZERO_ADDRESS, _to, _value) 131 | 132 | 133 | @private 134 | def _burn(_to: address, _value: uint256): 135 | """ 136 | @dev Internal function that burns an amount of the token of a given 137 | account. 138 | @param _to The account whose tokens will be burned. 139 | @param _value The amount that will be burned. 140 | """ 141 | assert _to != ZERO_ADDRESS 142 | self.total_supply -= _value 143 | self.balanceOf[_to] -= _value 144 | log.Transfer(_to, ZERO_ADDRESS, _value) 145 | 146 | 147 | @public 148 | def burn(_value: uint256): 149 | """ 150 | @dev Burn an amount of the token of msg.sender. 151 | @param _value The amount that will be burned. 152 | """ 153 | assert msg.sender == self.minter, "Only minter is allowed to burn" 154 | self._burn(msg.sender, _value) 155 | 156 | 157 | @public 158 | def burnFrom(_to: address, _value: uint256): 159 | """ 160 | @dev Burn an amount of the token from a given account. 161 | @param _to The account whose tokens will be burned. 162 | @param _value The amount that will be burned. 163 | """ 164 | assert msg.sender == self.minter, "Only minter is allowed to burn" 165 | self._burn(_to, _value) -------------------------------------------------------------------------------- /contracts/readme.md: -------------------------------------------------------------------------------- 1 | # yVault 2 | 3 | 4 | ## Controller 5 | 6 | earn -> Strategy.deposit 7 | 8 | withdrawall-> Strategy.withdrawall 9 | 10 | withdraw -> Strategy.withdraw 11 | 12 | balanceOf -> Strategy.balanceOf 13 | 14 | 15 | ## yvault: 16 | 17 | earn -> Controller.earn 18 | 19 | deposit:用户存钱 20 | 21 | withdraw:用户取钱。(钱不够触发。 Controller.withdraw 22 | 23 | claim: 用户领取分红 24 | 25 | make_profit: Strategy.harvest 触发分红. 26 | 27 | cal_out: 某个用户可领取的分红 28 | 29 | cal_out_pending: 某个用户在路上的分红(也就是分红还没有从挖矿合约领取.只能看到,无法领取,等harvest触发后就可以领取了) 30 | 31 | balanceOf: token.balanceOf(address(this)) + Controller.balanceOf (也就是TVL) 32 | 33 | ## Strategy 34 | 35 | deposit: 存钱到某个合约 获取利息啥的 36 | 37 | withdraw: 从某个合约取钱出来 38 | 39 | withdrawall: 把所有的钱从挖矿合约退出. 40 | 41 | harvest: 领取分红. 42 | 43 | balanceOf: 存放在挖矿合约里面的钱 44 | 45 | balanceOfPendingReward:还未从挖矿合约领取的收益. 46 | 47 | 48 | ## yam 相关合约 49 | 50 | yam:0x0e2298E3B3390e3b945a5456fBf59eCc3f55DA16 51 | 52 | wethpool:0x587A07cE5c265A38Dd6d42def1566BA73eeb06F5 weth:0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 53 | snxpool:0x6c3FC1FFDb14D92394f40eeC91D9Ce8B807f132D snx:0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F 54 | lendpool:0x6009A344C7F993B16EBa2c673fefd2e07f9be5FD lend:0x80fB784B7eD66730e8b1DBd9820aFD29931aab03 55 | mkrpool:0xcFe1E539AcB2D489a651cA011a6eB93d32f97E23 mkr:0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2 56 | amplpool:0x9EbB67687FEE2d265D7b824714DF13622D90E663 ampl_lp:0xc5be99A02C6857f9Eac67BbCE58DF5572498F40c 57 | yfipool:0xc5B6488c7D5BeD173B76Bd5DCA712f45fB9EaEaB yfi:0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e 58 | linkpool:0xFDC28897A1E32B595f1f4f1D3aE0Df93B1eee452 link:0x514910771AF9Ca656af840dff83E8264EcF986CA 59 | comppool:0x8538E5910c6F80419CD3170c26073Ff238048c9E comp:0xc00e94Cb662C3520282E6f5717214004A7f26888 60 | 61 | -------------------------------------------------------------------------------- /contracts/standard/Controller.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at Etherscan.io on 2020-07-26 3 | */ 4 | 5 | // SPDX-License-Identifier: MIT 6 | 7 | pragma solidity ^0.5.15; 8 | 9 | interface IERC20 { 10 | function totalSupply() external view returns (uint256); 11 | function balanceOf(address account) external view returns (uint256); 12 | function transfer(address recipient, uint256 amount) external returns (bool); 13 | function allowance(address owner, address spender) external view returns (uint256); 14 | function approve(address spender, uint256 amount) external returns (bool); 15 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 16 | event Transfer(address indexed from, address indexed to, uint256 value); 17 | event Approval(address indexed owner, address indexed spender, uint256 value); 18 | } 19 | 20 | library SafeMath { 21 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 22 | uint256 c = a + b; 23 | require(c >= a, "SafeMath: addition overflow"); 24 | 25 | return c; 26 | } 27 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 28 | return sub(a, b, "SafeMath: subtraction overflow"); 29 | } 30 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 31 | require(b <= a, errorMessage); 32 | uint256 c = a - b; 33 | 34 | return c; 35 | } 36 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 37 | if (a == 0) { 38 | return 0; 39 | } 40 | 41 | uint256 c = a * b; 42 | require(c / a == b, "SafeMath: multiplication overflow"); 43 | 44 | return c; 45 | } 46 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 47 | return div(a, b, "SafeMath: division by zero"); 48 | } 49 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 50 | // Solidity only automatically asserts when dividing by 0 51 | require(b > 0, errorMessage); 52 | uint256 c = a / b; 53 | 54 | return c; 55 | } 56 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 57 | return mod(a, b, "SafeMath: modulo by zero"); 58 | } 59 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 60 | require(b != 0, errorMessage); 61 | return a % b; 62 | } 63 | } 64 | 65 | library Address { 66 | function isContract(address account) internal view returns (bool) { 67 | bytes32 codehash; 68 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 69 | // solhint-disable-next-line no-inline-assembly 70 | assembly { codehash := extcodehash(account) } 71 | return (codehash != 0x0 && codehash != accountHash); 72 | } 73 | function toPayable(address account) internal pure returns (address payable) { 74 | return address(uint160(account)); 75 | } 76 | function sendValue(address payable recipient, uint256 amount) internal { 77 | require(address(this).balance >= amount, "Address: insufficient balance"); 78 | 79 | // solhint-disable-next-line avoid-call-value 80 | (bool success, ) = recipient.call.value(amount)(""); 81 | require(success, "Address: unable to send value, recipient may have reverted"); 82 | } 83 | } 84 | 85 | library SafeERC20 { 86 | using SafeMath for uint256; 87 | using Address for address; 88 | 89 | function safeTransfer(IERC20 token, address to, uint256 value) internal { 90 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 91 | } 92 | 93 | function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 94 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 95 | } 96 | 97 | function safeApprove(IERC20 token, address spender, uint256 value) internal { 98 | require((value == 0) || (token.allowance(address(this), spender) == 0), 99 | "SafeERC20: approve from non-zero to non-zero allowance" 100 | ); 101 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 102 | } 103 | function callOptionalReturn(IERC20 token, bytes memory data) private { 104 | require(address(token).isContract(), "SafeERC20: call to non-contract"); 105 | 106 | // solhint-disable-next-line avoid-low-level-calls 107 | (bool success, bytes memory returndata) = address(token).call(data); 108 | require(success, "SafeERC20: low-level call failed"); 109 | 110 | if (returndata.length > 0) { // Return data is optional 111 | // solhint-disable-next-line max-line-length 112 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 113 | } 114 | } 115 | } 116 | 117 | interface Strategy { 118 | function want() external view returns (address); 119 | function deposit() external; 120 | function withdraw(address) external; 121 | function withdraw(uint) external; 122 | function withdrawAll() external returns (uint); 123 | function balanceOf() external view returns (uint); 124 | } 125 | 126 | interface Converter { 127 | function convert(address) external returns (uint); 128 | } 129 | 130 | interface OneSplitAudit { 131 | function swap( 132 | address fromToken, 133 | address destToken, 134 | uint256 amount, 135 | uint256 minReturn, 136 | uint256[] calldata distribution, 137 | uint256 flags 138 | ) 139 | external 140 | payable 141 | returns(uint256 returnAmount); 142 | 143 | function getExpectedReturn( 144 | address fromToken, 145 | address destToken, 146 | uint256 amount, 147 | uint256 parts, 148 | uint256 flags // See constants in IOneSplit.sol 149 | ) 150 | external 151 | view 152 | returns( 153 | uint256 returnAmount, 154 | uint256[] memory distribution 155 | ); 156 | } 157 | 158 | contract Controller { 159 | using SafeERC20 for IERC20; 160 | using Address for address; 161 | using SafeMath for uint256; 162 | 163 | address public governance; 164 | address public onesplit; 165 | address public rewards; 166 | address public factory; 167 | mapping(address => address) public vaults; 168 | mapping(address => address) public strategies; 169 | mapping(address => mapping(address => address)) public converters; 170 | 171 | uint public split = 5000; 172 | uint public constant max = 10000; 173 | 174 | constructor() public { 175 | governance = tx.origin; 176 | onesplit = address(0x50FDA034C0Ce7a8f7EFDAebDA7Aa7cA21CC1267e); 177 | rewards = 0x887F507EaAc58adD20263C6918538A9BdC882d47; 178 | } 179 | 180 | function setFactory(address _factory) public { 181 | require(msg.sender == governance, "!governance"); 182 | factory = _factory; 183 | } 184 | 185 | function setSplit(uint _split) public { 186 | require(msg.sender == governance, "!governance"); 187 | split = _split; 188 | } 189 | 190 | function setOneSplit(address _onesplit) public { 191 | require(msg.sender == governance, "!governance"); 192 | onesplit = _onesplit; 193 | } 194 | 195 | function setGovernance(address _governance) public { 196 | require(msg.sender == governance, "!governance"); 197 | governance = _governance; 198 | } 199 | 200 | function setVault(address _token, address _vault) public { 201 | require(msg.sender == governance, "!governance"); 202 | vaults[_token] = _vault; 203 | } 204 | 205 | function setConverter(address _input, address _output, address _converter) public { 206 | require(msg.sender == governance, "!governance"); 207 | converters[_input][_output] = _converter; 208 | } 209 | 210 | function setStrategy(address _token, address _strategy) public { 211 | //某个币对应一个策略,比如现在的ycrv就是挖 yfii 212 | require(msg.sender == governance, "!governance"); 213 | address _current = strategies[_token]; 214 | if (_current != address(0)) {//之前的策略存在的话,那么就先提取所有资金 215 | Strategy(_current).withdrawAll(); 216 | } 217 | strategies[_token] = _strategy; 218 | } 219 | 220 | // 221 | function earn(address _token, uint _amount) public { 222 | address _strategy = strategies[_token]; //获取策略的合约地址 223 | address _want = Strategy(_strategy).want();//策略需要的token地址 224 | if (_want != _token) {//如果策略需要的和输入的不一样,需要先转换 225 | address converter = converters[_token][_want];//转换器合约地址. 226 | IERC20(_token).safeTransfer(converter, _amount);//给转换器打钱 227 | _amount = Converter(converter).convert(_strategy);//执行转换... 228 | IERC20(_want).safeTransfer(_strategy, _amount); 229 | } else { 230 | IERC20(_token).safeTransfer(_strategy, _amount); 231 | } 232 | Strategy(_strategy).deposit();//存钱 233 | } 234 | 235 | function balanceOf(address _token) external view returns (uint) { 236 | return Strategy(strategies[_token]).balanceOf(); 237 | } 238 | 239 | function withdrawAll(address _token) public { 240 | require(msg.sender == governance, "!governance"); 241 | Strategy(strategies[_token]).withdrawAll(); 242 | } 243 | 244 | function inCaseTokensGetStuck(address _token, uint _amount) public {//转任意erc20 245 | require(msg.sender == governance, "!governance"); 246 | IERC20(_token).safeTransfer(governance, _amount); 247 | } 248 | 249 | function getExpectedReturn(address _strategy, address _token, uint parts) public view returns (uint expected) { 250 | uint _balance = IERC20(_token).balanceOf(_strategy);//获取策略器 某个代币的余额 251 | address _want = Strategy(_strategy).want();//策略器需要的代币. 252 | (expected,) = OneSplitAudit(onesplit).getExpectedReturn(_token, _want, _balance, parts, 0); 253 | } 254 | 255 | // Only allows to withdraw non-core strategy tokens ~ this is over and above normal yield 256 | function yearn(address _strategy, address _token, uint parts) public { 257 | // This contract should never have value in it, but just incase since this is a public call 258 | uint _before = IERC20(_token).balanceOf(address(this)); 259 | Strategy(_strategy).withdraw(_token); 260 | uint _after = IERC20(_token).balanceOf(address(this)); 261 | if (_after > _before) { 262 | uint _amount = _after.sub(_before); 263 | address _want = Strategy(_strategy).want(); 264 | uint[] memory _distribution; 265 | uint _expected; 266 | _before = IERC20(_want).balanceOf(address(this)); 267 | IERC20(_token).safeApprove(onesplit, 0); 268 | IERC20(_token).safeApprove(onesplit, _amount); 269 | (_expected, _distribution) = OneSplitAudit(onesplit).getExpectedReturn(_token, _want, _amount, parts, 0); 270 | OneSplitAudit(onesplit).swap(_token, _want, _amount, _expected, _distribution, 0); 271 | _after = IERC20(_want).balanceOf(address(this)); 272 | if (_after > _before) { 273 | _amount = _after.sub(_before); 274 | uint _reward = _amount.mul(split).div(max); 275 | earn(_want, _amount.sub(_reward)); 276 | IERC20(_want).safeTransfer(rewards, _reward); 277 | } 278 | } 279 | } 280 | 281 | function withdraw(address _token, uint _amount) public { 282 | require(msg.sender == vaults[_token], "!vault"); 283 | Strategy(strategies[_token]).withdraw(_amount); 284 | } 285 | } -------------------------------------------------------------------------------- /contracts/standard/StrategyYFII.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at Etherscan.io on 2020-07-31 3 | */ 4 | 5 | // SPDX-License-Identifier: MIT 6 | 7 | pragma solidity ^0.5.15; 8 | 9 | interface IERC20 { 10 | function totalSupply() external view returns (uint256); 11 | function balanceOf(address account) external view returns (uint256); 12 | function transfer(address recipient, uint256 amount) external returns (bool); 13 | function allowance(address owner, address spender) external view returns (uint256); 14 | function decimals() external view returns (uint); 15 | function name() external view returns (string memory); 16 | function approve(address spender, uint256 amount) external returns (bool); 17 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 18 | event Transfer(address indexed from, address indexed to, uint256 value); 19 | event Approval(address indexed owner, address indexed spender, uint256 value); 20 | } 21 | 22 | library SafeMath { 23 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 24 | uint256 c = a + b; 25 | require(c >= a, "SafeMath: addition overflow"); 26 | 27 | return c; 28 | } 29 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 30 | return sub(a, b, "SafeMath: subtraction overflow"); 31 | } 32 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 33 | require(b <= a, errorMessage); 34 | uint256 c = a - b; 35 | 36 | return c; 37 | } 38 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 39 | if (a == 0) { 40 | return 0; 41 | } 42 | 43 | uint256 c = a * b; 44 | require(c / a == b, "SafeMath: multiplication overflow"); 45 | 46 | return c; 47 | } 48 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 49 | return div(a, b, "SafeMath: division by zero"); 50 | } 51 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 52 | // Solidity only automatically asserts when dividing by 0 53 | require(b > 0, errorMessage); 54 | uint256 c = a / b; 55 | 56 | return c; 57 | } 58 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 59 | return mod(a, b, "SafeMath: modulo by zero"); 60 | } 61 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 62 | require(b != 0, errorMessage); 63 | return a % b; 64 | } 65 | } 66 | 67 | library Address { 68 | function isContract(address account) internal view returns (bool) { 69 | bytes32 codehash; 70 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 71 | // solhint-disable-next-line no-inline-assembly 72 | assembly { codehash := extcodehash(account) } 73 | return (codehash != 0x0 && codehash != accountHash); 74 | } 75 | function toPayable(address account) internal pure returns (address payable) { 76 | return address(uint160(account)); 77 | } 78 | function sendValue(address payable recipient, uint256 amount) internal { 79 | require(address(this).balance >= amount, "Address: insufficient balance"); 80 | 81 | // solhint-disable-next-line avoid-call-value 82 | (bool success, ) = recipient.call.value(amount)(""); 83 | require(success, "Address: unable to send value, recipient may have reverted"); 84 | } 85 | } 86 | 87 | library SafeERC20 { 88 | using SafeMath for uint256; 89 | using Address for address; 90 | 91 | function safeTransfer(IERC20 token, address to, uint256 value) internal { 92 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 93 | } 94 | 95 | function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 96 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 97 | } 98 | 99 | function safeApprove(IERC20 token, address spender, uint256 value) internal { 100 | require((value == 0) || (token.allowance(address(this), spender) == 0), 101 | "SafeERC20: approve from non-zero to non-zero allowance" 102 | ); 103 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 104 | } 105 | function callOptionalReturn(IERC20 token, bytes memory data) private { 106 | require(address(token).isContract(), "SafeERC20: call to non-contract"); 107 | 108 | // solhint-disable-next-line avoid-low-level-calls 109 | (bool success, bytes memory returndata) = address(token).call(data); 110 | require(success, "SafeERC20: low-level call failed"); 111 | 112 | if (returndata.length > 0) { // Return data is optional 113 | // solhint-disable-next-line max-line-length 114 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 115 | } 116 | } 117 | } 118 | 119 | interface Controller { 120 | function vaults(address) external view returns (address); 121 | function rewards() external view returns (address); 122 | } 123 | 124 | /* 125 | 126 | A strategy must implement the following calls; 127 | 128 | - deposit() 129 | - withdraw(address) must exclude any tokens used in the yield - Controller role - withdraw should return to Controller 130 | - withdraw(uint) - Controller | Vault role - withdraw should always return to vault 131 | - withdrawAll() - Controller | Vault role - withdraw should always return to vault 132 | - balanceOf() 133 | 134 | Where possible, strategies must remain as immutable as possible, instead of updating variables, we update the contract by linking it in the controller 135 | 136 | */ 137 | 138 | interface Yam { 139 | function withdraw(uint) external; 140 | function getReward() external; 141 | function stake(uint) external; 142 | function balanceOf(address) external view returns (uint); 143 | function exit() external; 144 | function earned(address) external view returns (uint); 145 | } 146 | 147 | 148 | interface Yvault{ 149 | function make_profit(uint256 amount) external; 150 | } 151 | 152 | contract Strategy { 153 | using SafeERC20 for IERC20; 154 | using Address for address; 155 | using SafeMath for uint256; 156 | 157 | address public pool; 158 | address public output; 159 | string public getName; 160 | 161 | address constant public yfii = address(0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83); 162 | address constant public ycrv = address(0xdF5e0e81Dff6FAF3A7e52BA697820c5e32D806A8); 163 | 164 | uint public fee = 600; 165 | uint public burnfee = 300; 166 | uint public callfee = 100; 167 | uint constant public max = 10000; 168 | 169 | address public governance; 170 | address public controller; 171 | 172 | address public want; 173 | 174 | // address[] public swapRouting; 175 | 176 | constructor() public { 177 | governance = tx.origin; 178 | controller = 0xDE60d11E7cDBaC266Ad332DF289AD9dE2EE32e68; 179 | output = yfii; 180 | pool = 0xb81D3cB2708530ea990a287142b82D058725C092; 181 | want = ycrv; 182 | getName = string( 183 | abi.encodePacked("yfii:Strategy:", 184 | abi.encodePacked(IERC20(want).name(), 185 | abi.encodePacked(":",IERC20(output).name()) 186 | ) 187 | )); 188 | 189 | } 190 | 191 | function deposit() external { 192 | IERC20(want).safeApprove(pool, 0); 193 | IERC20(want).safeApprove(pool, IERC20(want).balanceOf(address(this))); 194 | Yam(pool).stake(IERC20(want).balanceOf(address(this))); 195 | } 196 | 197 | // Controller only function for creating additional rewards from dust 198 | function withdraw(IERC20 _asset) external returns (uint balance) { 199 | require(msg.sender == controller, "!controller"); 200 | require(want != address(_asset), "want"); 201 | balance = _asset.balanceOf(address(this)); 202 | _asset.safeTransfer(controller, balance); 203 | } 204 | 205 | // Withdraw partial funds, normally used with a vault withdrawal 206 | function withdraw(uint _amount) external { 207 | require(msg.sender == controller, "!controller"); 208 | uint _balance = IERC20(want).balanceOf(address(this)); 209 | if (_balance < _amount) { 210 | _amount = _withdrawSome(_amount.sub(_balance)); 211 | _amount = _amount.add(_balance); 212 | } 213 | 214 | address _vault = Controller(controller).vaults(address(want)); 215 | require(_vault != address(0), "!vault"); // additional protection so we don't burn the funds 216 | IERC20(want).safeTransfer(_vault, _amount); 217 | } 218 | 219 | // Withdraw all funds, normally used when migrating strategies 220 | function withdrawAll() public returns (uint balance) { 221 | require(msg.sender == controller||msg.sender==governance, "!controller"); 222 | _withdrawAll(); 223 | balance = IERC20(want).balanceOf(address(this)); 224 | 225 | address _vault = Controller(controller).vaults(address(want)); 226 | require(_vault != address(0), "!vault"); // additional protection so we don't burn the funds 227 | IERC20(want).safeTransfer(_vault, balance); 228 | 229 | } 230 | 231 | function _withdrawAll() internal { 232 | Yam(pool).exit(); 233 | } 234 | 235 | 236 | function harvest() public { 237 | require(!Address.isContract(msg.sender),"!contract"); 238 | Yam(pool).getReward(); 239 | address _vault = Controller(controller).vaults(address(want)); 240 | require(_vault != address(0), "!vault"); // additional protection so we don't burn the funds 241 | 242 | // fee 243 | uint b = IERC20(yfii).balanceOf(address(this)); 244 | uint _fee = b.mul(fee).div(max); 245 | uint _callfee = b.mul(callfee).div(max); 246 | uint _burnfee = b.mul(burnfee).div(max); 247 | IERC20(yfii).safeTransfer(Controller(controller).rewards(), _fee); //6% 5% team +1% insurance 248 | IERC20(yfii).safeTransfer(msg.sender, _callfee); //call fee 1% 249 | IERC20(yfii).safeTransfer(address(0x6666666666666666666666666666666666666666), _burnfee); //burn fee 3% 250 | 251 | //把yfii 存进去分红. 252 | IERC20(yfii).safeApprove(_vault, 0); 253 | IERC20(yfii).safeApprove(_vault, IERC20(yfii).balanceOf(address(this))); 254 | Yvault(_vault).make_profit(IERC20(yfii).balanceOf(address(this))); 255 | } 256 | 257 | 258 | function _withdrawSome(uint256 _amount) internal returns (uint) { 259 | Yam(pool).withdraw(_amount); 260 | return _amount; 261 | } 262 | 263 | 264 | function balanceOf() public view returns (uint) { 265 | return Yam(pool).balanceOf(address(this)); 266 | 267 | } 268 | function balanceOfPendingReward() public view returns(uint){ //还没有领取的收益有多少... 269 | return Yam(pool).earned(address(this)); 270 | } 271 | 272 | 273 | function setGovernance(address _governance) external { 274 | require(msg.sender == governance, "!governance"); 275 | governance = _governance; 276 | } 277 | 278 | function setController(address _controller) external { 279 | require(msg.sender == governance, "!governance"); 280 | controller = _controller; 281 | } 282 | 283 | function setFee(uint256 _fee) external{ 284 | require(msg.sender == governance, "!governance"); 285 | fee = _fee; 286 | } 287 | function setCallFee(uint256 _fee) external{ 288 | require(msg.sender == governance, "!governance"); 289 | callfee = _fee; 290 | } 291 | function setBurnFee(uint256 _fee) external{ 292 | require(msg.sender == governance, "!governance"); 293 | burnfee = _fee; 294 | } 295 | } -------------------------------------------------------------------------------- /contracts/standard/config.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"token":"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2","vault":"0xf693705e79ccc8707D3FcB4D89381CaC28e45a22","strategy":"0x602ec22B362B0E8ae658D18f4435fE8c5c23cA0C","name":"WETH"}, 3 | {"token":"0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F","vault":"0xd4bEf8D8D8d7cBB89f63933Db6907439f9E6Fd0f","strategy":"","name":"SNX"}, 4 | {"token":"0x80fB784B7eD66730e8b1DBd9820aFD29931aab03","vault":"0xA2D35bcDFc271767903f0Ed4aF56a066F6c99Ae7","strategy":"","name":"LEND"}, 5 | {"token":"0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2","vault":"0x537350b9301fCf045Eaf1CEa2F225276C89D5f6D","strategy":"","name":"MKR"}, 6 | {"token":"0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e","vault":"0x4BD410A06FBB3A22C31017964D13Cbc5867d3d61","strategy":"","name":"YFI"}, 7 | {"token":"0x514910771AF9Ca656af840dff83E8264EcF986CA","vault":"0xCda9230923FCb25e26a20D7D9D12e1744405C9fC","strategy":"0x780c2450632ecb4be69DA859987Be4875545E90b","name":"LINK"}, 8 | {"token":"0xc00e94Cb662C3520282E6f5717214004A7f26888","vault":"0x7AEFB9DCE3700B7CE8B1f556043BB1D436C77e0d","strategy":"","name":"COMP"}, 9 | {"token":"0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599","vault":"0x2f4Ae3a95C7B457DB53706EEE8979aEca4ec0082","strategy":"","name":"WBTC"}, 10 | {"token":"0xdF5e0e81Dff6FAF3A7e52BA697820c5e32D806A8","vault":"0xD2db1EF55549eCdacb4e7da081216AE96f0Eedcb","strategy":"0x9eFE9FB2010B2c5fa7D34E69e709DD296d9c0bD9","name":"YCRV"}, 11 | {"token":"0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83","vault":"0xf5a232b1325769E09B303D7292589a2C7AEe2Aa4","strategy":"0xe9bA312991e76116879b484135D2b86Ea27d0A0f","name":"YFII"}, 12 | {"token":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","vault":"0x35a228bBe17F7c6D1ebaCc59fcA3aC6733135E63","strategy":"","name":"USDC"}, 13 | {"token":"0x6B175474E89094C44Da98b954EedeAC495271d0F","vault":"0x8FDD31b72Cc18c965E6a7BC85174994e72799732","strategy":"0x6285FF6AEF7BA5Bddeb67B033dc75f6Da0980191","name":"DAI"}, 14 | {"token":"0x845838DF265Dcd2c412A1Dc9e959c7d08537f8a2","vault":"0xf811c062D14fdF9Fda95D6A2C54e137afE80De45","strategy":"0xEfb684AB29371e701CCe3CA9e3FD8f5E33042eee","name":"CCRV(cDAI+cUSDC)"} 15 | ] -------------------------------------------------------------------------------- /contracts/standard/readme.md: -------------------------------------------------------------------------------- 1 | ## contract address 2 | 3 | Controller: 0xe14e60d0F7fb15b1A98FDE88A3415C17b023bf36 4 | 5 | ## WETH 6 | 7 | token: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 8 | 9 | vault: 0xf693705e79ccc8707D3FcB4D89381CaC28e45a22 10 | 11 | strategy: 0x602ec22B362B0E8ae658D18f4435fE8c5c23cA0C 12 | 13 | ## SNX 14 | 15 | token: 0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F 16 | 17 | vault: 0xd4bEf8D8D8d7cBB89f63933Db6907439f9E6Fd0f 18 | 19 | strategy: 20 | 21 | ## LEND 22 | 23 | token: 0x80fB784B7eD66730e8b1DBd9820aFD29931aab03 24 | 25 | vault: 0xA2D35bcDFc271767903f0Ed4aF56a066F6c99Ae7 26 | 27 | strategy: 28 | 29 | ## MKR 30 | 31 | token:0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2 32 | 33 | vault: 0x537350b9301fCf045Eaf1CEa2F225276C89D5f6D 34 | 35 | strategy: 36 | 37 | ## YFI 38 | 39 | token:0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e 40 | 41 | vault: 0x4BD410A06FBB3A22C31017964D13Cbc5867d3d61 42 | 43 | strategy: 44 | 45 | ## LINK 46 | 47 | token:0x514910771AF9Ca656af840dff83E8264EcF986CA 48 | 49 | vault: 0xCda9230923FCb25e26a20D7D9D12e1744405C9fC 50 | 51 | strategy: 0x780c2450632ecb4be69DA859987Be4875545E90b 52 | 53 | ## COMP 54 | 55 | token:0xc00e94Cb662C3520282E6f5717214004A7f26888 56 | 57 | vault: 0x7AEFB9DCE3700B7CE8B1f556043BB1D436C77e0d 58 | 59 | strategy: 60 | 61 | ## WBTC 62 | 63 | token:0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599 64 | 65 | vault: 0x2f4Ae3a95C7B457DB53706EEE8979aEca4ec0082 66 | 67 | strategy: 68 | 69 | 70 | 71 | ## YCRV 72 | 73 | token : 0xdF5e0e81Dff6FAF3A7e52BA697820c5e32D806A8 74 | 75 | Strategy: 76 | 77 | - StrategyCRV:0x9eFE9FB2010B2c5fa7D34E69e709DD296d9c0bD9 78 | - StrategyPool1: 0x83612eAc340b967aD380feC9a2D50Ea3FcA1A2cb 79 | 80 | vault: 0xD2db1EF55549eCdacb4e7da081216AE96f0Eedcb 81 | 82 | Controller: 0xDE60d11E7cDBaC266Ad332DF289AD9dE2EE32e68(和上面的不一样) 83 | 84 | ## YFII 85 | 86 | token: 0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83 87 | 88 | Strategy: 0xe9bA312991e76116879b484135D2b86Ea27d0A0f v2 89 | 90 | vault: 0xf5a232b1325769E09B303D7292589a2C7AEe2Aa4 91 | 92 | 93 | ## USDT 在测试. 94 | 95 | token: 0xdAC17F958D2ee523a2206206994597C13D831ec7 96 | 97 | Strategy: 0xe2df4c46acabb1cdb446351d6b24727944a5bfcc dforce 98 | 99 | vault: 0x72Cf258c852Dc485a853370171d46B9D29fD3184 100 | 101 | ## USDC 102 | 103 | token: 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 104 | 105 | Strategy: 106 | 107 | vault: 0x35a228bBe17F7c6D1ebaCc59fcA3aC6733135E63 108 | 109 | 110 | ## DAI 111 | 112 | token: 0x6B175474E89094C44Da98b954EedeAC495271d0F 113 | 114 | Strategy: 0x6285FF6AEF7BA5Bddeb67B033dc75f6Da0980191 115 | 116 | vault: 0x8FDD31b72Cc18c965E6a7BC85174994e72799732 117 | 118 | ## Curve.fi: cCrv Token (cDAI+cUSDC) 119 | 120 | token: 0x845838DF265Dcd2c412A1Dc9e959c7d08537f8a2 121 | 122 | Strategy: 0xEfb684AB29371e701CCe3CA9e3FD8f5E33042eee 123 | 124 | vault: 0xf811c062D14fdF9Fda95D6A2C54e137afE80De45 125 | 126 | ## Curve.fi: bCrv Token (Curve.fi yDAI/yUSDC/yUSDT/yBUSD) 127 | 128 | token: 0x3b3ac5386837dc563660fb6a0937dfaa5924333b 129 | 130 | Strategy: 131 | 132 | vault: 0xf4485B4f10C388d5b09DB36bA8adD2ceEA1E040B 133 | 134 | ## usdx/usdc lp dforce 135 | 136 | pool:https://cn.etherscan.com/address/0xa94e2074beb6d1bf28014b81ff2062eab3600c48#code 137 | 138 | token: 0x460067f15e9B461a5F4c482E80217A2F45269385 139 | 140 | Strategy: 141 | 142 | vault: 143 | 144 | ## Strategy的标准接口 145 | 146 | ### deposit 147 | 148 | ```function deposit() external ``` 149 | 150 | 质押代币到目标挖矿合约 151 | 152 | 153 | 154 | ### withdraw 155 | 156 | ```function withdraw(uint _amount) external``` 157 | 158 | 从挖矿合约取出质押的钱 159 | 160 | ### withdrawAll 161 | 162 | ```function withdrawAll() public returns (uint balance) ``` 163 | 164 | 提取目标挖矿合约里面所有的钱 165 | 166 | 167 | ### harvest 168 | 169 | ```function harvest() public``` 170 | 171 | 从挖矿合约收取利息->换算成收益代币(yfii)->分钱 172 | 173 | ### balanceOf 174 | 175 | ``` function balanceOf() public view returns (uint)``` 176 | 177 | 在目标合约存了多少钱. 178 | 179 | ### balanceOfPendingReward 180 | 181 | ```function balanceOfPendingReward() public view returns(uint)``` 182 | 183 | 有多少分红没有领取 184 | 185 | ### harvertYFII 186 | 187 | ``` function harvertYFII() public view returns(uint[] memory amounts)``` 188 | 189 | balanceOfPendingReward 的数量换算成yfii的个数. 190 | -------------------------------------------------------------------------------- /contracts/standard/v2/apy.json: -------------------------------------------------------------------------------- 1 | { 2 | "usdt":"39.54%", 3 | "dai":"86.3%", 4 | "ycrv":"42.63%", 5 | "tusd":"42.63%" 6 | } -------------------------------------------------------------------------------- /contracts/standard/v2/bscconfig.json: -------------------------------------------------------------------------------- 1 | //controller :0xb313b02235Acb925D51Be22bAf90Dc68B4Bf8Af5 2 | //controller: test inprod:0x5B916D02A9745C64EC6C0AFe41Ee4893Dd5a01B7 3 | [ 4 | { 5 | "token": "0x55d398326f99059ff775485246999027b3197955", 6 | "Strategy": "0x92f5ff3f1b4d8aD81Ba1765a2F1af612205119c2", 7 | "vault": "0x1F19D041FDCE1B70901008229d77A8B02E315618", 8 | "name":"usdt", 9 | "StrategyName":"" 10 | }, 11 | { 12 | "token": "0xe9e7cea3dedca5984780bafc599bd69add087d56", 13 | "Strategy": "0x5d6d4d666f522723C993279D107833B22d40A193", 14 | "vault": "0xeB3C085FBc1030bb127114CB1A3B9A02A24eF62d", 15 | "name":"busd", 16 | "StrategyName":"" 17 | }, 18 | { 19 | "token": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", 20 | "Strategy": "0xD601e0dBcbBb2e976d5B499c811e2EdAe304C634", 21 | "vault": "0x72dd5Df626ebBc020fdF431502799413c56Ac12C", 22 | "name":"bnb", 23 | "StrategyName":"for" 24 | }, 25 | { 26 | "token": "0x2170ed0880ac9a755fd29b2688956bd959f933f8", 27 | "Strategy": "0x06B8759925b3F49A2aFc13D7ff4dCc7E3B0ef323", 28 | "vault": "0xb98f8339CD3CD50701aCdE307875B78c373e6515", 29 | "name":"eth", 30 | "StrategyName":"for" 31 | }, 32 | { 33 | "token": "0x7F70642d88cf1C4a3a7abb072B53B929b653edA5", 34 | "Strategy": "0xC49c6ee0dB9452446370e62dEBD38B35444093Ef", 35 | "vault": "0x57Ea66bb8F83D09127b792FDf0af4A94fc5D6314", 36 | "name":"yfii", 37 | "StrategyName":"for" 38 | } 39 | ] -------------------------------------------------------------------------------- /contracts/standard/v2/config.json: -------------------------------------------------------------------------------- 1 | // controller: 0x8C2a19108d8F6aEC72867E9cfb1bF517601b515f 2 | 3 | [ 4 | { 5 | "token": "0xdAC17F958D2ee523a2206206994597C13D831ec7", 6 | "Strategy": "0x8a61b5f61c8338b86E632c67085A7d80d88fe881", //for 7 | "Strategy1": "", //for 8 | "vault": "0x72Cf258c852Dc485a853370171d46B9D29fD3184", 9 | "name":"usdt", 10 | "StrategyName":"dforce" 11 | }, 12 | { 13 | "token": "0xdF5e0e81Dff6FAF3A7e52BA697820c5e32D806A8", 14 | "Strategy": "0x898828957133d4c50030a5A2D55Ca370915E6A77", 15 | "vault": "0x3E3db9cc5b540d2794DB3861BE5A4887cF77E48B", 16 | "name":"ycrv", 17 | "StrategyName":"crv" 18 | }, 19 | { 20 | "token": "0x6B175474E89094C44Da98b954EedeAC495271d0F", 21 | "Strategy": "0xbDD4a57c5EE8558370bb661d29a979657D81258e", 22 | "vault": "0x1e0DC67aEa5aA74718822590294230162B5f2064", 23 | "name":"dai", 24 | "StrategyName":"dforce" 25 | }, 26 | { 27 | "token": "0x0000000000085d4780B73119b644AE5ecd22b376", 28 | "Strategy": "0x30aE128ebCdec11F62cB3fa9C6a0E8269a9AF686", 29 | "vault": "0x4243f5C8683089b65a9F588B1AE578d5D84bFBC9", 30 | "name":"tusd", 31 | "StrategyName":"crv" 32 | }, 33 | { 34 | "token": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", 35 | "Strategy": "0xC96EA19A7bD3D4f04d6d67E20CDe88e88352Fd14", 36 | "vault": "0x23B4dB3a435517fd5f2661a9c5a16f78311201c1", 37 | "name":"usdc", 38 | "StrategyName":"for" 39 | }, 40 | { 41 | "token": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", 42 | "Strategy": "0x6FC7Be79036D0D610B252D435177A687EB39c44a", 43 | "vault": "0xa8EA49a9e242fFfBdECc4583551c3BcB111456E6", 44 | "name": "eth", 45 | "StrategyName": "for" 46 | },{ 47 | "token": "0x4Fabb145d64652a948d72533023f6E7A623C7C53", 48 | "Strategy": "0x672077cdeac2dF427d4Dc639e7531D2f3e69c597", 49 | "vault": "0xc46d2fC00554f1f874F37e6e3E828A0AdFEFfbcB", 50 | "name": "busd", 51 | "StrategyName": "for" 52 | },{ 53 | "token": "0x0316eb71485b0ab14103307bf65a021042c6d380", 54 | "Strategy": "0xC6Cf79574A4138855DFC63fBDFABD9669ccb76C3", 55 | "vault": "0x26AEdD2205FF8a87AEF2eC9691d77Ce3f40CE6E9", 56 | "name": "hbtc", 57 | "StrategyName": "for" 58 | }, 59 | { 60 | "token": "0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852", 61 | "Strategy": "0x9466AAC3e97F1E716d97c8331ba346Bb243c13bD", 62 | "vault": "0x7E43210a4c6831D421f57026617Fdfc8ED3A0baf", 63 | "name": "eth/usdt", 64 | "StrategyName": "uni" 65 | }, 66 | { 67 | "token": "0xa478c2975ab1ea89e8196811f51a7b7ade33eb11", 68 | "Strategy": "0x41cCed5B81634EcFbd9eCA039aF5dfD05e713B2c", 69 | "vault": "0x19d994471D61d36FE367928Cc58102a376089D1f", 70 | "name": "eth/dai", 71 | "StrategyName": "uni" 72 | }, 73 | { 74 | "token": "0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc", 75 | "Strategy": "0x1DE7D7AE631Dc4FFac3af9Cb4a9633820ba85Cd8", 76 | "vault": "0x68A23248000d5d4C943EE685989998c1B19bD74E", 77 | "name": "eth/usdc", 78 | "StrategyName": "uni" 79 | }, 80 | { 81 | "token": "0xBb2b8038a1640196FbE3e38816F3e67Cba72D940", 82 | "Strategy": "0xd24e08bdfefd68138F975035874F38554389A2E6", 83 | "vault": "0xb918368082655fA223c162266ecd88Aa7Ae40bc9", 84 | "name": "eth/wbtc", 85 | "StrategyName": "uni" 86 | },{ 87 | "token": "0x5B5CFE992AdAC0C9D48E05854B2d91C73a003858", 88 | "Strategy": "0x99CE9eEF12c68c4B3568AC161024d1Ac49d52A11", 89 | "vault": "0xED434A25612B8d64E3257Fff5f96B33031729fDF", 90 | "name": "husd3crv", 91 | "StrategyName": "crv" 92 | } 93 | ] -------------------------------------------------------------------------------- /contracts/standard/v2/readme.md: -------------------------------------------------------------------------------- 1 | # v2版的机枪池 2 | 3 | 主要是使用了iToken 4 | 5 | 退出费0.1% 在strategy里面设置 6 | 7 | ## vault 8 | 9 | 用户充值 10 | 11 | 1. depositAll 12 | 2. deposit(uint _amount) 13 | 14 | 用户提现 15 | 16 | 1. withdrawAll 17 | 2. withdraw(uint _amount) 18 | 19 | 计算用户收入 20 | 21 | 持有的itoken * getPricePerFullShare() 22 | 23 | ## strategy 24 | 25 | 需要实现的方法 26 | 27 | deposit:把vault的钱拿进去挖矿 28 | 29 | withdraw(uint _amount):从挖矿合约里面取钱 30 | 31 | withdrawAll:把挖矿合约里面的钱全部转移出来 且把钱转还到vault合约 32 | 33 | setNewPool:(可选 如果某个系列特别多的话 可以用这个.是为了不需要来一个新的水果类的,就要重新部署strategy合约。。。) 34 | 35 | harvest: 领取挖矿合约的代币 并且把收入分配出去...且再质押进去 36 | - 目前是90%换成原来的token 37 | - 10%换成yfii 38 | - 1% call fee 39 | - 1% 保险 40 | - 5% reward pool 41 | - 3% team 42 | 43 | balanceOf: 有多少钱充进去挖矿了 44 | 45 | harvertYFII: 未领取奖励换成yfii有多少.(需要未领取的奖励->换成yfii) 46 | 47 | 48 | ## controller 49 | 50 | 0xcDCf1f9Ac816Fed665B09a00f60c885dd8848b02 test in prod的地址 51 | -------------------------------------------------------------------------------- /contracts/standard/v2/testinpord.json: -------------------------------------------------------------------------------- 1 | // controller: 0xcDCf1f9Ac816Fed665B09a00f60c885dd8848b02 2 | 3 | [ 4 | 5 | ] -------------------------------------------------------------------------------- /contracts/t/swap.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at Etherscan.io on 2020-07-31 3 | */ 4 | 5 | // SPDX-License-Identifier: MIT 6 | 7 | pragma solidity ^0.5.15; 8 | 9 | interface IERC20 { 10 | function totalSupply() external view returns (uint256); 11 | function balanceOf(address account) external view returns (uint256); 12 | function transfer(address recipient, uint256 amount) external returns (bool); 13 | function allowance(address owner, address spender) external view returns (uint256); 14 | function decimals() external view returns (uint); 15 | function approve(address spender, uint256 amount) external returns (bool); 16 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 17 | event Transfer(address indexed from, address indexed to, uint256 value); 18 | event Approval(address indexed owner, address indexed spender, uint256 value); 19 | } 20 | 21 | library SafeMath { 22 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 23 | uint256 c = a + b; 24 | require(c >= a, "SafeMath: addition overflow"); 25 | 26 | return c; 27 | } 28 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 29 | return sub(a, b, "SafeMath: subtraction overflow"); 30 | } 31 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 32 | require(b <= a, errorMessage); 33 | uint256 c = a - b; 34 | 35 | return c; 36 | } 37 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 38 | if (a == 0) { 39 | return 0; 40 | } 41 | 42 | uint256 c = a * b; 43 | require(c / a == b, "SafeMath: multiplication overflow"); 44 | 45 | return c; 46 | } 47 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 48 | return div(a, b, "SafeMath: division by zero"); 49 | } 50 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 51 | // Solidity only automatically asserts when dividing by 0 52 | require(b > 0, errorMessage); 53 | uint256 c = a / b; 54 | 55 | return c; 56 | } 57 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 58 | return mod(a, b, "SafeMath: modulo by zero"); 59 | } 60 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 61 | require(b != 0, errorMessage); 62 | return a % b; 63 | } 64 | } 65 | 66 | library Address { 67 | function isContract(address account) internal view returns (bool) { 68 | bytes32 codehash; 69 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 70 | // solhint-disable-next-line no-inline-assembly 71 | assembly { codehash := extcodehash(account) } 72 | return (codehash != 0x0 && codehash != accountHash); 73 | } 74 | function toPayable(address account) internal pure returns (address payable) { 75 | return address(uint160(account)); 76 | } 77 | function sendValue(address payable recipient, uint256 amount) internal { 78 | require(address(this).balance >= amount, "Address: insufficient balance"); 79 | 80 | // solhint-disable-next-line avoid-call-value 81 | (bool success, ) = recipient.call.value(amount)(""); 82 | require(success, "Address: unable to send value, recipient may have reverted"); 83 | } 84 | } 85 | 86 | library SafeERC20 { 87 | using SafeMath for uint256; 88 | using Address for address; 89 | 90 | function safeTransfer(IERC20 token, address to, uint256 value) internal { 91 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 92 | } 93 | 94 | function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 95 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 96 | } 97 | 98 | function safeApprove(IERC20 token, address spender, uint256 value) internal { 99 | require((value == 0) || (token.allowance(address(this), spender) == 0), 100 | "SafeERC20: approve from non-zero to non-zero allowance" 101 | ); 102 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 103 | } 104 | function callOptionalReturn(IERC20 token, bytes memory data) private { 105 | require(address(token).isContract(), "SafeERC20: call to non-contract"); 106 | 107 | // solhint-disable-next-line avoid-low-level-calls 108 | (bool success, bytes memory returndata) = address(token).call(data); 109 | require(success, "SafeERC20: low-level call failed"); 110 | 111 | if (returndata.length > 0) { // Return data is optional 112 | // solhint-disable-next-line max-line-length 113 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 114 | } 115 | } 116 | } 117 | 118 | 119 | 120 | contract Balancer { 121 | function joinPool(uint poolAmountOut, uint[] calldata maxAmountsIn) external; 122 | function exitPool(uint poolAmountIn, uint[] calldata minAmountsOut) external; 123 | function swapExactAmountIn( 124 | address tokenIn, 125 | uint tokenAmountIn, 126 | address tokenOut, 127 | uint minAmountOut, 128 | uint maxPrice 129 | ) external returns (uint tokenAmountOut, uint spotPriceAfter); 130 | function swapExactAmountOut( 131 | address tokenIn, 132 | uint maxAmountIn, 133 | address tokenOut, 134 | uint tokenAmountOut, 135 | uint maxPrice 136 | ) external returns (uint tokenAmountIn, uint spotPriceAfter); 137 | function joinswapExternAmountIn(address tokenIn, uint tokenAmountIn, uint minPoolAmountOut) external returns (uint poolAmountOut); 138 | function exitswapPoolAmountIn(address tokenOut, uint poolAmountIn, uint minAmountOut) external returns (uint tokenAmountOut); 139 | } 140 | interface UniswapRouter { 141 | function swapExactTokensForTokens( 142 | uint amountIn, 143 | uint amountOutMin, 144 | address[] calldata path, 145 | address to, 146 | uint deadline 147 | ) external returns (uint[] memory amounts); 148 | function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) 149 | external returns (uint[] memory amounts); 150 | } 151 | 152 | contract Swap { 153 | using SafeERC20 for IERC20; 154 | using Address for address; 155 | using SafeMath for uint256; 156 | 157 | address public owner; 158 | 159 | constructor()public{ 160 | owner = tx.origin; 161 | init(); 162 | } 163 | modifier onlyOwner(){ 164 | require(msg.sender == owner,"not owner"); 165 | _; 166 | } 167 | 168 | address constant public yfii = address(0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83); 169 | address constant public crv = address(0xD533a949740bb3306d119CC777fa900bA034cd52); 170 | address constant public unirouter = address(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); 171 | address constant public weth = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); 172 | address constant public dai = address(0x6B175474E89094C44Da98b954EedeAC495271d0F); 173 | address constant public balancer = address(0x16cAC1403377978644e78769Daa49d8f6B6CF565); 174 | 175 | function init () public{ 176 | IERC20(crv).safeApprove(unirouter, uint(-1)); 177 | IERC20(dai).safeApprove(balancer, uint(-1)); 178 | } 179 | 180 | function doswap(uint256 _amount) public { 181 | IERC20(crv).safeTransferFrom(msg.sender, address(this), _amount); 182 | 183 | // crv->weth->dai 184 | address[] memory path3 = new address[](3); 185 | path3[0] = address(crv); 186 | path3[1] = address(weth); 187 | path3[2] = address(dai); 188 | UniswapRouter(unirouter).swapExactTokensForTokens(IERC20(crv).balanceOf(address(this)), 0, path3, address(this), now.add(1800)); 189 | 190 | // dai ->yfii 191 | Balancer(balancer).swapExactAmountIn(dai, IERC20(dai).balanceOf(address(this)), yfii, 0, uint(-1)); 192 | 193 | IERC20(yfii).safeTransfer(msg.sender, IERC20(yfii).balanceOf(address(this))); 194 | 195 | } 196 | function inCaseTokenGetsStuck(IERC20 _TokenAddress) onlyOwner public { 197 | uint qty = _TokenAddress.balanceOf(address(this)); 198 | _TokenAddress.safeTransfer(msg.sender, qty); 199 | } 200 | 201 | // incase of half-way error 202 | function inCaseETHGetsStuck() onlyOwner public{ 203 | (bool result, ) = msg.sender.call.value(address(this).balance)(""); 204 | require(result, "transfer of ETH failed"); 205 | } 206 | } -------------------------------------------------------------------------------- /contracts/t/swap1.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at Etherscan.io on 2020-07-31 3 | */ 4 | 5 | // SPDX-License-Identifier: MIT 6 | 7 | pragma solidity ^0.5.15; 8 | 9 | interface IERC20 { 10 | function totalSupply() external view returns (uint256); 11 | function balanceOf(address account) external view returns (uint256); 12 | function transfer(address recipient, uint256 amount) external returns (bool); 13 | function allowance(address owner, address spender) external view returns (uint256); 14 | function decimals() external view returns (uint); 15 | function approve(address spender, uint256 amount) external returns (bool); 16 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 17 | event Transfer(address indexed from, address indexed to, uint256 value); 18 | event Approval(address indexed owner, address indexed spender, uint256 value); 19 | } 20 | 21 | library SafeMath { 22 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 23 | uint256 c = a + b; 24 | require(c >= a, "SafeMath: addition overflow"); 25 | 26 | return c; 27 | } 28 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 29 | return sub(a, b, "SafeMath: subtraction overflow"); 30 | } 31 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 32 | require(b <= a, errorMessage); 33 | uint256 c = a - b; 34 | 35 | return c; 36 | } 37 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 38 | if (a == 0) { 39 | return 0; 40 | } 41 | 42 | uint256 c = a * b; 43 | require(c / a == b, "SafeMath: multiplication overflow"); 44 | 45 | return c; 46 | } 47 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 48 | return div(a, b, "SafeMath: division by zero"); 49 | } 50 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 51 | // Solidity only automatically asserts when dividing by 0 52 | require(b > 0, errorMessage); 53 | uint256 c = a / b; 54 | 55 | return c; 56 | } 57 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 58 | return mod(a, b, "SafeMath: modulo by zero"); 59 | } 60 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 61 | require(b != 0, errorMessage); 62 | return a % b; 63 | } 64 | } 65 | 66 | library Address { 67 | function isContract(address account) internal view returns (bool) { 68 | bytes32 codehash; 69 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 70 | // solhint-disable-next-line no-inline-assembly 71 | assembly { codehash := extcodehash(account) } 72 | return (codehash != 0x0 && codehash != accountHash); 73 | } 74 | function toPayable(address account) internal pure returns (address payable) { 75 | return address(uint160(account)); 76 | } 77 | function sendValue(address payable recipient, uint256 amount) internal { 78 | require(address(this).balance >= amount, "Address: insufficient balance"); 79 | 80 | // solhint-disable-next-line avoid-call-value 81 | (bool success, ) = recipient.call.value(amount)(""); 82 | require(success, "Address: unable to send value, recipient may have reverted"); 83 | } 84 | } 85 | 86 | library SafeERC20 { 87 | using SafeMath for uint256; 88 | using Address for address; 89 | 90 | function safeTransfer(IERC20 token, address to, uint256 value) internal { 91 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 92 | } 93 | 94 | function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 95 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 96 | } 97 | 98 | function safeApprove(IERC20 token, address spender, uint256 value) internal { 99 | require((value == 0) || (token.allowance(address(this), spender) == 0), 100 | "SafeERC20: approve from non-zero to non-zero allowance" 101 | ); 102 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 103 | } 104 | function callOptionalReturn(IERC20 token, bytes memory data) private { 105 | require(address(token).isContract(), "SafeERC20: call to non-contract"); 106 | 107 | // solhint-disable-next-line avoid-low-level-calls 108 | (bool success, bytes memory returndata) = address(token).call(data); 109 | require(success, "SafeERC20: low-level call failed"); 110 | 111 | if (returndata.length > 0) { // Return data is optional 112 | // solhint-disable-next-line max-line-length 113 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 114 | } 115 | } 116 | } 117 | 118 | interface CrvYvault{ 119 | function withdraw(uint _shares) external; 120 | } 121 | 122 | 123 | interface UniswapRouter { 124 | function swapExactTokensForTokens( 125 | uint amountIn, 126 | uint amountOutMin, 127 | address[] calldata path, 128 | address to, 129 | uint deadline 130 | ) external returns (uint[] memory amounts); 131 | function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) 132 | external returns (uint[] memory amounts); 133 | 134 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 135 | uint amountIn, 136 | uint amountOutMin, 137 | address[] calldata path, 138 | address to, 139 | uint deadline 140 | ) external; 141 | } 142 | 143 | contract Swap { 144 | using SafeERC20 for IERC20; 145 | using Address for address; 146 | using SafeMath for uint256; 147 | 148 | address public owner; 149 | 150 | constructor()public{ 151 | owner = tx.origin; 152 | } 153 | modifier onlyOwner(){ 154 | require(msg.sender == owner,"not owner"); 155 | _; 156 | } 157 | 158 | address constant public yfii = address(0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83); 159 | address constant public unirouter = address(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); 160 | address constant public weth = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); 161 | address constant public dai = address(0x6B175474E89094C44Da98b954EedeAC495271d0F); 162 | address constant public pasta = address(0x08A2E41FB99A7599725190B9C970Ad3893fa33CF); 163 | address constant public yycrv = address(0x5dbcF33D8c2E976c6b560249878e6F1491Bca25c); 164 | address constant public ycrv = address(0xdF5e0e81Dff6FAF3A7e52BA697820c5e32D806A8); 165 | 166 | 167 | 168 | function doswap(uint256 _amount) public { 169 | IERC20(pasta).safeApprove(unirouter, 0); 170 | IERC20(pasta).safeApprove(unirouter, uint(-1)); 171 | address[] memory path2 = new address[](2); 172 | path2[0] = address(pasta); 173 | path2[1] = address(yycrv); 174 | UniswapRouter(unirouter).swapExactTokensForTokensSupportingFeeOnTransferTokens(IERC20(pasta).balanceOf(address(this)), 0, path2, address(this), now.add(1800)); 175 | 176 | //yycrv-> yvault-> ycrv 177 | CrvYvault(yycrv).withdraw(IERC20(yycrv).balanceOf(address(this))); 178 | 179 | //ycrv -> weth-> yfii 180 | IERC20(ycrv).safeApprove(unirouter, 0); 181 | IERC20(ycrv).safeApprove(unirouter, uint(-1)); 182 | address[] memory path3 = new address[](3); 183 | path3[0] = address(ycrv); 184 | path3[1] = address(weth); 185 | path3[2] = address(yfii); 186 | UniswapRouter(unirouter).swapExactTokensForTokens(IERC20(ycrv).balanceOf(address(this)), 0, path3, address(this), now.add(1800)); 187 | 188 | } 189 | function inCaseTokenGetsStuck(IERC20 _TokenAddress) onlyOwner public { 190 | uint qty = _TokenAddress.balanceOf(address(this)); 191 | _TokenAddress.safeTransfer(msg.sender, qty); 192 | } 193 | 194 | // incase of half-way error 195 | function inCaseETHGetsStuck() onlyOwner public{ 196 | (bool result, ) = msg.sender.call.value(address(this).balance)(""); 197 | require(result, "transfer of ETH failed"); 198 | } 199 | } -------------------------------------------------------------------------------- /contracts/yfiiVoterProxy.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at Etherscan.io on 2020-08-30 3 | */ 4 | 5 | // SPDX-License-Identifier: MIT 6 | 7 | pragma solidity ^0.5.16; 8 | 9 | interface IERC20 { 10 | function totalSupply() external view returns (uint256); 11 | function balanceOf(address account) external view returns (uint256); 12 | function transfer(address recipient, uint256 amount) external returns (bool); 13 | function allowance(address owner, address spender) external view returns (uint256); 14 | function approve(address spender, uint256 amount) external returns (bool); 15 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 16 | event Transfer(address indexed from, address indexed to, uint256 value); 17 | event Approval(address indexed owner, address indexed spender, uint256 value); 18 | } 19 | 20 | interface YFIIVAULT { 21 | function plyr_(address) external view returns (uint, uint,uint); 22 | } 23 | 24 | contract YfiiVoterProxy { 25 | 26 | IERC20 public constant yfii = IERC20(0xa1d0E215a23d7030842FC67cE582a6aFa3CCaB83); 27 | IERC20 public constant poo3 = IERC20(0xf1750B770485A5d0589A6ba1270D9FC354884D45); 28 | YFIIVAULT public constant vault = YFIIVAULT(0xf5a232b1325769E09B303D7292589a2C7AEe2Aa4); 29 | 30 | function decimals() external pure returns (uint8) { 31 | return uint8(18); 32 | } 33 | 34 | function name() external pure returns (string memory) { 35 | return "YFIIPOWAH"; 36 | } 37 | 38 | function symbol() external pure returns (string memory) { 39 | return "YFII"; 40 | } 41 | 42 | function totalSupply() external view returns (uint) { 43 | return yfii.totalSupply(); 44 | } 45 | 46 | function balanceOf(address _voter) external view returns (uint) { 47 | (uint _votes,) = vault.plyr_(_voter); 48 | return _votes+yfii.balanceOf(_voter)+poo3.balanceOf(_voter); 49 | } 50 | } -------------------------------------------------------------------------------- /contracts/yfiicontract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.15; 2 | 3 | interface IERC20 { 4 | function totalSupply() external view returns (uint); 5 | function balanceOf(address account) external view returns (uint); 6 | function transfer(address recipient, uint amount) external returns (bool); 7 | function allowance(address owner, address spender) external view returns (uint); 8 | function approve(address spender, uint amount) external returns (bool); 9 | function transferFrom(address sender, address recipient, uint amount) external returns (bool); 10 | event Transfer(address indexed from, address indexed to, uint value); 11 | event Approval(address indexed owner, address indexed spender, uint value); 12 | } 13 | 14 | contract Context { 15 | constructor () internal { } 16 | // solhint-disable-previous-line no-empty-blocks 17 | 18 | function _msgSender() internal view returns (address payable) { 19 | return msg.sender; 20 | } 21 | } 22 | 23 | contract ERC20 is Context, IERC20 { 24 | using SafeMath for uint; 25 | 26 | mapping (address => uint) private _balances; 27 | 28 | mapping (address => mapping (address => uint)) private _allowances; 29 | 30 | uint private _totalSupply; 31 | function totalSupply() public view returns (uint) { 32 | return _totalSupply; 33 | } 34 | function balanceOf(address account) public view returns (uint) { 35 | return _balances[account]; 36 | } 37 | function transfer(address recipient, uint amount) public returns (bool) { 38 | _transfer(_msgSender(), recipient, amount); 39 | return true; 40 | } 41 | function allowance(address owner, address spender) public view returns (uint) { 42 | return _allowances[owner][spender]; 43 | } 44 | function approve(address spender, uint amount) public returns (bool) { 45 | _approve(_msgSender(), spender, amount); 46 | return true; 47 | } 48 | function transferFrom(address sender, address recipient, uint amount) public returns (bool) { 49 | _transfer(sender, recipient, amount); 50 | _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 51 | return true; 52 | } 53 | function increaseAllowance(address spender, uint addedValue) public returns (bool) { 54 | _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 55 | return true; 56 | } 57 | function decreaseAllowance(address spender, uint subtractedValue) public returns (bool) { 58 | _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 59 | return true; 60 | } 61 | function _transfer(address sender, address recipient, uint amount) internal { 62 | require(sender != address(0), "ERC20: transfer from the zero address"); 63 | require(recipient != address(0), "ERC20: transfer to the zero address"); 64 | 65 | _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 66 | _balances[recipient] = _balances[recipient].add(amount); 67 | emit Transfer(sender, recipient, amount); 68 | } 69 | function _mint(address account, uint amount) internal { 70 | require(account != address(0), "ERC20: mint to the zero address"); 71 | 72 | _totalSupply = _totalSupply.add(amount); 73 | _balances[account] = _balances[account].add(amount); 74 | emit Transfer(address(0), account, amount); 75 | } 76 | function _burn(address account, uint amount) internal { 77 | require(account != address(0), "ERC20: burn from the zero address"); 78 | 79 | _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 80 | _totalSupply = _totalSupply.sub(amount); 81 | emit Transfer(account, address(0), amount); 82 | } 83 | function _approve(address owner, address spender, uint amount) internal { 84 | require(owner != address(0), "ERC20: approve from the zero address"); 85 | require(spender != address(0), "ERC20: approve to the zero address"); 86 | 87 | _allowances[owner][spender] = amount; 88 | emit Approval(owner, spender, amount); 89 | } 90 | } 91 | 92 | contract ERC20Detailed is IERC20 { 93 | string private _name; 94 | string private _symbol; 95 | uint8 private _decimals; 96 | 97 | constructor (string memory name, string memory symbol, uint8 decimals) public { 98 | _name = name; 99 | _symbol = symbol; 100 | _decimals = decimals; 101 | } 102 | function name() public view returns (string memory) { 103 | return _name; 104 | } 105 | function symbol() public view returns (string memory) { 106 | return _symbol; 107 | } 108 | function decimals() public view returns (uint8) { 109 | return _decimals; 110 | } 111 | } 112 | 113 | library SafeMath { 114 | function add(uint a, uint b) internal pure returns (uint) { 115 | uint c = a + b; 116 | require(c >= a, "SafeMath: addition overflow"); 117 | 118 | return c; 119 | } 120 | function sub(uint a, uint b) internal pure returns (uint) { 121 | return sub(a, b, "SafeMath: subtraction overflow"); 122 | } 123 | function sub(uint a, uint b, string memory errorMessage) internal pure returns (uint) { 124 | require(b <= a, errorMessage); 125 | uint c = a - b; 126 | 127 | return c; 128 | } 129 | function mul(uint a, uint b) internal pure returns (uint) { 130 | if (a == 0) { 131 | return 0; 132 | } 133 | 134 | uint c = a * b; 135 | require(c / a == b, "SafeMath: multiplication overflow"); 136 | 137 | return c; 138 | } 139 | function div(uint a, uint b) internal pure returns (uint) { 140 | return div(a, b, "SafeMath: division by zero"); 141 | } 142 | function div(uint a, uint b, string memory errorMessage) internal pure returns (uint) { 143 | // Solidity only automatically asserts when dividing by 0 144 | require(b > 0, errorMessage); 145 | uint c = a / b; 146 | 147 | return c; 148 | } 149 | } 150 | 151 | library Address { 152 | function isContract(address account) internal view returns (bool) { 153 | bytes32 codehash; 154 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 155 | // solhint-disable-next-line no-inline-assembly 156 | assembly { codehash := extcodehash(account) } 157 | return (codehash != 0x0 && codehash != accountHash); 158 | } 159 | } 160 | 161 | library SafeERC20 { 162 | using SafeMath for uint; 163 | using Address for address; 164 | 165 | function safeTransfer(IERC20 token, address to, uint value) internal { 166 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 167 | } 168 | 169 | function safeTransferFrom(IERC20 token, address from, address to, uint value) internal { 170 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 171 | } 172 | 173 | function safeApprove(IERC20 token, address spender, uint value) internal { 174 | require((value == 0) || (token.allowance(address(this), spender) == 0), 175 | "SafeERC20: approve from non-zero to non-zero allowance" 176 | ); 177 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 178 | } 179 | function callOptionalReturn(IERC20 token, bytes memory data) private { 180 | require(address(token).isContract(), "SafeERC20: call to non-contract"); 181 | 182 | // solhint-disable-next-line avoid-low-level-calls 183 | (bool success, bytes memory returndata) = address(token).call(data); 184 | require(success, "SafeERC20: low-level call failed"); 185 | 186 | if (returndata.length > 0) { // Return data is optional 187 | // solhint-disable-next-line max-line-length 188 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 189 | } 190 | } 191 | } 192 | 193 | contract YFII is ERC20, ERC20Detailed { 194 | using SafeERC20 for IERC20; 195 | using Address for address; 196 | using SafeMath for uint; 197 | 198 | 199 | address public governance; 200 | mapping (address => bool) public minters; 201 | 202 | constructor (string memory name, string memory symbol) public ERC20Detailed(name, symbol, 18) { 203 | governance = tx.origin; 204 | } 205 | 206 | function mint(address account, uint256 amount) public { 207 | require(minters[msg.sender], "!minter"); 208 | _mint(account, amount); 209 | } 210 | 211 | function setGovernance(address _governance) public { 212 | require(msg.sender == governance, "!governance"); 213 | governance = _governance; 214 | } 215 | 216 | function addMinter(address _minter) public { 217 | require(msg.sender == governance, "!governance"); 218 | minters[_minter] = true; 219 | } 220 | 221 | function removeMinter(address _minter) public { 222 | require(msg.sender == governance, "!governance"); 223 | minters[_minter] = false; 224 | } 225 | } 226 | contract NewToken is ERC20, ERC20Detailed { 227 | using SafeERC20 for IERC20; 228 | using Address for address; 229 | using SafeMath for uint; 230 | 231 | 232 | address public governance; 233 | mapping (address => bool) public minters; 234 | 235 | constructor (string memory name, string memory symbol) public ERC20Detailed(name, symbol, 18) { 236 | governance = tx.origin; 237 | } 238 | 239 | function mint(address account, uint256 amount) public { 240 | require(minters[msg.sender], "!minter"); 241 | _mint(account, amount); 242 | } 243 | 244 | function setGovernance(address _governance) public { 245 | require(msg.sender == governance, "!governance"); 246 | governance = _governance; 247 | } 248 | 249 | function addMinter(address _minter) public { 250 | require(msg.sender == governance, "!governance"); 251 | minters[_minter] = true; 252 | } 253 | 254 | function removeMinter(address _minter) public { 255 | require(msg.sender == governance, "!governance"); 256 | minters[_minter] = false; 257 | } 258 | } -------------------------------------------------------------------------------- /contracts/yfiipool1/StrategyCurveYfii.sol: -------------------------------------------------------------------------------- 1 | /** 2 | *Submitted for verification at Etherscan.io on 2020-07-31 3 | */ 4 | 5 | // SPDX-License-Identifier: MIT 6 | 7 | pragma solidity ^0.5.15; 8 | 9 | interface IERC20 { 10 | function totalSupply() external view returns (uint256); 11 | function balanceOf(address account) external view returns (uint256); 12 | function transfer(address recipient, uint256 amount) external returns (bool); 13 | function allowance(address owner, address spender) external view returns (uint256); 14 | function decimals() external view returns (uint); 15 | function approve(address spender, uint256 amount) external returns (bool); 16 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 17 | event Transfer(address indexed from, address indexed to, uint256 value); 18 | event Approval(address indexed owner, address indexed spender, uint256 value); 19 | } 20 | 21 | library SafeMath { 22 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 23 | uint256 c = a + b; 24 | require(c >= a, "SafeMath: addition overflow"); 25 | 26 | return c; 27 | } 28 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 29 | return sub(a, b, "SafeMath: subtraction overflow"); 30 | } 31 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 32 | require(b <= a, errorMessage); 33 | uint256 c = a - b; 34 | 35 | return c; 36 | } 37 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 38 | if (a == 0) { 39 | return 0; 40 | } 41 | 42 | uint256 c = a * b; 43 | require(c / a == b, "SafeMath: multiplication overflow"); 44 | 45 | return c; 46 | } 47 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 48 | return div(a, b, "SafeMath: division by zero"); 49 | } 50 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 51 | // Solidity only automatically asserts when dividing by 0 52 | require(b > 0, errorMessage); 53 | uint256 c = a / b; 54 | 55 | return c; 56 | } 57 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 58 | return mod(a, b, "SafeMath: modulo by zero"); 59 | } 60 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 61 | require(b != 0, errorMessage); 62 | return a % b; 63 | } 64 | } 65 | 66 | library Address { 67 | function isContract(address account) internal view returns (bool) { 68 | bytes32 codehash; 69 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 70 | // solhint-disable-next-line no-inline-assembly 71 | assembly { codehash := extcodehash(account) } 72 | return (codehash != 0x0 && codehash != accountHash); 73 | } 74 | function toPayable(address account) internal pure returns (address payable) { 75 | return address(uint160(account)); 76 | } 77 | function sendValue(address payable recipient, uint256 amount) internal { 78 | require(address(this).balance >= amount, "Address: insufficient balance"); 79 | 80 | // solhint-disable-next-line avoid-call-value 81 | (bool success, ) = recipient.call.value(amount)(""); 82 | require(success, "Address: unable to send value, recipient may have reverted"); 83 | } 84 | } 85 | 86 | library SafeERC20 { 87 | using SafeMath for uint256; 88 | using Address for address; 89 | 90 | function safeTransfer(IERC20 token, address to, uint256 value) internal { 91 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 92 | } 93 | 94 | function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 95 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 96 | } 97 | 98 | function safeApprove(IERC20 token, address spender, uint256 value) internal { 99 | require((value == 0) || (token.allowance(address(this), spender) == 0), 100 | "SafeERC20: approve from non-zero to non-zero allowance" 101 | ); 102 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 103 | } 104 | function callOptionalReturn(IERC20 token, bytes memory data) private { 105 | require(address(token).isContract(), "SafeERC20: call to non-contract"); 106 | 107 | // solhint-disable-next-line avoid-low-level-calls 108 | (bool success, bytes memory returndata) = address(token).call(data); 109 | require(success, "SafeERC20: low-level call failed"); 110 | 111 | if (returndata.length > 0) { // Return data is optional 112 | // solhint-disable-next-line max-line-length 113 | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 114 | } 115 | } 116 | } 117 | 118 | interface Controller { 119 | function vaults(address) external view returns (address); 120 | function rewards() external view returns (address); 121 | } 122 | 123 | /* 124 | 125 | A strategy must implement the following calls; 126 | 127 | - deposit() 128 | - withdraw(address) must exclude any tokens used in the yield - Controller role - withdraw should return to Controller 129 | - withdraw(uint) - Controller | Vault role - withdraw should always return to vault 130 | - withdrawAll() - Controller | Vault role - withdraw should always return to vault 131 | - balanceOf() 132 | 133 | Where possible, strategies must remain as immutable as possible, instead of updating variables, we update the contract by linking it in the controller 134 | 135 | */ 136 | 137 | interface Yfii { 138 | function withdraw(uint) external; 139 | function getReward() external; 140 | function stake(uint) external; 141 | function balanceOf(address) external view returns (uint); 142 | function exit() external; 143 | } 144 | 145 | contract Balancer { 146 | function joinPool(uint poolAmountOut, uint[] calldata maxAmountsIn) external; 147 | function exitPool(uint poolAmountIn, uint[] calldata minAmountsOut) external; 148 | function swapExactAmountIn( 149 | address tokenIn, 150 | uint tokenAmountIn, 151 | address tokenOut, 152 | uint minAmountOut, 153 | uint maxPrice 154 | ) external returns (uint tokenAmountOut, uint spotPriceAfter); 155 | function swapExactAmountOut( 156 | address tokenIn, 157 | uint maxAmountIn, 158 | address tokenOut, 159 | uint tokenAmountOut, 160 | uint maxPrice 161 | ) external returns (uint tokenAmountIn, uint spotPriceAfter); 162 | function joinswapExternAmountIn(address tokenIn, uint tokenAmountIn, uint minPoolAmountOut) external returns (uint poolAmountOut); 163 | function exitswapPoolAmountIn(address tokenOut, uint poolAmountIn, uint minAmountOut) external returns (uint tokenAmountOut); 164 | } 165 | 166 | interface yERC20 { 167 | function deposit(uint256 _amount) external; 168 | function withdraw(uint256 _amount) external; 169 | } 170 | 171 | interface ICurveFi { 172 | 173 | function get_virtual_price() external view returns (uint); 174 | function add_liquidity( 175 | uint256[4] calldata amounts, 176 | uint256 min_mint_amount 177 | ) external; 178 | function remove_liquidity_imbalance( 179 | uint256[4] calldata amounts, 180 | uint256 max_burn_amount 181 | ) external; 182 | function remove_liquidity( 183 | uint256 _amount, 184 | uint256[4] calldata amounts 185 | ) external; 186 | function exchange( 187 | int128 from, int128 to, uint256 _from_amount, uint256 _min_to_amount 188 | ) external; 189 | } 190 | interface Yvault{ 191 | function make_profit(uint256 amount) external; 192 | } 193 | contract StrategyYfii { 194 | using SafeERC20 for IERC20; 195 | using Address for address; 196 | using SafeMath for uint256; 197 | 198 | address constant public want = address(0x49bD7631856078257d5Aef996Cb1218519eA1Db4); 199 | address constant public pool = address(0x343887B22FB4088ED3cFeDCdDb08c67C01ca639A); 200 | address constant public yfii = address(0xf2d645D45F0A46CDfa080595Df1d6C9D733296c3); 201 | 202 | 203 | uint constant public fee = 50; 204 | uint constant public max = 10000; 205 | 206 | address public governance; 207 | address public controller; 208 | 209 | constructor(address _controller) public { 210 | governance = msg.sender; 211 | controller = _controller; 212 | } 213 | 214 | function deposit() external { //把ycrv stake到 pool1 215 | IERC20(want).safeApprove(pool, 0); 216 | IERC20(want).safeApprove(pool, IERC20(want).balanceOf(address(this))); 217 | Yfii(pool).stake(IERC20(want).balanceOf(address(this))); 218 | } 219 | 220 | // Controller only function for creating additional rewards from dust 221 | function withdraw(IERC20 _asset) external returns (uint balance) { 222 | require(msg.sender == controller, "!controller"); 223 | require(want != address(_asset), "want"); 224 | balance = _asset.balanceOf(address(this)); 225 | _asset.safeTransfer(controller, balance); 226 | } 227 | 228 | // Withdraw partial funds, normally used with a vault withdrawal 229 | function withdraw(uint _amount) external { 230 | require(msg.sender == controller, "!controller"); 231 | uint _balance = IERC20(want).balanceOf(address(this)); 232 | if (_balance < _amount) { 233 | _amount = _withdrawSome(_amount.sub(_balance));//要提取的钱不够,从pool提缺少的出来 234 | _amount = _amount.add(_balance); 235 | } 236 | 237 | address _vault = Controller(controller).vaults(address(want));//金库的地址. 238 | require(_vault != address(0), "!vault"); // additional protection so we don't burn the funds 239 | IERC20(want).safeTransfer(_vault, _amount); 240 | } 241 | 242 | // Withdraw all funds, normally used when migrating strategies 243 | function withdrawAll() external returns (uint balance) { //把ycrv 还到金库 走人 244 | require(msg.sender == controller, "!controller"); 245 | _withdrawAll(); 246 | balance = IERC20(want).balanceOf(address(this)); 247 | 248 | address _vault = Controller(controller).vaults(address(want)); 249 | require(_vault != address(0), "!vault"); // additional protection so we don't burn the funds 250 | IERC20(want).safeTransfer(_vault, balance); 251 | 252 | } 253 | 254 | function _withdrawAll() internal { //退池子 已经领取收益. 收益换成ycrv 255 | Yfii(pool).exit(); 256 | harvest(); 257 | } 258 | 259 | function harvest() public {//砸盘yfii 260 | Yfii(pool).getReward(); //领取yfii 261 | address _vault = Controller(controller).vaults(address(want)); 262 | require(_vault != address(0), "!vault"); // additional protection so we don't burn the funds 263 | 264 | 265 | //把yfii 存进去分红. 266 | IERC20(yfii).safeApprove(_vault, 0); 267 | IERC20(yfii).safeApprove(_vault, IERC20(yfii).balanceOf(address(this))); 268 | Yvault(_vault).make_profit(IERC20(yfii).balanceOf(address(this))); 269 | } 270 | 271 | function _withdrawSome(uint256 _amount) internal returns (uint) { 272 | Yfii(pool).withdraw(_amount); 273 | return _amount; 274 | } 275 | 276 | function balanceOfCurve() public view returns (uint) { 277 | return IERC20(want).balanceOf(address(this)); 278 | } 279 | 280 | function balanceOfYfii() public view returns (uint) { 281 | return Yfii(pool).balanceOf(address(this)); 282 | } 283 | 284 | function balanceOf() public view returns (uint) { 285 | return balanceOfCurve(); 286 | 287 | } 288 | 289 | function setGovernance(address _governance) external { 290 | require(msg.sender == governance, "!governance"); 291 | governance = _governance; 292 | } 293 | 294 | function setController(address _controller) external { 295 | require(msg.sender == governance, "!governance"); 296 | controller = _controller; 297 | } 298 | } -------------------------------------------------------------------------------- /contracts/yfiipool2/readme.md: -------------------------------------------------------------------------------- 1 | # StrategyYfiiPool2 2 | 3 | 接受bpt来挖 yfii 4 | 5 | yvault内置了 dai2bpt,bpt2dai 来方便转换 -------------------------------------------------------------------------------- /py/cal.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from web3 import Web3, HTTPProvider 4 | 5 | w3url = "https://mainnet.infura.io/v3/998f64f3627548bbaf2630599c1eefca" 6 | 7 | w3 = Web3(HTTPProvider(w3url)) 8 | 9 | with open("abi/vault.json") as f: 10 | abi = json.loads(f.read()) 11 | 12 | 13 | def get_total_out(contract_address): 14 | contract_address = w3.toChecksumAddress(contract_address) 15 | contract_instance = w3.eth.contract(abi=abi, address=contract_address) 16 | total_out = contract_instance.functions.global_(0).call()[1] 17 | return total_out 18 | 19 | 20 | if __name__ == "__main__": 21 | vaults_address = set( 22 | [ 23 | "0xf693705e79ccc8707D3FcB4D89381CaC28e45a22", 24 | "0xd4bEf8D8D8d7cBB89f63933Db6907439f9E6Fd0f", 25 | "0xA2D35bcDFc271767903f0Ed4aF56a066F6c99Ae7", 26 | "0x537350b9301fCf045Eaf1CEa2F225276C89D5f6D", 27 | "0x4BD410A06FBB3A22C31017964D13Cbc5867d3d61", 28 | "0xCda9230923FCb25e26a20D7D9D12e1744405C9fC", 29 | "0x7AEFB9DCE3700B7CE8B1f556043BB1D436C77e0d", 30 | "0x2f4Ae3a95C7B457DB53706EEE8979aEca4ec0082", 31 | "0xD2db1EF55549eCdacb4e7da081216AE96f0Eedcb", 32 | "0xf5a232b1325769E09B303D7292589a2C7AEe2Aa4", 33 | "0x804a3DBb6C1f4c379B3ee985488Ef37C4cBbac5C", 34 | "0x35a228bBe17F7c6D1ebaCc59fcA3aC6733135E63", 35 | "0x8FDD31b72Cc18c965E6a7BC85174994e72799732", 36 | "0xA9C7216650dA5A9bbC049ffa56008029344DB010", 37 | "0x956da37db508901294f62488e030ce0871293270", 38 | "0x5c8Bb2C9C0bC2655dE05198de50651820b95C541", 39 | "0xed288394e3086fb90e43f4919b5d3661c05278be", 40 | "0xD2db1EF55549eCdacb4e7da081216AE96f0Eedcb", 41 | "0x7b0f825efe96dd46f1460227d634ea37b10ca7c5", 42 | "0xd0249f2e69098029b2b37c888c061a0d95f989a2", 43 | "0xa407c685422d6b4bf07809216bb597125312a790", 44 | "0xab721be37a57b7f91098cb5f11ae423dc76350a9", 45 | "0xf811c062D14fdF9Fda95D6A2C54e137afE80De45", 46 | ] 47 | ) 48 | 49 | total_out = sum([get_total_out(i) for i in vaults_address]) 50 | total_out = total_out / 1e18 51 | print(total_out) 52 | -------------------------------------------------------------------------------- /py/deploy.py: -------------------------------------------------------------------------------- 1 | from web3.auto import w3 2 | from web3 import Web3 3 | from solc import compile_standard 4 | import os 5 | import json 6 | import random 7 | import decimal 8 | 9 | ctx = decimal.Context() 10 | ctx.prec = 50 11 | 12 | 13 | def float_to_str(f): 14 | """ 15 | Convert the given float to a string, 16 | without resorting to scientific notation 17 | """ 18 | d1 = ctx.create_decimal(repr(f)) 19 | return format(d1, "f") 20 | 21 | 22 | w3.eth.defaultAccount = w3.eth.accounts[0] 23 | 24 | 25 | def geneateCompiled_sol(sol_name, contract_name): 26 | basedir = "/Users/gaojin/Documents/GitHub/yvault/contracts" 27 | fname = os.path.join(basedir, sol_name) 28 | with open(fname) as f: 29 | content = f.read() 30 | _compile_standard = { 31 | "language": "Solidity", 32 | "sources": {sol_name: {"content": content}}, 33 | "settings": { 34 | "outputSelection": { 35 | "*": {"*": ["metadata", "evm.bytecode", "evm.bytecode.sourceMap"]} 36 | } 37 | }, 38 | } 39 | compiled_sol = compile_standard(_compile_standard) 40 | bytecode = compiled_sol["contracts"][sol_name][contract_name]["evm"]["bytecode"][ 41 | "object" 42 | ] 43 | abi = json.loads(compiled_sol["contracts"][sol_name][contract_name]["metadata"])[ 44 | "output" 45 | ]["abi"] 46 | 47 | c = w3.eth.contract(abi=abi, bytecode=bytecode) 48 | return c, abi 49 | 50 | 51 | def deploy(): 52 | ## Controller 53 | Controller, abi = geneateCompiled_sol("Controller.sol", "Controller") 54 | tx_hash = Controller.constructor().transact() 55 | tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash) 56 | controller_instance = w3.eth.contract(address=tx_receipt.contractAddress, abi=abi) 57 | 58 | Yfii, abi = geneateCompiled_sol("yfiicontract.sol", "YFII") 59 | tx_hash = Yfii.constructor("YFII", "YFII").transact() 60 | tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash) 61 | yfii_instance = w3.eth.contract(address=tx_receipt.contractAddress, abi=abi) 62 | print(yfii_instance.functions.name().call()) 63 | 64 | token, abi = geneateCompiled_sol("yfiicontract.sol", "NewToken") 65 | tx_hash = token.constructor("NewToken", "NewToken").transact() 66 | tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash) 67 | token_instance = w3.eth.contract(address=tx_receipt.contractAddress, abi=abi) 68 | print(token_instance.functions.name().call()) 69 | 70 | StrategyYfii, abi = geneateCompiled_sol("yfiipool1/StrategyCurveYfii.sol", "StrategyYfii") 71 | tx_hash = StrategyYfii.constructor(controller_instance.address).transact() 72 | tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash) 73 | strategyYfii_instance = w3.eth.contract(address=tx_receipt.contractAddress, abi=abi) 74 | # print(strategyYfii_instance.functions.controller().call()) 75 | assert ( 76 | strategyYfii_instance.functions.controller().call() 77 | == controller_instance.address 78 | ) 79 | 80 | yVault, abi = geneateCompiled_sol("yfiipool1/yvault.sol", "yVault") 81 | tx_hash = yVault.constructor( 82 | token_instance.address, controller_instance.address, yfii_instance.address 83 | ).transact() 84 | tx_receipt = w3.eth.waitForTransactionReceipt(tx_hash) 85 | yVault_instance = w3.eth.contract(address=tx_receipt.contractAddress, abi=abi) 86 | 87 | assert yVault_instance.functions.controller().call() == controller_instance.address 88 | assert yVault_instance.functions.Yfiitoken().call() == yfii_instance.address 89 | assert yVault_instance.functions.token().call() == token_instance.address 90 | 91 | return ( 92 | yfii_instance, 93 | token_instance, 94 | controller_instance, 95 | yVault_instance, 96 | strategyYfii_instance, 97 | ) 98 | 99 | 100 | ( 101 | yfii_instance, 102 | token_instance, 103 | controller_instance, 104 | yVault_instance, 105 | strategyYfii_instance, 106 | ) = deploy() 107 | from_0 = w3.eth.accounts[0] 108 | from_1 = w3.eth.accounts[1] 109 | from_2 = w3.eth.accounts[2] 110 | 111 | 112 | def run(): 113 | setup() 114 | 115 | # from_1 depost 116 | w3.eth.defaultAccount = from_1 117 | deposit_balance = w3.toWei("1000", "ether") 118 | yVault_instance.functions.deposit(deposit_balance).transact() 119 | # 检查 yVault的余额情况 120 | assert ( 121 | token_instance.functions.balanceOf(yVault_instance.address).call() 122 | == deposit_balance 123 | ) 124 | total_stake, total_out, earnings_per_share = yVault_instance.functions.global_( 125 | 0 126 | ).call() 127 | assert [total_stake, total_out, earnings_per_share] == [deposit_balance, 0, 0] 128 | 129 | # 检查 用户存入情况 130 | stake, payout, total_out = yVault_instance.functions.plyr_(from_1).call() 131 | assert [stake, payout, total_out] == [deposit_balance, 0, 0] 132 | 133 | # cal_out 134 | assert yVault_instance.functions.cal_out(from_1).call() == 0 135 | 136 | # make_profit 137 | w3.eth.defaultAccount = from_0 138 | make_profit_balance = w3.toWei("1", "ether") 139 | yVault_instance.functions.make_profit(make_profit_balance).transact() 140 | assert ( 141 | yfii_instance.functions.balanceOf(yVault_instance.address).call() 142 | == make_profit_balance 143 | ) 144 | 145 | _earnings_per_share = earnings_per_share + ( 146 | int(float_to_str(make_profit_balance * 10 ** 40 / total_stake)) 147 | ) 148 | _earnings_per_share = int(_earnings_per_share) 149 | total_stake, total_out, earnings_per_share = yVault_instance.functions.global_( 150 | 0 151 | ).call() 152 | assert [total_stake, total_out, earnings_per_share] == [ 153 | deposit_balance, 154 | make_profit_balance, 155 | _earnings_per_share, 156 | ] 157 | # 算出应该领取的分红 158 | # _calout = int(float_to_str(earnings_per_share * stake/10**40 )) - payout 159 | # assert yVault_instance.functions.cal_out(from_1).call() == make_profit_balance 160 | 161 | # 领取分红 162 | # w3.eth.defaultAccount = from_1 163 | # yVault_instance.functions.claim().transact() 164 | 165 | # stake, payout, total_out = yVault_instance.functions.plyr_(from_1).call() 166 | # assert [stake, payout, total_out] == [deposit_balance, _calout, make_profit_balance] 167 | 168 | # assert ( 169 | # yfii_instance.functions.balanceOf(yVault_instance.address).call() 170 | # == make_profit_balance - _calout 171 | # ) 172 | justRun() 173 | 174 | check() 175 | 176 | def justRun(): 177 | i = 0 178 | while True: 179 | i += 1 180 | print(i) 181 | random_deposit() 182 | random_make_profit() 183 | if i % 20 == 0: 184 | claim() 185 | if i % 10 == 0: 186 | random_withdraw() 187 | if i >= 1000: 188 | break 189 | 190 | def random_deposit(): 191 | w3.eth.defaultAccount = from_1 192 | deposit_balance = random.randint(1000, pow(2, 75)) 193 | yVault_instance.functions.deposit(deposit_balance).transact() 194 | 195 | w3.eth.defaultAccount = from_2 196 | deposit_balance = random.randint(1000, pow(2, 75)) 197 | yVault_instance.functions.deposit(deposit_balance).transact() 198 | 199 | 200 | def random_withdraw(): 201 | w3.eth.defaultAccount = from_1 202 | 203 | stake, payout, total_out = yVault_instance.functions.plyr_(from_1).call() 204 | # print(from_1,[stake, payout, total_out]) 205 | withdraw_balance = random.randint(1, stake // 2) 206 | yVault_instance.functions.withdraw(withdraw_balance).transact() 207 | 208 | w3.eth.defaultAccount = from_2 209 | 210 | stake, payout, total_out = yVault_instance.functions.plyr_(from_2).call() 211 | # print(from_2,[stake, payout, total_out]) 212 | 213 | withdraw_balance = random.randint(1, stake // 2) 214 | yVault_instance.functions.withdraw(withdraw_balance).transact() 215 | 216 | 217 | def random_make_profit(): 218 | w3.eth.defaultAccount = from_0 219 | make_profit_balance = random.randint(1, pow(10, 2)) 220 | yVault_instance.functions.make_profit(make_profit_balance).transact() 221 | 222 | 223 | def claim(): 224 | w3.eth.defaultAccount = from_1 225 | yVault_instance.functions.claim().transact() 226 | w3.eth.defaultAccount = from_2 227 | yVault_instance.functions.claim().transact() 228 | 229 | 230 | def check(): 231 | """ 232 | 最后检查各种分红是否正常... 233 | 234 | 先claim的话 235 | 那么理论上 yVault_instance上的yfii余额为0 236 | from_0+from_1+from_2的yfii 余额加起来为初始余额 237 | 238 | token的话,余额会到 yVault_instance 上面 239 | yVault_instance+from_1+from_2 的token 余额加起来为初始*2 240 | 241 | 242 | 243 | 244 | """ 245 | init_balance = w3.toWei(str(pow(2, 100)), "ether") # 初始化的余额 246 | claim() 247 | 248 | assert yfii_instance.functions.balanceOf(yVault_instance.address).call() == 0 249 | 250 | assert ( 251 | yfii_instance.functions.balanceOf(from_0).call() 252 | + yfii_instance.functions.balanceOf(from_1).call() 253 | + yfii_instance.functions.balanceOf(from_2).call() 254 | == init_balance 255 | ) 256 | assert ( 257 | token_instance.functions.balanceOf(yVault_instance.address).call() 258 | + token_instance.functions.balanceOf(from_1).call() 259 | + token_instance.functions.balanceOf(from_2).call() 260 | == init_balance * 2 261 | ) 262 | 263 | stake1, payout1, total_out1 = yVault_instance.functions.plyr_(from_1).call() 264 | 265 | stake2, payout2, total_out2 = yVault_instance.functions.plyr_(from_2).call() 266 | 267 | assert ( 268 | stake1 + stake2 269 | == token_instance.functions.balanceOf(yVault_instance.address).call() 270 | ) 271 | 272 | assert total_out1 == yfii_instance.functions.balanceOf(from_1).call() 273 | assert total_out2 == yfii_instance.functions.balanceOf(from_2).call() 274 | 275 | 276 | def setup(): 277 | 278 | w3.eth.defaultAccount = from_0 279 | ## yfii mint to from_0 280 | yfii_instance.functions.addMinter(from_0).transact() 281 | mint_balance = w3.toWei(str(pow(2, 100)), "ether") 282 | yfii_instance.functions.mint(from_0, mint_balance).transact() 283 | 284 | assert yfii_instance.functions.balanceOf(from_0).call() == mint_balance 285 | 286 | ## token mint to from_1,from_2 287 | token_instance.functions.addMinter(from_0).transact() 288 | token_instance.functions.mint(from_1, mint_balance).transact() 289 | token_instance.functions.mint(from_2, mint_balance).transact() 290 | 291 | assert token_instance.functions.balanceOf(from_1).call() == mint_balance 292 | assert token_instance.functions.balanceOf(from_2).call() == mint_balance 293 | 294 | ## approve 295 | approve_balance = w3.toWei(str(pow(2, 100) - 1), "ether") 296 | 297 | ## yfii: from_0 approve to yVault_instance 298 | yfii_instance.functions.approve( 299 | yVault_instance.address, approve_balance 300 | ).transact() ## make_profit 301 | 302 | ## token: from_1 approve to yVault_instance 303 | w3.eth.defaultAccount = from_1 304 | token_instance.functions.approve( 305 | yVault_instance.address, approve_balance 306 | ).transact() ## deposit 307 | 308 | ## token: from_2 approve to yVault_instance 309 | w3.eth.defaultAccount = from_2 310 | token_instance.functions.approve( 311 | yVault_instance.address, approve_balance 312 | ).transact() ## deposit 313 | 314 | 315 | if __name__ == "__main__": 316 | run() 317 | -------------------------------------------------------------------------------- /py/getClaimAbleTokens.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | from web3 import Web3, HTTPProvider 4 | 5 | w3url = "https://mainnet.infura.io/v3/998f64f3627548bbaf2630599c1eefca" 6 | 7 | w3 = Web3(HTTPProvider(w3url)) 8 | 9 | with open("abi/crvdeposit.json") as f: 10 | abi = json.loads(f.read()) 11 | 12 | contract_instance = w3.eth.contract(abi=abi,address=w3.toChecksumAddress('0x7ca5b0a2910B33e9759DC7dDB0413949071D7575')) 13 | 14 | contract_instance.functions.claimable_tokens('0xEfb684AB29371e701CCe3CA9e3FD8f5E33042eee').call() 15 | 16 | if __name__ == "__main__": 17 | pass -------------------------------------------------------------------------------- /truffle-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Use this file to configure your truffle project. It's seeded with some 3 | * common settings for different networks and features like migrations, 4 | * compilation and testing. Uncomment the ones you need or modify 5 | * them to suit your project as necessary. 6 | * 7 | * More information about configuration can be found at: 8 | * 9 | * truffleframework.com/docs/advanced/configuration 10 | * 11 | * To deploy via Infura you'll need a wallet provider (like @truffle/hdwallet-provider) 12 | * to sign your transactions before they're sent to a remote public node. Infura accounts 13 | * are available for free at: infura.io/register. 14 | * 15 | * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate 16 | * public/private key pairs. If you're publishing your code to GitHub make sure you load this 17 | * phrase from a file you've .gitignored so it doesn't accidentally become public. 18 | * 19 | */ 20 | 21 | // const HDWalletProvider = require('@truffle/hdwallet-provider'); 22 | // const infuraKey = "fj4jll3k....."; 23 | // 24 | // const fs = require('fs'); 25 | // const mnemonic = fs.readFileSync(".secret").toString().trim(); 26 | 27 | module.exports = { 28 | /** 29 | * Networks define how you connect to your ethereum client and let you set the 30 | * defaults web3 uses to send transactions. If you don't specify one truffle 31 | * will spin up a development blockchain for you on port 9545 when you 32 | * run `develop` or `test`. You can ask a truffle command to use a specific 33 | * network from the command line, e.g 34 | * 35 | * $ truffle test --network 36 | */ 37 | 38 | networks: { 39 | // Useful for testing. The `development` name is special - truffle uses it by default 40 | // if it's defined here and no other network is specified at the command line. 41 | // You should run a client (like ganache-cli, geth or parity) in a separate terminal 42 | // tab if you use this network and you must also set the `host`, `port` and `network_id` 43 | // options below to some value. 44 | // 45 | development: { 46 | host: "127.0.0.1", // Localhost (default: none) 47 | port: 8545, // Standard Ethereum port (default: none) 48 | network_id: "*", // Any network (default: none) 49 | }, 50 | 51 | // Another network with more advanced options... 52 | // advanced: { 53 | // port: 8777, // Custom port 54 | // network_id: 1342, // Custom network 55 | // gas: 8500000, // Gas sent with each transaction (default: ~6700000) 56 | // gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei) 57 | // from:
, // Account to send txs from (default: accounts[0]) 58 | // websockets: true // Enable EventEmitter interface for web3 (default: false) 59 | // }, 60 | 61 | // Useful for deploying to a public network. 62 | // NB: It's important to wrap the provider as a function. 63 | // ropsten: { 64 | // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`), 65 | // network_id: 3, // Ropsten's id 66 | // gas: 5500000, // Ropsten has a lower block limit than mainnet 67 | // confirmations: 2, // # of confs to wait between deployments. (default: 0) 68 | // timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 69 | // skipDryRun: true // Skip dry run before migrations? (default: false for public nets ) 70 | // }, 71 | 72 | // Useful for private networks 73 | // private: { 74 | // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), 75 | // network_id: 2111, // This network is yours, in the cloud. 76 | // production: true // Treats this network as if it was a public net. (default: false) 77 | // } 78 | }, 79 | 80 | // Set default mocha options here, use special reporters etc. 81 | mocha: { 82 | // timeout: 100000 83 | }, 84 | 85 | // Configure your compilers 86 | compilers: { 87 | solc: { 88 | version: "0.5.16", // Fetch exact version from solc-bin (default: truffle's version) 89 | // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) 90 | settings: { // See the solidity docs for advice about optimization and evmVersion 91 | optimizer: { 92 | enabled: true, 93 | runs: 200 94 | }, 95 | // evmVersion: "byzantium" 96 | } 97 | } 98 | } 99 | } 100 | --------------------------------------------------------------------------------