├── .dapploy ├── .eslintrc ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .remarkrc ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── dapploy ├── greenkeeper.json ├── package.json ├── reports └── empty ├── scripts └── fetch_abi.py ├── sonar-project.properties ├── src ├── awsFolderUploader.js ├── configParser.js ├── deployDapp.js ├── deployTemplate.js ├── execWrapper.js ├── fileReader.js ├── index.html ├── ipfsUploader.js ├── truffleMigrator.js └── web3ConfigExporter.js ├── templates ├── template-solidity │ ├── .babelrc │ ├── .circleci │ │ └── config.yml │ ├── .dapploy │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── adapters │ │ ├── CappedCrowdsaleAdapter.sol │ │ ├── ERC20Adapter.sol │ │ ├── ERC721Adapter.sol │ │ ├── PaymentChannel.sol │ │ └── RefundEscrowAdapter.sol │ ├── contracts │ │ ├── Migrations.sol │ │ ├── access │ │ │ ├── Roles.sol │ │ │ └── roles │ │ │ │ ├── CapperRole.sol │ │ │ │ ├── MinterRole.sol │ │ │ │ ├── PauserRole.sol │ │ │ │ ├── SignerRole.sol │ │ │ │ ├── WhitelistAdminRole.sol │ │ │ │ └── WhitelistedRole.sol │ │ ├── cryptography │ │ │ ├── ECDSA.sol │ │ │ └── MerkleProof.sol │ │ ├── drafts │ │ │ ├── .gitkeep │ │ │ ├── Counters.sol │ │ │ ├── ERC1046 │ │ │ │ └── ERC20Metadata.sol │ │ │ ├── ERC20Snapshot.sol │ │ │ ├── SignatureBouncer.sol │ │ │ └── SignedSafeMath.sol │ │ ├── introspection │ │ │ ├── ERC165.sol │ │ │ ├── ERC165Checker.sol │ │ │ └── IERC165.sol │ │ ├── lifecycle │ │ │ └── Pausable.sol │ │ ├── math │ │ │ ├── Math.sol │ │ │ └── SafeMath.sol │ │ ├── ownership │ │ │ ├── Ownable.sol │ │ │ └── Secondary.sol │ │ ├── token │ │ │ ├── ERC20 │ │ │ │ ├── ERC20.sol │ │ │ │ ├── ERC20Burnable.sol │ │ │ │ ├── ERC20Capped.sol │ │ │ │ ├── ERC20Detailed.sol │ │ │ │ ├── ERC20Mintable.sol │ │ │ │ ├── ERC20Pausable.sol │ │ │ │ └── IERC20.sol │ │ │ └── ERC721 │ │ │ │ ├── ERC721.sol │ │ │ │ ├── ERC721Burnable.sol │ │ │ │ ├── ERC721Enumerable.sol │ │ │ │ ├── ERC721Full.sol │ │ │ │ ├── ERC721Holder.sol │ │ │ │ ├── ERC721Metadata.sol │ │ │ │ ├── ERC721MetadataMintable.sol │ │ │ │ ├── ERC721Mintable.sol │ │ │ │ ├── ERC721Pausable.sol │ │ │ │ ├── IERC721.sol │ │ │ │ ├── IERC721Enumerable.sol │ │ │ │ ├── IERC721Full.sol │ │ │ │ ├── IERC721Metadata.sol │ │ │ │ └── IERC721Receiver.sol │ │ └── utils │ │ │ ├── Address.sol │ │ │ ├── Arrays.sol │ │ │ └── ReentrancyGuard.sol │ ├── env.template │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── package.json │ ├── src │ │ └── empty │ ├── truffle.js │ └── yarn.lock ├── template-web3-client.js └── template-web3-server.js └── yarn.lock /.dapploy: -------------------------------------------------------------------------------- 1 | # Where to find your truffle project, the network and where you want to copy locally 2 | [Truffle] 3 | projectDir=./samples/sample-datavault-solidity 4 | network=development 5 | contractOutput=./samples/sample-datavault-react/src/ABI 6 | 7 | # Include if you want to remote copy your contract ABIs to AWS backend 8 | # Setup your aws_access_key_id and aws_secret_access_key in ~/.aws/credentials 9 | #[AWS] 10 | #bucketName=layerone.smart-contracts 11 | #remotePath=ABI 12 | 13 | # Where to place generated web3 interface adapter on web3 client, 14 | # add any exclusions to keep from config 15 | [Web3] 16 | web3ClientPath=./samples/sample-datavault-react/src/web3Adapter-client.js 17 | excludeContracts=Migrations,QuadkeyLib,DutchAuctionLib 18 | 19 | # Include Portis section if you want Portis support in your web3 client 20 | # [Portis] 21 | # portisApiKey= 22 | # infuraApiKey= 23 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["airbnb", "standard", "standard-react"], 3 | "parser": "babel-eslint", 4 | "env": { 5 | "browser": true, 6 | "node": true, 7 | "es6": true, 8 | "mocha": true 9 | }, 10 | "rules": { 11 | "func-names": 0, 12 | "quotes": [2, "backtick"], 13 | "no-plusplus": 0, 14 | "class-methods-use-this": 0, 15 | "prefer-destructuring": 0, 16 | "max-len": 0, 17 | "no-console": 0 18 | }, 19 | "globals": {} 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | 6 | jobs: 7 | build: 8 | 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: actions/setup-node@v1 14 | with: 15 | node-version: '10.x' 16 | - uses: sonarsource/sonarcloud-github-action@master 17 | env: 18 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 19 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN_1 }} 20 | - name: build 21 | run: | 22 | yarn install 23 | ./dapploy init test 24 | cd test 25 | yarn install 26 | node_modules/.bin/ganache-cli > /dev/null & sleep 5 27 | ../dapploy -c .dapploy 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | keys 9 | password 10 | react 11 | sample/truffle-project/build 12 | dist 13 | 14 | # Runtime data 15 | pids 16 | *.pid 17 | *.seed 18 | *.pid.lock 19 | 20 | # Directory for instrumented libs generated by jscoverage/JSCover 21 | lib-cov 22 | 23 | # Coverage directory used by tools like istanbul 24 | coverage 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # TypeScript v1 declaration files 46 | typings/ 47 | 48 | # Optional npm cache directory 49 | .npm 50 | 51 | # Optional eslint cache 52 | .eslintcache 53 | 54 | # Optional REPL history 55 | .node_repl_history 56 | 57 | # Output of 'npm pack' 58 | *.tgz 59 | 60 | # Yarn Integrity file 61 | .yarn-integrity 62 | 63 | # dotenv environment variables file 64 | .env 65 | 66 | # next.js build output 67 | .next 68 | 69 | samples/.DS_Store 70 | .DS_Store 71 | -------------------------------------------------------------------------------- /.remarkrc: -------------------------------------------------------------------------------- 1 | { 2 | 3 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [logo]: https://cdn.xy.company/img/brand/XYO_full_colored.png 2 | 3 | [![logo]](https://xyo.network) 4 | 5 | # dApploy 6 | 7 | ![](https://github.com/XYOracleNetwork/tool-dapploy-nodejs/workflows/CI/badge.svg) [![Maintainability](https://api.codeclimate.com/v1/badges/f3dd4f4d35e1bd9eeabc/maintainability)](https://codeclimate.com/github/XYOracleNetwork/tool-dapploy-nodejs/maintainability) [![DepShield Badge](https://depshield.sonatype.org/badges/XYOracleNetwork/tool-dapploy-nodejs/depshield.svg)](https://depshield.github.io) [![BCH compliance](https://bettercodehub.com/edge/badge/XYOracleNetwork/tool-dapploy-nodejs?branch=master)](https://bettercodehub.com/results/XYOracleNetwork/tool-dapploy-nodejs) [![Sonarcloud Status](https://sonarcloud.io/api/project_badges/measure?project=XYOracleNetwork_sdk-core-nodejs&metric=alert_status)](https://sonarcloud.io/dashboard?id=XYOracleNetwork_sdk-core-nodejs) [![Known Vulnerabilities](https://snyk.io/test/github/XYOracleNetwork/tool-dapploy-nodejs/badge.svg)](https://snyk.io/test/github/XYOracleNetwork/tool-dapploy-nodejs) 8 | 9 | ## Table of Contents 10 | 11 | - [Title](#dapploy) 12 | - [Getting Started](#getting-started) 13 | - [Install](#install) 14 | - [Usage](#usage) 15 | - [Creating a smart contract](#creating-a-smart-contract) 16 | - [dApploy an ABI to IPFS](#dapploy-an-abi-to-ipfs) 17 | - [dApploy to public testnet or mainnet](#dapploy-to-public-testnet-or-mainnet) 18 | - [Use S3 to host your ABI](#use-s3-to-host-your-abi) 19 | - [License](#license) 20 | - [Credits](#credits) 21 | 22 | ## Getting Started 23 | 24 | Finally, you can deploy dApps in less than 5 seconds flat WITHOUT even lifting a finger... Guaranteed! 25 | 26 | OK, you may have to lift a finger. 27 | 28 | But here's the deal. 29 | 30 | We've gone through the hoops of deploying dApps on the Ethereum Network and have nuked out all of the annoying parts to make dapployment a breeze. 31 | 32 | ### Install 33 | 34 | 1. Install from source to get access to the sample projects. Remember, 'YARN ALL THE THINGS' from the main project dir by running this: 35 | 36 | 37 | yarn && cd samples/sample-datavault-react/ && yarn && cd ../sample-datavault-solidity && yarn && cd ../.. 38 | 39 | 2. _OR_ globally install Dapploy using: 40 | ``` 41 | yarn global add @xyo-network/tool-dapploy-nodejs 42 | OR 43 | npm install -g @xyo-network/tool-dapploy-nodejs 44 | ``` 45 | 46 | ### Usage 47 | 48 | 3. Run `dapploy -h` to see the options: 49 | 50 | 51 | $> dapploy -h 52 | Usage: dapploy [options] [command] 53 | 54 | Options: 55 | 56 | -V, --version output the version number 57 | -t, --projectDir Truffle Project Directory 58 | -n, --network [network] Deploy to network (default: development) 59 | -c, --config Config file (default: .dapploy) 60 | -o, --contractOutput Contract Output Directory 61 | -x, --excludeContracts [Contract1,Contract2] Exclude contracts from the web3 interface (files are still copied) 62 | -a, --includeContracts [Contract1,Contract2] Include contracts from the web3 interface (files are still copied) 63 | -l, --clean Clean contracts before migrating 64 | -r, --remoteOnly Only copy contracts remote 65 | -p, --pinToIpfs Pin contracts to IPFS for remote 66 | -P, --postSaveToIpfs Save contracts to IPFS for remoteaccess after migrating 67 | -k, --bucketName Do remote copy of ABI to aws bucket (make sure to setup ~/.aws) 68 | -y, --copyOnly Only do folder copy and S3 copy 69 | -i, --init Add default config file to current directory 70 | -h, --help output usage information 71 | 72 | $> dapploy init -h 73 | Usage: init [options] [dir] 74 | 75 | Configure a new truffle project from scratch 76 | 77 | Options: 78 | 79 | -g, --configOnly Create dapploy config file in current directory 80 | -s, --specifyContract [contract] Which type of project to create. Supporting: [ERC20, ERC721] (default: ERC20) 81 | -h, --help output usage information 82 | 83 | 4. If you did not add dapploy globally with '-g', Add dapploy alias to run from any project in your bash_profile: 84 | 85 | 86 | echo "alias dapploy=\"//tool-dapploy-nodejs/dapploy\""| cat >> .bash_profile 87 | 88 | ### Creating a smart contract 89 | 90 | `dapploy init` - create a new smart contract project 91 | 92 | 1. Create a new ERC20 project using dapploy: 93 | 94 | 95 | dapploy init my-first-coin -s ERC20 96 | cd my-first-coin 97 | 98 | 2. Make sure Ganache is downloaded, installed and open: [Download and install Ganache from their site](https://truffleframework.com/ganache) 99 | 100 | - Click the Gear Icon thingy ( ⚙️ ) to open `Preferences...` 101 | Make sure that port is set to 8545. 102 | 103 | 3. Dapploy from root directory 104 | 105 | - if you have alias setup for dapploy, just run 106 | 107 | 108 | dapploy 109 | 110 | - otherwise run 111 | 112 | 113 | /dapploy 114 | 115 | Congrats, you just built your first ERC-20 Token! Head on over to [Dapper](https://github.com/XYOracleNetwork/tool-dapper-react) to play with it in a web-ui 116 | 117 | ### dApploy an ABI to IPFS 118 | 119 | dapploy -p 120 | 121 | $ Contracts stored to IPFS QmZ2Ezv4nsQ5tqGoHz4pUxa9GW88TWKMSzdxdMfxsHerWT 122 | $ View contracts at https://ipfs.xyo.network/ipfs/QmZ2Ezv4nsQ5tqGoHz4pUxa9GW88TWKMSzdxdMfxsHerWT 123 | 124 | ### dApploy to public testnet or mainnet 125 | 126 | 1. [Sign up for Infura](https://infura.io/) 127 | 128 | 2. [Install MetaMask from their site](https://metamask.io/) 129 | 130 | - Sign into Metamask and change Network on Metamask to kovan/ropsten/mainnet 131 | 132 | 3. Add your metamask wallet and infura data to `env.template` file: 133 | 134 | 135 | WALLET=// wallet used to deploy contracts 136 | INFURA_API_KEY=// API key you get from infura 137 | MNENOMIC=// 12 word pass key from derived from your wallet private key 138 | 139 | 4. Move `env.template` to `.env` (this file is already in your .gitignore) 140 | 141 | 142 | mv env.template .env 143 | 144 | 5. Using kovan, run 145 | 146 | 147 | dapploy -n kovan 148 | 149 | Ropsten: 150 | 151 | dapploy -n ropsten 152 | 153 | _NOTE_ You don't need to specify `-n network` if you change `.dapploy` configuration file in your project from `network=development` to `network=kovan` etc. 154 | 155 | vi .dapploy 156 | 157 | If you are feeling adventurous run a local testnet node: 158 | 159 | [Ropsten testnet node setup (Geth)](https://github.com/XYOracleNetwork/tool-dapploy-nodejs/wiki/Local-Ropsten-Config) 160 | 161 | [Kovan testnet node setup (Parity)](https://github.com/XYOracleNetwork/tool-dapploy-nodejs/wiki/Kovan-setup-(Parity)) 162 | 163 | ### Multiple Browser Support 164 | 165 | 1. Setup account with [portis.io](https://portis.io) 166 | 167 | 2. Add Portis and Infura key to .dapploy 168 | 169 | 170 | vi .dapploy 171 | 172 | Uncomment: 173 | 174 | # [Portis] 175 | # portisApiKey= 176 | # infuraApiKey= 177 | 178 | ### Use S3 to host your ABI 179 | 180 | 1. Confugure your AWS credentials in terminal by creating credentials file. [S3 credential instructions here](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-credentials.html): 181 | 182 | 183 | vi ~/.aws/credentials 184 | [default] 185 | aws_access_key_id = AKIAIFYQ4UEUUJ6GDH6A 186 | aws_secret_access_key = FAKEasdfas=aqewrasdfa/sdfasdfasdfasdfFAKE 187 | 188 | 2. Configure dapploy 189 | 190 | 191 | vi .dapploy 192 | 193 | Uncomment: 194 | 195 | #[AWS] 196 | #bucketName=layerone.smart-contracts 197 | #remotePath=ABI 198 | 199 | ## License 200 | 201 | See the [LICENSE](LICENSE) file for license details. 202 | 203 | ## Credits 204 | 205 | Made with 🔥and ❄️ by [XYO](https://www.xyo.network) 206 | 207 | -------------------------------------------------------------------------------- /dapploy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /* ** Main Program ** 4 | 5 | @description - This program may be configured using parameter options below 6 | Makes it simple to deploy your contracts to your network of choice 7 | run with --help 8 | */ 9 | const program = require(`commander`) 10 | const { dapploy } = require(`./src/deployDapp`) 11 | const { parseConfig, initConfig } = require(`./src/configParser`) 12 | const { buildAndDeployTemplate, supported } = require(`./src/deployTemplate`) 13 | const defaultConfig = `.dapploy` 14 | const version = require(`./package.json`).version 15 | 16 | program 17 | .version(version) 18 | .option(`-t, --projectDir `, `Truffle Project Directory`) 19 | .option(`-n, --network `, `Deploy to network`) 20 | .option(`-c, --config `, `Config file`, defaultConfig) 21 | .option(`-o, --contractOutput `, `Contract Output Directory`) 22 | .option( 23 | `-x, --excludeContracts [Contract1,Contract2]`, 24 | `Exclude contracts from the web3 interface (files are still copied)` 25 | ) 26 | .option( 27 | `-a, --includeContracts [Contract1,Contract2]`, 28 | `Include contracts from the web3 interface (files are still copied)` 29 | ) 30 | .option(`-l, --clean`, `Clean contracts before migrating`) 31 | .option(`-r, --remoteOnly`, `Only copy contracts remote`) 32 | .option(`-p, --pinToIpfs`, `Pin contracts to IPFS for remote access`) 33 | .option(`-P, --postSaveToIpfs`, `Pin contracts to IPFS for remote access`) 34 | .option( 35 | `-k, --bucketName `, 36 | `Do remote copy of ABI to aws bucket (make sure to setup ~/.aws)` 37 | ) 38 | .option(`-y, --copyOnly`, `Only do folder copy and S3 copy`) 39 | .option(`-w, --web3Adapters`, `Create web3 Adapters from contracts dir`) 40 | .option(`-i, --init`, `Add default config file to current directory`) 41 | 42 | let execute = [p => dapploy(p)] 43 | program 44 | .command(`init [dir]`) 45 | .description(`Configure a new truffle project from scratch`) 46 | .option(`-g, --configOnly`, `Create dapploy config file in current directory`) 47 | .option( 48 | `-s, --specifyContract [contract]`, 49 | `Which type of project to create.\n\t\t\t\t\tSupporting: ${supported}`, 50 | `ERC20` 51 | ) 52 | .action((dir, cmd) => { 53 | // console.log("HERE", program, cmd) 54 | program.initPath = dir || `./` 55 | program.specifyContract = cmd.specifyContract 56 | if (cmd.configOnly) { 57 | execute = [p => initConfig(p)] 58 | } else { 59 | execute = [p => buildAndDeployTemplate(p)] 60 | } 61 | }) 62 | 63 | program.parse(process.argv) 64 | 65 | async function asyncForEach (array, callback) { 66 | for (let index = 0; index < array.length; index++) { 67 | await callback(array[index], index, array) 68 | } 69 | } 70 | 71 | try { 72 | parseConfig(program) 73 | } catch (err) { 74 | console.log(err) 75 | process.exit(1) 76 | } 77 | (async () => { 78 | asyncForEach(execute, async (exe) => { 79 | // console.log(`Running command`, exe) 80 | try { 81 | await exe(program) 82 | } catch (err) { 83 | console.log(err) 84 | process.exit(1) 85 | throw err 86 | } 87 | }) 88 | })() 89 | -------------------------------------------------------------------------------- /greenkeeper.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": { 3 | "default": { 4 | "packages": [ 5 | "package.json", 6 | "samples/sample-datavault-react/package.json", 7 | "samples/sample-datavault-solidity/package.json", 8 | "templates/template-solidity/package.json" 9 | ] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@xyo-network/tool-dapploy-nodejs", 3 | "version": "0.1.7", 4 | "license": "MIT", 5 | "description": "Dapploy is a handy CLI tool for dApps. Create, build, and dapploy your Smart Contracts!", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/XYOracleNetwork/tool-dapploy-nodejs.git" 9 | }, 10 | "bugs": { 11 | "url": "https://github.com/XYOracleNetwork/tool-dapploy-nodejs/issues" 12 | }, 13 | "dependencies": { 14 | "aws-sdk": "^2.605.0", 15 | "commander": "^4.1.0", 16 | "configparser": "^0.3.6", 17 | "ipfs-http-client": "^41.0.0", 18 | "shelljs": "^0.8.3", 19 | "truffle": "^5.1.9", 20 | "untildify": "^4.0.0", 21 | "web3": "^1.2.5-rc.0" 22 | }, 23 | "devDependencies": { 24 | "babel-eslint": "^10.0.3", 25 | "eslint": "^6.8.0", 26 | "eslint-config-airbnb": "^18.0.1", 27 | "eslint-config-standard": "^14.1.0", 28 | "eslint-config-standard-react": "^9.2.0", 29 | "eslint-plugin-import": "^2.20.0", 30 | "eslint-plugin-jsx-a11y": "^6.2.3", 31 | "eslint-plugin-node": "^11.0.0", 32 | "eslint-plugin-promise": "^4.2.1", 33 | "eslint-plugin-react": "^7.18.0", 34 | "eslint-plugin-standard": "^4.0.1", 35 | "ganache-cli": "^6.8.2" 36 | }, 37 | "publishConfig": { 38 | "registry": "https://registry.npmjs.org/" 39 | }, 40 | "bin": { 41 | "dapploy": "./dapploy" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /reports/empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XYOracleNetwork-v1/tool-dapploy-nodejs/96f95e66cd4f497b4a3e91bd71e4d2057aaf0643/reports/empty -------------------------------------------------------------------------------- /scripts/fetch_abi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import argparse 3 | import requests 4 | import json 5 | 6 | # Exports contract ABI in JSON 7 | 8 | ABI_ENDPOINT = 'https://api.etherscan.io/api?module=contract&action=getabi&address=' 9 | 10 | parser = argparse.ArgumentParser() 11 | parser.add_argument('addr', type=str, help='Contract address') 12 | parser.add_argument('-o', '--output', type=str, help="Path to the output JSON file", required=True) 13 | 14 | def __main__(): 15 | 16 | args = parser.parse_args() 17 | 18 | response = requests.get('%s%s'%(ABI_ENDPOINT, args.addr)) 19 | response_json = response.json() 20 | abi_json = json.loads(response_json['result']) 21 | result = json.dumps({"abi":abi_json}, indent=4, sort_keys=True) 22 | 23 | open(args.output, 'w').write(result) 24 | 25 | if __name__ == '__main__': 26 | __main__() 27 | -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.projectKey=XYOracleNetwork_tool-dapploy-nodejs 2 | sonar.projectName=tool-dapploy-nodejs 3 | 4 | # ===================================================== 5 | # Meta-data for the project 6 | # ===================================================== 7 | 8 | sonar.links.homepage=https://github.com/XYOracleNetwork/tool-dapploy-nodejs 9 | sonar.links.ci=https://github.com/XYOracleNetwork/tool-dapploy-nodejs 10 | sonar.links.scm=https://github.com/XYOracleNetwork/tool-dapploy-nodejs 11 | sonar.links.issue=https://github.com/XYOracleNetwork/tool-dapploy-nodejs/issues 12 | 13 | 14 | # ===================================================== 15 | # Properties that will be shared amongst all modules 16 | # ===================================================== 17 | 18 | sonar.host.url=https://sonarcloud.io 19 | sonar.organization=xyo-network 20 | sonar.sources=. 21 | sonar.exclusions=node_modules/**/* 22 | sonar.login=${SONAR_TOKEN} 23 | 24 | # ===================================================== 25 | # TypeScript config 26 | # ===================================================== 27 | sonar.typescript.tsconfigPath=./tsconfig.json -------------------------------------------------------------------------------- /src/awsFolderUploader.js: -------------------------------------------------------------------------------- 1 | const abiFilePaths = require(`./fileReader`).abiFilePaths 2 | 3 | const AWS = require(`aws-sdk`) 4 | const path = require(`path`) 5 | const fs = require(`fs`) 6 | 7 | const uploadFiles = (bucketName, remotePath, awsS3Client, files) => { 8 | const promises = [] 9 | // for each file in the directory 10 | files.forEach((filePath) => { 11 | const rPath = remotePath ? `${remotePath}/` : `` 12 | const fileName = `${rPath}${path.basename(filePath)}` 13 | // ignore if directory 14 | if (fs.lstatSync(filePath).isDirectory()) { 15 | return 16 | } 17 | promises.push( 18 | new Promise((resolve, reject) => { 19 | // read file contents 20 | fs.readFile(filePath, (error, fileContent) => { 21 | if (error) { 22 | reject(error) 23 | } 24 | console.log(`Saving`, bucketName, fileName) 25 | const params = { 26 | Bucket: bucketName, 27 | ACL: `bucket-owner-full-control`, 28 | Key: fileName, 29 | Body: fileContent, 30 | ContentType: `json` 31 | } 32 | // upload file to awsS3Client 33 | awsS3Client.putObject(params, (err, res) => { 34 | if (err) { 35 | return reject(err) 36 | } 37 | console.log(`Successfully uploaded '${fileName}'`) 38 | 39 | return resolve(res) 40 | }) 41 | }) 42 | }) 43 | ) 44 | }) 45 | return Promise.all(promises) 46 | } 47 | 48 | const clearBucket = async (bucketName, remotePath, awsS3Client) => { 49 | const params = { 50 | Bucket: bucketName, 51 | Prefix: `${remotePath}` 52 | } 53 | // console.log(` $ Clearing bucket ${JSON.stringify(params)}`) 54 | 55 | const listedObjects = await awsS3Client.listObjectsV2(params).promise() 56 | // console.log(` $ Objects in bucket ${JSON.stringify(listedObjects)}`) 57 | 58 | const deleteParams = { 59 | Bucket: bucketName, 60 | Delete: { Objects: [] } 61 | } 62 | if (listedObjects.Contents.length > 0) { 63 | listedObjects.Contents.forEach(({ Key }) => { 64 | deleteParams.Delete.Objects.push({ Key }) 65 | }) 66 | await awsS3Client.deleteObjects(deleteParams).promise() 67 | } 68 | 69 | if (listedObjects.Contents.IsTruncated) await clearBucket(bucketName, remotePath) 70 | } 71 | 72 | const uploadRemote = async (program) => { 73 | const bucketName = program.bucketName.substring( 74 | 0, 75 | program.bucketName.indexOf(`/`) 76 | ) 77 | let bucketPath = program.bucketName.substring( 78 | program.bucketName.indexOf(`/`) + 1, 79 | program.bucketName.length 80 | ) 81 | if (bucketPath && !bucketPath.endsWith(`/`)) { 82 | bucketPath = `${bucketPath}/` 83 | } 84 | 85 | if (bucketName) { 86 | return abiFilePaths(program).then(async (files) => { 87 | const rPath = program.remotePath ? `${program.remotePath}/` : bucketPath 88 | 89 | const remotePath = `${rPath}${program.network}` 90 | console.log(` $ Copying contracts to remote AWS bucket ${bucketName}`) 91 | 92 | const awsS3Client = new AWS.S3({ 93 | signatureVersion: `v4` 94 | }) 95 | 96 | // const client = s3.createClient() 97 | await clearBucket(bucketName, remotePath, awsS3Client) 98 | return uploadFiles(bucketName, remotePath, awsS3Client, files) 99 | }) 100 | } 101 | return true 102 | } 103 | 104 | module.exports = { uploadRemote } 105 | -------------------------------------------------------------------------------- /src/configParser.js: -------------------------------------------------------------------------------- 1 | const ConfigParser = require(`configparser`) 2 | 3 | const config = new ConfigParser() 4 | const untildify = require(`untildify`) 5 | const fs = require(`fs`) 6 | 7 | /* eslint no-param-reassign: "error" */ 8 | const parseParams = (program, section, params) => { 9 | params.forEach((param) => { 10 | const parsedParam = config.get(section, param) 11 | if (parsedParam && !program[param]) { 12 | program[param] = untildify(parsedParam) 13 | } 14 | }) 15 | } 16 | 17 | const configParsing = (program) => { 18 | if (config.sections().length > 0) { 19 | const abiDir = config.get(`Truffle`, `contractOutput`) 20 | if (abiDir) { 21 | program.contractOutput = abiDir 22 | } 23 | parseParams(program, `Truffle`, [`projectDir`, `network`]) 24 | 25 | if (config.sections().includes(`AWS`)) { 26 | parseParams(program, `AWS`, [`bucketName`, `remotePath`]) 27 | } 28 | 29 | if (config.sections().includes(`Web3`)) { 30 | parseParams(program, `Web3`, [`web3ClientPath`, `web3ServerPath`]) 31 | const excludeStr = config.get(`Web3`, `excludeContracts`) 32 | if (excludeStr) { 33 | program.excludeContracts = excludeStr.split(`,`) 34 | } 35 | } 36 | 37 | const includeStr = config.get(`Web3`, `includeContracts`) 38 | if (includeStr) { 39 | program.includeContracts = includeStr.split(`,`) 40 | } 41 | 42 | if (config.sections().includes(`Portis`)) { 43 | parseParams(program, `Portis`, [`portisApiKey`, `infuraApiKey`]) 44 | } 45 | } else { 46 | console.log(`Empty config file, using defaults`) 47 | } 48 | } 49 | 50 | const parseConfig = (program) => { 51 | console.log(` $ Parsing config`, program.config) 52 | try { 53 | config.read(program.config) 54 | } catch (err) { 55 | console.log(`Invalid or missing config, using defaults`) 56 | return 57 | } 58 | configParsing(program) 59 | } 60 | 61 | const initConfig = (program) => { 62 | let projectDir = program.initPath || `./` 63 | if (projectDir.charAt(projectDir.length - 1) !== `/`) { 64 | projectDir += `/` 65 | } 66 | const configFile = `${projectDir}.dapploy` 67 | if (fs.existsSync(configFile)) { 68 | throw new Error( 69 | `A config file was found at: ${configFile}. Stopping to prevent overwriting data.` 70 | ) 71 | } 72 | console.log(` $ Creating config file at ${configFile}`) 73 | // Adding sections and adding keys 74 | config.addSection(`Truffle`) 75 | config.set(`Truffle`, `projectDir`, `./`) 76 | config.set(`Truffle`, `network`, `development`) 77 | config.set(`Truffle`, `contractOutput`, `./src/ABI`) 78 | 79 | config.addSection(`Web3`) 80 | config.set(`Web3`, `web3ClientPath`, `./src/web3Adapter-client.js`) 81 | config.set(`Web3`, `web3ServerPath`, `./src/web3Adapter-server.js`) 82 | config.set(`Web3`, `excludeContracts`, `Migrations`) 83 | 84 | config.write(configFile) 85 | 86 | console.log(`$ Make sure you configure a "development" network in truffle.js`) 87 | return Promise.resolve(true) 88 | } 89 | 90 | module.exports = { parseConfig, initConfig } 91 | -------------------------------------------------------------------------------- /src/deployDapp.js: -------------------------------------------------------------------------------- 1 | const path = require(`path`) // from node.js 2 | const { uploadRemote } = require(`./awsFolderUploader`) 3 | const { migrateTruffle, contractDataOnNetwork } = require(`./truffleMigrator`) 4 | const { execPromise } = require(`./execWrapper`) 5 | const { 6 | exportClientConfig, 7 | exportServerConfig 8 | } = require(`./web3ConfigExporter`) 9 | const { uploadIPFS } = require(`./ipfsUploader`) 10 | const tempContractsOutput = `/tmp/tempContractsOutputFolder` 11 | /* Copies the contracts in the specified project to a local project (react client, etc) 12 | 13 | */ 14 | const copyContractsLocal = async (program) => { 15 | if (!program.contractOutput) { 16 | console.log( 17 | ` $ Skipping local copy add contractOutput param if you want to copy the ABI locally` 18 | ) 19 | return Promise.resolve() 20 | } 21 | const fromPath = path.join(program.projectDir, `build/contracts/*`) 22 | console.log(` $ Copying contracts locally to ${program.contractOutput}`) 23 | 24 | if (fromPath === program.contractOutput) { 25 | console.log(` $ From path is equal to path, ignoring copy`) 26 | // if contract output is equal to fromPath, just let it 27 | return Promise.resolve() 28 | } 29 | // Copy to temp folder before moving to destination in case src and dest are the same 30 | // Is there a cleaner way? 31 | // cp -rfpiU... all just throw errors when src == dest, and paths strings 32 | 33 | await execPromise(`mkdir -p ${tempContractsOutput}`) 34 | await execPromise(`mkdir -p ${program.contractOutput}`) 35 | await execPromise(`cp -p ${fromPath} ${tempContractsOutput}`) 36 | await execPromise(`mv ${tempContractsOutput}/* ${program.contractOutput}`) 37 | return execPromise(`rm -rf ${tempContractsOutput}`) 38 | } 39 | 40 | const cleanIfNeeded = (program) => { 41 | if (program.clean) { 42 | const clean = `rm -rf build` 43 | console.log(` $ Cleaning build folder at ${program.projectDir}`) 44 | return execPromise(clean, { cwd: program.projectDir }) 45 | } 46 | console.log(` $ Skipping cleaning (use -l for clean migration)`) 47 | 48 | return Promise.resolve() 49 | } 50 | 51 | const createWeb3Module = (program, contracts) => { 52 | if (program.web3ClientPath) { 53 | console.log(` $ Exporting Web3 Client module to ${program.web3ClientPath}`) 54 | exportClientConfig(program, contracts) 55 | } 56 | if (program.web3ServerPath) { 57 | console.log(` $ Exporting Web3 Server module to ${program.web3ServerPath}`) 58 | exportServerConfig(program, contracts) 59 | } 60 | if (program.web3Adapters) { 61 | process.exit(0) 62 | } 63 | } 64 | 65 | const dapploy = async (program) => { 66 | console.log(`Running dapploy`) 67 | 68 | if (program.remoteOnly) { 69 | return uploadRemote(program) 70 | } 71 | if (program.pinToIpfs) { 72 | return uploadIPFS(program) 73 | } 74 | 75 | return cleanIfNeeded(program) 76 | .then(() => { 77 | if (program.copyOnly) { 78 | console.log(` # Skipping Migration`) 79 | return Promise.resolve(undefined) 80 | } 81 | if (program.web3Adapters) { 82 | return contractDataOnNetwork(program.contractOutput, program.network) 83 | } 84 | return migrateTruffle(program) 85 | }) 86 | .then((contracts) => { 87 | if (contracts) { 88 | createWeb3Module(program, contracts) 89 | } 90 | return copyContractsLocal(program) 91 | }) 92 | .then(async () => { 93 | if (program.bucketName) { 94 | console.log(` # Uploading to AWS bucket`) 95 | await uploadRemote(program) 96 | } 97 | if (program.postSaveToIpfs) { 98 | console.log(` # Upoading to IPFS`) 99 | await uploadIPFS(program) 100 | } 101 | return Promise.resolve(undefined) 102 | }) 103 | } 104 | 105 | module.exports = { dapploy } 106 | -------------------------------------------------------------------------------- /src/deployTemplate.js: -------------------------------------------------------------------------------- 1 | const { execPromise } = require(`./execWrapper`) 2 | const shell = require(`shelljs`) 3 | const supported = [`ERC20`, `ERC721`, `RefundEscrow`] 4 | const fs = require(`fs`) 5 | 6 | const updateMigration = (distPath, whichContract) => { 7 | const migrationFile = `${distPath}/migrations/2_deploy_contracts.js` 8 | let parameters 9 | switch (whichContract) { 10 | case `ERC721`: { 11 | parameters = `[\`Fun Token\`, \`FT\`]` 12 | break 13 | } 14 | case `RefundEscrow`: { 15 | parameters = `[contractOwner]` 16 | break 17 | } 18 | case `CappedCrowdsale`: { 19 | // TODO add support for multiple contract instantiations 20 | parameters = `[[1000],[10000, contractOwner, contract0]]` 21 | break 22 | } 23 | default: { 24 | parameters = `[\`Fun Token\`, \`FT\`, 18, 100000000]` 25 | } 26 | } 27 | const requireString = `artifacts.require(\`${whichContract}Adapter.sol\`)` 28 | console.log(` $ Updating Migration file:`, migrationFile) 29 | shell.sed(`-i`, `CONTRACT_PARAMS`, parameters, migrationFile) 30 | shell.sed(`-i`, `CONTRACT_REQUIRE`, requireString, migrationFile) 31 | } 32 | 33 | const deployTemplate = async (distPath, whichContract) => { 34 | const templatePath = `${__dirname}/../templates/template-solidity` 35 | console.log(` $ Creating truffle project in ${distPath} from ${templatePath}`) 36 | console.log(` $ Copying ${templatePath} to ${distPath}`) 37 | 38 | // Copy to temp folder before moving to destination in case src and dest are the same 39 | // Is there a cleaner way? 40 | // cp -rfpiU... all just throw errors when src == dest, and paths strings 41 | 42 | await execPromise(`mkdir -p ${distPath}`) 43 | await execPromise(`cp -r ${templatePath}/* ${distPath}`) 44 | await execPromise(`cp ${templatePath}/.dapploy ${distPath}`) 45 | return execPromise( 46 | `cp ${distPath}/adapters/${whichContract}Adapter.sol ${distPath}/contracts/` 47 | ) 48 | } 49 | 50 | const getTemplateContract = (program) => { 51 | let whichContract = `ERC20` // default 52 | if (program.specifyContract && supported.includes(program.specifyContract)) { 53 | whichContract = program.specifyContract 54 | } else { 55 | console.log( 56 | `$ Unsupported contract type, ${ 57 | program.specifyContract 58 | } using default. The following contracts are supported: ${supported} ` 59 | ) 60 | } 61 | console.log(` $ Initializing project with ${whichContract} `) 62 | 63 | return whichContract 64 | } 65 | 66 | const checkDistributionPath = (distPath) => { 67 | const packagePath = `${distPath}/package.json` 68 | console.log(`checking path`, packagePath) 69 | if (fs.existsSync(packagePath)) { 70 | throw new Error( 71 | `Existing project found ${packagePath}, init in empty folder.` 72 | ) 73 | } 74 | return Promise.resolve(true) 75 | } 76 | 77 | const buildAndDeployTemplate = (program) => { 78 | const distPath = program.initPath || `./` 79 | const whichContract = getTemplateContract(program) 80 | return checkDistributionPath(distPath) 81 | .then(() => deployTemplate(distPath, whichContract)) 82 | .then(() => { 83 | updateMigration(distPath, whichContract) 84 | console.log(` $ Building template`) 85 | return execPromise(`cd ${distPath} && yarn`) 86 | }) 87 | } 88 | 89 | module.exports = { supported, buildAndDeployTemplate } 90 | -------------------------------------------------------------------------------- /src/execWrapper.js: -------------------------------------------------------------------------------- 1 | const { exec } = require(`child_process`) 2 | 3 | const logProcess = (process, parser) => { 4 | process.stdout.on(`data`, (data) => { 5 | console.log(data) 6 | if (parser) parser(data) 7 | }) 8 | } 9 | 10 | const execPromise = (command, options, parser) => new Promise((resolve, reject) => { 11 | logProcess( 12 | exec(command, options, (error, stdout, stderr) => { 13 | if (error) { 14 | return reject(error) 15 | } 16 | 17 | return resolve({ stdout, stderr }) 18 | }), 19 | parser 20 | ) 21 | }) 22 | 23 | module.exports = { 24 | logProcess, 25 | execPromise 26 | } 27 | -------------------------------------------------------------------------------- /src/fileReader.js: -------------------------------------------------------------------------------- 1 | const fs = require(`fs`) // from node.js 2 | const path = require(`path`) // from node.js 3 | 4 | const abiPath = program => path.join(program.projectDir, `build/contracts`) 5 | 6 | const abiFilePaths = program => readDir(abiPath(program)) 7 | 8 | // get of list of files from 'dir' directory 9 | const readDir = dir => new Promise((resolve, reject) => { 10 | const resolvePath = dir 11 | fs.readdir(resolvePath, (err, files) => { 12 | if (!files || files.length === 0) { 13 | console.log( 14 | `provided folder '${resolvePath}' is empty or does not exist.` 15 | ) 16 | console.log(`Make sure your project was compiled!`) 17 | return reject(err) 18 | } 19 | // get the full paths of the file 20 | const filePaths = files.map(fileName => path.join(resolvePath, fileName)) 21 | return resolve(filePaths) 22 | }) 23 | }) 24 | 25 | module.exports = { readDir, abiPath, abiFilePaths } 26 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /src/ipfsUploader.js: -------------------------------------------------------------------------------- 1 | const abiFilePaths = require(`./fileReader`).abiFilePaths 2 | const IPFS = require(`ipfs-http-client`) 3 | const fs = require(`fs`) 4 | const path = require(`path`) 5 | 6 | const ipfsParams = { 7 | host: `ipfs.xyo.network`, 8 | port: 5002, 9 | protocol: `https` 10 | } 11 | const ipfs = new IPFS(ipfsParams) 12 | 13 | const folder = `contracts` 14 | 15 | const pinToIPFS = hash => new Promise((resolve, reject) => { 16 | ipfs.pin.add(hash, (err, res) => { 17 | if (err) { 18 | reject(err) 19 | } else { 20 | console.log(` $ Contracts pinned on IPFS`) 21 | resolve(res) 22 | } 23 | }) 24 | }) 25 | 26 | const addToIPFS = data => new Promise((resolve, reject) => ipfs.add(data, { wrapWithDirectory: false }, (err, res) => { 27 | if (err) { 28 | console.log(`Got IPFS error:`, err) 29 | reject(err) 30 | } else { 31 | res.forEach((fileObj) => { 32 | if (!fileObj.path.includes(`Mock`)) { 33 | console.log(`${fileObj.path}: ${fileObj.hash}`) 34 | } 35 | }) 36 | } 37 | })) 38 | 39 | const uploadIPFS = program => abiFilePaths(program) 40 | .then((files) => { 41 | const promises = [] 42 | files.forEach((filePath) => { 43 | const content = fs.readFileSync(filePath) 44 | // const ipfsPath = `/${folder}/${path.basename(filePath)}` 45 | promises.push(addToIPFS({ path: path.basename(filePath), content })) 46 | }) 47 | 48 | return Promise.all(promises) 49 | }) 50 | .catch((err) => { 51 | console.log(err) 52 | }) 53 | 54 | module.exports = { uploadIPFS } 55 | -------------------------------------------------------------------------------- /src/truffleMigrator.js: -------------------------------------------------------------------------------- 1 | const { execPromise } = require(`./execWrapper`) 2 | const { readDir } = require(`./fileReader`) 3 | const glob = require(`glob`) 4 | const fs = require(`fs`) 5 | 6 | /* 7 | Wraps truffle migration based on configuration and returns a contracts dictionary 8 | @param projectDir the directory of the truffle project 9 | @param network the network (kovan, ropsten, development, mainnet) 10 | @param excludeContracts which contracts to leave out of the web3 instantiation module (optional) 11 | */ 12 | const migrateTruffle = ({ 13 | projectDir, 14 | network, 15 | excludeContracts, 16 | includeContracts 17 | }) => { 18 | console.log(` $ Migrating contracts at ${projectDir}`) 19 | 20 | if (!projectDir || !network) { 21 | throw new Error( 22 | `Missing projectDir or network, are you missing a .dapploy file?` 23 | ) 24 | } 25 | const command = `${__dirname}/../node_modules/.bin/truffle migrate --network ${network} --reset` 26 | console.log(` $ Using truffle command: ${command}`) 27 | 28 | const contracts = [] 29 | const parser = (data) => { 30 | const nameAddress = data.match(/[\s]*(.*): (0x.*)/) 31 | if (nameAddress) { 32 | if (!excludeContracts || !excludeContracts.includes(nameAddress[1])) { 33 | // if nothing excluded or is not in the excludes, add contract 34 | if (includeContracts) { 35 | if (includeContracts.includes(nameAddress[1])) { 36 | // included contracts exists, so add if in includeContracts 37 | contracts.push({ name: nameAddress[1], address: nameAddress[2] }) 38 | } 39 | } else { 40 | // include contracts not specified, so add by default 41 | contracts.push({ name: nameAddress[1], address: nameAddress[2] }) 42 | } 43 | } else if ( 44 | includeContracts && 45 | includeContracts.includes(nameAddress[1]) 46 | ) { 47 | // include overrides exclude 48 | Promise.reject( 49 | new Error(`Cannot include and exclude the same contract!`) 50 | ) 51 | } 52 | } 53 | } 54 | 55 | return execPromise(command, { cwd: projectDir }, parser).then(() => Promise.resolve(contracts)) 56 | } 57 | 58 | const getNetworkId = (network) => { 59 | let netId = 5777 60 | switch (network) { 61 | case `mainnet`: 62 | netId = 1 63 | break 64 | case `roptsten`: 65 | netId = 3 66 | break 67 | case `rinkeby`: 68 | netId = 4 69 | break 70 | case `kovan`: 71 | netId = 42 72 | break 73 | case `development`: 74 | netId = 5777 75 | break 76 | default: { 77 | netId = 5777 78 | } 79 | } 80 | return netId 81 | } 82 | 83 | const contractDataOnNetwork = (dir, network) => new Promise((resolve, reject) => { 84 | const jsonPath = `${dir}/*.json` 85 | 86 | glob(jsonPath, (er, files) => { 87 | if (er) { 88 | return reject(er) 89 | } 90 | if (!files || files.length === 0) { 91 | return reject( 92 | new Error( 93 | `Contract output path, '${jsonPath}' does not include json files.` 94 | ) 95 | ) 96 | } 97 | 98 | const contractDatas = files 99 | .map((file) => { 100 | const data = JSON.parse(fs.readFileSync(file)) 101 | return data && data.networks[getNetworkId(network)] 102 | ? { 103 | name: data.contractName, 104 | address: data.networks[getNetworkId(network)].address 105 | } 106 | : undefined 107 | }) 108 | .filter(n => n) 109 | // get the contracts that have a network matching the passed id 110 | return resolve(contractDatas) 111 | }) 112 | }) 113 | 114 | module.exports = { migrateTruffle, contractDataOnNetwork } 115 | -------------------------------------------------------------------------------- /src/web3ConfigExporter.js: -------------------------------------------------------------------------------- 1 | const shell = require(`shelljs`) 2 | const path = require(`path`) 3 | 4 | const getTempFile = type => `./temp999-${type}` // Copy the template to working file for us to modify 5 | const fs = require(`fs`) 6 | 7 | const portisConfigString = ({ portisApiKey, network, infuraApiKey }) => { 8 | if (portisApiKey) { 9 | const allowedNetworks = [ 10 | `mainnet`, 11 | `ropsten`, 12 | `kovan`, 13 | `rinkeby`, 14 | `sokol`, 15 | `core` 16 | ] 17 | if (allowedNetworks.includes(network)) { 18 | return `return new Web3(new PortisProvider({ 19 | apiKey: '${portisApiKey}', 20 | network: '${network}', 21 | }))` 22 | } 23 | if (infuraApiKey) { 24 | return `return new Web3(new PortisProvider({ 25 | apiKey: '${portisApiKey}', 26 | infuraApiKey: '${infuraApiKey}', 27 | network: '${network}', 28 | }))` 29 | } 30 | } 31 | // default to localhost if no metamask, use portis 32 | return `return new Web3(new PortisProvider({ 33 | providerNodeUrl: 'http://localhost:8545', 34 | }))` 35 | } 36 | 37 | const contractDeclarationString = (contracts) => { 38 | let returnString = `` 39 | contracts.forEach((contract) => { 40 | returnString += `export let ${contract.name}\n` 41 | }) 42 | 43 | return returnString 44 | } 45 | 46 | const contractInstantiationString = (program, contracts, type) => { 47 | let { contractOutput } = program 48 | const { projectDir } = program 49 | const web3AdapterPath = 50 | type === `client` ? program.web3ClientPath : program.web3ServerPath 51 | if (!contractOutput) { 52 | contractOutput = `${projectDir}/build/contracts` 53 | } 54 | const relativePath = path.relative( 55 | path.dirname(web3AdapterPath), 56 | contractOutput 57 | ) 58 | 59 | let returnString = `\n` 60 | 61 | contracts.forEach((contract) => { 62 | const address = `address${contract.name}` 63 | const json = `json${contract.name}` 64 | returnString += `\t\tconst ${json} = require('./${relativePath}/${ 65 | contract.name 66 | }.json')\n` 67 | returnString += `\t\tif (${json} && ${json}.networks[netId]) {\n` 68 | returnString += `\t\t\tconst ${address} = ${json}.networks[netId].address\n` 69 | returnString += `\t\t\t${contract.name} = new web3.eth.Contract(\n` 70 | returnString += `\t\t\t${json}.abi,\n` 71 | returnString += `\t\t\t${address})\n` 72 | returnString += `\t\t\tSmartContracts.push({name: '${ 73 | contract.name 74 | }', contract: ${contract.name}, address: ${address}})\n` 75 | returnString += `\t\t}\n` 76 | }) 77 | return returnString 78 | } 79 | 80 | const exportClientConfig = (program, contracts) => { 81 | const tempFile = getTempFile(`client`) 82 | copyTemplate(`client`) 83 | shell.sed( 84 | `-i`, 85 | `PORTIS_DECLARATION`, 86 | `import { PortisProvider } from 'portis'`, 87 | tempFile 88 | ) 89 | shell.sed(`-i`, `PORTIS_PROVIDER`, portisConfigString(program), tempFile) 90 | shell.sed( 91 | `-i`, 92 | `CONTRACT_DECLARATIONS`, 93 | contractDeclarationString(contracts), 94 | tempFile 95 | ) 96 | shell.sed( 97 | `-i`, 98 | `CONTRACT_INSTANTIATION`, 99 | contractInstantiationString(program, contracts, `client`), 100 | tempFile 101 | ) 102 | return moveTemplateTo(tempFile, program.web3ClientPath) 103 | } 104 | 105 | const copyTemplate = (type) => { 106 | const templateFile = `${__dirname}/../templates/template-web3-${type}.js` 107 | const tempFile = getTempFile(type) 108 | // console.log(`Copying`, templateFile, `to`, tempFile) 109 | shell.cp(templateFile, tempFile) 110 | } 111 | 112 | const exportServerConfig = (program, contracts) => { 113 | const tempFile = getTempFile(`server`) 114 | copyTemplate(`server`) 115 | 116 | shell.sed( 117 | `-i`, 118 | `CONTRACT_DECLARATIONS`, 119 | contractDeclarationString(contracts), 120 | tempFile 121 | ) 122 | shell.sed( 123 | `-i`, 124 | `CONTRACT_INSTANTIATION`, 125 | contractInstantiationString(program, contracts, `server`), 126 | tempFile 127 | ) 128 | 129 | return moveTemplateTo(tempFile, program.web3ServerPath) 130 | } 131 | 132 | const moveTemplateTo = (tempFile, web3Path) => { 133 | const outPath = path.dirname(web3Path) 134 | shell.mkdir(`-p`, outPath) 135 | if (!fs.existsSync(outPath)) { 136 | return Promise.reject(new Error(`Cannot create web3 adapter at ${outPath}`)) 137 | } 138 | console.log(` $ Moving template to`, web3Path) 139 | shell.mv(tempFile, web3Path) 140 | return Promise.resolve(true) 141 | } 142 | 143 | module.exports = { exportClientConfig, exportServerConfig } 144 | -------------------------------------------------------------------------------- /templates/template-solidity/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-2", "stage-3"] 3 | } 4 | -------------------------------------------------------------------------------- /templates/template-solidity/.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/node:8 6 | 7 | working_directory: ~/ 8 | 9 | steps: 10 | - checkout 11 | 12 | - run: 13 | name: 'Checking Versions' 14 | command: | 15 | node --version 16 | npm --version 17 | 18 | - run: 19 | name: 'Run ganache-cli, run truffle tests' 20 | command: | 21 | cd samples/sample-datavault-solidity 22 | node_modules/.bin/ganache-cli > /dev/null & 23 | sleep 5 24 | node_modules/.bin/truffle test 25 | 26 | # Download and cache dependencies 27 | - restore_cache: 28 | keys: 29 | - v1-dependencies-{{ checksum "package.json" }} 30 | # fallback to using the latest cache if no exact match is found 31 | - v1-dependencies- 32 | 33 | - run: 34 | name: 'Yarn project and samples' 35 | command: | 36 | yarn 37 | 38 | - save_cache: 39 | paths: 40 | - node_modules 41 | key: v1-dependencies-{{ checksum "package.json" }} 42 | 43 | # TODO run some more tests 44 | - store_test_results: 45 | path: reports 46 | -------------------------------------------------------------------------------- /templates/template-solidity/.dapploy: -------------------------------------------------------------------------------- 1 | # Where to find your truffle project, the network and where you want to copy locally 2 | [Truffle] 3 | projectDir=./ 4 | network=development 5 | contractOutput=./src/ABI 6 | 7 | # Include if you want to remote copy your contract ABIs to AWS backend 8 | # Setup your aws_access_key_id and aws_secret_access_key in ~/.aws/credentials 9 | # [AWS] 10 | # bucketName=layerone.smart-contracts 11 | # remotePath=ABI 12 | 13 | # Where to place generated web3 interface adapter on web3 client, 14 | # add any exclusions to keep from config 15 | [Web3] 16 | web3ClientPath=./src/web3Adapter-client.js 17 | web3ServerPath=./src/web3Adapter-server.js 18 | excludeContracts=Migrations 19 | 20 | # Include Portis section if you want Portis support in your web3 client 21 | # see portis.io 22 | # [Portis] 23 | # portisApiKey= 24 | # infuraApiKey= 25 | 26 | -------------------------------------------------------------------------------- /templates/template-solidity/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | # Logs 3 | logs 4 | *.log 5 | npm-debug.log* 6 | yarn-debug.log* 7 | yarn-error.log* 8 | 9 | # Runtime data 10 | pids 11 | *.pid 12 | *.seed 13 | *.pid.lock 14 | 15 | # Directory for instrumented libs generated by jscoverage/JSCover 16 | lib-cov 17 | 18 | # Coverage directory used by tools like istanbul 19 | coverage 20 | 21 | # nyc test coverage 22 | .nyc_output 23 | 24 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 25 | .grunt 26 | 27 | # Bower dependency directory (https://bower.io/) 28 | bower_components 29 | 30 | # node-waf configuration 31 | .lock-wscript 32 | 33 | # Compiled binary addons (https://nodejs.org/api/addons.html) 34 | build/Release 35 | 36 | # Dependency directories 37 | node_modules/ 38 | jspm_packages/ 39 | 40 | # TypeScript v1 declaration files 41 | typings/ 42 | 43 | # Optional npm cache directory 44 | .npm 45 | 46 | # Optional eslint cache 47 | .eslintcache 48 | 49 | # Optional REPL history 50 | .node_repl_history 51 | 52 | # Output of 'npm pack' 53 | *.tgz 54 | 55 | # Yarn Integrity file 56 | .yarn-integrity 57 | 58 | # dotenv environment variables file 59 | .env 60 | 61 | # next.js build output 62 | .next 63 | -------------------------------------------------------------------------------- /templates/template-solidity/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 XYO Network 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /templates/template-solidity/README.md: -------------------------------------------------------------------------------- 1 | A bare-bones configured template for a solidity project 2 | 3 | Example Dapp for use by Dapp Deployer. 4 | 5 | Use dapploy to build and deploy this contract to a local blockchain like Ganache from the project directory: 6 | ``` 7 | dapploy 8 | ``` 9 | -------------------------------------------------------------------------------- /templates/template-solidity/adapters/CappedCrowdsaleAdapter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./crowdsale/validation/CappedCrowdsale.sol"; 4 | 5 | /** 6 | * @title Capped Crowdsale contract adapter 7 | * @dev Basic implementation of Capped Crowdsale 8 | */ 9 | contract CappedCrowdsaleAdapter is CappedCrowdsale { 10 | constructor ( 11 | uint cap, 12 | uint256 rate, 13 | address wallet, 14 | ERC20 token 15 | ) 16 | CappedCrowdsale(cap) 17 | Crowdsale(rate, wallet, token) 18 | public { 19 | } 20 | } -------------------------------------------------------------------------------- /templates/template-solidity/adapters/ERC20Adapter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./token/ERC20/ERC20Mintable.sol"; 4 | 5 | /** 6 | * @title Basic ERC20 Adapter 7 | * @dev Basic implementation of ERC20 with initial supply 8 | */ 9 | contract ERC20Adapter is ERC20Mintable { 10 | string public _name; 11 | string public _symbol; 12 | uint public _decimals; 13 | 14 | constructor ( 15 | string memory name, 16 | string memory symbol, 17 | uint decimals, 18 | uint supply 19 | ) 20 | public 21 | { 22 | _name = name; 23 | _symbol = symbol; 24 | _decimals = decimals; 25 | mint(msg.sender, supply * (10**decimals)); 26 | } 27 | } -------------------------------------------------------------------------------- /templates/template-solidity/adapters/ERC721Adapter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./token/ERC721/ERC721Metadata.sol"; 4 | 5 | 6 | /** 7 | * @title A 721 Token Contract - A non-fungible token contract 8 | * @dev Basic version of ERC721Token. 9 | */ 10 | contract ERC721Adapter is ERC721Metadata { 11 | 12 | /* 13 | Construct a ERC721 with a name and symbol 14 | */ 15 | constructor 16 | ( 17 | string memory name, 18 | string memory symbol 19 | ) 20 | ERC721Metadata(name, symbol) 21 | public 22 | { 23 | // TODO Customize your 721 construction 24 | } 25 | 26 | /* 27 | Let's at least allow some minting of tokens! 28 | @param beneficiary - who should receive it 29 | @param tokenId - the id of the 721 token 30 | */ 31 | function mint 32 | ( 33 | address beneficiary, 34 | uint tokenId 35 | ) 36 | public 37 | { 38 | _mint(beneficiary, tokenId); 39 | } 40 | } -------------------------------------------------------------------------------- /templates/template-solidity/adapters/PaymentChannel.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./math/SafeMath.sol"; 4 | import "./cryptography/ECDSA.sol"; 5 | 6 | /** 7 | * @title PaymentChannel 8 | * @author Eric Olszewski 9 | * 10 | * @dev Ethereum payment channels allow for off-chain transactions with an on-chain 11 | * settlement. In this implementation, a party (sender) can open a channel with a 12 | * deposit, expiration, and recipient. The sender can then sign transactions off-chain 13 | * and send them to the recipient, who can submit one of these signed transactions to 14 | * chain to close and settle the channel. 15 | */ 16 | contract PaymentChannel { 17 | using SafeMath for uint256; 18 | using ECDSA for bytes32; 19 | 20 | //============================================================================ 21 | // EVENTS 22 | //============================================================================ 23 | 24 | event ChannelOpened(address indexed sender, address indexed recipient, uint expiration, uint256 deposit); 25 | event ChannelClosed(uint256 senderBalance, uint256 recipientBalance); 26 | 27 | // Creator of channel 28 | address public sender; 29 | // Recipient of channel 30 | address public recipient; 31 | // When sender can close the channel 32 | uint256 public expiration; 33 | 34 | //============================================================================ 35 | // PUBLIC FUNCTIONS 36 | //============================================================================ 37 | 38 | /** 39 | * @dev Constructor 40 | * @param _recipient address Address of the receiving party 41 | * @param _duration uint256 Time period past creation that defines expiration 42 | */ 43 | constructor(address _recipient, uint256 _duration) public payable { 44 | // sanity checks 45 | require(msg.value > 0); 46 | require(msg.sender != _recipient); 47 | 48 | sender = msg.sender; 49 | recipient = _recipient; 50 | expiration = now + _duration; 51 | 52 | emit ChannelOpened(sender, recipient, expiration, msg.value); 53 | } 54 | 55 | /** 56 | * @dev Close a channel with a signed message from the sender 57 | * @param _balance uint256 The balance agreed to by the sender in their signed message 58 | * @param _signedMessage bytes The signed hash of the balance by the sender 59 | */ 60 | function closeChannel(uint256 _balance, bytes memory _signedMessage) public { 61 | // only recipient can call closeChannel 62 | require(msg.sender == recipient); 63 | require(isValidSignature(_balance, _signedMessage)); 64 | 65 | // temp vars for calculating sender and recipient remittances 66 | uint256 balance = _balance; 67 | uint256 remainder = 0; 68 | 69 | // if _balance > address(this).balance, send address(this).balance to recipient 70 | if (_balance > address(this).balance) { 71 | balance = address(this).balance; 72 | } else { 73 | remainder = address(this).balance.sub(balance); 74 | } 75 | 76 | // remit payment to recipient 77 | recipient.transfer(balance); 78 | 79 | emit ChannelClosed(remainder, balance); 80 | 81 | // remit remainder to sender 82 | selfdestruct(sender); 83 | } 84 | 85 | /** 86 | * @dev Extend the expiration date of the channel 87 | * @param _expiration uint256 Updated expiration date 88 | */ 89 | function extendExpiration(uint256 _expiration) public { 90 | // only sender can call extendExpiration 91 | require(msg.sender == sender); 92 | require(_expiration > expiration); 93 | 94 | // update expiration 95 | expiration = _expiration; 96 | } 97 | 98 | /** 99 | * @dev Allows sender to claim channel balance if expired 100 | */ 101 | function claimTimeout() public { 102 | // must be beyond expiration date 103 | require(now >= expiration); 104 | 105 | // remit payment to sender 106 | selfdestruct(sender); 107 | } 108 | 109 | //============================================================================ 110 | // INTERNAL FUNCTIONS 111 | //============================================================================ 112 | 113 | /** 114 | * @dev Derive and verify sender address from signed message and message hash 115 | * @param _balance uint256 The balance agreed to by the sender in their signed message 116 | * @param _signedMessage bytes The signed hash of the balance by the sender 117 | */ 118 | function isValidSignature(uint256 _balance, bytes memory _signedMessage) 119 | internal 120 | view 121 | returns (bool) 122 | { 123 | bytes32 message = prefixed(keccak256(abi.encodePacked(address(this), _balance))); 124 | 125 | // check that the signature is from the payment sender 126 | return message.recover(_signedMessage) == sender; 127 | } 128 | 129 | /** 130 | * @dev Builds a prefixed hash to mimic the behavior of eth_sign 131 | * @param _hash bytes32 Message hash to be prefixed 132 | */ 133 | function prefixed(bytes32 _hash) 134 | internal 135 | pure 136 | returns (bytes32) 137 | { 138 | return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)); 139 | } 140 | } -------------------------------------------------------------------------------- /templates/template-solidity/adapters/RefundEscrowAdapter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./payment/escrow/RefundEscrow.sol"; 4 | 5 | /** 6 | * @title Basic Refund Escrow Contract Adapter 7 | * @dev Basic implementation of MintableToken with initial supply of 8 | */ 9 | contract RefundEscrowAdapter is RefundEscrow { 10 | 11 | constructor ( 12 | address escrowAccount 13 | ) 14 | RefundEscrow(escrowAccount) 15 | public { 16 | } 17 | } -------------------------------------------------------------------------------- /templates/template-solidity/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | constructor() public { 8 | owner = msg.sender; 9 | } 10 | 11 | modifier restricted() { 12 | if (msg.sender == owner) _; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) public restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/access/Roles.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title Roles 5 | * @dev Library for managing addresses assigned to a Role. 6 | */ 7 | library Roles { 8 | struct Role { 9 | mapping (address => bool) bearer; 10 | } 11 | 12 | /** 13 | * @dev give an account access to this role 14 | */ 15 | function add(Role storage role, address account) internal { 16 | require(account != address(0)); 17 | require(!has(role, account)); 18 | 19 | role.bearer[account] = true; 20 | } 21 | 22 | /** 23 | * @dev remove an account's access to this role 24 | */ 25 | function remove(Role storage role, address account) internal { 26 | require(account != address(0)); 27 | require(has(role, account)); 28 | 29 | role.bearer[account] = false; 30 | } 31 | 32 | /** 33 | * @dev check if an account has this role 34 | * @return bool 35 | */ 36 | function has(Role storage role, address account) internal view returns (bool) { 37 | require(account != address(0)); 38 | return role.bearer[account]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/access/roles/CapperRole.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../Roles.sol"; 4 | 5 | contract CapperRole { 6 | using Roles for Roles.Role; 7 | 8 | event CapperAdded(address indexed account); 9 | event CapperRemoved(address indexed account); 10 | 11 | Roles.Role private _cappers; 12 | 13 | constructor () internal { 14 | _addCapper(msg.sender); 15 | } 16 | 17 | modifier onlyCapper() { 18 | require(isCapper(msg.sender)); 19 | _; 20 | } 21 | 22 | function isCapper(address account) public view returns (bool) { 23 | return _cappers.has(account); 24 | } 25 | 26 | function addCapper(address account) public onlyCapper { 27 | _addCapper(account); 28 | } 29 | 30 | function renounceCapper() public { 31 | _removeCapper(msg.sender); 32 | } 33 | 34 | function _addCapper(address account) internal { 35 | _cappers.add(account); 36 | emit CapperAdded(account); 37 | } 38 | 39 | function _removeCapper(address account) internal { 40 | _cappers.remove(account); 41 | emit CapperRemoved(account); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/access/roles/MinterRole.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../Roles.sol"; 4 | 5 | contract MinterRole { 6 | using Roles for Roles.Role; 7 | 8 | event MinterAdded(address indexed account); 9 | event MinterRemoved(address indexed account); 10 | 11 | Roles.Role private _minters; 12 | 13 | constructor () internal { 14 | _addMinter(msg.sender); 15 | } 16 | 17 | modifier onlyMinter() { 18 | require(isMinter(msg.sender)); 19 | _; 20 | } 21 | 22 | function isMinter(address account) public view returns (bool) { 23 | return _minters.has(account); 24 | } 25 | 26 | function addMinter(address account) public onlyMinter { 27 | _addMinter(account); 28 | } 29 | 30 | function renounceMinter() public { 31 | _removeMinter(msg.sender); 32 | } 33 | 34 | function _addMinter(address account) internal { 35 | _minters.add(account); 36 | emit MinterAdded(account); 37 | } 38 | 39 | function _removeMinter(address account) internal { 40 | _minters.remove(account); 41 | emit MinterRemoved(account); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/access/roles/PauserRole.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../Roles.sol"; 4 | 5 | contract PauserRole { 6 | using Roles for Roles.Role; 7 | 8 | event PauserAdded(address indexed account); 9 | event PauserRemoved(address indexed account); 10 | 11 | Roles.Role private _pausers; 12 | 13 | constructor () internal { 14 | _addPauser(msg.sender); 15 | } 16 | 17 | modifier onlyPauser() { 18 | require(isPauser(msg.sender)); 19 | _; 20 | } 21 | 22 | function isPauser(address account) public view returns (bool) { 23 | return _pausers.has(account); 24 | } 25 | 26 | function addPauser(address account) public onlyPauser { 27 | _addPauser(account); 28 | } 29 | 30 | function renouncePauser() public { 31 | _removePauser(msg.sender); 32 | } 33 | 34 | function _addPauser(address account) internal { 35 | _pausers.add(account); 36 | emit PauserAdded(account); 37 | } 38 | 39 | function _removePauser(address account) internal { 40 | _pausers.remove(account); 41 | emit PauserRemoved(account); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/access/roles/SignerRole.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../Roles.sol"; 4 | 5 | contract SignerRole { 6 | using Roles for Roles.Role; 7 | 8 | event SignerAdded(address indexed account); 9 | event SignerRemoved(address indexed account); 10 | 11 | Roles.Role private _signers; 12 | 13 | constructor () internal { 14 | _addSigner(msg.sender); 15 | } 16 | 17 | modifier onlySigner() { 18 | require(isSigner(msg.sender)); 19 | _; 20 | } 21 | 22 | function isSigner(address account) public view returns (bool) { 23 | return _signers.has(account); 24 | } 25 | 26 | function addSigner(address account) public onlySigner { 27 | _addSigner(account); 28 | } 29 | 30 | function renounceSigner() public { 31 | _removeSigner(msg.sender); 32 | } 33 | 34 | function _addSigner(address account) internal { 35 | _signers.add(account); 36 | emit SignerAdded(account); 37 | } 38 | 39 | function _removeSigner(address account) internal { 40 | _signers.remove(account); 41 | emit SignerRemoved(account); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/access/roles/WhitelistAdminRole.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../Roles.sol"; 4 | 5 | /** 6 | * @title WhitelistAdminRole 7 | * @dev WhitelistAdmins are responsible for assigning and removing Whitelisted accounts. 8 | */ 9 | contract WhitelistAdminRole { 10 | using Roles for Roles.Role; 11 | 12 | event WhitelistAdminAdded(address indexed account); 13 | event WhitelistAdminRemoved(address indexed account); 14 | 15 | Roles.Role private _whitelistAdmins; 16 | 17 | constructor () internal { 18 | _addWhitelistAdmin(msg.sender); 19 | } 20 | 21 | modifier onlyWhitelistAdmin() { 22 | require(isWhitelistAdmin(msg.sender)); 23 | _; 24 | } 25 | 26 | function isWhitelistAdmin(address account) public view returns (bool) { 27 | return _whitelistAdmins.has(account); 28 | } 29 | 30 | function addWhitelistAdmin(address account) public onlyWhitelistAdmin { 31 | _addWhitelistAdmin(account); 32 | } 33 | 34 | function renounceWhitelistAdmin() public { 35 | _removeWhitelistAdmin(msg.sender); 36 | } 37 | 38 | function _addWhitelistAdmin(address account) internal { 39 | _whitelistAdmins.add(account); 40 | emit WhitelistAdminAdded(account); 41 | } 42 | 43 | function _removeWhitelistAdmin(address account) internal { 44 | _whitelistAdmins.remove(account); 45 | emit WhitelistAdminRemoved(account); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/access/roles/WhitelistedRole.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../Roles.sol"; 4 | import "./WhitelistAdminRole.sol"; 5 | 6 | /** 7 | * @title WhitelistedRole 8 | * @dev Whitelisted accounts have been approved by a WhitelistAdmin to perform certain actions (e.g. participate in a 9 | * crowdsale). This role is special in that the only accounts that can add it are WhitelistAdmins (who can also remove 10 | * it), and not Whitelisteds themselves. 11 | */ 12 | contract WhitelistedRole is WhitelistAdminRole { 13 | using Roles for Roles.Role; 14 | 15 | event WhitelistedAdded(address indexed account); 16 | event WhitelistedRemoved(address indexed account); 17 | 18 | Roles.Role private _whitelisteds; 19 | 20 | modifier onlyWhitelisted() { 21 | require(isWhitelisted(msg.sender)); 22 | _; 23 | } 24 | 25 | function isWhitelisted(address account) public view returns (bool) { 26 | return _whitelisteds.has(account); 27 | } 28 | 29 | function addWhitelisted(address account) public onlyWhitelistAdmin { 30 | _addWhitelisted(account); 31 | } 32 | 33 | function removeWhitelisted(address account) public onlyWhitelistAdmin { 34 | _removeWhitelisted(account); 35 | } 36 | 37 | function renounceWhitelisted() public { 38 | _removeWhitelisted(msg.sender); 39 | } 40 | 41 | function _addWhitelisted(address account) internal { 42 | _whitelisteds.add(account); 43 | emit WhitelistedAdded(account); 44 | } 45 | 46 | function _removeWhitelisted(address account) internal { 47 | _whitelisteds.remove(account); 48 | emit WhitelistedRemoved(account); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/cryptography/ECDSA.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title Elliptic curve signature operations 5 | * @dev Based on https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d 6 | * TODO Remove this library once solidity supports passing a signature to ecrecover. 7 | * See https://github.com/ethereum/solidity/issues/864 8 | */ 9 | 10 | library ECDSA { 11 | /** 12 | * @dev Recover signer address from a message by using their signature 13 | * @param hash bytes32 message, the hash is the signed message. What is recovered is the signer address. 14 | * @param signature bytes signature, the signature is generated using web3.eth.sign() 15 | */ 16 | function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { 17 | // Check the signature length 18 | if (signature.length != 65) { 19 | return (address(0)); 20 | } 21 | 22 | // Divide the signature in r, s and v variables 23 | bytes32 r; 24 | bytes32 s; 25 | uint8 v; 26 | 27 | // ecrecover takes the signature parameters, and the only way to get them 28 | // currently is to use assembly. 29 | // solhint-disable-next-line no-inline-assembly 30 | assembly { 31 | r := mload(add(signature, 0x20)) 32 | s := mload(add(signature, 0x40)) 33 | v := byte(0, mload(add(signature, 0x60))) 34 | } 35 | 36 | // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature 37 | // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines 38 | // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most 39 | // signatures from current libraries generate a unique signature with an s-value in the lower half order. 40 | // 41 | // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value 42 | // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or 43 | // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept 44 | // these malleable signatures as well. 45 | if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { 46 | return address(0); 47 | } 48 | 49 | if (v != 27 && v != 28) { 50 | return address(0); 51 | } 52 | 53 | // If the signature is valid (and not malleable), return the signer address 54 | return ecrecover(hash, v, r, s); 55 | } 56 | 57 | /** 58 | * toEthSignedMessageHash 59 | * @dev prefix a bytes32 value with "\x19Ethereum Signed Message:" 60 | * and hash the result 61 | */ 62 | function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { 63 | // 32 is the length in bytes of hash, 64 | // enforced by the type signature above 65 | return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/cryptography/MerkleProof.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title MerkleProof 5 | * @dev Merkle proof verification based on 6 | * https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol 7 | */ 8 | library MerkleProof { 9 | /** 10 | * @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves 11 | * and each pair of pre-images are sorted. 12 | * @param proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree 13 | * @param root Merkle root 14 | * @param leaf Leaf of Merkle tree 15 | */ 16 | function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { 17 | bytes32 computedHash = leaf; 18 | 19 | for (uint256 i = 0; i < proof.length; i++) { 20 | bytes32 proofElement = proof[i]; 21 | 22 | if (computedHash < proofElement) { 23 | // Hash(current computed hash + current element of the proof) 24 | computedHash = keccak256(abi.encodePacked(computedHash, proofElement)); 25 | } else { 26 | // Hash(current element of the proof + current computed hash) 27 | computedHash = keccak256(abi.encodePacked(proofElement, computedHash)); 28 | } 29 | } 30 | 31 | // Check if the computed hash (root) is equal to the provided root 32 | return computedHash == root; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/drafts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XYOracleNetwork-v1/tool-dapploy-nodejs/96f95e66cd4f497b4a3e91bd71e4d2057aaf0643/templates/template-solidity/contracts/drafts/.gitkeep -------------------------------------------------------------------------------- /templates/template-solidity/contracts/drafts/Counters.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../math/SafeMath.sol"; 4 | 5 | /** 6 | * @title Counters 7 | * @author Matt Condon (@shrugs) 8 | * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number 9 | * of elements in a mapping, issuing ERC721 ids, or counting request ids 10 | * 11 | * Include with `using Counters for Counters.Counter;` 12 | * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the SafeMath 13 | * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never 14 | * directly accessed. 15 | */ 16 | library Counters { 17 | using SafeMath for uint256; 18 | 19 | struct Counter { 20 | // This variable should never be directly accessed by users of the library: interactions must be restricted to 21 | // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add 22 | // this feature: see https://github.com/ethereum/solidity/issues/4637 23 | uint256 _value; // default: 0 24 | } 25 | 26 | function current(Counter storage counter) internal view returns (uint256) { 27 | return counter._value; 28 | } 29 | 30 | function increment(Counter storage counter) internal { 31 | counter._value += 1; 32 | } 33 | 34 | function decrement(Counter storage counter) internal { 35 | counter._value = counter._value.sub(1); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/drafts/ERC1046/ERC20Metadata.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../../token/ERC20/IERC20.sol"; 4 | 5 | /** 6 | * @title ERC-1047 Token Metadata 7 | * @dev See https://eips.ethereum.org/EIPS/eip-1046 8 | * @dev tokenURI must respond with a URI that implements https://eips.ethereum.org/EIPS/eip-1047 9 | */ 10 | contract ERC20Metadata { 11 | string private _tokenURI; 12 | 13 | constructor (string memory tokenURI_) public { 14 | _setTokenURI(tokenURI_); 15 | } 16 | 17 | function tokenURI() external view returns (string memory) { 18 | return _tokenURI; 19 | } 20 | 21 | function _setTokenURI(string memory tokenURI_) internal { 22 | _tokenURI = tokenURI_; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/drafts/ERC20Snapshot.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../math/SafeMath.sol"; 4 | import "../utils/Arrays.sol"; 5 | import "../drafts/Counters.sol"; 6 | import "../token/ERC20/ERC20.sol"; 7 | 8 | /** 9 | * @title ERC20 token with snapshots. 10 | * @dev Inspired by Jordi Baylina's MiniMeToken to record historical balances: 11 | * https://github.com/Giveth/minime/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol 12 | * When a snapshot is made, the balances and totalSupply at the time of the snapshot are recorded for later 13 | * access. 14 | * 15 | * To make a snapshot, call the `snapshot` function, which will emit the `Snapshot` event and return a snapshot id. 16 | * To get the total supply from a snapshot, call the function `totalSupplyAt` with the snapshot id. 17 | * To get the balance of an account from a snapshot, call the `balanceOfAt` function with the snapshot id and the 18 | * account address. 19 | * @author Validity Labs AG 20 | */ 21 | contract ERC20Snapshot is ERC20 { 22 | using SafeMath for uint256; 23 | using Arrays for uint256[]; 24 | using Counters for Counters.Counter; 25 | 26 | // Snapshotted values have arrays of ids and the value corresponding to that id. These could be an array of a 27 | // Snapshot struct, but that would impede usage of functions that work on an array. 28 | struct Snapshots { 29 | uint256[] ids; 30 | uint256[] values; 31 | } 32 | 33 | mapping (address => Snapshots) private _accountBalanceSnapshots; 34 | Snapshots private _totalSupplySnaphots; 35 | 36 | // Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid. 37 | Counters.Counter private _currentSnapshotId; 38 | 39 | event Snapshot(uint256 id); 40 | 41 | // Creates a new snapshot id. Balances are only stored in snapshots on demand: unless a snapshot was taken, a 42 | // balance change will not be recorded. This means the extra added cost of storing snapshotted balances is only paid 43 | // when required, but is also flexible enough that it allows for e.g. daily snapshots. 44 | function snapshot() public returns (uint256) { 45 | _currentSnapshotId.increment(); 46 | 47 | uint256 currentId = _currentSnapshotId.current(); 48 | emit Snapshot(currentId); 49 | return currentId; 50 | } 51 | 52 | function balanceOfAt(address account, uint256 snapshotId) public view returns (uint256) { 53 | (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]); 54 | 55 | return snapshotted ? value : balanceOf(account); 56 | } 57 | 58 | function totalSupplyAt(uint256 snapshotId) public view returns(uint256) { 59 | (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnaphots); 60 | 61 | return snapshotted ? value : totalSupply(); 62 | } 63 | 64 | // _transfer, _mint and _burn are the only functions where the balances are modified, so it is there that the 65 | // snapshots are updated. Note that the update happens _before_ the balance change, with the pre-modified value. 66 | // The same is true for the total supply and _mint and _burn. 67 | function _transfer(address from, address to, uint256 value) internal { 68 | _updateAccountSnapshot(from); 69 | _updateAccountSnapshot(to); 70 | 71 | super._transfer(from, to, value); 72 | } 73 | 74 | function _mint(address account, uint256 value) internal { 75 | _updateAccountSnapshot(account); 76 | _updateTotalSupplySnapshot(); 77 | 78 | super._mint(account, value); 79 | } 80 | 81 | function _burn(address account, uint256 value) internal { 82 | _updateAccountSnapshot(account); 83 | _updateTotalSupplySnapshot(); 84 | 85 | super._burn(account, value); 86 | } 87 | 88 | // When a valid snapshot is queried, there are three possibilities: 89 | // a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never 90 | // created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds 91 | // to this id is the current one. 92 | // b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the 93 | // requested id, and its value is the one to return. 94 | // c) More snapshots were created after the requested one, and the queried value was later modified. There will be 95 | // no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is 96 | // larger than the requested one. 97 | // 98 | // In summary, we need to find an element in an array, returning the index of the smallest value that is larger if 99 | // it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does 100 | // exactly this. 101 | function _valueAt(uint256 snapshotId, Snapshots storage snapshots) 102 | private view returns (bool, uint256) 103 | { 104 | require(snapshotId > 0); 105 | require(snapshotId <= _currentSnapshotId.current()); 106 | 107 | uint256 index = snapshots.ids.findUpperBound(snapshotId); 108 | 109 | if (index == snapshots.ids.length) { 110 | return (false, 0); 111 | } else { 112 | return (true, snapshots.values[index]); 113 | } 114 | } 115 | 116 | function _updateAccountSnapshot(address account) private { 117 | _updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account)); 118 | } 119 | 120 | function _updateTotalSupplySnapshot() private { 121 | _updateSnapshot(_totalSupplySnaphots, totalSupply()); 122 | } 123 | 124 | function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private { 125 | uint256 currentId = _currentSnapshotId.current(); 126 | if (_lastSnapshotId(snapshots.ids) < currentId) { 127 | snapshots.ids.push(currentId); 128 | snapshots.values.push(currentValue); 129 | } 130 | } 131 | 132 | function _lastSnapshotId(uint256[] storage ids) private view returns (uint256) { 133 | if (ids.length == 0) { 134 | return 0; 135 | } else { 136 | return ids[ids.length - 1]; 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/drafts/SignatureBouncer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../access/roles/SignerRole.sol"; 4 | import "../cryptography/ECDSA.sol"; 5 | 6 | /** 7 | * @title SignatureBouncer 8 | * @author PhABC, Shrugs and aflesher 9 | * @dev SignatureBouncer allows users to submit a signature as a permission to 10 | * do an action. 11 | * If the signature is from one of the authorized signer addresses, the 12 | * signature is valid. 13 | * Note that SignatureBouncer offers no protection against replay attacks, users 14 | * must add this themselves! 15 | * 16 | * Signer addresses can be individual servers signing grants or different 17 | * users within a decentralized club that have permission to invite other 18 | * members. This technique is useful for whitelists and airdrops; instead of 19 | * putting all valid addresses on-chain, simply sign a grant of the form 20 | * keccak256(abi.encodePacked(`:contractAddress` + `:granteeAddress`)) using a 21 | * valid signer address. 22 | * Then restrict access to your crowdsale/whitelist/airdrop using the 23 | * `onlyValidSignature` modifier (or implement your own using _isValidSignature). 24 | * In addition to `onlyValidSignature`, `onlyValidSignatureAndMethod` and 25 | * `onlyValidSignatureAndData` can be used to restrict access to only a given 26 | * method or a given method with given parameters respectively. 27 | * See the tests in SignatureBouncer.test.js for specific usage examples. 28 | * 29 | * @notice A method that uses the `onlyValidSignatureAndData` modifier must make 30 | * the _signature parameter the "last" parameter. You cannot sign a message that 31 | * has its own signature in it so the last 128 bytes of msg.data (which 32 | * represents the length of the _signature data and the _signature data itself) 33 | * is ignored when validating. Also non fixed sized parameters make constructing 34 | * the data in the signature much more complex. 35 | * See https://ethereum.stackexchange.com/a/50616 for more details. 36 | */ 37 | contract SignatureBouncer is SignerRole { 38 | using ECDSA for bytes32; 39 | 40 | // Function selectors are 4 bytes long, as documented in 41 | // https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector 42 | uint256 private constant _METHOD_ID_SIZE = 4; 43 | // Signature size is 65 bytes (tightly packed v + r + s), but gets padded to 96 bytes 44 | uint256 private constant _SIGNATURE_SIZE = 96; 45 | 46 | constructor () internal { 47 | // solhint-disable-previous-line no-empty-blocks 48 | } 49 | 50 | /** 51 | * @dev requires that a valid signature of a signer was provided 52 | */ 53 | modifier onlyValidSignature(bytes memory signature) { 54 | require(_isValidSignature(msg.sender, signature)); 55 | _; 56 | } 57 | 58 | /** 59 | * @dev requires that a valid signature with a specified method of a signer was provided 60 | */ 61 | modifier onlyValidSignatureAndMethod(bytes memory signature) { 62 | require(_isValidSignatureAndMethod(msg.sender, signature)); 63 | _; 64 | } 65 | 66 | /** 67 | * @dev requires that a valid signature with a specified method and params of a signer was provided 68 | */ 69 | modifier onlyValidSignatureAndData(bytes memory signature) { 70 | require(_isValidSignatureAndData(msg.sender, signature)); 71 | _; 72 | } 73 | 74 | /** 75 | * @dev is the signature of `this + account` from a signer? 76 | * @return bool 77 | */ 78 | function _isValidSignature(address account, bytes memory signature) internal view returns (bool) { 79 | return _isValidDataHash(keccak256(abi.encodePacked(address(this), account)), signature); 80 | } 81 | 82 | /** 83 | * @dev is the signature of `this + account + methodId` from a signer? 84 | * @return bool 85 | */ 86 | function _isValidSignatureAndMethod(address account, bytes memory signature) internal view returns (bool) { 87 | bytes memory data = new bytes(_METHOD_ID_SIZE); 88 | for (uint i = 0; i < data.length; i++) { 89 | data[i] = msg.data[i]; 90 | } 91 | return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature); 92 | } 93 | 94 | /** 95 | * @dev is the signature of `this + account + methodId + params(s)` from a signer? 96 | * @notice the signature parameter of the method being validated must be the "last" parameter 97 | * @return bool 98 | */ 99 | function _isValidSignatureAndData(address account, bytes memory signature) internal view returns (bool) { 100 | require(msg.data.length > _SIGNATURE_SIZE); 101 | 102 | bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE); 103 | for (uint i = 0; i < data.length; i++) { 104 | data[i] = msg.data[i]; 105 | } 106 | 107 | return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature); 108 | } 109 | 110 | /** 111 | * @dev internal function to convert a hash to an eth signed message 112 | * and then recover the signature and check it against the signer role 113 | * @return bool 114 | */ 115 | function _isValidDataHash(bytes32 hash, bytes memory signature) internal view returns (bool) { 116 | address signer = hash.toEthSignedMessageHash().recover(signature); 117 | 118 | return signer != address(0) && isSigner(signer); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/drafts/SignedSafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title SignedSafeMath 5 | * @dev Signed math operations with safety checks that revert on error 6 | */ 7 | library SignedSafeMath { 8 | int256 constant private INT256_MIN = -2**255; 9 | 10 | /** 11 | * @dev Multiplies two signed integers, reverts on overflow. 12 | */ 13 | function mul(int256 a, int256 b) internal pure returns (int256) { 14 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 15 | // benefit is lost if 'b' is also tested. 16 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 17 | if (a == 0) { 18 | return 0; 19 | } 20 | 21 | require(!(a == -1 && b == INT256_MIN)); // This is the only case of overflow not detected by the check below 22 | 23 | int256 c = a * b; 24 | require(c / a == b); 25 | 26 | return c; 27 | } 28 | 29 | /** 30 | * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero. 31 | */ 32 | function div(int256 a, int256 b) internal pure returns (int256) { 33 | require(b != 0); // Solidity only automatically asserts when dividing by 0 34 | require(!(b == -1 && a == INT256_MIN)); // This is the only case of overflow 35 | 36 | int256 c = a / b; 37 | 38 | return c; 39 | } 40 | 41 | /** 42 | * @dev Subtracts two signed integers, reverts on overflow. 43 | */ 44 | function sub(int256 a, int256 b) internal pure returns (int256) { 45 | int256 c = a - b; 46 | require((b >= 0 && c <= a) || (b < 0 && c > a)); 47 | 48 | return c; 49 | } 50 | 51 | /** 52 | * @dev Adds two signed integers, reverts on overflow. 53 | */ 54 | function add(int256 a, int256 b) internal pure returns (int256) { 55 | int256 c = a + b; 56 | require((b >= 0 && c >= a) || (b < 0 && c < a)); 57 | 58 | return c; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/introspection/ERC165.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./IERC165.sol"; 4 | 5 | /** 6 | * @title ERC165 7 | * @author Matt Condon (@shrugs) 8 | * @dev Implements ERC165 using a lookup table. 9 | */ 10 | contract ERC165 is IERC165 { 11 | bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; 12 | /* 13 | * 0x01ffc9a7 === 14 | * bytes4(keccak256('supportsInterface(bytes4)')) 15 | */ 16 | 17 | /** 18 | * @dev a mapping of interface id to whether or not it's supported 19 | */ 20 | mapping(bytes4 => bool) private _supportedInterfaces; 21 | 22 | /** 23 | * @dev A contract implementing SupportsInterfaceWithLookup 24 | * implement ERC165 itself 25 | */ 26 | constructor () internal { 27 | _registerInterface(_INTERFACE_ID_ERC165); 28 | } 29 | 30 | /** 31 | * @dev implement supportsInterface(bytes4) using a lookup table 32 | */ 33 | function supportsInterface(bytes4 interfaceId) external view returns (bool) { 34 | return _supportedInterfaces[interfaceId]; 35 | } 36 | 37 | /** 38 | * @dev internal method for registering an interface 39 | */ 40 | function _registerInterface(bytes4 interfaceId) internal { 41 | require(interfaceId != 0xffffffff); 42 | _supportedInterfaces[interfaceId] = true; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/introspection/ERC165Checker.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title ERC165Checker 5 | * @dev Use `using ERC165Checker for address`; to include this library 6 | * https://eips.ethereum.org/EIPS/eip-165 7 | */ 8 | library ERC165Checker { 9 | // As per the EIP-165 spec, no interface should ever match 0xffffffff 10 | bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff; 11 | 12 | bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; 13 | /* 14 | * 0x01ffc9a7 === 15 | * bytes4(keccak256('supportsInterface(bytes4)')) 16 | */ 17 | 18 | /** 19 | * @notice Query if a contract supports ERC165 20 | * @param account The address of the contract to query for support of ERC165 21 | * @return true if the contract at account implements ERC165 22 | */ 23 | function _supportsERC165(address account) internal view returns (bool) { 24 | // Any contract that implements ERC165 must explicitly indicate support of 25 | // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid 26 | return _supportsERC165Interface(account, _INTERFACE_ID_ERC165) && 27 | !_supportsERC165Interface(account, _INTERFACE_ID_INVALID); 28 | } 29 | 30 | /** 31 | * @notice Query if a contract implements an interface, also checks support of ERC165 32 | * @param account The address of the contract to query for support of an interface 33 | * @param interfaceId The interface identifier, as specified in ERC-165 34 | * @return true if the contract at account indicates support of the interface with 35 | * identifier interfaceId, false otherwise 36 | * @dev Interface identification is specified in ERC-165. 37 | */ 38 | function _supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) { 39 | // query support of both ERC165 as per the spec and support of _interfaceId 40 | return _supportsERC165(account) && 41 | _supportsERC165Interface(account, interfaceId); 42 | } 43 | 44 | /** 45 | * @notice Query if a contract implements interfaces, also checks support of ERC165 46 | * @param account The address of the contract to query for support of an interface 47 | * @param interfaceIds A list of interface identifiers, as specified in ERC-165 48 | * @return true if the contract at account indicates support all interfaces in the 49 | * interfaceIds list, false otherwise 50 | * @dev Interface identification is specified in ERC-165. 51 | */ 52 | function _supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) { 53 | // query support of ERC165 itself 54 | if (!_supportsERC165(account)) { 55 | return false; 56 | } 57 | 58 | // query support of each interface in _interfaceIds 59 | for (uint256 i = 0; i < interfaceIds.length; i++) { 60 | if (!_supportsERC165Interface(account, interfaceIds[i])) { 61 | return false; 62 | } 63 | } 64 | 65 | // all interfaces supported 66 | return true; 67 | } 68 | 69 | /** 70 | * @notice Query if a contract implements an interface, does not check ERC165 support 71 | * @param account The address of the contract to query for support of an interface 72 | * @param interfaceId The interface identifier, as specified in ERC-165 73 | * @return true if the contract at account indicates support of the interface with 74 | * identifier interfaceId, false otherwise 75 | * @dev Assumes that account contains a contract that supports ERC165, otherwise 76 | * the behavior of this method is undefined. This precondition can be checked 77 | * with the `supportsERC165` method in this library. 78 | * Interface identification is specified in ERC-165. 79 | */ 80 | function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) { 81 | // success determines whether the staticcall succeeded and result determines 82 | // whether the contract at account indicates support of _interfaceId 83 | (bool success, bool result) = _callERC165SupportsInterface(account, interfaceId); 84 | 85 | return (success && result); 86 | } 87 | 88 | /** 89 | * @notice Calls the function with selector 0x01ffc9a7 (ERC165) and suppresses throw 90 | * @param account The address of the contract to query for support of an interface 91 | * @param interfaceId The interface identifier, as specified in ERC-165 92 | * @return success true if the STATICCALL succeeded, false otherwise 93 | * @return result true if the STATICCALL succeeded and the contract at account 94 | * indicates support of the interface with identifier interfaceId, false otherwise 95 | */ 96 | function _callERC165SupportsInterface(address account, bytes4 interfaceId) 97 | private 98 | view 99 | returns (bool success, bool result) 100 | { 101 | bytes memory encodedParams = abi.encodeWithSelector(_INTERFACE_ID_ERC165, interfaceId); 102 | 103 | // solhint-disable-next-line no-inline-assembly 104 | assembly { 105 | let encodedParams_data := add(0x20, encodedParams) 106 | let encodedParams_size := mload(encodedParams) 107 | 108 | let output := mload(0x40) // Find empty storage location using "free memory pointer" 109 | mstore(output, 0x0) 110 | 111 | success := staticcall( 112 | 30000, // 30k gas 113 | account, // To addr 114 | encodedParams_data, 115 | encodedParams_size, 116 | output, 117 | 0x20 // Outputs are 32 bytes long 118 | ) 119 | 120 | result := mload(output) // Load the result 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/introspection/IERC165.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title IERC165 5 | * @dev https://eips.ethereum.org/EIPS/eip-165 6 | */ 7 | interface IERC165 { 8 | /** 9 | * @notice Query if a contract implements an interface 10 | * @param interfaceId The interface identifier, as specified in ERC-165 11 | * @dev Interface identification is specified in ERC-165. This function 12 | * uses less than 30,000 gas. 13 | */ 14 | function supportsInterface(bytes4 interfaceId) external view returns (bool); 15 | } 16 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/lifecycle/Pausable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../access/roles/PauserRole.sol"; 4 | 5 | /** 6 | * @title Pausable 7 | * @dev Base contract which allows children to implement an emergency stop mechanism. 8 | */ 9 | contract Pausable is PauserRole { 10 | event Paused(address account); 11 | event Unpaused(address account); 12 | 13 | bool private _paused; 14 | 15 | constructor () internal { 16 | _paused = false; 17 | } 18 | 19 | /** 20 | * @return true if the contract is paused, false otherwise. 21 | */ 22 | function paused() public view returns (bool) { 23 | return _paused; 24 | } 25 | 26 | /** 27 | * @dev Modifier to make a function callable only when the contract is not paused. 28 | */ 29 | modifier whenNotPaused() { 30 | require(!_paused); 31 | _; 32 | } 33 | 34 | /** 35 | * @dev Modifier to make a function callable only when the contract is paused. 36 | */ 37 | modifier whenPaused() { 38 | require(_paused); 39 | _; 40 | } 41 | 42 | /** 43 | * @dev called by the owner to pause, triggers stopped state 44 | */ 45 | function pause() public onlyPauser whenNotPaused { 46 | _paused = true; 47 | emit Paused(msg.sender); 48 | } 49 | 50 | /** 51 | * @dev called by the owner to unpause, returns to normal state 52 | */ 53 | function unpause() public onlyPauser whenPaused { 54 | _paused = false; 55 | emit Unpaused(msg.sender); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/math/Math.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title Math 5 | * @dev Assorted math operations 6 | */ 7 | library Math { 8 | /** 9 | * @dev Returns the largest of two numbers. 10 | */ 11 | function max(uint256 a, uint256 b) internal pure returns (uint256) { 12 | return a >= b ? a : b; 13 | } 14 | 15 | /** 16 | * @dev Returns the smallest of two numbers. 17 | */ 18 | function min(uint256 a, uint256 b) internal pure returns (uint256) { 19 | return a < b ? a : b; 20 | } 21 | 22 | /** 23 | * @dev Calculates the average of two numbers. Since these are integers, 24 | * averages of an even and odd number cannot be represented, and will be 25 | * rounded down. 26 | */ 27 | function average(uint256 a, uint256 b) internal pure returns (uint256) { 28 | // (a + b) / 2 can overflow, so we distribute 29 | return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/math/SafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title SafeMath 5 | * @dev Unsigned math operations with safety checks that revert on error 6 | */ 7 | library SafeMath { 8 | /** 9 | * @dev Multiplies two unsigned integers, reverts on overflow. 10 | */ 11 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 12 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 13 | // benefit is lost if 'b' is also tested. 14 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 15 | if (a == 0) { 16 | return 0; 17 | } 18 | 19 | uint256 c = a * b; 20 | require(c / a == b); 21 | 22 | return c; 23 | } 24 | 25 | /** 26 | * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. 27 | */ 28 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 29 | // Solidity only automatically asserts when dividing by 0 30 | require(b > 0); 31 | uint256 c = a / b; 32 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 33 | 34 | return c; 35 | } 36 | 37 | /** 38 | * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). 39 | */ 40 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 41 | require(b <= a); 42 | uint256 c = a - b; 43 | 44 | return c; 45 | } 46 | 47 | /** 48 | * @dev Adds two unsigned integers, reverts on overflow. 49 | */ 50 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 51 | uint256 c = a + b; 52 | require(c >= a); 53 | 54 | return c; 55 | } 56 | 57 | /** 58 | * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), 59 | * reverts when dividing by zero. 60 | */ 61 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 62 | require(b != 0); 63 | return a % b; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/ownership/Ownable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title Ownable 5 | * @dev The Ownable contract has an owner address, and provides basic authorization control 6 | * functions, this simplifies the implementation of "user permissions". 7 | */ 8 | contract Ownable { 9 | address private _owner; 10 | 11 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 12 | 13 | /** 14 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 15 | * account. 16 | */ 17 | constructor () internal { 18 | _owner = msg.sender; 19 | emit OwnershipTransferred(address(0), _owner); 20 | } 21 | 22 | /** 23 | * @return the address of the owner. 24 | */ 25 | function owner() public view returns (address) { 26 | return _owner; 27 | } 28 | 29 | /** 30 | * @dev Throws if called by any account other than the owner. 31 | */ 32 | modifier onlyOwner() { 33 | require(isOwner()); 34 | _; 35 | } 36 | 37 | /** 38 | * @return true if `msg.sender` is the owner of the contract. 39 | */ 40 | function isOwner() public view returns (bool) { 41 | return msg.sender == _owner; 42 | } 43 | 44 | /** 45 | * @dev Allows the current owner to relinquish control of the contract. 46 | * It will not be possible to call the functions with the `onlyOwner` 47 | * modifier anymore. 48 | * @notice Renouncing ownership will leave the contract without an owner, 49 | * thereby removing any functionality that is only available to the owner. 50 | */ 51 | function renounceOwnership() public onlyOwner { 52 | emit OwnershipTransferred(_owner, address(0)); 53 | _owner = address(0); 54 | } 55 | 56 | /** 57 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 58 | * @param newOwner The address to transfer ownership to. 59 | */ 60 | function transferOwnership(address newOwner) public onlyOwner { 61 | _transferOwnership(newOwner); 62 | } 63 | 64 | /** 65 | * @dev Transfers control of the contract to a newOwner. 66 | * @param newOwner The address to transfer ownership to. 67 | */ 68 | function _transferOwnership(address newOwner) internal { 69 | require(newOwner != address(0)); 70 | emit OwnershipTransferred(_owner, newOwner); 71 | _owner = newOwner; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/ownership/Secondary.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title Secondary 5 | * @dev A Secondary contract can only be used by its primary account (the one that created it) 6 | */ 7 | contract Secondary { 8 | address private _primary; 9 | 10 | event PrimaryTransferred( 11 | address recipient 12 | ); 13 | 14 | /** 15 | * @dev Sets the primary account to the one that is creating the Secondary contract. 16 | */ 17 | constructor () internal { 18 | _primary = msg.sender; 19 | emit PrimaryTransferred(_primary); 20 | } 21 | 22 | /** 23 | * @dev Reverts if called from any account other than the primary. 24 | */ 25 | modifier onlyPrimary() { 26 | require(msg.sender == _primary); 27 | _; 28 | } 29 | 30 | /** 31 | * @return the address of the primary. 32 | */ 33 | function primary() public view returns (address) { 34 | return _primary; 35 | } 36 | 37 | /** 38 | * @dev Transfers contract to a new primary. 39 | * @param recipient The address of new primary. 40 | */ 41 | function transferPrimary(address recipient) public onlyPrimary { 42 | require(recipient != address(0)); 43 | _primary = recipient; 44 | emit PrimaryTransferred(_primary); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC20/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./IERC20.sol"; 4 | import "../../math/SafeMath.sol"; 5 | 6 | /** 7 | * @title Standard ERC20 token 8 | * 9 | * @dev Implementation of the basic standard token. 10 | * https://eips.ethereum.org/EIPS/eip-20 11 | * Originally based on code by FirstBlood: 12 | * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 13 | * 14 | * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for 15 | * all accounts just by listening to said events. Note that this isn't required by the specification, and other 16 | * compliant implementations may not do it. 17 | */ 18 | contract ERC20 is IERC20 { 19 | using SafeMath for uint256; 20 | 21 | mapping (address => uint256) private _balances; 22 | 23 | mapping (address => mapping (address => uint256)) private _allowed; 24 | 25 | uint256 private _totalSupply; 26 | 27 | /** 28 | * @dev Total number of tokens in existence 29 | */ 30 | function totalSupply() public view returns (uint256) { 31 | return _totalSupply; 32 | } 33 | 34 | /** 35 | * @dev Gets the balance of the specified address. 36 | * @param owner The address to query the balance of. 37 | * @return A uint256 representing the amount owned by the passed address. 38 | */ 39 | function balanceOf(address owner) public view returns (uint256) { 40 | return _balances[owner]; 41 | } 42 | 43 | /** 44 | * @dev Function to check the amount of tokens that an owner allowed to a spender. 45 | * @param owner address The address which owns the funds. 46 | * @param spender address The address which will spend the funds. 47 | * @return A uint256 specifying the amount of tokens still available for the spender. 48 | */ 49 | function allowance(address owner, address spender) public view returns (uint256) { 50 | return _allowed[owner][spender]; 51 | } 52 | 53 | /** 54 | * @dev Transfer token to a specified address 55 | * @param to The address to transfer to. 56 | * @param value The amount to be transferred. 57 | */ 58 | function transfer(address to, uint256 value) public returns (bool) { 59 | _transfer(msg.sender, to, value); 60 | return true; 61 | } 62 | 63 | /** 64 | * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 65 | * Beware that changing an allowance with this method brings the risk that someone may use both the old 66 | * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 67 | * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 68 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 69 | * @param spender The address which will spend the funds. 70 | * @param value The amount of tokens to be spent. 71 | */ 72 | function approve(address spender, uint256 value) public returns (bool) { 73 | _approve(msg.sender, spender, value); 74 | return true; 75 | } 76 | 77 | /** 78 | * @dev Transfer tokens from one address to another. 79 | * Note that while this function emits an Approval event, this is not required as per the specification, 80 | * and other compliant implementations may not emit the event. 81 | * @param from address The address which you want to send tokens from 82 | * @param to address The address which you want to transfer to 83 | * @param value uint256 the amount of tokens to be transferred 84 | */ 85 | function transferFrom(address from, address to, uint256 value) public returns (bool) { 86 | _transfer(from, to, value); 87 | _approve(from, msg.sender, _allowed[from][msg.sender].sub(value)); 88 | return true; 89 | } 90 | 91 | /** 92 | * @dev Increase the amount of tokens that an owner allowed to a spender. 93 | * approve should be called when _allowed[msg.sender][spender] == 0. To increment 94 | * allowed value is better to use this function to avoid 2 calls (and wait until 95 | * the first transaction is mined) 96 | * From MonolithDAO Token.sol 97 | * Emits an Approval event. 98 | * @param spender The address which will spend the funds. 99 | * @param addedValue The amount of tokens to increase the allowance by. 100 | */ 101 | function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { 102 | _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue)); 103 | return true; 104 | } 105 | 106 | /** 107 | * @dev Decrease the amount of tokens that an owner allowed to a spender. 108 | * approve should be called when _allowed[msg.sender][spender] == 0. To decrement 109 | * allowed value is better to use this function to avoid 2 calls (and wait until 110 | * the first transaction is mined) 111 | * From MonolithDAO Token.sol 112 | * Emits an Approval event. 113 | * @param spender The address which will spend the funds. 114 | * @param subtractedValue The amount of tokens to decrease the allowance by. 115 | */ 116 | function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { 117 | _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue)); 118 | return true; 119 | } 120 | 121 | /** 122 | * @dev Transfer token for a specified addresses 123 | * @param from The address to transfer from. 124 | * @param to The address to transfer to. 125 | * @param value The amount to be transferred. 126 | */ 127 | function _transfer(address from, address to, uint256 value) internal { 128 | require(to != address(0)); 129 | 130 | _balances[from] = _balances[from].sub(value); 131 | _balances[to] = _balances[to].add(value); 132 | emit Transfer(from, to, value); 133 | } 134 | 135 | /** 136 | * @dev Internal function that mints an amount of the token and assigns it to 137 | * an account. This encapsulates the modification of balances such that the 138 | * proper events are emitted. 139 | * @param account The account that will receive the created tokens. 140 | * @param value The amount that will be created. 141 | */ 142 | function _mint(address account, uint256 value) internal { 143 | require(account != address(0)); 144 | 145 | _totalSupply = _totalSupply.add(value); 146 | _balances[account] = _balances[account].add(value); 147 | emit Transfer(address(0), account, value); 148 | } 149 | 150 | /** 151 | * @dev Internal function that burns an amount of the token of a given 152 | * account. 153 | * @param account The account whose tokens will be burnt. 154 | * @param value The amount that will be burnt. 155 | */ 156 | function _burn(address account, uint256 value) internal { 157 | require(account != address(0)); 158 | 159 | _totalSupply = _totalSupply.sub(value); 160 | _balances[account] = _balances[account].sub(value); 161 | emit Transfer(account, address(0), value); 162 | } 163 | 164 | /** 165 | * @dev Approve an address to spend another addresses' tokens. 166 | * @param owner The address that owns the tokens. 167 | * @param spender The address that will spend the tokens. 168 | * @param value The number of tokens that can be spent. 169 | */ 170 | function _approve(address owner, address spender, uint256 value) internal { 171 | require(spender != address(0)); 172 | require(owner != address(0)); 173 | 174 | _allowed[owner][spender] = value; 175 | emit Approval(owner, spender, value); 176 | } 177 | 178 | /** 179 | * @dev Internal function that burns an amount of the token of a given 180 | * account, deducting from the sender's allowance for said account. Uses the 181 | * internal burn function. 182 | * Emits an Approval event (reflecting the reduced allowance). 183 | * @param account The account whose tokens will be burnt. 184 | * @param value The amount that will be burnt. 185 | */ 186 | function _burnFrom(address account, uint256 value) internal { 187 | _burn(account, value); 188 | _approve(account, msg.sender, _allowed[account][msg.sender].sub(value)); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC20/ERC20Burnable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./ERC20.sol"; 4 | 5 | /** 6 | * @title Burnable Token 7 | * @dev Token that can be irreversibly burned (destroyed). 8 | */ 9 | contract ERC20Burnable is ERC20 { 10 | /** 11 | * @dev Burns a specific amount of tokens. 12 | * @param value The amount of token to be burned. 13 | */ 14 | function burn(uint256 value) public { 15 | _burn(msg.sender, value); 16 | } 17 | 18 | /** 19 | * @dev Burns a specific amount of tokens from the target address and decrements allowance 20 | * @param from address The account whose tokens will be burned. 21 | * @param value uint256 The amount of token to be burned. 22 | */ 23 | function burnFrom(address from, uint256 value) public { 24 | _burnFrom(from, value); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC20/ERC20Capped.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./ERC20Mintable.sol"; 4 | 5 | /** 6 | * @title Capped token 7 | * @dev Mintable token with a token cap. 8 | */ 9 | contract ERC20Capped is ERC20Mintable { 10 | uint256 private _cap; 11 | 12 | constructor (uint256 cap) public { 13 | require(cap > 0); 14 | _cap = cap; 15 | } 16 | 17 | /** 18 | * @return the cap for the token minting. 19 | */ 20 | function cap() public view returns (uint256) { 21 | return _cap; 22 | } 23 | 24 | function _mint(address account, uint256 value) internal { 25 | require(totalSupply().add(value) <= _cap); 26 | super._mint(account, value); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC20/ERC20Detailed.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./IERC20.sol"; 4 | 5 | /** 6 | * @title ERC20Detailed token 7 | * @dev The decimals are only for visualization purposes. 8 | * All the operations are done using the smallest and indivisible token unit, 9 | * just as on Ethereum all the operations are done in wei. 10 | */ 11 | contract ERC20Detailed is IERC20 { 12 | string private _name; 13 | string private _symbol; 14 | uint8 private _decimals; 15 | 16 | constructor (string memory name, string memory symbol, uint8 decimals) public { 17 | _name = name; 18 | _symbol = symbol; 19 | _decimals = decimals; 20 | } 21 | 22 | /** 23 | * @return the name of the token. 24 | */ 25 | function name() public view returns (string memory) { 26 | return _name; 27 | } 28 | 29 | /** 30 | * @return the symbol of the token. 31 | */ 32 | function symbol() public view returns (string memory) { 33 | return _symbol; 34 | } 35 | 36 | /** 37 | * @return the number of decimals of the token. 38 | */ 39 | function decimals() public view returns (uint8) { 40 | return _decimals; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC20/ERC20Mintable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./ERC20.sol"; 4 | import "../../access/roles/MinterRole.sol"; 5 | 6 | /** 7 | * @title ERC20Mintable 8 | * @dev ERC20 minting logic 9 | */ 10 | contract ERC20Mintable is ERC20, MinterRole { 11 | /** 12 | * @dev Function to mint tokens 13 | * @param to The address that will receive the minted tokens. 14 | * @param value The amount of tokens to mint. 15 | * @return A boolean that indicates if the operation was successful. 16 | */ 17 | function mint(address to, uint256 value) public onlyMinter returns (bool) { 18 | _mint(to, value); 19 | return true; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC20/ERC20Pausable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./ERC20.sol"; 4 | import "../../lifecycle/Pausable.sol"; 5 | 6 | /** 7 | * @title Pausable token 8 | * @dev ERC20 modified with pausable transfers. 9 | */ 10 | contract ERC20Pausable is ERC20, Pausable { 11 | function transfer(address to, uint256 value) public whenNotPaused returns (bool) { 12 | return super.transfer(to, value); 13 | } 14 | 15 | function transferFrom(address from, address to, uint256 value) public whenNotPaused returns (bool) { 16 | return super.transferFrom(from, to, value); 17 | } 18 | 19 | function approve(address spender, uint256 value) public whenNotPaused returns (bool) { 20 | return super.approve(spender, value); 21 | } 22 | 23 | function increaseAllowance(address spender, uint addedValue) public whenNotPaused returns (bool success) { 24 | return super.increaseAllowance(spender, addedValue); 25 | } 26 | 27 | function decreaseAllowance(address spender, uint subtractedValue) public whenNotPaused returns (bool success) { 28 | return super.decreaseAllowance(spender, subtractedValue); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC20/IERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title ERC20 interface 5 | * @dev see https://eips.ethereum.org/EIPS/eip-20 6 | */ 7 | interface IERC20 { 8 | function transfer(address to, uint256 value) external returns (bool); 9 | 10 | function approve(address spender, uint256 value) external returns (bool); 11 | 12 | function transferFrom(address from, address to, uint256 value) external returns (bool); 13 | 14 | function totalSupply() external view returns (uint256); 15 | 16 | function balanceOf(address who) external view returns (uint256); 17 | 18 | function allowance(address owner, address spender) external view returns (uint256); 19 | 20 | event Transfer(address indexed from, address indexed to, uint256 value); 21 | 22 | event Approval(address indexed owner, address indexed spender, uint256 value); 23 | } 24 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/ERC721.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./IERC721.sol"; 4 | import "./IERC721Receiver.sol"; 5 | import "../../math/SafeMath.sol"; 6 | import "../../utils/Address.sol"; 7 | import "../../drafts/Counters.sol"; 8 | import "../../introspection/ERC165.sol"; 9 | 10 | /** 11 | * @title ERC721 Non-Fungible Token Standard basic implementation 12 | * @dev see https://eips.ethereum.org/EIPS/eip-721 13 | */ 14 | contract ERC721 is ERC165, IERC721 { 15 | using SafeMath for uint256; 16 | using Address for address; 17 | using Counters for Counters.Counter; 18 | 19 | // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` 20 | // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` 21 | bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; 22 | 23 | // Mapping from token ID to owner 24 | mapping (uint256 => address) private _tokenOwner; 25 | 26 | // Mapping from token ID to approved address 27 | mapping (uint256 => address) private _tokenApprovals; 28 | 29 | // Mapping from owner to number of owned token 30 | mapping (address => Counters.Counter) private _ownedTokensCount; 31 | 32 | // Mapping from owner to operator approvals 33 | mapping (address => mapping (address => bool)) private _operatorApprovals; 34 | 35 | bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; 36 | /* 37 | * 0x80ac58cd === 38 | * bytes4(keccak256('balanceOf(address)')) ^ 39 | * bytes4(keccak256('ownerOf(uint256)')) ^ 40 | * bytes4(keccak256('approve(address,uint256)')) ^ 41 | * bytes4(keccak256('getApproved(uint256)')) ^ 42 | * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ 43 | * bytes4(keccak256('isApprovedForAll(address,address)')) ^ 44 | * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ 45 | * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ 46 | * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) 47 | */ 48 | 49 | constructor () public { 50 | // register the supported interfaces to conform to ERC721 via ERC165 51 | _registerInterface(_INTERFACE_ID_ERC721); 52 | } 53 | 54 | /** 55 | * @dev Gets the balance of the specified address 56 | * @param owner address to query the balance of 57 | * @return uint256 representing the amount owned by the passed address 58 | */ 59 | function balanceOf(address owner) public view returns (uint256) { 60 | require(owner != address(0)); 61 | return _ownedTokensCount[owner].current(); 62 | } 63 | 64 | /** 65 | * @dev Gets the owner of the specified token ID 66 | * @param tokenId uint256 ID of the token to query the owner of 67 | * @return address currently marked as the owner of the given token ID 68 | */ 69 | function ownerOf(uint256 tokenId) public view returns (address) { 70 | address owner = _tokenOwner[tokenId]; 71 | require(owner != address(0)); 72 | return owner; 73 | } 74 | 75 | /** 76 | * @dev Approves another address to transfer the given token ID 77 | * The zero address indicates there is no approved address. 78 | * There can only be one approved address per token at a given time. 79 | * Can only be called by the token owner or an approved operator. 80 | * @param to address to be approved for the given token ID 81 | * @param tokenId uint256 ID of the token to be approved 82 | */ 83 | function approve(address to, uint256 tokenId) public { 84 | address owner = ownerOf(tokenId); 85 | require(to != owner); 86 | require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); 87 | 88 | _tokenApprovals[tokenId] = to; 89 | emit Approval(owner, to, tokenId); 90 | } 91 | 92 | /** 93 | * @dev Gets the approved address for a token ID, or zero if no address set 94 | * Reverts if the token ID does not exist. 95 | * @param tokenId uint256 ID of the token to query the approval of 96 | * @return address currently approved for the given token ID 97 | */ 98 | function getApproved(uint256 tokenId) public view returns (address) { 99 | require(_exists(tokenId)); 100 | return _tokenApprovals[tokenId]; 101 | } 102 | 103 | /** 104 | * @dev Sets or unsets the approval of a given operator 105 | * An operator is allowed to transfer all tokens of the sender on their behalf 106 | * @param to operator address to set the approval 107 | * @param approved representing the status of the approval to be set 108 | */ 109 | function setApprovalForAll(address to, bool approved) public { 110 | require(to != msg.sender); 111 | _operatorApprovals[msg.sender][to] = approved; 112 | emit ApprovalForAll(msg.sender, to, approved); 113 | } 114 | 115 | /** 116 | * @dev Tells whether an operator is approved by a given owner 117 | * @param owner owner address which you want to query the approval of 118 | * @param operator operator address which you want to query the approval of 119 | * @return bool whether the given operator is approved by the given owner 120 | */ 121 | function isApprovedForAll(address owner, address operator) public view returns (bool) { 122 | return _operatorApprovals[owner][operator]; 123 | } 124 | 125 | /** 126 | * @dev Transfers the ownership of a given token ID to another address 127 | * Usage of this method is discouraged, use `safeTransferFrom` whenever possible 128 | * Requires the msg.sender to be the owner, approved, or operator 129 | * @param from current owner of the token 130 | * @param to address to receive the ownership of the given token ID 131 | * @param tokenId uint256 ID of the token to be transferred 132 | */ 133 | function transferFrom(address from, address to, uint256 tokenId) public { 134 | require(_isApprovedOrOwner(msg.sender, tokenId)); 135 | 136 | _transferFrom(from, to, tokenId); 137 | } 138 | 139 | /** 140 | * @dev Safely transfers the ownership of a given token ID to another address 141 | * If the target address is a contract, it must implement `onERC721Received`, 142 | * which is called upon a safe transfer, and return the magic value 143 | * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, 144 | * the transfer is reverted. 145 | * Requires the msg.sender to be the owner, approved, or operator 146 | * @param from current owner of the token 147 | * @param to address to receive the ownership of the given token ID 148 | * @param tokenId uint256 ID of the token to be transferred 149 | */ 150 | function safeTransferFrom(address from, address to, uint256 tokenId) public { 151 | safeTransferFrom(from, to, tokenId, ""); 152 | } 153 | 154 | /** 155 | * @dev Safely transfers the ownership of a given token ID to another address 156 | * If the target address is a contract, it must implement `onERC721Received`, 157 | * which is called upon a safe transfer, and return the magic value 158 | * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, 159 | * the transfer is reverted. 160 | * Requires the msg.sender to be the owner, approved, or operator 161 | * @param from current owner of the token 162 | * @param to address to receive the ownership of the given token ID 163 | * @param tokenId uint256 ID of the token to be transferred 164 | * @param _data bytes data to send along with a safe transfer check 165 | */ 166 | function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public { 167 | transferFrom(from, to, tokenId); 168 | require(_checkOnERC721Received(from, to, tokenId, _data)); 169 | } 170 | 171 | /** 172 | * @dev Returns whether the specified token exists 173 | * @param tokenId uint256 ID of the token to query the existence of 174 | * @return bool whether the token exists 175 | */ 176 | function _exists(uint256 tokenId) internal view returns (bool) { 177 | address owner = _tokenOwner[tokenId]; 178 | return owner != address(0); 179 | } 180 | 181 | /** 182 | * @dev Returns whether the given spender can transfer a given token ID 183 | * @param spender address of the spender to query 184 | * @param tokenId uint256 ID of the token to be transferred 185 | * @return bool whether the msg.sender is approved for the given token ID, 186 | * is an operator of the owner, or is the owner of the token 187 | */ 188 | function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { 189 | address owner = ownerOf(tokenId); 190 | return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); 191 | } 192 | 193 | /** 194 | * @dev Internal function to mint a new token 195 | * Reverts if the given token ID already exists 196 | * @param to The address that will own the minted token 197 | * @param tokenId uint256 ID of the token to be minted 198 | */ 199 | function _mint(address to, uint256 tokenId) internal { 200 | require(to != address(0)); 201 | require(!_exists(tokenId)); 202 | 203 | _tokenOwner[tokenId] = to; 204 | _ownedTokensCount[to].increment(); 205 | 206 | emit Transfer(address(0), to, tokenId); 207 | } 208 | 209 | /** 210 | * @dev Internal function to burn a specific token 211 | * Reverts if the token does not exist 212 | * Deprecated, use _burn(uint256) instead. 213 | * @param owner owner of the token to burn 214 | * @param tokenId uint256 ID of the token being burned 215 | */ 216 | function _burn(address owner, uint256 tokenId) internal { 217 | require(ownerOf(tokenId) == owner); 218 | 219 | _clearApproval(tokenId); 220 | 221 | _ownedTokensCount[owner].decrement(); 222 | _tokenOwner[tokenId] = address(0); 223 | 224 | emit Transfer(owner, address(0), tokenId); 225 | } 226 | 227 | /** 228 | * @dev Internal function to burn a specific token 229 | * Reverts if the token does not exist 230 | * @param tokenId uint256 ID of the token being burned 231 | */ 232 | function _burn(uint256 tokenId) internal { 233 | _burn(ownerOf(tokenId), tokenId); 234 | } 235 | 236 | /** 237 | * @dev Internal function to transfer ownership of a given token ID to another address. 238 | * As opposed to transferFrom, this imposes no restrictions on msg.sender. 239 | * @param from current owner of the token 240 | * @param to address to receive the ownership of the given token ID 241 | * @param tokenId uint256 ID of the token to be transferred 242 | */ 243 | function _transferFrom(address from, address to, uint256 tokenId) internal { 244 | require(ownerOf(tokenId) == from); 245 | require(to != address(0)); 246 | 247 | _clearApproval(tokenId); 248 | 249 | _ownedTokensCount[from].decrement(); 250 | _ownedTokensCount[to].increment(); 251 | 252 | _tokenOwner[tokenId] = to; 253 | 254 | emit Transfer(from, to, tokenId); 255 | } 256 | 257 | /** 258 | * @dev Internal function to invoke `onERC721Received` on a target address 259 | * The call is not executed if the target address is not a contract 260 | * @param from address representing the previous owner of the given token ID 261 | * @param to target address that will receive the tokens 262 | * @param tokenId uint256 ID of the token to be transferred 263 | * @param _data bytes optional data to send along with the call 264 | * @return bool whether the call correctly returned the expected magic value 265 | */ 266 | function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) 267 | internal returns (bool) 268 | { 269 | if (!to.isContract()) { 270 | return true; 271 | } 272 | 273 | bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data); 274 | return (retval == _ERC721_RECEIVED); 275 | } 276 | 277 | /** 278 | * @dev Private function to clear current approval of a given token ID 279 | * @param tokenId uint256 ID of the token to be transferred 280 | */ 281 | function _clearApproval(uint256 tokenId) private { 282 | if (_tokenApprovals[tokenId] != address(0)) { 283 | _tokenApprovals[tokenId] = address(0); 284 | } 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/ERC721Burnable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./ERC721.sol"; 4 | 5 | /** 6 | * @title ERC721 Burnable Token 7 | * @dev ERC721 Token that can be irreversibly burned (destroyed). 8 | */ 9 | contract ERC721Burnable is ERC721 { 10 | /** 11 | * @dev Burns a specific ERC721 token. 12 | * @param tokenId uint256 id of the ERC721 token to be burned. 13 | */ 14 | function burn(uint256 tokenId) public { 15 | require(_isApprovedOrOwner(msg.sender, tokenId)); 16 | _burn(tokenId); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/ERC721Enumerable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./IERC721Enumerable.sol"; 4 | import "./ERC721.sol"; 5 | import "../../introspection/ERC165.sol"; 6 | 7 | /** 8 | * @title ERC-721 Non-Fungible Token with optional enumeration extension logic 9 | * @dev See https://eips.ethereum.org/EIPS/eip-721 10 | */ 11 | contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { 12 | // Mapping from owner to list of owned token IDs 13 | mapping(address => uint256[]) private _ownedTokens; 14 | 15 | // Mapping from token ID to index of the owner tokens list 16 | mapping(uint256 => uint256) private _ownedTokensIndex; 17 | 18 | // Array with all token ids, used for enumeration 19 | uint256[] private _allTokens; 20 | 21 | // Mapping from token id to position in the allTokens array 22 | mapping(uint256 => uint256) private _allTokensIndex; 23 | 24 | bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; 25 | /* 26 | * 0x780e9d63 === 27 | * bytes4(keccak256('totalSupply()')) ^ 28 | * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ 29 | * bytes4(keccak256('tokenByIndex(uint256)')) 30 | */ 31 | 32 | /** 33 | * @dev Constructor function 34 | */ 35 | constructor () public { 36 | // register the supported interface to conform to ERC721Enumerable via ERC165 37 | _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE); 38 | } 39 | 40 | /** 41 | * @dev Gets the token ID at a given index of the tokens list of the requested owner 42 | * @param owner address owning the tokens list to be accessed 43 | * @param index uint256 representing the index to be accessed of the requested tokens list 44 | * @return uint256 token ID at the given index of the tokens list owned by the requested address 45 | */ 46 | function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) { 47 | require(index < balanceOf(owner)); 48 | return _ownedTokens[owner][index]; 49 | } 50 | 51 | /** 52 | * @dev Gets the total amount of tokens stored by the contract 53 | * @return uint256 representing the total amount of tokens 54 | */ 55 | function totalSupply() public view returns (uint256) { 56 | return _allTokens.length; 57 | } 58 | 59 | /** 60 | * @dev Gets the token ID at a given index of all the tokens in this contract 61 | * Reverts if the index is greater or equal to the total number of tokens 62 | * @param index uint256 representing the index to be accessed of the tokens list 63 | * @return uint256 token ID at the given index of the tokens list 64 | */ 65 | function tokenByIndex(uint256 index) public view returns (uint256) { 66 | require(index < totalSupply()); 67 | return _allTokens[index]; 68 | } 69 | 70 | /** 71 | * @dev Internal function to transfer ownership of a given token ID to another address. 72 | * As opposed to transferFrom, this imposes no restrictions on msg.sender. 73 | * @param from current owner of the token 74 | * @param to address to receive the ownership of the given token ID 75 | * @param tokenId uint256 ID of the token to be transferred 76 | */ 77 | function _transferFrom(address from, address to, uint256 tokenId) internal { 78 | super._transferFrom(from, to, tokenId); 79 | 80 | _removeTokenFromOwnerEnumeration(from, tokenId); 81 | 82 | _addTokenToOwnerEnumeration(to, tokenId); 83 | } 84 | 85 | /** 86 | * @dev Internal function to mint a new token 87 | * Reverts if the given token ID already exists 88 | * @param to address the beneficiary that will own the minted token 89 | * @param tokenId uint256 ID of the token to be minted 90 | */ 91 | function _mint(address to, uint256 tokenId) internal { 92 | super._mint(to, tokenId); 93 | 94 | _addTokenToOwnerEnumeration(to, tokenId); 95 | 96 | _addTokenToAllTokensEnumeration(tokenId); 97 | } 98 | 99 | /** 100 | * @dev Internal function to burn a specific token 101 | * Reverts if the token does not exist 102 | * Deprecated, use _burn(uint256) instead 103 | * @param owner owner of the token to burn 104 | * @param tokenId uint256 ID of the token being burned 105 | */ 106 | function _burn(address owner, uint256 tokenId) internal { 107 | super._burn(owner, tokenId); 108 | 109 | _removeTokenFromOwnerEnumeration(owner, tokenId); 110 | // Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund 111 | _ownedTokensIndex[tokenId] = 0; 112 | 113 | _removeTokenFromAllTokensEnumeration(tokenId); 114 | } 115 | 116 | /** 117 | * @dev Gets the list of token IDs of the requested owner 118 | * @param owner address owning the tokens 119 | * @return uint256[] List of token IDs owned by the requested address 120 | */ 121 | function _tokensOfOwner(address owner) internal view returns (uint256[] storage) { 122 | return _ownedTokens[owner]; 123 | } 124 | 125 | /** 126 | * @dev Private function to add a token to this extension's ownership-tracking data structures. 127 | * @param to address representing the new owner of the given token ID 128 | * @param tokenId uint256 ID of the token to be added to the tokens list of the given address 129 | */ 130 | function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { 131 | _ownedTokensIndex[tokenId] = _ownedTokens[to].length; 132 | _ownedTokens[to].push(tokenId); 133 | } 134 | 135 | /** 136 | * @dev Private function to add a token to this extension's token tracking data structures. 137 | * @param tokenId uint256 ID of the token to be added to the tokens list 138 | */ 139 | function _addTokenToAllTokensEnumeration(uint256 tokenId) private { 140 | _allTokensIndex[tokenId] = _allTokens.length; 141 | _allTokens.push(tokenId); 142 | } 143 | 144 | /** 145 | * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that 146 | * while the token is not assigned a new owner, the _ownedTokensIndex mapping is _not_ updated: this allows for 147 | * gas optimizations e.g. when performing a transfer operation (avoiding double writes). 148 | * This has O(1) time complexity, but alters the order of the _ownedTokens array. 149 | * @param from address representing the previous owner of the given token ID 150 | * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address 151 | */ 152 | function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { 153 | // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and 154 | // then delete the last slot (swap and pop). 155 | 156 | uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); 157 | uint256 tokenIndex = _ownedTokensIndex[tokenId]; 158 | 159 | // When the token to delete is the last token, the swap operation is unnecessary 160 | if (tokenIndex != lastTokenIndex) { 161 | uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; 162 | 163 | _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token 164 | _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index 165 | } 166 | 167 | // This also deletes the contents at the last position of the array 168 | _ownedTokens[from].length--; 169 | 170 | // Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occupied by 171 | // lastTokenId, or just over the end of the array if the token was the last one). 172 | } 173 | 174 | /** 175 | * @dev Private function to remove a token from this extension's token tracking data structures. 176 | * This has O(1) time complexity, but alters the order of the _allTokens array. 177 | * @param tokenId uint256 ID of the token to be removed from the tokens list 178 | */ 179 | function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { 180 | // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and 181 | // then delete the last slot (swap and pop). 182 | 183 | uint256 lastTokenIndex = _allTokens.length.sub(1); 184 | uint256 tokenIndex = _allTokensIndex[tokenId]; 185 | 186 | // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so 187 | // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding 188 | // an 'if' statement (like in _removeTokenFromOwnerEnumeration) 189 | uint256 lastTokenId = _allTokens[lastTokenIndex]; 190 | 191 | _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token 192 | _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index 193 | 194 | // This also deletes the contents at the last position of the array 195 | _allTokens.length--; 196 | _allTokensIndex[tokenId] = 0; 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/ERC721Full.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./ERC721.sol"; 4 | import "./ERC721Enumerable.sol"; 5 | import "./ERC721Metadata.sol"; 6 | 7 | /** 8 | * @title Full ERC721 Token 9 | * This implementation includes all the required and some optional functionality of the ERC721 standard 10 | * Moreover, it includes approve all functionality using operator terminology 11 | * @dev see https://eips.ethereum.org/EIPS/eip-721 12 | */ 13 | contract ERC721Full is ERC721, ERC721Enumerable, ERC721Metadata { 14 | constructor (string memory name, string memory symbol) public ERC721Metadata(name, symbol) { 15 | // solhint-disable-previous-line no-empty-blocks 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/ERC721Holder.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./IERC721Receiver.sol"; 4 | 5 | contract ERC721Holder is IERC721Receiver { 6 | function onERC721Received(address, address, uint256, bytes memory) public returns (bytes4) { 7 | return this.onERC721Received.selector; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/ERC721Metadata.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./ERC721.sol"; 4 | import "./IERC721Metadata.sol"; 5 | import "../../introspection/ERC165.sol"; 6 | 7 | contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { 8 | // Token name 9 | string private _name; 10 | 11 | // Token symbol 12 | string private _symbol; 13 | 14 | // Optional mapping for token URIs 15 | mapping(uint256 => string) private _tokenURIs; 16 | 17 | bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f; 18 | /* 19 | * 0x5b5e139f === 20 | * bytes4(keccak256('name()')) ^ 21 | * bytes4(keccak256('symbol()')) ^ 22 | * bytes4(keccak256('tokenURI(uint256)')) 23 | */ 24 | 25 | /** 26 | * @dev Constructor function 27 | */ 28 | constructor (string memory name, string memory symbol) public { 29 | _name = name; 30 | _symbol = symbol; 31 | 32 | // register the supported interfaces to conform to ERC721 via ERC165 33 | _registerInterface(_INTERFACE_ID_ERC721_METADATA); 34 | } 35 | 36 | /** 37 | * @dev Gets the token name 38 | * @return string representing the token name 39 | */ 40 | function name() external view returns (string memory) { 41 | return _name; 42 | } 43 | 44 | /** 45 | * @dev Gets the token symbol 46 | * @return string representing the token symbol 47 | */ 48 | function symbol() external view returns (string memory) { 49 | return _symbol; 50 | } 51 | 52 | /** 53 | * @dev Returns an URI for a given token ID 54 | * Throws if the token ID does not exist. May return an empty string. 55 | * @param tokenId uint256 ID of the token to query 56 | */ 57 | function tokenURI(uint256 tokenId) external view returns (string memory) { 58 | require(_exists(tokenId)); 59 | return _tokenURIs[tokenId]; 60 | } 61 | 62 | /** 63 | * @dev Internal function to set the token URI for a given token 64 | * Reverts if the token ID does not exist 65 | * @param tokenId uint256 ID of the token to set its URI 66 | * @param uri string URI to assign 67 | */ 68 | function _setTokenURI(uint256 tokenId, string memory uri) internal { 69 | require(_exists(tokenId)); 70 | _tokenURIs[tokenId] = uri; 71 | } 72 | 73 | /** 74 | * @dev Internal function to burn a specific token 75 | * Reverts if the token does not exist 76 | * Deprecated, use _burn(uint256) instead 77 | * @param owner owner of the token to burn 78 | * @param tokenId uint256 ID of the token being burned by the msg.sender 79 | */ 80 | function _burn(address owner, uint256 tokenId) internal { 81 | super._burn(owner, tokenId); 82 | 83 | // Clear metadata (if any) 84 | if (bytes(_tokenURIs[tokenId]).length != 0) { 85 | delete _tokenURIs[tokenId]; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/ERC721MetadataMintable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./ERC721Metadata.sol"; 4 | import "../../access/roles/MinterRole.sol"; 5 | 6 | 7 | /** 8 | * @title ERC721MetadataMintable 9 | * @dev ERC721 minting logic with metadata 10 | */ 11 | contract ERC721MetadataMintable is ERC721, ERC721Metadata, MinterRole { 12 | /** 13 | * @dev Function to mint tokens 14 | * @param to The address that will receive the minted tokens. 15 | * @param tokenId The token id to mint. 16 | * @param tokenURI The token URI of the minted token. 17 | * @return A boolean that indicates if the operation was successful. 18 | */ 19 | function mintWithTokenURI(address to, uint256 tokenId, string memory tokenURI) public onlyMinter returns (bool) { 20 | _mint(to, tokenId); 21 | _setTokenURI(tokenId, tokenURI); 22 | return true; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/ERC721Mintable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./ERC721.sol"; 4 | import "../../access/roles/MinterRole.sol"; 5 | 6 | /** 7 | * @title ERC721Mintable 8 | * @dev ERC721 minting logic 9 | */ 10 | contract ERC721Mintable is ERC721, MinterRole { 11 | /** 12 | * @dev Function to mint tokens 13 | * @param to The address that will receive the minted tokens. 14 | * @param tokenId The token id to mint. 15 | * @return A boolean that indicates if the operation was successful. 16 | */ 17 | function mint(address to, uint256 tokenId) public onlyMinter returns (bool) { 18 | _mint(to, tokenId); 19 | return true; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/ERC721Pausable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./ERC721.sol"; 4 | import "../../lifecycle/Pausable.sol"; 5 | 6 | /** 7 | * @title ERC721 Non-Fungible Pausable token 8 | * @dev ERC721 modified with pausable transfers. 9 | */ 10 | contract ERC721Pausable is ERC721, Pausable { 11 | function approve(address to, uint256 tokenId) public whenNotPaused { 12 | super.approve(to, tokenId); 13 | } 14 | 15 | function setApprovalForAll(address to, bool approved) public whenNotPaused { 16 | super.setApprovalForAll(to, approved); 17 | } 18 | 19 | function transferFrom(address from, address to, uint256 tokenId) public whenNotPaused { 20 | super.transferFrom(from, to, tokenId); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/IERC721.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../../introspection/IERC165.sol"; 4 | 5 | /** 6 | * @title ERC721 Non-Fungible Token Standard basic interface 7 | * @dev see https://eips.ethereum.org/EIPS/eip-721 8 | */ 9 | contract IERC721 is IERC165 { 10 | event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); 11 | event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); 12 | event ApprovalForAll(address indexed owner, address indexed operator, bool approved); 13 | 14 | function balanceOf(address owner) public view returns (uint256 balance); 15 | function ownerOf(uint256 tokenId) public view returns (address owner); 16 | 17 | function approve(address to, uint256 tokenId) public; 18 | function getApproved(uint256 tokenId) public view returns (address operator); 19 | 20 | function setApprovalForAll(address operator, bool _approved) public; 21 | function isApprovedForAll(address owner, address operator) public view returns (bool); 22 | 23 | function transferFrom(address from, address to, uint256 tokenId) public; 24 | function safeTransferFrom(address from, address to, uint256 tokenId) public; 25 | 26 | function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public; 27 | } 28 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/IERC721Enumerable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./IERC721.sol"; 4 | 5 | /** 6 | * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension 7 | * @dev See https://eips.ethereum.org/EIPS/eip-721 8 | */ 9 | contract IERC721Enumerable is IERC721 { 10 | function totalSupply() public view returns (uint256); 11 | function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256 tokenId); 12 | 13 | function tokenByIndex(uint256 index) public view returns (uint256); 14 | } 15 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/IERC721Full.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./IERC721.sol"; 4 | import "./IERC721Enumerable.sol"; 5 | import "./IERC721Metadata.sol"; 6 | 7 | /** 8 | * @title ERC-721 Non-Fungible Token Standard, full implementation interface 9 | * @dev See https://eips.ethereum.org/EIPS/eip-721 10 | */ 11 | contract IERC721Full is IERC721, IERC721Enumerable, IERC721Metadata { 12 | // solhint-disable-previous-line no-empty-blocks 13 | } 14 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/IERC721Metadata.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "./IERC721.sol"; 4 | 5 | /** 6 | * @title ERC-721 Non-Fungible Token Standard, optional metadata extension 7 | * @dev See https://eips.ethereum.org/EIPS/eip-721 8 | */ 9 | contract IERC721Metadata is IERC721 { 10 | function name() external view returns (string memory); 11 | function symbol() external view returns (string memory); 12 | function tokenURI(uint256 tokenId) external view returns (string memory); 13 | } 14 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/token/ERC721/IERC721Receiver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title ERC721 token receiver interface 5 | * @dev Interface for any contract that wants to support safeTransfers 6 | * from ERC721 asset contracts. 7 | */ 8 | contract IERC721Receiver { 9 | /** 10 | * @notice Handle the receipt of an NFT 11 | * @dev The ERC721 smart contract calls this function on the recipient 12 | * after a `safeTransfer`. This function MUST return the function selector, 13 | * otherwise the caller will revert the transaction. The selector to be 14 | * returned can be obtained as `this.onERC721Received.selector`. This 15 | * function MAY throw to revert and reject the transfer. 16 | * Note: the ERC721 contract address is always the message sender. 17 | * @param operator The address which called `safeTransferFrom` function 18 | * @param from The address which previously owned the token 19 | * @param tokenId The NFT identifier which is being transferred 20 | * @param data Additional data with no specified format 21 | * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` 22 | */ 23 | function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) 24 | public returns (bytes4); 25 | } 26 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/utils/Address.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * Utility library of inline functions on addresses 5 | */ 6 | library Address { 7 | /** 8 | * Returns whether the target address is a contract 9 | * @dev This function will return false if invoked during the constructor of a contract, 10 | * as the code is not actually created until after the constructor finishes. 11 | * @param account address of the account to check 12 | * @return whether the target address is a contract 13 | */ 14 | function isContract(address account) internal view returns (bool) { 15 | uint256 size; 16 | // XXX Currently there is no better way to check if there is a contract in an address 17 | // than to check the size of the code at that address. 18 | // See https://ethereum.stackexchange.com/a/14016/36603 19 | // for more details about how this works. 20 | // TODO Check this again before the Serenity release, because all addresses will be 21 | // contracts then. 22 | // solhint-disable-next-line no-inline-assembly 23 | assembly { size := extcodesize(account) } 24 | return size > 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/utils/Arrays.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | import "../math/Math.sol"; 4 | 5 | 6 | /** 7 | * @title Arrays 8 | * @dev Utility library of inline array functions 9 | */ 10 | library Arrays { 11 | /** 12 | * @dev Upper bound search function which is kind of binary search algorithm. It searches sorted 13 | * array to find index of the element value. If element is found then returns its index otherwise 14 | * it returns index of first element which is greater than searched value. If searched element is 15 | * bigger than any array element function then returns first index after last element (i.e. all 16 | * values inside the array are smaller than the target). Complexity O(log n). 17 | * @param array The array sorted in ascending order. 18 | * @param element The element's value to be found. 19 | * @return The calculated index value. Returns 0 for empty array. 20 | */ 21 | function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { 22 | if (array.length == 0) { 23 | return 0; 24 | } 25 | 26 | uint256 low = 0; 27 | uint256 high = array.length; 28 | 29 | while (low < high) { 30 | uint256 mid = Math.average(low, high); 31 | 32 | // Note that mid will always be strictly less than high (i.e. it will be a valid array index) 33 | // because Math.average rounds down (it does integer division with truncation). 34 | if (array[mid] > element) { 35 | high = mid; 36 | } else { 37 | low = mid + 1; 38 | } 39 | } 40 | 41 | // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. 42 | if (low > 0 && array[low - 1] == element) { 43 | return low - 1; 44 | } else { 45 | return low; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /templates/template-solidity/contracts/utils/ReentrancyGuard.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.5.0 <0.6.0; 2 | 3 | /** 4 | * @title Helps contracts guard against reentrancy attacks. 5 | * @author Remco Bloemen , Eenae 6 | * @dev If you mark a function `nonReentrant`, you should also 7 | * mark it `external`. 8 | */ 9 | contract ReentrancyGuard { 10 | /// @dev counter to allow mutex lock with only one SSTORE operation 11 | uint256 private _guardCounter; 12 | 13 | constructor () internal { 14 | // The counter starts at one to prevent changing it from zero to a non-zero 15 | // value, which is a more expensive operation. 16 | _guardCounter = 1; 17 | } 18 | 19 | /** 20 | * @dev Prevents a contract from calling itself, directly or indirectly. 21 | * Calling a `nonReentrant` function from another `nonReentrant` 22 | * function is not supported. It is possible to prevent this from happening 23 | * by making the `nonReentrant` function external, and make it call a 24 | * `private` function that does the actual work. 25 | */ 26 | modifier nonReentrant() { 27 | _guardCounter += 1; 28 | uint256 localCounter = _guardCounter; 29 | _; 30 | require(localCounter == _guardCounter); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /templates/template-solidity/env.template: -------------------------------------------------------------------------------- 1 | // UPDATE WITH YOUR PRIVATE DATA, move to .env 2 | WALLET=// wallet used to deploy contracts 3 | INFURA_API_KEY=// API key you get from infura 4 | MNENOMIC=// 12 word pass key from derived from your wallet private key 5 | -------------------------------------------------------------------------------- /templates/template-solidity/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /templates/template-solidity/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const Contract = CONTRACT_REQUIRE 2 | 3 | module.exports = function (deployer, _, [contractOwner]) { 4 | const contractParams = CONTRACT_PARAMS 5 | return deployer.deploy(Contract, ...contractParams, { from: contractOwner }) 6 | } 7 | -------------------------------------------------------------------------------- /templates/template-solidity/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "template-solidity", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "babel-cli": "^6.26.0", 8 | "babel-polyfill": "^6.26.0", 9 | "babel-preset-es2015": "^6.24.1", 10 | "babel-preset-stage-2": "^6.24.1", 11 | "babel-preset-stage-3": "^6.24.1", 12 | "babel-register": "^6.26.0", 13 | "dotenv": "^8.2.0", 14 | "ganache-cli": "^6.8.2", 15 | "openzeppelin-solidity": "^2.4.0", 16 | "portis": "^1.3.5", 17 | "truffle": "^5.1.9", 18 | "truffle-hdwallet-provider": "^1.0.17", 19 | "web3": "^1.2.5-rc.0" 20 | }, 21 | "scripts": { 22 | "test": "echo \"Error: no test specified\" && exit 1", 23 | "build-server": "babel src --out-dir .compiled --source-maps --watch" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /templates/template-solidity/src/empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/XYOracleNetwork-v1/tool-dapploy-nodejs/96f95e66cd4f497b4a3e91bd71e4d2057aaf0643/templates/template-solidity/src/empty -------------------------------------------------------------------------------- /templates/template-solidity/truffle.js: -------------------------------------------------------------------------------- 1 | require(`babel-register`)({ 2 | ignore: /node_modules\/(?!openzeppelin-solidity)/ 3 | }) 4 | require(`babel-polyfill`) 5 | const HDWalletProvider = require(`truffle-hdwallet-provider`) 6 | require(`dotenv`).config() // Store environment-specific variable from '.env' to process.env 7 | 8 | // NOTE: If retreiving mnemonic from Metamask - use 1st wallet in profile list, 9 | // or add index param in HDWalletProvider 10 | 11 | const wallet = process.env.WALLET 12 | const mnemonic = process.env.MNENOMIC 13 | const infuraKey = process.env.INFURA_API_KEY 14 | if (!infuraKey || !wallet || !mnemonic) { 15 | console.log(`No .env file found, so you cannot deploy to remote network!`) 16 | } 17 | 18 | module.exports = { 19 | migrations_directory: `./migrations`, 20 | networks: { 21 | development: { 22 | network_id: `*`, // Match any network id 23 | host: `localhost`, 24 | port: 8545 25 | }, 26 | ropsten: { 27 | network_id: 3, 28 | provider: () => new HDWalletProvider( 29 | mnemonic, 30 | `https://ropsten.infura.io/${infuraKey}` 31 | ), 32 | gas: 6986331, 33 | gasPrice: 2500000000 34 | }, 35 | rinkeby: { 36 | network_id: 4, 37 | from: wallet, 38 | provider: () => new HDWalletProvider( 39 | mnemonic, 40 | `https://rinkeby.infura.io/v3/${infuraKey}` 41 | ), 42 | gas: 6986331, 43 | gasPrice: 2500000000 44 | }, 45 | kovan: { 46 | network_id: 42, 47 | from: wallet, 48 | provider: () => new HDWalletProvider( 49 | mnemonic, 50 | `https://kovan.infura.io/v3/${infuraKey}` 51 | ), 52 | gas: 6986331, 53 | gasPrice: 2500000000 54 | }, 55 | mainnet: { 56 | network_id: 1, 57 | provider: () => new HDWalletProvider( 58 | mnemonic, 59 | `https://mainnet.infura.io/${infuraKey}` 60 | ), 61 | gas: 4500000, 62 | gasPrice: 2500000000 63 | } 64 | }, 65 | solc: { 66 | optimizer: { 67 | enabled: true, 68 | runs: 500 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /templates/template-web3-client.js: -------------------------------------------------------------------------------- 1 | /* 2 | This is an auto-generated web3 interface to the smart contracts deployed via Dapploy 3 | Do not make changes to this file, they get overwritten each Dapploy :) 4 | */ 5 | /* eslint-disable */ 6 | import Web3 from 'web3' 7 | 8 | PORTIS_DECLARATION 9 | 10 | export const getWeb3 = () => { 11 | if (typeof window.web3 !== 'undefined') { 12 | return new Web3(window.web3.currentProvider) 13 | } 14 | PORTIS_PROVIDER 15 | } 16 | 17 | const contractObject = name => 18 | SmartContracts.find(contract => contract.name === name) 19 | 20 | export const contractNamed = name => { 21 | const contractObj = contractObject(name) 22 | return contractObj ? contractObj.contract : undefined 23 | } 24 | 25 | export const contractAddress = name => { 26 | const contractObj = contractObject(name) 27 | return contractObj ? contractObj.address : undefined 28 | } 29 | 30 | export const validateContracts = async => { 31 | return Promise.all( 32 | SmartContracts.map(contract => validContract(contract.name)), 33 | ).then(results => { 34 | return results.reduce((result, next) => result && next) 35 | }) 36 | } 37 | 38 | export const validContract = async name => { 39 | console.log('Validating Contract', name) 40 | const address = contractAddress(name) 41 | return new Promise((resolve, reject) => { 42 | web3.eth 43 | .getCode(address) 44 | .then( 45 | code => 46 | code === '0x0' || code === '0x' ? resolve(false) : resolve(true), 47 | ) 48 | .catch(err => reject(err)) 49 | }) 50 | } 51 | 52 | const getCurrentUser = async () => 53 | web3.eth.getAccounts().then(accounts => accounts[0]) 54 | 55 | export let SmartContracts = [] 56 | export let web3 57 | export let currentUser 58 | 59 | CONTRACT_DECLARATIONS 60 | 61 | const refreshContracts = async web3 => 62 | web3.eth.net.getId().then(netId => { 63 | SmartContracts = [] 64 | CONTRACT_INSTANTIATION 65 | return Promise.resolve(SmartContracts) 66 | }) 67 | 68 | export function injectWeb3() { 69 | web3 = getWeb3() 70 | 71 | const refreshUser = () => 72 | getCurrentUser().then(account => { 73 | currentUser = account 74 | }) 75 | const refreshDapp = async () => 76 | Promise.all([refreshUser(), refreshContracts(web3)]) 77 | 78 | // Will refresh local store when new user is chosen: 79 | web3.currentProvider.publicConfigStore.on('update', refreshDapp) 80 | 81 | return refreshDapp() 82 | } 83 | -------------------------------------------------------------------------------- /templates/template-web3-server.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import HDWalletProvider from "truffle-hdwallet-provider" 3 | import "dotenv/config" 4 | import Web3 from "web3" 5 | import { readLocalABI } from "./ABIReader" 6 | import "babel-polyfill" 7 | 8 | const mnemonic = process.env.MNENOMIC 9 | const infuraKey = process.env.INFURA_API_KEY 10 | 11 | export class SmartContractService { 12 | constructor() { 13 | console.log("Init SmartContractService") 14 | this.smartContracts = [] 15 | this.currentUser = undefined 16 | this.refreshContracts.bind(this) 17 | this.reloadWeb3.bind(this) 18 | this.refreshUser.bind(this) 19 | } 20 | 21 | getCurrentNetwork = () => { 22 | return this.currentNetwork 23 | } 24 | 25 | getSmartContracts = () => this.smartContracts 26 | 27 | getCurrentConfigStore = () => 28 | this.web3 29 | ? this.web3.currentProvider 30 | ? this.web3.currentProvider.publicConfigStore 31 | : undefined 32 | : undefined 33 | 34 | getNetworksString = networks => { 35 | let networkString = "" 36 | let iterator = 0 37 | Object.entries(networks).forEach(net => { 38 | networkString += this.getNetworkString(iterator, net[0]) 39 | iterator++ 40 | }) 41 | return networkString 42 | } 43 | 44 | getNetworkString = (iterator, netId) => { 45 | let addComma = (iterator, word) => (iterator > 0 ? `, ${word}` : word) 46 | let word = "localhost" 47 | switch (netId) { 48 | case "1": 49 | word = "mainnet" 50 | break 51 | case "3": 52 | word = "roptsten" 53 | break 54 | case "4": 55 | word = "rinkeby" 56 | break 57 | case "42": 58 | word = "kovan" 59 | break 60 | case "5777": 61 | word = "localhost" 62 | break 63 | } 64 | return addComma(iterator, word) 65 | } 66 | 67 | contractObject = name => 68 | this.smartContracts.find(contract => contract.name === name) 69 | 70 | contractNamed = name => { 71 | const contractObj = this.contractObject(name) 72 | return contractObj ? contractObj.contract : undefined 73 | } 74 | 75 | contractAddress = name => { 76 | const contractObj = this.contractObject(name) 77 | return contractObj ? contractObj.address : undefined 78 | } 79 | 80 | validateContracts = async => { 81 | return Promise.all( 82 | this.smartContracts.map(contract => this.validContract(contract.name)) 83 | ).then(results => { 84 | if (results.length == 0) { 85 | throw new Error("No contracts found on this network") 86 | } else { 87 | return results.reduce((result, next) => result && next) 88 | } 89 | }) 90 | } 91 | 92 | validContract = async name => { 93 | const address = this.contractAddress(name) 94 | return new Promise((resolve, reject) => { 95 | this.web3.eth 96 | .getCode(address) 97 | .then( 98 | code => 99 | code === "0x0" || code === "0x" ? resolve(false) : resolve(true) 100 | ) 101 | .catch(err => reject(err)) 102 | }) 103 | } 104 | 105 | getCurrentUser = () => this.currentUser 106 | 107 | refreshContracts = async (netId, dir) => { 108 | console.log("Refreshing contracts") 109 | let contracts = [] 110 | return readLocalABI(dir) 111 | .then(files => { 112 | return { abi: files } 113 | }) 114 | .then(data => { 115 | contracts = data.abi 116 | this.currentNetwork = this.getNetworkString(0, String(netId)) 117 | let sc = [] 118 | contracts.forEach(contract => { 119 | let json = contract.data 120 | if (json && json.networks[netId]) { 121 | console.log( 122 | "Adding Contract", 123 | json.contractName, 124 | json.networks[netId] 125 | ) 126 | const address = json.networks[netId].address 127 | const contract = new this.web3.eth.Contract(json.abi, address) 128 | sc.push({ 129 | name: json.contractName, 130 | contract: contract, 131 | address: address, 132 | networks: json.networks 133 | }) 134 | } else if (Object.entries(json.networks).length > 0) { 135 | console.log( 136 | "You are on the wrong network", 137 | this.web3.currentProvider.network, 138 | Object.entries(json.networks)[0] 139 | ) 140 | throw new Error("Wrong Network Detected") 141 | } 142 | }) 143 | this.smartContracts = sc 144 | return sc 145 | }) 146 | .catch(err => { 147 | console.log("Caught here", err) 148 | // throw new Error('Could not refresh', err) 149 | }) 150 | } 151 | 152 | getWeb3 = netId => { 153 | if (netId !== "5777") { 154 | return new Web3( 155 | new HDWalletProvider( 156 | mnemonic, 157 | `https://${this.getNetworksString(netId)}.infura.io/v3/${infuraKey}` 158 | ) 159 | ) 160 | } else { 161 | var provider = new HDWalletProvider(mnemonic, "http://localhost:8545") 162 | return new Web3(provider) 163 | } 164 | } 165 | 166 | refreshUser = async () => 167 | this.web3.eth.getAccounts().then(accounts => { 168 | console.log(`Updating USER from ${this.currentUser} to ${accounts[0]}`) 169 | this.currentUser = accounts[0] 170 | return accounts[0] 171 | }) 172 | 173 | reloadWeb3 = async (netId, dir) => { 174 | this.web3 = this.getWeb3(netId) 175 | return this.refreshContracts(netId, dir) 176 | } 177 | } 178 | --------------------------------------------------------------------------------