├── .editorconfig ├── .env.example ├── .eslintignore ├── .eslintrc.json ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── feature_request.yml │ ├── other.yml │ └── question.yml ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── nodejs.yml ├── .gitignore ├── .husky ├── .gitignore └── pre-commit ├── .prettierignore ├── .prettierrc.json ├── .solhint.json ├── .solhintignore ├── .vscode └── settings.json ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── contracts ├── Migrations.sol ├── interface │ ├── IAddressConfig.sol │ ├── IAllocator.sol │ ├── IDev.sol │ ├── IDevMinter.sol │ ├── ILockup.sol │ ├── IMarket.sol │ ├── IMarketBehavior.sol │ ├── IMarketFactory.sol │ ├── IMarketGroup.sol │ ├── IMetrics.sol │ ├── IMetricsFactory.sol │ ├── IMetricsGroup.sol │ ├── IPolicy.sol │ ├── IPolicyFactory.sol │ ├── IPolicyGroup.sol │ ├── IProperty.sol │ ├── IPropertyFactory.sol │ ├── IPropertyGroup.sol │ ├── IUsingStorage.sol │ └── IWithdraw.sol ├── src │ ├── allocator │ │ └── Allocator.sol │ ├── common │ │ ├── config │ │ │ ├── AddressConfig.sol │ │ │ └── UsingConfig.sol │ │ ├── libs │ │ │ ├── Curve.sol │ │ │ └── Decimals.sol │ │ └── storage │ │ │ ├── EternalStorage.sol │ │ │ └── UsingStorage.sol │ ├── dev │ │ ├── Dev.sol │ │ ├── DevMigration.sol │ │ └── DevMinter.sol │ ├── lockup │ │ ├── Lockup.sol │ │ └── LockupStorage.sol │ ├── market │ │ ├── Market.sol │ │ ├── MarketFactory.sol │ │ └── MarketGroup.sol │ ├── metrics │ │ ├── Metrics.sol │ │ ├── MetricsFactory.sol │ │ └── MetricsGroup.sol │ ├── policy │ │ ├── DIP1.sol │ │ ├── DIP55.sol │ │ ├── DIP7.sol │ │ ├── Patch780.sol │ │ ├── PolicyFactory.sol │ │ ├── PolicyGroup.sol │ │ ├── TheFirstPolicy.sol │ │ └── TreasuryFee.sol │ ├── property │ │ ├── Property.sol │ │ ├── PropertyFactory.sol │ │ └── PropertyGroup.sol │ └── withdraw │ │ ├── Withdraw.sol │ │ └── WithdrawStorage.sol └── test │ ├── common │ ├── config │ │ └── UsingConfig.sol │ ├── libs │ │ └── Decimals.sol │ └── storage │ │ └── UsingStorage.sol │ ├── lockup │ ├── LockupStorageTest.sol │ └── LockupTest.sol │ ├── market │ ├── MarketTest1.sol │ ├── MarketTest2.sol │ └── MarketTest3.sol │ ├── metrics │ └── MetricsGroupTest.sol │ ├── policy │ ├── PolicyTest1.sol │ ├── PolicyTestBase.sol │ ├── PolicyTestForAllocator.sol │ ├── PolicyTestForPolicyFactory.sol │ ├── PolicyTestForProperty.sol │ └── PolicyTestForWithdraw.sol │ ├── token │ └── STokenManagerTest.sol │ ├── treasury │ └── TreasuryTest.sol │ └── withdraw │ ├── WithdrawStorageTest.sol │ └── WithdrawTest.sol ├── docs ├── POLICY.md ├── WHITEPAPER.JA.md ├── WHITEPAPER.md └── audit-report__quantstamp--sept-15-2020.pdf ├── migrations ├── 1_address-config.ts ├── 2_initialize.ts ├── 3_the-first-policy.ts ├── 4_finalize_initialization.ts ├── 5_dev-migration.ts └── 6_add_minter.ts ├── package.json ├── public └── asset │ ├── logo.png │ └── policy │ └── staking-ratio-vs-mint-amount.svg ├── renovate.json ├── scripts ├── 1015-desable-market.ts ├── 528-change-authenticate-interface.ts ├── 533-1-dip9-migration.ts ├── 533-2-bulk-initialize-metrics-count-per-property.ts ├── 533-3-dip9-after-migration.ts ├── 557-create-and-authenticate-one-tx.ts ├── 560-check-transfer-result.ts ├── 565-delete-loop.ts ├── 566-1-fix-reward-calculation-for-creators.ts ├── 566-2-bulk-initialize.ts ├── 566-3-finilize.ts ├── 592-cut-gas-price.ts ├── 618-delete-unnecessary-function.ts ├── 632-one-transaction-withdrawal.ts ├── 637-bug-fix.ts ├── 786-dev-minter.ts ├── 898-delete-vote-counter.ts ├── bulk-initialize-last-cumulative-property-interest.ts ├── bulk-initialize-states-at-lockup.ts ├── deploy-withdraw.ts ├── dip38.ts ├── lib │ ├── api.ts │ ├── bulk-initializer.ts │ ├── instance │ │ ├── allocator.ts │ │ ├── common.ts │ │ ├── lockup.ts │ │ ├── market-factory.ts │ │ ├── market-group.ts │ │ ├── metrics-factory.ts │ │ ├── metrics-group.ts │ │ ├── policy-factory.ts │ │ ├── policy-group.ts │ │ ├── policy.ts │ │ ├── property-factory.ts │ │ ├── property-group.ts │ │ └── withdraw.ts │ └── types.ts └── treasury-fee.ts ├── test ├── allocator │ └── allocator.ts ├── common │ ├── config │ │ ├── address-config.ts │ │ └── using-config.ts │ ├── libs │ │ └── decimals.ts │ └── storage │ │ ├── eternal-storage.ts │ │ └── using-storage.ts ├── dev │ ├── dev-migration.ts │ ├── dev-minter.ts │ └── dev.ts ├── lockup │ ├── lockup-common.ts │ ├── lockup-s-token-common.ts │ ├── lockup-s-token-scenario.ts │ ├── lockup-s-token.ts │ ├── lockup-scenario.ts │ ├── lockup-storage.ts │ └── lockup.ts ├── market │ ├── market-factory.ts │ ├── market-group.ts │ └── market.ts ├── metrics │ ├── metrics-factory.ts │ ├── metrics-group.ts │ └── metrics.ts ├── policy │ ├── dip1.ts │ ├── dip55.ts │ ├── dip7.ts │ ├── patch750.ts │ ├── policy-factory.ts │ ├── policy-group.ts │ ├── policy.ts │ ├── the-first-policy.ts │ ├── treasury-fee.ts │ └── utils.ts ├── property │ ├── property-factory.ts │ ├── property-group.ts │ └── property.ts ├── test-lib │ ├── const.ts │ ├── instance.ts │ └── utils │ │ ├── common.ts │ │ ├── error.ts │ │ ├── event.ts │ │ ├── log.ts │ │ ├── mint-amount.ts │ │ └── snapshot.ts └── withdraw │ ├── withdraw-common.ts │ ├── withdraw-scenario.ts │ ├── withdraw-storage.ts │ └── withdraw.ts ├── truffle-config.js ├── tsconfig.build.json ├── tsconfig.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | ETHEREUM_PROVIDERS_MAINNET='Endpoint in Mainnet' 2 | ETHEREUM_PROVIDERS_ROPSTEN='Endpoint in Ropsten Network' 3 | ETHEREUM_PROVIDERS_AZURE='Endpoint in Azure Blockchain Service' 4 | ETHEREUM_WALLET_MNEMONIC='Mnemonic by more than 12 words' 5 | ETHEREUM_MOCK_HOST='Network host name for mockup' 6 | ETHEREUM_MOCK_PORT='Network port number for mockup' 7 | CONFIG='AddressConfig Contract address' 8 | EGS_TOKEN='EthGasStation API access token' 9 | ETHEREUM_ETHERSCAN_API_KEY='Etherscan API key' 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | types/ 3 | *.js 4 | !truffle-config.js 5 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "parserOptions": { 4 | "project": "./tsconfig.json", 5 | "tsconfigRootDir": "." 6 | }, 7 | "env": { "mocha": true }, 8 | "plugins": ["@typescript-eslint"], 9 | "extends": ["xo", "xo-typescript", "prettier"], 10 | "rules": { 11 | "@typescript-eslint/prefer-readonly-parameter-types": "off", 12 | "@typescript-eslint/no-unsafe-member-access": "off", 13 | "@typescript-eslint/no-unsafe-call": "off", 14 | "@typescript-eslint/no-unsafe-return": "off", 15 | "@typescript-eslint/no-base-to-string": "off", 16 | "@typescript-eslint/naming-convention": [ 17 | "error", 18 | { 19 | "selector": ["variable", "function"], 20 | "format": ["camelCase", "UPPER_CASE", "PascalCase", "snake_case"], 21 | "leadingUnderscore": "allow" 22 | } 23 | ] 24 | }, 25 | "overrides": [ 26 | { 27 | "files": ["test/**/*.ts"], 28 | "globals": { 29 | "artifacts": "readonly", 30 | "contract": "readonly", 31 | "web3": "readonly" 32 | } 33 | }, 34 | { 35 | "files": ["migrations/**/*", "test/**/*"], 36 | "globals": { 37 | "artifacts": "readonly", 38 | "Truffle": "readonly" 39 | }, 40 | "rules": { 41 | "@typescript-eslint/ban-ts-comment": "off", 42 | "@typescript-eslint/prefer-ts-expect-error": "off" 43 | } 44 | } 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guide 2 | 3 | ## How to contribute? 4 | 5 | You can find problems from [Issues](https://github.com/dev-protocol/protocol/issues) or fix other problems. 6 | 7 | Basic Pull Request steps: 8 | 9 | 1. Fork this repository 10 | 1. Create your feature branch: `git checkout -b awesome-feature` 11 | 1. Commit your changes: `git commit -am "Add awesome feature"` 12 | 1. Push to the branch: `git push origin awesome-feature` 13 | 1. Submit a pull request to this repository 14 | 15 | ## How to start development? 16 | 17 | First as follows: 18 | 19 | ``` 20 | git clone git@github.com:YOUR-USERNAME/protocol.git 21 | cd protocol 22 | yarn 23 | yarn generate 24 | ``` 25 | 26 | If you change something, please update the test code as well. 27 | 28 | Run all tests: 29 | 30 | ``` 31 | yarn test 32 | ``` 33 | 34 | If there is no problem tests succeed! 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Create a report to help us improve 3 | title: '[BUG] ' 4 | labels: [bug] 5 | body: 6 | - type: textarea 7 | id: subject 8 | attributes: 9 | label: Problem subject 10 | description: Use one of the following boxes. If none of them apply, please specify. 11 | placeholder: | 12 | - [ ] Contracts 13 | - [ ] Tests 14 | - [ ] Documentation 15 | - [ ] Other (please specify) 16 | validations: 17 | required: false 18 | - type: textarea 19 | id: description 20 | attributes: 21 | label: Description 22 | description: Please write what problem/bug you are experiencing or want to report. 23 | validations: 24 | required: true 25 | - type: textarea 26 | id: expectedbhv 27 | attributes: 28 | label: Expected behavior/contents 29 | description: Please write here the expected behavior/contents 30 | validations: 31 | required: true 32 | - type: textarea 33 | id: actualbhv 34 | attributes: 35 | label: Actual behavior/contents 36 | description: Please write here the actual behavior/contents 37 | validations: 38 | required: false 39 | - type: checkboxes 40 | id: coc 41 | attributes: 42 | label: Code of Conduct 43 | description: By submitting this issue, I confirm I've read and complied with the [CoC](https://github.com/dev-protocol/protocol/blob/main/CODE_OF_CONDUCT.md) 🖖 44 | options: 45 | - label: I agree to follow this project's Code of Conduct 46 | required: true 47 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest features, propose improvements, discuss new ideas 3 | title: '[FEATURE] ' 4 | labels: [enhancement] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: Provide a general summary of the issue in the title above 9 | - type: textarea 10 | id: description 11 | attributes: 12 | label: Detailed description 13 | description: Provide a detailed description of the change or addition you are proposing 14 | validations: 15 | required: true 16 | - type: textarea 17 | id: context 18 | attributes: 19 | label: Context 20 | description: | 21 | Why is this change important to you? How would you use it? 22 | How can it benefit other users? 23 | validations: 24 | required: true 25 | - type: textarea 26 | id: possibleimpl 27 | attributes: 28 | label: Possible implementation 29 | description: Not obligatory, but suggest an idea for implementing addition or change 30 | validations: 31 | required: false 32 | - type: textarea 33 | id: extrainformation 34 | attributes: 35 | label: Additional information 36 | description: Is there anything else we should know about this feature? 37 | validations: 38 | required: false 39 | - type: checkboxes 40 | id: coc 41 | attributes: 42 | label: Code of Conduct 43 | description: By submitting this issue, I confirm I've read and complied with the [CoC](https://github.com/dev-protocol/protocol/blob/main/CODE_OF_CONDUCT.md) 🖖 44 | options: 45 | - label: I agree to follow this project's Code of Conduct 46 | required: true 47 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/other.yml: -------------------------------------------------------------------------------- 1 | name: Other 2 | description: Use this for any other issues. PLEASE do not create blank issues 3 | title: '[OTHER]' 4 | labels: [triage] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: '# Other issue' 9 | - type: textarea 10 | id: issuedescription 11 | attributes: 12 | label: What would you like to share? 13 | description: Provide a clear and concise explanation of your issue. 14 | validations: 15 | required: true 16 | - type: textarea 17 | id: extrainfo 18 | attributes: 19 | label: Additional information 20 | description: Is there anything else we should know about this issue? 21 | validations: 22 | required: false 23 | - type: checkboxes 24 | id: coc 25 | attributes: 26 | label: Code of Conduct 27 | description: By submitting this issue, I confirm I've read and complied with the [CoC](https://github.com/dev-protocol/protocol/blob/main/CODE_OF_CONDUCT.md) 🖖 28 | options: 29 | - label: I agree to follow this project's Code of Conduct 30 | required: true 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.yml: -------------------------------------------------------------------------------- 1 | name: Question 2 | description: Ask the team a question about this project 3 | title: '[QUESTION] ' 4 | labels: [question] 5 | body: 6 | - type: input 7 | id: description 8 | attributes: 9 | label: Question information 10 | description: Please write your question/discussion about this project here 11 | validations: 12 | required: true 13 | - type: checkboxes 14 | id: coc 15 | attributes: 16 | label: Code of Conduct 17 | description: By submitting this issue, I confirm I've read and complied with the [CoC](https://github.com/dev-protocol/protocol/blob/main/CODE_OF_CONDUCT.md) 🖖 18 | options: 19 | - label: I agree to follow this project's Code of Conduct 20 | required: true 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | 4 | 5 | ### Why is this change needed? 6 | 7 | 8 | 9 | ### Related Issues 10 | 11 | 12 | 13 | 14 | ### Code of Conduct 15 | 16 | - [ ] By submitting this pull request, I confirm I've read and complied with the [CoC](https://github.com/dev-protocol/protocol/blob/main/CODE_OF_CONDUCT.md) 🖖 17 | -------------------------------------------------------------------------------- /.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 | # Optional REPL history 57 | .node_repl_history 58 | 59 | # Output of 'npm pack' 60 | *.tgz 61 | 62 | # Yarn Integrity file 63 | .yarn-integrity 64 | 65 | # dotenv environment variables file 66 | .env 67 | .env.test 68 | .env.gpg 69 | 70 | # parcel-bundler cache (https://parceljs.org/) 71 | .cache 72 | 73 | # next.js build output 74 | .next 75 | 76 | # nuxt.js build output 77 | .nuxt 78 | 79 | # vuepress build output 80 | .vuepress/dist 81 | 82 | # Serverless directories 83 | .serverless/ 84 | 85 | # FuseBox cache 86 | .fusebox/ 87 | 88 | # DynamoDB Local files 89 | .dynamodb/ 90 | 91 | # output of typechain 92 | build 93 | types 94 | 95 | # output of tsc 96 | *.js 97 | !truffle-config.js 98 | 99 | # use yarn 100 | package-lock.json 101 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn lint 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | build 2 | contracts/modules 3 | *.js 4 | !truffle-config.js 5 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "useTabs": true, 5 | "overrides": [ 6 | { 7 | "files": ["*.sol"], 8 | "options": { 9 | "singleQuote": false 10 | } 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:recommended", 3 | "rules": { 4 | "compiler-version": ["error", "0.5.17"], 5 | "no-empty-blocks": "off", 6 | "reason-string": "off" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.solhintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | contracts/modules 3 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "solidity.linter": "solhint", 3 | "solidity.packageDefaultDependenciesContractsDirectory": "", 4 | "solidity.packageDefaultDependenciesDirectory": "node_modules", 5 | "eslint.autoFixOnSave": true, 6 | "eslint.validate": [ 7 | "javascript", 8 | { 9 | "language": "typescript", 10 | "autoFix": true 11 | } 12 | ], 13 | "editor.codeActionsOnSave": { 14 | "source.fixAll.eslint": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | - Using welcoming and inclusive language 18 | - Being respectful of differing viewpoints and experiences 19 | - Gracefully accepting constructive criticism 20 | - Focusing on what is best for the community 21 | - Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | - The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | - Trolling, insulting/derogatory comments, and personal or political attacks 28 | - Public or private harassment 29 | - Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | - Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at hi@devtoken.rocks. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Dev Protocol](https://raw.githubusercontent.com/dev-protocol/protocol/main/public/asset/logo.png) 2 | 3 | [![CI Status](https://github.com/dev-protocol/protocol/workflows/Node/badge.svg)](https://github.com/dev-protocol/protocol/actions) 4 | [![code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) 5 | [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier) 6 | 7 | # Dev Protocol 8 | 9 | This repository is the place to develop smart contracts for Dev Protocol. 10 | 11 | - Whitepaper: https://github.com/dev-protocol/protocol/blob/main/docs/WHITEPAPER.md 12 | - ホワイトペーパー(日本語): https://github.com/dev-protocol/protocol/blob/main/docs/WHITEPAPER.JA.md 13 | 14 | ## How to use 15 | 16 | ### install 17 | 18 | First, install this repository as an npm package. 19 | 20 | ```bash 21 | > npm i -D @devprotocol/protocol 22 | ``` 23 | 24 | ### import 25 | 26 | You can use the Dev Protocol interface by importing it from a Solidity file. 27 | 28 | ``` 29 | import {IAddressConfig} from "@devprotocol/protocol/contracts/interface/IAddressConfig.sol"; 30 | import {IPropertyGroup} from "@devprotocol/protocol/contracts/interface/IPropertyGroup.sol"; 31 | 32 | contract TestContract { 33 | function validatePropertyAddress(address _property) external view { 34 | IAddressConfig addressConfig = IAddressConfig(0x1D415aa39D647834786EB9B5a333A50e9935b796); 35 | IPropertyGroup propertyGroup = IPropertyGroup(addressConfig.propertyGroup()); 36 | require(propertyGroup.isGroup(_property), "not property address"); 37 | } 38 | } 39 | ``` 40 | 41 | This is an example of logic that uses the PropertyGroup contract feature of the Dev Protocol to validate if it is a Property address. 42 | 43 | The available interfaces can be found in "node_modules/@devprotocol/protocol/contracts/interface/". 44 | 45 | AddressConfig holds the addresses of the contracts used in the Dev Protocol. 46 | 47 | ``` 48 | AddressConfig address 49 | mainnet:0x1D415aa39D647834786EB9B5a333A50e9935b796 50 | Ropsten:0xD6D07f1c048bDF2B3d5d9B6c25eD1FC5348D0A70 51 | ``` 52 | 53 | ## How to contribute: 54 | 55 | Read the [contributing guide](https://github.com/dev-protocol/protocol/blob/main/.github/CONTRIBUTING.md), and create PR when you have time. 🧚✨ 56 | 57 | ## How to setup 58 | 59 | Executing the following command will compile each contract. 60 | 61 | ``` 62 | git clone https://github.com/dev-protocol/protocol.git 63 | cd protocol 64 | yarn 65 | yarn generate 66 | ``` 67 | 68 | run the following command to test each contract. 69 | 70 | ``` 71 | yarn test 72 | ``` 73 | 74 | If you use Visual Studio Code, we recommend that you install the following plug-ins: 75 | 76 | ``` 77 | EditorConfig 78 | vscode-eslint 79 | solidity 80 | ``` 81 | -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint256 public lastCompletedMigration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | constructor() public { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint256 completed) public restricted { 16 | lastCompletedMigration = completed; 17 | } 18 | 19 | function upgrade(address newAddress) public restricted { 20 | Migrations upgraded = Migrations(newAddress); 21 | upgraded.setCompleted(lastCompletedMigration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/interface/IAddressConfig.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IAddressConfig { 5 | function token() external view returns (address); 6 | 7 | function allocator() external view returns (address); 8 | 9 | function allocatorStorage() external view returns (address); 10 | 11 | function withdraw() external view returns (address); 12 | 13 | function withdrawStorage() external view returns (address); 14 | 15 | function marketFactory() external view returns (address); 16 | 17 | function marketGroup() external view returns (address); 18 | 19 | function propertyFactory() external view returns (address); 20 | 21 | function propertyGroup() external view returns (address); 22 | 23 | function metricsGroup() external view returns (address); 24 | 25 | function metricsFactory() external view returns (address); 26 | 27 | function policy() external view returns (address); 28 | 29 | function policyFactory() external view returns (address); 30 | 31 | function policySet() external view returns (address); 32 | 33 | function policyGroup() external view returns (address); 34 | 35 | function lockup() external view returns (address); 36 | 37 | function lockupStorage() external view returns (address); 38 | 39 | function voteTimes() external view returns (address); 40 | 41 | function voteTimesStorage() external view returns (address); 42 | 43 | function voteCounter() external view returns (address); 44 | 45 | function voteCounterStorage() external view returns (address); 46 | 47 | function setAllocator(address _addr) external; 48 | 49 | function setAllocatorStorage(address _addr) external; 50 | 51 | function setWithdraw(address _addr) external; 52 | 53 | function setWithdrawStorage(address _addr) external; 54 | 55 | function setMarketFactory(address _addr) external; 56 | 57 | function setMarketGroup(address _addr) external; 58 | 59 | function setPropertyFactory(address _addr) external; 60 | 61 | function setPropertyGroup(address _addr) external; 62 | 63 | function setMetricsFactory(address _addr) external; 64 | 65 | function setMetricsGroup(address _addr) external; 66 | 67 | function setPolicyFactory(address _addr) external; 68 | 69 | function setPolicyGroup(address _addr) external; 70 | 71 | function setPolicySet(address _addr) external; 72 | 73 | function setPolicy(address _addr) external; 74 | 75 | function setToken(address _addr) external; 76 | 77 | function setLockup(address _addr) external; 78 | 79 | function setLockupStorage(address _addr) external; 80 | 81 | function setVoteTimes(address _addr) external; 82 | 83 | function setVoteTimesStorage(address _addr) external; 84 | 85 | function setVoteCounter(address _addr) external; 86 | 87 | function setVoteCounterStorage(address _addr) external; 88 | } 89 | -------------------------------------------------------------------------------- /contracts/interface/IAllocator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IAllocator { 5 | function beforeBalanceChange( 6 | address _property, 7 | address _from, 8 | address _to 9 | ) external; 10 | 11 | function calculateMaxRewardsPerBlock() external view returns (uint256); 12 | } 13 | -------------------------------------------------------------------------------- /contracts/interface/IDev.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IDev { 5 | function deposit(address _to, uint256 _amount) external returns (bool); 6 | 7 | function depositFrom( 8 | address _from, 9 | address _to, 10 | uint256 _amount 11 | ) external returns (bool); 12 | 13 | function fee(address _from, uint256 _amount) external returns (bool); 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interface/IDevMinter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IDevMinter { 5 | function mint(address account, uint256 amount) external returns (bool); 6 | 7 | function renounceMinter() external; 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interface/ILockup.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface ILockup { 5 | function depositToProperty(address _property, uint256 _amount) 6 | external 7 | returns (uint256); 8 | 9 | function depositToProperty( 10 | address _property, 11 | uint256 _amount, 12 | bytes32 _data 13 | ) external returns (uint256); 14 | 15 | function depositToPosition(uint256 _tokenId, uint256 _amount) 16 | external 17 | returns (bool); 18 | 19 | function lockup( 20 | address _from, 21 | address _property, 22 | uint256 _value 23 | ) external; 24 | 25 | function update() external; 26 | 27 | function withdraw(address _property, uint256 _amount) external; 28 | 29 | function withdrawByPosition(uint256 _tokenId, uint256 _amount) 30 | external 31 | returns (bool); 32 | 33 | function calculateCumulativeRewardPrices() 34 | external 35 | view 36 | returns ( 37 | uint256 _reward, 38 | uint256 _holders, 39 | uint256 _interest, 40 | uint256 _holdersCap 41 | ); 42 | 43 | function calculateRewardAmount(address _property) 44 | external 45 | view 46 | returns (uint256, uint256); 47 | 48 | /** 49 | * caution!!!this function is deprecated!!! 50 | * use calculateRewardAmount 51 | */ 52 | function calculateCumulativeHoldersRewardAmount(address _property) 53 | external 54 | view 55 | returns (uint256); 56 | 57 | function getPropertyValue(address _property) 58 | external 59 | view 60 | returns (uint256); 61 | 62 | function getAllValue() external view returns (uint256); 63 | 64 | function getValue(address _property, address _sender) 65 | external 66 | view 67 | returns (uint256); 68 | 69 | function calculateWithdrawableInterestAmount( 70 | address _property, 71 | address _user 72 | ) external view returns (uint256); 73 | 74 | function calculateWithdrawableInterestAmountByPosition(uint256 _tokenId) 75 | external 76 | view 77 | returns (uint256); 78 | 79 | function cap() external view returns (uint256); 80 | 81 | function updateCap(uint256 _cap) external; 82 | 83 | function devMinter() external view returns (address); 84 | 85 | function sTokensManager() external view returns (address); 86 | 87 | function migrateToSTokens(address _property) external returns (uint256); 88 | } 89 | -------------------------------------------------------------------------------- /contracts/interface/IMarket.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IMarket { 5 | function authenticate( 6 | address _prop, 7 | string calldata _args1, 8 | string calldata _args2, 9 | string calldata _args3, 10 | string calldata _args4, 11 | string calldata _args5 12 | ) external returns (bool); 13 | 14 | function authenticateFromPropertyFactory( 15 | address _prop, 16 | address _author, 17 | string calldata _args1, 18 | string calldata _args2, 19 | string calldata _args3, 20 | string calldata _args4, 21 | string calldata _args5 22 | ) external returns (bool); 23 | 24 | function authenticatedCallback(address _property, bytes32 _idHash) 25 | external 26 | returns (address); 27 | 28 | function deauthenticate(address _metrics) external; 29 | 30 | function schema() external view returns (string memory); 31 | 32 | function behavior() external view returns (address); 33 | 34 | function issuedMetrics() external view returns (uint256); 35 | 36 | function enabled() external view returns (bool); 37 | 38 | function votingEndBlockNumber() external view returns (uint256); 39 | 40 | function toEnable() external; 41 | 42 | function toDisable() external; 43 | } 44 | -------------------------------------------------------------------------------- /contracts/interface/IMarketBehavior.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IMarketBehavior { 5 | function authenticate( 6 | address _prop, 7 | string calldata _args1, 8 | string calldata _args2, 9 | string calldata _args3, 10 | string calldata _args4, 11 | string calldata _args5, 12 | address market, 13 | address account 14 | ) external returns (bool); 15 | 16 | function schema() external view returns (string memory); 17 | 18 | function getId(address _metrics) external view returns (string memory); 19 | 20 | function getMetrics(string calldata _id) external view returns (address); 21 | } 22 | -------------------------------------------------------------------------------- /contracts/interface/IMarketFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IMarketFactory { 5 | function create(address _addr) external returns (address); 6 | 7 | function enable(address _addr) external; 8 | 9 | function disable(address _addr) external; 10 | } 11 | -------------------------------------------------------------------------------- /contracts/interface/IMarketGroup.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IMarketGroup { 5 | function addGroup(address _addr) external; 6 | 7 | function deleteGroup(address _addr) external; 8 | 9 | function isGroup(address _addr) external view returns (bool); 10 | 11 | function getCount() external view returns (uint256); 12 | } 13 | -------------------------------------------------------------------------------- /contracts/interface/IMetrics.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IMetrics { 5 | function market() external view returns (address); 6 | 7 | function property() external view returns (address); 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interface/IMetricsFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IMetricsFactory { 5 | function create(address _property) external returns (address); 6 | 7 | function destroy(address _metrics) external; 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interface/IMetricsGroup.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IMetricsGroup { 5 | function addGroup(address _addr) external; 6 | 7 | function removeGroup(address _addr) external; 8 | 9 | function isGroup(address _addr) external view returns (bool); 10 | 11 | function totalIssuedMetrics() external view returns (uint256); 12 | 13 | function hasAssets(address _property) external view returns (bool); 14 | 15 | function getMetricsCountPerProperty(address _property) 16 | external 17 | view 18 | returns (uint256); 19 | 20 | function totalAuthenticatedProperties() external view returns (uint256); 21 | } 22 | -------------------------------------------------------------------------------- /contracts/interface/IPolicy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IPolicy { 5 | function rewards(uint256 _lockups, uint256 _assets) 6 | external 7 | view 8 | returns (uint256); 9 | 10 | function holdersShare(uint256 _amount, uint256 _lockups) 11 | external 12 | view 13 | returns (uint256); 14 | 15 | function authenticationFee(uint256 _assets, uint256 _propertyAssets) 16 | external 17 | view 18 | returns (uint256); 19 | 20 | function marketVotingBlocks() external view returns (uint256); 21 | 22 | function policyVotingBlocks() external view returns (uint256); 23 | 24 | function shareOfTreasury(uint256 _supply) external view returns (uint256); 25 | 26 | function treasury() external view returns (address); 27 | 28 | function capSetter() external view returns (address); 29 | } 30 | -------------------------------------------------------------------------------- /contracts/interface/IPolicyFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IPolicyFactory { 5 | function create(address _newPolicyAddress) external; 6 | 7 | function forceAttach(address _policy) external; 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interface/IPolicyGroup.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IPolicyGroup { 5 | function addGroup(address _addr) external; 6 | 7 | function isGroup(address _addr) external view returns (bool); 8 | 9 | function isDuringVotingPeriod(address _policy) external view returns (bool); 10 | } 11 | -------------------------------------------------------------------------------- /contracts/interface/IProperty.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IProperty { 5 | function author() external view returns (address); 6 | 7 | function changeAuthor(address _nextAuthor) external; 8 | 9 | function changeName(string calldata _name) external; 10 | 11 | function changeSymbol(string calldata _symbol) external; 12 | 13 | function withdraw(address _sender, uint256 _value) external; 14 | 15 | function transfer(address _to, uint256 _value) public returns (bool); 16 | } 17 | -------------------------------------------------------------------------------- /contracts/interface/IPropertyFactory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IPropertyFactory { 5 | function create( 6 | string calldata _name, 7 | string calldata _symbol, 8 | address _author 9 | ) external returns (address); 10 | 11 | function createAndAuthenticate( 12 | string calldata _name, 13 | string calldata _symbol, 14 | address _market, 15 | string calldata _args1, 16 | string calldata _args2, 17 | string calldata _args3 18 | ) external returns (bool); 19 | 20 | function createChangeAuthorEvent(address _old, address _new) external; 21 | 22 | function createChangeNameEvent(string calldata _old, string calldata _new) 23 | external; 24 | 25 | function createChangeSymbolEvent(string calldata _old, string calldata _new) 26 | external; 27 | } 28 | -------------------------------------------------------------------------------- /contracts/interface/IPropertyGroup.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IPropertyGroup { 5 | function addGroup(address _addr) external; 6 | 7 | function isGroup(address _addr) external view returns (bool); 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interface/IUsingStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IUsingStorage { 5 | function getStorageAddress() external view returns (address); 6 | 7 | function createStorage() external; 8 | 9 | function setStorage(address _storageAddress) external; 10 | 11 | function changeOwner(address newOwner) external; 12 | } 13 | -------------------------------------------------------------------------------- /contracts/interface/IWithdraw.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MPL-2.0 2 | pragma solidity >=0.5.17; 3 | 4 | interface IWithdraw { 5 | function withdraw(address _property) external; 6 | 7 | function getRewardsAmount(address _property) 8 | external 9 | view 10 | returns (uint256); 11 | 12 | function beforeBalanceChange( 13 | address _property, 14 | address _from, 15 | address _to 16 | ) external; 17 | 18 | /** 19 | * caution!!!this function is deprecated!!! 20 | * use calculateRewardAmount 21 | */ 22 | function calculateWithdrawableAmount(address _property, address _user) 23 | external 24 | view 25 | returns (uint256); 26 | 27 | function calculateRewardAmount(address _property, address _user) 28 | external 29 | view 30 | returns ( 31 | uint256 _amount, 32 | uint256 _price, 33 | uint256 _cap, 34 | uint256 _allReward 35 | ); 36 | 37 | function devMinter() external view returns (address); 38 | } 39 | -------------------------------------------------------------------------------- /contracts/src/allocator/Allocator.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import "../common/config/UsingConfig.sol"; 4 | import "../../interface/IAllocator.sol"; 5 | import "../../interface/IWithdraw.sol"; 6 | import "../../interface/IPolicy.sol"; 7 | import "../../interface/ILockup.sol"; 8 | import "../../interface/IPropertyGroup.sol"; 9 | import "../../interface/IMetricsGroup.sol"; 10 | 11 | /** 12 | * A contract that determines the total number of mint. 13 | * Lockup contract and Withdraw contract mint new DEV tokens based on the total number of new mint determined by this contract. 14 | */ 15 | contract Allocator is UsingConfig, IAllocator { 16 | /** 17 | * @dev Initialize the passed address as AddressConfig address. 18 | * @param _config AddressConfig address. 19 | */ 20 | constructor(address _config) public UsingConfig(_config) {} 21 | 22 | /** 23 | * @dev Returns the maximum number of mints per block. 24 | * @return Maximum number of mints per block. 25 | */ 26 | function calculateMaxRewardsPerBlock() external view returns (uint256) { 27 | uint256 totalAssets = IMetricsGroup(config().metricsGroup()) 28 | .totalIssuedMetrics(); 29 | uint256 totalLockedUps = ILockup(config().lockup()).getAllValue(); 30 | return IPolicy(config().policy()).rewards(totalLockedUps, totalAssets); 31 | } 32 | 33 | /** 34 | * @dev Passthrough to `Withdraw.beforeBalanceChange` funtion. 35 | * @param _property Address of the Property address to transfer. 36 | * @param _from Address of the sender. 37 | * @param _to Address of the recipient. 38 | */ 39 | function beforeBalanceChange( 40 | address _property, 41 | address _from, 42 | address _to 43 | ) external { 44 | require( 45 | IPropertyGroup(config().propertyGroup()).isGroup(msg.sender), 46 | "this is illegal address" 47 | ); 48 | 49 | IWithdraw(config().withdraw()).beforeBalanceChange( 50 | _property, 51 | _from, 52 | _to 53 | ); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /contracts/src/common/config/UsingConfig.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import "../../../interface/IAddressConfig.sol"; 4 | 5 | /** 6 | * Module for using AddressConfig contracts. 7 | */ 8 | contract UsingConfig { 9 | address private _config; 10 | 11 | /** 12 | * Initialize the argument as AddressConfig address. 13 | */ 14 | constructor(address _addressConfig) public { 15 | _config = _addressConfig; 16 | } 17 | 18 | /** 19 | * Returns the latest AddressConfig instance. 20 | */ 21 | function config() internal view returns (IAddressConfig) { 22 | return IAddressConfig(_config); 23 | } 24 | 25 | /** 26 | * Returns the latest AddressConfig address. 27 | */ 28 | function configAddress() external view returns (address) { 29 | return _config; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /contracts/src/common/libs/Curve.sol: -------------------------------------------------------------------------------- 1 | /* solhint-disable const-name-snakecase */ 2 | pragma solidity 0.5.17; 3 | 4 | import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; 5 | 6 | contract Curve { 7 | using SafeMath for uint256; 8 | uint256 private constant basis = 10000000000000000000000000; 9 | uint256 private constant power_basis = 10000000000; 10 | 11 | /** 12 | * @dev From the passed variables, calculate the amount of reward reduced along the curve. 13 | * @param _lockups Total number of locked up tokens. 14 | * @param _assets Total number of authenticated assets. 15 | * @param _totalSupply Total supply the token. 16 | * @param _mintPerBlockAndAseet Maximum number of reward per block per asset. 17 | * @return Calculated reward amount per block per asset. 18 | */ 19 | function curveRewards( 20 | uint256 _lockups, 21 | uint256 _assets, 22 | uint256 _totalSupply, 23 | uint256 _mintPerBlockAndAseet 24 | ) internal pure returns (uint256) { 25 | uint256 t = _totalSupply; 26 | uint256 s = (_lockups.mul(basis)).div(t); 27 | uint256 assets = _assets.mul(basis.sub(s)); 28 | uint256 max = assets.mul(_mintPerBlockAndAseet); 29 | uint256 _d = basis.sub(s); 30 | uint256 _p = ( 31 | (power_basis.mul(12)).sub(s.div((basis.div((power_basis.mul(10)))))) 32 | ).div(2); 33 | uint256 p = _p.div(power_basis); 34 | uint256 rp = p.add(1); 35 | uint256 f = _p.sub(p.mul(power_basis)); 36 | uint256 d1 = _d; 37 | uint256 d2 = _d; 38 | for (uint256 i = 0; i < p; i++) { 39 | d1 = (d1.mul(_d)).div(basis); 40 | } 41 | for (uint256 i = 0; i < rp; i++) { 42 | d2 = (d2.mul(_d)).div(basis); 43 | } 44 | uint256 g = ((d1.sub(d2)).mul(f)).div(power_basis); 45 | uint256 d = d1.sub(g); 46 | uint256 mint = max.mul(d); 47 | mint = mint.div(basis).div(basis); 48 | return mint; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /contracts/src/common/libs/Decimals.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; 4 | 5 | /** 6 | * Library for emulating calculations involving decimals. 7 | */ 8 | library Decimals { 9 | using SafeMath for uint256; 10 | uint120 private constant BASIS_VAKUE = 1000000000000000000; 11 | 12 | /** 13 | * @dev Returns the ratio of the first argument to the second argument. 14 | * @param _a Numerator. 15 | * @param _b Fraction. 16 | * @return Calculated ratio. 17 | */ 18 | function outOf(uint256 _a, uint256 _b) 19 | internal 20 | pure 21 | returns (uint256 result) 22 | { 23 | if (_a == 0) { 24 | return 0; 25 | } 26 | uint256 a = _a.mul(BASIS_VAKUE); 27 | if (a < _b) { 28 | return 0; 29 | } 30 | return (a.div(_b)); 31 | } 32 | 33 | /** 34 | * @dev Returns multiplied the number by 10^18. 35 | * @param _a Numerical value to be multiplied. 36 | * @return Multiplied value. 37 | */ 38 | function mulBasis(uint256 _a) internal pure returns (uint256) { 39 | return _a.mul(BASIS_VAKUE); 40 | } 41 | 42 | /** 43 | * @dev Returns divisioned the number by 10^18. 44 | * This function can use it to restore the number of digits in the result of `outOf`. 45 | * @param _a Numerical value to be divisioned. 46 | * @return Divisioned value. 47 | */ 48 | function divBasis(uint256 _a) internal pure returns (uint256) { 49 | return _a.div(BASIS_VAKUE); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /contracts/src/common/storage/UsingStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import "../../../interface/IUsingStorage.sol"; 4 | import {Ownable} from "@openzeppelin/contracts/ownership/Ownable.sol"; 5 | import "./EternalStorage.sol"; 6 | 7 | /** 8 | * Module for contrast handling EternalStorage. 9 | */ 10 | contract UsingStorage is Ownable, IUsingStorage { 11 | address private _storage; 12 | 13 | /** 14 | * Modifier to verify that EternalStorage is set. 15 | */ 16 | modifier hasStorage() { 17 | require(_storage != address(0), "storage is not set"); 18 | _; 19 | } 20 | 21 | /** 22 | * Returns the set EternalStorage instance. 23 | */ 24 | function eternalStorage() 25 | internal 26 | view 27 | hasStorage 28 | returns (EternalStorage) 29 | { 30 | return EternalStorage(_storage); 31 | } 32 | 33 | /** 34 | * Returns the set EternalStorage address. 35 | */ 36 | function getStorageAddress() external view hasStorage returns (address) { 37 | return _storage; 38 | } 39 | 40 | /** 41 | * Create a new EternalStorage contract. 42 | * This function call will fail if the EternalStorage contract is already set. 43 | * Also, only the owner can execute it. 44 | */ 45 | function createStorage() external onlyOwner { 46 | require(_storage == address(0), "storage is set"); 47 | EternalStorage tmp = new EternalStorage(); 48 | _storage = address(tmp); 49 | } 50 | 51 | /** 52 | * Assigns the EternalStorage contract that has already been created. 53 | * Only the owner can execute this function. 54 | */ 55 | function setStorage(address _storageAddress) external onlyOwner { 56 | _storage = _storageAddress; 57 | } 58 | 59 | /** 60 | * Delegates the owner of the current EternalStorage contract. 61 | * Only the owner can execute this function. 62 | */ 63 | function changeOwner(address newOwner) external onlyOwner { 64 | EternalStorage(_storage).changeOwner(newOwner); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /contracts/src/dev/Dev.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | // prettier-ignore 4 | import {ERC20Detailed} from "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol"; 5 | // prettier-ignore 6 | import {ERC20Mintable} from "@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol"; 7 | // prettier-ignore 8 | import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol"; 9 | import "../common/config/UsingConfig.sol"; 10 | import "../../interface/ILockup.sol"; 11 | import "../../interface/IDev.sol"; 12 | import "../../interface/IMarketGroup.sol"; 13 | 14 | /** 15 | * The contract used as the DEV token. 16 | * The DEV token is an ERC20 token used as the native token of the Dev Protocol. 17 | * The DEV token is created by migration from its predecessor, the MVP, legacy DEV token. For that reason, the initial supply is 0. 18 | * Also, mint will be performed based on the Allocator contract. 19 | * When authenticated a new asset by the Market contracts, DEV token is burned as fees. 20 | */ 21 | contract Dev is ERC20Detailed, ERC20Mintable, ERC20Burnable, UsingConfig, IDev { 22 | /** 23 | * Initialize the passed address as AddressConfig address. 24 | * The token name is `Dev`, the token symbol is `DEV`, and the decimals is 18. 25 | */ 26 | constructor(address _config) 27 | public 28 | ERC20Detailed("Dev", "DEV", 18) 29 | UsingConfig(_config) 30 | {} 31 | 32 | /** 33 | * Staking DEV tokens. 34 | * The transfer destination must always be included in the address set for Property tokens. 35 | * This is because if the transfer destination is not a Property token, it is possible that the staked DEV token cannot be withdrawn. 36 | */ 37 | function deposit(address _to, uint256 _amount) external returns (bool) { 38 | require(transfer(_to, _amount), "dev transfer failed"); 39 | lock(msg.sender, _to, _amount); 40 | return true; 41 | } 42 | 43 | /** 44 | * Staking DEV tokens by an allowanced address. 45 | * The transfer destination must always be included in the address set for Property tokens. 46 | * This is because if the transfer destination is not a Property token, it is possible that the staked DEV token cannot be withdrawn. 47 | */ 48 | function depositFrom( 49 | address _from, 50 | address _to, 51 | uint256 _amount 52 | ) external returns (bool) { 53 | require(transferFrom(_from, _to, _amount), "dev transferFrom failed"); 54 | lock(_from, _to, _amount); 55 | return true; 56 | } 57 | 58 | /** 59 | * Burn the DEV tokens as an authentication fee. 60 | * Only Market contracts can execute this function. 61 | */ 62 | function fee(address _from, uint256 _amount) external returns (bool) { 63 | require( 64 | IMarketGroup(config().marketGroup()).isGroup(msg.sender), 65 | "this is illegal address" 66 | ); 67 | _burn(_from, _amount); 68 | return true; 69 | } 70 | 71 | /** 72 | * Call `Lockup.lockup` to execute staking. 73 | */ 74 | function lock( 75 | address _from, 76 | address _to, 77 | uint256 _amount 78 | ) private { 79 | ILockup(config().lockup()).lockup(_from, _to, _amount); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /contracts/src/dev/DevMigration.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | // prettier-ignore 4 | import {ERC20Mintable} from "@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol"; 5 | // prettier-ignore 6 | import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol"; 7 | 8 | /** 9 | * A contract to migrate two ERC20 tokens. 10 | * Used to migrate the legacy DEV tokens to the latest DEV tokens. 11 | */ 12 | contract DevMigration { 13 | address public legacy; 14 | address public next; 15 | 16 | /** 17 | * Initialize the two passed addresses as the source and destination. 18 | */ 19 | constructor(address _legacy, address _next) public { 20 | legacy = _legacy; 21 | next = _next; 22 | } 23 | 24 | /** 25 | * Migrates tokens. 26 | * The steps: Transfer a sender's all balances of source tokens to this contract and then burn the same amount. Then mint the destination tokens. 27 | * Notes: 28 | * - Approve is required to transfer the balance of the source token. 29 | * - The source tokens must be burnable. 30 | * - The destination tokens must be mintable. 31 | * - This contract needs permission to mint the destination tokens. 32 | */ 33 | function migrate() external returns (bool) { 34 | ERC20Burnable _legacy = ERC20Burnable(legacy); 35 | ERC20Mintable _next = ERC20Mintable(next); 36 | uint256 balance = _legacy.balanceOf(msg.sender); 37 | require( 38 | _legacy.transferFrom(msg.sender, address(this), balance), 39 | "legacy dev transferFrom failed" 40 | ); 41 | _legacy.burn(balance); 42 | require(_next.mint(msg.sender, balance), "next dev mint failed"); 43 | return true; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /contracts/src/dev/DevMinter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | // prettier-ignore 4 | import {ERC20Mintable} from "@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol"; 5 | import {Ownable} from "@openzeppelin/contracts/ownership/Ownable.sol"; 6 | import "../common/config/UsingConfig.sol"; 7 | import "../../interface/IAddressConfig.sol"; 8 | import "../../interface/IDevMinter.sol"; 9 | 10 | contract DevMinter is UsingConfig, Ownable, IDevMinter { 11 | /** 12 | * Initialize the passed address as AddressConfig address. 13 | */ 14 | constructor(address _config) public UsingConfig(_config) {} 15 | 16 | /** 17 | * Mint Dev token 18 | */ 19 | function mint(address account, uint256 amount) external returns (bool) { 20 | IAddressConfig conf = config(); 21 | require( 22 | msg.sender == conf.lockup() || msg.sender == conf.withdraw(), 23 | "illegal access" 24 | ); 25 | return ERC20Mintable(conf.token()).mint(account, amount); 26 | } 27 | 28 | /** 29 | * Delete mint role 30 | */ 31 | function renounceMinter() external onlyOwner { 32 | IAddressConfig conf = config(); 33 | address token = conf.token(); 34 | ERC20Mintable(token).renounceMinter(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /contracts/src/market/MarketFactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {Ownable} from "@openzeppelin/contracts/ownership/Ownable.sol"; 4 | import "../common/config/UsingConfig.sol"; 5 | import "../market/Market.sol"; 6 | import "../../interface/IMarket.sol"; 7 | import "../../interface/IMarketFactory.sol"; 8 | import "../../interface/IMarketGroup.sol"; 9 | 10 | /** 11 | * A factory contract that creates a new Market contract. 12 | */ 13 | contract MarketFactory is Ownable, IMarketFactory, UsingConfig { 14 | event Create(address indexed _from, address _market); 15 | 16 | /** 17 | * Initialize the passed address as AddressConfig address. 18 | */ 19 | constructor(address _config) public UsingConfig(_config) {} 20 | 21 | /** 22 | * Creates a new Market contract. 23 | */ 24 | function create(address _addr) external returns (address) { 25 | /** 26 | * Validates the passed address is not 0 address. 27 | */ 28 | require(_addr != address(0), "this is illegal address"); 29 | 30 | /** 31 | * Creates a new Market contract with the passed address as the IMarketBehavior. 32 | */ 33 | Market market = new Market(address(config()), _addr); 34 | 35 | /** 36 | * Adds the created Market contract to the Market address set. 37 | */ 38 | address marketAddr = address(market); 39 | IMarketGroup marketGroup = IMarketGroup(config().marketGroup()); 40 | marketGroup.addGroup(marketAddr); 41 | 42 | /** 43 | * For the first Market contract, it will be activated immediately. 44 | * If not, the Market contract will be activated after a vote by the voters. 45 | */ 46 | if (marketGroup.getCount() == 1) { 47 | market.toEnable(); 48 | } 49 | 50 | emit Create(msg.sender, marketAddr); 51 | return marketAddr; 52 | } 53 | 54 | /** 55 | * Creates a new Market contract. 56 | */ 57 | function enable(address _addr) external onlyOwner { 58 | /** 59 | * Validates the passed address is not 0 address. 60 | */ 61 | IMarketGroup marketGroup = IMarketGroup(config().marketGroup()); 62 | require(marketGroup.isGroup(_addr), "illegal address"); 63 | 64 | /** 65 | * Market will be enable. 66 | */ 67 | IMarket market = IMarket(_addr); 68 | require(market.enabled() == false, "already enabled"); 69 | 70 | market.toEnable(); 71 | } 72 | 73 | /** 74 | * Creates a new Market contract. 75 | */ 76 | function disable(address _addr) external onlyOwner { 77 | /** 78 | * Validates the passed address is not 0 address. 79 | */ 80 | IMarketGroup marketGroup = IMarketGroup(config().marketGroup()); 81 | require(marketGroup.isGroup(_addr), "illegal address"); 82 | 83 | /** 84 | * Market will be enable. 85 | */ 86 | IMarket market = IMarket(_addr); 87 | require(market.enabled() == true, "already disabled"); 88 | 89 | market.toDisable(); 90 | marketGroup.deleteGroup(_addr); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /contracts/src/market/MarketGroup.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; 4 | import "../common/config/UsingConfig.sol"; 5 | import "../common/storage/UsingStorage.sol"; 6 | import "../../interface/IMarketGroup.sol"; 7 | 8 | contract MarketGroup is UsingConfig, UsingStorage, IMarketGroup { 9 | using SafeMath for uint256; 10 | 11 | constructor(address _config) public UsingConfig(_config) UsingStorage() {} 12 | 13 | function addGroup(address _addr) external { 14 | require(msg.sender == config().marketFactory(), "illegal access"); 15 | 16 | require( 17 | eternalStorage().getBool(getGroupKey(_addr)) == false, 18 | "already enabled" 19 | ); 20 | eternalStorage().setBool(getGroupKey(_addr), true); 21 | addCount(); 22 | } 23 | 24 | function deleteGroup(address _addr) external { 25 | require(msg.sender == config().marketFactory(), "illegal access"); 26 | 27 | require( 28 | eternalStorage().getBool(getGroupKey(_addr)) == true, 29 | "not exist" 30 | ); 31 | eternalStorage().setBool(getGroupKey(_addr), false); 32 | reduceCount(); 33 | } 34 | 35 | function isGroup(address _addr) external view returns (bool) { 36 | return eternalStorage().getBool(getGroupKey(_addr)); 37 | } 38 | 39 | function reduceCount() private { 40 | bytes32 key = getCountKey(); 41 | uint256 number = eternalStorage().getUint(key); 42 | number = number.sub(1); 43 | eternalStorage().setUint(key, number); 44 | } 45 | 46 | function addCount() private { 47 | bytes32 key = getCountKey(); 48 | uint256 number = eternalStorage().getUint(key); 49 | number = number.add(1); 50 | eternalStorage().setUint(key, number); 51 | } 52 | 53 | function getCount() external view returns (uint256) { 54 | bytes32 key = getCountKey(); 55 | return eternalStorage().getUint(key); 56 | } 57 | 58 | function getCountKey() private pure returns (bytes32) { 59 | return keccak256(abi.encodePacked("_count")); 60 | } 61 | 62 | function getGroupKey(address _addr) private pure returns (bytes32) { 63 | return keccak256(abi.encodePacked("_group", _addr)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /contracts/src/metrics/Metrics.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import "../../interface/IMetrics.sol"; 4 | 5 | /** 6 | * A contract for associating a Property and an asset authenticated by a Market. 7 | */ 8 | contract Metrics is IMetrics { 9 | address public market; 10 | address public property; 11 | 12 | constructor(address _market, address _property) public { 13 | //Do not validate because there is no AddressConfig 14 | market = _market; 15 | property = _property; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/src/metrics/MetricsFactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import "../common/config/UsingConfig.sol"; 4 | import "../metrics/Metrics.sol"; 5 | import "../../interface/IMetrics.sol"; 6 | import "../../interface/IMetricsGroup.sol"; 7 | import "../../interface/IMarketGroup.sol"; 8 | import "../../interface/IMetricsFactory.sol"; 9 | 10 | /** 11 | * A factory contract for creating new Metrics contracts and logical deletion of Metrics contracts. 12 | */ 13 | contract MetricsFactory is UsingConfig, IMetricsFactory { 14 | event Create(address indexed _from, address _metrics); 15 | event Destroy(address indexed _from, address _metrics); 16 | 17 | /** 18 | * Initialize the passed address as AddressConfig address. 19 | */ 20 | constructor(address _config) public UsingConfig(_config) {} 21 | 22 | /** 23 | * Creates a new Metrics contract. 24 | */ 25 | function create(address _property) external returns (address) { 26 | /** 27 | * Validates the sender is included in the Market address set. 28 | */ 29 | require( 30 | IMarketGroup(config().marketGroup()).isGroup(msg.sender), 31 | "this is illegal address" 32 | ); 33 | 34 | /** 35 | * Creates a new Metrics contract. 36 | */ 37 | Metrics metrics = new Metrics(msg.sender, _property); 38 | 39 | /** 40 | * Adds the new Metrics contract to the Metrics address set. 41 | */ 42 | IMetricsGroup metricsGroup = IMetricsGroup(config().metricsGroup()); 43 | address metricsAddress = address(metrics); 44 | metricsGroup.addGroup(metricsAddress); 45 | 46 | emit Create(msg.sender, metricsAddress); 47 | return metricsAddress; 48 | } 49 | 50 | /** 51 | * Logical deletions a Metrics contract. 52 | */ 53 | function destroy(address _metrics) external { 54 | /** 55 | * Validates the passed address is included in the Metrics address set. 56 | */ 57 | IMetricsGroup metricsGroup = IMetricsGroup(config().metricsGroup()); 58 | require(metricsGroup.isGroup(_metrics), "address is not metrics"); 59 | 60 | /** 61 | * Validates the sender is included in the Market address set. 62 | */ 63 | require( 64 | IMarketGroup(config().marketGroup()).isGroup(msg.sender), 65 | "this is illegal address" 66 | ); 67 | 68 | /** 69 | * Validates the sender is the Market contract associated with the passed Metrics. 70 | */ 71 | IMetrics metrics = IMetrics(_metrics); 72 | require(msg.sender == metrics.market(), "this is illegal address"); 73 | 74 | /** 75 | * Logical deletions a Metrics contract. 76 | */ 77 | IMetricsGroup(config().metricsGroup()).removeGroup(_metrics); 78 | emit Destroy(msg.sender, _metrics); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /contracts/src/metrics/MetricsGroup.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; 4 | import "../common/config/UsingConfig.sol"; 5 | import "../common/storage/UsingStorage.sol"; 6 | import "../../interface/IMetrics.sol"; 7 | import "../../interface/IMetricsGroup.sol"; 8 | 9 | contract MetricsGroup is UsingConfig, UsingStorage, IMetricsGroup { 10 | using SafeMath for uint256; 11 | 12 | constructor(address _config) public UsingConfig(_config) {} 13 | 14 | function addGroup(address _addr) external { 15 | require( 16 | msg.sender == config().metricsFactory(), 17 | "this is illegal address" 18 | ); 19 | 20 | require( 21 | eternalStorage().getBool(getGroupKey(_addr)) == false, 22 | "already enabled" 23 | ); 24 | eternalStorage().setBool(getGroupKey(_addr), true); 25 | address property = IMetrics(_addr).property(); 26 | uint256 totalCount = eternalStorage().getUint(getTotalCountKey()); 27 | uint256 metricsCountPerProperty = getMetricsCountPerProperty(property); 28 | if (metricsCountPerProperty == 0) { 29 | uint256 tmp = eternalStorage().getUint( 30 | getTotalAuthenticatedPropertiesKey() 31 | ); 32 | setTotalAuthenticatedProperties(tmp.add(1)); 33 | } 34 | totalCount = totalCount.add(1); 35 | metricsCountPerProperty = metricsCountPerProperty.add(1); 36 | setTotalIssuedMetrics(totalCount); 37 | setMetricsCountPerProperty(property, metricsCountPerProperty); 38 | } 39 | 40 | function removeGroup(address _addr) external { 41 | require( 42 | msg.sender == config().metricsFactory(), 43 | "this is illegal address" 44 | ); 45 | 46 | require( 47 | eternalStorage().getBool(getGroupKey(_addr)), 48 | "address is not group" 49 | ); 50 | eternalStorage().setBool(getGroupKey(_addr), false); 51 | address property = IMetrics(_addr).property(); 52 | uint256 totalCount = eternalStorage().getUint(getTotalCountKey()); 53 | uint256 metricsCountPerProperty = getMetricsCountPerProperty(property); 54 | if (metricsCountPerProperty == 1) { 55 | uint256 tmp = eternalStorage().getUint( 56 | getTotalAuthenticatedPropertiesKey() 57 | ); 58 | setTotalAuthenticatedProperties(tmp.sub(1)); 59 | } 60 | totalCount = totalCount.sub(1); 61 | metricsCountPerProperty = metricsCountPerProperty.sub(1); 62 | setTotalIssuedMetrics(totalCount); 63 | setMetricsCountPerProperty(property, metricsCountPerProperty); 64 | } 65 | 66 | function isGroup(address _addr) external view returns (bool) { 67 | return eternalStorage().getBool(getGroupKey(_addr)); 68 | } 69 | 70 | function totalIssuedMetrics() external view returns (uint256) { 71 | return eternalStorage().getUint(getTotalCountKey()); 72 | } 73 | 74 | function totalAuthenticatedProperties() external view returns (uint256) { 75 | return eternalStorage().getUint(getTotalAuthenticatedPropertiesKey()); 76 | } 77 | 78 | function hasAssets(address _property) external view returns (bool) { 79 | return getMetricsCountPerProperty(_property) > 0; 80 | } 81 | 82 | function getMetricsCountPerProperty(address _property) 83 | public 84 | view 85 | returns (uint256) 86 | { 87 | return 88 | eternalStorage().getUint(getMetricsCountPerPropertyKey(_property)); 89 | } 90 | 91 | function setMetricsCountPerProperty(address _property, uint256 _value) 92 | internal 93 | { 94 | eternalStorage().setUint( 95 | getMetricsCountPerPropertyKey(_property), 96 | _value 97 | ); 98 | } 99 | 100 | function setTotalIssuedMetrics(uint256 _value) private { 101 | eternalStorage().setUint(getTotalCountKey(), _value); 102 | } 103 | 104 | function setTotalAuthenticatedProperties(uint256 _value) private { 105 | eternalStorage().setUint(getTotalAuthenticatedPropertiesKey(), _value); 106 | } 107 | 108 | function getTotalCountKey() private pure returns (bytes32) { 109 | return keccak256(abi.encodePacked("_totalCount")); 110 | } 111 | 112 | function getMetricsCountPerPropertyKey(address _property) 113 | private 114 | pure 115 | returns (bytes32) 116 | { 117 | return 118 | keccak256(abi.encodePacked("_metricsCountPerProperty", _property)); 119 | } 120 | 121 | function getGroupKey(address _addr) private pure returns (bytes32) { 122 | return keccak256(abi.encodePacked("_group", _addr)); 123 | } 124 | 125 | function getTotalAuthenticatedPropertiesKey() 126 | private 127 | pure 128 | returns (bytes32) 129 | { 130 | return keccak256(abi.encodePacked("_totalAuthenticatedProperties")); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /contracts/src/policy/DIP1.sol: -------------------------------------------------------------------------------- 1 | /* solhint-disable const-name-snakecase */ 2 | /* solhint-disable var-name-mixedcase */ 3 | pragma solidity 0.5.17; 4 | 5 | import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; 6 | import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 7 | import "../common/config/UsingConfig.sol"; 8 | import "../../interface/IPolicy.sol"; 9 | 10 | /** 11 | * DIP1 is a contract that simply changed TheFirstPolicy to DIP numbering. 12 | */ 13 | contract DIP1 is IPolicy, UsingConfig { 14 | using SafeMath for uint256; 15 | uint256 public marketVotingBlocks = 525600; 16 | uint256 public policyVotingBlocks = 525600; 17 | 18 | uint256 private constant basis = 10000000000000000000000000; 19 | uint256 private constant power_basis = 10000000000; 20 | uint256 private constant mint_per_block_and_aseet = 250000000000000; 21 | 22 | constructor(address _config) public UsingConfig(_config) {} 23 | 24 | function rewards(uint256 _lockups, uint256 _assets) 25 | external 26 | view 27 | returns (uint256) 28 | { 29 | uint256 max = _assets.mul(mint_per_block_and_aseet); 30 | uint256 t = ERC20(config().token()).totalSupply(); 31 | uint256 s = (_lockups.mul(basis)).div(t); 32 | uint256 _d = basis.sub(s); 33 | uint256 _p = ( 34 | (power_basis.mul(12)).sub(s.div((basis.div((power_basis.mul(10)))))) 35 | ).div(2); 36 | uint256 p = _p.div(power_basis); 37 | uint256 rp = p.add(1); 38 | uint256 f = _p.sub(p.mul(power_basis)); 39 | uint256 d1 = _d; 40 | uint256 d2 = _d; 41 | for (uint256 i = 0; i < p; i++) { 42 | d1 = (d1.mul(_d)).div(basis); 43 | } 44 | for (uint256 i = 0; i < rp; i++) { 45 | d2 = (d2.mul(_d)).div(basis); 46 | } 47 | uint256 g = ((d1.sub(d2)).mul(f)).div(power_basis); 48 | uint256 d = d1.sub(g); 49 | uint256 mint = max.mul(d); 50 | mint = mint.div(basis); 51 | return mint; 52 | } 53 | 54 | function holdersShare(uint256 _reward, uint256 _lockups) 55 | external 56 | view 57 | returns (uint256) 58 | { 59 | return _lockups > 0 ? (_reward.mul(51)).div(100) : _reward; 60 | } 61 | 62 | function authenticationFee(uint256 total_assets, uint256 property_lockups) 63 | external 64 | view 65 | returns (uint256) 66 | { 67 | uint256 a = total_assets.div(10000); 68 | uint256 b = property_lockups.div(100000000000000000000000); 69 | if (a <= b) { 70 | return 0; 71 | } 72 | return a.sub(b); 73 | } 74 | 75 | function shareOfTreasury(uint256) external view returns (uint256) { 76 | return 0; 77 | } 78 | 79 | function treasury() external view returns (address) { 80 | return address(0); 81 | } 82 | 83 | function capSetter() external view returns (address) { 84 | return address(0); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /contracts/src/policy/DIP55.sol: -------------------------------------------------------------------------------- 1 | /* solhint-disable const-name-snakecase */ 2 | pragma solidity 0.5.17; 3 | 4 | import {Ownable} from "@openzeppelin/contracts/ownership/Ownable.sol"; 5 | import "./Patch780.sol"; 6 | 7 | /** 8 | * GeometricMean is a contract that changes the `rewards` of DIP7. 9 | */ 10 | contract DIP55 is Patch780 { 11 | address private capSetterAddress; 12 | 13 | constructor(address _config) public Patch780(_config) {} 14 | 15 | function setCapSetter(address _setter) external onlyOwner { 16 | capSetterAddress = _setter; 17 | } 18 | 19 | function capSetter() external view returns (address) { 20 | return capSetterAddress; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /contracts/src/policy/DIP7.sol: -------------------------------------------------------------------------------- 1 | /* solhint-disable const-name-snakecase */ 2 | pragma solidity 0.5.17; 3 | 4 | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import "./DIP1.sol"; 6 | import "../common/libs/Curve.sol"; 7 | 8 | /** 9 | * DIP7 is a contract that changes the `rewards` of DIP1. 10 | */ 11 | contract DIP7 is DIP1, Curve { 12 | uint256 private constant mint_per_block_and_aseet = 120000000000000; 13 | 14 | constructor(address _config) public DIP1(_config) {} 15 | 16 | function rewards(uint256 _lockups, uint256 _assets) 17 | external 18 | view 19 | returns (uint256) 20 | { 21 | uint256 totalSupply = IERC20(config().token()).totalSupply(); 22 | return 23 | curveRewards( 24 | _lockups, 25 | _assets, 26 | totalSupply, 27 | mint_per_block_and_aseet 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /contracts/src/policy/Patch780.sol: -------------------------------------------------------------------------------- 1 | /* solhint-disable const-name-snakecase */ 2 | pragma solidity 0.5.17; 3 | 4 | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import "./TreasuryFee.sol"; 6 | 7 | contract Patch780 is TreasuryFee { 8 | uint256 private constant mint_per_block_and_aseet = 132000000000000; 9 | 10 | constructor(address _config) public TreasuryFee(_config) {} 11 | 12 | function rewards(uint256 _lockups, uint256 _assets) 13 | external 14 | view 15 | returns (uint256) 16 | { 17 | uint256 totalSupply = IERC20(config().token()).totalSupply(); 18 | return 19 | curveRewards( 20 | _lockups, 21 | _assets, 22 | totalSupply, 23 | mint_per_block_and_aseet 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/src/policy/PolicyFactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {Ownable} from "@openzeppelin/contracts/ownership/Ownable.sol"; 4 | import "../common/config/UsingConfig.sol"; 5 | import "../../interface/IPolicyGroup.sol"; 6 | import "../../interface/IPolicyFactory.sol"; 7 | 8 | /** 9 | * A factory contract that creates a new Policy contract. 10 | */ 11 | contract PolicyFactory is UsingConfig, IPolicyFactory, Ownable { 12 | event Create(address indexed _from, address _policy); 13 | 14 | /** 15 | * Initialize the passed address as AddressConfig address. 16 | */ 17 | constructor(address _config) public UsingConfig(_config) {} 18 | 19 | /** 20 | * Creates a new Policy contract. 21 | */ 22 | function create(address _newPolicyAddress) external { 23 | /** 24 | * Validates the passed address is not 0 address. 25 | */ 26 | require(_newPolicyAddress != address(0), "this is illegal address"); 27 | 28 | emit Create(msg.sender, _newPolicyAddress); 29 | 30 | /** 31 | * In the case of the first Policy, it will be activated immediately. 32 | */ 33 | IPolicyGroup policyGroup = IPolicyGroup(config().policyGroup()); 34 | if (config().policy() == address(0)) { 35 | config().setPolicy(_newPolicyAddress); 36 | } 37 | 38 | /** 39 | * Adds the created Policy contract to the Policy address set. 40 | */ 41 | policyGroup.addGroup(_newPolicyAddress); 42 | } 43 | 44 | /** 45 | * Set the policy to force a policy without a vote. 46 | */ 47 | function forceAttach(address _policy) external onlyOwner { 48 | /** 49 | * Validates the passed Policy address is included the Policy address set 50 | */ 51 | require( 52 | IPolicyGroup(config().policyGroup()).isGroup(_policy), 53 | "this is illegal address" 54 | ); 55 | /** 56 | * Validates the voting deadline has not passed. 57 | */ 58 | IPolicyGroup policyGroup = IPolicyGroup(config().policyGroup()); 59 | require(policyGroup.isDuringVotingPeriod(_policy), "deadline is over"); 60 | 61 | /** 62 | * Sets the passed Policy to current Policy. 63 | */ 64 | config().setPolicy(_policy); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /contracts/src/policy/PolicyGroup.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; 4 | import "../common/config/UsingConfig.sol"; 5 | import "../common/storage/UsingStorage.sol"; 6 | import "../../interface/IPolicyGroup.sol"; 7 | import "../../interface/IPolicy.sol"; 8 | 9 | contract PolicyGroup is UsingConfig, UsingStorage, IPolicyGroup { 10 | using SafeMath for uint256; 11 | 12 | constructor(address _config) public UsingConfig(_config) {} 13 | 14 | function addGroup(address _addr) external { 15 | require( 16 | msg.sender == config().policyFactory(), 17 | "this is illegal address" 18 | ); 19 | bytes32 key = getGroupKey(_addr); 20 | require(eternalStorage().getBool(key) == false, "already group"); 21 | eternalStorage().setBool(key, true); 22 | setVotingEndBlockNumber(_addr); 23 | } 24 | 25 | function isGroup(address _addr) external view returns (bool) { 26 | return eternalStorage().getBool(getGroupKey(_addr)); 27 | } 28 | 29 | function isDuringVotingPeriod(address _policy) 30 | external 31 | view 32 | returns (bool) 33 | { 34 | bytes32 key = getVotingEndBlockNumberKey(_policy); 35 | uint256 votingEndBlockNumber = eternalStorage().getUint(key); 36 | return block.number < votingEndBlockNumber; 37 | } 38 | 39 | function setVotingEndBlockNumber(address _policy) private { 40 | require( 41 | msg.sender == config().policyFactory(), 42 | "this is illegal address" 43 | ); 44 | bytes32 key = getVotingEndBlockNumberKey(_policy); 45 | uint256 tmp = IPolicy(config().policy()).policyVotingBlocks(); 46 | uint256 votingEndBlockNumber = block.number.add(tmp); 47 | eternalStorage().setUint(key, votingEndBlockNumber); 48 | } 49 | 50 | function getVotingEndBlockNumberKey(address _policy) 51 | private 52 | pure 53 | returns (bytes32) 54 | { 55 | return keccak256(abi.encodePacked("_votingEndBlockNumber", _policy)); 56 | } 57 | 58 | function getGroupKey(address _addr) private pure returns (bytes32) { 59 | return keccak256(abi.encodePacked("_group", _addr)); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /contracts/src/policy/TheFirstPolicy.sol: -------------------------------------------------------------------------------- 1 | /* solhint-disable const-name-snakecase */ 2 | /* solhint-disable var-name-mixedcase */ 3 | pragma solidity 0.5.17; 4 | 5 | import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; 6 | import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 7 | import "../common/config/UsingConfig.sol"; 8 | import "../../interface/IPolicy.sol"; 9 | 10 | /** 11 | * TheFirstPolicy is the first policy contract. 12 | */ 13 | contract TheFirstPolicy is IPolicy, UsingConfig { 14 | using SafeMath for uint256; 15 | uint256 public marketVotingBlocks = 525600; 16 | uint256 public policyVotingBlocks = 525600; 17 | 18 | uint256 private constant basis = 10000000000000000000000000; 19 | uint256 private constant power_basis = 10000000000; 20 | uint256 private constant mint_per_block_and_aseet = 250000000000000; 21 | 22 | constructor(address _config) public UsingConfig(_config) {} 23 | 24 | function rewards(uint256 _lockups, uint256 _assets) 25 | external 26 | view 27 | returns (uint256) 28 | { 29 | uint256 max = _assets.mul(mint_per_block_and_aseet); 30 | uint256 t = ERC20(config().token()).totalSupply(); 31 | uint256 s = (_lockups.mul(basis)).div(t); 32 | uint256 _d = basis.sub(s); 33 | uint256 _p = ( 34 | (power_basis.mul(12)).sub(s.div((basis.div((power_basis.mul(10)))))) 35 | ).div(2); 36 | uint256 p = _p.div(power_basis); 37 | uint256 rp = p.add(1); 38 | uint256 f = _p.sub(p.mul(power_basis)); 39 | uint256 d1 = _d; 40 | uint256 d2 = _d; 41 | for (uint256 i = 0; i < p; i++) { 42 | d1 = (d1.mul(_d)).div(basis); 43 | } 44 | for (uint256 i = 0; i < rp; i++) { 45 | d2 = (d2.mul(_d)).div(basis); 46 | } 47 | uint256 g = ((d1.sub(d2)).mul(f)).div(power_basis); 48 | uint256 d = d1.sub(g); 49 | uint256 mint = max.mul(d); 50 | mint = mint.div(basis); 51 | return mint; 52 | } 53 | 54 | function holdersShare(uint256 _reward, uint256 _lockups) 55 | external 56 | view 57 | returns (uint256) 58 | { 59 | return _lockups > 0 ? (_reward.mul(95)).div(100) : _reward; 60 | } 61 | 62 | function authenticationFee(uint256 total_assets, uint256 property_lockups) 63 | external 64 | view 65 | returns (uint256) 66 | { 67 | uint256 a = total_assets.div(10000); 68 | uint256 b = property_lockups.div(100000000000000000000000); 69 | if (a <= b) { 70 | return 0; 71 | } 72 | return a.sub(b); 73 | } 74 | 75 | function shareOfTreasury(uint256) external view returns (uint256) { 76 | return 0; 77 | } 78 | 79 | function treasury() external view returns (address) { 80 | return address(0); 81 | } 82 | 83 | function capSetter() external view returns (address) { 84 | return address(0); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /contracts/src/policy/TreasuryFee.sol: -------------------------------------------------------------------------------- 1 | /* solhint-disable const-name-snakecase */ 2 | pragma solidity 0.5.17; 3 | 4 | import {Ownable} from "@openzeppelin/contracts/ownership/Ownable.sol"; 5 | import "./DIP7.sol"; 6 | 7 | /** 8 | * TreasuryFee is a contract that changes the `rewards` of DIP7. 9 | */ 10 | contract TreasuryFee is DIP7, Ownable { 11 | address private treasuryAddress; 12 | 13 | constructor(address _config) public DIP7(_config) {} 14 | 15 | function shareOfTreasury(uint256 _supply) external view returns (uint256) { 16 | return _supply.div(100).mul(5); 17 | } 18 | 19 | function treasury() external view returns (address) { 20 | return treasuryAddress; 21 | } 22 | 23 | function setTreasury(address _treasury) external onlyOwner { 24 | treasuryAddress = _treasury; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/src/property/PropertyGroup.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import "../common/config/UsingConfig.sol"; 4 | import "../common/storage/UsingStorage.sol"; 5 | import "../../interface/IPropertyGroup.sol"; 6 | 7 | contract PropertyGroup is UsingConfig, UsingStorage, IPropertyGroup { 8 | constructor(address _config) public UsingConfig(_config) {} 9 | 10 | function addGroup(address _addr) external { 11 | require( 12 | msg.sender == config().propertyFactory(), 13 | "this is illegal address" 14 | ); 15 | 16 | require( 17 | eternalStorage().getBool(getGroupKey(_addr)) == false, 18 | "already enabled" 19 | ); 20 | eternalStorage().setBool(getGroupKey(_addr), true); 21 | } 22 | 23 | function isGroup(address _addr) external view returns (bool) { 24 | return eternalStorage().getBool(getGroupKey(_addr)); 25 | } 26 | 27 | function getGroupKey(address _addr) private pure returns (bytes32) { 28 | return keccak256(abi.encodePacked("_group", _addr)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /contracts/test/common/config/UsingConfig.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {UsingConfig} from "../../../src/common/config/UsingConfig.sol"; 4 | import {IAddressConfig} from "../../../interface/IAddressConfig.sol"; 5 | 6 | contract UsingConfigTest is UsingConfig { 7 | constructor(address _config) public UsingConfig(_config) {} 8 | 9 | function getToken() external view returns (address) { 10 | return config().token(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/test/common/libs/Decimals.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {Decimals} from "../../../src/common/libs/Decimals.sol"; 4 | 5 | contract DecimalsTest { 6 | using Decimals for uint256; 7 | 8 | function outOf(uint256 _a, uint256 _b) 9 | external 10 | pure 11 | returns (uint256 result) 12 | { 13 | return _a.outOf(_b); 14 | } 15 | 16 | function mulBasis(uint256 _a) external pure returns (uint256 result) { 17 | return _a.mulBasis(); 18 | } 19 | 20 | function divBasis(uint256 _a) external pure returns (uint256 result) { 21 | return _a.divBasis(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/test/common/storage/UsingStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {UsingStorage} from "../../../src/common/storage/UsingStorage.sol"; 4 | 5 | contract UsingStorageTest is UsingStorage { 6 | function getEternalStorageAddress() public view returns (address) { 7 | return address(eternalStorage()); 8 | } 9 | 10 | function setUInt(uint256 _value) external { 11 | eternalStorage().setUint(getUintKey(), _value); 12 | } 13 | 14 | function getUInt() external view returns (uint256) { 15 | return eternalStorage().getUint(getUintKey()); 16 | } 17 | 18 | function getUintKey() private pure returns (bytes32) { 19 | return keccak256(abi.encodePacked("_uint")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /contracts/test/lockup/LockupStorageTest.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {LockupStorage} from "../../src/lockup/LockupStorage.sol"; 4 | 5 | contract LockupStorageTest is LockupStorage { 6 | function setStorageAllValueTest(uint256 _value) external { 7 | setStorageAllValue(_value); 8 | } 9 | 10 | function setStorageValueTest( 11 | address _property, 12 | address _sender, 13 | uint256 _value 14 | ) external { 15 | setStorageValue(_property, _sender, _value); 16 | } 17 | 18 | function setStorageInterestPriceTest(address _property, uint256 _value) 19 | external 20 | { 21 | setStorageInterestPrice(_property, _value); 22 | } 23 | 24 | function setStorageLastInterestPriceTest( 25 | address _property, 26 | address _user, 27 | uint256 _value 28 | ) external { 29 | setStorageLastInterestPrice(_property, _user, _value); 30 | } 31 | 32 | function setStorageLastSameRewardsAmountAndBlockTest( 33 | uint256 _amount, 34 | uint256 _block 35 | ) external { 36 | setStorageLastSameRewardsAmountAndBlock(_amount, _block); 37 | } 38 | 39 | function setStorageCumulativeGlobalRewardsTest(uint256 _value) external { 40 | setStorageCumulativeGlobalRewards(_value); 41 | } 42 | 43 | function setStoragePendingInterestWithdrawalTest( 44 | address _property, 45 | address _user, 46 | uint256 _value 47 | ) external { 48 | setStoragePendingInterestWithdrawal(_property, _user, _value); 49 | } 50 | 51 | function setStorageDIP4GenesisBlockTest(uint256 _block) external { 52 | setStorageDIP4GenesisBlock(_block); 53 | } 54 | 55 | function setStorageLastStakedInterestPriceTest( 56 | address _property, 57 | address _user, 58 | uint256 _value 59 | ) external { 60 | setStorageLastStakedInterestPrice(_property, _user, _value); 61 | } 62 | 63 | function setStorageLastStakesChangedCumulativeRewardTest(uint256 _value) 64 | external 65 | { 66 | setStorageLastStakesChangedCumulativeReward(_value); 67 | } 68 | 69 | function setStorageLastCumulativeHoldersRewardPriceTest(uint256 _a) 70 | external 71 | { 72 | setStorageLastCumulativeHoldersRewardPrice(_a); 73 | } 74 | 75 | function setStorageLastCumulativeInterestPriceTest(uint256 _a) external { 76 | setStorageLastCumulativeInterestPrice(_a); 77 | } 78 | 79 | function setStorageLastCumulativeHoldersRewardAmountPerPropertyTest( 80 | address _property, 81 | uint256 _value 82 | ) external { 83 | setStorageLastCumulativeHoldersRewardAmountPerProperty( 84 | _property, 85 | _value 86 | ); 87 | } 88 | 89 | function setStorageLastCumulativeHoldersRewardPricePerPropertyTest( 90 | address _property, 91 | uint256 _value 92 | ) external { 93 | setStorageLastCumulativeHoldersRewardPricePerProperty( 94 | _property, 95 | _value 96 | ); 97 | } 98 | 99 | function setStorageCapTest(uint256 _value) external { 100 | setStorageCap(_value); 101 | } 102 | 103 | function setStorageCumulativeHoldersRewardCapTest(uint256 _value) external { 104 | setStorageCumulativeHoldersRewardCap(_value); 105 | } 106 | 107 | function setStorageLastCumulativeHoldersPriceCapTest(uint256 _value) 108 | external 109 | { 110 | setStorageLastCumulativeHoldersPriceCap(_value); 111 | } 112 | 113 | function setStorageInitialCumulativeHoldersRewardCapTest( 114 | address _property, 115 | uint256 _value 116 | ) external { 117 | setStorageInitialCumulativeHoldersRewardCap(_property, _value); 118 | } 119 | 120 | function setStorageFallbackInitialCumulativeHoldersRewardCapTest( 121 | uint256 _value 122 | ) external { 123 | setStorageFallbackInitialCumulativeHoldersRewardCap(_value); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /contracts/test/lockup/LockupTest.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {Lockup} from "../../src/lockup/Lockup.sol"; 4 | import {LockupStorageTest} from "./LockupStorageTest.sol"; 5 | 6 | contract LockupTest is LockupStorageTest, Lockup { 7 | constructor( 8 | address _config, 9 | address _devMinter, 10 | address _sTokensManager 11 | ) public Lockup(_config, _devMinter, _sTokensManager) {} 12 | } 13 | -------------------------------------------------------------------------------- /contracts/test/market/MarketTest1.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {Ownable} from "@openzeppelin/contracts/ownership/Ownable.sol"; 4 | import {UsingConfig} from "../../src/common/config/UsingConfig.sol"; 5 | import {IMarketBehavior} from "../../interface/IMarketBehavior.sol"; 6 | import {IMarket} from "../../interface/IMarket.sol"; 7 | 8 | contract MarketTest1 is Ownable, IMarketBehavior, UsingConfig { 9 | string public schema = "[]"; 10 | address private associatedMarket; 11 | address private metrics; 12 | uint256 private lastBlock; 13 | uint256 private currentBlock; 14 | mapping(address => string) private keys; 15 | mapping(string => address) private addresses; 16 | 17 | constructor(address _config) public UsingConfig(_config) {} 18 | 19 | function authenticate( 20 | address _prop, 21 | string memory _args1, 22 | string memory, 23 | string memory, 24 | string memory, 25 | string memory, 26 | address market, 27 | address 28 | ) public returns (bool) { 29 | require(msg.sender == associatedMarket, "Invalid sender"); 30 | 31 | bytes32 idHash = keccak256(abi.encodePacked(_args1)); 32 | address _metrics = IMarket(market).authenticatedCallback(_prop, idHash); 33 | keys[_metrics] = _args1; 34 | addresses[_args1] = _metrics; 35 | return true; 36 | } 37 | 38 | function getId(address _metrics) public view returns (string memory) { 39 | return keys[_metrics]; 40 | } 41 | 42 | function getMetrics(string memory _id) public view returns (address) { 43 | return addresses[_id]; 44 | } 45 | 46 | function setAssociatedMarket(address _associatedMarket) external onlyOwner { 47 | associatedMarket = _associatedMarket; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /contracts/test/market/MarketTest2.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {Ownable} from "@openzeppelin/contracts/ownership/Ownable.sol"; 4 | import {UsingConfig} from "../../src/common/config/UsingConfig.sol"; 5 | import {IMarketBehavior} from "../../interface/IMarketBehavior.sol"; 6 | import {IMarket} from "../../interface/IMarket.sol"; 7 | 8 | contract MarketTest2 is Ownable, IMarketBehavior, UsingConfig { 9 | string public schema = "[]"; 10 | address private associatedMarket; 11 | mapping(address => string) internal keys; 12 | mapping(string => address) private addresses; 13 | 14 | constructor(address _config) public UsingConfig(_config) {} 15 | 16 | function authenticate( 17 | address _prop, 18 | string memory _args1, 19 | string memory, 20 | string memory, 21 | string memory, 22 | string memory, 23 | address market, 24 | address 25 | ) public returns (bool) { 26 | require(msg.sender == associatedMarket, "Invalid sender"); 27 | 28 | bytes32 idHash = keccak256(abi.encodePacked(_args1)); 29 | address _metrics = IMarket(market).authenticatedCallback(_prop, idHash); 30 | keys[_metrics] = _args1; 31 | addresses[_args1] = _metrics; 32 | return true; 33 | } 34 | 35 | function getId(address _metrics) public view returns (string memory) { 36 | return keys[_metrics]; 37 | } 38 | 39 | function getMetrics(string memory _id) public view returns (address) { 40 | return addresses[_id]; 41 | } 42 | 43 | function setAssociatedMarket(address _associatedMarket) external onlyOwner { 44 | associatedMarket = _associatedMarket; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /contracts/test/market/MarketTest3.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {Ownable} from "@openzeppelin/contracts/ownership/Ownable.sol"; 4 | import {UsingConfig} from "../../src/common/config/UsingConfig.sol"; 5 | import {IMarketBehavior} from "../../interface/IMarketBehavior.sol"; 6 | import {IMarket} from "../../interface/IMarket.sol"; 7 | 8 | contract MarketTest3 is Ownable, IMarketBehavior, UsingConfig { 9 | string public schema = "[]"; 10 | address private associatedMarket; 11 | mapping(address => string) internal keys; 12 | mapping(string => address) private addresses; 13 | address public currentAuthinticateAccount; 14 | 15 | constructor(address _config) public UsingConfig(_config) {} 16 | 17 | function authenticate( 18 | address _prop, 19 | string memory _args1, 20 | string memory, 21 | string memory, 22 | string memory, 23 | string memory, 24 | address market, 25 | address account 26 | ) public returns (bool) { 27 | require(msg.sender == associatedMarket, "Invalid sender"); 28 | 29 | bytes32 idHash = keccak256(abi.encodePacked(_args1)); 30 | address _metrics = IMarket(market).authenticatedCallback(_prop, idHash); 31 | keys[_metrics] = _args1; 32 | addresses[_args1] = _metrics; 33 | currentAuthinticateAccount = account; 34 | return true; 35 | } 36 | 37 | function getId(address _metrics) public view returns (string memory) { 38 | return keys[_metrics]; 39 | } 40 | 41 | function getMetrics(string memory _id) public view returns (address) { 42 | return addresses[_id]; 43 | } 44 | 45 | function setAssociatedMarket(address _associatedMarket) external onlyOwner { 46 | associatedMarket = _associatedMarket; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /contracts/test/metrics/MetricsGroupTest.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {MetricsGroup} from "../../src/metrics/MetricsGroup.sol"; 4 | 5 | contract MetricsGroupTest is MetricsGroup { 6 | constructor(address _config) public MetricsGroup(_config) {} 7 | 8 | function __setMetricsCountPerProperty(address _property, uint256 _value) 9 | external 10 | { 11 | setMetricsCountPerProperty(_property, _value); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /contracts/test/policy/PolicyTest1.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {PolicyTestBase} from "./PolicyTestBase.sol"; 4 | import {Decimals} from "../../src/common/libs/Decimals.sol"; 5 | 6 | contract PolicyTest1 is PolicyTestBase { 7 | using Decimals for uint256; 8 | 9 | function rewards(uint256 _lockups, uint256 _assets) 10 | external 11 | view 12 | returns (uint256) 13 | { 14 | return _lockups + _assets; 15 | } 16 | 17 | function holdersShare(uint256 _amount, uint256 _lockups) 18 | external 19 | view 20 | returns (uint256) 21 | { 22 | uint256 sum = _amount + _lockups; 23 | uint256 share = _lockups.outOf(sum); 24 | return _amount - (_amount * share).divBasis(); 25 | } 26 | 27 | function authenticationFee(uint256 _assets, uint256 _propertyLockups) 28 | external 29 | view 30 | returns (uint256) 31 | { 32 | return _assets + _propertyLockups - 1; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/test/policy/PolicyTestBase.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; 4 | import {IPolicy} from "../../interface/IPolicy.sol"; 5 | 6 | contract PolicyTestBase is IPolicy { 7 | using SafeMath for uint256; 8 | address public treasury; 9 | address public capSetter; 10 | 11 | // solhint-disable-next-line no-unused-vars 12 | function rewards(uint256 _lockups, uint256 _assets) 13 | external 14 | view 15 | returns (uint256) 16 | { 17 | return 100000000000000000000; 18 | } 19 | 20 | function holdersShare(uint256 _amount, uint256 _lockups) 21 | external 22 | view 23 | returns (uint256) 24 | { 25 | return _lockups > 0 ? (_amount * 90) / 100 : _amount; 26 | } 27 | 28 | function authenticationFee(uint256 _assets, uint256 _propertyLockups) 29 | external 30 | view 31 | returns (uint256) 32 | { 33 | return _assets + _propertyLockups + 1; 34 | } 35 | 36 | function marketVotingBlocks() external view returns (uint256) { 37 | return 10; 38 | } 39 | 40 | function policyVotingBlocks() external view returns (uint256) { 41 | return 20; 42 | } 43 | 44 | function shareOfTreasury(uint256 _supply) external view returns (uint256) { 45 | return _supply.div(100).mul(5); 46 | } 47 | 48 | function setTreasury(address _treasury) external { 49 | treasury = _treasury; 50 | } 51 | 52 | function setCapSetter(address _capSetter) external { 53 | capSetter = _capSetter; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /contracts/test/policy/PolicyTestForAllocator.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {PolicyTestBase} from "./PolicyTestBase.sol"; 4 | 5 | contract PolicyTestForAllocator is PolicyTestBase { 6 | function rewards(uint256 _lockups, uint256 _assets) 7 | external 8 | view 9 | returns (uint256) 10 | { 11 | return _assets > 0 ? _lockups : 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /contracts/test/policy/PolicyTestForPolicyFactory.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {PolicyTestBase} from "./PolicyTestBase.sol"; 4 | 5 | contract PolicyTestForPolicyFactory is PolicyTestBase { 6 | function policyVotingBlocks() external view returns (uint256) { 7 | return 10; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /contracts/test/policy/PolicyTestForProperty.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {PolicyTestBase} from "./PolicyTestBase.sol"; 4 | 5 | contract PolicyTestForProperty is PolicyTestBase { 6 | function rewards(uint256 _lockups, uint256 _assets) 7 | external 8 | view 9 | returns (uint256) 10 | { 11 | return _assets > 0 ? _lockups : 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /contracts/test/policy/PolicyTestForWithdraw.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {PolicyTestBase} from "./PolicyTestBase.sol"; 4 | 5 | contract PolicyTestForWithdraw is PolicyTestBase { 6 | // solhint-disable-next-line no-unused-vars 7 | function rewards(uint256 _lockups, uint256 _assets) 8 | external 9 | view 10 | returns (uint256) 11 | { 12 | return _lockups > 0 ? 100000000000000000000 : 0; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /contracts/test/token/STokenManagerTest.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | pragma experimental ABIEncoderV2; 3 | 4 | import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 5 | import {Counters} from "@openzeppelin/contracts/drafts/Counters.sol"; 6 | import {Strings} from "@openzeppelin/contracts/drafts/Strings.sol"; 7 | import {IAddressConfig} from "../../interface/IAddressConfig.sol"; 8 | 9 | contract STokensManagerTest is ERC721 { 10 | using Counters for Counters.Counter; 11 | using Strings for uint256; 12 | Counters.Counter private _tokenIds; 13 | address public config; 14 | uint256 public latestTokenId; 15 | mapping(bytes32 => bytes) private bytesStorage; 16 | mapping(uint256 => bytes32) private payloadStorage; 17 | 18 | struct StakingPositionV1 { 19 | address property; 20 | uint256 amount; 21 | uint256 price; 22 | uint256 cumulativeReward; 23 | uint256 pendingReward; 24 | } 25 | 26 | modifier onlyLockup() { 27 | require( 28 | IAddressConfig(config).lockup() == _msgSender(), 29 | "illegal access" 30 | ); 31 | _; 32 | } 33 | 34 | function initialize(address _config) external { 35 | config = _config; 36 | } 37 | 38 | function tokenURI(uint256 _tokenId) public pure returns (string memory) { 39 | return _tokenId.fromUint256(); 40 | } 41 | 42 | function mint( 43 | address _owner, 44 | address _property, 45 | uint256 _amount, 46 | uint256 _price, 47 | bytes32 _payload 48 | ) external onlyLockup returns (uint256 tokenId_) { 49 | _tokenIds.increment(); 50 | uint256 newTokenId = _tokenIds.current(); 51 | _safeMint(_owner, newTokenId); 52 | StakingPositionV1 memory newPosition = StakingPositionV1( 53 | _property, 54 | _amount, 55 | _price, 56 | 0, 57 | 0 58 | ); 59 | setStoragePositionsV1(newTokenId, newPosition); 60 | latestTokenId = newTokenId; 61 | payloadStorage[newTokenId] = _payload; 62 | return newTokenId; 63 | } 64 | 65 | function payloadOf(uint256 _tokenId) external view returns (bytes32) { 66 | return payloadStorage[_tokenId]; 67 | } 68 | 69 | function update( 70 | uint256 _tokenId, 71 | uint256 _amount, 72 | uint256 _price, 73 | uint256 _cumulativeReward, 74 | uint256 _pendingReward 75 | ) external onlyLockup returns (bool) { 76 | require(_exists(_tokenId), "not found"); 77 | StakingPositionV1 memory currentPosition = getStoragePositionsV1( 78 | _tokenId 79 | ); 80 | currentPosition.amount = _amount; 81 | currentPosition.price = _price; 82 | currentPosition.cumulativeReward = _cumulativeReward; 83 | currentPosition.pendingReward = _pendingReward; 84 | setStoragePositionsV1(_tokenId, currentPosition); 85 | return true; 86 | } 87 | 88 | function positions(uint256 _tokenId) 89 | external 90 | view 91 | returns ( 92 | address, 93 | uint256, 94 | uint256, 95 | uint256, 96 | uint256 97 | ) 98 | { 99 | StakingPositionV1 memory currentPosition = getStoragePositionsV1( 100 | _tokenId 101 | ); 102 | return ( 103 | currentPosition.property, 104 | currentPosition.amount, 105 | currentPosition.price, 106 | currentPosition.cumulativeReward, 107 | currentPosition.pendingReward 108 | ); 109 | } 110 | 111 | function getStoragePositionsV1(uint256 _tokenId) 112 | private 113 | view 114 | returns (StakingPositionV1 memory) 115 | { 116 | bytes32 key = getStoragePositionsV1Key(_tokenId); 117 | bytes memory tmp = bytesStorage[key]; 118 | require(keccak256(tmp) != keccak256(bytes("")), "illegal token id"); 119 | return abi.decode(tmp, (StakingPositionV1)); 120 | } 121 | 122 | function setStoragePositionsV1( 123 | uint256 _tokenId, 124 | StakingPositionV1 memory _position 125 | ) private { 126 | bytes32 key = getStoragePositionsV1Key(_tokenId); 127 | bytes memory tmp = abi.encode(_position); 128 | bytesStorage[key] = tmp; 129 | } 130 | 131 | function getStoragePositionsV1Key(uint256 _tokenId) 132 | private 133 | pure 134 | returns (bytes32) 135 | { 136 | return keccak256(abi.encodePacked("_positionsV1", _tokenId)); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /contracts/test/treasury/TreasuryTest.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {Ownable} from "@openzeppelin/contracts/ownership/Ownable.sol"; 4 | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 5 | import {IWithdraw} from "../../interface/IWithdraw.sol"; 6 | import {IAddressConfig} from "../../interface/IAddressConfig.sol"; 7 | 8 | contract TreasuryTest is Ownable { 9 | IAddressConfig private config; 10 | 11 | /** 12 | * Initialize the passed address as AddressConfig address. 13 | */ 14 | constructor(address _config) public { 15 | config = IAddressConfig(_config); 16 | } 17 | 18 | function withdraw(address _property) external { 19 | IWithdraw(config.withdraw()).withdraw(_property); 20 | } 21 | 22 | function transfer() external onlyOwner returns (bool) { 23 | IERC20 token = IERC20(config.token()); 24 | uint256 balance = token.balanceOf(address(this)); 25 | return token.transfer(msg.sender, balance); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /contracts/test/withdraw/WithdrawStorageTest.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {WithdrawStorage} from "../../src/withdraw/WithdrawStorage.sol"; 4 | 5 | contract WithdrawStorageTest is WithdrawStorage { 6 | function setRewardsAmountTest(address _property, uint256 _value) external { 7 | setRewardsAmount(_property, _value); 8 | } 9 | 10 | function setCumulativePriceTest(address _property, uint256 _value) 11 | external 12 | { 13 | setCumulativePrice(_property, _value); 14 | } 15 | 16 | function setLastWithdrawalPriceTest( 17 | address _property, 18 | address _user, 19 | uint256 _value 20 | ) external { 21 | setLastWithdrawalPrice(_property, _user, _value); 22 | } 23 | 24 | function setPendingWithdrawalTest( 25 | address _property, 26 | address _user, 27 | uint256 _value 28 | ) external { 29 | setPendingWithdrawal(_property, _user, _value); 30 | } 31 | 32 | function setStorageLastWithdrawnRewardCapTest( 33 | address _property, 34 | address _user, 35 | uint256 _value 36 | ) external { 37 | setStorageLastWithdrawnRewardCap(_property, _user, _value); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/test/withdraw/WithdrawTest.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.17; 2 | 3 | import {Withdraw} from "../../src/withdraw/Withdraw.sol"; 4 | 5 | contract WithdrawTest is Withdraw { 6 | constructor(address _config, address _devMinter) 7 | public 8 | Withdraw(_config, _devMinter) 9 | {} 10 | 11 | function setCumulativePriceTest(address _property, uint256 _value) 12 | external 13 | { 14 | setCumulativePrice(_property, _value); 15 | } 16 | 17 | function setLastWithdrawalPriceTest( 18 | address _property, 19 | address _user, 20 | uint256 _value 21 | ) external { 22 | setLastWithdrawalPrice(_property, _user, _value); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docs/audit-report__quantstamp--sept-15-2020.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-protocol/protocol/02f2a392678b89d731ad048f56dd9dfcdcefaf70/docs/audit-report__quantstamp--sept-15-2020.pdf -------------------------------------------------------------------------------- /migrations/1_address-config.ts: -------------------------------------------------------------------------------- 1 | const handler = function (deployer, network) { 2 | if (network === 'test') { 3 | return 4 | } 5 | 6 | deployer.deploy(artifacts.require('AddressConfig')) 7 | } as Truffle.Migration 8 | 9 | export = handler 10 | -------------------------------------------------------------------------------- /migrations/2_initialize.ts: -------------------------------------------------------------------------------- 1 | const handler = function (deployer, network) { 2 | if (network === 'test') { 3 | return 4 | } 5 | 6 | const { address } = artifacts.require('AddressConfig') 7 | 8 | // Allocator 9 | deployer.deploy(artifacts.require('Allocator'), address) 10 | 11 | // Dev 12 | deployer.deploy(artifacts.require('Dev'), address) 13 | 14 | // Lockup 15 | deployer.deploy(artifacts.require('Lockup'), address, '', '') 16 | 17 | // Market 18 | deployer.deploy(artifacts.require('MarketFactory'), address) 19 | deployer.deploy(artifacts.require('MarketGroup'), address) 20 | 21 | // Metrics 22 | deployer.deploy(artifacts.require('MetricsFactory'), address) 23 | deployer.deploy(artifacts.require('MetricsGroup'), address) 24 | 25 | // Policy 26 | deployer.deploy(artifacts.require('PolicyFactory'), address) 27 | deployer.deploy(artifacts.require('PolicyGroup'), address) 28 | deployer.deploy(artifacts.require('PolicySet'), address) 29 | 30 | // Property 31 | deployer.deploy(artifacts.require('PropertyFactory'), address) 32 | deployer.deploy(artifacts.require('PropertyGroup'), address) 33 | 34 | // Vote 35 | deployer.deploy(artifacts.require('VoteCounter'), address) 36 | 37 | // Withdraw 38 | deployer.deploy(artifacts.require('Withdraw'), address, '') 39 | } as Truffle.Migration 40 | 41 | export = handler 42 | -------------------------------------------------------------------------------- /migrations/3_the-first-policy.ts: -------------------------------------------------------------------------------- 1 | const handler = function (deployer, network) { 2 | if (network === 'test') { 3 | return 4 | } 5 | 6 | const { address } = artifacts.require('AddressConfig') 7 | 8 | deployer.deploy(artifacts.require('TheFirstPolicy'), address) 9 | } as Truffle.Migration 10 | 11 | export = handler 12 | -------------------------------------------------------------------------------- /migrations/4_finalize_initialization.ts: -------------------------------------------------------------------------------- 1 | const handler = function (deployer, network) { 2 | if (network === 'test') { 3 | return 4 | } 5 | 6 | // Allocator 7 | const allocator = artifacts.require('Allocator') 8 | 9 | // Dev 10 | const token = artifacts.require('Dev') 11 | 12 | // Lockup 13 | const lockup = artifacts.require('Lockup') 14 | const lockupStorage = artifacts.require('LockupStorage') 15 | 16 | // Market 17 | const marketFactory = artifacts.require('MarketFactory') 18 | const marketGroup = artifacts.require('MarketGroup') 19 | 20 | // Metrics 21 | const metricsFactory = artifacts.require('MetricsFactory') 22 | const metricsGroup = artifacts.require('MetricsGroup') 23 | 24 | // Policy 25 | const policyFactory = artifacts.require('PolicyFactory') 26 | const policyGroup = artifacts.require('PolicyGroup') 27 | 28 | // Property 29 | const propertyFactory = artifacts.require('PropertyFactory') 30 | const propertyGroup = artifacts.require('PropertyGroup') 31 | 32 | // Withdraw 33 | const withdraw = artifacts.require('Withdraw') 34 | const withdrawStorage = artifacts.require('WithdrawStorage') 35 | ;(deployer as unknown as Promise) 36 | .then(async () => artifacts.require('AddressConfig').deployed()) 37 | .then(async (addressConfig) => 38 | Promise.all([ 39 | addressConfig.setAllocator(allocator.address), 40 | addressConfig.setLockup(lockup.address), 41 | addressConfig.setLockupStorage(lockupStorage.address), 42 | addressConfig.setMarketFactory(marketFactory.address), 43 | addressConfig.setMarketGroup(marketGroup.address), 44 | addressConfig.setMetricsFactory(metricsFactory.address), 45 | addressConfig.setMetricsGroup(metricsGroup.address), 46 | addressConfig.setPolicyFactory(policyFactory.address), 47 | addressConfig.setPolicyGroup(policyGroup.address), 48 | addressConfig.setPropertyFactory(propertyFactory.address), 49 | addressConfig.setPropertyGroup(propertyGroup.address), 50 | addressConfig.setWithdraw(withdraw.address), 51 | addressConfig.setWithdrawStorage(withdrawStorage.address), 52 | addressConfig.setToken(token.address), 53 | ]) 54 | ) 55 | .then(async () => { 56 | console.log('*** Setting AddressConfig is completed ***') 57 | 58 | return Promise.all([ 59 | lockupStorage.deployed(), 60 | marketGroup.deployed(), 61 | metricsGroup.deployed(), 62 | policyGroup.deployed(), 63 | propertyGroup.deployed(), 64 | withdrawStorage.deployed(), 65 | ]) 66 | }) 67 | .then(async (storages) => 68 | Promise.all(storages.map(async (x) => x.createStorage())) 69 | ) 70 | .then(() => { 71 | console.log( 72 | '*** Storage creation for all storage contracts are completed ***' 73 | ) 74 | }) 75 | .catch((err) => { 76 | console.error('*** ERROR! ***', err) 77 | }) 78 | } as Truffle.Migration 79 | 80 | export = handler 81 | -------------------------------------------------------------------------------- /migrations/5_dev-migration.ts: -------------------------------------------------------------------------------- 1 | const legacy = '0x98626e2c9231f03504273d55f397409defd4a093' 2 | 3 | const handler = function (deployer, network) { 4 | if (network === 'test') { 5 | return 6 | } 7 | 8 | const { address: next } = artifacts.require('Dev') 9 | 10 | deployer.deploy(artifacts.require('DevMigration'), legacy, next) 11 | } as Truffle.Migration 12 | 13 | export = handler 14 | -------------------------------------------------------------------------------- /migrations/6_add_minter.ts: -------------------------------------------------------------------------------- 1 | const handler = function (deployer, network) { 2 | if (network === 'test') { 3 | return 4 | } 5 | 6 | const lockup = artifacts.require('Lockup') 7 | const devMigration = artifacts.require('DevMigration') 8 | const withdraw = artifacts.require('Withdraw') 9 | ;(deployer as unknown as Promise) 10 | .then(async () => artifacts.require('Dev').deployed()) 11 | .then(async (dev) => 12 | Promise.all([ 13 | dev.addMinter(devMigration.address), 14 | dev.addMinter(lockup.address), 15 | dev.addMinter(withdraw.address), 16 | ]) 17 | ) 18 | .then(() => { 19 | console.log( 20 | '*** The addition of the address of the contract to mint is completed ***' 21 | ) 22 | }) 23 | .catch((err) => { 24 | console.error('*** ERROR! ***', err) 25 | }) 26 | } as Truffle.Migration 27 | 28 | export = handler 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@devprotocol/protocol", 3 | "version": "3.4.1", 4 | "description": "Securitize for Internet assets", 5 | "scripts": { 6 | "test": "truffle test", 7 | "generate": "truffle compile && typechain --target truffle './build/**/*.json'", 8 | "deploy": "truffle migrate --network", 9 | "predeploy": "yarn build", 10 | "lint": "yarn lint:eslint && yarn lint:solhint && yarn lint:format", 11 | "lint:eslint": "eslint . --ext .ts,.js --fix", 12 | "lint:solhint": "solhint --fix --max-warnings 0 \"contracts/**/*.sol\"", 13 | "lint:format": "prettier --write '**/*.{sol,ts,js,json,md,yml}'", 14 | "prepack": "yarn build", 15 | "build": "tsc -p tsconfig.build.json", 16 | "prebuild": "del 'migrations/**/*.js' 'scripts/**/*.js' && yarn generate", 17 | "prepare": "husky install" 18 | }, 19 | "files": [ 20 | "contracts/interface" 21 | ], 22 | "author": "aggre", 23 | "license": "MPL-2.0", 24 | "devDependencies": { 25 | "@devprotocol/util-ts": "2.2.1", 26 | "@truffle/hdwallet-provider": "2.1.0", 27 | "@types/bent": "7.3.2", 28 | "@types/dotenv": "8.2.0", 29 | "@types/node": "16.18.0", 30 | "@types/shelljs": "0.8.11", 31 | "@typescript-eslint/eslint-plugin": "5.40.1", 32 | "@typescript-eslint/parser": "5.40.1", 33 | "bent": "7.3.12", 34 | "bignumber.js": "9.1.0", 35 | "del-cli": "4.0.1", 36 | "dotenv": "16.0.3", 37 | "eslint": "8.26.0", 38 | "eslint-config-prettier": "8.5.0", 39 | "eslint-config-xo": "0.42.0", 40 | "eslint-config-xo-typescript": "0.50.0", 41 | "husky": "7.0.4", 42 | "p-queue": "7.3.0", 43 | "prettier": "2.7.1", 44 | "prettier-plugin-solidity": "1.0.0-dev.24", 45 | "solhint": "3.3.7", 46 | "truffle": "5.4.29", 47 | "truffle-plugin-verify": "0.5.31", 48 | "truffle-typings": "1.0.8", 49 | "ts-generator": "0.1.1", 50 | "ts-node": "10.9.1", 51 | "typechain": "4.0.3", 52 | "typechain-target-truffle": "1.0.2", 53 | "typescript": "4.8.4", 54 | "web3": "1.7.4" 55 | }, 56 | "dependencies": { 57 | "@devprotocol/i-s-tokens": "2.0.1", 58 | "@openzeppelin/contracts": "2.5.1" 59 | }, 60 | "directories": { 61 | "doc": "docs", 62 | "test": "test" 63 | }, 64 | "repository": { 65 | "type": "git", 66 | "url": "git+https://github.com/dev-protocol/protocol.git" 67 | }, 68 | "bugs": { 69 | "url": "https://github.com/dev-protocol/protocol/issues" 70 | }, 71 | "homepage": "https://github.com/dev-protocol/protocol#readme" 72 | } 73 | -------------------------------------------------------------------------------- /public/asset/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-protocol/protocol/02f2a392678b89d731ad048f56dd9dfcdcefaf70/public/asset/logo.png -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"], 3 | "automerge": true, 4 | "packageRules": [ 5 | { 6 | "packageNames": ["@openzeppelin/contracts"], 7 | "allowedVersions": "2.5.1" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /scripts/1015-desable-market.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | import { config } from 'dotenv' 3 | import { DevCommonInstance } from './lib/instance/common' 4 | import { MarketFactry } from './lib/instance/market-factory' 5 | import { MarketGroup } from './lib/instance/market-group' 6 | 7 | config() 8 | const { CONFIG: configAddress, EGS_TOKEN: egsApiKey } = process.env 9 | 10 | const handler = async ( 11 | callback: (err: Error | undefined) => void 12 | ): Promise => { 13 | if (!configAddress || !egsApiKey) { 14 | return 15 | } 16 | 17 | const gasFetcher = async () => 4000000 18 | const gasPriceFetcher = ethGasStationFetcher(egsApiKey) 19 | const dev = new DevCommonInstance( 20 | artifacts, 21 | configAddress, 22 | gasFetcher, 23 | gasPriceFetcher 24 | ) 25 | await dev.prepare() 26 | 27 | // MarketFactory 28 | const mf = new MarketFactry(dev) 29 | const mfNext = await mf.create() 30 | await mf.set(mfNext) 31 | 32 | // MarketGroup 33 | const mg = new MarketGroup(dev) 34 | const mgCurrent = await mg.load() 35 | const mgNext = await mg.create() 36 | await mg.changeOwner(mgCurrent, mgNext) 37 | await mg.set(mgNext) 38 | 39 | callback(undefined) 40 | } 41 | 42 | export = handler 43 | -------------------------------------------------------------------------------- /scripts/528-change-authenticate-interface.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | 3 | const { CONFIG, EGS_TOKEN } = process.env 4 | const gas = 6721975 5 | 6 | const handler = async ( 7 | callback: (err: Error | undefined) => void 8 | ): Promise => { 9 | if (!CONFIG || !EGS_TOKEN) { 10 | return 11 | } 12 | 13 | const fastest = ethGasStationFetcher(EGS_TOKEN) 14 | 15 | // Generate current contract 16 | const [config] = await Promise.all([ 17 | artifacts.require('AddressConfig').at(CONFIG), 18 | ]) 19 | console.log('Generated AddressConfig contract', config.address) 20 | 21 | // Deploy 22 | const nextMarketFactory = await artifacts 23 | .require('MarketFactory') 24 | .new(config.address, { gasPrice: await fastest(), gas }) 25 | console.log('Deployed the new MarketFactory', nextMarketFactory.address) 26 | 27 | // Enable new Contract 28 | await config.setMarketFactory(nextMarketFactory.address, { 29 | gasPrice: await fastest(), 30 | gas, 31 | }) 32 | console.log('Updated MarketFactory address') 33 | callback(undefined) 34 | } 35 | 36 | export = handler 37 | -------------------------------------------------------------------------------- /scripts/533-1-dip9-migration.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | 3 | const { CONFIG, EGS_TOKEN, DEV_MINTER } = process.env 4 | const gas = 6721975 5 | 6 | const handler = async ( 7 | callback: (err: Error | undefined) => void 8 | ): Promise => { 9 | if (!CONFIG || !EGS_TOKEN || !DEV_MINTER) { 10 | return 11 | } 12 | 13 | // Generate current contract 14 | const [config] = await Promise.all([ 15 | artifacts.require('AddressConfig').at(CONFIG), 16 | ]) 17 | console.log('Generated AddressConfig contract', config.address) 18 | 19 | const [lockup, , dev] = await Promise.all([ 20 | artifacts.require('Lockup').at(await config.lockup()), 21 | artifacts.require('MetricsGroup').at(await config.metricsGroup()), 22 | artifacts.require('Dev').at(await config.token()), 23 | ]) 24 | console.log('Generated current Lockup contract', lockup.address) 25 | console.log('Generated current Dev contract', dev.address) 26 | 27 | const fastest = ethGasStationFetcher(EGS_TOKEN) 28 | 29 | // Deploy new Lockup 30 | const nextLockup = await artifacts 31 | .require('Lockup') 32 | .new(config.address, DEV_MINTER, '', { gasPrice: await fastest(), gas }) 33 | console.log('Deployed the new Lockup', nextLockup.address) 34 | 35 | // Deploy MetricsGroupMigration as a new MetricsGroup 36 | // const nextMetricsGroup = await artifacts 37 | // .require('MetricsGroupMigration') 38 | // .new(config.address, { gasPrice: await fastest(), gas }) 39 | // console.log( 40 | // 'Deployed the new MetricsGroupMigration as a new MetricsGroup', 41 | // nextMetricsGroup.address 42 | // ) 43 | 44 | // Deploy new MetricsFactory 45 | const nextMetricsFactory = await artifacts 46 | .require('MetricsFactory') 47 | .new(config.address, { gasPrice: await fastest(), gas }) 48 | console.log('Deployed the new MetricsFactory', nextMetricsFactory.address) 49 | 50 | // Deploy new Withdraw 51 | const nextWithdraw = await artifacts 52 | .require('Withdraw') 53 | .new(config.address, DEV_MINTER, { gasPrice: await fastest(), gas }) 54 | console.log('Deployed the new Withdraw', nextWithdraw.address) 55 | 56 | // Add minter 57 | await dev.addMinter(nextLockup.address, { gasPrice: await fastest(), gas }) 58 | console.log('Added next Lockup as a minter') 59 | await dev.addMinter(nextWithdraw.address, { gasPrice: await fastest(), gas }) 60 | console.log('Added next Withdraw as a minter') 61 | 62 | // Delegate storage for Lockup 63 | const lockupStorageAddress = await lockup.getStorageAddress() 64 | console.log('Got EternalStorage address that uses by Lockup') 65 | await nextLockup.setStorage(lockupStorageAddress, { 66 | gasPrice: await fastest(), 67 | gas, 68 | }) 69 | console.log('Set EternalStorage address to the new Lockup') 70 | 71 | // Delegate storage for MetricsGroup 72 | // const metricsGroupStorageAddress = await metricsGroup.getStorageAddress() 73 | // console.log('Got EternalStorage address that uses by MetricsGroup') 74 | // await nextMetricsGroup.setStorage(metricsGroupStorageAddress, { 75 | // gasPrice: await fastest(), 76 | // gas, 77 | // }) 78 | // console.log('Set EternalStorage address to the new MetricsGroup') 79 | 80 | // Activation 81 | await lockup.changeOwner(nextLockup.address, { 82 | gasPrice: await fastest(), 83 | gas, 84 | }) 85 | console.log('Delegated EternalStorage owner to the new Lockup') 86 | 87 | await config.setLockup(nextLockup.address, { gasPrice: await fastest(), gas }) 88 | console.log('updated AddressConfig for Lockup') 89 | 90 | // Await metricsGroup.changeOwner(nextMetricsGroup.address, { 91 | // gasPrice: await fastest(), 92 | // gas, 93 | // }) 94 | // console.log('Delegated EternalStorage owner to the new MetricsGroup') 95 | 96 | // await config.setMetricsGroup(nextMetricsGroup.address, { 97 | // gasPrice: await fastest(), 98 | // gas, 99 | // }) 100 | console.log('updated AddressConfig for MetricsGroup') 101 | 102 | await config.setWithdraw(nextWithdraw.address, { 103 | gasPrice: await fastest(), 104 | gas, 105 | }) 106 | console.log('updated AddressConfig for Withdraw') 107 | 108 | await config.setMetricsFactory(nextMetricsFactory.address, { 109 | gasPrice: await fastest(), 110 | gas, 111 | }) 112 | console.log('updated AddressConfig for MetricsFactory') 113 | 114 | callback(undefined) 115 | } 116 | 117 | export = handler 118 | -------------------------------------------------------------------------------- /scripts/533-2-bulk-initialize-metrics-count-per-property.ts: -------------------------------------------------------------------------------- 1 | // Unused value 2 | // import Web3 from 'web3' 3 | import { 4 | prepare, 5 | createQueue, 6 | createGraphQLPropertyFactoryCreateFetcher, 7 | createGetMetricsCountPerProperty, 8 | // Already nonexistent value 9 | // create__SetMetricsCountPerProperty, 10 | } from './lib/bulk-initializer' 11 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 12 | import { graphql } from './lib/api' 13 | import { GraphQLPropertyFactoryCreateResponse } from './lib/types' 14 | const { CONFIG, EGS_TOKEN } = process.env 15 | 16 | const handler = async ( 17 | callback: (err: Error | undefined) => void 18 | ): Promise => { 19 | if (!CONFIG || !EGS_TOKEN) { 20 | return 21 | } 22 | 23 | // Unused value 24 | // const [from] = await (web3 as Web3).eth.getAccounts() 25 | 26 | const lockup = await prepare(CONFIG, web3) 27 | console.log('Generated Lockup contract', lockup.options) 28 | 29 | const fetchGraphQL = createGraphQLPropertyFactoryCreateFetcher(graphql()) 30 | const all = await (async () => 31 | new Promise< 32 | GraphQLPropertyFactoryCreateResponse['data']['property_factory_create'] 33 | >((resolve) => { 34 | const f = async ( 35 | i = 0, 36 | prev: GraphQLPropertyFactoryCreateResponse['data']['property_factory_create'] = [] 37 | ): Promise => { 38 | const { data } = await fetchGraphQL(i) 39 | const { property_factory_create: items } = data 40 | const next = [...prev, ...items] 41 | if (items.length > 0) { 42 | f(i + items.length, next).catch(console.error) 43 | } else { 44 | resolve(next) 45 | } 46 | } 47 | 48 | f().catch(console.error) 49 | }))() 50 | console.log('GraphQL fetched', all) 51 | console.log('all targets', all.length) 52 | 53 | const fetchFastestGasPrice = ethGasStationFetcher(EGS_TOKEN) 54 | 55 | const getMetricsCountPerProperty = createGetMetricsCountPerProperty({} as any) 56 | // Already nonexistent value 57 | // const setMetricsCountPerProperty = create__SetMetricsCountPerProperty( 58 | // {} as any 59 | // )(from) 60 | 61 | const filteringTacks = all.map(({ property, ...x }) => async () => { 62 | const asses = await getMetricsCountPerProperty(property) 63 | const skip = 64 | asses !== '0' || x.authentication_aggregate.aggregate.count === 0 65 | console.log('Should skip item?', skip, property) 66 | return { property, skip, ...x } 67 | }) 68 | const shouldInitilizeItems = await createQueue(10) 69 | .addAll(filteringTacks) 70 | .then((done) => done.filter(({ skip }) => !skip)) 71 | console.log('Should skip items', all.length - shouldInitilizeItems.length) 72 | console.log('Should initilize items', shouldInitilizeItems.length) 73 | 74 | const initializeTasks = shouldInitilizeItems.map((data) => async () => { 75 | const { property } = data 76 | const assets = data.authentication_aggregate.aggregate.count 77 | const gasPrice = await fetchFastestGasPrice() 78 | console.log('Start initilization', property, assets, gasPrice) 79 | 80 | // Already nonexistent value 81 | // await new Promise((resolve) => { 82 | // setMetricsCountPerProperty(property, assets.toString(), gasPrice) 83 | // .on('transactionHash', (hash: string) => 84 | // console.log('Created the transaction', hash) 85 | // ) 86 | // .on('confirmation', resolve) 87 | // .on('error', (err) => { 88 | // console.error(err) 89 | // resolve(err) 90 | // }) 91 | // }) 92 | // console.log('Done initilization', property, assets) 93 | }) 94 | 95 | await createQueue(2).addAll(initializeTasks).catch(console.error) 96 | 97 | callback(undefined) 98 | } 99 | 100 | export = handler 101 | -------------------------------------------------------------------------------- /scripts/533-3-dip9-after-migration.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | 3 | const { CONFIG, EGS_TOKEN } = process.env 4 | const gas = 6721975 5 | 6 | const handler = async ( 7 | callback: (err: Error | undefined) => void 8 | ): Promise => { 9 | if (!CONFIG || !EGS_TOKEN) { 10 | return 11 | } 12 | 13 | // Generate current contract 14 | const [config] = await Promise.all([ 15 | artifacts.require('AddressConfig').at(CONFIG), 16 | ]) 17 | console.log('Generated AddressConfig contract', config.address) 18 | 19 | const [metricsGroup] = await Promise.all([ 20 | artifacts.require('MetricsGroup').at(await config.metricsGroup()), 21 | ]) 22 | console.log('Generated current MetricsGroup contract', metricsGroup.address) 23 | 24 | const fastest = ethGasStationFetcher(EGS_TOKEN) 25 | 26 | // Deploy new MetricsGroup 27 | const nextMetricsGroup = await artifacts 28 | .require('MetricsGroup') 29 | .new(config.address, { gasPrice: await fastest(), gas }) 30 | console.log('Deployed the new MetricsGroup', nextMetricsGroup.address) 31 | 32 | // Delegate storage for MetricsGroup 33 | const metricsGroupStorageAddress = await metricsGroup.getStorageAddress() 34 | console.log('Got EternalStorage address that uses by MetricsGroup') 35 | await nextMetricsGroup.setStorage(metricsGroupStorageAddress, { 36 | gasPrice: await fastest(), 37 | gas, 38 | }) 39 | console.log('Set EternalStorage address to the new MetricsGroup') 40 | 41 | // Activation 42 | await metricsGroup.changeOwner(nextMetricsGroup.address, { 43 | gasPrice: await fastest(), 44 | gas, 45 | }) 46 | console.log('Delegated EternalStorage owner to the new MetricsGroup') 47 | 48 | await config.setMetricsGroup(nextMetricsGroup.address, { 49 | gasPrice: await fastest(), 50 | gas, 51 | }) 52 | console.log('updated AddressConfig for MetricsGroup') 53 | 54 | callback(undefined) 55 | } 56 | 57 | export = handler 58 | -------------------------------------------------------------------------------- /scripts/557-create-and-authenticate-one-tx.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | 3 | const { CONFIG, EGS_TOKEN } = process.env 4 | const gas = 6721975 5 | 6 | const handler = async ( 7 | callback: (err: Error | undefined) => void 8 | ): Promise => { 9 | if (!CONFIG || !EGS_TOKEN) { 10 | return 11 | } 12 | 13 | const fastest = ethGasStationFetcher(EGS_TOKEN) 14 | 15 | // Generate current contract 16 | const [config] = await Promise.all([ 17 | artifacts.require('AddressConfig').at(CONFIG), 18 | ]) 19 | console.log('Generated AddressConfig contract', config.address) 20 | 21 | // Deploy 22 | const nextMarketFactory = await artifacts 23 | .require('MarketFactory') 24 | .new(config.address, { gasPrice: await fastest(), gas }) 25 | console.log('Deployed the new MarketFactory', nextMarketFactory.address) 26 | 27 | const nextPropertyFactory = await artifacts 28 | .require('PropertyFactory') 29 | .new(config.address, { gasPrice: await fastest(), gas }) 30 | console.log('Deployed the new PropertyFactory', nextPropertyFactory.address) 31 | 32 | // Enable new Contract 33 | await config.setMarketFactory(nextMarketFactory.address, { 34 | gasPrice: await fastest(), 35 | gas, 36 | }) 37 | console.log('Updated MarketFactory address') 38 | 39 | await config.setPropertyFactory(nextPropertyFactory.address, { 40 | gasPrice: await fastest(), 41 | gas, 42 | }) 43 | console.log('Updated PropertyFactory address') 44 | 45 | callback(undefined) 46 | } 47 | 48 | export = handler 49 | -------------------------------------------------------------------------------- /scripts/560-check-transfer-result.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | import { config } from 'dotenv' 3 | import { DevCommonInstance } from './lib/instance/common' 4 | import { PropertyFactory } from './lib/instance/property-factory' 5 | 6 | config() 7 | const { CONFIG: configAddress, EGS_TOKEN: egsApiKey } = process.env 8 | 9 | const handler = async ( 10 | callback: (err: Error | undefined) => void 11 | ): Promise => { 12 | if (!configAddress || !egsApiKey) { 13 | return 14 | } 15 | 16 | const gasFetcher = async () => 6721975 17 | const gasPriceFetcher = ethGasStationFetcher(egsApiKey) 18 | const dev = new DevCommonInstance( 19 | artifacts, 20 | configAddress, 21 | gasFetcher, 22 | gasPriceFetcher 23 | ) 24 | await dev.prepare() 25 | 26 | const propertyFactory = new PropertyFactory(dev) 27 | const nextPropertyFactory = await propertyFactory.create() 28 | await propertyFactory.set(nextPropertyFactory) 29 | callback(undefined) 30 | } 31 | 32 | export = handler 33 | -------------------------------------------------------------------------------- /scripts/565-delete-loop.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | import { config } from 'dotenv' 3 | import { DevCommonInstance } from './lib/instance/common' 4 | import { PolicyGroup } from './lib/instance/policy-group' 5 | import { PolicyFactory } from './lib/instance/policy-factory' 6 | 7 | config() 8 | const { CONFIG: configAddress, EGS_TOKEN: egsApiKey } = process.env 9 | 10 | const handler = async ( 11 | callback: (err: Error | undefined) => void 12 | ): Promise => { 13 | if (!configAddress || !egsApiKey) { 14 | return 15 | } 16 | 17 | const gasFetcher = async () => 6721975 18 | const gasPriceFetcher = ethGasStationFetcher(egsApiKey) 19 | const dev = new DevCommonInstance( 20 | artifacts, 21 | configAddress, 22 | gasFetcher, 23 | gasPriceFetcher 24 | ) 25 | await dev.prepare() 26 | 27 | const policyGroup = new PolicyGroup(dev) 28 | const currentPolicyGroup = await policyGroup.load() 29 | const nextPolicyGroup = await policyGroup.create() 30 | await policyGroup.changeOwner(currentPolicyGroup, nextPolicyGroup) 31 | await policyGroup.set(nextPolicyGroup) 32 | 33 | const policyFactory = new PolicyFactory(dev) 34 | const nextPolicyFactory = await policyFactory.create() 35 | await policyFactory.set(nextPolicyFactory) 36 | 37 | await dev.addressConfig.setPolicySet( 38 | '0x0000000000000000000000000000000000000000', 39 | await dev.gasInfo 40 | ) 41 | console.log('PolicySet address is 0') 42 | 43 | callback(undefined) 44 | } 45 | 46 | export = handler 47 | -------------------------------------------------------------------------------- /scripts/566-1-fix-reward-calculation-for-creators.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | 3 | const { CONFIG, EGS_TOKEN } = process.env 4 | const gas = 6721975 5 | 6 | const handler = async ( 7 | callback: (err: Error | undefined) => void 8 | ): Promise => { 9 | if (!CONFIG || !EGS_TOKEN) { 10 | return 11 | } 12 | 13 | // Generate current contract 14 | const [config] = await Promise.all([ 15 | artifacts.require('AddressConfig').at(CONFIG), 16 | ]) 17 | console.log('Generated AddressConfig contract', config.address) 18 | 19 | const [withdrawStorage, dev] = await Promise.all([ 20 | artifacts.require('WithdrawStorage').at(await config.withdrawStorage()), 21 | artifacts.require('Dev').at(await config.token()), 22 | ]) 23 | console.log( 24 | 'Generated current WithdrawStorage contract', 25 | withdrawStorage.address 26 | ) 27 | console.log('Generated current Dev contract', dev.address) 28 | 29 | const fastest = ethGasStationFetcher(EGS_TOKEN) 30 | 31 | // Deploy WithdrawMigration as a new Withdraw 32 | // const nextWithdraw = await artifacts 33 | // .require('WithdrawMigration') 34 | // .new(config.address, { gasPrice: await fastest(), gas }) 35 | // .catch(console.error) 36 | // if (!nextWithdraw) { 37 | // return 38 | // } 39 | 40 | // console.log('Deployed the new Withdraw', nextWithdraw.address) 41 | 42 | // Deploy new WithdrawStorage 43 | const nextWithdrawStorage = await artifacts 44 | .require('WithdrawStorage') 45 | .new({ gasPrice: await fastest(), gas }) 46 | console.log('Deployed the new WithdrawStorage', nextWithdrawStorage.address) 47 | 48 | // Add minter 49 | // await dev 50 | // .addMinter(nextWithdraw.address, { gasPrice: await fastest(), gas }) 51 | // .catch(console.error) 52 | // console.log('Added next Withdraw as a minter') 53 | 54 | // Delegate storage for WithdrawStorage 55 | const withdrawStorageAddress = await withdrawStorage.getStorageAddress() 56 | console.log('Got EternalStorage address that uses by WithdrawStorage') 57 | await nextWithdrawStorage 58 | .setStorage(withdrawStorageAddress, { 59 | gasPrice: await fastest(), 60 | gas, 61 | }) 62 | .catch(console.error) 63 | if (!nextWithdrawStorage) { 64 | return 65 | } 66 | 67 | console.log('Set EternalStorage address to the new WithdrawStorage') 68 | 69 | // Activation 70 | await withdrawStorage 71 | .changeOwner(nextWithdrawStorage.address, { 72 | gasPrice: await fastest(), 73 | gas, 74 | }) 75 | .catch(console.error) 76 | console.log('Delegated EternalStorage owner to the new WithdrawStorage') 77 | 78 | await config 79 | .setWithdrawStorage(nextWithdrawStorage.address, { 80 | gasPrice: await fastest(), 81 | gas, 82 | }) 83 | .catch(console.error) 84 | console.log('updated AddressConfig for WithdrawStorage') 85 | 86 | // Await config 87 | // .setWithdraw(nextWithdraw.address, { 88 | // gasPrice: await fastest(), 89 | // gas, 90 | // }) 91 | // .catch(console.error) 92 | // console.log('updated AddressConfig for Withdraw') 93 | 94 | callback(undefined) 95 | } 96 | 97 | export = handler 98 | -------------------------------------------------------------------------------- /scripts/566-3-finilize.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | 3 | const { CONFIG, EGS_TOKEN, DEV_MINTER } = process.env 4 | const gas = 6721975 5 | 6 | const handler = async ( 7 | callback: (err: Error | undefined) => void 8 | ): Promise => { 9 | if (!CONFIG || !EGS_TOKEN || !DEV_MINTER) { 10 | return 11 | } 12 | 13 | // Generate current contract 14 | const [config] = await Promise.all([ 15 | artifacts.require('AddressConfig').at(CONFIG), 16 | ]) 17 | console.log('Generated AddressConfig contract', config.address) 18 | 19 | const [dev] = await Promise.all([ 20 | artifacts.require('Dev').at(await config.token()), 21 | ]) 22 | console.log('Generated current Dev contract', dev.address) 23 | 24 | const fastest = ethGasStationFetcher(EGS_TOKEN) 25 | 26 | // Deploy new Withdraw 27 | const nextWithdraw = await artifacts 28 | .require('Withdraw') 29 | .new(config.address, DEV_MINTER, { gasPrice: await fastest(), gas }) 30 | .catch(console.error) 31 | if (!nextWithdraw) { 32 | return 33 | } 34 | 35 | console.log('Deployed the new Withdraw', nextWithdraw.address) 36 | 37 | // Add minter 38 | await dev 39 | .addMinter(nextWithdraw.address, { gasPrice: await fastest(), gas }) 40 | .catch(console.error) 41 | console.log('Added next Withdraw as a minter') 42 | 43 | // Activation 44 | await config 45 | .setWithdraw(nextWithdraw.address, { 46 | gasPrice: await fastest(), 47 | gas, 48 | }) 49 | .catch(console.error) 50 | console.log('updated AddressConfig for Withdraw') 51 | 52 | callback(undefined) 53 | } 54 | 55 | export = handler 56 | -------------------------------------------------------------------------------- /scripts/592-cut-gas-price.ts: -------------------------------------------------------------------------------- 1 | import { config } from 'dotenv' 2 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 3 | import { DevCommonInstance } from './lib/instance/common' 4 | import { Lockup } from './lib/instance/lockup' 5 | 6 | config() 7 | const { CONFIG: configAddress, EGS_TOKEN: egsApiKey } = process.env 8 | 9 | const handler = async ( 10 | callback: (err: Error | undefined) => void 11 | ): Promise => { 12 | if (!configAddress || !egsApiKey) { 13 | return 14 | } 15 | 16 | const gasFetcher = async () => 6721975 17 | const gasPriceFetcher = ethGasStationFetcher(egsApiKey) 18 | const dev = new DevCommonInstance( 19 | artifacts, 20 | configAddress, 21 | gasFetcher, 22 | gasPriceFetcher 23 | ) 24 | await dev.prepare() 25 | 26 | // Lockup 27 | const lockup = new Lockup(dev) 28 | const lockupInstance = await lockup.load() 29 | const nextLockupInstance = await lockup.create() 30 | await lockup.changeOwner(lockupInstance, nextLockupInstance) 31 | await lockup.set(nextLockupInstance) 32 | 33 | callback(undefined) 34 | } 35 | 36 | export = handler 37 | -------------------------------------------------------------------------------- /scripts/618-delete-unnecessary-function.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | import { config } from 'dotenv' 3 | import { DevCommonInstance } from './lib/instance/common' 4 | import { PolicyGroup } from './lib/instance/policy-group' 5 | 6 | config() 7 | const { CONFIG: configAddress, EGS_TOKEN: egsApiKey } = process.env 8 | 9 | const handler = async ( 10 | callback: (err: Error | undefined) => void 11 | ): Promise => { 12 | if (!configAddress || !egsApiKey) { 13 | return 14 | } 15 | 16 | const gasFetcher = async () => 6721975 17 | const gasPriceFetcher = ethGasStationFetcher(egsApiKey) 18 | const dev = new DevCommonInstance( 19 | artifacts, 20 | configAddress, 21 | gasFetcher, 22 | gasPriceFetcher 23 | ) 24 | await dev.prepare() 25 | 26 | const policyGroup = new PolicyGroup(dev) 27 | const currentPolicyGroup = await policyGroup.load() 28 | const nextPolicyGroup = await policyGroup.create() 29 | await policyGroup.changeOwner(currentPolicyGroup, nextPolicyGroup) 30 | await policyGroup.set(nextPolicyGroup) 31 | 32 | callback(undefined) 33 | } 34 | 35 | export = handler 36 | -------------------------------------------------------------------------------- /scripts/632-one-transaction-withdrawal.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | import { config } from 'dotenv' 3 | import { DevCommonInstance } from './lib/instance/common' 4 | import { Lockup } from './lib/instance/lockup' 5 | import { PolicyFactory } from './lib/instance/policy-factory' 6 | 7 | config() 8 | const { CONFIG: configAddress, EGS_TOKEN: egsApiKey } = process.env 9 | 10 | const handler = async ( 11 | callback: (err: Error | undefined) => void 12 | ): Promise => { 13 | if (!configAddress || !egsApiKey) { 14 | return 15 | } 16 | 17 | const gasFetcher = async () => 6721975 18 | const gasPriceFetcher = ethGasStationFetcher(egsApiKey) 19 | const dev = new DevCommonInstance( 20 | artifacts, 21 | configAddress, 22 | gasFetcher, 23 | gasPriceFetcher 24 | ) 25 | await dev.prepare() 26 | 27 | const l = new Lockup(dev) 28 | const lCurrent = await l.load() 29 | const lNext = await l.create() 30 | await l.changeOwner(lCurrent, lNext) 31 | await l.set(lNext) 32 | 33 | const pf = new PolicyFactory(dev) 34 | const pfNext = await pf.create() 35 | await pf.set(pfNext) 36 | 37 | callback(undefined) 38 | } 39 | 40 | export = handler 41 | -------------------------------------------------------------------------------- /scripts/637-bug-fix.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | import { config } from 'dotenv' 3 | import { DevCommonInstance } from './lib/instance/common' 4 | import { Lockup } from './lib/instance/lockup' 5 | 6 | config() 7 | const { CONFIG: configAddress, EGS_TOKEN: egsApiKey } = process.env 8 | 9 | const handler = async ( 10 | callback: (err: Error | undefined) => void 11 | ): Promise => { 12 | if (!configAddress || !egsApiKey) { 13 | return 14 | } 15 | 16 | const gasFetcher = async () => 6721975 17 | const gasPriceFetcher = ethGasStationFetcher(egsApiKey) 18 | const dev = new DevCommonInstance( 19 | artifacts, 20 | configAddress, 21 | gasFetcher, 22 | gasPriceFetcher 23 | ) 24 | await dev.prepare() 25 | 26 | const l = new Lockup(dev) 27 | const lCurrent = await l.load() 28 | const lNext = await l.create() 29 | await l.changeOwner(lCurrent, lNext) 30 | await l.set(lNext) 31 | 32 | callback(undefined) 33 | } 34 | 35 | export = handler 36 | -------------------------------------------------------------------------------- /scripts/786-dev-minter.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | import { config } from 'dotenv' 3 | import { DevCommonInstance } from './lib/instance/common' 4 | import { Lockup } from './lib/instance/lockup' 5 | import { Withdraw } from './lib/instance/withdraw' 6 | 7 | config() 8 | const { CONFIG: configAddress, EGS_TOKEN: egsApiKey } = process.env 9 | 10 | const handler = async ( 11 | callback: (err: Error | undefined) => void 12 | ): Promise => { 13 | if (!configAddress || !egsApiKey) { 14 | return 15 | } 16 | 17 | const gasFetcher = async () => 4000000 18 | const gasPriceFetcher = ethGasStationFetcher(egsApiKey) 19 | const dev = new DevCommonInstance( 20 | artifacts, 21 | configAddress, 22 | gasFetcher, 23 | gasPriceFetcher 24 | ) 25 | await dev.prepare() 26 | 27 | const devMinter = await dev.artifacts 28 | .require('DevMinter') 29 | .new(dev.addressConfig.address, await dev.gasInfo) 30 | console.log('DevMinter contract', devMinter.address) 31 | 32 | await dev.dev.addMinter(devMinter.address, await dev.gasInfo) 33 | 34 | const l = new Lockup(dev) 35 | const lCurrent = await l.load() 36 | const lNext = await l.create(devMinter.address) 37 | 38 | const w = new Withdraw(dev) 39 | const wCurrent = await w.load() 40 | const wNext = await w.create(devMinter.address) 41 | 42 | await Promise.all([ 43 | l.changeOwner(lCurrent, lNext), 44 | l.set(lNext), 45 | w.changeOwner(wCurrent, wNext), 46 | w.set(wNext), 47 | ]) 48 | 49 | callback(undefined) 50 | } 51 | 52 | export = handler 53 | -------------------------------------------------------------------------------- /scripts/898-delete-vote-counter.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | import { config } from 'dotenv' 3 | import { DevCommonInstance } from './lib/instance/common' 4 | import { MarketFactry } from './lib/instance/market-factory' 5 | import { PolicyFactory } from './lib/instance/policy-factory' 6 | import { PolicyGroup } from './lib/instance/policy-group' 7 | 8 | config() 9 | const { CONFIG: configAddress, EGS_TOKEN: egsApiKey } = process.env 10 | 11 | const handler = async ( 12 | callback: (err: Error | undefined) => void 13 | ): Promise => { 14 | if (!configAddress || !egsApiKey) { 15 | return 16 | } 17 | 18 | const gasFetcher = async () => 4000000 19 | const gasPriceFetcher = ethGasStationFetcher(egsApiKey) 20 | const dev = new DevCommonInstance( 21 | artifacts, 22 | configAddress, 23 | gasFetcher, 24 | gasPriceFetcher 25 | ) 26 | await dev.prepare() 27 | 28 | // MarketFactory 29 | const mf = new MarketFactry(dev) 30 | const mfNext = await mf.create() 31 | await mf.set(mfNext) 32 | 33 | // PolicyFactory 34 | const pf = new PolicyFactory(dev) 35 | const pfNext = await pf.create() 36 | await pf.set(pfNext) 37 | 38 | // PolicyGroup 39 | const pg = new PolicyGroup(dev) 40 | const pgCurrent = await pg.load() 41 | const pgNext = await pg.create() 42 | await pg.changeOwner(pgCurrent, pgNext) 43 | await pg.set(pgNext) 44 | 45 | await dev.addressConfig.setVoteCounter( 46 | '0x0000000000000000000000000000000000000000' 47 | ) 48 | 49 | callback(undefined) 50 | } 51 | 52 | export = handler 53 | -------------------------------------------------------------------------------- /scripts/bulk-initialize-last-cumulative-property-interest.ts: -------------------------------------------------------------------------------- 1 | import Web3 from 'web3' 2 | import { 3 | prepare, 4 | createGraphQLFetcher, 5 | createDifferenceCaller, 6 | createGetStorageLastCumulativePropertyInterest, 7 | createInitializeLastCumulativePropertyInterest, 8 | createQueue, 9 | } from './lib/bulk-initializer' 10 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 11 | import { graphql } from './lib/api' 12 | import { GraphQLResponse, PromiseReturn } from './lib/types' 13 | const { CONFIG, EGS_TOKEN } = process.env 14 | 15 | const handler = async ( 16 | callback: (err: Error | undefined) => void 17 | ): Promise => { 18 | if (!CONFIG || !EGS_TOKEN) { 19 | return 20 | } 21 | 22 | const [from] = await (web3 as Web3).eth.getAccounts() 23 | 24 | const lockup = await prepare(CONFIG) 25 | console.log('Generated Lockup contract', lockup.options) 26 | 27 | const fetchGraphQL = createGraphQLFetcher(graphql()) 28 | const all = await (async () => 29 | new Promise((resolve) => { 30 | const f = async ( 31 | i = 0, 32 | prev: GraphQLResponse['data']['account_lockup'] = [] 33 | ): Promise => { 34 | const { data } = await fetchGraphQL(i) 35 | const { account_lockup: items } = data 36 | const next = [...prev, ...items] 37 | if (items.length > 0) { 38 | f(i + items.length, next).catch(console.error) 39 | } else { 40 | resolve(next) 41 | } 42 | } 43 | 44 | f().catch(console.error) 45 | }))() 46 | console.log('GraphQL fetched', all) 47 | 48 | const fetchFastestGasPrice = ethGasStationFetcher(EGS_TOKEN) 49 | 50 | const lastCumulativePropertyInterest = 51 | createGetStorageLastCumulativePropertyInterest(lockup) 52 | const initializeLastCumulativePropertyInterest = 53 | createInitializeLastCumulativePropertyInterest(lockup)(from) 54 | 55 | console.log('all targets', all.length) 56 | 57 | const filteringTacks = all.map( 58 | ({ property_address, account_address, block_number }) => 59 | async () => { 60 | const res = await lastCumulativePropertyInterest()( 61 | property_address, 62 | account_address 63 | ) 64 | const skip = res !== '0' 65 | console.log( 66 | 'Should skip item?', 67 | skip, 68 | property_address, 69 | account_address, 70 | res, 71 | block_number 72 | ) 73 | return { property_address, account_address, skip, block_number } 74 | } 75 | ) 76 | const shouldInitilizeItems = await createQueue(10) 77 | .addAll(filteringTacks) 78 | .then((done) => done.filter((x) => !x.skip)) 79 | console.log('Should skip items', all.length - shouldInitilizeItems.length) 80 | console.log('Should initilize items', shouldInitilizeItems.length) 81 | 82 | const initializeTasks = shouldInitilizeItems.map( 83 | ({ property_address, account_address, block_number }) => 84 | async () => { 85 | const lockupAtThisTime = await prepare(CONFIG, block_number) 86 | const difference = createDifferenceCaller(lockupAtThisTime) 87 | const res: 88 | | Error 89 | | PromiseReturn>> = 90 | await difference(block_number)(property_address).catch( 91 | (err) => new Error(err) 92 | ) 93 | if (res instanceof Error) { 94 | console.log( 95 | 'Could be pre-DIP4 staking', 96 | property_address, 97 | account_address, 98 | block_number 99 | ) 100 | return 101 | } 102 | 103 | const interest = res._interestAmount 104 | const gasPrice = await fetchFastestGasPrice() 105 | console.log( 106 | 'Start initilization', 107 | property_address, 108 | account_address, 109 | interest, 110 | gasPrice 111 | ) 112 | 113 | await new Promise((resolve, reject) => { 114 | initializeLastCumulativePropertyInterest( 115 | property_address, 116 | account_address, 117 | interest, 118 | gasPrice 119 | ) 120 | .on('transactionHash', (hash: string) => { 121 | console.log('Created the transaction', hash) 122 | }) 123 | .on('confirmation', resolve) 124 | .on('error', reject) 125 | }) 126 | console.log('Done initilization', property_address, account_address) 127 | } 128 | ) 129 | 130 | await createQueue(2).addAll(initializeTasks).catch(console.error) 131 | 132 | callback(undefined) 133 | } 134 | 135 | export = handler 136 | -------------------------------------------------------------------------------- /scripts/deploy-withdraw.ts: -------------------------------------------------------------------------------- 1 | import { DevCommonInstance } from './lib/instance/common' 2 | import { Withdraw } from './lib/instance/withdraw' 3 | import { config } from 'dotenv' 4 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 5 | config() 6 | const { CONFIG: configAddress, EGS_TOKEN: egsApiKey } = process.env 7 | 8 | const handler = async ( 9 | callback: (err: Error | undefined) => void 10 | ): Promise => { 11 | if (!configAddress || !egsApiKey) { 12 | return 13 | } 14 | 15 | const gasFetcher = async () => 6721975 16 | const gasPriceFetcher = ethGasStationFetcher(egsApiKey) 17 | const dev = new DevCommonInstance( 18 | artifacts, 19 | configAddress, 20 | gasFetcher, 21 | gasPriceFetcher 22 | ) 23 | await dev.prepare() 24 | 25 | // Withdraw 26 | const withdraw = new Withdraw(dev) 27 | const nextWithdraw = await withdraw.create() 28 | await withdraw.set(nextWithdraw) 29 | 30 | callback(undefined) 31 | } 32 | 33 | export = handler 34 | -------------------------------------------------------------------------------- /scripts/dip38.ts: -------------------------------------------------------------------------------- 1 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 2 | import { config } from 'dotenv' 3 | import { DevCommonInstance } from './lib/instance/common' 4 | import { MetricsGroup } from './lib/instance/metrics-group' 5 | import { Lockup } from './lib/instance/lockup' 6 | import { Withdraw } from './lib/instance/withdraw' 7 | import { PolicyFactory } from './lib/instance/policy-factory' 8 | import { Policy } from './lib/instance/policy' 9 | 10 | config() 11 | const { 12 | CONFIG: configAddress, 13 | EGS_TOKEN: egsApiKey, 14 | CAP_SETTER: capSetter, 15 | } = process.env 16 | 17 | const handler = async ( 18 | callback: (err: Error | undefined) => void 19 | ): Promise => { 20 | if (!configAddress || !egsApiKey || !capSetter) { 21 | return 22 | } 23 | 24 | const gasFetcher = async () => 4000000 25 | const gasPriceFetcher = ethGasStationFetcher(egsApiKey) 26 | const dev = new DevCommonInstance( 27 | artifacts, 28 | configAddress, 29 | gasFetcher, 30 | gasPriceFetcher 31 | ) 32 | await dev.prepare() 33 | 34 | // Create the new Policy 35 | const policy = new Policy(dev) 36 | const policy_current = await policy.load() 37 | const treasury = await policy_current.treasury() 38 | const policy_next = await artifacts 39 | .require('DIP55') 40 | .new(dev.addressConfig.address, await dev.gasInfo) 41 | await Promise.all([ 42 | policy_next.setTreasury(treasury, await dev.gasInfo), 43 | policy_next.setCapSetter(capSetter, await dev.gasInfo), 44 | ]) 45 | 46 | // Create the new PolicyFactory 47 | const policy_factory = new PolicyFactory(dev) 48 | const policy_factory_current = await policy_factory.load() 49 | 50 | // Force attach the new Policy 51 | await policy_factory_current.create(policy_next.address, await dev.gasInfo) 52 | await policy_factory_current.forceAttach( 53 | policy_next.address, 54 | await dev.gasInfo 55 | ) 56 | 57 | // Create the new MetricsGroup 58 | const metrics_group = new MetricsGroup(dev) 59 | const metrics_group_current = await metrics_group.load() 60 | const metrics_group_next = await metrics_group.create() 61 | 62 | // Create the LockupMigration 63 | const lockup = new Lockup(dev) 64 | const lockup_current = await lockup.load() 65 | const lockup_next = await lockup.create(await lockup_current.devMinter()) 66 | 67 | // Create the new Withdraw 68 | const withdraw = new Withdraw(dev) 69 | const withdraw_current = await withdraw.load() 70 | const withdraw_next = await withdraw.create( 71 | await withdraw_current.devMinter() 72 | ) 73 | 74 | // Delegate to all new contracts 75 | await Promise.all([ 76 | metrics_group.changeOwner(metrics_group_current, metrics_group_next), 77 | lockup.changeOwner(lockup_current, lockup_next), 78 | withdraw.changeOwner(withdraw_current, withdraw_next), 79 | ]) 80 | 81 | // Set all new contracts 82 | await Promise.all([ 83 | metrics_group.set(metrics_group_next), 84 | lockup.set(lockup_next), 85 | withdraw.set(withdraw_next), 86 | ]) 87 | 88 | callback(undefined) 89 | } 90 | 91 | export = handler 92 | -------------------------------------------------------------------------------- /scripts/lib/api.ts: -------------------------------------------------------------------------------- 1 | import bent from 'bent' 2 | export const graphql = () => 3 | bent('https://api.devprtcl.com/v1/graphql', 'POST', 'json') 4 | -------------------------------------------------------------------------------- /scripts/lib/instance/allocator.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { AllocatorInstance } from '../../../types/truffle-contracts' 3 | import { DevCommonInstance } from './common' 4 | 5 | export class Allocator { 6 | private readonly _dev: DevCommonInstance 7 | constructor(dev: DevCommonInstance) { 8 | this._dev = dev 9 | } 10 | 11 | public async load(): Promise { 12 | const address = await this._dev.addressConfig.allocator() 13 | const allocator = await this._dev.artifacts.require('Allocator').at(address) 14 | console.log('load Allocator contract', allocator.address) 15 | return allocator 16 | } 17 | 18 | public async create(): Promise { 19 | const allocator = await this._dev.artifacts 20 | .require('Allocator') 21 | .new(this._dev.addressConfig.address, await this._dev.gasInfo) 22 | console.log('new Allocator contract', allocator.address) 23 | return allocator 24 | } 25 | 26 | public async set(allocator: AllocatorInstance): Promise { 27 | await this._dev.addressConfig.setAllocator( 28 | allocator.address, 29 | await this._dev.gasInfo 30 | ) 31 | console.log('set Allocator contract', allocator.address) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /scripts/lib/instance/common.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | 3 | import { 4 | AddressConfigInstance, 5 | DevInstance, 6 | } from '../../../types/truffle-contracts' 7 | 8 | export class DevCommonInstance { 9 | private readonly _artifacts: Truffle.Artifacts 10 | private readonly _gasFetcher: () => Promise 11 | private readonly _gasPriceFetcher: () => Promise 12 | private readonly _configAddress: string 13 | 14 | private _addressConfig!: AddressConfigInstance 15 | private _dev!: DevInstance 16 | 17 | constructor( 18 | _artifacts: Truffle.Artifacts, 19 | _configAddress: string, 20 | _gasFetcher: () => Promise, 21 | _gasPriceFetcher: () => Promise 22 | ) { 23 | this._artifacts = _artifacts 24 | this._configAddress = _configAddress 25 | this._gasFetcher = _gasFetcher 26 | this._gasPriceFetcher = _gasPriceFetcher 27 | } 28 | 29 | public get artifacts(): Truffle.Artifacts { 30 | return this._artifacts 31 | } 32 | 33 | public get gasInfo(): Promise<{ 34 | gas: number | string 35 | gasPrice: number | string 36 | }> { 37 | return Promise.all([this._gasFetcher(), this._gasPriceFetcher()]) 38 | .then(([gas, gasPrice]) => ({ gas, gasPrice })) 39 | .catch((err: Error) => { 40 | console.error(err) 41 | return { 42 | gas: 0, 43 | gasPrice: 0, 44 | } 45 | }) 46 | } 47 | 48 | public get addressConfig(): AddressConfigInstance { 49 | return this._addressConfig 50 | } 51 | 52 | public get dev(): DevInstance { 53 | return this._dev 54 | } 55 | 56 | public async prepare(): Promise { 57 | await this._loadAddressConfig() 58 | await this._loadDev() 59 | } 60 | 61 | private async _loadAddressConfig(): Promise { 62 | this._addressConfig = await this._artifacts 63 | .require('AddressConfig') 64 | .at(this._configAddress) 65 | console.log('load AddressConfig contract', this._addressConfig.address) 66 | } 67 | 68 | private async _loadDev(): Promise { 69 | const address = await this._addressConfig.token() 70 | this._dev = await this._artifacts.require('Dev').at(address) 71 | console.log('load Dev contract', this._dev.address) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /scripts/lib/instance/lockup.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { LockupInstance } from '../../../types/truffle-contracts' 3 | import { DevCommonInstance } from './common' 4 | 5 | type InstanceOfLockup = LockupInstance 6 | 7 | export class Lockup { 8 | private readonly _dev: DevCommonInstance 9 | constructor(dev: DevCommonInstance) { 10 | this._dev = dev 11 | } 12 | 13 | public async load(): Promise { 14 | const address = await this._dev.addressConfig.lockup() 15 | const lockup = await this._dev.artifacts.require('Lockup').at(address) 16 | console.log('load Lockup contract', lockup.address) 17 | return lockup 18 | } 19 | 20 | public async create( 21 | devMinter = '', 22 | sTokenManager = '' 23 | ): Promise { 24 | if (devMinter === '') { 25 | const tmp = await this.load() 26 | devMinter = await tmp.devMinter() 27 | } 28 | 29 | if (sTokenManager === '') { 30 | const tmp = await this.load() 31 | sTokenManager = await tmp.sTokensManager() 32 | } 33 | 34 | const lockup = await this._dev.artifacts 35 | .require('Lockup') 36 | .new( 37 | this._dev.addressConfig.address, 38 | devMinter, 39 | sTokenManager, 40 | await this._dev.gasInfo 41 | ) 42 | console.log('new Lockup contract', lockup.address) 43 | return lockup 44 | } 45 | 46 | public async set(lockup: InstanceOfLockup): Promise { 47 | await this._dev.addressConfig.setLockup( 48 | lockup.address, 49 | await this._dev.gasInfo 50 | ) 51 | console.log('set Lockup contract', lockup.address) 52 | } 53 | 54 | public async changeOwner( 55 | before: InstanceOfLockup, 56 | after: InstanceOfLockup 57 | ): Promise { 58 | const storageAddress = await before.getStorageAddress() 59 | console.log(`storage address ${storageAddress}`) 60 | await after.setStorage(storageAddress, await this._dev.gasInfo) 61 | await before.changeOwner(after.address, await this._dev.gasInfo) 62 | 63 | console.log(`change owner from ${before.address} to ${after.address}`) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /scripts/lib/instance/market-factory.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { MarketFactoryInstance } from '../../../types/truffle-contracts' 3 | import { DevCommonInstance } from './common' 4 | 5 | export class MarketFactry { 6 | private readonly _dev: DevCommonInstance 7 | constructor(dev: DevCommonInstance) { 8 | this._dev = dev 9 | } 10 | 11 | public async load(): Promise { 12 | const address = await this._dev.addressConfig.marketFactory() 13 | const marketFactory = await this._dev.artifacts 14 | .require('MarketFactory') 15 | .at(address) 16 | console.log('load MarketFactory contract', marketFactory.address) 17 | return marketFactory 18 | } 19 | 20 | public async create(): Promise { 21 | const marketFactory = await this._dev.artifacts 22 | .require('MarketFactory') 23 | .new(this._dev.addressConfig.address, await this._dev.gasInfo) 24 | console.log('new MarketFactory contract', marketFactory.address) 25 | return marketFactory 26 | } 27 | 28 | public async set(marketFactory: MarketFactoryInstance): Promise { 29 | await this._dev.addressConfig.setMarketFactory( 30 | marketFactory.address, 31 | await this._dev.gasInfo 32 | ) 33 | console.log('set MarketFactory contract', marketFactory.address) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /scripts/lib/instance/market-group.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { MarketGroupInstance } from '../../../types/truffle-contracts' 3 | import { DevCommonInstance } from './common' 4 | 5 | export class MarketGroup { 6 | private readonly _dev: DevCommonInstance 7 | constructor(dev: DevCommonInstance) { 8 | this._dev = dev 9 | } 10 | 11 | public async load(): Promise { 12 | const address = await this._dev.addressConfig.marketGroup() 13 | const marketGroup = await this._dev.artifacts 14 | .require('MarketGroup') 15 | .at(address) 16 | console.log('load MarketGroup contract', marketGroup.address) 17 | return marketGroup 18 | } 19 | 20 | public async create(): Promise { 21 | const marketGroup = await this._dev.artifacts 22 | .require('MarketGroup') 23 | .new(this._dev.addressConfig.address, await this._dev.gasInfo) 24 | console.log('new MarketGroup contract', marketGroup.address) 25 | return marketGroup 26 | } 27 | 28 | public async set(marketGroup: MarketGroupInstance): Promise { 29 | await this._dev.addressConfig.setMarketGroup( 30 | marketGroup.address, 31 | await this._dev.gasInfo 32 | ) 33 | console.log('set MarketGroup contract', marketGroup.address) 34 | } 35 | 36 | public async changeOwner( 37 | before: MarketGroupInstance, 38 | after: MarketGroupInstance 39 | ): Promise { 40 | const storageAddress = await before.getStorageAddress() 41 | console.log(`storage address ${storageAddress}`) 42 | await after.setStorage(storageAddress, await this._dev.gasInfo) 43 | await before.changeOwner(after.address, await this._dev.gasInfo) 44 | 45 | console.log(`change owner from ${before.address} to ${after.address}`) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /scripts/lib/instance/metrics-factory.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { MetricsFactoryInstance } from '../../../types/truffle-contracts' 3 | import { DevCommonInstance } from './common' 4 | 5 | export class MetricsFactory { 6 | private readonly _dev: DevCommonInstance 7 | constructor(dev: DevCommonInstance) { 8 | this._dev = dev 9 | } 10 | 11 | public async load(): Promise { 12 | const address = await this._dev.addressConfig.metricsFactory() 13 | const metricsFactory = await this._dev.artifacts 14 | .require('MetricsFactory') 15 | .at(address) 16 | console.log('load MetricsFactory contract', metricsFactory.address) 17 | return metricsFactory 18 | } 19 | 20 | public async create(): Promise { 21 | const metricsFactory = await this._dev.artifacts 22 | .require('MetricsFactory') 23 | .new(this._dev.addressConfig.address, await this._dev.gasInfo) 24 | console.log('new MetricsFactory contract', metricsFactory.address) 25 | return metricsFactory 26 | } 27 | 28 | public async set(metricsFactory: MetricsFactoryInstance): Promise { 29 | await this._dev.addressConfig.setMetricsFactory( 30 | metricsFactory.address, 31 | await this._dev.gasInfo 32 | ) 33 | console.log('set MetricsFactory contract', metricsFactory.address) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /scripts/lib/instance/metrics-group.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { MetricsGroupInstance } from '../../../types/truffle-contracts' 3 | import { DevCommonInstance } from './common' 4 | 5 | export class MetricsGroup { 6 | private readonly _dev: DevCommonInstance 7 | constructor(dev: DevCommonInstance) { 8 | this._dev = dev 9 | } 10 | 11 | public async load(): Promise { 12 | const address = await this._dev.addressConfig.metricsGroup() 13 | const metricsGroup = await this._dev.artifacts 14 | .require('MetricsGroup') 15 | .at(address) 16 | console.log('load MetricsGroup contract', metricsGroup.address) 17 | return metricsGroup 18 | } 19 | 20 | public async create(): Promise { 21 | const metricsGroup = await this._dev.artifacts 22 | .require('MetricsGroup') 23 | .new(this._dev.addressConfig.address, await this._dev.gasInfo) 24 | console.log('new MetricsGroup contract', metricsGroup.address) 25 | return metricsGroup 26 | } 27 | 28 | public async set(metricsGroup: MetricsGroupInstance): Promise { 29 | await this._dev.addressConfig.setMetricsGroup( 30 | metricsGroup.address, 31 | await this._dev.gasInfo 32 | ) 33 | console.log('set MetricsGroup contract', metricsGroup.address) 34 | } 35 | 36 | public async changeOwner( 37 | before: MetricsGroupInstance, 38 | after: MetricsGroupInstance 39 | ): Promise { 40 | const storageAddress = await before.getStorageAddress() 41 | console.log(`storage address ${storageAddress}`) 42 | await after.setStorage(storageAddress, await this._dev.gasInfo) 43 | await before.changeOwner(after.address, await this._dev.gasInfo) 44 | 45 | console.log(`change owner from ${before.address} to ${after.address}`) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /scripts/lib/instance/policy-factory.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { PolicyFactoryInstance } from '../../../types/truffle-contracts' 3 | import { DevCommonInstance } from './common' 4 | 5 | export class PolicyFactory { 6 | private readonly _dev: DevCommonInstance 7 | constructor(dev: DevCommonInstance) { 8 | this._dev = dev 9 | } 10 | 11 | public async load(): Promise { 12 | const address = await this._dev.addressConfig.policyFactory() 13 | const policyFactory = await this._dev.artifacts 14 | .require('PolicyFactory') 15 | .at(address) 16 | console.log('load PolicyFactory contract', policyFactory.address) 17 | return policyFactory 18 | } 19 | 20 | public async create(): Promise { 21 | const policyFactory = await this._dev.artifacts 22 | .require('PolicyFactory') 23 | .new(this._dev.addressConfig.address, await this._dev.gasInfo) 24 | console.log('new PolicyFactory contract', policyFactory.address) 25 | return policyFactory 26 | } 27 | 28 | public async set(policyFactory: PolicyFactoryInstance): Promise { 29 | await this._dev.addressConfig.setPolicyFactory( 30 | policyFactory.address, 31 | await this._dev.gasInfo 32 | ) 33 | console.log('set PolicyFactory contract', policyFactory.address) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /scripts/lib/instance/policy-group.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { PolicyGroupInstance } from '../../../types/truffle-contracts' 3 | import { DevCommonInstance } from './common' 4 | 5 | export class PolicyGroup { 6 | private readonly _dev: DevCommonInstance 7 | constructor(dev: DevCommonInstance) { 8 | this._dev = dev 9 | } 10 | 11 | public async load(): Promise { 12 | const address = await this._dev.addressConfig.policyGroup() 13 | const policyGroup = await this._dev.artifacts 14 | .require('PolicyGroup') 15 | .at(address) 16 | console.log('load PolicyGroup contract', policyGroup.address) 17 | return policyGroup 18 | } 19 | 20 | public async create(): Promise { 21 | const policyGroup = await this._dev.artifacts 22 | .require('PolicyGroup') 23 | .new(this._dev.addressConfig.address, await this._dev.gasInfo) 24 | console.log('new PolicyGroup contract', policyGroup.address) 25 | return policyGroup 26 | } 27 | 28 | public async set(policyGroup: PolicyGroupInstance): Promise { 29 | await this._dev.addressConfig.setPolicyGroup( 30 | policyGroup.address, 31 | await this._dev.gasInfo 32 | ) 33 | console.log('set PolicyGroup contract', policyGroup.address) 34 | } 35 | 36 | public async changeOwner( 37 | before: PolicyGroupInstance, 38 | after: PolicyGroupInstance 39 | ): Promise { 40 | const storageAddress = await before.getStorageAddress() 41 | console.log(`storage address ${storageAddress}`) 42 | await after.setStorage(storageAddress, await this._dev.gasInfo) 43 | await before.changeOwner(after.address, await this._dev.gasInfo) 44 | 45 | console.log(`change owner from ${before.address} to ${after.address}`) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /scripts/lib/instance/policy.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { IPolicyInstance } from '../../../types/truffle-contracts' 3 | import { DevCommonInstance } from './common' 4 | 5 | export class Policy { 6 | private readonly _dev: DevCommonInstance 7 | constructor(dev: DevCommonInstance) { 8 | this._dev = dev 9 | } 10 | 11 | public async load(): Promise { 12 | const address = await this._dev.addressConfig.policy() 13 | const policy = await this._dev.artifacts.require('IPolicy').at(address) 14 | console.log('load Policy contract', policy.address) 15 | return policy 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /scripts/lib/instance/property-factory.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { PropertyFactoryInstance } from '../../../types/truffle-contracts' 3 | import { DevCommonInstance } from './common' 4 | 5 | export class PropertyFactory { 6 | private readonly _dev: DevCommonInstance 7 | constructor(dev: DevCommonInstance) { 8 | this._dev = dev 9 | } 10 | 11 | public async load(): Promise { 12 | const address = await this._dev.addressConfig.propertyFactory() 13 | const propertyFactory = await this._dev.artifacts 14 | .require('PropertyFactory') 15 | .at(address) 16 | console.log('load PropertyFactory contract', propertyFactory.address) 17 | return propertyFactory 18 | } 19 | 20 | public async create(): Promise { 21 | const propertyFactory = await this._dev.artifacts 22 | .require('PropertyFactory') 23 | .new(this._dev.addressConfig.address, await this._dev.gasInfo) 24 | console.log('new PropertyFactory contract', propertyFactory.address) 25 | return propertyFactory 26 | } 27 | 28 | public async set(propertyFactory: PropertyFactoryInstance): Promise { 29 | await this._dev.addressConfig.setPropertyFactory( 30 | propertyFactory.address, 31 | await this._dev.gasInfo 32 | ) 33 | console.log('set PropertyFactory contract', propertyFactory.address) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /scripts/lib/instance/property-group.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { PropertyGroupInstance } from '../../../types/truffle-contracts' 3 | import { DevCommonInstance } from './common' 4 | 5 | export class PropertyGroup { 6 | private readonly _dev: DevCommonInstance 7 | constructor(dev: DevCommonInstance) { 8 | this._dev = dev 9 | } 10 | 11 | public async load(): Promise { 12 | const address = await this._dev.addressConfig.propertyGroup() 13 | const propertyGroup = await this._dev.artifacts 14 | .require('PropertyGroup') 15 | .at(address) 16 | console.log('load PropertyGroup contract', propertyGroup.address) 17 | return propertyGroup 18 | } 19 | 20 | public async create(): Promise { 21 | const propertyGroup = await this._dev.artifacts 22 | .require('PropertyGroup') 23 | .new(this._dev.addressConfig.address, await this._dev.gasInfo) 24 | console.log('new PropertyGroup contract', propertyGroup.address) 25 | return propertyGroup 26 | } 27 | 28 | public async set(propertyGroup: PropertyGroupInstance): Promise { 29 | await this._dev.addressConfig.setPropertyGroup( 30 | propertyGroup.address, 31 | await this._dev.gasInfo 32 | ) 33 | console.log('set PropertyGroup contract', propertyGroup.address) 34 | } 35 | 36 | public async changeOwner( 37 | before: PropertyGroupInstance, 38 | after: PropertyGroupInstance 39 | ): Promise { 40 | const storageAddress = await before.getStorageAddress() 41 | console.log(`storage address ${storageAddress}`) 42 | await after.setStorage(storageAddress) 43 | await before.changeOwner(after.address) 44 | 45 | console.log(`change owner from ${before.address} to ${after.address}`) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /scripts/lib/instance/withdraw.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/await-thenable */ 2 | import { 3 | WithdrawInstance, 4 | WithdrawStorageInstance, 5 | } from '../../../types/truffle-contracts' 6 | import { DevCommonInstance } from './common' 7 | 8 | type InstanceOfWithdraw = WithdrawInstance 9 | 10 | export class Withdraw { 11 | private readonly _dev: DevCommonInstance 12 | constructor(dev: DevCommonInstance) { 13 | this._dev = dev 14 | } 15 | 16 | public async load(): Promise { 17 | const address = await this._dev.addressConfig.withdraw() 18 | const withdraw = await this._dev.artifacts.require('Withdraw').at(address) 19 | console.log('load Withdraw contract', withdraw.address) 20 | return withdraw 21 | } 22 | 23 | public async create(devMinter = ''): Promise { 24 | if (devMinter === '') { 25 | const tmp = await this.load() 26 | devMinter = await tmp.devMinter() 27 | } 28 | 29 | const withdraw = await this._dev.artifacts 30 | .require('Withdraw') 31 | .new(this._dev.addressConfig.address, devMinter, await this._dev.gasInfo) 32 | console.log('new Withdraw contract', withdraw.address) 33 | return withdraw 34 | } 35 | 36 | public async set(withdraw: InstanceOfWithdraw): Promise { 37 | await this._dev.addressConfig.setWithdraw( 38 | withdraw.address, 39 | await this._dev.gasInfo 40 | ) 41 | console.log('set Withdraw contract', withdraw.address) 42 | } 43 | 44 | public async changeOwner( 45 | before: WithdrawStorageInstance | InstanceOfWithdraw, 46 | after: InstanceOfWithdraw 47 | ): Promise { 48 | const storageAddress = await before.getStorageAddress() 49 | console.log(`storage address ${storageAddress}`) 50 | await after.setStorage(storageAddress, await this._dev.gasInfo) 51 | await before.changeOwner(after.address, await this._dev.gasInfo) 52 | 53 | console.log(`change owner from ${before.address} to ${after.address}`) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /scripts/lib/types.ts: -------------------------------------------------------------------------------- 1 | export type GraphQLResponse = { 2 | data: { 3 | account_lockup: Array<{ 4 | property_address: string 5 | account_address: string 6 | block_number: number 7 | }> 8 | } 9 | } 10 | export type GraphQLPropertyFactoryCreateResponse = { 11 | data: { 12 | property_factory_create: Array<{ 13 | property: string 14 | authentication_aggregate: { 15 | aggregate: { 16 | count: number 17 | } 18 | } 19 | }> 20 | } 21 | } 22 | 23 | export type GraphQLPropertyAuthenticationPropertyResponse = { 24 | data: { 25 | property_authentication: Array<{ 26 | property: string 27 | }> 28 | } 29 | } 30 | 31 | export type PromiseReturn> = T extends Promise 32 | ? P 33 | : never 34 | export type Event = { 35 | readonly address: string 36 | readonly blockHash: string 37 | readonly blockNumber: number 38 | readonly event: string 39 | readonly logIndex: number 40 | readonly raw: { 41 | readonly data: string 42 | readonly topics: string 43 | } 44 | readonly returnValues: Record 45 | readonly signature: string 46 | readonly transactionHash: string 47 | readonly transactionIndex: number 48 | } 49 | export type ReceiptEvent = Record 50 | export type TxReceipt = { 51 | readonly blockHash: string 52 | readonly blockNumber: number 53 | readonly contractAddress: string | undefined 54 | readonly cumulativeGasUsed: number 55 | readonly events: ReceiptEvent 56 | readonly from: string 57 | readonly gasUsed: number 58 | readonly logsBloom: string 59 | readonly status: boolean 60 | readonly to: string 61 | readonly transactionHash: string 62 | readonly transactionIndex: number 63 | } 64 | export type SendTx = { 65 | readonly on: ( 66 | type: T, 67 | callback: T extends 'transactionHash' 68 | ? (hash: string) => void 69 | : T extends 'confirmation' 70 | ? (confirmationNumber: number, receipt: TxReceipt) => void 71 | : (err: Readonly) => void 72 | ) => SendTx 73 | } 74 | -------------------------------------------------------------------------------- /scripts/treasury-fee.ts: -------------------------------------------------------------------------------- 1 | import { DevCommonInstance } from './lib/instance/common' 2 | import { PolicyFactory } from './lib/instance/policy-factory' 3 | import { PropertyFactory } from './lib/instance/property-factory' 4 | import { config } from 'dotenv' 5 | import { ethGasStationFetcher } from '@devprotocol/util-ts' 6 | 7 | // Caution!!!!!!!!!!!!!!!!!! 8 | // Please set TRESUARY_ADDRESS to env file before exexute this script. 9 | 10 | config() 11 | const { 12 | CONFIG: configAddress, 13 | EGS_TOKEN: egsApiKey, 14 | TRESUARY_ADDRESS: tresauryAddress, 15 | } = process.env 16 | 17 | const handler = async ( 18 | callback: (err: Error | undefined) => void 19 | ): Promise => { 20 | if (!configAddress || !egsApiKey) { 21 | return 22 | } 23 | 24 | const gasFetcher = async () => 6721975 25 | const gasPriceFetcher = ethGasStationFetcher(egsApiKey) 26 | const dev = new DevCommonInstance( 27 | artifacts, 28 | configAddress, 29 | gasFetcher, 30 | gasPriceFetcher 31 | ) 32 | await dev.prepare() 33 | 34 | // Policy 35 | const newPolicy = await artifacts 36 | .require('TreasuryFee') 37 | .new(dev.addressConfig.address, await dev.gasInfo) 38 | console.log('new policy was created:', newPolicy.address) 39 | // Tresuary 40 | await newPolicy.setTreasury(tresauryAddress!, await dev.gasInfo) 41 | console.log('tresuary address was settted:', await newPolicy.treasury()) 42 | 43 | // PolicyFactory 44 | const policyFacgtory = new PolicyFactory(dev) 45 | const nextPolicyFactory = await policyFacgtory.create() 46 | await policyFacgtory.set(nextPolicyFactory) 47 | 48 | // Set new policy 49 | await nextPolicyFactory.create(newPolicy.address, await dev.gasInfo) 50 | console.log('new policy was joined policy group') 51 | await nextPolicyFactory.forceAttach(newPolicy.address, await dev.gasInfo) 52 | console.log('new policy was set current policy') 53 | 54 | // PropertyFactory 55 | const propertyFactory = new PropertyFactory(dev) 56 | const nextPropertyFactory = await propertyFactory.create() 57 | await propertyFactory.set(nextPropertyFactory) 58 | 59 | callback(undefined) 60 | } 61 | 62 | export = handler 63 | -------------------------------------------------------------------------------- /test/common/config/using-config.ts: -------------------------------------------------------------------------------- 1 | import { DevProtocolInstance } from '../../test-lib/instance' 2 | 3 | contract('UsingConfigTest', ([deployer]) => { 4 | const usingConfigContract = artifacts.require('UsingConfigTest') 5 | const dev = new DevProtocolInstance(deployer) 6 | before(async () => { 7 | await dev.generateAddressConfig() 8 | await dev.generateDev() 9 | await dev.generateDevMinter() 10 | }) 11 | describe('UsingConfig; config', () => { 12 | it('You can get the address of config by setting it in the constructor.', async () => { 13 | const usingConfigTest = await usingConfigContract.new( 14 | dev.addressConfig.address, 15 | { from: deployer } 16 | ) 17 | const tokenAddress = await usingConfigTest.getToken() 18 | 19 | expect(tokenAddress).to.be.equal(await dev.addressConfig.token()) 20 | }) 21 | }) 22 | describe('UsingConfig; configAddress', () => { 23 | it('You can get the address of config .', async () => { 24 | const usingConfigTest = await usingConfigContract.new( 25 | dev.addressConfig.address, 26 | { from: deployer } 27 | ) 28 | const configAddress = await usingConfigTest.configAddress() 29 | 30 | expect(configAddress).to.be.equal(dev.addressConfig.address) 31 | }) 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /test/common/libs/decimals.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from 'bignumber.js' 2 | import { toBigNumber } from '../../test-lib/utils/common' 3 | import { validateErrorMessage } from '../../test-lib/utils/error' 4 | contract('DecimalsTest', ([deployer]) => { 5 | const decimalsTestContract = artifacts.require('DecimalsTest') 6 | describe('Decimals; outOf', () => { 7 | it('outOf returns ratio of the first args out of second args', async () => { 8 | const decimalsTest = await decimalsTestContract.new({ 9 | from: deployer, 10 | }) 11 | const resultBN = await decimalsTest.outOf(28, 70) 12 | const result = new BigNumber(resultBN.toString()) 13 | const answer = 28 / 70 14 | expect(result.div(1000000000000000000).toNumber()).to.be.equal(answer) 15 | }) 16 | it('outOf returns error if the denominator is 10^36 times greater than the numerator', async () => { 17 | const decimalsTest = await decimalsTestContract.new({ 18 | from: deployer, 19 | }) 20 | const result = await decimalsTest.outOf( 21 | 28, 22 | '700000000000000000000000000000000000000' 23 | ) 24 | expect(result.toNumber()).to.be.equal(0) 25 | }) 26 | }) 27 | describe('Decimals; mulBasis', () => { 28 | it('The value multiplied by basis is returned.', async () => { 29 | const decimalsTest = await decimalsTestContract.new({ 30 | from: deployer, 31 | }) 32 | const resultBN = await decimalsTest.mulBasis(28).then(toBigNumber) 33 | expect(resultBN.toString()).to.be.equal('28000000000000000000') 34 | }) 35 | it('Whatever you multiply 0 by 0, you get 0.', async () => { 36 | const decimalsTest = await decimalsTestContract.new({ 37 | from: deployer, 38 | }) 39 | const resultBN = await decimalsTest.mulBasis(0).then(toBigNumber) 40 | expect(resultBN.toString()).to.be.equal('0') 41 | }) 42 | it('Large numbers cause overflow.', async () => { 43 | const decimalsTest = await decimalsTestContract.new({ 44 | from: deployer, 45 | }) 46 | const res = await decimalsTest 47 | .mulBasis(toBigNumber(2 ** 255)) 48 | .catch((err: Error) => err) 49 | validateErrorMessage(res, 'SafeMath: multiplication overflow', false) 50 | }) 51 | }) 52 | describe('Decimals; divBasis', () => { 53 | it('The value divided by basis comes back.', async () => { 54 | const decimalsTest = await decimalsTestContract.new({ 55 | from: deployer, 56 | }) 57 | const resultBN = await decimalsTest 58 | .divBasis(toBigNumber(28000000000000000000)) 59 | .then(toBigNumber) 60 | expect(resultBN.toString()).to.be.equal('28') 61 | }) 62 | it('Zero is zero divided by whatever.', async () => { 63 | const decimalsTest = await decimalsTestContract.new({ 64 | from: deployer, 65 | }) 66 | const resultBN = await decimalsTest.divBasis(0).then(toBigNumber) 67 | expect(resultBN.toString()).to.be.equal('0') 68 | }) 69 | }) 70 | }) 71 | -------------------------------------------------------------------------------- /test/common/storage/using-storage.ts: -------------------------------------------------------------------------------- 1 | import { UsingStorageTestInstance } from '../../../types/truffle-contracts' 2 | import { validateErrorMessage } from '../../test-lib/utils/error' 3 | 4 | contract('UsingStorageTest', ([deployer]) => { 5 | const UsingStorageTestContract = artifacts.require('UsingStorageTest') 6 | let usingStorageTest: UsingStorageTestInstance 7 | before(async () => { 8 | usingStorageTest = await UsingStorageTestContract.new({ 9 | from: deployer, 10 | }) 11 | }) 12 | describe('UsingStorage: eternalStorage', () => { 13 | it('returns EternalStorage instance', async () => { 14 | const usingStorage = await UsingStorageTestContract.new() 15 | await usingStorage.createStorage() 16 | const result = await usingStorage.getEternalStorageAddress() 17 | const expected = await usingStorage.getStorageAddress() 18 | expect(result).to.be.equal(expected) 19 | }) 20 | }) 21 | describe('UsingStorage; hasStorage, createStorage', () => { 22 | it('If storage has not been created, an error will occur when trying to get the storage address.', async () => { 23 | const result = await usingStorageTest 24 | .getStorageAddress() 25 | .catch((err: Error) => err) 26 | validateErrorMessage(result, 'storage is not set', false) 27 | }) 28 | it('If storage has not been created, an error will occur when accessing storage.', async () => { 29 | const result = await usingStorageTest.getUInt().catch((err: Error) => err) 30 | validateErrorMessage(result, 'storage is not set', false) 31 | }) 32 | it('If storage has been created, the storage address can be obtained.', async () => { 33 | await usingStorageTest.createStorage() 34 | const result = await usingStorageTest.getStorageAddress() 35 | expect(web3.utils.isAddress(result)).to.be.equal(true) 36 | }) 37 | it('If the storage has been created, you can access the storage.', async () => { 38 | const result = await usingStorageTest.getUInt() 39 | expect(result.toNumber()).to.be.equal(0) 40 | }) 41 | it('Creating storage again after storage has been created results in an error.', async () => { 42 | const result = await usingStorageTest 43 | .createStorage() 44 | .catch((err: Error) => err) 45 | validateErrorMessage(result, 'storage is set') 46 | }) 47 | }) 48 | 49 | describe('UsingStorage; getStorageAddress, setStorage, changeOwner', () => { 50 | let usingStorageTestNext: UsingStorageTestInstance 51 | before(async () => { 52 | await usingStorageTest.setUInt(1) 53 | usingStorageTestNext = await UsingStorageTestContract.new({ 54 | from: deployer, 55 | }) 56 | }) 57 | it('Can get the value set in the storage.', async () => { 58 | const result = await usingStorageTest.getUInt() 59 | expect(result.toNumber()).to.be.equal(1) 60 | }) 61 | it('the storage address is taken over, the same storage can be accessed from the takeover destination.', async () => { 62 | const storageAddress = await usingStorageTest.getStorageAddress() 63 | await usingStorageTestNext.setStorage(storageAddress) 64 | const result = await usingStorageTestNext.getUInt() 65 | expect(result.toNumber()).to.be.equal(1) 66 | }) 67 | it('Before delegating authority, you can not write.', async () => { 68 | const result = await usingStorageTestNext 69 | .setUInt(2) 70 | .catch((err: Error) => err) 71 | validateErrorMessage(result, 'not current owner') 72 | }) 73 | it('Delegation of authority is not possible from the delegate.', async () => { 74 | const result = await usingStorageTestNext 75 | .changeOwner(usingStorageTestNext.address) 76 | .catch((err: Error) => err) 77 | validateErrorMessage(result, 'not current owner') 78 | }) 79 | it('When delegating authority, the delegate can write to storage', async () => { 80 | await usingStorageTest.changeOwner(usingStorageTestNext.address) 81 | await usingStorageTestNext.setUInt(2) 82 | const result = await usingStorageTestNext.getUInt() 83 | expect(result.toNumber()).to.be.equal(2) 84 | }) 85 | it('When delegating authority, delegation source can not write to storage.', async () => { 86 | const result = await usingStorageTest 87 | .setUInt(2) 88 | .catch((err: Error) => err) 89 | validateErrorMessage(result, 'not current owner') 90 | }) 91 | }) 92 | }) 93 | -------------------------------------------------------------------------------- /test/dev/dev-minter.ts: -------------------------------------------------------------------------------- 1 | import { DevProtocolInstance } from '../test-lib/instance' 2 | import { DevMinterInstance } from '../../types/truffle-contracts' 3 | import { validateErrorMessage } from '../test-lib/utils/error' 4 | import { 5 | takeSnapshot, 6 | revertToSnapshot, 7 | Snapshot, 8 | } from '../test-lib/utils/snapshot' 9 | 10 | contract('DevMinter', ([deployer, user1, lockup, withdraw]) => { 11 | const createDevInstance = async (): Promise => { 12 | const dev = new DevProtocolInstance(deployer) 13 | await dev.generateAddressConfig() 14 | await dev.generateDev() 15 | await dev.generateDevMinter() 16 | await dev.addressConfig.setLockup(lockup) 17 | await dev.addressConfig.setWithdraw(withdraw) 18 | return dev 19 | } 20 | 21 | const createDevInstanceNotAddMinter = 22 | async (): Promise => { 23 | const contract = artifacts.require 24 | 25 | const addressConfig = await contract('AddressConfig').new({ 26 | from: deployer, 27 | }) 28 | const dev = await contract('Dev').new(addressConfig.address, { 29 | from: deployer, 30 | }) 31 | await addressConfig.setToken(dev.address, { 32 | from: deployer, 33 | }) 34 | const devMinter = await contract('DevMinter').new(addressConfig.address, { 35 | from: deployer, 36 | }) 37 | await addressConfig.setLockup(lockup, { 38 | from: deployer, 39 | }) 40 | await addressConfig.setWithdraw(withdraw, { 41 | from: deployer, 42 | }) 43 | return devMinter 44 | } 45 | 46 | let dev: DevProtocolInstance 47 | let snapshot: Snapshot 48 | let snapshotId: string 49 | 50 | before(async () => { 51 | dev = await createDevInstance() 52 | }) 53 | 54 | beforeEach(async () => { 55 | snapshot = (await takeSnapshot()) as Snapshot 56 | snapshotId = snapshot.result 57 | }) 58 | 59 | afterEach(async () => { 60 | await revertToSnapshot(snapshotId) 61 | }) 62 | 63 | describe('mint', () => { 64 | describe('success', () => { 65 | it('If DevMinter has minter privileges, it can mint Dev tokens.(Lockup)', async () => { 66 | const before = await dev.dev.balanceOf(user1) 67 | expect(before.toString()).to.equal('0') 68 | await dev.devMinter.mint(user1, 100, { from: lockup }) 69 | const after = await dev.dev.balanceOf(user1) 70 | expect(after.toString()).to.equal('100') 71 | }) 72 | it('If DevMinter has minter privileges, it can mint Dev tokens.(withdraw)', async () => { 73 | const before = await dev.dev.balanceOf(user1) 74 | expect(before.toString()).to.equal('0') 75 | await dev.devMinter.mint(user1, 100, { from: withdraw }) 76 | const after = await dev.dev.balanceOf(user1) 77 | expect(after.toString()).to.equal('100') 78 | }) 79 | }) 80 | describe('fail', () => { 81 | it('If DevMinter does not has minter privileges, it can not mint Dev tokens', async () => { 82 | const devMinter = await createDevInstanceNotAddMinter() 83 | const result = await devMinter 84 | .mint(user1, 100, { from: withdraw }) 85 | .catch((err: Error) => err) 86 | validateErrorMessage( 87 | result, 88 | 'MinterRole: caller does not have the Minter role' 89 | ) 90 | }) 91 | it('Error when minting from other than Lockup and Withdraw contracts', async () => { 92 | const result = await dev.devMinter 93 | .mint(user1, 100) 94 | .catch((err: Error) => err) 95 | validateErrorMessage(result, 'illegal access') 96 | }) 97 | }) 98 | }) 99 | describe('renounceMinter', () => { 100 | describe('success', () => { 101 | it('we can remove mint privileges.', async () => { 102 | const before = await dev.dev.isMinter(dev.devMinter.address) 103 | expect(before).to.equal(true) 104 | await dev.devMinter.renounceMinter() 105 | const after = await dev.dev.isMinter(dev.devMinter.address) 106 | expect(after).to.equal(false) 107 | const result = await dev.devMinter 108 | .mint(user1, 100, { from: withdraw }) 109 | .catch((err: Error) => err) 110 | validateErrorMessage( 111 | result, 112 | 'MinterRole: caller does not have the Minter role' 113 | ) 114 | }) 115 | }) 116 | describe('fail', () => { 117 | it('Only the owner can run it.', async () => { 118 | const result = await dev.devMinter 119 | .renounceMinter({ from: user1 }) 120 | .catch((err: Error) => err) 121 | validateErrorMessage(result, 'Ownable: caller is not the owner') 122 | }) 123 | }) 124 | }) 125 | }) 126 | -------------------------------------------------------------------------------- /test/lockup/lockup-common.ts: -------------------------------------------------------------------------------- 1 | import { DevProtocolInstance } from '../test-lib/instance' 2 | import { 3 | PropertyInstance, 4 | PolicyTestBaseInstance, 5 | } from '../../types/truffle-contracts' 6 | import BigNumber from 'bignumber.js' 7 | import { getPropertyAddress } from '../test-lib/utils/log' 8 | 9 | export const err = (error: Error): Error => error 10 | 11 | export const init = async ( 12 | deployer: string, 13 | user: string, 14 | initialUpdate = true 15 | ): Promise<[DevProtocolInstance, PropertyInstance, PolicyTestBaseInstance]> => { 16 | const dev = new DevProtocolInstance(deployer) 17 | await dev.generateAddressConfig() 18 | await dev.generateDev() 19 | await dev.generateDevMinter() 20 | await dev.generateSTokenManager() 21 | await Promise.all([ 22 | dev.generateAllocator(), 23 | dev.generateMarketFactory(), 24 | dev.generateMarketGroup(), 25 | dev.generateMetricsFactory(), 26 | dev.generateMetricsGroup(), 27 | dev.generateLockup(), 28 | dev.generateWithdraw(), 29 | dev.generatePropertyFactory(), 30 | dev.generatePropertyGroup(), 31 | dev.generatePolicyFactory(), 32 | dev.generatePolicyGroup(), 33 | ]) 34 | await dev.dev.mint(deployer, new BigNumber(1e18).times(10000000)) 35 | const policyAddress = await dev.generatePolicy('PolicyTestBase') 36 | // eslint-disable-next-line @typescript-eslint/await-thenable 37 | const policy = await artifacts.require('PolicyTestBase').at(policyAddress) 38 | const propertyAddress = getPropertyAddress( 39 | await dev.propertyFactory.create('test', 'TEST', user, { 40 | from: user, 41 | }) 42 | ) 43 | const [property] = await Promise.all([ 44 | artifacts.require('Property').at(propertyAddress), 45 | ]) 46 | 47 | await dev.addressConfig.setMetricsFactory(deployer) 48 | await dev.metricsGroup.addGroup( 49 | ( 50 | await dev.createMetrics(deployer, property.address) 51 | ).address 52 | ) 53 | 54 | if (initialUpdate) { 55 | await dev.lockup.update() 56 | } 57 | 58 | return [dev, property, policy] 59 | } 60 | -------------------------------------------------------------------------------- /test/lockup/lockup-s-token-common.ts: -------------------------------------------------------------------------------- 1 | import { DevProtocolInstance } from '../test-lib/instance' 2 | import { getPropertyAddress } from '../test-lib/utils/log' 3 | import { PropertyInstance } from '../../types/truffle-contracts' 4 | import BigNumber from 'bignumber.js' 5 | 6 | export const deployerBalance = new BigNumber(1e18).times(10000000) 7 | 8 | export const err = (error: Error): Error => error 9 | 10 | export const init = async ( 11 | deployer: string, 12 | user: string 13 | ): Promise<[DevProtocolInstance, PropertyInstance]> => { 14 | const dev = new DevProtocolInstance(deployer) 15 | await dev.generateAddressConfig() 16 | await dev.generateDev() 17 | await dev.generateDevMinter() 18 | await dev.generateSTokenManager() 19 | await Promise.all([ 20 | dev.generateAllocator(), 21 | dev.generateMarketFactory(), 22 | dev.generateMarketGroup(), 23 | dev.generateMetricsFactory(), 24 | dev.generateMetricsGroup(), 25 | dev.generateLockup(), 26 | dev.generateWithdraw(), 27 | dev.generatePropertyFactory(), 28 | dev.generatePropertyGroup(), 29 | dev.generatePolicyFactory(), 30 | dev.generatePolicyGroup(), 31 | ]) 32 | await dev.dev.mint(deployer, deployerBalance) 33 | await dev.generatePolicy('PolicyTestBase') 34 | const propertyAddress = getPropertyAddress( 35 | await dev.propertyFactory.create('test', 'TEST', user, { 36 | from: user, 37 | }) 38 | ) 39 | const [property] = await Promise.all([ 40 | artifacts.require('Property').at(propertyAddress), 41 | ]) 42 | 43 | await dev.addressConfig.setMetricsFactory(deployer) 44 | await dev.metricsGroup.addGroup( 45 | ( 46 | await dev.createMetrics(deployer, property.address) 47 | ).address 48 | ) 49 | 50 | await dev.lockup.update() 51 | 52 | return [dev, property] 53 | } 54 | -------------------------------------------------------------------------------- /test/market/market-group.ts: -------------------------------------------------------------------------------- 1 | import { DevProtocolInstance } from '../test-lib/instance' 2 | import { validateErrorMessage } from '../test-lib/utils/error' 3 | import { 4 | takeSnapshot, 5 | revertToSnapshot, 6 | Snapshot, 7 | } from '../test-lib/utils/snapshot' 8 | 9 | contract( 10 | 'MarketGroupTest', 11 | ([ 12 | deployer, 13 | marketFactory, 14 | dummyMarketFactory, 15 | market1, 16 | market2, 17 | dummyMarket, 18 | ]) => { 19 | const dev = new DevProtocolInstance(deployer) 20 | let snapshot: Snapshot 21 | let snapshotId: string 22 | 23 | beforeEach(async () => { 24 | snapshot = (await takeSnapshot()) as Snapshot 25 | snapshotId = snapshot.result 26 | }) 27 | 28 | afterEach(async () => { 29 | await revertToSnapshot(snapshotId) 30 | }) 31 | describe('MarketGroup addGroup, isGroup, getCount', () => { 32 | before(async () => { 33 | await dev.generateAddressConfig() 34 | await dev.generateMarketGroup() 35 | await dev.addressConfig.setMarketFactory(marketFactory, { 36 | from: deployer, 37 | }) 38 | await dev.marketGroup.addGroup(market1, { from: marketFactory }) 39 | }) 40 | it('When a market address is specified', async () => { 41 | const result = await dev.marketGroup.isGroup(market1) 42 | expect(result).to.be.equal(true) 43 | }) 44 | it('The number increases as you add addresses', async () => { 45 | let result = await dev.marketGroup.getCount() 46 | expect(result.toNumber()).to.be.equal(1) 47 | await dev.marketGroup.addGroup(market2, { from: marketFactory }) 48 | result = await dev.marketGroup.getCount() 49 | expect(result.toNumber()).to.be.equal(2) 50 | }) 51 | it('When the market address is not specified', async () => { 52 | const result = await dev.marketGroup.isGroup(dummyMarket) 53 | expect(result).to.be.equal(false) 54 | }) 55 | it('Existing market cannot be added', async () => { 56 | const result = await dev.marketGroup 57 | .addGroup(market1, { 58 | from: marketFactory, 59 | }) 60 | .catch((err: Error) => err) 61 | validateErrorMessage(result, 'already enabled') 62 | }) 63 | it('Can not execute addGroup without marketFactory address', async () => { 64 | const result = await dev.marketGroup 65 | .addGroup(dummyMarket, { 66 | from: dummyMarketFactory, 67 | }) 68 | .catch((err: Error) => err) 69 | validateErrorMessage(result, 'illegal access') 70 | }) 71 | }) 72 | describe('MarketGroup deleteGroup, isGroup, getCount', () => { 73 | before(async () => { 74 | await dev.generateAddressConfig() 75 | await dev.generateMarketGroup() 76 | await dev.addressConfig.setMarketFactory(marketFactory, { 77 | from: deployer, 78 | }) 79 | await dev.marketGroup.addGroup(market1, { from: marketFactory }) 80 | }) 81 | it('The number reduce as you delete addresses', async () => { 82 | let result = await dev.marketGroup.getCount() 83 | expect(result.toNumber()).to.be.equal(1) 84 | await dev.marketGroup.deleteGroup(market1, { from: marketFactory }) 85 | result = await dev.marketGroup.getCount() 86 | expect(result.toNumber()).to.be.equal(0) 87 | }) 88 | it('Excluded from the group', async () => { 89 | let result = await dev.marketGroup.isGroup(market1) 90 | expect(result).to.be.equal(true) 91 | await dev.marketGroup.deleteGroup(market1, { from: marketFactory }) 92 | result = await dev.marketGroup.isGroup(market1) 93 | expect(result).to.be.equal(false) 94 | }) 95 | it('Existing market cannot be added', async () => { 96 | const result = await dev.marketGroup 97 | .deleteGroup(market2, { 98 | from: marketFactory, 99 | }) 100 | .catch((err: Error) => err) 101 | validateErrorMessage(result, 'not exist') 102 | }) 103 | it('Can not execute addGroup without marketFactory address', async () => { 104 | const result = await dev.marketGroup 105 | .deleteGroup(dummyMarket, { 106 | from: dummyMarketFactory, 107 | }) 108 | .catch((err: Error) => err) 109 | validateErrorMessage(result, 'illegal access') 110 | }) 111 | }) 112 | } 113 | ) 114 | -------------------------------------------------------------------------------- /test/metrics/metrics.ts: -------------------------------------------------------------------------------- 1 | contract('metricsTest', ([metricsFactory, market, property]) => { 2 | const metricsContract = artifacts.require('Metrics') 3 | describe('Metrics; constructor', () => { 4 | it('The set address can be referenced.', async () => { 5 | const metrics = await metricsContract.new(market, property, { 6 | from: metricsFactory, 7 | }) 8 | expect(await metrics.market()).to.be.equal(market) 9 | expect(await metrics.property()).to.be.equal(property) 10 | }) 11 | }) 12 | }) 13 | -------------------------------------------------------------------------------- /test/policy/policy-group.ts: -------------------------------------------------------------------------------- 1 | import { DevProtocolInstance } from '../test-lib/instance' 2 | import { mine } from '../test-lib/utils/common' 3 | import { 4 | takeSnapshot, 5 | revertToSnapshot, 6 | Snapshot, 7 | } from '../test-lib/utils/snapshot' 8 | import { 9 | validateErrorMessage, 10 | validateAddressErrorMessage, 11 | } from '../test-lib/utils/error' 12 | 13 | contract( 14 | 'PolicyGroupTest', 15 | ([deployer, policyFactory, dummyPolicyFactory, dummyPolicy]) => { 16 | const init = async (): Promise => { 17 | const dev = new DevProtocolInstance(deployer) 18 | await dev.generateAddressConfig() 19 | await dev.generatePolicyGroup() 20 | await dev.generatePolicyFactory() 21 | const policy = await dev.getPolicy('PolicyTestForPolicyFactory', deployer) 22 | await dev.policyFactory.create(policy.address, { 23 | from: deployer, 24 | }) 25 | await dev.addressConfig.setPolicyFactory(policyFactory, { 26 | from: deployer, 27 | }) 28 | return dev 29 | } 30 | 31 | let dev: DevProtocolInstance 32 | let snapshot: Snapshot 33 | let snapshotId: string 34 | 35 | before(async () => { 36 | dev = await init() 37 | }) 38 | 39 | beforeEach(async () => { 40 | snapshot = (await takeSnapshot()) as Snapshot 41 | snapshotId = snapshot.result 42 | }) 43 | 44 | afterEach(async () => { 45 | await revertToSnapshot(snapshotId) 46 | }) 47 | 48 | describe('PolicyGroup; addGroup, isGroup', () => { 49 | it('When a policy address is specified', async () => { 50 | const currentPolicy = await dev.addressConfig.policy() 51 | 52 | const result = await dev.policyGroup.isGroup(currentPolicy) 53 | expect(result).to.be.equal(true) 54 | }) 55 | it('When the policy address is not specified', async () => { 56 | const result = await dev.policyGroup.isGroup(dummyPolicy) 57 | expect(result).to.be.equal(false) 58 | }) 59 | it('can add new policy', async () => { 60 | const policy = await dev.getPolicy( 61 | 'PolicyTestForPolicyFactory', 62 | deployer 63 | ) 64 | await dev.policyGroup.addGroup(policy.address, { 65 | from: policyFactory, 66 | }) 67 | 68 | const result = await dev.policyGroup.isGroup(policy.address) 69 | expect(result).to.be.equal(true) 70 | }) 71 | it('can add new policy', async () => { 72 | const policy = await dev.getPolicy( 73 | 'PolicyTestForPolicyFactory', 74 | deployer 75 | ) 76 | await dev.policyGroup.addGroup(policy.address, { 77 | from: policyFactory, 78 | }) 79 | 80 | const result = await dev.policyGroup.isGroup(policy.address) 81 | expect(result).to.be.equal(true) 82 | }) 83 | it('Existing policy cannot be added', async () => { 84 | const currentPolicy = await dev.addressConfig.policy() 85 | const result = await dev.policyGroup 86 | .addGroup(currentPolicy, { 87 | from: policyFactory, 88 | }) 89 | .catch((err: Error) => err) 90 | validateErrorMessage(result, 'already group') 91 | }) 92 | it('Can not execute addGroup without policyFactory address', async () => { 93 | const result = await dev.policyGroup 94 | .addGroup(dummyPolicy, { 95 | from: dummyPolicyFactory, 96 | }) 97 | .catch((err: Error) => err) 98 | validateAddressErrorMessage(result) 99 | }) 100 | }) 101 | describe('PolicyGroup; isDuringVotingPeriod', () => { 102 | it('If it is during the voting period, true will come back.', async () => { 103 | const policy = await dev.getPolicy( 104 | 'PolicyTestForPolicyFactory', 105 | deployer 106 | ) 107 | await dev.policyGroup.addGroup(policy.address, { 108 | from: policyFactory, 109 | }) 110 | let isDuringVotingPeriod = await dev.policyGroup.isDuringVotingPeriod( 111 | policy.address 112 | ) 113 | expect(isDuringVotingPeriod).to.be.equal(true) 114 | await mine(10) 115 | isDuringVotingPeriod = await dev.policyGroup.isDuringVotingPeriod( 116 | policy.address 117 | ) 118 | expect(isDuringVotingPeriod).to.be.equal(false) 119 | }) 120 | }) 121 | } 122 | ) 123 | -------------------------------------------------------------------------------- /test/policy/policy.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from 'bignumber.js' 2 | 3 | contract('Policy', ([account1, account2]) => { 4 | const policyContract = artifacts.require('PolicyTest1') 5 | let policy: any 6 | beforeEach(async () => { 7 | policy = await policyContract.new() 8 | }) 9 | describe('PolicyTest1; rewards', () => { 10 | it('Returns the total number of mint per block when the total number of lockups and the total number of assets is passed', async () => { 11 | const result = (await policy.rewards(45, 76)) as BigNumber 12 | expect(result.toNumber()).to.be.equal(121) 13 | }) 14 | }) 15 | describe('PolicyTest1; holdersShare', () => { 16 | it('Returns the reward that the Property holders can receive when the reward per Property and the number of locked-ups is passed', async () => { 17 | const result = (await policy.holdersShare(10000, 700)) as BigNumber 18 | expect(result.toNumber()).to.be.equal(9346) 19 | }) 20 | }) 21 | describe('PolicyTest1; authenticationFee', () => { 22 | it('Returns the authentication fee when the total number of assets and the number of lockups is passed', async () => { 23 | const result = (await policy.authenticationFee(1000, 100)) as BigNumber 24 | expect(result.toNumber()).to.be.equal(1099) 25 | }) 26 | }) 27 | describe('PolicyTest1; marketVotingBlocks', () => { 28 | it('Returns the number of the blocks of the voting period for the new Market', async () => { 29 | const result = (await policy.marketVotingBlocks()) as BigNumber 30 | expect(result.toNumber()).to.be.equal(10) 31 | }) 32 | }) 33 | describe('PolicyTest1; policyVotingBlocks', () => { 34 | it('Returns the number of the blocks of the voting period for the new Policy', async () => { 35 | const result = (await policy.policyVotingBlocks()) as BigNumber 36 | expect(result.toNumber()).to.be.equal(20) 37 | }) 38 | }) 39 | describe('PolicyTest1; shareOfTreasury', () => { 40 | it('Returns the number of the share treasury', async () => { 41 | const result = (await policy.shareOfTreasury(100)) as BigNumber 42 | expect(result.toNumber()).to.be.equal(5) 43 | }) 44 | }) 45 | describe('PolicyTest1; setTreasury', () => { 46 | it('get the set treasury address', async () => { 47 | await policy.setTreasury(account1) 48 | const tmp = (await policy.treasury()) as string 49 | expect(tmp).to.be.equal(account1) 50 | }) 51 | }) 52 | describe('PolicyTest1; setCapSetter', () => { 53 | it('get the set cap setter address', async () => { 54 | await policy.setCapSetter(account2) 55 | const tmp = (await policy.capSetter()) as string 56 | expect(tmp).to.be.equal(account2) 57 | }) 58 | }) 59 | }) 60 | -------------------------------------------------------------------------------- /test/policy/utils.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from 'bignumber.js' 2 | 3 | const random = (): BigNumber => 4 | ((f) => new BigNumber(f()).times(f().slice(0, 1)))((): string => 5 | Math.random().toString().replace('0.', '') 6 | ) 7 | export const batchRandom = (): BigNumber[] => [ 8 | random(), 9 | random(), 10 | random(), 11 | random(), 12 | random(), 13 | random(), 14 | random(), 15 | random(), 16 | random(), 17 | random(), 18 | random(), 19 | random(), 20 | ] 21 | -------------------------------------------------------------------------------- /test/property/property-group.ts: -------------------------------------------------------------------------------- 1 | import { DevProtocolInstance } from '../test-lib/instance' 2 | import { 3 | validateErrorMessage, 4 | validateAddressErrorMessage, 5 | } from '../test-lib/utils/error' 6 | 7 | contract( 8 | 'PrpertyGroupTest', 9 | ([ 10 | deployer, 11 | propertyFactory, 12 | dummyPropertyFactory, 13 | property, 14 | dummyProperty, 15 | ]) => { 16 | const dev = new DevProtocolInstance(deployer) 17 | describe('PrpertyGroup; addGroup, isGroup', () => { 18 | before(async () => { 19 | await dev.generateAddressConfig() 20 | await dev.generatePropertyGroup() 21 | await dev.addressConfig.setPropertyFactory(propertyFactory, { 22 | from: deployer, 23 | }) 24 | await dev.propertyGroup.addGroup(property, { from: propertyFactory }) 25 | }) 26 | 27 | it('Create a new Property Contract and emit Create Event telling created property address', async () => { 28 | const result = await dev.propertyGroup.isGroup(property) 29 | expect(result).to.be.equal(true) 30 | }) 31 | 32 | it('Adds a new Property Contract address to State Contract', async () => { 33 | const result = await dev.propertyGroup.isGroup(dummyProperty) 34 | expect(result).to.be.equal(false) 35 | }) 36 | it('Existing property cannot be added', async () => { 37 | const result = await dev.propertyGroup 38 | .addGroup(property, { 39 | from: propertyFactory, 40 | }) 41 | .catch((err: Error) => err) 42 | validateErrorMessage(result, 'already enabled') 43 | }) 44 | it('Can not execute addGroup without propertyFactory address', async () => { 45 | const result = await dev.propertyGroup 46 | .addGroup(dummyProperty, { 47 | from: dummyPropertyFactory, 48 | }) 49 | .catch((err: Error) => err) 50 | validateAddressErrorMessage(result) 51 | }) 52 | }) 53 | } 54 | ) 55 | -------------------------------------------------------------------------------- /test/test-lib/const.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_ADDRESS = '0x0000000000000000000000000000000000000000' 2 | export const SHARE_OF_TREASURY = 5 // % 3 | -------------------------------------------------------------------------------- /test/test-lib/utils/common.ts: -------------------------------------------------------------------------------- 1 | import Web3 from 'web3' 2 | import BigNumber from 'bignumber.js' 3 | import { SHARE_OF_TREASURY } from './../const' 4 | 5 | export async function mine(count: number): Promise { 6 | for (let i = 0; i < count; i++) { 7 | // eslint-disable-next-line no-await-in-loop 8 | await new Promise((resolve) => { 9 | web3.currentProvider.send( 10 | { 11 | jsonrpc: '2.0', 12 | method: 'evm_mine', 13 | params: [], 14 | id: 0, 15 | }, 16 | resolve 17 | ) 18 | }) 19 | } 20 | } 21 | 22 | export const toBigNumber = (v: string | BigNumber | number): BigNumber => 23 | new BigNumber(v) 24 | 25 | export const collectsEth = 26 | (to: string) => 27 | async (accounts: Truffle.Accounts, min = 50, rate = 0.5): Promise => { 28 | const getBalance = async (address: string): Promise => 29 | web3.eth.getBalance(address).then(toBigNumber) 30 | const web3Client = new Web3( 31 | new Web3.providers.WebsocketProvider(web3.eth.currentProvider.host) 32 | ) 33 | const minimum = toBigNumber(Web3.utils.toWei(`${min}`, 'ether')) 34 | accounts.map(async (account) => { 35 | const [balance, value] = await Promise.all([ 36 | getBalance(to), 37 | getBalance(account), 38 | ]) 39 | if (balance.isLessThan(minimum)) { 40 | await web3Client.eth 41 | .sendTransaction({ 42 | to, 43 | from: account, 44 | value: value.times(rate).toFixed(), 45 | }) 46 | .catch((err: Error) => err) 47 | } 48 | }) 49 | } 50 | 51 | export const getBlock = async (): Promise => web3.eth.getBlockNumber() 52 | 53 | export function gasLogger(txRes: Truffle.TransactionResponse) { 54 | console.log(txRes.receipt.gasUsed) 55 | } 56 | 57 | export function keccak256(...values: string[]): string { 58 | return (web3 as Web3).utils.soliditySha3(...values)! 59 | } 60 | 61 | export function splitValue( 62 | _value: BigNumber, 63 | percentage = SHARE_OF_TREASURY 64 | ): [BigNumber, BigNumber] { 65 | const tmp = _value.div(new BigNumber(100)).times(new BigNumber(percentage)) 66 | const tmp2 = _value.minus(tmp) 67 | return [tmp2, tmp] 68 | } 69 | -------------------------------------------------------------------------------- /test/test-lib/utils/error.ts: -------------------------------------------------------------------------------- 1 | export function validateErrorMessage( 2 | result: any, 3 | errorMessage: string, 4 | reason = true 5 | ): void { 6 | const message = reason ? `Reason given: ${errorMessage}` : errorMessage 7 | expect(result).to.be.an.instanceOf(Error) 8 | expect((result as Error).message).to.include(message) 9 | } 10 | 11 | export function validateAddressErrorMessage(result: any, reason = true): void { 12 | validateErrorMessage(result, 'this is illegal address', reason) 13 | } 14 | 15 | export function validateNotOwnerErrorMessage(result: any, reason = true): void { 16 | validateErrorMessage(result, 'Ownable: caller is not the owner.', reason) 17 | } 18 | -------------------------------------------------------------------------------- /test/test-lib/utils/event.ts: -------------------------------------------------------------------------------- 1 | import Web3 from 'web3' 2 | import { AbiItem } from 'web3-utils' 3 | 4 | export const watch = 5 | (deployedContract: any) => 6 | ( 7 | name: string, 8 | handler: (err: Error, values: Record) => void 9 | ): void => { 10 | const { contract: deployed } = deployedContract as { 11 | contract: { _jsonInterface: AbiItem[]; _address: string } 12 | } 13 | const web3WithWebsockets = new Web3( 14 | new Web3.providers.WebsocketProvider(web3.eth.currentProvider.host) 15 | ) 16 | // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment 17 | const { events } = new web3WithWebsockets.eth.Contract( 18 | deployed._jsonInterface, 19 | deployed._address 20 | ) 21 | 22 | events.allEvents((err: Error, e: any) => { 23 | if (e.event === name) { 24 | handler(err, e.returnValues) 25 | } 26 | }) 27 | } 28 | 29 | export const waitForEvent = 30 | (deployedContract: any) => 31 | async (name: string, timeout = 10000): Promise => 32 | new Promise((resolve, reject) => { 33 | setTimeout(() => { 34 | reject(new Error()) 35 | }, timeout) 36 | watch(deployedContract)(name, (err) => { 37 | if (err) { 38 | reject(err) 39 | return 40 | } 41 | 42 | resolve() 43 | }) 44 | }) 45 | 46 | export const getEventValue = 47 | (deployedContract: any) => 48 | async (name: string, arg: string, timeout = 10000): Promise => 49 | new Promise((resolve, reject) => { 50 | setTimeout(() => { 51 | reject(new Error()) 52 | }, timeout) 53 | watch(deployedContract)(name, (err, values) => { 54 | if (err) { 55 | reject(err) 56 | return 57 | } 58 | 59 | resolve(values[arg]) 60 | }) 61 | }) 62 | -------------------------------------------------------------------------------- /test/test-lib/utils/log.ts: -------------------------------------------------------------------------------- 1 | export function getMarketAddress( 2 | transaction: Truffle.TransactionResponse 3 | ): string { 4 | const tmp = transaction.logs.filter( 5 | (e: { event: string }) => e.event === 'Create' 6 | )[0].args._market as string 7 | return tmp 8 | } 9 | 10 | export function getMetricsAddress( 11 | transaction: Truffle.TransactionResponse 12 | ): string { 13 | const tmp = transaction.logs.filter( 14 | (e: { event: string }) => e.event === 'Create' 15 | )[0].args._metrics as string 16 | return tmp 17 | } 18 | 19 | export function getPropertyAddress( 20 | transaction: Truffle.TransactionResponse 21 | ): string { 22 | const tmp = transaction.logs.filter( 23 | (e: { event: string }) => e.event === 'Create' 24 | )[0].args._property as string 25 | return tmp 26 | } 27 | 28 | export function getTransferToAddress( 29 | transaction: Truffle.TransactionResponse 30 | ): string { 31 | const tmp = transaction.logs.filter( 32 | (e: { event: string }) => e.event === 'Transfer' 33 | )[0].args.to as string 34 | return tmp 35 | } 36 | -------------------------------------------------------------------------------- /test/test-lib/utils/mint-amount.ts: -------------------------------------------------------------------------------- 1 | import BigNumber from 'bignumber.js' 2 | import { DevProtocolInstance } from '../instance' 3 | import { toBigNumber } from './common' 4 | import { PropertyInstance } from '../../../types/truffle-contracts' 5 | 6 | async function getWithdrawAmount( 7 | dev: DevProtocolInstance, 8 | propertyAddress: string 9 | ): Promise<[BigNumber, BigNumber]> { 10 | const cal = await dev.allocator 11 | .calculateMaxRewardsPerBlock() 12 | .then(toBigNumber) 13 | const policyAddress = await dev.addressConfig.policy() 14 | // eslint-disable-next-line @typescript-eslint/await-thenable 15 | const policyInstance = await artifacts.require('IPolicy').at(policyAddress) 16 | const value = await dev.lockup.getPropertyValue(propertyAddress) 17 | const share = await policyInstance 18 | .holdersShare(cal.toFixed(), value.toString()) 19 | .then(toBigNumber) 20 | return [cal, share] 21 | } 22 | 23 | export async function getWithdrawHolderAmount( 24 | dev: DevProtocolInstance, 25 | propertyAddress: string, 26 | transitionalBlock = 1 27 | ): Promise { 28 | const [, share] = await getWithdrawAmount(dev, propertyAddress) 29 | return share.times(transitionalBlock) 30 | } 31 | 32 | export async function getWithdrawInterestAmount( 33 | dev: DevProtocolInstance, 34 | calculateWithdrawableAmount: BigNumber, 35 | propertyAddress: string, 36 | transitionalBlock = 1 37 | ): Promise { 38 | const [cal, share] = await getWithdrawAmount(dev, propertyAddress) 39 | const tmp = cal.minus(share) 40 | return calculateWithdrawableAmount.plus(tmp.times(transitionalBlock)) 41 | } 42 | 43 | // eslint-disable-next-line max-params 44 | export async function getWithdrawHolderSplitAmount( 45 | dev: DevProtocolInstance, 46 | calculateWithdrawableAmount: BigNumber, 47 | property: PropertyInstance, 48 | user: string, 49 | transitionalBlock = 1 50 | ): Promise { 51 | const [, share] = await getWithdrawAmount(dev, property.address) 52 | const totalSupply = await property.totalSupply().then(toBigNumber) 53 | const balance = await property.balanceOf(user).then(toBigNumber) 54 | const tmp = share.div(totalSupply).times(balance) 55 | return calculateWithdrawableAmount.plus(tmp.times(transitionalBlock)) 56 | } 57 | -------------------------------------------------------------------------------- /test/test-lib/utils/snapshot.ts: -------------------------------------------------------------------------------- 1 | export const takeSnapshot = async () => 2 | new Promise((resolve, reject) => { 3 | web3.currentProvider.send( 4 | { 5 | jsonrpc: '2.0', 6 | method: 'evm_snapshot', 7 | id: new Date().getTime(), 8 | }, 9 | (err: Error, snapshotId: number) => { 10 | if (err) { 11 | reject(err) 12 | } 13 | 14 | resolve(snapshotId) 15 | } 16 | ) 17 | }) 18 | 19 | export const revertToSnapshot = async (id: string) => 20 | new Promise((resolve, reject) => { 21 | web3.currentProvider.send( 22 | { 23 | jsonrpc: '2.0', 24 | method: 'evm_revert', 25 | params: [id], 26 | id: new Date().getTime(), 27 | }, 28 | (err: Error, result: unknown) => { 29 | if (err) { 30 | reject(err) 31 | } 32 | 33 | resolve(result) 34 | } 35 | ) 36 | }) 37 | 38 | export type Snapshot = { 39 | id: number 40 | jsonrpc: string 41 | result: string 42 | } 43 | -------------------------------------------------------------------------------- /test/withdraw/withdraw-common.ts: -------------------------------------------------------------------------------- 1 | import { DevProtocolInstance } from '../test-lib/instance' 2 | import { 3 | MetricsInstance, 4 | PropertyInstance, 5 | IPolicyInstance, 6 | MarketInstance, 7 | } from '../../types/truffle-contracts' 8 | import BigNumber from 'bignumber.js' 9 | import { getPropertyAddress, getMarketAddress } from '../test-lib/utils/log' 10 | import { getEventValue } from '../test-lib/utils/event' 11 | 12 | export const init = async ( 13 | deployer: string, 14 | user: string, 15 | generateWithdrawTest = false 16 | ): Promise< 17 | [ 18 | DevProtocolInstance, 19 | MetricsInstance, 20 | PropertyInstance, 21 | IPolicyInstance, 22 | MarketInstance 23 | ] 24 | > => { 25 | const dev = new DevProtocolInstance(deployer) 26 | await dev.generateAddressConfig() 27 | await dev.generateDev() 28 | await dev.generateDevMinter() 29 | await dev.generateSTokenManager() 30 | await Promise.all([ 31 | dev.generateAllocator(), 32 | dev.generateMarketFactory(), 33 | dev.generateMarketGroup(), 34 | dev.generateMetricsFactory(), 35 | dev.generateMetricsGroup(), 36 | dev.generateLockup(), 37 | dev.generatePropertyFactory(), 38 | dev.generatePropertyGroup(), 39 | dev.generatePolicyFactory(), 40 | dev.generatePolicyGroup(), 41 | ]) 42 | if (generateWithdrawTest) { 43 | await dev.generateWithdrawTest() 44 | } else { 45 | await dev.generateWithdraw() 46 | } 47 | 48 | await dev.dev.mint(deployer, new BigNumber(1e18).times(10000000)) 49 | await dev.dev.mint(user, new BigNumber(1e18).times(10000000)) 50 | 51 | const policyAddress = await dev.generatePolicy('PolicyTestForWithdraw') 52 | // eslint-disable-next-line @typescript-eslint/await-thenable 53 | const policy = await artifacts 54 | .require('PolicyTestForWithdraw') 55 | .at(policyAddress) 56 | const propertyAddress = getPropertyAddress( 57 | await dev.propertyFactory.create('test', 'TEST', deployer) 58 | ) 59 | const [property] = await Promise.all([ 60 | artifacts.require('Property').at(propertyAddress), 61 | ]) 62 | await dev.metricsGroup.__setMetricsCountPerProperty(property.address, 1) 63 | const marketBehavior = await artifacts 64 | .require('MarketTest1') 65 | .new(dev.addressConfig.address) 66 | const marketAddress = getMarketAddress( 67 | await dev.marketFactory.create(marketBehavior.address) 68 | ) 69 | await marketBehavior.setAssociatedMarket(marketAddress) 70 | const [market] = await Promise.all([ 71 | artifacts.require('Market').at(marketAddress), 72 | ]) 73 | market 74 | .authenticate(property.address, 'id1', '', '', '', '') 75 | .catch(console.error) 76 | const metricsAddress = await (async () => 77 | getEventValue(dev.metricsFactory)('Create', '_metrics'))() 78 | const [metrics] = await Promise.all([ 79 | artifacts.require('Metrics').at(metricsAddress as string), 80 | ]) 81 | await dev.lockup.update() 82 | 83 | return [dev, metrics, property, policy, market] 84 | } 85 | -------------------------------------------------------------------------------- /test/withdraw/withdraw-storage.ts: -------------------------------------------------------------------------------- 1 | import { WithdrawStorageTestInstance } from '../../types/truffle-contracts' 2 | 3 | contract('WithdrawStorageTest', ([withdraw, property, user]) => { 4 | let storage: WithdrawStorageTestInstance 5 | before(async () => { 6 | storage = await artifacts.require('WithdrawStorageTest').new() 7 | await storage.createStorage() 8 | }) 9 | describe('WithdrawStorageTest; setRewardsAmount, getRewardsAmount', () => { 10 | it('Initial value is 0.', async () => { 11 | const result = await storage.getRewardsAmount(property, { 12 | from: withdraw, 13 | }) 14 | expect(result.toNumber()).to.be.equal(0) 15 | }) 16 | it('The set value can be taken as it is.', async () => { 17 | await storage.setRewardsAmountTest(property, 5, { 18 | from: withdraw, 19 | }) 20 | const result = await storage.getRewardsAmount(property, { 21 | from: withdraw, 22 | }) 23 | expect(result.toNumber()).to.be.equal(5) 24 | }) 25 | }) 26 | describe('WithdrawStorageTest; setCumulativePrice, getCumulativePrice', () => { 27 | it('Initial value is 0.', async () => { 28 | const result = await storage.getCumulativePrice(property, { 29 | from: withdraw, 30 | }) 31 | expect(result.toNumber()).to.be.equal(0) 32 | }) 33 | it('The set value can be taken as it is.', async () => { 34 | await storage.setCumulativePriceTest(property, 50, { 35 | from: withdraw, 36 | }) 37 | const result = await storage.getCumulativePrice(property, { 38 | from: withdraw, 39 | }) 40 | expect(result.toNumber()).to.be.equal(50) 41 | }) 42 | }) 43 | describe('WithdrawStorageTest; setLastWithdrawalPrice, getLastWithdrawalPrice', () => { 44 | it('Initial value is 0.', async () => { 45 | const result = await storage.getLastWithdrawalPrice(property, user, { 46 | from: withdraw, 47 | }) 48 | expect(result.toNumber()).to.be.equal(0) 49 | }) 50 | it('The set value can be taken as it is.', async () => { 51 | await storage.setLastWithdrawalPriceTest(property, user, 50000, { 52 | from: withdraw, 53 | }) 54 | const result = await storage.getLastWithdrawalPrice(property, user, { 55 | from: withdraw, 56 | }) 57 | expect(result.toNumber()).to.be.equal(50000) 58 | }) 59 | }) 60 | describe('WithdrawStorageTest; setPendingWithdrawal, getPendingWithdrawal', () => { 61 | it('Initial value is 0.', async () => { 62 | const result = await storage.getPendingWithdrawal(property, user, { 63 | from: withdraw, 64 | }) 65 | expect(result.toNumber()).to.be.equal(0) 66 | }) 67 | it('The set value can be taken as it is.', async () => { 68 | await storage.setPendingWithdrawalTest(property, user, 500000, { 69 | from: withdraw, 70 | }) 71 | const result = await storage.getPendingWithdrawal(property, user, { 72 | from: withdraw, 73 | }) 74 | expect(result.toNumber()).to.be.equal(500000) 75 | }) 76 | }) 77 | describe('WithdrawStorageTest; setStorageLastWithdrawnRewardCap, getStorageLastWithdrawnRewardCap', () => { 78 | it('Initial value is 0.', async () => { 79 | const result = await storage.getStorageLastWithdrawnRewardCap( 80 | property, 81 | user, 82 | { 83 | from: withdraw, 84 | } 85 | ) 86 | expect(result.toNumber()).to.be.equal(0) 87 | }) 88 | it('The set value can be taken as it is.', async () => { 89 | await storage.setStorageLastWithdrawnRewardCapTest( 90 | property, 91 | user, 92 | 5000000, 93 | { 94 | from: withdraw, 95 | } 96 | ) 97 | const result = await storage.getStorageLastWithdrawnRewardCap( 98 | property, 99 | user, 100 | { 101 | from: withdraw, 102 | } 103 | ) 104 | expect(result.toNumber()).to.be.equal(5000000) 105 | }) 106 | }) 107 | }) 108 | -------------------------------------------------------------------------------- /test/withdraw/withdraw.ts: -------------------------------------------------------------------------------- 1 | import { init } from './withdraw-common' 2 | import { DevProtocolInstance } from '../test-lib/instance' 3 | import { PropertyInstance } from '../../types/truffle-contracts' 4 | import { 5 | takeSnapshot, 6 | revertToSnapshot, 7 | Snapshot, 8 | } from '../test-lib/utils/snapshot' 9 | import { 10 | validateErrorMessage, 11 | validateAddressErrorMessage, 12 | } from '../test-lib/utils/error' 13 | 14 | contract('WithdrawTest', ([deployer, user1, , user3]) => { 15 | let dev: DevProtocolInstance 16 | let property: PropertyInstance 17 | let snapshot: Snapshot 18 | let snapshotId: string 19 | 20 | before(async () => { 21 | ;[dev, , property] = await init(deployer, user3) 22 | }) 23 | 24 | beforeEach(async () => { 25 | snapshot = (await takeSnapshot()) as Snapshot 26 | snapshotId = snapshot.result 27 | }) 28 | 29 | afterEach(async () => { 30 | await revertToSnapshot(snapshotId) 31 | }) 32 | 33 | describe('Withdraw; withdraw', () => { 34 | it('should fail to call when passed address is not property contract', async () => { 35 | const res = await dev.withdraw 36 | .withdraw(deployer) 37 | .catch((err: Error) => err) 38 | validateAddressErrorMessage(res) 39 | }) 40 | it(`should fail to call when hasn't withdrawable amount`, async () => { 41 | const res = await dev.withdraw 42 | .withdraw(property.address, { from: user1 }) 43 | .catch((err: Error) => err) 44 | validateErrorMessage(res, 'withdraw value is 0') 45 | }) 46 | }) 47 | describe('Withdraw; devMinter', () => { 48 | it('get the address of the DevMinter contract.', async () => { 49 | const devMinterAddress = await dev.withdraw.devMinter() 50 | expect(devMinterAddress).to.be.equal(dev.devMinter.address) 51 | }) 52 | }) 53 | }) 54 | -------------------------------------------------------------------------------- /truffle-config.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | /* eslint-disable @typescript-eslint/no-require-imports */ 3 | 4 | require('ts-node/register') 5 | require('dotenv').config() 6 | const HDWalletProvider = require('@truffle/hdwallet-provider') 7 | const { 8 | ETHEREUM_PROVIDERS_MAINNET, 9 | ETHEREUM_PROVIDERS_ROPSTEN, 10 | ETHEREUM_PROVIDERS_AZURE, 11 | ETHEREUM_WALLET_MNEMONIC, 12 | ETHEREUM_MOCK_HOST, 13 | ETHEREUM_MOCK_PORT, 14 | ETHEREUM_ETHERSCAN_API_KEY, 15 | } = process.env 16 | 17 | module.exports = { 18 | test_file_extension_regexp: /.*\.ts$/, 19 | compilers: { 20 | solc: { 21 | version: '^0.5.16', 22 | settings: { 23 | optimizer: { 24 | enabled: true, 25 | }, 26 | }, 27 | }, 28 | }, 29 | networks: { 30 | mainnet: { 31 | provider: () => 32 | new HDWalletProvider( 33 | ETHEREUM_WALLET_MNEMONIC, 34 | ETHEREUM_PROVIDERS_MAINNET 35 | ), 36 | network_id: 1, 37 | gas: 4000000, 38 | gasPrice: 10000000000, 39 | }, 40 | ropsten: { 41 | provider: () => 42 | new HDWalletProvider( 43 | ETHEREUM_WALLET_MNEMONIC, 44 | ETHEREUM_PROVIDERS_ROPSTEN 45 | ), 46 | network_id: 3, 47 | gas: 4000000, 48 | gasPrice: 10000000000, 49 | }, 50 | mock: { 51 | host: ETHEREUM_MOCK_HOST, 52 | port: ETHEREUM_MOCK_PORT, 53 | network_id: '*', 54 | }, 55 | azure: { 56 | provider: () => 57 | new HDWalletProvider( 58 | ETHEREUM_WALLET_MNEMONIC, 59 | ETHEREUM_PROVIDERS_AZURE 60 | ), 61 | network_id: '*', 62 | gas: 0, 63 | gasPrice: 0, 64 | }, 65 | }, 66 | plugins: ['truffle-plugin-verify'], 67 | api_keys: { 68 | etherscan: ETHEREUM_ETHERSCAN_API_KEY, 69 | }, 70 | } 71 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["test"] 4 | } 5 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "lib": ["es2015", "es2016", "es2017", "es2018", "esnext"], 5 | "moduleResolution": "node", 6 | "module": "commonjs", 7 | "strict": true, 8 | "rootDir": "./", 9 | "esModuleInterop": true, 10 | "skipLibCheck": true, 11 | "resolveJsonModule": true, 12 | "typeRoots": ["./node_modules/@types", "./types"], 13 | "types": ["node", "truffle-contracts"] 14 | }, 15 | "include": ["**/*"] 16 | } 17 | --------------------------------------------------------------------------------