├── .prettierignore ├── .soliumignore ├── migrations └── 1_initial_migration.js ├── .gitlab-ci.yml ├── .soliumrc.json ├── .travis.yml ├── contracts ├── Example.sol └── Migrations.sol ├── LICENSE ├── package.json ├── test └── Example.js ├── .gitignore ├── README.md └── truffle-config.js /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | *.sol 4 | -------------------------------------------------------------------------------- /.soliumignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | contracts/Migrations.sol 3 | -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('Migrations') 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations) 5 | } 6 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: node:10 2 | 3 | stages: 4 | - test 5 | 6 | cache: 7 | paths: 8 | - node_modules/ 9 | 10 | test: 11 | stage: test 12 | before_script: 13 | - npm i -g ganache-cli 14 | - ganache-cli -h localhost -p 8545 2>&1 > ganache-output.log & 15 | script: 16 | - npm install 17 | - npm run lint 18 | - npm run test 19 | -------------------------------------------------------------------------------- /.soliumrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solium:recommended", 3 | "plugins": [ 4 | "security" 5 | ], 6 | "rules": { 7 | "mixedcase": "error", 8 | "quotes": [ 9 | "error", 10 | "double" 11 | ], 12 | "indentation": [ 13 | "error", 14 | 4 15 | ], 16 | "linebreak-style": [ 17 | "error", 18 | "unix" 19 | ] 20 | } 21 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "10" 4 | 5 | cache: 6 | directories: 7 | - node_modules 8 | 9 | before_install: 10 | - npm install -g ganache-cli 11 | - ganache-cli --gasLimit 8000000 -h localhost -p 8545 2>&1 > ganache-output.log & 12 | 13 | install: 14 | - npm install 15 | 16 | jobs: 17 | include: 18 | - stage: test 19 | script: 20 | - npm run lint 21 | - npm run test 22 | -------------------------------------------------------------------------------- /contracts/Example.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.8; 2 | 3 | /** 4 | * @title An example contract 5 | * @author nya1 6 | * @notice Used only to show how tests are working (see test folder) 7 | */ 8 | contract Example { 9 | string public myString = "INITIAL"; 10 | 11 | /** 12 | * @dev Change `myString` variable 13 | * @param newStr New string 14 | */ 15 | function changeString (string memory newStr) public { 16 | require(bytes(newStr).length < 100, "String should be less than 100 characters"); 17 | myString = newStr; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.21 <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 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 nya1 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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "solidity-boilerplate", 4 | "version": "0.1.0", 5 | "description": "A boilerplate project to quickly kickstart your solidity projects, linting, CI setup included", 6 | "main": "truffle-config.js", 7 | "directories": { 8 | "test": "test" 9 | }, 10 | "scripts": { 11 | "test": "truffle test", 12 | "compile": "truffle compile", 13 | "build": "truffle build", 14 | "truffle": "truffle", 15 | "lint": "prettier-standard '**/*.js' --fix; solium -d contracts", 16 | "lint:js": "prettier-standard '**/*.js' --fix", 17 | "lint:sol": "solium -d contracts" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/nya1/solidity-boilerplate.git" 22 | }, 23 | "author": "nya1", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/nya1/solidity-boilerplate/issues" 27 | }, 28 | "homepage": "https://github.com/nya1/solidity-boilerplate#readme", 29 | "devDependencies": { 30 | "ethlint": "^1.2.4", 31 | "prettier-standard": "^9.1.1", 32 | "truffle": "^5.0.22", 33 | "truffle-assertions": "^0.9.1" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /test/Example.js: -------------------------------------------------------------------------------- 1 | const Example = artifacts.require('Example') 2 | // helper module 3 | const truffleAssert = require('truffle-assertions') 4 | 5 | contract('Example', accounts => { 6 | let instance 7 | // deploy a new contract for this test run 8 | before(async function () { 9 | instance = await Example.new() 10 | }) 11 | 12 | it('string should be set to initial value', async function () { 13 | const myStrContract = await instance.myString.call() 14 | assert.equal(myStrContract, 'INITIAL') 15 | }) 16 | 17 | it('should change string successfully', async function () { 18 | // generate string 19 | const myStringTest = 'test_str_' + new Date() / 1000 20 | 21 | // send transaction (and make sure it doesn't throw) 22 | await truffleAssert.passes(instance.changeString(myStringTest)) 23 | 24 | // make sure contract was updated 25 | const myStrContract = await instance.myString.call() 26 | assert.equal(myStrContract, myStringTest) 27 | }) 28 | 29 | it('should fail to change string', async function () { 30 | const stringThatReverts = 31 | 'STRING_LONGER_THAN_100_CHARSSTRING_LONGER_THAN_100_CHARSSTRING_LONGER_THAN_100_CHARSSTRING_LONGER_THAN_100_CHARS' 32 | // assert revert and error message 33 | await truffleAssert.reverts( 34 | instance.changeString(stringThatReverts), 35 | 'String should be less than 100 characters' 36 | ) 37 | }) 38 | }) 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Optional REPL history 57 | .node_repl_history 58 | 59 | # Output of 'npm pack' 60 | *.tgz 61 | 62 | # Yarn Integrity file 63 | .yarn-integrity 64 | 65 | # dotenv environment variables file 66 | .env 67 | .env.test 68 | 69 | # parcel-bundler cache (https://parceljs.org/) 70 | .cache 71 | 72 | # next.js build output 73 | .next 74 | 75 | # nuxt.js build output 76 | .nuxt 77 | 78 | # vuepress build output 79 | .vuepress/dist 80 | 81 | # Serverless directories 82 | .serverless/ 83 | 84 | # FuseBox cache 85 | .fusebox/ 86 | 87 | # DynamoDB Local files 88 | .dynamodb/ 89 | 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # solidity boilerplate 2 | 3 | [![JavaScript Style Guide](https://img.shields.io/badge/js%20code%20style-standard-brightgreen.svg)](https://github.com/standard/standard) 4 | [![Solidity Style Guide](https://img.shields.io/badge/solidity%20code%20style-ethlint-brightgreen.svg)](https://github.com/duaraghav8/Ethlint) 5 | [![Build Status](https://travis-ci.org/nya1/solidity-boilerplate.svg?branch=master)](https://travis-ci.org/nya1/solidity-boilerplate) 6 | 7 | 8 | A modern boilerplate project to quickly kickstart your solidity project with best practices. 9 | 10 | Included 11 | 12 | * Truffle 5 with optimization enabled 13 | * Ethlint (Solium) linter with rules 14 | * Standard and prettier to lint JS code 15 | * Example contract with tests 16 | * Complete continuous integration setup for Travis / GitLab CI 17 | 18 | 19 | This is not an obstructive or complex boilerplate, you can remove/add any modules with minimal effort. 20 | 21 | 22 | TODO: 23 | 24 | * Add solidity documentation generator 25 | * Add solidity coverage 26 | * Create truffle box 27 | 28 | 29 | ## Get started 30 | 31 | Clone repo and create your project 32 | 33 | `git clone https://github.com/nya1/solidity-boilerplate my-project` 34 | 35 | 36 | ## Install 37 | 38 | `npm install` 39 | 40 | 41 | ## Truffle 42 | 43 | This project includes a fixed truffle version in package.json, this means a deterministic development between developers using the same codebase. 44 | 45 | Commands: 46 | 47 | `npm run compile` (alias of `truffle compile`) 48 | 49 | `npm run build` (alias of `truffle build`) 50 | 51 | 52 | To run custom truffle commands with the local installed version use `npm run truffle` with `--` delimiter, example: 53 | 54 | `npm run truffle -- debug 0x8e5dadfb921ddddfa8f53af1f9bd8beeac6838d52d7e0c2fe5085b42a4f3ca76` 55 | 56 | Will be automatically translated to (local truffle): 57 | 58 | `truffle debug 0x8e5dadfb921ddddfa8f53af1f9bd8beeac6838d52d7e0c2fe5085b42a4f3ca76` 59 | 60 | 61 | ## Test 62 | 63 | `npm run test` 64 | 65 | 66 | ### Continuous integration 67 | 68 | CI will: 69 | 70 | * Start `gananche-cli` node 71 | * Install package 72 | * Run linting (`npm run lint`) 73 | * Run tests (`npm run test`) 74 | 75 | 76 | ## Lint 77 | 78 | Lint both JS and Solidity files: 79 | 80 | `npm run lint` 81 | 82 | 83 | Javascript files only: 84 | 85 | `npm run lint:js` 86 | 87 | 88 | Solidity files only: 89 | 90 | `npm run lint:sol` 91 | 92 | 93 | ## License 94 | 95 | MIT 96 | 97 | -------------------------------------------------------------------------------- /truffle-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Use this file to configure your truffle project. It's seeded with some 3 | * common settings for different networks and features like migrations, 4 | * compilation and testing. Uncomment the ones you need or modify 5 | * them to suit your project as necessary. 6 | * 7 | * More information about configuration can be found at: 8 | * 9 | * truffleframework.com/docs/advanced/configuration 10 | * 11 | * To deploy via Infura you'll need a wallet provider (like truffle-hdwallet-provider) 12 | * to sign your transactions before they're sent to a remote public node. Infura accounts 13 | * are available for free at: infura.io/register. 14 | * 15 | * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate 16 | * public/private key pairs. If you're publishing your code to GitHub make sure you load this 17 | * phrase from a file you've .gitignored so it doesn't accidentally become public. 18 | * 19 | */ 20 | 21 | // const HDWalletProvider = require('truffle-hdwallet-provider'); 22 | // const infuraKey = "fj4jll3k....."; 23 | // 24 | // const fs = require('fs'); 25 | // const mnemonic = fs.readFileSync(".secret").toString().trim(); 26 | 27 | module.exports = { 28 | /** 29 | * Networks define how you connect to your ethereum client and let you set the 30 | * defaults web3 uses to send transactions. If you don't specify one truffle 31 | * will spin up a development blockchain for you on port 9545 when you 32 | * run `develop` or `test`. You can ask a truffle command to use a specific 33 | * network from the command line, e.g 34 | * 35 | * $ truffle test --network 36 | */ 37 | 38 | networks: { 39 | // Useful for testing. The `development` name is special - truffle uses it by default 40 | // if it's defined here and no other network is specified at the command line. 41 | // You should run a client (like ganache-cli, geth or parity) in a separate terminal 42 | // tab if you use this network and you must also set the `host`, `port` and `network_id` 43 | // options below to some value. 44 | // 45 | development: { 46 | host: '127.0.0.1', // Localhost (default: none) 47 | port: 8545, // Standard Ethereum port (default: none) 48 | network_id: '*' // Any network (default: none) 49 | } 50 | // Another network with more advanced options... 51 | // advanced: { 52 | // port: 8777, // Custom port 53 | // network_id: 1342, // Custom network 54 | // gas: 8500000, // Gas sent with each transaction (default: ~6700000) 55 | // gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei) 56 | // from:
, // Account to send txs from (default: accounts[0]) 57 | // websockets: true // Enable EventEmitter interface for web3 (default: false) 58 | // }, 59 | // Useful for deploying to a public network. 60 | // NB: It's important to wrap the provider as a function. 61 | // ropsten: { 62 | // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`), 63 | // network_id: 3, // Ropsten's id 64 | // gas: 5500000, // Ropsten has a lower block limit than mainnet 65 | // confirmations: 2, // # of confs to wait between deployments. (default: 0) 66 | // timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 67 | // skipDryRun: true // Skip dry run before migrations? (default: false for public nets ) 68 | // }, 69 | // Useful for private networks 70 | // private: { 71 | // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), 72 | // network_id: 2111, // This network is yours, in the cloud. 73 | // production: true // Treats this network as if it was a public net. (default: false) 74 | // } 75 | }, 76 | 77 | // Set default mocha options here, use special reporters etc. 78 | mocha: { 79 | // timeout: 100000 80 | }, 81 | 82 | // Configure your compilers 83 | compilers: { 84 | solc: { 85 | version: '^0.5.8', 86 | optimizer: { 87 | enabled: true, 88 | runs: 200 89 | } 90 | } 91 | // version: "0.5.1", // Fetch exact version from solc-bin (default: truffle's version) 92 | // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) 93 | // settings: { // See the solidity docs for advice about optimization and evmVersion 94 | // optimizer: { 95 | // enabled: false, 96 | // runs: 200 97 | // }, 98 | // evmVersion: "byzantium" 99 | // } 100 | } 101 | } 102 | --------------------------------------------------------------------------------