├── .gitignore ├── LICENSE ├── README.md ├── abi ├── Timelock.json ├── ValueLiquidityToken.json └── ValueMasterPool.json ├── contracts ├── VALUE │ ├── Timelock.sol │ ├── ValueLiquidityToken.sol │ ├── ValueMasterPool.sol │ └── mock │ │ ├── MockERC20.sol │ │ └── MockLegacyPool.sol └── YFV │ ├── YFV.sol │ ├── YFV_DevRewards.sol │ ├── YFV_Referral.sol │ ├── YFV_Rewards.sol │ ├── YFV_Rewards_Pool1_BAL.sol │ ├── YFV_Rewards_Pool2_YFI.sol │ ├── YFV_Rewards_Pool3_BAT.sol │ ├── YFV_Rewards_Pool4_REN.sol │ ├── YFV_Rewards_Pool5_KNC.sol │ ├── YFV_Rewards_Pool6_BTC.sol │ ├── YFV_Rewards_Pool7_ETH.sol │ ├── YFV_Rewards_Pool8_LINK.sol │ ├── YFV_Rewards_Pool9_YCrvUNIv2.sol │ ├── YFV_Stake.sol │ ├── YFV_Stake_v2.sol │ ├── YFV_Vote.sol │ ├── vETH.sol │ └── vUSD.sol ├── package.json ├── test ├── Timelock.test.js ├── ValueLiquidityToken.test.js ├── ValueMasterPool.test.js └── update_allocPoints.test.js └── truffle-config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 yfv-finance 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Value Defi Smart-contracts 2 | #### Bringing True Value to DeFi 3 | 4 | [Full announcement](https://medium.com/@yfv.finance/yfv-bringing-true-value-to-yield-farming-bddc4edf889a) 5 | 6 | VALUE (previously known as YFV) is the governance token of YFValue protocol. The project aims to bring the true value of yield farming finance accessible to all users, regardless of whether you are a big whale or small minnow, via its unique features, namely the voting of the inflationary rate of the supply and a referral system with automatic burning done fully on-chain. 7 | - ValueDefi.io is a DeFi yield aggregator 8 | - First-ever Vote on-chain Supply Inflation rate to enable farmers to vote on-chain and automatic execution will be made based on the votes counted. 9 | - YFV has a stable-coins pool which allows even small players to join the DeFi Yield Farming. The number of users will then be 100x or more compared to other DeFi Yield Farming Protocol. 10 | - Referral and Burn On-chain to motivate the community who are giving a hand for bringing YFV to the public. 11 | - Last but not least, the separated Elastic Supply Stable-coins vUSD and vETH are great add-on benefits for the farmers and the whole ecosystem later on along the road map. 12 | 13 | ### Smart contracts comparison with super-classes 14 | 15 | [Diff checker: YFI and YFV](https://www.diffchecker.com/xmmWFRAg) 16 | 17 | [Diff checker: YFIRewards and YFVRewards (Seed Pool)](https://www.diffchecker.com/PT4d1PSC) 18 | - Seed Pool supports 4 stables coin instead of a single y coin from the original code 19 | 20 | [Diff checker: YFIRewards and YFV_Rewards_PoolXXX (Balancer/Uni Pool)](https://www.diffchecker.com/PWyndemv) 21 | - Removed rewardDistribution 22 | - notifyRewardAmount() can only call once by owner and reward amount cant be over TOTAL_REWARD 23 | 24 | [Diff checker: YFV_Stake and YFV_Stake_v2](https://www.diffchecker.com/ILtq1RZG) 25 | - Added whitelistedPools (so hackers can't attack via stakeOnBelf by penny amount anymore) 26 | - Added lowStakeDepositFee, highStakeDepositFee, unlockWithdrawFee (and disable all at the beginning. Will set by governance after VIP-1.1) 27 | - Set yfvInsuranceFund to Governance Multisig Wallet (and move to deployed Insurance Fund contract later) 28 | - Owner (governance) can set epochReward to 0 to disable the pool with no harm 29 | - Check if the minter rights (vETH and vUSD) are revoked, and set epochReward to zero with no harm (in checkNextEpoch() modifier) 30 | - Use the same solidity version uniformly across the contract 31 | - Optimise gas usage for getReward() method 32 | - Add governanceRecoverUnsupported for recover any ERC20 sent in mess up 33 | - Governance can add more reward if needed via addTotalReward() but not more than 10 times 34 | - Ability to upgrade vUSD and vETH contract (v1 is still experimental, we may need vUSDv2 with rebase() function working soon) 35 | 36 | **_Staking Deposit/Withdraw Fee system:_** 37 | - unlockWithdrawFee = 0.1%: stakers will need to pay 0.1% (sent to insurance fund)of amount they want to withdraw if the coin still frozen 38 | - lowStakeDepositFee = 0.1%: stakers still can stake with low amount but need to pay 0.1% (sent to insurance fund) 39 | - specially, if lowStakeDepositFee = 10000 -> low amount stakers will not pay anything (rich-men pay tax, not poor-men) 40 | - highStakeDepositFee = 0.1%: stakers need to pay 0.1% of extra amount more than 90 YFV (sent to insurance fund) 41 | -------------------------------------------------------------------------------- /abi/Timelock.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "admin_", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "uint256", 11 | "name": "delay_", 12 | "type": "uint256" 13 | } 14 | ], 15 | "stateMutability": "nonpayable", 16 | "type": "constructor" 17 | }, 18 | { 19 | "anonymous": false, 20 | "inputs": [ 21 | { 22 | "indexed": true, 23 | "internalType": "bytes32", 24 | "name": "txHash", 25 | "type": "bytes32" 26 | }, 27 | { 28 | "indexed": true, 29 | "internalType": "address", 30 | "name": "target", 31 | "type": "address" 32 | }, 33 | { 34 | "indexed": false, 35 | "internalType": "uint256", 36 | "name": "value", 37 | "type": "uint256" 38 | }, 39 | { 40 | "indexed": false, 41 | "internalType": "string", 42 | "name": "signature", 43 | "type": "string" 44 | }, 45 | { 46 | "indexed": false, 47 | "internalType": "bytes", 48 | "name": "data", 49 | "type": "bytes" 50 | }, 51 | { 52 | "indexed": false, 53 | "internalType": "uint256", 54 | "name": "eta", 55 | "type": "uint256" 56 | } 57 | ], 58 | "name": "CancelTransaction", 59 | "type": "event" 60 | }, 61 | { 62 | "anonymous": false, 63 | "inputs": [ 64 | { 65 | "indexed": true, 66 | "internalType": "bytes32", 67 | "name": "txHash", 68 | "type": "bytes32" 69 | }, 70 | { 71 | "indexed": true, 72 | "internalType": "address", 73 | "name": "target", 74 | "type": "address" 75 | }, 76 | { 77 | "indexed": false, 78 | "internalType": "uint256", 79 | "name": "value", 80 | "type": "uint256" 81 | }, 82 | { 83 | "indexed": false, 84 | "internalType": "string", 85 | "name": "signature", 86 | "type": "string" 87 | }, 88 | { 89 | "indexed": false, 90 | "internalType": "bytes", 91 | "name": "data", 92 | "type": "bytes" 93 | }, 94 | { 95 | "indexed": false, 96 | "internalType": "uint256", 97 | "name": "eta", 98 | "type": "uint256" 99 | } 100 | ], 101 | "name": "ExecuteTransaction", 102 | "type": "event" 103 | }, 104 | { 105 | "anonymous": false, 106 | "inputs": [ 107 | { 108 | "indexed": true, 109 | "internalType": "address", 110 | "name": "newAdmin", 111 | "type": "address" 112 | } 113 | ], 114 | "name": "NewAdmin", 115 | "type": "event" 116 | }, 117 | { 118 | "anonymous": false, 119 | "inputs": [ 120 | { 121 | "indexed": true, 122 | "internalType": "uint256", 123 | "name": "newDelay", 124 | "type": "uint256" 125 | } 126 | ], 127 | "name": "NewDelay", 128 | "type": "event" 129 | }, 130 | { 131 | "anonymous": false, 132 | "inputs": [ 133 | { 134 | "indexed": true, 135 | "internalType": "address", 136 | "name": "newOperator", 137 | "type": "address" 138 | } 139 | ], 140 | "name": "NewOperator", 141 | "type": "event" 142 | }, 143 | { 144 | "anonymous": false, 145 | "inputs": [ 146 | { 147 | "indexed": true, 148 | "internalType": "address", 149 | "name": "newPendingAdmin", 150 | "type": "address" 151 | } 152 | ], 153 | "name": "NewPendingAdmin", 154 | "type": "event" 155 | }, 156 | { 157 | "anonymous": false, 158 | "inputs": [ 159 | { 160 | "indexed": true, 161 | "internalType": "bytes32", 162 | "name": "txHash", 163 | "type": "bytes32" 164 | }, 165 | { 166 | "indexed": true, 167 | "internalType": "address", 168 | "name": "target", 169 | "type": "address" 170 | }, 171 | { 172 | "indexed": false, 173 | "internalType": "uint256", 174 | "name": "value", 175 | "type": "uint256" 176 | }, 177 | { 178 | "indexed": false, 179 | "internalType": "string", 180 | "name": "signature", 181 | "type": "string" 182 | }, 183 | { 184 | "indexed": false, 185 | "internalType": "bytes", 186 | "name": "data", 187 | "type": "bytes" 188 | }, 189 | { 190 | "indexed": false, 191 | "internalType": "uint256", 192 | "name": "eta", 193 | "type": "uint256" 194 | } 195 | ], 196 | "name": "QueueTransaction", 197 | "type": "event" 198 | }, 199 | { 200 | "inputs": [], 201 | "name": "GRACE_PERIOD", 202 | "outputs": [ 203 | { 204 | "internalType": "uint256", 205 | "name": "", 206 | "type": "uint256" 207 | } 208 | ], 209 | "stateMutability": "view", 210 | "type": "function" 211 | }, 212 | { 213 | "inputs": [], 214 | "name": "MAXIMUM_DELAY", 215 | "outputs": [ 216 | { 217 | "internalType": "uint256", 218 | "name": "", 219 | "type": "uint256" 220 | } 221 | ], 222 | "stateMutability": "view", 223 | "type": "function" 224 | }, 225 | { 226 | "inputs": [], 227 | "name": "MINIMUM_DELAY", 228 | "outputs": [ 229 | { 230 | "internalType": "uint256", 231 | "name": "", 232 | "type": "uint256" 233 | } 234 | ], 235 | "stateMutability": "view", 236 | "type": "function" 237 | }, 238 | { 239 | "inputs": [], 240 | "name": "acceptAdmin", 241 | "outputs": [], 242 | "stateMutability": "nonpayable", 243 | "type": "function" 244 | }, 245 | { 246 | "inputs": [], 247 | "name": "admin", 248 | "outputs": [ 249 | { 250 | "internalType": "address", 251 | "name": "", 252 | "type": "address" 253 | } 254 | ], 255 | "stateMutability": "view", 256 | "type": "function" 257 | }, 258 | { 259 | "inputs": [], 260 | "name": "admin_initialized", 261 | "outputs": [ 262 | { 263 | "internalType": "bool", 264 | "name": "", 265 | "type": "bool" 266 | } 267 | ], 268 | "stateMutability": "view", 269 | "type": "function" 270 | }, 271 | { 272 | "inputs": [ 273 | { 274 | "internalType": "address", 275 | "name": "target", 276 | "type": "address" 277 | }, 278 | { 279 | "internalType": "uint256", 280 | "name": "value", 281 | "type": "uint256" 282 | }, 283 | { 284 | "internalType": "string", 285 | "name": "signature", 286 | "type": "string" 287 | }, 288 | { 289 | "internalType": "bytes", 290 | "name": "data", 291 | "type": "bytes" 292 | }, 293 | { 294 | "internalType": "uint256", 295 | "name": "eta", 296 | "type": "uint256" 297 | } 298 | ], 299 | "name": "cancelTransaction", 300 | "outputs": [], 301 | "stateMutability": "nonpayable", 302 | "type": "function" 303 | }, 304 | { 305 | "inputs": [], 306 | "name": "delay", 307 | "outputs": [ 308 | { 309 | "internalType": "uint256", 310 | "name": "", 311 | "type": "uint256" 312 | } 313 | ], 314 | "stateMutability": "view", 315 | "type": "function" 316 | }, 317 | { 318 | "inputs": [ 319 | { 320 | "internalType": "address", 321 | "name": "target", 322 | "type": "address" 323 | }, 324 | { 325 | "internalType": "uint256", 326 | "name": "value", 327 | "type": "uint256" 328 | }, 329 | { 330 | "internalType": "string", 331 | "name": "signature", 332 | "type": "string" 333 | }, 334 | { 335 | "internalType": "bytes", 336 | "name": "data", 337 | "type": "bytes" 338 | }, 339 | { 340 | "internalType": "uint256", 341 | "name": "eta", 342 | "type": "uint256" 343 | } 344 | ], 345 | "name": "executeTransaction", 346 | "outputs": [ 347 | { 348 | "internalType": "bytes", 349 | "name": "", 350 | "type": "bytes" 351 | } 352 | ], 353 | "stateMutability": "payable", 354 | "type": "function" 355 | }, 356 | { 357 | "inputs": [], 358 | "name": "operator", 359 | "outputs": [ 360 | { 361 | "internalType": "address", 362 | "name": "", 363 | "type": "address" 364 | } 365 | ], 366 | "stateMutability": "view", 367 | "type": "function" 368 | }, 369 | { 370 | "inputs": [], 371 | "name": "pendingAdmin", 372 | "outputs": [ 373 | { 374 | "internalType": "address", 375 | "name": "", 376 | "type": "address" 377 | } 378 | ], 379 | "stateMutability": "view", 380 | "type": "function" 381 | }, 382 | { 383 | "inputs": [ 384 | { 385 | "internalType": "address", 386 | "name": "target", 387 | "type": "address" 388 | }, 389 | { 390 | "internalType": "uint256", 391 | "name": "value", 392 | "type": "uint256" 393 | }, 394 | { 395 | "internalType": "string", 396 | "name": "signature", 397 | "type": "string" 398 | }, 399 | { 400 | "internalType": "bytes", 401 | "name": "data", 402 | "type": "bytes" 403 | }, 404 | { 405 | "internalType": "uint256", 406 | "name": "eta", 407 | "type": "uint256" 408 | } 409 | ], 410 | "name": "queueTransaction", 411 | "outputs": [ 412 | { 413 | "internalType": "bytes32", 414 | "name": "", 415 | "type": "bytes32" 416 | } 417 | ], 418 | "stateMutability": "nonpayable", 419 | "type": "function" 420 | }, 421 | { 422 | "inputs": [ 423 | { 424 | "internalType": "bytes32", 425 | "name": "", 426 | "type": "bytes32" 427 | } 428 | ], 429 | "name": "queuedTransactions", 430 | "outputs": [ 431 | { 432 | "internalType": "bool", 433 | "name": "", 434 | "type": "bool" 435 | } 436 | ], 437 | "stateMutability": "view", 438 | "type": "function" 439 | }, 440 | { 441 | "inputs": [ 442 | { 443 | "internalType": "uint256", 444 | "name": "delay_", 445 | "type": "uint256" 446 | } 447 | ], 448 | "name": "setDelay", 449 | "outputs": [], 450 | "stateMutability": "nonpayable", 451 | "type": "function" 452 | }, 453 | { 454 | "inputs": [ 455 | { 456 | "internalType": "address", 457 | "name": "operator_", 458 | "type": "address" 459 | } 460 | ], 461 | "name": "setOperator", 462 | "outputs": [], 463 | "stateMutability": "nonpayable", 464 | "type": "function" 465 | }, 466 | { 467 | "inputs": [ 468 | { 469 | "internalType": "address", 470 | "name": "pendingAdmin_", 471 | "type": "address" 472 | } 473 | ], 474 | "name": "setPendingAdmin", 475 | "outputs": [], 476 | "stateMutability": "nonpayable", 477 | "type": "function" 478 | }, 479 | { 480 | "stateMutability": "payable", 481 | "type": "receive" 482 | } 483 | ] -------------------------------------------------------------------------------- /abi/ValueLiquidityToken.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "contract IERC20", 6 | "name": "_yfv", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "uint256", 11 | "name": "_cap", 12 | "type": "uint256" 13 | } 14 | ], 15 | "stateMutability": "nonpayable", 16 | "type": "constructor" 17 | }, 18 | { 19 | "anonymous": false, 20 | "inputs": [ 21 | { 22 | "indexed": true, 23 | "internalType": "address", 24 | "name": "owner", 25 | "type": "address" 26 | }, 27 | { 28 | "indexed": true, 29 | "internalType": "address", 30 | "name": "spender", 31 | "type": "address" 32 | }, 33 | { 34 | "indexed": false, 35 | "internalType": "uint256", 36 | "name": "value", 37 | "type": "uint256" 38 | } 39 | ], 40 | "name": "Approval", 41 | "type": "event" 42 | }, 43 | { 44 | "anonymous": false, 45 | "inputs": [ 46 | { 47 | "indexed": true, 48 | "internalType": "address", 49 | "name": "delegator", 50 | "type": "address" 51 | }, 52 | { 53 | "indexed": true, 54 | "internalType": "address", 55 | "name": "fromDelegate", 56 | "type": "address" 57 | }, 58 | { 59 | "indexed": true, 60 | "internalType": "address", 61 | "name": "toDelegate", 62 | "type": "address" 63 | } 64 | ], 65 | "name": "DelegateChanged", 66 | "type": "event" 67 | }, 68 | { 69 | "anonymous": false, 70 | "inputs": [ 71 | { 72 | "indexed": true, 73 | "internalType": "address", 74 | "name": "delegate", 75 | "type": "address" 76 | }, 77 | { 78 | "indexed": false, 79 | "internalType": "uint256", 80 | "name": "previousBalance", 81 | "type": "uint256" 82 | }, 83 | { 84 | "indexed": false, 85 | "internalType": "uint256", 86 | "name": "newBalance", 87 | "type": "uint256" 88 | } 89 | ], 90 | "name": "DelegateVotesChanged", 91 | "type": "event" 92 | }, 93 | { 94 | "anonymous": false, 95 | "inputs": [ 96 | { 97 | "indexed": true, 98 | "internalType": "address", 99 | "name": "dst", 100 | "type": "address" 101 | }, 102 | { 103 | "indexed": false, 104 | "internalType": "uint256", 105 | "name": "amount", 106 | "type": "uint256" 107 | } 108 | ], 109 | "name": "Deposit", 110 | "type": "event" 111 | }, 112 | { 113 | "anonymous": false, 114 | "inputs": [ 115 | { 116 | "indexed": true, 117 | "internalType": "address", 118 | "name": "from", 119 | "type": "address" 120 | }, 121 | { 122 | "indexed": true, 123 | "internalType": "address", 124 | "name": "to", 125 | "type": "address" 126 | }, 127 | { 128 | "indexed": false, 129 | "internalType": "uint256", 130 | "name": "value", 131 | "type": "uint256" 132 | } 133 | ], 134 | "name": "Transfer", 135 | "type": "event" 136 | }, 137 | { 138 | "anonymous": false, 139 | "inputs": [ 140 | { 141 | "indexed": true, 142 | "internalType": "address", 143 | "name": "src", 144 | "type": "address" 145 | }, 146 | { 147 | "indexed": false, 148 | "internalType": "uint256", 149 | "name": "amount", 150 | "type": "uint256" 151 | } 152 | ], 153 | "name": "Withdrawal", 154 | "type": "event" 155 | }, 156 | { 157 | "inputs": [], 158 | "name": "DELEGATION_TYPEHASH", 159 | "outputs": [ 160 | { 161 | "internalType": "bytes32", 162 | "name": "", 163 | "type": "bytes32" 164 | } 165 | ], 166 | "stateMutability": "view", 167 | "type": "function" 168 | }, 169 | { 170 | "inputs": [], 171 | "name": "DOMAIN_TYPEHASH", 172 | "outputs": [ 173 | { 174 | "internalType": "bytes32", 175 | "name": "", 176 | "type": "bytes32" 177 | } 178 | ], 179 | "stateMutability": "view", 180 | "type": "function" 181 | }, 182 | { 183 | "inputs": [ 184 | { 185 | "internalType": "address", 186 | "name": "_minter", 187 | "type": "address" 188 | } 189 | ], 190 | "name": "addMinter", 191 | "outputs": [], 192 | "stateMutability": "nonpayable", 193 | "type": "function" 194 | }, 195 | { 196 | "inputs": [ 197 | { 198 | "internalType": "address", 199 | "name": "owner", 200 | "type": "address" 201 | }, 202 | { 203 | "internalType": "address", 204 | "name": "spender", 205 | "type": "address" 206 | } 207 | ], 208 | "name": "allowance", 209 | "outputs": [ 210 | { 211 | "internalType": "uint256", 212 | "name": "", 213 | "type": "uint256" 214 | } 215 | ], 216 | "stateMutability": "view", 217 | "type": "function" 218 | }, 219 | { 220 | "inputs": [ 221 | { 222 | "internalType": "address", 223 | "name": "spender", 224 | "type": "address" 225 | }, 226 | { 227 | "internalType": "uint256", 228 | "name": "amount", 229 | "type": "uint256" 230 | } 231 | ], 232 | "name": "approve", 233 | "outputs": [ 234 | { 235 | "internalType": "bool", 236 | "name": "", 237 | "type": "bool" 238 | } 239 | ], 240 | "stateMutability": "nonpayable", 241 | "type": "function" 242 | }, 243 | { 244 | "inputs": [ 245 | { 246 | "internalType": "address", 247 | "name": "account", 248 | "type": "address" 249 | } 250 | ], 251 | "name": "balanceOf", 252 | "outputs": [ 253 | { 254 | "internalType": "uint256", 255 | "name": "", 256 | "type": "uint256" 257 | } 258 | ], 259 | "stateMutability": "view", 260 | "type": "function" 261 | }, 262 | { 263 | "inputs": [ 264 | { 265 | "internalType": "uint256", 266 | "name": "_amount", 267 | "type": "uint256" 268 | } 269 | ], 270 | "name": "burn", 271 | "outputs": [], 272 | "stateMutability": "nonpayable", 273 | "type": "function" 274 | }, 275 | { 276 | "inputs": [ 277 | { 278 | "internalType": "address", 279 | "name": "_account", 280 | "type": "address" 281 | }, 282 | { 283 | "internalType": "uint256", 284 | "name": "_amount", 285 | "type": "uint256" 286 | } 287 | ], 288 | "name": "burnFrom", 289 | "outputs": [], 290 | "stateMutability": "nonpayable", 291 | "type": "function" 292 | }, 293 | { 294 | "inputs": [], 295 | "name": "cap", 296 | "outputs": [ 297 | { 298 | "internalType": "uint256", 299 | "name": "", 300 | "type": "uint256" 301 | } 302 | ], 303 | "stateMutability": "view", 304 | "type": "function" 305 | }, 306 | { 307 | "inputs": [ 308 | { 309 | "internalType": "address", 310 | "name": "", 311 | "type": "address" 312 | }, 313 | { 314 | "internalType": "uint32", 315 | "name": "", 316 | "type": "uint32" 317 | } 318 | ], 319 | "name": "checkpoints", 320 | "outputs": [ 321 | { 322 | "internalType": "uint32", 323 | "name": "fromBlock", 324 | "type": "uint32" 325 | }, 326 | { 327 | "internalType": "uint256", 328 | "name": "votes", 329 | "type": "uint256" 330 | } 331 | ], 332 | "stateMutability": "view", 333 | "type": "function" 334 | }, 335 | { 336 | "inputs": [], 337 | "name": "decimals", 338 | "outputs": [ 339 | { 340 | "internalType": "uint8", 341 | "name": "", 342 | "type": "uint8" 343 | } 344 | ], 345 | "stateMutability": "view", 346 | "type": "function" 347 | }, 348 | { 349 | "inputs": [ 350 | { 351 | "internalType": "address", 352 | "name": "spender", 353 | "type": "address" 354 | }, 355 | { 356 | "internalType": "uint256", 357 | "name": "subtractedValue", 358 | "type": "uint256" 359 | } 360 | ], 361 | "name": "decreaseAllowance", 362 | "outputs": [ 363 | { 364 | "internalType": "bool", 365 | "name": "", 366 | "type": "bool" 367 | } 368 | ], 369 | "stateMutability": "nonpayable", 370 | "type": "function" 371 | }, 372 | { 373 | "inputs": [ 374 | { 375 | "internalType": "address", 376 | "name": "delegatee", 377 | "type": "address" 378 | } 379 | ], 380 | "name": "delegate", 381 | "outputs": [], 382 | "stateMutability": "nonpayable", 383 | "type": "function" 384 | }, 385 | { 386 | "inputs": [ 387 | { 388 | "internalType": "address", 389 | "name": "delegatee", 390 | "type": "address" 391 | }, 392 | { 393 | "internalType": "uint256", 394 | "name": "nonce", 395 | "type": "uint256" 396 | }, 397 | { 398 | "internalType": "uint256", 399 | "name": "expiry", 400 | "type": "uint256" 401 | }, 402 | { 403 | "internalType": "uint8", 404 | "name": "v", 405 | "type": "uint8" 406 | }, 407 | { 408 | "internalType": "bytes32", 409 | "name": "r", 410 | "type": "bytes32" 411 | }, 412 | { 413 | "internalType": "bytes32", 414 | "name": "s", 415 | "type": "bytes32" 416 | } 417 | ], 418 | "name": "delegateBySig", 419 | "outputs": [], 420 | "stateMutability": "nonpayable", 421 | "type": "function" 422 | }, 423 | { 424 | "inputs": [ 425 | { 426 | "internalType": "address", 427 | "name": "delegator", 428 | "type": "address" 429 | } 430 | ], 431 | "name": "delegates", 432 | "outputs": [ 433 | { 434 | "internalType": "address", 435 | "name": "", 436 | "type": "address" 437 | } 438 | ], 439 | "stateMutability": "view", 440 | "type": "function" 441 | }, 442 | { 443 | "inputs": [ 444 | { 445 | "internalType": "uint256", 446 | "name": "_amount", 447 | "type": "uint256" 448 | } 449 | ], 450 | "name": "deposit", 451 | "outputs": [], 452 | "stateMutability": "nonpayable", 453 | "type": "function" 454 | }, 455 | { 456 | "inputs": [ 457 | { 458 | "internalType": "address", 459 | "name": "account", 460 | "type": "address" 461 | } 462 | ], 463 | "name": "getCurrentVotes", 464 | "outputs": [ 465 | { 466 | "internalType": "uint256", 467 | "name": "", 468 | "type": "uint256" 469 | } 470 | ], 471 | "stateMutability": "view", 472 | "type": "function" 473 | }, 474 | { 475 | "inputs": [ 476 | { 477 | "internalType": "address", 478 | "name": "account", 479 | "type": "address" 480 | }, 481 | { 482 | "internalType": "uint256", 483 | "name": "blockNumber", 484 | "type": "uint256" 485 | } 486 | ], 487 | "name": "getPriorVotes", 488 | "outputs": [ 489 | { 490 | "internalType": "uint256", 491 | "name": "", 492 | "type": "uint256" 493 | } 494 | ], 495 | "stateMutability": "view", 496 | "type": "function" 497 | }, 498 | { 499 | "inputs": [], 500 | "name": "governance", 501 | "outputs": [ 502 | { 503 | "internalType": "address", 504 | "name": "", 505 | "type": "address" 506 | } 507 | ], 508 | "stateMutability": "view", 509 | "type": "function" 510 | }, 511 | { 512 | "inputs": [ 513 | { 514 | "internalType": "contract IERC20", 515 | "name": "_token", 516 | "type": "address" 517 | }, 518 | { 519 | "internalType": "address", 520 | "name": "_to", 521 | "type": "address" 522 | }, 523 | { 524 | "internalType": "uint256", 525 | "name": "_amount", 526 | "type": "uint256" 527 | } 528 | ], 529 | "name": "governanceRecoverUnsupported", 530 | "outputs": [], 531 | "stateMutability": "nonpayable", 532 | "type": "function" 533 | }, 534 | { 535 | "inputs": [ 536 | { 537 | "internalType": "address", 538 | "name": "spender", 539 | "type": "address" 540 | }, 541 | { 542 | "internalType": "uint256", 543 | "name": "addedValue", 544 | "type": "uint256" 545 | } 546 | ], 547 | "name": "increaseAllowance", 548 | "outputs": [ 549 | { 550 | "internalType": "bool", 551 | "name": "", 552 | "type": "bool" 553 | } 554 | ], 555 | "stateMutability": "nonpayable", 556 | "type": "function" 557 | }, 558 | { 559 | "inputs": [ 560 | { 561 | "internalType": "address", 562 | "name": "_to", 563 | "type": "address" 564 | }, 565 | { 566 | "internalType": "uint256", 567 | "name": "_amount", 568 | "type": "uint256" 569 | } 570 | ], 571 | "name": "mint", 572 | "outputs": [], 573 | "stateMutability": "nonpayable", 574 | "type": "function" 575 | }, 576 | { 577 | "inputs": [ 578 | { 579 | "internalType": "address", 580 | "name": "", 581 | "type": "address" 582 | } 583 | ], 584 | "name": "minters", 585 | "outputs": [ 586 | { 587 | "internalType": "bool", 588 | "name": "", 589 | "type": "bool" 590 | } 591 | ], 592 | "stateMutability": "view", 593 | "type": "function" 594 | }, 595 | { 596 | "inputs": [], 597 | "name": "name", 598 | "outputs": [ 599 | { 600 | "internalType": "string", 601 | "name": "", 602 | "type": "string" 603 | } 604 | ], 605 | "stateMutability": "view", 606 | "type": "function" 607 | }, 608 | { 609 | "inputs": [ 610 | { 611 | "internalType": "address", 612 | "name": "", 613 | "type": "address" 614 | } 615 | ], 616 | "name": "nonces", 617 | "outputs": [ 618 | { 619 | "internalType": "uint256", 620 | "name": "", 621 | "type": "uint256" 622 | } 623 | ], 624 | "stateMutability": "view", 625 | "type": "function" 626 | }, 627 | { 628 | "inputs": [ 629 | { 630 | "internalType": "address", 631 | "name": "", 632 | "type": "address" 633 | } 634 | ], 635 | "name": "numCheckpoints", 636 | "outputs": [ 637 | { 638 | "internalType": "uint32", 639 | "name": "", 640 | "type": "uint32" 641 | } 642 | ], 643 | "stateMutability": "view", 644 | "type": "function" 645 | }, 646 | { 647 | "inputs": [ 648 | { 649 | "internalType": "address", 650 | "name": "_minter", 651 | "type": "address" 652 | } 653 | ], 654 | "name": "removeMinter", 655 | "outputs": [], 656 | "stateMutability": "nonpayable", 657 | "type": "function" 658 | }, 659 | { 660 | "inputs": [ 661 | { 662 | "internalType": "uint256", 663 | "name": "_cap", 664 | "type": "uint256" 665 | } 666 | ], 667 | "name": "setCap", 668 | "outputs": [], 669 | "stateMutability": "nonpayable", 670 | "type": "function" 671 | }, 672 | { 673 | "inputs": [ 674 | { 675 | "internalType": "address", 676 | "name": "_governance", 677 | "type": "address" 678 | } 679 | ], 680 | "name": "setGovernance", 681 | "outputs": [], 682 | "stateMutability": "nonpayable", 683 | "type": "function" 684 | }, 685 | { 686 | "inputs": [], 687 | "name": "symbol", 688 | "outputs": [ 689 | { 690 | "internalType": "string", 691 | "name": "", 692 | "type": "string" 693 | } 694 | ], 695 | "stateMutability": "view", 696 | "type": "function" 697 | }, 698 | { 699 | "inputs": [], 700 | "name": "totalSupply", 701 | "outputs": [ 702 | { 703 | "internalType": "uint256", 704 | "name": "", 705 | "type": "uint256" 706 | } 707 | ], 708 | "stateMutability": "view", 709 | "type": "function" 710 | }, 711 | { 712 | "inputs": [ 713 | { 714 | "internalType": "address", 715 | "name": "recipient", 716 | "type": "address" 717 | }, 718 | { 719 | "internalType": "uint256", 720 | "name": "amount", 721 | "type": "uint256" 722 | } 723 | ], 724 | "name": "transfer", 725 | "outputs": [ 726 | { 727 | "internalType": "bool", 728 | "name": "", 729 | "type": "bool" 730 | } 731 | ], 732 | "stateMutability": "nonpayable", 733 | "type": "function" 734 | }, 735 | { 736 | "inputs": [ 737 | { 738 | "internalType": "address", 739 | "name": "sender", 740 | "type": "address" 741 | }, 742 | { 743 | "internalType": "address", 744 | "name": "recipient", 745 | "type": "address" 746 | }, 747 | { 748 | "internalType": "uint256", 749 | "name": "amount", 750 | "type": "uint256" 751 | } 752 | ], 753 | "name": "transferFrom", 754 | "outputs": [ 755 | { 756 | "internalType": "bool", 757 | "name": "", 758 | "type": "bool" 759 | } 760 | ], 761 | "stateMutability": "nonpayable", 762 | "type": "function" 763 | }, 764 | { 765 | "inputs": [ 766 | { 767 | "internalType": "uint256", 768 | "name": "_amount", 769 | "type": "uint256" 770 | } 771 | ], 772 | "name": "withdraw", 773 | "outputs": [], 774 | "stateMutability": "nonpayable", 775 | "type": "function" 776 | }, 777 | { 778 | "inputs": [], 779 | "name": "yfv", 780 | "outputs": [ 781 | { 782 | "internalType": "contract IERC20", 783 | "name": "", 784 | "type": "address" 785 | } 786 | ], 787 | "stateMutability": "view", 788 | "type": "function" 789 | }, 790 | { 791 | "inputs": [], 792 | "name": "yfvLockedBalance", 793 | "outputs": [ 794 | { 795 | "internalType": "uint256", 796 | "name": "", 797 | "type": "uint256" 798 | } 799 | ], 800 | "stateMutability": "view", 801 | "type": "function" 802 | } 803 | ] -------------------------------------------------------------------------------- /abi/ValueMasterPool.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "anonymous": false, 4 | "inputs": [ 5 | { 6 | "indexed": true, 7 | "internalType": "address", 8 | "name": "user", 9 | "type": "address" 10 | }, 11 | { 12 | "indexed": true, 13 | "internalType": "uint256", 14 | "name": "pid", 15 | "type": "uint256" 16 | }, 17 | { 18 | "indexed": false, 19 | "internalType": "uint256", 20 | "name": "amount", 21 | "type": "uint256" 22 | } 23 | ], 24 | "name": "Deposit", 25 | "type": "event" 26 | }, 27 | { 28 | "anonymous": false, 29 | "inputs": [ 30 | { 31 | "indexed": true, 32 | "internalType": "address", 33 | "name": "user", 34 | "type": "address" 35 | }, 36 | { 37 | "indexed": true, 38 | "internalType": "uint256", 39 | "name": "pid", 40 | "type": "uint256" 41 | }, 42 | { 43 | "indexed": false, 44 | "internalType": "uint256", 45 | "name": "amount", 46 | "type": "uint256" 47 | } 48 | ], 49 | "name": "EmergencyWithdraw", 50 | "type": "event" 51 | }, 52 | { 53 | "anonymous": false, 54 | "inputs": [ 55 | { 56 | "indexed": true, 57 | "internalType": "address", 58 | "name": "previousOwner", 59 | "type": "address" 60 | }, 61 | { 62 | "indexed": true, 63 | "internalType": "address", 64 | "name": "newOwner", 65 | "type": "address" 66 | } 67 | ], 68 | "name": "OwnershipTransferred", 69 | "type": "event" 70 | }, 71 | { 72 | "anonymous": false, 73 | "inputs": [ 74 | { 75 | "indexed": true, 76 | "internalType": "address", 77 | "name": "user", 78 | "type": "address" 79 | }, 80 | { 81 | "indexed": true, 82 | "internalType": "uint256", 83 | "name": "pid", 84 | "type": "uint256" 85 | }, 86 | { 87 | "indexed": false, 88 | "internalType": "uint256", 89 | "name": "amount", 90 | "type": "uint256" 91 | } 92 | ], 93 | "name": "Withdraw", 94 | "type": "event" 95 | }, 96 | { 97 | "inputs": [ 98 | { 99 | "internalType": "uint256", 100 | "name": "_allocPoint", 101 | "type": "uint256" 102 | }, 103 | { 104 | "internalType": "contract IERC20", 105 | "name": "_lpToken", 106 | "type": "address" 107 | }, 108 | { 109 | "internalType": "bool", 110 | "name": "_withUpdate", 111 | "type": "bool" 112 | }, 113 | { 114 | "internalType": "uint256", 115 | "name": "_lastRewardBlock", 116 | "type": "uint256" 117 | } 118 | ], 119 | "name": "add", 120 | "outputs": [], 121 | "stateMutability": "nonpayable", 122 | "type": "function" 123 | }, 124 | { 125 | "inputs": [ 126 | { 127 | "internalType": "uint256", 128 | "name": "_pid", 129 | "type": "uint256" 130 | }, 131 | { 132 | "internalType": "uint256", 133 | "name": "_amount", 134 | "type": "uint256" 135 | }, 136 | { 137 | "internalType": "address", 138 | "name": "_referrer", 139 | "type": "address" 140 | } 141 | ], 142 | "name": "deposit", 143 | "outputs": [], 144 | "stateMutability": "nonpayable", 145 | "type": "function" 146 | }, 147 | { 148 | "inputs": [ 149 | { 150 | "internalType": "uint256", 151 | "name": "_pid", 152 | "type": "uint256" 153 | } 154 | ], 155 | "name": "emergencyWithdraw", 156 | "outputs": [], 157 | "stateMutability": "nonpayable", 158 | "type": "function" 159 | }, 160 | { 161 | "inputs": [ 162 | { 163 | "internalType": "contract IERC20", 164 | "name": "_token", 165 | "type": "address" 166 | }, 167 | { 168 | "internalType": "uint256", 169 | "name": "amount", 170 | "type": "uint256" 171 | }, 172 | { 173 | "internalType": "address", 174 | "name": "to", 175 | "type": "address" 176 | } 177 | ], 178 | "name": "governanceRecoverUnsupported", 179 | "outputs": [], 180 | "stateMutability": "nonpayable", 181 | "type": "function" 182 | }, 183 | { 184 | "inputs": [], 185 | "name": "massUpdatePools", 186 | "outputs": [], 187 | "stateMutability": "nonpayable", 188 | "type": "function" 189 | }, 190 | { 191 | "inputs": [ 192 | { 193 | "internalType": "uint256", 194 | "name": "_pid", 195 | "type": "uint256" 196 | } 197 | ], 198 | "name": "migrate", 199 | "outputs": [], 200 | "stateMutability": "nonpayable", 201 | "type": "function" 202 | }, 203 | { 204 | "inputs": [], 205 | "name": "renounceOwnership", 206 | "outputs": [], 207 | "stateMutability": "nonpayable", 208 | "type": "function" 209 | }, 210 | { 211 | "inputs": [ 212 | { 213 | "internalType": "uint256", 214 | "name": "_pid", 215 | "type": "uint256" 216 | }, 217 | { 218 | "internalType": "uint256", 219 | "name": "_allocPoint", 220 | "type": "uint256" 221 | }, 222 | { 223 | "internalType": "bool", 224 | "name": "_withUpdate", 225 | "type": "bool" 226 | } 227 | ], 228 | "name": "set", 229 | "outputs": [], 230 | "stateMutability": "nonpayable", 231 | "type": "function" 232 | }, 233 | { 234 | "inputs": [ 235 | { 236 | "internalType": "uint8", 237 | "name": "_index", 238 | "type": "uint8" 239 | }, 240 | { 241 | "internalType": "uint256", 242 | "name": "_epochEndBlock", 243 | "type": "uint256" 244 | } 245 | ], 246 | "name": "setEpochEndBlock", 247 | "outputs": [], 248 | "stateMutability": "nonpayable", 249 | "type": "function" 250 | }, 251 | { 252 | "inputs": [ 253 | { 254 | "internalType": "uint8", 255 | "name": "_index", 256 | "type": "uint8" 257 | }, 258 | { 259 | "internalType": "uint256", 260 | "name": "_epochRewardMultipler", 261 | "type": "uint256" 262 | } 263 | ], 264 | "name": "setEpochRewardMultipler", 265 | "outputs": [], 266 | "stateMutability": "nonpayable", 267 | "type": "function" 268 | }, 269 | { 270 | "inputs": [ 271 | { 272 | "internalType": "address", 273 | "name": "_insuranceFundAddr", 274 | "type": "address" 275 | } 276 | ], 277 | "name": "setInsuranceFundAddr", 278 | "outputs": [], 279 | "stateMutability": "nonpayable", 280 | "type": "function" 281 | }, 282 | { 283 | "inputs": [ 284 | { 285 | "internalType": "contract ILiquidityMigrator", 286 | "name": "_migrator", 287 | "type": "address" 288 | } 289 | ], 290 | "name": "setMigrator", 291 | "outputs": [], 292 | "stateMutability": "nonpayable", 293 | "type": "function" 294 | }, 295 | { 296 | "inputs": [ 297 | { 298 | "internalType": "address", 299 | "name": "_rewardReferral", 300 | "type": "address" 301 | } 302 | ], 303 | "name": "setRewardReferral", 304 | "outputs": [], 305 | "stateMutability": "nonpayable", 306 | "type": "function" 307 | }, 308 | { 309 | "inputs": [ 310 | { 311 | "internalType": "uint256", 312 | "name": "_valuePerBlock", 313 | "type": "uint256" 314 | } 315 | ], 316 | "name": "setValuePerBlock", 317 | "outputs": [], 318 | "stateMutability": "nonpayable", 319 | "type": "function" 320 | }, 321 | { 322 | "inputs": [ 323 | { 324 | "internalType": "address", 325 | "name": "newOwner", 326 | "type": "address" 327 | } 328 | ], 329 | "name": "transferOwnership", 330 | "outputs": [], 331 | "stateMutability": "nonpayable", 332 | "type": "function" 333 | }, 334 | { 335 | "inputs": [ 336 | { 337 | "internalType": "uint256", 338 | "name": "_pid", 339 | "type": "uint256" 340 | } 341 | ], 342 | "name": "updatePool", 343 | "outputs": [], 344 | "stateMutability": "nonpayable", 345 | "type": "function" 346 | }, 347 | { 348 | "inputs": [ 349 | { 350 | "internalType": "uint256", 351 | "name": "_pid", 352 | "type": "uint256" 353 | }, 354 | { 355 | "internalType": "uint256", 356 | "name": "_amount", 357 | "type": "uint256" 358 | } 359 | ], 360 | "name": "withdraw", 361 | "outputs": [], 362 | "stateMutability": "nonpayable", 363 | "type": "function" 364 | }, 365 | { 366 | "inputs": [ 367 | { 368 | "internalType": "contract ValueLiquidityToken", 369 | "name": "_value", 370 | "type": "address" 371 | }, 372 | { 373 | "internalType": "address", 374 | "name": "_insuranceFundAddr", 375 | "type": "address" 376 | }, 377 | { 378 | "internalType": "uint256", 379 | "name": "_valuePerBlock", 380 | "type": "uint256" 381 | }, 382 | { 383 | "internalType": "uint256", 384 | "name": "_startBlock", 385 | "type": "uint256" 386 | } 387 | ], 388 | "stateMutability": "nonpayable", 389 | "type": "constructor" 390 | }, 391 | { 392 | "inputs": [], 393 | "name": "chi", 394 | "outputs": [ 395 | { 396 | "internalType": "contract IFreeFromUpTo", 397 | "name": "", 398 | "type": "address" 399 | } 400 | ], 401 | "stateMutability": "view", 402 | "type": "function" 403 | }, 404 | { 405 | "inputs": [ 406 | { 407 | "internalType": "uint256", 408 | "name": "", 409 | "type": "uint256" 410 | } 411 | ], 412 | "name": "epochEndBlocks", 413 | "outputs": [ 414 | { 415 | "internalType": "uint256", 416 | "name": "", 417 | "type": "uint256" 418 | } 419 | ], 420 | "stateMutability": "view", 421 | "type": "function" 422 | }, 423 | { 424 | "inputs": [ 425 | { 426 | "internalType": "uint256", 427 | "name": "", 428 | "type": "uint256" 429 | } 430 | ], 431 | "name": "epochRewardMultiplers", 432 | "outputs": [ 433 | { 434 | "internalType": "uint256", 435 | "name": "", 436 | "type": "uint256" 437 | } 438 | ], 439 | "stateMutability": "view", 440 | "type": "function" 441 | }, 442 | { 443 | "inputs": [ 444 | { 445 | "internalType": "uint256", 446 | "name": "_from", 447 | "type": "uint256" 448 | }, 449 | { 450 | "internalType": "uint256", 451 | "name": "_to", 452 | "type": "uint256" 453 | } 454 | ], 455 | "name": "getMultiplier", 456 | "outputs": [ 457 | { 458 | "internalType": "uint256", 459 | "name": "", 460 | "type": "uint256" 461 | } 462 | ], 463 | "stateMutability": "view", 464 | "type": "function" 465 | }, 466 | { 467 | "inputs": [], 468 | "name": "insuranceFundAddr", 469 | "outputs": [ 470 | { 471 | "internalType": "address", 472 | "name": "", 473 | "type": "address" 474 | } 475 | ], 476 | "stateMutability": "view", 477 | "type": "function" 478 | }, 479 | { 480 | "inputs": [], 481 | "name": "migrator", 482 | "outputs": [ 483 | { 484 | "internalType": "contract ILiquidityMigrator", 485 | "name": "", 486 | "type": "address" 487 | } 488 | ], 489 | "stateMutability": "view", 490 | "type": "function" 491 | }, 492 | { 493 | "inputs": [], 494 | "name": "owner", 495 | "outputs": [ 496 | { 497 | "internalType": "address", 498 | "name": "", 499 | "type": "address" 500 | } 501 | ], 502 | "stateMutability": "view", 503 | "type": "function" 504 | }, 505 | { 506 | "inputs": [ 507 | { 508 | "internalType": "uint256", 509 | "name": "_pid", 510 | "type": "uint256" 511 | }, 512 | { 513 | "internalType": "address", 514 | "name": "_user", 515 | "type": "address" 516 | } 517 | ], 518 | "name": "pendingValue", 519 | "outputs": [ 520 | { 521 | "internalType": "uint256", 522 | "name": "", 523 | "type": "uint256" 524 | } 525 | ], 526 | "stateMutability": "view", 527 | "type": "function" 528 | }, 529 | { 530 | "inputs": [ 531 | { 532 | "internalType": "uint256", 533 | "name": "", 534 | "type": "uint256" 535 | } 536 | ], 537 | "name": "poolInfo", 538 | "outputs": [ 539 | { 540 | "internalType": "contract IERC20", 541 | "name": "lpToken", 542 | "type": "address" 543 | }, 544 | { 545 | "internalType": "uint256", 546 | "name": "allocPoint", 547 | "type": "uint256" 548 | }, 549 | { 550 | "internalType": "uint256", 551 | "name": "lastRewardBlock", 552 | "type": "uint256" 553 | }, 554 | { 555 | "internalType": "uint256", 556 | "name": "accValuePerShare", 557 | "type": "uint256" 558 | }, 559 | { 560 | "internalType": "bool", 561 | "name": "isStarted", 562 | "type": "bool" 563 | } 564 | ], 565 | "stateMutability": "view", 566 | "type": "function" 567 | }, 568 | { 569 | "inputs": [], 570 | "name": "poolLength", 571 | "outputs": [ 572 | { 573 | "internalType": "uint256", 574 | "name": "", 575 | "type": "uint256" 576 | } 577 | ], 578 | "stateMutability": "view", 579 | "type": "function" 580 | }, 581 | { 582 | "inputs": [], 583 | "name": "REFERRAL_COMMISSION_PERCENT", 584 | "outputs": [ 585 | { 586 | "internalType": "uint256", 587 | "name": "", 588 | "type": "uint256" 589 | } 590 | ], 591 | "stateMutability": "view", 592 | "type": "function" 593 | }, 594 | { 595 | "inputs": [], 596 | "name": "rewardReferral", 597 | "outputs": [ 598 | { 599 | "internalType": "address", 600 | "name": "", 601 | "type": "address" 602 | } 603 | ], 604 | "stateMutability": "view", 605 | "type": "function" 606 | }, 607 | { 608 | "inputs": [ 609 | { 610 | "internalType": "uint256", 611 | "name": "_pid", 612 | "type": "uint256" 613 | }, 614 | { 615 | "internalType": "address", 616 | "name": "_user", 617 | "type": "address" 618 | } 619 | ], 620 | "name": "stakingPower", 621 | "outputs": [ 622 | { 623 | "internalType": "uint256", 624 | "name": "", 625 | "type": "uint256" 626 | } 627 | ], 628 | "stateMutability": "view", 629 | "type": "function" 630 | }, 631 | { 632 | "inputs": [], 633 | "name": "startBlock", 634 | "outputs": [ 635 | { 636 | "internalType": "uint256", 637 | "name": "", 638 | "type": "uint256" 639 | } 640 | ], 641 | "stateMutability": "view", 642 | "type": "function" 643 | }, 644 | { 645 | "inputs": [], 646 | "name": "totalAllocPoint", 647 | "outputs": [ 648 | { 649 | "internalType": "uint256", 650 | "name": "", 651 | "type": "uint256" 652 | } 653 | ], 654 | "stateMutability": "view", 655 | "type": "function" 656 | }, 657 | { 658 | "inputs": [ 659 | { 660 | "internalType": "uint256", 661 | "name": "", 662 | "type": "uint256" 663 | }, 664 | { 665 | "internalType": "address", 666 | "name": "", 667 | "type": "address" 668 | } 669 | ], 670 | "name": "userInfo", 671 | "outputs": [ 672 | { 673 | "internalType": "uint256", 674 | "name": "amount", 675 | "type": "uint256" 676 | }, 677 | { 678 | "internalType": "uint256", 679 | "name": "rewardDebt", 680 | "type": "uint256" 681 | }, 682 | { 683 | "internalType": "uint256", 684 | "name": "accumulatedStakingPower", 685 | "type": "uint256" 686 | } 687 | ], 688 | "stateMutability": "view", 689 | "type": "function" 690 | }, 691 | { 692 | "inputs": [], 693 | "name": "value", 694 | "outputs": [ 695 | { 696 | "internalType": "contract ValueLiquidityToken", 697 | "name": "", 698 | "type": "address" 699 | } 700 | ], 701 | "stateMutability": "view", 702 | "type": "function" 703 | }, 704 | { 705 | "inputs": [], 706 | "name": "valuePerBlock", 707 | "outputs": [ 708 | { 709 | "internalType": "uint256", 710 | "name": "", 711 | "type": "uint256" 712 | } 713 | ], 714 | "stateMutability": "view", 715 | "type": "function" 716 | } 717 | ] -------------------------------------------------------------------------------- /contracts/VALUE/Timelock.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.12; 2 | 3 | import "@openzeppelin/contracts/math/SafeMath.sol"; 4 | 5 | contract Timelock { 6 | using SafeMath for uint; 7 | 8 | event NewAdmin(address indexed newAdmin); 9 | event NewPendingAdmin(address indexed newPendingAdmin); 10 | event NewOperator(address indexed newOperator); 11 | event NewDelay(uint indexed newDelay); 12 | event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); 13 | event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); 14 | event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); 15 | 16 | uint public constant GRACE_PERIOD = 14 days; 17 | uint public constant MINIMUM_DELAY = 24 hours; 18 | uint public constant MAXIMUM_DELAY = 30 days; 19 | 20 | address public admin; // should be a multi-sig or DAO 21 | address public pendingAdmin; 22 | address public operator; // add this role (could be EOA) to initiate (queue) a new tx 23 | uint public delay; 24 | bool public admin_initialized; 25 | 26 | mapping (bytes32 => bool) public queuedTransactions; 27 | 28 | constructor(address admin_, uint delay_) public { 29 | require(delay_ >= MINIMUM_DELAY, "Timelock::constructor: Delay must exceed minimum delay."); 30 | require(delay_ <= MAXIMUM_DELAY, "Timelock::constructor: Delay must not exceed maximum delay."); 31 | 32 | admin = admin_; 33 | operator = admin_; 34 | delay = delay_; 35 | admin_initialized = false; 36 | } 37 | 38 | receive() external payable { } 39 | 40 | function setDelay(uint delay_) public { 41 | require(msg.sender == address(this), "Timelock::setDelay: Call must come from Timelock."); 42 | require(delay_ >= MINIMUM_DELAY, "Timelock::setDelay: Delay must exceed minimum delay."); 43 | require(delay_ <= MAXIMUM_DELAY, "Timelock::setDelay: Delay must not exceed maximum delay."); 44 | delay = delay_; 45 | 46 | emit NewDelay(delay); 47 | } 48 | 49 | function setOperator(address operator_) public { 50 | require(msg.sender == address(this), "Timelock::setDelay: Call must come from Timelock."); 51 | operator = operator_; 52 | 53 | emit NewOperator(operator); 54 | } 55 | 56 | function acceptAdmin() public { 57 | require(msg.sender == pendingAdmin, "Timelock::acceptAdmin: Call must come from pendingAdmin."); 58 | admin = msg.sender; 59 | pendingAdmin = address(0); 60 | 61 | emit NewAdmin(admin); 62 | } 63 | 64 | function setPendingAdmin(address pendingAdmin_) public { 65 | // allows one time setting of admin for deployment purposes 66 | if (admin_initialized) { 67 | require(msg.sender == address(this), "Timelock::setPendingAdmin: Call must come from Timelock."); 68 | } else { 69 | require(msg.sender == admin, "Timelock::setPendingAdmin: First call must come from admin."); 70 | admin_initialized = true; 71 | } 72 | pendingAdmin = pendingAdmin_; 73 | 74 | emit NewPendingAdmin(pendingAdmin); 75 | } 76 | 77 | function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) { 78 | require(msg.sender == admin || msg.sender == operator, "Timelock::queueTransaction: Call must come from admin or operator."); 79 | require(eta >= getBlockTimestamp().add(delay), "Timelock::queueTransaction: Estimated execution block must satisfy delay."); 80 | 81 | bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); 82 | queuedTransactions[txHash] = true; 83 | 84 | emit QueueTransaction(txHash, target, value, signature, data, eta); 85 | return txHash; 86 | } 87 | 88 | function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public { 89 | require(msg.sender == admin, "Timelock::cancelTransaction: Call must come from admin."); 90 | 91 | bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); 92 | queuedTransactions[txHash] = false; 93 | 94 | emit CancelTransaction(txHash, target, value, signature, data, eta); 95 | } 96 | 97 | function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) { 98 | require(msg.sender == admin, "Timelock::executeTransaction: Call must come from admin."); 99 | 100 | bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); 101 | require(queuedTransactions[txHash], "Timelock::executeTransaction: Transaction hasn't been queued."); 102 | require(getBlockTimestamp() >= eta, "Timelock::executeTransaction: Transaction hasn't surpassed time lock."); 103 | require(getBlockTimestamp() <= eta.add(GRACE_PERIOD), "Timelock::executeTransaction: Transaction is stale."); 104 | 105 | queuedTransactions[txHash] = false; 106 | 107 | bytes memory callData; 108 | 109 | if (bytes(signature).length == 0) { 110 | callData = data; 111 | } else { 112 | callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data); 113 | } 114 | 115 | // solium-disable-next-line security/no-call-value 116 | (bool success, bytes memory returnData) = target.call{value: value}(callData); 117 | require(success, "Timelock::executeTransaction: Transaction execution reverted."); 118 | 119 | emit ExecuteTransaction(txHash, target, value, signature, data, eta); 120 | 121 | return returnData; 122 | } 123 | 124 | function getBlockTimestamp() internal view returns (uint) { 125 | // solium-disable-next-line security/no-block-members 126 | return block.timestamp; 127 | } 128 | } -------------------------------------------------------------------------------- /contracts/VALUE/ValueLiquidityToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 | 8 | // Value Liquidity (VALUE) with Governance Alpha 9 | contract ValueLiquidityToken is ERC20 { 10 | using SafeERC20 for IERC20; 11 | using SafeMath for uint256; 12 | 13 | IERC20 public yfv; 14 | 15 | address public governance; 16 | uint256 public cap; 17 | uint256 public yfvLockedBalance; 18 | mapping(address => bool) public minters; 19 | 20 | event Deposit(address indexed dst, uint amount); 21 | event Withdrawal(address indexed src, uint amount); 22 | 23 | constructor (IERC20 _yfv, uint256 _cap) public ERC20("Value Liquidity", "VALUE") { 24 | governance = msg.sender; 25 | yfv = _yfv; 26 | cap = _cap; 27 | } 28 | 29 | function mint(address _to, uint256 _amount) public { 30 | require(msg.sender == governance || minters[msg.sender], "!governance && !minter"); 31 | _mint(_to, _amount); 32 | _moveDelegates(address(0), _delegates[_to], _amount); 33 | } 34 | 35 | function burn(uint256 _amount) public { 36 | _burn(msg.sender, _amount); 37 | _moveDelegates(_delegates[msg.sender], address(0), _amount); 38 | } 39 | 40 | function burnFrom(address _account, uint256 _amount) public { 41 | uint256 decreasedAllowance = allowance(_account, msg.sender).sub(_amount, "ERC20: burn amount exceeds allowance"); 42 | _approve(_account, msg.sender, decreasedAllowance); 43 | _burn(_account, _amount); 44 | _moveDelegates(_delegates[_account], address(0), _amount); 45 | } 46 | 47 | function setGovernance(address _governance) public { 48 | require(msg.sender == governance, "!governance"); 49 | governance = _governance; 50 | } 51 | 52 | function addMinter(address _minter) public { 53 | require(msg.sender == governance, "!governance"); 54 | minters[_minter] = true; 55 | } 56 | 57 | function removeMinter(address _minter) public { 58 | require(msg.sender == governance, "!governance"); 59 | minters[_minter] = false; 60 | } 61 | 62 | function setCap(uint256 _cap) public { 63 | require(msg.sender == governance, "!governance"); 64 | require(_cap.add(yfvLockedBalance) >= totalSupply(), "_cap (plus yfvLockedBalance) is below current supply"); 65 | cap = _cap; 66 | } 67 | 68 | function deposit(uint256 _amount) public { 69 | yfv.safeTransferFrom(msg.sender, address(this), _amount); 70 | yfvLockedBalance = yfvLockedBalance.add(_amount); 71 | _mint(msg.sender, _amount); 72 | _moveDelegates(address(0), _delegates[msg.sender], _amount); 73 | Deposit(msg.sender, _amount); 74 | } 75 | 76 | function withdraw(uint256 _amount) public { 77 | yfvLockedBalance = yfvLockedBalance.sub(_amount, "There is not enough locked YFV to withdraw"); 78 | yfv.safeTransfer(msg.sender, _amount); 79 | _burn(msg.sender, _amount); 80 | _moveDelegates(_delegates[msg.sender], address(0), _amount); 81 | Withdrawal(msg.sender, _amount); 82 | } 83 | 84 | // This function allows governance to take unsupported tokens out of the contract. 85 | // This is in an effort to make someone whole, should they seriously mess up. 86 | // There is no guarantee governance will vote to return these. 87 | // It also allows for removal of airdropped tokens. 88 | function governanceRecoverUnsupported(IERC20 _token, address _to, uint256 _amount) external { 89 | require(msg.sender == governance, "!governance"); 90 | if (_token == yfv) { 91 | uint256 yfvBalance = yfv.balanceOf(address(this)); 92 | require(_amount <= yfvBalance.sub(yfvLockedBalance), "cant withdraw more then stuck amount"); 93 | } 94 | _token.safeTransfer(_to, _amount); 95 | } 96 | 97 | /** 98 | * @dev See {ERC20-_beforeTokenTransfer}. 99 | * 100 | * Requirements: 101 | * 102 | * - minted tokens must not cause the total supply to go over the cap. 103 | */ 104 | function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual override { 105 | super._beforeTokenTransfer(from, to, amount); 106 | 107 | if (from == address(0)) {// When minting tokens 108 | require(totalSupply().add(amount) <= cap.add(yfvLockedBalance), "ERC20Capped: cap exceeded"); 109 | } 110 | } 111 | 112 | // Copied and modified from YAM code: 113 | // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol 114 | // https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol 115 | // Which is copied and modified from COMPOUND: 116 | // https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol 117 | 118 | /// @dev A record of each accounts delegate 119 | mapping(address => address) internal _delegates; 120 | 121 | /// @notice A checkpoint for marking number of votes from a given block 122 | struct Checkpoint { 123 | uint32 fromBlock; 124 | uint256 votes; 125 | } 126 | 127 | /// @notice A record of votes checkpoints for each account, by index 128 | mapping(address => mapping(uint32 => Checkpoint)) public checkpoints; 129 | 130 | /// @notice The number of checkpoints for each account 131 | mapping(address => uint32) public numCheckpoints; 132 | 133 | /// @notice The EIP-712 typehash for the contract's domain 134 | bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); 135 | 136 | /// @notice The EIP-712 typehash for the delegation struct used by the contract 137 | bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); 138 | 139 | /// @notice A record of states for signing / validating signatures 140 | mapping(address => uint) public nonces; 141 | 142 | /// @notice An event thats emitted when an account changes its delegate 143 | event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); 144 | 145 | /// @notice An event thats emitted when a delegate account's vote balance changes 146 | event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance); 147 | 148 | /** 149 | * @notice Delegate votes from `msg.sender` to `delegatee` 150 | * @param delegator The address to get delegatee for 151 | */ 152 | function delegates(address delegator) 153 | external 154 | view 155 | returns (address) 156 | { 157 | return _delegates[delegator]; 158 | } 159 | 160 | /** 161 | * @notice Delegate votes from `msg.sender` to `delegatee` 162 | * @param delegatee The address to delegate votes to 163 | */ 164 | function delegate(address delegatee) external { 165 | return _delegate(msg.sender, delegatee); 166 | } 167 | 168 | /** 169 | * @notice Delegates votes from signatory to `delegatee` 170 | * @param delegatee The address to delegate votes to 171 | * @param nonce The contract state required to match the signature 172 | * @param expiry The time at which to expire the signature 173 | * @param v The recovery byte of the signature 174 | * @param r Half of the ECDSA signature pair 175 | * @param s Half of the ECDSA signature pair 176 | */ 177 | function delegateBySig( 178 | address delegatee, 179 | uint nonce, 180 | uint expiry, 181 | uint8 v, 182 | bytes32 r, 183 | bytes32 s 184 | ) 185 | external 186 | { 187 | bytes32 domainSeparator = keccak256( 188 | abi.encode( 189 | DOMAIN_TYPEHASH, 190 | keccak256(bytes(name())), 191 | getChainId(), 192 | address(this) 193 | ) 194 | ); 195 | 196 | bytes32 structHash = keccak256( 197 | abi.encode( 198 | DELEGATION_TYPEHASH, 199 | delegatee, 200 | nonce, 201 | expiry 202 | ) 203 | ); 204 | 205 | bytes32 digest = keccak256( 206 | abi.encodePacked( 207 | "\x19\x01", 208 | domainSeparator, 209 | structHash 210 | ) 211 | ); 212 | address signatory = ecrecover(digest, v, r, s); 213 | require(signatory != address(0), "VALUE::delegateBySig: invalid signature"); 214 | require(nonce == nonces[signatory]++, "VALUE::delegateBySig: invalid nonce"); 215 | require(now <= expiry, "VALUE::delegateBySig: signature expired"); 216 | return _delegate(signatory, delegatee); 217 | } 218 | 219 | /** 220 | * @notice Gets the current votes balance for `account` 221 | * @param account The address to get votes balance 222 | * @return The number of current votes for `account` 223 | */ 224 | function getCurrentVotes(address account) 225 | external 226 | view 227 | returns (uint256) 228 | { 229 | uint32 nCheckpoints = numCheckpoints[account]; 230 | return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0; 231 | } 232 | 233 | /** 234 | * @notice Determine the prior number of votes for an account as of a block number 235 | * @dev Block number must be a finalized block or else this function will revert to prevent misinformation. 236 | * @param account The address of the account to check 237 | * @param blockNumber The block number to get the vote balance at 238 | * @return The number of votes the account had as of the given block 239 | */ 240 | function getPriorVotes(address account, uint blockNumber) 241 | external 242 | view 243 | returns (uint256) 244 | { 245 | require(blockNumber < block.number, "VALUE::getPriorVotes: not yet determined"); 246 | 247 | uint32 nCheckpoints = numCheckpoints[account]; 248 | if (nCheckpoints == 0) { 249 | return 0; 250 | } 251 | 252 | // First check most recent balance 253 | if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { 254 | return checkpoints[account][nCheckpoints - 1].votes; 255 | } 256 | 257 | // Next check implicit zero balance 258 | if (checkpoints[account][0].fromBlock > blockNumber) { 259 | return 0; 260 | } 261 | 262 | uint32 lower = 0; 263 | uint32 upper = nCheckpoints - 1; 264 | while (upper > lower) { 265 | uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow 266 | Checkpoint memory cp = checkpoints[account][center]; 267 | if (cp.fromBlock == blockNumber) { 268 | return cp.votes; 269 | } else if (cp.fromBlock < blockNumber) { 270 | lower = center; 271 | } else { 272 | upper = center - 1; 273 | } 274 | } 275 | return checkpoints[account][lower].votes; 276 | } 277 | 278 | function _delegate(address delegator, address delegatee) 279 | internal 280 | { 281 | address currentDelegate = _delegates[delegator]; 282 | uint256 delegatorBalance = balanceOf(delegator); // balance of underlying VALUEs (not scaled); 283 | _delegates[delegator] = delegatee; 284 | 285 | emit DelegateChanged(delegator, currentDelegate, delegatee); 286 | 287 | _moveDelegates(currentDelegate, delegatee, delegatorBalance); 288 | } 289 | 290 | function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal { 291 | if (srcRep != dstRep && amount > 0) { 292 | if (srcRep != address(0)) { 293 | // decrease old representative 294 | uint32 srcRepNum = numCheckpoints[srcRep]; 295 | uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0; 296 | uint256 srcRepNew = srcRepOld.sub(amount); 297 | _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew); 298 | } 299 | 300 | if (dstRep != address(0)) { 301 | // increase new representative 302 | uint32 dstRepNum = numCheckpoints[dstRep]; 303 | uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0; 304 | uint256 dstRepNew = dstRepOld.add(amount); 305 | _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew); 306 | } 307 | } 308 | } 309 | 310 | function _writeCheckpoint( 311 | address delegatee, 312 | uint32 nCheckpoints, 313 | uint256 oldVotes, 314 | uint256 newVotes 315 | ) 316 | internal 317 | { 318 | uint32 blockNumber = safe32(block.number, "VALUE::_writeCheckpoint: block number exceeds 32 bits"); 319 | 320 | if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) { 321 | checkpoints[delegatee][nCheckpoints - 1].votes = newVotes; 322 | } else { 323 | checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes); 324 | numCheckpoints[delegatee] = nCheckpoints + 1; 325 | } 326 | 327 | emit DelegateVotesChanged(delegatee, oldVotes, newVotes); 328 | } 329 | 330 | function safe32(uint n, string memory errorMessage) internal pure returns (uint32) { 331 | require(n < 2 ** 32, errorMessage); 332 | return uint32(n); 333 | } 334 | 335 | function getChainId() internal pure returns (uint) { 336 | uint256 chainId; 337 | assembly {chainId := chainid()} 338 | return chainId; 339 | } 340 | } 341 | -------------------------------------------------------------------------------- /contracts/VALUE/ValueMasterPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 | import "@openzeppelin/contracts/utils/EnumerableSet.sol"; 8 | import "@openzeppelin/contracts/math/SafeMath.sol"; 9 | import "@openzeppelin/contracts/access/Ownable.sol"; 10 | import "./ValueLiquidityToken.sol"; 11 | 12 | interface ILiquidityMigrator { 13 | // Perform LP token migration from legacy Balancer to ValueLiquid. 14 | // Take the current LP token address and return the new LP token address. 15 | // Migrator should have full access to the caller's LP token. 16 | // Return the new LP token address. 17 | // 18 | // XXX Migrator must have allowance access to Balancer LP tokens. 19 | // ValueLiquid must mint EXACTLY the same amount of Balancer LP tokens or 20 | // else something bad will happen. Traditional Balancer does not 21 | // do that so be careful! 22 | function migrate(IERC20 token) external returns (IERC20); 23 | } 24 | 25 | interface IYFVReferral { 26 | function setReferrer(address farmer, address referrer) external; 27 | function getReferrer(address farmer) external view returns (address); 28 | } 29 | 30 | interface IFreeFromUpTo { 31 | function freeFromUpTo(address from, uint256 value) external returns (uint256 freed); 32 | } 33 | 34 | // Note that it's ownable and the owner wields tremendous power. The ownership 35 | // will be transferred to a governance smart contract (Timelock multisig signers) once VALUE is sufficiently 36 | // distributed and the community can show to govern itself. 37 | // 38 | // Have fun reading it. Hopefully it's bug-free. God bless. 39 | contract ValueMasterPool is Ownable { 40 | using SafeMath for uint256; 41 | using SafeERC20 for IERC20; 42 | IFreeFromUpTo public constant chi = IFreeFromUpTo(0x0000000000004946c0e9F43F4Dee607b0eF1fA1c); 43 | modifier discountCHI { 44 | uint256 gasStart = gasleft(); 45 | _; 46 | uint256 gasSpent = 21000 + gasStart - gasleft() + 16 * msg.data.length; 47 | chi.freeFromUpTo(msg.sender, (gasSpent + 14154) / 41130); 48 | } 49 | // Info of each user. 50 | struct UserInfo { 51 | uint256 amount; // How many LP tokens the user has provided. 52 | uint256 rewardDebt; // Reward debt. See explanation below. 53 | // 54 | // We do some fancy math here. Basically, any point in time, the amount of VALUEs 55 | // entitled to a user but is pending to be distributed is: 56 | // 57 | // pending reward = (user.amount * pool.accValuePerShare) - user.rewardDebt 58 | // 59 | // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 60 | // 1. The pool's `accValuePerShare` (and `lastRewardBlock`) gets updated. 61 | // 2. User receives the pending reward sent to his/her address. 62 | // 3. User's `amount` gets updated. 63 | // 4. User's `rewardDebt` gets updated. 64 | uint256 accumulatedStakingPower; // will accumulate every time user harvest 65 | } 66 | // Info of each pool. 67 | struct PoolInfo { 68 | IERC20 lpToken; // Address of LP token contract. 69 | uint256 allocPoint; // How many allocation points assigned to this pool. VALUEs to distribute per block. 70 | uint256 lastRewardBlock; // Last block number that VALUEs distribution occurs. 71 | uint256 accValuePerShare; // Accumulated VALUEs per share, times 1e12. See below. 72 | bool isStarted; // if lastRewardBlock has passed 73 | } 74 | uint256 public constant REFERRAL_COMMISSION_PERCENT = 1; 75 | address public rewardReferral; 76 | // The VALUE TOKEN! 77 | ValueLiquidityToken public value; 78 | // InsuranceFund address. 79 | address public insuranceFundAddr; 80 | // VALUE tokens created per block. 81 | uint256 public valuePerBlock; 82 | // The liquidity migrator contract. It has a lot of power. Can only be set through governance (owner). 83 | ILiquidityMigrator public migrator; 84 | // Info of each pool. 85 | PoolInfo[] public poolInfo; 86 | // Info of each user that stakes LP tokens. 87 | mapping (uint256 => mapping (address => UserInfo)) public userInfo; 88 | // Total allocation poitns. Must be the sum of all allocation points in all pools. 89 | uint256 public totalAllocPoint = 0; 90 | // The block number when VALUE mining starts. 91 | uint256 public startBlock; 92 | // Block number when each epoch ends. 93 | uint256[3] public epochEndBlocks = [10887300, 11080000, 20000000]; 94 | // Reward multipler 95 | uint256[4] public epochRewardMultiplers = [5000, 10000, 1, 0]; 96 | 97 | event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 98 | event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 99 | event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount); 100 | 101 | constructor( 102 | ValueLiquidityToken _value, 103 | address _insuranceFundAddr, 104 | uint256 _valuePerBlock, 105 | uint256 _startBlock 106 | ) public { 107 | value = _value; 108 | insuranceFundAddr = _insuranceFundAddr; 109 | valuePerBlock = _valuePerBlock; // supposed to be 0.001 (1e16 wei) 110 | startBlock = _startBlock; // supposed to be 10,883,800 (Fri Sep 18 2020 3:00:00 GMT+0) 111 | } 112 | 113 | function poolLength() external view returns (uint256) { 114 | return poolInfo.length; 115 | } 116 | 117 | // Add a new lp to the pool. Can only be called by the owner. 118 | // XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do. 119 | function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate, uint256 _lastRewardBlock) public onlyOwner { 120 | if (_withUpdate) { 121 | massUpdatePools(); 122 | } 123 | if (block.number < startBlock) { 124 | // chef is sleeping 125 | if (_lastRewardBlock == 0) { 126 | _lastRewardBlock = startBlock; 127 | } else { 128 | if (_lastRewardBlock < startBlock) { 129 | _lastRewardBlock = startBlock; 130 | } 131 | } 132 | } else { 133 | // chef is cooking 134 | if (_lastRewardBlock == 0 || _lastRewardBlock < block.number) { 135 | _lastRewardBlock = block.number; 136 | } 137 | } 138 | bool _isStarted = (block.number >= _lastRewardBlock) && (_lastRewardBlock >= startBlock); 139 | poolInfo.push(PoolInfo({ 140 | lpToken: _lpToken, 141 | allocPoint: _allocPoint, 142 | lastRewardBlock: _lastRewardBlock, 143 | accValuePerShare: 0, 144 | isStarted: _isStarted 145 | })); 146 | if (_isStarted) { 147 | totalAllocPoint = totalAllocPoint.add(_allocPoint); 148 | } 149 | } 150 | 151 | // Update the given pool's VALUE allocation point. Can only be called by the owner. 152 | function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner { 153 | if (_withUpdate) { 154 | massUpdatePools(); 155 | } 156 | PoolInfo storage pool = poolInfo[_pid]; 157 | if (pool.isStarted) { 158 | totalAllocPoint = totalAllocPoint.sub(pool.allocPoint).add(_allocPoint); 159 | } 160 | pool.allocPoint = _allocPoint; 161 | } 162 | 163 | function setValuePerBlock(uint256 _valuePerBlock) public onlyOwner { 164 | massUpdatePools(); 165 | valuePerBlock = _valuePerBlock; 166 | } 167 | 168 | function setEpochEndBlock(uint8 _index, uint256 _epochEndBlock) public onlyOwner { 169 | require(_index < 3, "_index out of range"); 170 | require(_epochEndBlock > block.number, "Too late to update"); 171 | require(epochEndBlocks[_index] > block.number, "Too late to update"); 172 | epochEndBlocks[_index] = _epochEndBlock; 173 | } 174 | 175 | function setEpochRewardMultipler(uint8 _index, uint256 _epochRewardMultipler) public onlyOwner { 176 | require(_index > 0 && _index < 4, "Index out of range"); 177 | require(epochEndBlocks[_index - 1] > block.number, "Too late to update"); 178 | epochRewardMultiplers[_index] = _epochRewardMultipler; 179 | } 180 | 181 | function setRewardReferral(address _rewardReferral) external onlyOwner { 182 | rewardReferral = _rewardReferral; 183 | } 184 | 185 | // Set the migrator contract. Can only be called by the owner. 186 | function setMigrator(ILiquidityMigrator _migrator) public onlyOwner { 187 | migrator = _migrator; 188 | } 189 | 190 | // Migrate lp token to another lp contract. 191 | function migrate(uint256 _pid) public onlyOwner { 192 | require(address(migrator) != address(0), "migrate: no migrator"); 193 | PoolInfo storage pool = poolInfo[_pid]; 194 | IERC20 lpToken = pool.lpToken; 195 | uint256 bal = lpToken.balanceOf(address(this)); 196 | lpToken.safeApprove(address(migrator), bal); 197 | IERC20 newLpToken = migrator.migrate(lpToken); 198 | require(bal == newLpToken.balanceOf(address(this)), "migrate: bad"); 199 | pool.lpToken = newLpToken; 200 | } 201 | 202 | // Return reward multiplier over the given _from to _to block. 203 | function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) { 204 | for (uint8 epochId = 3; epochId >= 1; --epochId) { 205 | if (_to >= epochEndBlocks[epochId - 1]) { 206 | if (_from >= epochEndBlocks[epochId - 1]) return _to.sub(_from).mul(epochRewardMultiplers[epochId]); 207 | uint256 multiplier = _to.sub(epochEndBlocks[epochId - 1]).mul(epochRewardMultiplers[epochId]); 208 | if (epochId == 1) return multiplier.add(epochEndBlocks[0].sub(_from).mul(epochRewardMultiplers[0])); 209 | for (epochId = epochId - 1; epochId >= 1; --epochId) { 210 | if (_from >= epochEndBlocks[epochId - 1]) return multiplier.add(epochEndBlocks[epochId].sub(_from).mul(epochRewardMultiplers[epochId])); 211 | multiplier = multiplier.add(epochEndBlocks[epochId].sub(epochEndBlocks[epochId - 1]).mul(epochRewardMultiplers[epochId])); 212 | } 213 | return multiplier.add(epochEndBlocks[0].sub(_from).mul(epochRewardMultiplers[0])); 214 | } 215 | } 216 | return _to.sub(_from).mul(epochRewardMultiplers[0]); 217 | } 218 | 219 | // View function to see pending VALUEs on frontend. 220 | function pendingValue(uint256 _pid, address _user) public view returns (uint256) { 221 | PoolInfo storage pool = poolInfo[_pid]; 222 | UserInfo storage user = userInfo[_pid][_user]; 223 | uint256 accValuePerShare = pool.accValuePerShare; 224 | uint256 lpSupply = pool.lpToken.balanceOf(address(this)); 225 | if (block.number > pool.lastRewardBlock && lpSupply != 0) { 226 | uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); 227 | if (totalAllocPoint > 0) { 228 | uint256 valueReward = multiplier.mul(valuePerBlock).mul(pool.allocPoint).div(totalAllocPoint); 229 | accValuePerShare = accValuePerShare.add(valueReward.mul(1e12).div(lpSupply)); 230 | } 231 | } 232 | return user.amount.mul(accValuePerShare).div(1e12).sub(user.rewardDebt); 233 | } 234 | 235 | function stakingPower(uint256 _pid, address _user) public view returns (uint256) { 236 | UserInfo storage user = userInfo[_pid][_user]; 237 | return user.accumulatedStakingPower.add(pendingValue(_pid, _user)); 238 | } 239 | 240 | // Update reward variables for all pools. Be careful of gas spending! 241 | function massUpdatePools() public discountCHI { 242 | uint256 length = poolInfo.length; 243 | for (uint256 pid = 0; pid < length; ++pid) { 244 | updatePool(pid); 245 | } 246 | } 247 | 248 | // Update reward variables of the given pool to be up-to-date. 249 | function updatePool(uint256 _pid) public discountCHI { 250 | PoolInfo storage pool = poolInfo[_pid]; 251 | if (block.number <= pool.lastRewardBlock) { 252 | return; 253 | } 254 | uint256 lpSupply = pool.lpToken.balanceOf(address(this)); 255 | if (lpSupply == 0) { 256 | pool.lastRewardBlock = block.number; 257 | return; 258 | } 259 | if (!pool.isStarted) { 260 | pool.isStarted = true; 261 | totalAllocPoint = totalAllocPoint.add(pool.allocPoint); 262 | } 263 | uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); 264 | if (totalAllocPoint > 0) { 265 | uint256 valueReward = multiplier.mul(valuePerBlock).mul(pool.allocPoint).div(totalAllocPoint); 266 | safeValueMint(address(this), valueReward); 267 | pool.accValuePerShare = pool.accValuePerShare.add(valueReward.mul(1e12).div(lpSupply)); 268 | } 269 | pool.lastRewardBlock = block.number; 270 | } 271 | 272 | // Deposit LP tokens to ValueMasterPool for VALUE allocation. 273 | function deposit(uint256 _pid, uint256 _amount, address _referrer) public discountCHI { 274 | PoolInfo storage pool = poolInfo[_pid]; 275 | UserInfo storage user = userInfo[_pid][msg.sender]; 276 | updatePool(_pid); 277 | if (rewardReferral != address(0) && _referrer != address(0)) { 278 | require(_referrer != msg.sender, "You cannot refer yourself."); 279 | IYFVReferral(rewardReferral).setReferrer(msg.sender, _referrer); 280 | } 281 | if (user.amount > 0) { 282 | uint256 pending = user.amount.mul(pool.accValuePerShare).div(1e12).sub(user.rewardDebt); 283 | if(pending > 0) { 284 | user.accumulatedStakingPower = user.accumulatedStakingPower.add(pending); 285 | uint256 actualPaid = pending.mul(100 - REFERRAL_COMMISSION_PERCENT).div(100); // 99% 286 | uint256 commission = pending - actualPaid; // 1% 287 | safeValueTransfer(msg.sender, actualPaid); 288 | if (rewardReferral != address(0)) { 289 | _referrer = IYFVReferral(rewardReferral).getReferrer(msg.sender); 290 | } 291 | if (_referrer != address(0)) { // send commission to referrer 292 | safeValueTransfer(_referrer, commission); 293 | } else { // send commission to insuranceFundAddr 294 | safeValueTransfer(insuranceFundAddr, commission); 295 | } 296 | } 297 | } 298 | if(_amount > 0) { 299 | pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount); 300 | user.amount = user.amount.add(_amount); 301 | } 302 | user.rewardDebt = user.amount.mul(pool.accValuePerShare).div(1e12); 303 | emit Deposit(msg.sender, _pid, _amount); 304 | } 305 | 306 | // Withdraw LP tokens from ValueMasterPool. 307 | function withdraw(uint256 _pid, uint256 _amount) public discountCHI { 308 | PoolInfo storage pool = poolInfo[_pid]; 309 | UserInfo storage user = userInfo[_pid][msg.sender]; 310 | require(user.amount >= _amount, "withdraw: not good"); 311 | updatePool(_pid); 312 | uint256 pending = user.amount.mul(pool.accValuePerShare).div(1e12).sub(user.rewardDebt); 313 | if(pending > 0) { 314 | user.accumulatedStakingPower = user.accumulatedStakingPower.add(pending); 315 | uint256 actualPaid = pending.mul(100 - REFERRAL_COMMISSION_PERCENT).div(100); // 99% 316 | uint256 commission = pending - actualPaid; // 1% 317 | safeValueTransfer(msg.sender, actualPaid); 318 | address _referrer = address(0); 319 | if (rewardReferral != address(0)) { 320 | _referrer = IYFVReferral(rewardReferral).getReferrer(msg.sender); 321 | } 322 | if (_referrer != address(0)) { // send commission to referrer 323 | safeValueTransfer(_referrer, commission); 324 | } else { // send commission to insuranceFundAddr 325 | safeValueTransfer(insuranceFundAddr, commission); 326 | } 327 | } 328 | if(_amount > 0) { 329 | user.amount = user.amount.sub(_amount); 330 | pool.lpToken.safeTransfer(address(msg.sender), _amount); 331 | } 332 | user.rewardDebt = user.amount.mul(pool.accValuePerShare).div(1e12); 333 | emit Withdraw(msg.sender, _pid, _amount); 334 | } 335 | 336 | // Withdraw without caring about rewards. EMERGENCY ONLY. 337 | function emergencyWithdraw(uint256 _pid) public { 338 | PoolInfo storage pool = poolInfo[_pid]; 339 | UserInfo storage user = userInfo[_pid][msg.sender]; 340 | pool.lpToken.safeTransfer(address(msg.sender), user.amount); 341 | emit EmergencyWithdraw(msg.sender, _pid, user.amount); 342 | user.amount = 0; 343 | user.rewardDebt = 0; 344 | } 345 | 346 | // Safe value mint, ensure it is never over cap and we are the current owner. 347 | function safeValueMint(address _to, uint256 _amount) internal { 348 | if (value.minters(address(this)) && _to != address(0)) { 349 | uint256 totalSupply = value.totalSupply(); 350 | uint256 realCap = value.cap().add(value.yfvLockedBalance()); 351 | if (totalSupply.add(_amount) > realCap) { 352 | value.mint(_to, realCap.sub(totalSupply)); 353 | } else { 354 | value.mint(_to, _amount); 355 | } 356 | } 357 | } 358 | 359 | // Safe value transfer function, just in case if rounding error causes pool to not have enough VALUEs. 360 | function safeValueTransfer(address _to, uint256 _amount) internal { 361 | uint256 valueBal = value.balanceOf(address(this)); 362 | if (_amount > valueBal) { 363 | value.transfer(_to, valueBal); 364 | } else { 365 | value.transfer(_to, _amount); 366 | } 367 | } 368 | 369 | // Update insuranceFund by the previous insuranceFund contract. 370 | function setInsuranceFundAddr(address _insuranceFundAddr) public { 371 | require(msg.sender == insuranceFundAddr, "insuranceFund: wut?"); 372 | insuranceFundAddr = _insuranceFundAddr; 373 | } 374 | 375 | // This function allows governance to take unsupported tokens out of the contract, since this pool exists longer than the other pools. 376 | // This is in an effort to make someone whole, should they seriously mess up. 377 | // There is no guarantee governance will vote to return these. 378 | // It also allows for removal of airdropped tokens. 379 | function governanceRecoverUnsupported(IERC20 _token, uint256 amount, address to) external onlyOwner { 380 | uint256 length = poolInfo.length; 381 | for (uint256 pid = 0; pid < length; ++pid) { 382 | PoolInfo storage pool = poolInfo[pid]; 383 | // cant take staked asset 384 | require(_token != pool.lpToken, "!pool.lpToken"); 385 | } 386 | // transfer to 387 | _token.safeTransfer(to, amount); 388 | } 389 | } 390 | -------------------------------------------------------------------------------- /contracts/VALUE/mock/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | 7 | contract MockERC20 is ERC20 { 8 | constructor( 9 | string memory name, 10 | string memory symbol, 11 | uint256 supply 12 | ) public ERC20(name, symbol) { 13 | _mint(msg.sender, supply); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /contracts/VALUE/mock/MockLegacyPool.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 | 7 | contract MockLegacyPool { 8 | IERC20 yfv; 9 | 10 | constructor(IERC20 _yfv) public { 11 | yfv = _yfv; 12 | } 13 | 14 | function setRewardStake(address _rewardStake) external { 15 | yfv.approve(_rewardStake, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/YFV/YFV.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.16; 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 YFV is ERC20, ERC20Detailed { 194 | using SafeERC20 for IERC20; 195 | using Address for address; 196 | using SafeMath for uint; 197 | 198 | address public governance; 199 | mapping (address => bool) public minters; 200 | 201 | constructor () public ERC20Detailed("YFValue", "YFV", 18) { 202 | governance = msg.sender; 203 | } 204 | 205 | function mint(address account, uint256 amount) public { 206 | require(minters[msg.sender], "!minter"); 207 | _mint(account, amount); 208 | } 209 | 210 | function burn(uint256 amount) public { 211 | _burn(msg.sender, amount); 212 | } 213 | 214 | function setGovernance(address _governance) public { 215 | require(msg.sender == governance, "!governance"); 216 | governance = _governance; 217 | } 218 | 219 | function addMinter(address _minter) public { 220 | require(msg.sender == governance, "!governance"); 221 | minters[_minter] = true; 222 | } 223 | 224 | function removeMinter(address _minter) public { 225 | require(msg.sender == governance, "!governance"); 226 | minters[_minter] = false; 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /contracts/YFV/YFV_DevRewards.sol: -------------------------------------------------------------------------------- 1 | // File: @openzeppelin/contracts/math/Math.sol 2 | 3 | pragma solidity ^0.5.0; 4 | 5 | /** 6 | * @dev Standard math utilities missing in the Solidity language. 7 | */ 8 | library Math { 9 | /** 10 | * @dev Returns the largest of two numbers. 11 | */ 12 | function max(uint256 a, uint256 b) internal pure returns (uint256) { 13 | return a >= b ? a : b; 14 | } 15 | 16 | /** 17 | * @dev Returns the smallest of two numbers. 18 | */ 19 | function min(uint256 a, uint256 b) internal pure returns (uint256) { 20 | return a < b ? a : b; 21 | } 22 | 23 | /** 24 | * @dev Returns the average of two numbers. The result is rounded towards 25 | * zero. 26 | */ 27 | function average(uint256 a, uint256 b) internal pure returns (uint256) { 28 | // (a + b) / 2 can overflow, so we distribute 29 | return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); 30 | } 31 | } 32 | 33 | // File: @openzeppelin/contracts/math/SafeMath.sol 34 | 35 | pragma solidity ^0.5.0; 36 | 37 | /** 38 | * @dev Wrappers over Solidity's arithmetic operations with added overflow 39 | * checks. 40 | * 41 | * Arithmetic operations in Solidity wrap on overflow. This can easily result 42 | * in bugs, because programmers usually assume that an overflow raises an 43 | * error, which is the standard behavior in high level programming languages. 44 | * `SafeMath` restores this intuition by reverting the transaction when an 45 | * operation overflows. 46 | * 47 | * Using this library instead of the unchecked operations eliminates an entire 48 | * class of bugs, so it's recommended to use it always. 49 | */ 50 | library SafeMath { 51 | /** 52 | * @dev Returns the addition of two unsigned integers, reverting on 53 | * overflow. 54 | * 55 | * Counterpart to Solidity's `+` operator. 56 | * 57 | * Requirements: 58 | * - Addition cannot overflow. 59 | */ 60 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 61 | uint256 c = a + b; 62 | require(c >= a, "SafeMath: addition overflow"); 63 | 64 | return c; 65 | } 66 | 67 | /** 68 | * @dev Returns the subtraction of two unsigned integers, reverting on 69 | * overflow (when the result is negative). 70 | * 71 | * Counterpart to Solidity's `-` operator. 72 | * 73 | * Requirements: 74 | * - Subtraction cannot overflow. 75 | */ 76 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 77 | return sub(a, b, "SafeMath: subtraction overflow"); 78 | } 79 | 80 | /** 81 | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 82 | * overflow (when the result is negative). 83 | * 84 | * Counterpart to Solidity's `-` operator. 85 | * 86 | * Requirements: 87 | * - Subtraction cannot overflow. 88 | * 89 | * _Available since v2.4.0._ 90 | */ 91 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 92 | require(b <= a, errorMessage); 93 | uint256 c = a - b; 94 | 95 | return c; 96 | } 97 | 98 | /** 99 | * @dev Returns the multiplication of two unsigned integers, reverting on 100 | * overflow. 101 | * 102 | * Counterpart to Solidity's `*` operator. 103 | * 104 | * Requirements: 105 | * - Multiplication cannot overflow. 106 | */ 107 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 108 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 109 | // benefit is lost if 'b' is also tested. 110 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 111 | if (a == 0) { 112 | return 0; 113 | } 114 | 115 | uint256 c = a * b; 116 | require(c / a == b, "SafeMath: multiplication overflow"); 117 | 118 | return c; 119 | } 120 | 121 | /** 122 | * @dev Returns the integer division of two unsigned integers. Reverts on 123 | * division by zero. The result is rounded towards zero. 124 | * 125 | * Counterpart to Solidity's `/` operator. Note: this function uses a 126 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 127 | * uses an invalid opcode to revert (consuming all remaining gas). 128 | * 129 | * Requirements: 130 | * - The divisor cannot be zero. 131 | */ 132 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 133 | return div(a, b, "SafeMath: division by zero"); 134 | } 135 | 136 | /** 137 | * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 138 | * division by zero. The result is rounded towards zero. 139 | * 140 | * Counterpart to Solidity's `/` operator. Note: this function uses a 141 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 142 | * uses an invalid opcode to revert (consuming all remaining gas). 143 | * 144 | * Requirements: 145 | * - The divisor cannot be zero. 146 | * 147 | * _Available since v2.4.0._ 148 | */ 149 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 150 | // Solidity only automatically asserts when dividing by 0 151 | require(b > 0, errorMessage); 152 | uint256 c = a / b; 153 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 154 | 155 | return c; 156 | } 157 | 158 | /** 159 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 160 | * Reverts when dividing by zero. 161 | * 162 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 163 | * opcode (which leaves remaining gas untouched) while Solidity uses an 164 | * invalid opcode to revert (consuming all remaining gas). 165 | * 166 | * Requirements: 167 | * - The divisor cannot be zero. 168 | */ 169 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 170 | return mod(a, b, "SafeMath: modulo by zero"); 171 | } 172 | 173 | /** 174 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 175 | * Reverts with custom message when dividing by zero. 176 | * 177 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 178 | * opcode (which leaves remaining gas untouched) while Solidity uses an 179 | * invalid opcode to revert (consuming all remaining gas). 180 | * 181 | * Requirements: 182 | * - The divisor cannot be zero. 183 | * 184 | * _Available since v2.4.0._ 185 | */ 186 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 187 | require(b != 0, errorMessage); 188 | return a % b; 189 | } 190 | } 191 | 192 | // File: @openzeppelin/contracts/GSN/Context.sol 193 | 194 | pragma solidity ^0.5.0; 195 | 196 | /* 197 | * @dev Provides information about the current execution context, including the 198 | * sender of the transaction and its data. While these are generally available 199 | * via msg.sender and msg.data, they should not be accessed in such a direct 200 | * manner, since when dealing with GSN meta-transactions the account sending and 201 | * paying for execution may not be the actual sender (as far as an application 202 | * is concerned). 203 | * 204 | * This contract is only required for intermediate, library-like contracts. 205 | */ 206 | contract Context { 207 | // Empty internal constructor, to prevent people from mistakenly deploying 208 | // an instance of this contract, which should be used via inheritance. 209 | constructor () internal {} 210 | // solhint-disable-previous-line no-empty-blocks 211 | 212 | function _msgSender() internal view returns (address payable) { 213 | return msg.sender; 214 | } 215 | 216 | function _msgData() internal view returns (bytes memory) { 217 | this; 218 | // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 219 | return msg.data; 220 | } 221 | } 222 | 223 | // File: @openzeppelin/contracts/ownership/Ownable.sol 224 | 225 | pragma solidity ^0.5.0; 226 | 227 | /** 228 | * @dev Contract module which provides a basic access control mechanism, where 229 | * there is an account (an owner) that can be granted exclusive access to 230 | * specific functions. 231 | * 232 | * This module is used through inheritance. It will make available the modifier 233 | * `onlyOwner`, which can be applied to your functions to restrict their use to 234 | * the owner. 235 | */ 236 | contract Ownable is Context { 237 | address private _owner; 238 | 239 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 240 | 241 | /** 242 | * @dev Initializes the contract setting the deployer as the initial owner. 243 | */ 244 | constructor () internal { 245 | _owner = _msgSender(); 246 | emit OwnershipTransferred(address(0), _owner); 247 | } 248 | 249 | /** 250 | * @dev Returns the address of the current owner. 251 | */ 252 | function owner() public view returns (address) { 253 | return _owner; 254 | } 255 | 256 | /** 257 | * @dev Throws if called by any account other than the owner. 258 | */ 259 | modifier onlyOwner() { 260 | require(isOwner(), "Ownable: caller is not the owner"); 261 | _; 262 | } 263 | 264 | /** 265 | * @dev Returns true if the caller is the current owner. 266 | */ 267 | function isOwner() public view returns (bool) { 268 | return _msgSender() == _owner; 269 | } 270 | 271 | /** 272 | * @dev Leaves the contract without owner. It will not be possible to call 273 | * `onlyOwner` functions anymore. Can only be called by the current owner. 274 | * 275 | * NOTE: Renouncing ownership will leave the contract without an owner, 276 | * thereby removing any functionality that is only available to the owner. 277 | */ 278 | function renounceOwnership() public onlyOwner { 279 | emit OwnershipTransferred(_owner, address(0)); 280 | _owner = address(0); 281 | } 282 | 283 | /** 284 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 285 | * Can only be called by the current owner. 286 | */ 287 | function transferOwnership(address newOwner) public onlyOwner { 288 | _transferOwnership(newOwner); 289 | } 290 | 291 | /** 292 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 293 | */ 294 | function _transferOwnership(address newOwner) internal { 295 | require(newOwner != address(0), "Ownable: new owner is the zero address"); 296 | emit OwnershipTransferred(_owner, newOwner); 297 | _owner = newOwner; 298 | } 299 | } 300 | 301 | // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 302 | 303 | pragma solidity ^0.5.0; 304 | 305 | /** 306 | * @dev Interface of the ERC20 standard as defined in the EIP. Does not include 307 | * the optional functions; to access them see {ERC20Detailed}. 308 | */ 309 | interface IERC20 { 310 | /** 311 | * @dev Returns the amount of tokens in existence. 312 | */ 313 | function totalSupply() external view returns (uint256); 314 | 315 | /** 316 | * @dev Returns the amount of tokens owned by `account`. 317 | */ 318 | function balanceOf(address account) external view returns (uint256); 319 | 320 | /** 321 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 322 | * 323 | * Returns a boolean value indicating whether the operation succeeded. 324 | * 325 | * Emits a {Transfer} event. 326 | */ 327 | function transfer(address recipient, uint256 amount) external returns (bool); 328 | 329 | function mint(address account, uint amount) external; 330 | 331 | function burn(uint amount) external; 332 | 333 | /** 334 | * @dev Returns the remaining number of tokens that `spender` will be 335 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 336 | * zero by default. 337 | * 338 | * This value changes when {approve} or {transferFrom} are called. 339 | */ 340 | function allowance(address owner, address spender) external view returns (uint256); 341 | 342 | /** 343 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 344 | * 345 | * Returns a boolean value indicating whether the operation succeeded. 346 | * 347 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 348 | * that someone may use both the old and the new allowance by unfortunate 349 | * transaction ordering. One possible solution to mitigate this race 350 | * condition is to first reduce the spender's allowance to 0 and set the 351 | * desired value afterwards: 352 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 353 | * 354 | * Emits an {Approval} event. 355 | */ 356 | function approve(address spender, uint256 amount) external returns (bool); 357 | 358 | /** 359 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 360 | * allowance mechanism. `amount` is then deducted from the caller's 361 | * allowance. 362 | * 363 | * Returns a boolean value indicating whether the operation succeeded. 364 | * 365 | * Emits a {Transfer} event. 366 | */ 367 | function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 368 | 369 | /** 370 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 371 | * another (`to`). 372 | * 373 | * Note that `value` may be zero. 374 | */ 375 | event Transfer(address indexed from, address indexed to, uint256 value); 376 | 377 | /** 378 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 379 | * a call to {approve}. `value` is the new allowance. 380 | */ 381 | event Approval(address indexed owner, address indexed spender, uint256 value); 382 | } 383 | 384 | contract YFVDevRewards is Ownable { 385 | using SafeMath for uint256; 386 | 387 | IERC20 public yfv = IERC20(0x45f24BaEef268BB6d63AEe5129015d69702BCDfa); 388 | IERC20 public vUSD = IERC20(0x1B8E12F839BD4e73A47adDF76cF7F0097d74c14C); 389 | IERC20 public vETH = IERC20(0x76A034e76Aa835363056dd418611E4f81870f16e); 390 | 391 | uint256 public vUSD_REWARD_FRACTION_RATE = 21000000000; // 21 * 1e9 (vUSD decimals = 9) 392 | uint256 public vETH_REWARD_FRACTION_RATE = 21000000000000; // 21000 * 1e9 (vETH decimals = 9) 393 | 394 | uint256 public constant DURATION = 50 weeks; 395 | uint256 public constant TOTAL_REWARD = 1470000 ether; 396 | 397 | uint256 public constant REWARD_RATE = TOTAL_REWARD / DURATION; 398 | 399 | uint256 public totalClaimedRewards = 0; 400 | uint256 public starttime = 1597759200; // Tuesday, August 18, 2020 2:00:00 PM (GMT+0) 401 | uint256 public endtime = starttime + DURATION; 402 | 403 | event RewardPaid(uint256 reward); 404 | event RewardBurn(uint256 reward); 405 | 406 | function totalReleasedRewards() public view returns (uint256) { 407 | if (block.timestamp <= starttime) return 0; 408 | else if (block.timestamp >= endtime) return TOTAL_REWARD; 409 | return REWARD_RATE.mul(block.timestamp - starttime); 410 | } 411 | 412 | function claimableRewards() public view returns (uint256) { 413 | return totalReleasedRewards().sub(totalClaimedRewards); 414 | } 415 | 416 | function claimRewards() public onlyOwner { 417 | uint256 reward = claimableRewards(); 418 | require(reward > 0, "There is nothing to claim"); 419 | totalClaimedRewards = totalClaimedRewards.add(reward); 420 | yfv.mint(msg.sender, reward); 421 | vUSD.mint(msg.sender, reward.div(vUSD_REWARD_FRACTION_RATE)); 422 | vETH.mint(msg.sender, reward.div(vETH_REWARD_FRACTION_RATE)); 423 | emit RewardPaid(reward); 424 | } 425 | 426 | function burnRewards(uint256 amount) public onlyOwner { 427 | uint256 reward = claimableRewards(); 428 | require(reward >= amount, "There is not enough reward to burn"); 429 | totalClaimedRewards = totalClaimedRewards.add(amount); 430 | yfv.mint(address(this), amount); 431 | yfv.burn(amount); 432 | emit RewardBurn(amount); 433 | } 434 | } 435 | -------------------------------------------------------------------------------- /contracts/YFV/YFV_Referral.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.0; 2 | 3 | contract YFVReferral { 4 | mapping(address => address) public referrers; // account_address -> referrer_address 5 | mapping(address => uint256) public referredCount; // referrer_address -> num_of_referred 6 | 7 | event Referral(address indexed referrer, address indexed farmer); 8 | 9 | // Standard contract ownership transfer. 10 | address public owner; 11 | address private nextOwner; 12 | 13 | mapping(address => bool) public isAdmin; 14 | 15 | constructor () public { 16 | owner = msg.sender; 17 | } 18 | 19 | // Standard modifier on methods invokable only by contract owner. 20 | modifier onlyOwner { 21 | require(msg.sender == owner, "OnlyOwner methods called by non-owner."); 22 | _; 23 | } 24 | 25 | modifier onlyAdmin { 26 | require(isAdmin[msg.sender], "OnlyAdmin methods called by non-admin."); 27 | _; 28 | } 29 | 30 | // Standard contract ownership transfer implementation, 31 | function approveNextOwner(address _nextOwner) external onlyOwner { 32 | require(_nextOwner != owner, "Cannot approve current owner."); 33 | nextOwner = _nextOwner; 34 | } 35 | 36 | function acceptNextOwner() external { 37 | require(msg.sender == nextOwner, "Can only accept preapproved new owner."); 38 | owner = nextOwner; 39 | } 40 | 41 | function setReferrer(address farmer, address referrer) public onlyAdmin { 42 | if (referrers[farmer] == address(0) && referrer != address(0)) { 43 | referrers[farmer] = referrer; 44 | referredCount[referrer] += 1; 45 | emit Referral(referrer, farmer); 46 | } 47 | } 48 | 49 | function getReferrer(address farmer) public view returns (address) { 50 | return referrers[farmer]; 51 | } 52 | 53 | // Set admin status. 54 | function setAdminStatus(address _admin, bool _status) external onlyOwner { 55 | isAdmin[_admin] = _status; 56 | } 57 | 58 | event EmergencyERC20Drain(address token, address owner, uint256 amount); 59 | 60 | // owner can drain tokens that are sent here by mistake 61 | function emergencyERC20Drain(ERC20 token, uint amount) external onlyOwner { 62 | emit EmergencyERC20Drain(address(token), owner, amount); 63 | token.transfer(owner, amount); 64 | } 65 | } 66 | 67 | /** 68 | * @title ERC20 interface 69 | * @dev see https://github.com/ethereum/EIPs/issues/20 70 | */ 71 | contract ERC20 { 72 | function totalSupply() public view returns (uint256); 73 | 74 | function balanceOf(address _who) public view returns (uint256); 75 | 76 | function transfer(address _to, uint256 _value) public returns (bool); 77 | 78 | function allowance(address _owner, address _spender) public view returns (uint256); 79 | 80 | function transferFrom(address _from, address _to, uint256 _value) public returns (bool); 81 | 82 | function approve(address _spender, uint256 _value) public returns (bool); 83 | 84 | event Transfer(address indexed from, address indexed to, uint256 value); 85 | event Approval(address indexed owner, address indexed spender, uint256 value); 86 | } 87 | -------------------------------------------------------------------------------- /contracts/YFV/YFV_Vote.sol: -------------------------------------------------------------------------------- 1 | /* 2 | ____ __ __ __ _ 3 | / __/__ __ ___ / /_ / / ___ / /_ (_)__ __ 4 | _\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ / 5 | /___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\ 6 | /___/ 7 | 8 | * Synthetix: YFIRewards.sol 9 | * 10 | * Docs: https://docs.synthetix.io/ 11 | * 12 | * 13 | * MIT License 14 | * =========== 15 | * 16 | * Copyright (c) 2020 Synthetix 17 | * 18 | * Permission is hereby granted, free of charge, to any person obtaining a copy 19 | * of this software and associated documentation files (the "Software"), to deal 20 | * in the Software without restriction, including without limitation the rights 21 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | * copies of the Software, and to permit persons to whom the Software is 23 | * furnished to do so, subject to the following conditions: 24 | * 25 | * The above copyright notice and this permission notice shall be included in all 26 | * copies or substantial portions of the Software. 27 | * 28 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 33 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 | */ 35 | 36 | // File: @openzeppelin/contracts/math/SafeMath.sol 37 | 38 | pragma solidity ^0.5.0; 39 | 40 | /** 41 | * @dev Wrappers over Solidity's arithmetic operations with added overflow 42 | * checks. 43 | * 44 | * Arithmetic operations in Solidity wrap on overflow. This can easily result 45 | * in bugs, because programmers usually assume that an overflow raises an 46 | * error, which is the standard behavior in high level programming languages. 47 | * `SafeMath` restores this intuition by reverting the transaction when an 48 | * operation overflows. 49 | * 50 | * Using this library instead of the unchecked operations eliminates an entire 51 | * class of bugs, so it's recommended to use it always. 52 | */ 53 | library SafeMath { 54 | /** 55 | * @dev Returns the addition of two unsigned integers, reverting on 56 | * overflow. 57 | * 58 | * Counterpart to Solidity's `+` operator. 59 | * 60 | * Requirements: 61 | * - Addition cannot overflow. 62 | */ 63 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 64 | uint256 c = a + b; 65 | require(c >= a, "SafeMath: addition overflow"); 66 | 67 | return c; 68 | } 69 | 70 | /** 71 | * @dev Returns the subtraction of two unsigned integers, reverting on 72 | * overflow (when the result is negative). 73 | * 74 | * Counterpart to Solidity's `-` operator. 75 | * 76 | * Requirements: 77 | * - Subtraction cannot overflow. 78 | */ 79 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 80 | return sub(a, b, "SafeMath: subtraction overflow"); 81 | } 82 | 83 | /** 84 | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 85 | * overflow (when the result is negative). 86 | * 87 | * Counterpart to Solidity's `-` operator. 88 | * 89 | * Requirements: 90 | * - Subtraction cannot overflow. 91 | * 92 | * _Available since v2.4.0._ 93 | */ 94 | function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 95 | require(b <= a, errorMessage); 96 | uint256 c = a - b; 97 | 98 | return c; 99 | } 100 | 101 | /** 102 | * @dev Returns the multiplication of two unsigned integers, reverting on 103 | * overflow. 104 | * 105 | * Counterpart to Solidity's `*` operator. 106 | * 107 | * Requirements: 108 | * - Multiplication cannot overflow. 109 | */ 110 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 111 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 112 | // benefit is lost if 'b' is also tested. 113 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 114 | if (a == 0) { 115 | return 0; 116 | } 117 | 118 | uint256 c = a * b; 119 | require(c / a == b, "SafeMath: multiplication overflow"); 120 | 121 | return c; 122 | } 123 | 124 | /** 125 | * @dev Returns the integer division of two unsigned integers. Reverts on 126 | * division by zero. The result is rounded towards zero. 127 | * 128 | * Counterpart to Solidity's `/` operator. Note: this function uses a 129 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 130 | * uses an invalid opcode to revert (consuming all remaining gas). 131 | * 132 | * Requirements: 133 | * - The divisor cannot be zero. 134 | */ 135 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 136 | return div(a, b, "SafeMath: division by zero"); 137 | } 138 | 139 | /** 140 | * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 141 | * division by zero. The result is rounded towards zero. 142 | * 143 | * Counterpart to Solidity's `/` operator. Note: this function uses a 144 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 145 | * uses an invalid opcode to revert (consuming all remaining gas). 146 | * 147 | * Requirements: 148 | * - The divisor cannot be zero. 149 | * 150 | * _Available since v2.4.0._ 151 | */ 152 | function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 153 | // Solidity only automatically asserts when dividing by 0 154 | require(b > 0, errorMessage); 155 | uint256 c = a / b; 156 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 157 | 158 | return c; 159 | } 160 | 161 | /** 162 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 163 | * Reverts when dividing by zero. 164 | * 165 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 166 | * opcode (which leaves remaining gas untouched) while Solidity uses an 167 | * invalid opcode to revert (consuming all remaining gas). 168 | * 169 | * Requirements: 170 | * - The divisor cannot be zero. 171 | */ 172 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 173 | return mod(a, b, "SafeMath: modulo by zero"); 174 | } 175 | 176 | /** 177 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 178 | * Reverts with custom message when dividing by zero. 179 | * 180 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 181 | * opcode (which leaves remaining gas untouched) while Solidity uses an 182 | * invalid opcode to revert (consuming all remaining gas). 183 | * 184 | * Requirements: 185 | * - The divisor cannot be zero. 186 | * 187 | * _Available since v2.4.0._ 188 | */ 189 | function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 190 | require(b != 0, errorMessage); 191 | return a % b; 192 | } 193 | } 194 | 195 | interface IYFVRewards { 196 | function stakingPower(address account) external view returns (uint256); 197 | } 198 | 199 | contract YFVVote { 200 | using SafeMath for uint256; 201 | 202 | uint8 public constant MAX_VOTERS_PER_ITEM = 50; 203 | 204 | uint16 public constant MIN_VOTING_VALUE = 50; // 50% (x0.5 times) 205 | uint16 public constant MAX_VOTING_VALUE = 200; // 200% (x2 times) 206 | 207 | mapping(address => mapping(uint256 => uint8)) public numVoters; // poolAddress -> votingItem (periodFinish) -> numVoters (the number of voters in this round) 208 | mapping(address => mapping(uint256 => address[MAX_VOTERS_PER_ITEM])) public voters; // poolAddress -> votingItem (periodFinish) -> voters (array) 209 | mapping(address => mapping(uint256 => mapping(address => bool))) public isInTopVoters; // poolAddress -> votingItem (periodFinish) -> isInTopVoters (map: voter -> in_top (true/false)) 210 | mapping(address => mapping(uint256 => mapping(address => uint16))) public voter2VotingValue; // poolAddress -> votingItem (periodFinish) -> voter2VotingValue (map: voter -> voting value) 211 | 212 | event Voted(address poolAddress, address indexed user, uint256 votingItem, uint16 votingValue); 213 | 214 | function isVotable(address poolAddress, address account, uint256 votingItem) public view returns (bool) { 215 | // already voted 216 | if (voter2VotingValue[poolAddress][votingItem][account] > 0) return false; 217 | 218 | IYFVRewards rewards = IYFVRewards(poolAddress); 219 | // hasn't any staking power 220 | if (rewards.stakingPower(account) == 0) return false; 221 | 222 | // number of voters is under limit still 223 | if (numVoters[poolAddress][votingItem] < MAX_VOTERS_PER_ITEM) return true; 224 | for (uint8 i = 0; i < numVoters[poolAddress][votingItem]; i++) { 225 | if (rewards.stakingPower(voters[poolAddress][votingItem][i]) < rewards.stakingPower(account)) return true; // there is some voters has lower staking power 226 | } 227 | 228 | return false; 229 | } 230 | 231 | function averageVotingValue(address poolAddress, uint256 votingItem) public view returns (uint16) { 232 | if (numVoters[poolAddress][votingItem] == 0) return 0; // no votes 233 | uint256 totalStakingPower = 0; 234 | uint256 totalWeightVotingValue = 0; 235 | IYFVRewards rewards = IYFVRewards(poolAddress); 236 | for (uint8 i = 0; i < numVoters[poolAddress][votingItem]; i++) { 237 | address voter = voters[poolAddress][votingItem][i]; 238 | totalStakingPower = totalStakingPower.add(rewards.stakingPower(voter)); 239 | totalWeightVotingValue = totalWeightVotingValue.add(rewards.stakingPower(voter).mul(voter2VotingValue[poolAddress][votingItem][voter])); 240 | } 241 | return (uint16) (totalWeightVotingValue.div(totalStakingPower)); 242 | } 243 | 244 | function vote(address poolAddress, uint256 votingItem, uint16 votingValue) public { 245 | require(votingValue >= MIN_VOTING_VALUE, "votingValue is smaller than MIN_VOTING_VALUE"); 246 | require(votingValue <= MAX_VOTING_VALUE, "votingValue is greater than MAX_VOTING_VALUE"); 247 | if (!isInTopVoters[poolAddress][votingItem][msg.sender]) { 248 | require(isVotable(poolAddress, msg.sender, votingItem), "This account is not votable"); 249 | uint8 voterIndex = MAX_VOTERS_PER_ITEM; 250 | if (numVoters[poolAddress][votingItem] < MAX_VOTERS_PER_ITEM) { 251 | voterIndex = numVoters[poolAddress][votingItem]; 252 | } else { 253 | IYFVRewards rewards = IYFVRewards(poolAddress); 254 | uint256 minStakingPower = rewards.stakingPower(msg.sender); 255 | for (uint8 i = 0; i < numVoters[poolAddress][votingItem]; i++) { 256 | if (rewards.stakingPower(voters[poolAddress][votingItem][i]) < minStakingPower) { 257 | voterIndex = i; 258 | minStakingPower = rewards.stakingPower(voters[poolAddress][votingItem][i]); 259 | } 260 | } 261 | } 262 | if (voterIndex < MAX_VOTERS_PER_ITEM) { 263 | if (voterIndex < numVoters[poolAddress][votingItem]) { 264 | isInTopVoters[poolAddress][votingItem][voters[poolAddress][votingItem][voterIndex]] = false; // remove lower power previous voter 265 | } else { 266 | ++numVoters[poolAddress][votingItem]; 267 | } 268 | isInTopVoters[poolAddress][votingItem][msg.sender] = true; 269 | voters[poolAddress][votingItem][voterIndex] = msg.sender; 270 | } 271 | } 272 | voter2VotingValue[poolAddress][votingItem][msg.sender] = votingValue; 273 | emit Voted(poolAddress, msg.sender, votingItem, votingValue); 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /contracts/YFV/vETH.sol: -------------------------------------------------------------------------------- 1 | // File: openzeppelin-eth/contracts/math/SafeMath.sol 2 | 3 | pragma solidity ^0.5.0; 4 | 5 | 6 | /** 7 | * @title SafeMath 8 | * @dev Math operations with safety checks that revert on error 9 | */ 10 | library SafeMath { 11 | 12 | /** 13 | * @dev Multiplies two numbers, reverts on overflow. 14 | */ 15 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 16 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 17 | // benefit is lost if 'b' is also tested. 18 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 19 | if (a == 0) { 20 | return 0; 21 | } 22 | 23 | uint256 c = a * b; 24 | require(c / a == b); 25 | 26 | return c; 27 | } 28 | 29 | /** 30 | * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. 31 | */ 32 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 33 | require(b > 0); // Solidity only automatically asserts when dividing by 0 34 | uint256 c = a / b; 35 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 36 | 37 | return c; 38 | } 39 | 40 | /** 41 | * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). 42 | */ 43 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 44 | require(b <= a); 45 | uint256 c = a - b; 46 | 47 | return c; 48 | } 49 | 50 | /** 51 | * @dev Adds two numbers, reverts on overflow. 52 | */ 53 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 54 | uint256 c = a + b; 55 | require(c >= a); 56 | 57 | return c; 58 | } 59 | 60 | /** 61 | * @dev Divides two numbers and returns the remainder (unsigned integer modulo), 62 | * reverts when dividing by zero. 63 | */ 64 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 65 | require(b != 0); 66 | return a % b; 67 | } 68 | } 69 | 70 | // File: zos-lib/contracts/Initializable.sol 71 | 72 | pragma solidity >=0.5.0 <0.6.0; 73 | 74 | 75 | /** 76 | * @title Initializable 77 | * 78 | * @dev Helper contract to support initializer functions. To use it, replace 79 | * the constructor with a function that has the `initializer` modifier. 80 | * WARNING: Unlike constructors, initializer functions must be manually 81 | * invoked. This applies both to deploying an Initializable contract, as well 82 | * as extending an Initializable contract via inheritance. 83 | * WARNING: When used with inheritance, manual care must be taken to not invoke 84 | * a parent initializer twice, or ensure that all initializers are idempotent, 85 | * because this is not dealt with automatically as with constructors. 86 | */ 87 | contract Initializable { 88 | 89 | /** 90 | * @dev Indicates that the contract has been initialized. 91 | */ 92 | bool private initialized; 93 | 94 | /** 95 | * @dev Indicates that the contract is in the process of being initialized. 96 | */ 97 | bool private initializing; 98 | 99 | /** 100 | * @dev Modifier to use in the initializer function of a contract. 101 | */ 102 | modifier initializer() { 103 | require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); 104 | 105 | bool isTopLevelCall = !initializing; 106 | if (isTopLevelCall) { 107 | initializing = true; 108 | initialized = true; 109 | } 110 | 111 | _; 112 | 113 | if (isTopLevelCall) { 114 | initializing = false; 115 | } 116 | } 117 | 118 | /// @dev Returns true if and only if the function is running in the constructor 119 | function isConstructor() private view returns (bool) { 120 | // extcodesize checks the size of the code stored in an address, and 121 | // address returns the current address. Since the code is still not 122 | // deployed when running a constructor, any checks on its code size will 123 | // yield zero, making it an effective way to detect if a contract is 124 | // under construction or not. 125 | uint256 cs; 126 | assembly { cs := extcodesize(address) } 127 | return cs == 0; 128 | } 129 | 130 | // Reserved storage space to allow for layout changes in the future. 131 | uint256[50] private ______gap; 132 | } 133 | 134 | // File: openzeppelin-eth/contracts/ownership/Ownable.sol 135 | 136 | pragma solidity ^0.5.0; 137 | 138 | 139 | /** 140 | * @title Ownable 141 | * @dev The Ownable contract has an owner address, and provides basic authorization control 142 | * functions, this simplifies the implementation of "user permissions". 143 | */ 144 | contract Ownable is Initializable { 145 | address private _owner; 146 | 147 | 148 | event OwnershipRenounced(address indexed previousOwner); 149 | event OwnershipTransferred( 150 | address indexed previousOwner, 151 | address indexed newOwner 152 | ); 153 | 154 | 155 | /** 156 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 157 | * account. 158 | */ 159 | function initialize(address sender) public initializer { 160 | _owner = sender; 161 | } 162 | 163 | /** 164 | * @return the address of the owner. 165 | */ 166 | function owner() public view returns(address) { 167 | return _owner; 168 | } 169 | 170 | /** 171 | * @dev Throws if called by any account other than the owner. 172 | */ 173 | modifier onlyOwner() { 174 | require(isOwner()); 175 | _; 176 | } 177 | 178 | /** 179 | * @return true if `msg.sender` is the owner of the contract. 180 | */ 181 | function isOwner() public view returns(bool) { 182 | return msg.sender == _owner; 183 | } 184 | 185 | /** 186 | * @dev Allows the current owner to relinquish control of the contract. 187 | * @notice Renouncing to ownership will leave the contract without an owner. 188 | * It will not be possible to call the functions with the `onlyOwner` 189 | * modifier anymore. 190 | */ 191 | function renounceOwnership() public onlyOwner { 192 | emit OwnershipRenounced(_owner); 193 | _owner = address(0); 194 | } 195 | 196 | /** 197 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 198 | * @param newOwner The address to transfer ownership to. 199 | */ 200 | function transferOwnership(address newOwner) public onlyOwner { 201 | _transferOwnership(newOwner); 202 | } 203 | 204 | /** 205 | * @dev Transfers control of the contract to a newOwner. 206 | * @param newOwner The address to transfer ownership to. 207 | */ 208 | function _transferOwnership(address newOwner) internal { 209 | require(newOwner != address(0)); 210 | emit OwnershipTransferred(_owner, newOwner); 211 | _owner = newOwner; 212 | } 213 | 214 | uint256[50] private ______gap; 215 | } 216 | 217 | // File: openzeppelin-eth/contracts/token/ERC20/IERC20.sol 218 | 219 | pragma solidity ^0.5.0; 220 | 221 | 222 | /** 223 | * @title ERC20 interface 224 | * @dev see https://github.com/ethereum/EIPs/issues/20 225 | */ 226 | interface IERC20 { 227 | function totalSupply() external view returns (uint256); 228 | 229 | function balanceOf(address who) external view returns (uint256); 230 | 231 | function allowance(address owner, address spender) 232 | external view returns (uint256); 233 | 234 | function transfer(address to, uint256 value) external returns (bool); 235 | 236 | function approve(address spender, uint256 value) 237 | external returns (bool); 238 | 239 | function transferFrom(address from, address to, uint256 value) 240 | external returns (bool); 241 | 242 | event Transfer( 243 | address indexed from, 244 | address indexed to, 245 | uint256 value 246 | ); 247 | 248 | event Approval( 249 | address indexed owner, 250 | address indexed spender, 251 | uint256 value 252 | ); 253 | } 254 | 255 | // File: openzeppelin-eth/contracts/token/ERC20/ERC20Detailed.sol 256 | 257 | pragma solidity ^0.5.0; 258 | 259 | 260 | 261 | 262 | /** 263 | * @title ERC20Detailed token 264 | * @dev The decimals are only for visualization purposes. 265 | * All the operations are done using the smallest and indivisible token unit, 266 | * just as on Ethereum all the operations are done in wei. 267 | */ 268 | contract ERC20Detailed is Initializable, IERC20 { 269 | string private _name; 270 | string private _symbol; 271 | uint8 private _decimals; 272 | 273 | function initialize(string memory name, string memory symbol, uint8 decimals) public initializer { 274 | _name = name; 275 | _symbol = symbol; 276 | _decimals = decimals; 277 | } 278 | 279 | /** 280 | * @return the name of the token. 281 | */ 282 | function name() public view returns(string memory) { 283 | return _name; 284 | } 285 | 286 | /** 287 | * @return the symbol of the token. 288 | */ 289 | function symbol() public view returns(string memory) { 290 | return _symbol; 291 | } 292 | 293 | /** 294 | * @return the number of decimals of the token. 295 | */ 296 | function decimals() public view returns(uint8) { 297 | return _decimals; 298 | } 299 | 300 | uint256[50] private ______gap; 301 | } 302 | 303 | // File: uFragments/contracts/lib/SafeMathInt.sol 304 | 305 | /* 306 | MIT License 307 | 308 | Copyright (c) 2018 requestnetwork 309 | Copyright (c) 2018 Fragments, Inc. 310 | 311 | Permission is hereby granted, free of charge, to any person obtaining a copy 312 | of this software and associated documentation files (the "Software"), to deal 313 | in the Software without restriction, including without limitation the rights 314 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 315 | copies of the Software, and to permit persons to whom the Software is 316 | furnished to do so, subject to the following conditions: 317 | 318 | The above copyright notice and this permission notice shall be included in all 319 | copies or substantial portions of the Software. 320 | 321 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 322 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 323 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 324 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 325 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 326 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 327 | SOFTWARE. 328 | */ 329 | 330 | pragma solidity ^0.5.0; 331 | 332 | 333 | /** 334 | * @title SafeMathInt 335 | * @dev Math operations for int256 with overflow safety checks. 336 | */ 337 | library SafeMathInt { 338 | int256 private constant MIN_INT256 = int256(1) << 255; 339 | int256 private constant MAX_INT256 = ~(int256(1) << 255); 340 | 341 | /** 342 | * @dev Multiplies two int256 variables and fails on overflow. 343 | */ 344 | function mul(int256 a, int256 b) 345 | internal 346 | pure 347 | returns (int256) 348 | { 349 | int256 c = a * b; 350 | 351 | // Detect overflow when multiplying MIN_INT256 with -1 352 | require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256)); 353 | require((b == 0) || (c / b == a)); 354 | return c; 355 | } 356 | 357 | /** 358 | * @dev Division of two int256 variables and fails on overflow. 359 | */ 360 | function div(int256 a, int256 b) 361 | internal 362 | pure 363 | returns (int256) 364 | { 365 | // Prevent overflow when dividing MIN_INT256 by -1 366 | require(b != -1 || a != MIN_INT256); 367 | 368 | // Solidity already throws when dividing by 0. 369 | return a / b; 370 | } 371 | 372 | /** 373 | * @dev Subtracts two int256 variables and fails on overflow. 374 | */ 375 | function sub(int256 a, int256 b) 376 | internal 377 | pure 378 | returns (int256) 379 | { 380 | int256 c = a - b; 381 | require((b >= 0 && c <= a) || (b < 0 && c > a)); 382 | return c; 383 | } 384 | 385 | /** 386 | * @dev Adds two int256 variables and fails on overflow. 387 | */ 388 | function add(int256 a, int256 b) 389 | internal 390 | pure 391 | returns (int256) 392 | { 393 | int256 c = a + b; 394 | require((b >= 0 && c >= a) || (b < 0 && c < a)); 395 | return c; 396 | } 397 | 398 | /** 399 | * @dev Converts to absolute value, and fails on overflow. 400 | */ 401 | function abs(int256 a) 402 | internal 403 | pure 404 | returns (int256) 405 | { 406 | require(a != MIN_INT256); 407 | return a < 0 ? -a : a; 408 | } 409 | } 410 | 411 | // File: uFragments/contracts/UFragments.sol 412 | 413 | pragma solidity ^0.5.0; 414 | 415 | 416 | 417 | 418 | 419 | 420 | /** 421 | * @title uFragments ERC20 token 422 | * @dev This is part of an implementation of the uFragments Ideal Money protocol. 423 | * uFragments is a normal ERC20 token, but its supply can be adjusted by splitting and 424 | * combining tokens proportionally across all wallets. 425 | * 426 | * uFragment balances are internally represented with a hidden denomination, 'gons'. 427 | * We support splitting the currency in expansion and combining the currency on contraction by 428 | * changing the exchange rate between the hidden 'gons' and the public 'fragments'. 429 | */ 430 | contract vETH is ERC20Detailed, Ownable { 431 | // PLEASE READ BEFORE CHANGING ANY ACCOUNTING OR MATH 432 | // Anytime there is division, there is a risk of numerical instability from rounding errors. In 433 | // order to minimize this risk, we adhere to the following guidelines: 434 | // 1) The conversion rate adopted is the number of gons that equals 1 fragment. 435 | // The inverse rate must not be used--TOTAL_GONS is always the numerator and _totalSupply is 436 | // always the denominator. (i.e. If you want to convert gons to fragments instead of 437 | // multiplying by the inverse rate, you should divide by the normal rate) 438 | // 2) Gon balances converted into Fragments are always rounded down (truncated). 439 | // 440 | // We make the following guarantees: 441 | // - If address 'A' transfers x Fragments to address 'B'. A's resulting external balance will 442 | // be decreased by precisely x Fragments, and B's external balance will be precisely 443 | // increased by x Fragments. 444 | // 445 | // We do not guarantee that the sum of all balances equals the result of calling totalSupply(). 446 | // This is because, for any conversion function 'f()' that has non-zero rounding error, 447 | // f(x0) + f(x1) + ... + f(xn) is not always equal to f(x0 + x1 + ... xn). 448 | using SafeMath for uint256; 449 | using SafeMathInt for int256; 450 | 451 | event LogRebase(uint256 indexed epoch, uint256 totalSupply); 452 | event LogMonetaryPolicyUpdated(address monetaryPolicy); 453 | 454 | // Used for authentication 455 | address public monetaryPolicy; 456 | 457 | modifier onlyMonetaryPolicy() { 458 | require(msg.sender == monetaryPolicy); 459 | _; 460 | } 461 | 462 | bool private rebasePausedDeprecated; 463 | bool private tokenPausedDeprecated; 464 | 465 | modifier validRecipient(address to) { 466 | require(to != address(0x0)); 467 | require(to != address(this)); 468 | _; 469 | } 470 | 471 | uint256 private constant DECIMALS = 9; 472 | uint256 private constant MAX_UINT256 = ~uint256(0); 473 | uint256 private constant INITIAL_FRAGMENTS_SUPPLY = 10000 * 10**DECIMALS; // 10k (locked in this base contract) 474 | 475 | // TOTAL_GONS is a multiple of INITIAL_FRAGMENTS_SUPPLY so that _gonsPerFragment is an integer. 476 | // Use the highest value that fits in a uint256 for max granularity. 477 | uint256 private constant TOTAL_GONS = MAX_UINT256 - (MAX_UINT256 % INITIAL_FRAGMENTS_SUPPLY); 478 | 479 | // MAX_SUPPLY = maximum integer < (sqrt(4*TOTAL_GONS + 1) - 1) / 2 480 | uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1 481 | 482 | uint256 private _totalSupply; 483 | uint256 private _gonsPerFragment; 484 | mapping(address => uint256) private _gonBalances; 485 | 486 | // This is denominated in Fragments, because the gons-fragments conversion might change before 487 | // it's fully paid. 488 | mapping (address => mapping (address => uint256)) private _allowedFragments; 489 | 490 | mapping (address => bool) public minters; 491 | 492 | function addMinter(address _minter) public onlyOwner { 493 | minters[_minter] = true; 494 | } 495 | 496 | function removeMinter(address _minter) public onlyOwner { 497 | minters[_minter] = false; 498 | } 499 | 500 | function mint(address account, uint amount) public { 501 | require(minters[msg.sender], "!minter"); 502 | require(account != address(0x0), "ERC20: mint to the zero address"); 503 | uint256 gonValue = amount.mul(_gonsPerFragment); 504 | _totalSupply = _totalSupply.add(amount); 505 | _gonBalances[account] = _gonBalances[account].add(gonValue); 506 | emit Transfer(address(0x0), account, amount); 507 | } 508 | 509 | function burn(uint amount) public { 510 | require(msg.sender != address(0x0), "ERC20: burn from the zero address"); 511 | uint256 gonValue = amount.mul(_gonsPerFragment); 512 | _gonBalances[msg.sender] = _gonBalances[msg.sender].sub(gonValue); 513 | _totalSupply = _totalSupply.sub(amount); 514 | emit Transfer(address(0x0), msg.sender, amount); 515 | } 516 | 517 | /** 518 | * @param monetaryPolicy_ The address of the monetary policy contract to use for authentication. 519 | */ 520 | function setMonetaryPolicy(address monetaryPolicy_) 521 | external 522 | onlyOwner 523 | { 524 | monetaryPolicy = monetaryPolicy_; 525 | emit LogMonetaryPolicyUpdated(monetaryPolicy_); 526 | } 527 | 528 | /** 529 | * @dev Notifies Fragments contract about a new rebase cycle. 530 | * @param supplyDelta The number of new fragment tokens to add into circulation via expansion. 531 | * @return The total number of fragments after the supply adjustment. 532 | */ 533 | function rebase(uint256 epoch, int256 supplyDelta) 534 | external 535 | onlyMonetaryPolicy 536 | returns (uint256) 537 | { 538 | if (supplyDelta == 0) { 539 | emit LogRebase(epoch, _totalSupply); 540 | return _totalSupply; 541 | } 542 | 543 | if (supplyDelta < 0) { 544 | _totalSupply = _totalSupply.sub(uint256(supplyDelta.abs())); 545 | } else { 546 | _totalSupply = _totalSupply.add(uint256(supplyDelta)); 547 | } 548 | 549 | if (_totalSupply > MAX_SUPPLY) { 550 | _totalSupply = MAX_SUPPLY; 551 | } 552 | 553 | _gonsPerFragment = TOTAL_GONS.div(_totalSupply); 554 | 555 | // From this point forward, _gonsPerFragment is taken as the source of truth. 556 | // We recalculate a new _totalSupply to be in agreement with the _gonsPerFragment 557 | // conversion rate. 558 | // This means our applied supplyDelta can deviate from the requested supplyDelta, 559 | // but this deviation is guaranteed to be < (_totalSupply^2)/(TOTAL_GONS - _totalSupply). 560 | // 561 | // In the case of _totalSupply <= MAX_UINT128 (our current supply cap), this 562 | // deviation is guaranteed to be < 1, so we can omit this step. If the supply cap is 563 | // ever increased, it must be re-included. 564 | // _totalSupply = TOTAL_GONS.div(_gonsPerFragment) 565 | 566 | emit LogRebase(epoch, _totalSupply); 567 | return _totalSupply; 568 | } 569 | 570 | function initialize(address owner_) 571 | public 572 | initializer 573 | { 574 | ERC20Detailed.initialize("Value ETH", "vETH", uint8(DECIMALS)); 575 | Ownable.initialize(owner_); 576 | 577 | rebasePausedDeprecated = false; 578 | tokenPausedDeprecated = false; 579 | 580 | _totalSupply = INITIAL_FRAGMENTS_SUPPLY; 581 | _gonBalances[address(this)] = TOTAL_GONS; 582 | _gonsPerFragment = TOTAL_GONS.div(_totalSupply); 583 | 584 | emit Transfer(address(0x0), owner_, _totalSupply); 585 | } 586 | 587 | /** 588 | * @return The total number of fragments. 589 | */ 590 | function totalSupply() 591 | public 592 | view 593 | returns (uint256) 594 | { 595 | return _totalSupply; 596 | } 597 | 598 | /** 599 | * @param who The address to query. 600 | * @return The balance of the specified address. 601 | */ 602 | function balanceOf(address who) 603 | public 604 | view 605 | returns (uint256) 606 | { 607 | return _gonBalances[who].div(_gonsPerFragment); 608 | } 609 | 610 | /** 611 | * @dev Transfer tokens to a specified address. 612 | * @param to The address to transfer to. 613 | * @param value The amount to be transferred. 614 | * @return True on success, false otherwise. 615 | */ 616 | function transfer(address to, uint256 value) 617 | public 618 | validRecipient(to) 619 | returns (bool) 620 | { 621 | uint256 gonValue = value.mul(_gonsPerFragment); 622 | _gonBalances[msg.sender] = _gonBalances[msg.sender].sub(gonValue); 623 | _gonBalances[to] = _gonBalances[to].add(gonValue); 624 | emit Transfer(msg.sender, to, value); 625 | return true; 626 | } 627 | 628 | /** 629 | * @dev Function to check the amount of tokens that an owner has allowed to a spender. 630 | * @param owner_ The address which owns the funds. 631 | * @param spender The address which will spend the funds. 632 | * @return The number of tokens still available for the spender. 633 | */ 634 | function allowance(address owner_, address spender) 635 | public 636 | view 637 | returns (uint256) 638 | { 639 | return _allowedFragments[owner_][spender]; 640 | } 641 | 642 | /** 643 | * @dev Transfer tokens from one address to another. 644 | * @param from The address you want to send tokens from. 645 | * @param to The address you want to transfer to. 646 | * @param value The amount of tokens to be transferred. 647 | */ 648 | function transferFrom(address from, address to, uint256 value) 649 | public 650 | validRecipient(to) 651 | returns (bool) 652 | { 653 | _allowedFragments[from][msg.sender] = _allowedFragments[from][msg.sender].sub(value); 654 | 655 | uint256 gonValue = value.mul(_gonsPerFragment); 656 | _gonBalances[from] = _gonBalances[from].sub(gonValue); 657 | _gonBalances[to] = _gonBalances[to].add(gonValue); 658 | emit Transfer(from, to, value); 659 | 660 | return true; 661 | } 662 | 663 | /** 664 | * @dev Approve the passed address to spend the specified amount of tokens on behalf of 665 | * msg.sender. This method is included for ERC20 compatibility. 666 | * increaseAllowance and decreaseAllowance should be used instead. 667 | * Changing an allowance with this method brings the risk that someone may transfer both 668 | * the old and the new allowance - if they are both greater than zero - if a transfer 669 | * transaction is mined before the later approve() call is mined. 670 | * 671 | * @param spender The address which will spend the funds. 672 | * @param value The amount of tokens to be spent. 673 | */ 674 | function approve(address spender, uint256 value) 675 | public 676 | returns (bool) 677 | { 678 | _allowedFragments[msg.sender][spender] = value; 679 | emit Approval(msg.sender, spender, value); 680 | return true; 681 | } 682 | 683 | /** 684 | * @dev Increase the amount of tokens that an owner has allowed to a spender. 685 | * This method should be used instead of approve() to avoid the double approval vulnerability 686 | * described above. 687 | * @param spender The address which will spend the funds. 688 | * @param addedValue The amount of tokens to increase the allowance by. 689 | */ 690 | function increaseAllowance(address spender, uint256 addedValue) 691 | public 692 | returns (bool) 693 | { 694 | _allowedFragments[msg.sender][spender] = 695 | _allowedFragments[msg.sender][spender].add(addedValue); 696 | emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]); 697 | return true; 698 | } 699 | 700 | /** 701 | * @dev Decrease the amount of tokens that an owner has allowed to a spender. 702 | * 703 | * @param spender The address which will spend the funds. 704 | * @param subtractedValue The amount of tokens to decrease the allowance by. 705 | */ 706 | function decreaseAllowance(address spender, uint256 subtractedValue) 707 | public 708 | returns (bool) 709 | { 710 | uint256 oldValue = _allowedFragments[msg.sender][spender]; 711 | if (subtractedValue >= oldValue) { 712 | _allowedFragments[msg.sender][spender] = 0; 713 | } else { 714 | _allowedFragments[msg.sender][spender] = oldValue.sub(subtractedValue); 715 | } 716 | emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]); 717 | return true; 718 | } 719 | } 720 | -------------------------------------------------------------------------------- /contracts/YFV/vUSD.sol: -------------------------------------------------------------------------------- 1 | // File: openzeppelin-eth/contracts/math/SafeMath.sol 2 | 3 | pragma solidity ^0.5.0; 4 | 5 | 6 | /** 7 | * @title SafeMath 8 | * @dev Math operations with safety checks that revert on error 9 | */ 10 | library SafeMath { 11 | 12 | /** 13 | * @dev Multiplies two numbers, reverts on overflow. 14 | */ 15 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 16 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 17 | // benefit is lost if 'b' is also tested. 18 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 19 | if (a == 0) { 20 | return 0; 21 | } 22 | 23 | uint256 c = a * b; 24 | require(c / a == b); 25 | 26 | return c; 27 | } 28 | 29 | /** 30 | * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. 31 | */ 32 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 33 | require(b > 0); // Solidity only automatically asserts when dividing by 0 34 | uint256 c = a / b; 35 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 36 | 37 | return c; 38 | } 39 | 40 | /** 41 | * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). 42 | */ 43 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 44 | require(b <= a); 45 | uint256 c = a - b; 46 | 47 | return c; 48 | } 49 | 50 | /** 51 | * @dev Adds two numbers, reverts on overflow. 52 | */ 53 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 54 | uint256 c = a + b; 55 | require(c >= a); 56 | 57 | return c; 58 | } 59 | 60 | /** 61 | * @dev Divides two numbers and returns the remainder (unsigned integer modulo), 62 | * reverts when dividing by zero. 63 | */ 64 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 65 | require(b != 0); 66 | return a % b; 67 | } 68 | } 69 | 70 | // File: zos-lib/contracts/Initializable.sol 71 | 72 | pragma solidity >=0.5.0 <0.6.0; 73 | 74 | 75 | /** 76 | * @title Initializable 77 | * 78 | * @dev Helper contract to support initializer functions. To use it, replace 79 | * the constructor with a function that has the `initializer` modifier. 80 | * WARNING: Unlike constructors, initializer functions must be manually 81 | * invoked. This applies both to deploying an Initializable contract, as well 82 | * as extending an Initializable contract via inheritance. 83 | * WARNING: When used with inheritance, manual care must be taken to not invoke 84 | * a parent initializer twice, or ensure that all initializers are idempotent, 85 | * because this is not dealt with automatically as with constructors. 86 | */ 87 | contract Initializable { 88 | 89 | /** 90 | * @dev Indicates that the contract has been initialized. 91 | */ 92 | bool private initialized; 93 | 94 | /** 95 | * @dev Indicates that the contract is in the process of being initialized. 96 | */ 97 | bool private initializing; 98 | 99 | /** 100 | * @dev Modifier to use in the initializer function of a contract. 101 | */ 102 | modifier initializer() { 103 | require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); 104 | 105 | bool isTopLevelCall = !initializing; 106 | if (isTopLevelCall) { 107 | initializing = true; 108 | initialized = true; 109 | } 110 | 111 | _; 112 | 113 | if (isTopLevelCall) { 114 | initializing = false; 115 | } 116 | } 117 | 118 | /// @dev Returns true if and only if the function is running in the constructor 119 | function isConstructor() private view returns (bool) { 120 | // extcodesize checks the size of the code stored in an address, and 121 | // address returns the current address. Since the code is still not 122 | // deployed when running a constructor, any checks on its code size will 123 | // yield zero, making it an effective way to detect if a contract is 124 | // under construction or not. 125 | uint256 cs; 126 | assembly { cs := extcodesize(address) } 127 | return cs == 0; 128 | } 129 | 130 | // Reserved storage space to allow for layout changes in the future. 131 | uint256[50] private ______gap; 132 | } 133 | 134 | // File: openzeppelin-eth/contracts/ownership/Ownable.sol 135 | 136 | pragma solidity ^0.5.0; 137 | 138 | 139 | /** 140 | * @title Ownable 141 | * @dev The Ownable contract has an owner address, and provides basic authorization control 142 | * functions, this simplifies the implementation of "user permissions". 143 | */ 144 | contract Ownable is Initializable { 145 | address private _owner; 146 | 147 | 148 | event OwnershipRenounced(address indexed previousOwner); 149 | event OwnershipTransferred( 150 | address indexed previousOwner, 151 | address indexed newOwner 152 | ); 153 | 154 | 155 | /** 156 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 157 | * account. 158 | */ 159 | function initialize(address sender) public initializer { 160 | _owner = sender; 161 | } 162 | 163 | /** 164 | * @return the address of the owner. 165 | */ 166 | function owner() public view returns(address) { 167 | return _owner; 168 | } 169 | 170 | /** 171 | * @dev Throws if called by any account other than the owner. 172 | */ 173 | modifier onlyOwner() { 174 | require(isOwner()); 175 | _; 176 | } 177 | 178 | /** 179 | * @return true if `msg.sender` is the owner of the contract. 180 | */ 181 | function isOwner() public view returns(bool) { 182 | return msg.sender == _owner; 183 | } 184 | 185 | /** 186 | * @dev Allows the current owner to relinquish control of the contract. 187 | * @notice Renouncing to ownership will leave the contract without an owner. 188 | * It will not be possible to call the functions with the `onlyOwner` 189 | * modifier anymore. 190 | */ 191 | function renounceOwnership() public onlyOwner { 192 | emit OwnershipRenounced(_owner); 193 | _owner = address(0); 194 | } 195 | 196 | /** 197 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 198 | * @param newOwner The address to transfer ownership to. 199 | */ 200 | function transferOwnership(address newOwner) public onlyOwner { 201 | _transferOwnership(newOwner); 202 | } 203 | 204 | /** 205 | * @dev Transfers control of the contract to a newOwner. 206 | * @param newOwner The address to transfer ownership to. 207 | */ 208 | function _transferOwnership(address newOwner) internal { 209 | require(newOwner != address(0)); 210 | emit OwnershipTransferred(_owner, newOwner); 211 | _owner = newOwner; 212 | } 213 | 214 | uint256[50] private ______gap; 215 | } 216 | 217 | // File: openzeppelin-eth/contracts/token/ERC20/IERC20.sol 218 | 219 | pragma solidity ^0.5.0; 220 | 221 | 222 | /** 223 | * @title ERC20 interface 224 | * @dev see https://github.com/ethereum/EIPs/issues/20 225 | */ 226 | interface IERC20 { 227 | function totalSupply() external view returns (uint256); 228 | 229 | function balanceOf(address who) external view returns (uint256); 230 | 231 | function allowance(address owner, address spender) 232 | external view returns (uint256); 233 | 234 | function transfer(address to, uint256 value) external returns (bool); 235 | 236 | function approve(address spender, uint256 value) 237 | external returns (bool); 238 | 239 | function transferFrom(address from, address to, uint256 value) 240 | external returns (bool); 241 | 242 | event Transfer( 243 | address indexed from, 244 | address indexed to, 245 | uint256 value 246 | ); 247 | 248 | event Approval( 249 | address indexed owner, 250 | address indexed spender, 251 | uint256 value 252 | ); 253 | } 254 | 255 | // File: openzeppelin-eth/contracts/token/ERC20/ERC20Detailed.sol 256 | 257 | pragma solidity ^0.5.0; 258 | 259 | 260 | 261 | 262 | /** 263 | * @title ERC20Detailed token 264 | * @dev The decimals are only for visualization purposes. 265 | * All the operations are done using the smallest and indivisible token unit, 266 | * just as on Ethereum all the operations are done in wei. 267 | */ 268 | contract ERC20Detailed is Initializable, IERC20 { 269 | string private _name; 270 | string private _symbol; 271 | uint8 private _decimals; 272 | 273 | function initialize(string memory name, string memory symbol, uint8 decimals) public initializer { 274 | _name = name; 275 | _symbol = symbol; 276 | _decimals = decimals; 277 | } 278 | 279 | /** 280 | * @return the name of the token. 281 | */ 282 | function name() public view returns(string memory) { 283 | return _name; 284 | } 285 | 286 | /** 287 | * @return the symbol of the token. 288 | */ 289 | function symbol() public view returns(string memory) { 290 | return _symbol; 291 | } 292 | 293 | /** 294 | * @return the number of decimals of the token. 295 | */ 296 | function decimals() public view returns(uint8) { 297 | return _decimals; 298 | } 299 | 300 | uint256[50] private ______gap; 301 | } 302 | 303 | // File: uFragments/contracts/lib/SafeMathInt.sol 304 | 305 | /* 306 | MIT License 307 | 308 | Copyright (c) 2018 requestnetwork 309 | Copyright (c) 2018 Fragments, Inc. 310 | 311 | Permission is hereby granted, free of charge, to any person obtaining a copy 312 | of this software and associated documentation files (the "Software"), to deal 313 | in the Software without restriction, including without limitation the rights 314 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 315 | copies of the Software, and to permit persons to whom the Software is 316 | furnished to do so, subject to the following conditions: 317 | 318 | The above copyright notice and this permission notice shall be included in all 319 | copies or substantial portions of the Software. 320 | 321 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 322 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 323 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 324 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 325 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 326 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 327 | SOFTWARE. 328 | */ 329 | 330 | pragma solidity ^0.5.0; 331 | 332 | 333 | /** 334 | * @title SafeMathInt 335 | * @dev Math operations for int256 with overflow safety checks. 336 | */ 337 | library SafeMathInt { 338 | int256 private constant MIN_INT256 = int256(1) << 255; 339 | int256 private constant MAX_INT256 = ~(int256(1) << 255); 340 | 341 | /** 342 | * @dev Multiplies two int256 variables and fails on overflow. 343 | */ 344 | function mul(int256 a, int256 b) 345 | internal 346 | pure 347 | returns (int256) 348 | { 349 | int256 c = a * b; 350 | 351 | // Detect overflow when multiplying MIN_INT256 with -1 352 | require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256)); 353 | require((b == 0) || (c / b == a)); 354 | return c; 355 | } 356 | 357 | /** 358 | * @dev Division of two int256 variables and fails on overflow. 359 | */ 360 | function div(int256 a, int256 b) 361 | internal 362 | pure 363 | returns (int256) 364 | { 365 | // Prevent overflow when dividing MIN_INT256 by -1 366 | require(b != -1 || a != MIN_INT256); 367 | 368 | // Solidity already throws when dividing by 0. 369 | return a / b; 370 | } 371 | 372 | /** 373 | * @dev Subtracts two int256 variables and fails on overflow. 374 | */ 375 | function sub(int256 a, int256 b) 376 | internal 377 | pure 378 | returns (int256) 379 | { 380 | int256 c = a - b; 381 | require((b >= 0 && c <= a) || (b < 0 && c > a)); 382 | return c; 383 | } 384 | 385 | /** 386 | * @dev Adds two int256 variables and fails on overflow. 387 | */ 388 | function add(int256 a, int256 b) 389 | internal 390 | pure 391 | returns (int256) 392 | { 393 | int256 c = a + b; 394 | require((b >= 0 && c >= a) || (b < 0 && c < a)); 395 | return c; 396 | } 397 | 398 | /** 399 | * @dev Converts to absolute value, and fails on overflow. 400 | */ 401 | function abs(int256 a) 402 | internal 403 | pure 404 | returns (int256) 405 | { 406 | require(a != MIN_INT256); 407 | return a < 0 ? -a : a; 408 | } 409 | } 410 | 411 | // File: uFragments/contracts/UFragments.sol 412 | 413 | pragma solidity ^0.5.0; 414 | 415 | 416 | 417 | 418 | 419 | 420 | /** 421 | * @title uFragments ERC20 token 422 | * @dev This is part of an implementation of the uFragments Ideal Money protocol. 423 | * uFragments is a normal ERC20 token, but its supply can be adjusted by splitting and 424 | * combining tokens proportionally across all wallets. 425 | * 426 | * uFragment balances are internally represented with a hidden denomination, 'gons'. 427 | * We support splitting the currency in expansion and combining the currency on contraction by 428 | * changing the exchange rate between the hidden 'gons' and the public 'fragments'. 429 | */ 430 | contract vUSD is ERC20Detailed, Ownable { 431 | // PLEASE READ BEFORE CHANGING ANY ACCOUNTING OR MATH 432 | // Anytime there is division, there is a risk of numerical instability from rounding errors. In 433 | // order to minimize this risk, we adhere to the following guidelines: 434 | // 1) The conversion rate adopted is the number of gons that equals 1 fragment. 435 | // The inverse rate must not be used--TOTAL_GONS is always the numerator and _totalSupply is 436 | // always the denominator. (i.e. If you want to convert gons to fragments instead of 437 | // multiplying by the inverse rate, you should divide by the normal rate) 438 | // 2) Gon balances converted into Fragments are always rounded down (truncated). 439 | // 440 | // We make the following guarantees: 441 | // - If address 'A' transfers x Fragments to address 'B'. A's resulting external balance will 442 | // be decreased by precisely x Fragments, and B's external balance will be precisely 443 | // increased by x Fragments. 444 | // 445 | // We do not guarantee that the sum of all balances equals the result of calling totalSupply(). 446 | // This is because, for any conversion function 'f()' that has non-zero rounding error, 447 | // f(x0) + f(x1) + ... + f(xn) is not always equal to f(x0 + x1 + ... xn). 448 | using SafeMath for uint256; 449 | using SafeMathInt for int256; 450 | 451 | event LogRebase(uint256 indexed epoch, uint256 totalSupply); 452 | event LogMonetaryPolicyUpdated(address monetaryPolicy); 453 | 454 | // Used for authentication 455 | address public monetaryPolicy; 456 | 457 | modifier onlyMonetaryPolicy() { 458 | require(msg.sender == monetaryPolicy); 459 | _; 460 | } 461 | 462 | bool private rebasePausedDeprecated; 463 | bool private tokenPausedDeprecated; 464 | 465 | modifier validRecipient(address to) { 466 | require(to != address(0x0)); 467 | require(to != address(this)); 468 | _; 469 | } 470 | 471 | uint256 private constant DECIMALS = 9; 472 | uint256 private constant MAX_UINT256 = ~uint256(0); 473 | uint256 private constant INITIAL_FRAGMENTS_SUPPLY = 10 * 10**6 * 10**DECIMALS; // 10 million (locked in this base contract) 474 | 475 | // TOTAL_GONS is a multiple of INITIAL_FRAGMENTS_SUPPLY so that _gonsPerFragment is an integer. 476 | // Use the highest value that fits in a uint256 for max granularity. 477 | uint256 private constant TOTAL_GONS = MAX_UINT256 - (MAX_UINT256 % INITIAL_FRAGMENTS_SUPPLY); 478 | 479 | // MAX_SUPPLY = maximum integer < (sqrt(4*TOTAL_GONS + 1) - 1) / 2 480 | uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1 481 | 482 | uint256 private _totalSupply; 483 | uint256 private _gonsPerFragment; 484 | mapping(address => uint256) private _gonBalances; 485 | 486 | // This is denominated in Fragments, because the gons-fragments conversion might change before 487 | // it's fully paid. 488 | mapping (address => mapping (address => uint256)) private _allowedFragments; 489 | 490 | mapping (address => bool) public minters; 491 | 492 | function addMinter(address _minter) public onlyOwner { 493 | minters[_minter] = true; 494 | } 495 | 496 | function removeMinter(address _minter) public onlyOwner { 497 | minters[_minter] = false; 498 | } 499 | 500 | function mint(address account, uint amount) public { 501 | require(minters[msg.sender], "!minter"); 502 | require(account != address(0x0), "ERC20: mint to the zero address"); 503 | uint256 gonValue = amount.mul(_gonsPerFragment); 504 | _totalSupply = _totalSupply.add(amount); 505 | _gonBalances[account] = _gonBalances[account].add(gonValue); 506 | emit Transfer(address(0x0), account, amount); 507 | } 508 | 509 | function burn(uint amount) public { 510 | require(msg.sender != address(0x0), "ERC20: burn from the zero address"); 511 | uint256 gonValue = amount.mul(_gonsPerFragment); 512 | _gonBalances[msg.sender] = _gonBalances[msg.sender].sub(gonValue); 513 | _totalSupply = _totalSupply.sub(amount); 514 | emit Transfer(address(0x0), msg.sender, amount); 515 | } 516 | 517 | /** 518 | * @param monetaryPolicy_ The address of the monetary policy contract to use for authentication. 519 | */ 520 | function setMonetaryPolicy(address monetaryPolicy_) 521 | external 522 | onlyOwner 523 | { 524 | monetaryPolicy = monetaryPolicy_; 525 | emit LogMonetaryPolicyUpdated(monetaryPolicy_); 526 | } 527 | 528 | /** 529 | * @dev Notifies Fragments contract about a new rebase cycle. 530 | * @param supplyDelta The number of new fragment tokens to add into circulation via expansion. 531 | * @return The total number of fragments after the supply adjustment. 532 | */ 533 | function rebase(uint256 epoch, int256 supplyDelta) 534 | external 535 | onlyMonetaryPolicy 536 | returns (uint256) 537 | { 538 | if (supplyDelta == 0) { 539 | emit LogRebase(epoch, _totalSupply); 540 | return _totalSupply; 541 | } 542 | 543 | if (supplyDelta < 0) { 544 | _totalSupply = _totalSupply.sub(uint256(supplyDelta.abs())); 545 | } else { 546 | _totalSupply = _totalSupply.add(uint256(supplyDelta)); 547 | } 548 | 549 | if (_totalSupply > MAX_SUPPLY) { 550 | _totalSupply = MAX_SUPPLY; 551 | } 552 | 553 | _gonsPerFragment = TOTAL_GONS.div(_totalSupply); 554 | 555 | // From this point forward, _gonsPerFragment is taken as the source of truth. 556 | // We recalculate a new _totalSupply to be in agreement with the _gonsPerFragment 557 | // conversion rate. 558 | // This means our applied supplyDelta can deviate from the requested supplyDelta, 559 | // but this deviation is guaranteed to be < (_totalSupply^2)/(TOTAL_GONS - _totalSupply). 560 | // 561 | // In the case of _totalSupply <= MAX_UINT128 (our current supply cap), this 562 | // deviation is guaranteed to be < 1, so we can omit this step. If the supply cap is 563 | // ever increased, it must be re-included. 564 | // _totalSupply = TOTAL_GONS.div(_gonsPerFragment) 565 | 566 | emit LogRebase(epoch, _totalSupply); 567 | return _totalSupply; 568 | } 569 | 570 | function initialize(address owner_) 571 | public 572 | initializer 573 | { 574 | ERC20Detailed.initialize("Value USD", "vUSD", uint8(DECIMALS)); 575 | Ownable.initialize(owner_); 576 | 577 | rebasePausedDeprecated = false; 578 | tokenPausedDeprecated = false; 579 | 580 | _totalSupply = INITIAL_FRAGMENTS_SUPPLY; 581 | _gonBalances[address(this)] = TOTAL_GONS; 582 | _gonsPerFragment = TOTAL_GONS.div(_totalSupply); 583 | 584 | emit Transfer(address(0x0), owner_, _totalSupply); 585 | } 586 | 587 | /** 588 | * @return The total number of fragments. 589 | */ 590 | function totalSupply() 591 | public 592 | view 593 | returns (uint256) 594 | { 595 | return _totalSupply; 596 | } 597 | 598 | /** 599 | * @param who The address to query. 600 | * @return The balance of the specified address. 601 | */ 602 | function balanceOf(address who) 603 | public 604 | view 605 | returns (uint256) 606 | { 607 | return _gonBalances[who].div(_gonsPerFragment); 608 | } 609 | 610 | /** 611 | * @dev Transfer tokens to a specified address. 612 | * @param to The address to transfer to. 613 | * @param value The amount to be transferred. 614 | * @return True on success, false otherwise. 615 | */ 616 | function transfer(address to, uint256 value) 617 | public 618 | validRecipient(to) 619 | returns (bool) 620 | { 621 | uint256 gonValue = value.mul(_gonsPerFragment); 622 | _gonBalances[msg.sender] = _gonBalances[msg.sender].sub(gonValue); 623 | _gonBalances[to] = _gonBalances[to].add(gonValue); 624 | emit Transfer(msg.sender, to, value); 625 | return true; 626 | } 627 | 628 | /** 629 | * @dev Function to check the amount of tokens that an owner has allowed to a spender. 630 | * @param owner_ The address which owns the funds. 631 | * @param spender The address which will spend the funds. 632 | * @return The number of tokens still available for the spender. 633 | */ 634 | function allowance(address owner_, address spender) 635 | public 636 | view 637 | returns (uint256) 638 | { 639 | return _allowedFragments[owner_][spender]; 640 | } 641 | 642 | /** 643 | * @dev Transfer tokens from one address to another. 644 | * @param from The address you want to send tokens from. 645 | * @param to The address you want to transfer to. 646 | * @param value The amount of tokens to be transferred. 647 | */ 648 | function transferFrom(address from, address to, uint256 value) 649 | public 650 | validRecipient(to) 651 | returns (bool) 652 | { 653 | _allowedFragments[from][msg.sender] = _allowedFragments[from][msg.sender].sub(value); 654 | 655 | uint256 gonValue = value.mul(_gonsPerFragment); 656 | _gonBalances[from] = _gonBalances[from].sub(gonValue); 657 | _gonBalances[to] = _gonBalances[to].add(gonValue); 658 | emit Transfer(from, to, value); 659 | 660 | return true; 661 | } 662 | 663 | /** 664 | * @dev Approve the passed address to spend the specified amount of tokens on behalf of 665 | * msg.sender. This method is included for ERC20 compatibility. 666 | * increaseAllowance and decreaseAllowance should be used instead. 667 | * Changing an allowance with this method brings the risk that someone may transfer both 668 | * the old and the new allowance - if they are both greater than zero - if a transfer 669 | * transaction is mined before the later approve() call is mined. 670 | * 671 | * @param spender The address which will spend the funds. 672 | * @param value The amount of tokens to be spent. 673 | */ 674 | function approve(address spender, uint256 value) 675 | public 676 | returns (bool) 677 | { 678 | _allowedFragments[msg.sender][spender] = value; 679 | emit Approval(msg.sender, spender, value); 680 | return true; 681 | } 682 | 683 | /** 684 | * @dev Increase the amount of tokens that an owner has allowed to a spender. 685 | * This method should be used instead of approve() to avoid the double approval vulnerability 686 | * described above. 687 | * @param spender The address which will spend the funds. 688 | * @param addedValue The amount of tokens to increase the allowance by. 689 | */ 690 | function increaseAllowance(address spender, uint256 addedValue) 691 | public 692 | returns (bool) 693 | { 694 | _allowedFragments[msg.sender][spender] = 695 | _allowedFragments[msg.sender][spender].add(addedValue); 696 | emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]); 697 | return true; 698 | } 699 | 700 | /** 701 | * @dev Decrease the amount of tokens that an owner has allowed to a spender. 702 | * 703 | * @param spender The address which will spend the funds. 704 | * @param subtractedValue The amount of tokens to decrease the allowance by. 705 | */ 706 | function decreaseAllowance(address spender, uint256 subtractedValue) 707 | public 708 | returns (bool) 709 | { 710 | uint256 oldValue = _allowedFragments[msg.sender][spender]; 711 | if (subtractedValue >= oldValue) { 712 | _allowedFragments[msg.sender][spender] = 0; 713 | } else { 714 | _allowedFragments[msg.sender][spender] = oldValue.sub(subtractedValue); 715 | } 716 | emit Approval(msg.sender, spender, _allowedFragments[msg.sender][spender]); 717 | return true; 718 | } 719 | } 720 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ValueDefi smartcontract", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "compile": "truffle compile", 8 | "testrpc": "ganache-cli --deterministic --gasLimit 10000000", 9 | "test": "truffle test", 10 | "test:verbose": "VERBOSE=true truffle test", 11 | "coverage": "yarn solidity-coverage", 12 | "lint": "eslint .", 13 | "lint:contracts": "solhint contracts/*.sol", 14 | "flat:contracts": "sol-merger \"./contracts/VALUE/*.sol\" ./build" 15 | }, 16 | "dependencies": { 17 | "@openzeppelin/contracts": "^3.1.0", 18 | "@openzeppelin/test-helpers": "^0.5.6", 19 | "sleep": "^6.3.0", 20 | "truffle": "^5.1.41", 21 | "truffle-flattener": "^1.4.4", 22 | "web3-utils": "^1.2.11" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/Timelock.test.js: -------------------------------------------------------------------------------- 1 | const {expectRevert, time, ether} = require('@openzeppelin/test-helpers'); 2 | const ethers = require('ethers'); 3 | const ValueLiquidityToken = artifacts.require('ValueLiquidityToken'); 4 | const ValueMasterPool = artifacts.require('ValueMasterPool'); 5 | const MockERC20 = artifacts.require('MockERC20'); 6 | const Timelock = artifacts.require('Timelock'); 7 | 8 | function encodeParameters(types, values) { 9 | const abi = new ethers.utils.AbiCoder(); 10 | return abi.encode(types, values); 11 | } 12 | 13 | contract('Timelock', ([alice, bob, carol, dev, minter]) => { 14 | beforeEach(async () => { 15 | this.yfv = await MockERC20.new('YFValue', 'YFV', ether('4000000'), {from: alice}); 16 | this.value = await ValueLiquidityToken.new(this.yfv.address, ether('2370000'), {from: alice}); 17 | this.timelock = await Timelock.new(bob, '86400', {from: alice}); 18 | }); 19 | 20 | it('should not allow non-owner to do operation', async () => { 21 | await this.value.setGovernance(this.timelock.address, {from: alice}); 22 | await expectRevert( 23 | this.value.setGovernance(carol, {from: alice}), 24 | 'Ownable: caller is not the owner', 25 | ); 26 | await expectRevert( 27 | this.value.setGovernance(carol, {from: bob}), 28 | 'Ownable: caller is not the owner', 29 | ); 30 | await expectRevert( 31 | this.timelock.queueTransaction( 32 | this.value.address, '0', 'mint(address,uint256)', 33 | encodeParameters(['address', 'uint256'], [carol, 0]), 34 | (await time.latest()).add(time.duration.days(4)), 35 | {from: alice}, 36 | ), 37 | 'Timelock.json::queueTransaction: Call must come from admin.', 38 | ); 39 | }); 40 | 41 | it('should do the timelock thing', async () => { 42 | await this.value.transferOwnership(this.timelock.address, {from: alice}); 43 | const eta = (await time.latest()).add(time.duration.days(4)); 44 | await this.timelock.queueTransaction( 45 | this.value.address, '0', 'transferOwnership(address)', 46 | encodeParameters(['address'], [carol]), eta, {from: bob}, 47 | ); 48 | await time.increase(time.duration.days(1)); 49 | await expectRevert( 50 | this.timelock.executeTransaction( 51 | this.value.address, '0', 'transferOwnership(address)', 52 | encodeParameters(['address'], [carol]), eta, {from: bob}, 53 | ), 54 | "Timelock.json::executeTransaction: Transaction hasn't surpassed time lock.", 55 | ); 56 | await time.increase(time.duration.days(4)); 57 | await this.timelock.executeTransaction( 58 | this.value.address, '0', 'transferOwnership(address)', 59 | encodeParameters(['address'], [carol]), eta, {from: bob}, 60 | ); 61 | assert.equal((await this.value.owner()).valueOf(), carol); 62 | }); 63 | 64 | it('should also work with ValueMasterPool', async () => { 65 | this.lp1 = await MockERC20.new('LPToken', 'LP', '10000000000', {from: minter}); 66 | this.lp2 = await MockERC20.new('LPToken', 'LP', '10000000000', {from: minter}); 67 | this.chef = await ValueMasterPool.new(this.value.address, '1000', '0', {from: alice}); 68 | await this.value.transferOwnership(this.chef.address, {from: alice}); 69 | await this.chef.add('100', this.lp1.address, true, 0); 70 | await this.chef.transferOwnership(this.timelock.address, {from: alice}); 71 | const eta = (await time.latest()).add(time.duration.days(4)); 72 | await this.timelock.queueTransaction( 73 | this.chef.address, '0', 'set(uint256,uint256,bool)', 74 | encodeParameters(['uint256', 'uint256', 'bool'], ['0', '200', false]), eta, {from: bob}, 75 | ); 76 | await this.timelock.queueTransaction( 77 | this.chef.address, '0', 'add(uint256,address,bool,uint256)', 78 | encodeParameters(['uint256', 'address', 'bool', 'uint256'], ['100', this.lp2.address, false, 0]), eta, {from: bob}, 79 | ); 80 | await time.increase(time.duration.days(4)); 81 | await this.timelock.executeTransaction( 82 | this.chef.address, '0', 'set(uint256,uint256,bool)', 83 | encodeParameters(['uint256', 'uint256', 'bool'], ['0', '200', false]), eta, {from: bob}, 84 | ); 85 | await this.timelock.executeTransaction( 86 | this.chef.address, '0', 'add(uint256,address,bool,uint256)', 87 | encodeParameters(['uint256', 'address', 'bool', 'uint256'], ['100', this.lp2.address, false, 0]), eta, {from: bob}, 88 | ); 89 | console.log(encodeParameters(['uint256', 'address', 'bool', 'uint256'], ['3000', '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', false, 0])); 90 | assert.equal((await this.chef.poolInfo('0')).valueOf().allocPoint, '200'); 91 | assert.equal((await this.chef.totalAllocPoint()).valueOf(), '300'); 92 | assert.equal((await this.chef.poolLength()).valueOf(), '2'); 93 | }); 94 | }); 95 | -------------------------------------------------------------------------------- /test/ValueLiquidityToken.test.js: -------------------------------------------------------------------------------- 1 | const {expectRevert, ether} = require('@openzeppelin/test-helpers'); 2 | const ValueLiquidityToken = artifacts.require('ValueLiquidityToken'); 3 | const MockERC20 = artifacts.require('MockERC20'); 4 | 5 | contract('ValueLiquidityToken', ([alice, bob, carol]) => { 6 | beforeEach(async () => { 7 | this.yfv = await MockERC20.new('YFValue', 'YFV', ether('4000000'), {from: alice}); 8 | this.value = await ValueLiquidityToken.new(this.yfv.address, ether('2370000'), {from: alice}); 9 | }); 10 | 11 | it('should have correct name and symbol and decimal', async () => { 12 | const name = await this.value.name(); 13 | const symbol = await this.value.symbol(); 14 | const decimals = await this.value.decimals(); 15 | assert.equal(name.valueOf(), 'Value Liquidity'); 16 | assert.equal(symbol.valueOf(), 'VALUE'); 17 | assert.equal(decimals.valueOf(), '18'); 18 | }); 19 | 20 | it('should only allow minters to mint token', async () => { 21 | await this.value.mint(alice, ether('100'), {from: alice}); 22 | await this.value.addMinter(bob, {from: alice}); 23 | await this.value.mint(carol, ether('1000'), {from: bob}); 24 | await this.value.removeMinter(bob, {from: alice}); 25 | await expectRevert( 26 | this.value.mint(carol, ether('1000'), {from: bob}), 27 | '!governance && !minter', 28 | ); 29 | const totalSupply = await this.value.totalSupply(); 30 | const aliceBal = await this.value.balanceOf(alice); 31 | const bobBal = await this.value.balanceOf(bob); 32 | const carolBal = await this.value.balanceOf(carol); 33 | assert.equal(totalSupply.valueOf(), String(ether('1100'))); 34 | assert.equal(aliceBal.valueOf(), String(ether('100'))); 35 | assert.equal(bobBal.valueOf(), '0'); 36 | assert.equal(carolBal.valueOf(), String(ether('1000'))); 37 | }); 38 | 39 | it('should deposit and withdraw not over the locked yfv', async () => { 40 | await this.yfv.approve(this.value.address, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', {from: alice}); 41 | await this.value.deposit(ether('2000'), {from: alice}); 42 | assert.equal(String(await this.yfv.balanceOf(alice)), String(ether('3998000'))); 43 | assert.equal(String(await this.yfv.balanceOf(this.value.address)), String(ether('2000'))); 44 | await this.yfv.transfer(bob, ether('1000'), {from: alice}); 45 | await expectRevert( 46 | this.value.deposit(ether('1000'), {from: bob}), 47 | 'ERC20: transfer amount exceeds allowance', 48 | ); 49 | await this.value.mint(bob, ether('10000'), {from: alice}); 50 | await this.value.approve(this.value.address, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', {from: bob}); 51 | await this.value.withdraw(ether('1000'), {from: bob}); 52 | assert.equal(String(await this.yfv.balanceOf(bob)), String(ether('2000'))); 53 | assert.equal(String(await this.value.balanceOf(bob)), String(ether('9000'))); 54 | assert.equal(String(await this.yfv.balanceOf(this.value.address)), String(ether('1000'))); 55 | await this.value.deposit(ether('9000'), {from: alice}); 56 | await expectRevert( 57 | this.value.withdraw(ether('9001'), {from: bob}), 58 | 'ERC20: burn amount exceeds balance', 59 | ); 60 | await this.value.approve(this.value.address, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', {from: alice}); 61 | this.value.withdraw(ether('1500'), {from: alice}); 62 | assert.equal(String(await this.value.yfvLockedBalance()), String(ether('8500'))); 63 | await expectRevert( 64 | this.value.withdraw(ether('9000'), {from: bob}), 65 | 'There is not enough locked YFV to withdraw', 66 | ); 67 | }); 68 | 69 | it('set new cap should not over totalSupply minus yfvLockedBalance', async () => { 70 | assert.equal(String(await this.value.cap()), String(ether('2370000'))); 71 | await this.value.mint(bob, ether('2370000'), {from: alice}); 72 | await expectRevert( 73 | this.value.mint(bob, ether('1'), {from: alice}), 74 | 'ERC20Capped: cap exceeded', 75 | ); 76 | assert.equal(String(await this.value.totalSupply()), String(ether('2370000'))); 77 | await this.yfv.approve(this.value.address, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', {from: alice}); 78 | await this.value.deposit(ether('1000000'), {from: alice}); 79 | assert.equal(String(await this.yfv.balanceOf(alice)), String(ether('3000000'))); 80 | assert.equal(String(await this.value.balanceOf(alice)), String(ether('1000000'))); 81 | assert.equal(String(await this.yfv.balanceOf(this.value.address)), String(ether('1000000'))); 82 | await this.value.setCap(ether('3000000'), {from: alice}); 83 | assert.equal(String(await this.value.cap()), String(ether('3000000'))); 84 | await this.value.mint(bob, ether('630000'), {from: alice}); 85 | assert.equal(String(await this.value.totalSupply()), String(ether('4000000'))); 86 | await expectRevert( 87 | this.value.setCap(ether('2900000'), {from: alice}), 88 | '_cap (plus yfvLockedBalance) is below current supply', 89 | ); 90 | await this.value.setCap(ether('3100000'), {from: alice}); 91 | }); 92 | 93 | it('should supply token transfers properly', async () => { 94 | await this.value.mint(alice, '100', {from: alice}); 95 | await this.value.mint(bob, '1000', {from: alice}); 96 | await this.value.transfer(carol, '10', {from: alice}); 97 | await this.value.transfer(carol, '100', {from: bob}); 98 | const totalSupply = await this.value.totalSupply(); 99 | const aliceBal = await this.value.balanceOf(alice); 100 | const bobBal = await this.value.balanceOf(bob); 101 | const carolBal = await this.value.balanceOf(carol); 102 | assert.equal(totalSupply.valueOf(), '1100'); 103 | assert.equal(aliceBal.valueOf(), '90'); 104 | assert.equal(bobBal.valueOf(), '900'); 105 | assert.equal(carolBal.valueOf(), '110'); 106 | }); 107 | 108 | it('should fail if you try to do bad transfers', async () => { 109 | await this.value.mint(alice, '100', {from: alice}); 110 | await expectRevert( 111 | this.value.transfer(carol, '110', {from: alice}), 112 | 'ERC20: transfer amount exceeds balance', 113 | ); 114 | await expectRevert( 115 | this.value.transfer(carol, '1', {from: bob}), 116 | 'ERC20: transfer amount exceeds balance', 117 | ); 118 | }); 119 | 120 | it('test governanceRecoverUnsupported', async () => { 121 | this.anErc20Token = await MockERC20.new('TokenA', 'A', ether('10000'), {from: bob}); 122 | await this.anErc20Token.transfer(this.value.address, ether('1000'), {from: bob}); 123 | assert.equal(String(await this.anErc20Token.balanceOf(bob)), String(ether('9000'))); 124 | assert.equal(String(await this.anErc20Token.balanceOf(this.value.address)), String(ether('1000'))); 125 | await this.value.governanceRecoverUnsupported(this.anErc20Token.address, carol, ether('1000')); 126 | assert.equal(String(await this.anErc20Token.balanceOf(carol)), String(ether('1000'))); 127 | assert.equal(String(await this.anErc20Token.balanceOf(this.value.address)), String(ether('0'))); 128 | await this.yfv.approve(this.value.address, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', {from: alice}); 129 | await this.value.deposit(ether('1000'), {from: alice}); 130 | assert.equal(String(await this.yfv.balanceOf(this.value.address)), String(ether('1000'))); 131 | await expectRevert( 132 | this.value.governanceRecoverUnsupported(this.yfv.address, carol, ether('1000'), {from: alice}), 133 | 'cant withdraw more then stuck amount', 134 | ); 135 | await this.yfv.transfer(this.value.address, ether('1000'), {from: alice}); 136 | assert.equal(String(await this.yfv.balanceOf(this.value.address)), String(ether('2000'))); 137 | await this.value.governanceRecoverUnsupported(this.yfv.address, carol, ether('1000'), {from: alice}); 138 | assert.equal(String(await this.yfv.balanceOf(carol)), String(ether('1000'))); 139 | }); 140 | }); 141 | -------------------------------------------------------------------------------- /test/ValueMasterPool.test.js: -------------------------------------------------------------------------------- 1 | const {expectRevert, time} = require('@openzeppelin/test-helpers'); 2 | 3 | const ValueLiquidityToken = artifacts.require('ValueLiquidityToken'); 4 | const ValueMasterPoolTest = artifacts.require('ValueMasterPool'); 5 | const YFVReferral = artifacts.require('YFVReferral'); 6 | const MockERC20 = artifacts.require('MockERC20'); 7 | 8 | const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000'; 9 | 10 | contract('ValueMasterPool', ([alice, bob, carol, insuranceFund, minter]) => { 11 | beforeEach(async () => { 12 | this.yfv = await MockERC20.new('YFValue', 'YFV', 40000000, {from: alice}); 13 | this.value = await ValueLiquidityToken.new(this.yfv.address, 2370000, {from: alice}); 14 | await this.yfv.approve(this.value.address, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', {from: alice}); 15 | await this.value.deposit(20000000, {from: alice}); 16 | }); 17 | 18 | it('should set correct state variables', async () => { 19 | this.masterPool = await ValueMasterPoolTest.new(this.value.address, insuranceFund, '1000', '0', {from: alice}); 20 | await this.value.addMinter(this.masterPool.address, {from: alice}); 21 | const value = await this.masterPool.value(); 22 | const insuranceFundAddr = await this.masterPool.insuranceFundAddr(); 23 | const governance = await this.value.governance(); 24 | assert.equal(value.valueOf(), this.value.address); 25 | assert.equal(insuranceFundAddr.valueOf(), insuranceFund); 26 | assert.equal(governance.valueOf(), alice); 27 | }); 28 | 29 | it('should allow insuranceFund and only insuranceFund to update insuranceFund', async () => { 30 | this.masterPool = await ValueMasterPoolTest.new(this.value.address, insuranceFund, '1000', '0', {from: alice}); 31 | assert.equal((await this.masterPool.insuranceFundAddr()).valueOf(), insuranceFund); 32 | await expectRevert(this.masterPool.setInsuranceFundAddr(bob, { from: bob }), 'insuranceFund: wut?'); 33 | await this.masterPool.setInsuranceFundAddr(bob, { from: insuranceFund }); 34 | assert.equal((await this.masterPool.insuranceFundAddr()).valueOf(), bob); 35 | await this.masterPool.setInsuranceFundAddr(alice, { from: bob }); 36 | assert.equal((await this.masterPool.insuranceFundAddr()).valueOf(), alice); 37 | }) 38 | 39 | it('test should give out VALUEs only after farming time', async () => { 40 | this.masterPool = await ValueMasterPoolTest.new(this.value.address, insuranceFund, '10', '50', {from: alice}); 41 | this.ref = await YFVReferral.new({from: alice}); 42 | await this.ref.setAdminStatus(this.masterPool.address, true, {from: alice}); 43 | await this.masterPool.setRewardReferral(this.ref.address, {from: alice}); 44 | console.log('startBlock=%s', String(await this.masterPool.startBlock().valueOf())); 45 | console.log('valuePerBlock=%s', String(await this.masterPool.valuePerBlock().valueOf())); 46 | console.log('totalSupply(VALUE)=%s', String(await this.value.totalSupply().valueOf())); 47 | await this.value.addMinter(this.masterPool.address, {from: alice}); 48 | this.lp = await MockERC20.new('LPToken', 'LP', '10000000000', {from: minter}); 49 | await this.lp.transfer(alice, '1000', {from: minter}); 50 | await this.lp.transfer(bob, '1000', {from: minter}); 51 | await this.lp.transfer(carol, '1000', {from: minter}); 52 | await this.masterPool.add('100', this.lp.address, true, 0); 53 | // console.log('init: pool(0)=%s', JSON.stringify(await this.masterPool.poolInfo(0))); 54 | await this.lp.approve(this.masterPool.address, '1000', {from: bob}); 55 | await this.lp.approve(this.masterPool.address, '1000', {from: carol}); 56 | await this.masterPool.deposit(0, '100', carol, {from: bob}); 57 | // console.log('bob deposit: pool(0)=%s', JSON.stringify(await this.masterPool.poolInfo(0))); 58 | await expectRevert( 59 | this.masterPool.deposit(0, '100', carol, {from: carol}), 60 | 'You cannot refer yourself', 61 | ); 62 | // await this.masterPool.deposit(0, '100', ADDRESS_ZERO, {from: carol}); 63 | // console.log('carol deposit: pool(0)=%s', JSON.stringify(await this.masterPool.poolInfo(0))); 64 | assert.equal((await this.value.balanceOf(bob)).valueOf(), '0'); 65 | assert.equal((await this.value.balanceOf(carol)).valueOf(), '0'); 66 | 67 | for (let i = 0; i < 5; i++) { 68 | console.log('block: %d', 50 + i * 10); 69 | await time.advanceBlockTo(50 + i * 10); 70 | await this.masterPool.deposit(0, '0', ADDRESS_ZERO, {from: bob}); 71 | // await this.masterPool.deposit(0, '0', ADDRESS_ZERO, {from: carol}); 72 | console.log('--> balanceOf(bob)=%s', String(await this.value.balanceOf(bob)).valueOf()); 73 | console.log('--> balanceOf(carol)=%s', String(await this.value.balanceOf(carol)).valueOf()); 74 | console.log('--> balanceOf(insuranceFund)=%s', String(await this.value.balanceOf(insuranceFund)).valueOf()); 75 | console.log('--> totalSupply(VALUE)=%s', String(await this.value.totalSupply().valueOf())); 76 | } 77 | }); 78 | 79 | it('test should update totalAllocPoint only after pool started', async () => { 80 | this.masterPool = await ValueMasterPoolTest.new(this.value.address, insuranceFund, '1', '300', {from: alice}); 81 | this.ref = await YFVReferral.new({from: alice}); 82 | await this.ref.setAdminStatus(this.masterPool.address, true, {from: alice}); 83 | await this.masterPool.setRewardReferral(this.ref.address, {from: alice}); 84 | await this.value.addMinter(this.masterPool.address, {from: alice}); 85 | this.lp = await MockERC20.new('LPToken', 'LP', '10000000000', {from: minter}); 86 | await this.lp.transfer(alice, '1000', {from: minter}); 87 | await this.lp.transfer(bob, '1000', {from: minter}); 88 | await this.lp.transfer(carol, '1000', {from: minter}); 89 | await this.lp.approve(this.masterPool.address, '1000', {from: bob}); 90 | await this.lp.approve(this.masterPool.address, '1000', {from: carol}); 91 | this.lp2 = await MockERC20.new('LPToken2', 'LP2', '10000000000', {from: minter}); 92 | await this.lp2.transfer(alice, '1000', {from: minter}); 93 | await this.lp2.transfer(bob, '1000', {from: minter}); 94 | await this.lp2.transfer(carol, '1000', {from: minter}); 95 | await this.lp2.approve(this.masterPool.address, '1000', {from: bob}); 96 | await this.lp2.approve(this.masterPool.address, '1000', {from: carol}); 97 | this.lp3 = await MockERC20.new('LPToken3', 'LP3', '10000000000', {from: minter}); 98 | await this.lp3.transfer(alice, '1000', {from: minter}); 99 | await this.lp3.transfer(bob, '1000', {from: minter}); 100 | await this.lp3.transfer(carol, '1000', {from: minter}); 101 | await this.lp3.approve(this.masterPool.address, '1000', {from: bob}); 102 | await this.lp3.approve(this.masterPool.address, '1000', {from: carol}); 103 | await this.masterPool.add('100', this.lp.address, true, 200); 104 | await this.masterPool.add('100', this.lp2.address, true, 400); 105 | await this.masterPool.deposit(0, '100', carol, {from: bob}); 106 | await this.masterPool.deposit(1, '100', ADDRESS_ZERO, {from: carol}); 107 | assert.equal((await this.value.balanceOf(bob)).valueOf(), '0'); 108 | assert.equal((await this.value.balanceOf(carol)).valueOf(), '0'); 109 | for (let i = 1; i <= 15; i++) { 110 | console.log('block: %d', 100 + i * 50); 111 | await time.advanceBlockTo(100 + i * 50); 112 | console.log('--> stakingPower(0, bob)=%s', String(await this.masterPool.stakingPower(0, bob)).valueOf()); 113 | console.log('--> stakingPower(1, carol)=%s', String(await this.masterPool.stakingPower(1, carol)).valueOf()); 114 | await this.masterPool.deposit(0, '0', ADDRESS_ZERO, {from: bob}); 115 | await this.masterPool.deposit(1, '0', ADDRESS_ZERO, {from: carol}); 116 | if (i == 4) { 117 | // update pool 118 | console.log('--> UPDATE POOL 2'); 119 | await this.masterPool.set(1, '50', true); 120 | } 121 | if (i == 5) { 122 | // open another late pool 123 | console.log('--> OPEN POOL 3'); 124 | await this.masterPool.add('1000', this.lp3.address, true, 450); 125 | await this.masterPool.deposit(2, '100', ADDRESS_ZERO, {from: carol}); 126 | console.log('--> UPDATE POOL 1'); 127 | await this.masterPool.set(0, '0', true); 128 | } 129 | if (i > 5) await this.masterPool.deposit(2, '0', ADDRESS_ZERO, {from: carol}); 130 | console.log('--> totalAllocPoint=%s', String(await this.masterPool.totalAllocPoint()).valueOf()); 131 | // console.log('--> pool[0]=%s', JSON.stringify(await this.masterPool.poolInfo(0))); 132 | // console.log('--> pool[1]=%s', JSON.stringify(await this.masterPool.poolInfo(1))); 133 | console.log('--> balanceOf(bob)=%s', String(await this.value.balanceOf(bob)).valueOf()); 134 | console.log('--> balanceOf(carol)=%s', String(await this.value.balanceOf(carol)).valueOf()); 135 | console.log('--> balanceOf(insuranceFund)=%s', String(await this.value.balanceOf(insuranceFund)).valueOf()); 136 | console.log('--> totalSupply(VALUE)=%s', String(await this.value.totalSupply().valueOf())); 137 | } 138 | }); 139 | }); 140 | -------------------------------------------------------------------------------- /test/update_allocPoints.test.js: -------------------------------------------------------------------------------- 1 | const {expectRevert, time} = require('@openzeppelin/test-helpers'); 2 | 3 | const ValueLiquidityToken = artifacts.require('ValueLiquidityToken'); 4 | const ValueMasterPool = artifacts.require('ValueMasterPool'); 5 | const YFVReferral = artifacts.require('YFVReferral'); 6 | const MockERC20 = artifacts.require('MockERC20'); 7 | 8 | const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000'; 9 | 10 | contract('ValueMasterPool', ([alice, bob, carol, insuranceFund, minter]) => { 11 | beforeEach(async () => { 12 | this.yfv = await MockERC20.new('YFValue', 'YFV', 40000000, {from: alice}); 13 | this.value = await ValueLiquidityToken.new(this.yfv.address, 2370000, {from: alice}); 14 | await this.yfv.approve(this.value.address, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', {from: alice}); 15 | await this.value.deposit(20000000, {from: alice}); 16 | }); 17 | 18 | it('test should update reward correctly after updating allocPoints', async () => { 19 | this.masterPool = await ValueMasterPool.new(this.value.address, insuranceFund, '10', '0', {from: alice}); 20 | await this.value.addMinter(this.masterPool.address, {from: alice}); 21 | this.lp = await MockERC20.new('LPToken', 'LP', '10000000000', {from: minter}); 22 | this.lp2 = await MockERC20.new('LPToken2', 'LP2', '10000000000', {from: minter}); 23 | await this.lp.transfer(alice, '1000', {from: minter}); 24 | await this.lp.transfer(bob, '1000', {from: minter}); 25 | await this.lp.transfer(carol, '1000', {from: minter}); 26 | await this.lp2.transfer(alice, '1000', {from: minter}); 27 | await this.lp2.transfer(bob, '1000', {from: minter}); 28 | await this.lp2.transfer(carol, '1000', {from: minter}); 29 | await this.masterPool.add('1000', this.lp.address, true, 0); 30 | await this.masterPool.add('1000', this.lp2.address, true, 0); 31 | await this.lp.approve(this.masterPool.address, '1000', {from: bob}); 32 | await this.lp.approve(this.masterPool.address, '1000', {from: carol}); 33 | await this.lp2.approve(this.masterPool.address, '1000', {from: bob}); 34 | await this.lp2.approve(this.masterPool.address, '1000', {from: carol}); 35 | await this.masterPool.deposit(0, '100', carol, {from: bob}); 36 | await this.masterPool.deposit(0, '1', bob, {from: carol}); 37 | await this.masterPool.deposit(1, '100', bob, {from: carol}); 38 | for (let i = 1; i <= 5; i++) { 39 | await time.advanceBlock(); 40 | console.log('latestBlock=%s', await time.latestBlock()); 41 | console.log('--> pendingValue(0, bob)=%s', String(await this.masterPool.pendingValue(0, bob))); 42 | console.log('--> pendingValue(1, carol)=%s', String(await this.masterPool.pendingValue(1, carol))); 43 | } 44 | console.log('========== TURN OFF POOL 0'); 45 | await this.masterPool.deposit(0, '0', ADDRESS_ZERO, {from: carol}); 46 | console.log('--> pool(0)=%s', JSON.stringify(await this.masterPool.poolInfo(0))); 47 | await this.masterPool.set(0, '0', false); 48 | // await this.masterPool.setValuePerBlock(100); 49 | // await this.masterPool.massUpdatePools(); 50 | console.log('--> pool(0)=%s', JSON.stringify(await this.masterPool.poolInfo(0))); 51 | // await this.masterPool.deposit(0, '0', ADDRESS_ZERO, {from: bob}); 52 | // await this.masterPool.deposit(1, '0', ADDRESS_ZERO, {from: carol}); 53 | console.log('--> balanceOf(bob)=%s', String(await this.value.balanceOf(bob)).valueOf()); 54 | console.log('--> balanceOf(carol)=%s', String(await this.value.balanceOf(carol)).valueOf()); 55 | for (let i = 1; i <= 5; i++) { 56 | await time.advanceBlock(); 57 | console.log('latestBlock=%s', await time.latestBlock()); 58 | console.log('--> pendingValue(0, bob)=%s', String(await this.masterPool.pendingValue(0, bob))); 59 | console.log('--> pendingValue(1, carol)=%s', String(await this.masterPool.pendingValue(1, carol))); 60 | } 61 | await this.masterPool.deposit(0, '0', ADDRESS_ZERO, {from: bob}); 62 | await this.masterPool.deposit(1, '0', ADDRESS_ZERO, {from: carol}); 63 | console.log('--> balanceOf(bob)=%s', String(await this.value.balanceOf(bob)).valueOf()); 64 | console.log('--> balanceOf(carol)=%s', String(await this.value.balanceOf(carol)).valueOf()); 65 | }); 66 | }); 67 | -------------------------------------------------------------------------------- /truffle-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // Uncommenting the defaults below 3 | // provides for an easier quick-start with Ganache. 4 | // You can also follow this format for other networks; 5 | // see 6 | // for more details on how to specify configuration options! 7 | 8 | // networks: { 9 | // development: { 10 | // host: "127.0.0.1", 11 | // port: 8545, 12 | // network_id: "*" 13 | // }, 14 | // test: { 15 | // host: "127.0.0.1", 16 | // port: 8545, 17 | // network_id: "*" 18 | // } 19 | // }, 20 | 21 | contracts_directory: './contracts/VALUE', 22 | migrations_directory: './migrations', 23 | 24 | compilers: { 25 | solc: { 26 | version: "0.6.12" 27 | } 28 | } 29 | }; 30 | --------------------------------------------------------------------------------