├── .eslintignore ├── .eslintrc ├── .gitattributes ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── .solcover.js ├── .soliumignore ├── .soliumrc.json ├── LICENSE.md ├── README.md ├── contracts ├── Counter.sol └── SimpleToken.sol ├── hardhat.config.ts ├── package.json ├── scripts ├── build ├── coverage ├── deploy.ts ├── flatten ├── prepublish ├── security └── test ├── test ├── counter.test.ts └── simpletoken.test.ts ├── tsconfig.json └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | build/ 2 | cache/ 3 | dist/ 4 | node_modules/ 5 | reports/ 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "@typescript-eslint/parser", 3 | "parserOptions": { 4 | "ecmaVersion": 2020, 5 | "sourceType": "module" 6 | }, 7 | "extends": ["plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"], 8 | "rules": { 9 | "prefer-const": "warn", 10 | "no-extra-semi": "off", 11 | "@typescript-eslint/no-extra-semi": "warn", 12 | "@typescript-eslint/no-inferrable-types": "warn", 13 | "@typescript-eslint/no-empty-function": "warn" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore node stuff 2 | node_modules 3 | yarn-error.log 4 | 5 | # Ignore build stuff 6 | cache 7 | build 8 | dist 9 | 10 | # Buidler cache 11 | cached 12 | 13 | # Ignore solc bin output 14 | bin 15 | 16 | # Others 17 | .env 18 | .DS_Store 19 | .vscode 20 | 21 | # Reports 22 | coverage.json 23 | reports 24 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abarmat/solidity-starter/aa04e401bdaf3269d9d2ee70aa25cbe8e500f7ef/.prettierignore -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "useTabs": false, 4 | "bracketSpacing": true, 5 | "overrides": [ 6 | { 7 | "files": "*.js", 8 | "options": { 9 | "semi": false, 10 | "trailingComma": "all", 11 | "tabWidth": 2, 12 | "singleQuote": true, 13 | "explicitTypes": "always" 14 | } 15 | }, 16 | { 17 | "files": "*.ts", 18 | "options": { 19 | "semi": false, 20 | "trailingComma": "all", 21 | "tabWidth": 2, 22 | "singleQuote": true, 23 | "explicitTypes": "always" 24 | } 25 | }, 26 | { 27 | "files": "*.sol", 28 | "options": { 29 | "tabWidth": 4, 30 | "singleQuote": false, 31 | "explicitTypes": "always" 32 | } 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /.solcover.js: -------------------------------------------------------------------------------- 1 | const skipFiles = [] 2 | 3 | module.exports = { 4 | providerOptions: { 5 | mnemonic: 'myth like bonus scare over problem client lizard pioneer submit female collect', 6 | network_id: 1337, 7 | }, 8 | skipFiles, 9 | istanbulFolder: './reports/coverage', 10 | testfiles: 'test/*.test.ts' 11 | } 12 | -------------------------------------------------------------------------------- /.soliumignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.soliumrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solium:recommended", 3 | "plugins": ["security"], 4 | "rules": { 5 | "no-experimental": ["off"], 6 | "quotes": ["error", "double"], 7 | "linebreak-style": ["error", "unix"], 8 | "security/no-inline-assembly": ["off"], 9 | "security/no-low-level-calls": ["off"] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2020 Ariel Barmat 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | 9 | Collaborators: 10 | 11 | Javier - https://github.com/javierlinked -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ethereum Solidity Starter 2 | 3 | This is a skeleton repository to work as a foundation for a smart contracts project using Solidity. 4 | 5 | ## Quickstart 6 | 7 | 1. Clone the repo 8 | 2. Run `yarn install` 9 | 10 | ## What’s Included? 11 | 12 | - **[Hardhat](https://hardhat.org/)**: Ethereum development environment for professionals. 13 | - **[Waffle](https://getwaffle.io/)**: The most advanced framework for testing smart contracts 14 | - **[Typechain](https://github.com/ethereum-ts/TypeChain)**: TypeScript bindings for Ethereum smart contracts 15 | - **[Tenderly](https://tenderly.co/)**: Real-time monitoring, alerting, and troubleshooting for Smart Contracts. 16 | - **[Ethers]()**: A complete Ethereum wallet implementation and utilities in JavaScript (and TypeScript). 17 | - **[Etherscan](https://etherscan.io)**: Verify contracts in The Ethereum Blockchain Explorer 18 | 19 | #### Hardhat Plugins 20 | - ABI Exporter 21 | - Gas Reporter 22 | - Contract Sizer 23 | - OpenZeppelin Upgrades 24 | ## Usage 25 | 26 | Look at the `package.json` inside scripts section to see available commands. A number of helper build scripts are located in `/scripts`. 27 | ### Build contracts 28 | 29 | Compiles contracts and creates Typechain bindings. 30 | 31 | `yarn build` 32 | 33 | ### Run tests 34 | 35 | Runs all tests in the `/test` folder. 36 | 37 | `yarn test` 38 | 39 | ### Run tests with gas report 40 | 41 | Run all tests calculating gas estimations. 42 | 43 | `yarn test:gas` 44 | 45 | The gas report will be saved on the `/reports` folder. 46 | 47 | ### Deploy to Ethereum 48 | 49 | Create/modify network config in hardhat.config.ts and add API key and private key, then run: 50 | 51 | `npx hardhat run --network rinkeby scripts/deploy.ts` 52 | 53 | ### Verify on Etherscan 54 | 55 | Using the hardhat-etherscan plugin, add Etherscan API key to hardhat.config.ts, then run: 56 | 57 | `npx hardhat verify --network rinkeby ` 58 | -------------------------------------------------------------------------------- /contracts/Counter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.8.15; 4 | import "hardhat/console.sol"; 5 | 6 | // NOTE: This is just a test contract, please delete me 7 | 8 | contract Counter { 9 | uint256 count = 0; 10 | 11 | event CountedTo(uint256 number); 12 | 13 | function getCount() public view returns (uint256) { 14 | return count; 15 | } 16 | 17 | function countUp() public returns (uint256) { 18 | console.log("countUp: count =", count); 19 | uint256 newCount = count + 1; 20 | require(newCount > count, "Uint256 overflow"); 21 | count = newCount; 22 | emit CountedTo(count); 23 | return count; 24 | } 25 | 26 | function countDown() public returns (uint256) { 27 | console.log("countDown: count =", count); 28 | uint256 newCount = count - 1; 29 | require(newCount < count, "Uint256 underflow"); 30 | count = newCount; 31 | emit CountedTo(count); 32 | return count; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/SimpleToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.15; 3 | 4 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | 6 | contract SimpleToken is ERC20 { 7 | constructor() ERC20("SimpleToken", "SIM") { 8 | _mint(msg.sender, 18 * 10**decimals()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from 'dotenv' 2 | dotenv.config() 3 | 4 | import { HardhatUserConfig } from 'hardhat/types' 5 | import { task } from 'hardhat/config' 6 | 7 | // Plugins 8 | 9 | import '@nomiclabs/hardhat-ethers' 10 | import '@nomiclabs/hardhat-etherscan' 11 | import '@nomiclabs/hardhat-waffle' 12 | import 'hardhat-abi-exporter' 13 | import 'hardhat-gas-reporter' 14 | import 'hardhat-contract-sizer' 15 | import '@tenderly/hardhat-tenderly' 16 | import '@openzeppelin/hardhat-upgrades' 17 | import '@typechain/hardhat' 18 | import 'solidity-coverage' 19 | 20 | // Networks 21 | 22 | interface NetworkConfig { 23 | network: string 24 | chainId: number 25 | gas?: number | 'auto' 26 | gasPrice?: number | 'auto' 27 | } 28 | 29 | const networkConfigs: NetworkConfig[] = [ 30 | { network: 'goerli', chainId: 5 }, 31 | { network: 'sepolia', chainId: 11155111 }, 32 | { network: 'mainnet', chainId: 1 }, 33 | { network: 'ropsten', chainId: 3 }, 34 | { network: 'rinkeby', chainId: 4 }, 35 | { network: 'kovan', chainId: 42 }, 36 | ] 37 | 38 | function getAccountMnemonic() { 39 | return process.env.MNEMONIC || '' 40 | } 41 | 42 | function getDefaultProviderURL(network: string) { 43 | return `https://${network}.infura.io/v3/${process.env.INFURA_KEY}` 44 | } 45 | 46 | function setupDefaultNetworkProviders(buidlerConfig) { 47 | for (const netConfig of networkConfigs) { 48 | buidlerConfig.networks[netConfig.network] = { 49 | chainId: netConfig.chainId, 50 | url: getDefaultProviderURL(netConfig.network), 51 | gas: netConfig.gasPrice || 'auto', 52 | gasPrice: netConfig.gasPrice || 'auto', 53 | accounts: { 54 | mnemonic: getAccountMnemonic(), 55 | }, 56 | } 57 | } 58 | } 59 | 60 | // Tasks 61 | 62 | task('accounts', 'Prints the list of accounts', async (taskArgs, bre) => { 63 | const accounts = await bre.ethers.getSigners() 64 | for (const account of accounts) { 65 | console.log(await account.getAddress()) 66 | } 67 | }) 68 | 69 | // Config 70 | 71 | const config: HardhatUserConfig = { 72 | paths: { 73 | sources: './contracts', 74 | tests: './test', 75 | artifacts: './build/contracts', 76 | }, 77 | solidity: { 78 | compilers: [ 79 | { 80 | version: '0.8.15', 81 | settings: { 82 | optimizer: { 83 | enabled: true, 84 | runs: 200, 85 | }, 86 | outputSelection: { 87 | '*': { 88 | '*': ['storageLayout'], 89 | }, 90 | }, 91 | }, 92 | }, 93 | ], 94 | }, 95 | defaultNetwork: 'hardhat', 96 | networks: { 97 | hardhat: { 98 | chainId: 1337, 99 | loggingEnabled: false, 100 | gas: 12000000, 101 | gasPrice: 'auto', 102 | blockGasLimit: 12000000, 103 | accounts: { 104 | mnemonic: 'myth like bonus scare over problem client lizard pioneer submit female collect', 105 | }, 106 | }, 107 | ganache: { 108 | chainId: 1337, 109 | url: 'http://localhost:8545', 110 | }, 111 | }, 112 | etherscan: { 113 | apiKey: process.env.ETHERSCAN_API_KEY, 114 | }, 115 | gasReporter: { 116 | enabled: process.env.REPORT_GAS ? true : false, 117 | showTimeSpent: true, 118 | currency: 'USD', 119 | outputFile: 'reports/gas-report.log', 120 | }, 121 | typechain: { 122 | outDir: 'build/types', 123 | target: 'ethers-v5', 124 | }, 125 | abiExporter: { 126 | path: './build/abis', 127 | clear: false, 128 | flat: true, 129 | }, 130 | tenderly: { 131 | project: process.env.TENDERLY_PROJECT, 132 | username: process.env.TENDERLY_USERNAME, 133 | }, 134 | contractSizer: { 135 | alphaSort: true, 136 | runOnCompile: false, 137 | disambiguatePaths: true, 138 | }, 139 | } 140 | 141 | setupDefaultNetworkProviders(config) 142 | 143 | export default config 144 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solidity-starter", 3 | "version": "0.1.0", 4 | "description": "Solidity starter", 5 | "main": "index.js", 6 | "scripts": { 7 | "prepublishOnly": "scripts/prepublish", 8 | "build": "scripts/build", 9 | "clean": "rm -rf build/ cache/ dist/", 10 | "compile": "hardhat compile", 11 | "test": "scripts/test", 12 | "test:gas": "RUN_EVM=true REPORT_GAS=true scripts/test", 13 | "test:coverage": "scripts/coverage", 14 | "lint": "npm run lint:ts && npm run lint:sol", 15 | "lint:fix": "npm run lint:ts:fix && npm run lint:sol:fix", 16 | "lint:ts": "eslint '*/**/*.{js,ts}'", 17 | "lint:ts:fix": "eslint '*/**/*.{js,ts}' --fix", 18 | "lint:sol": "solium --dir ./contracts", 19 | "lint:sol:fix": "solium --dir ./contracts --fix", 20 | "prettier": "npm run prettier:ts && npm run prettier:sol", 21 | "prettier:ts": "prettier --write 'test/**/*.ts'", 22 | "prettier:sol": "prettier --write 'contracts/*.sol'", 23 | "security": "scripts/security", 24 | "flatten": "scripts/flatten", 25 | "verify": "hardhat verify" 26 | }, 27 | "files": [ 28 | "dist/**/*", 29 | "README.md", 30 | "LICENSE" 31 | ], 32 | "author": "Ariel Barmat", 33 | "license": "MIT", 34 | "devDependencies": { 35 | "@nomiclabs/hardhat-ethers": "^2.1.1", 36 | "@nomiclabs/hardhat-etherscan": "^3.1.0", 37 | "@nomiclabs/hardhat-waffle": "^2.0.3", 38 | "@openzeppelin/hardhat-upgrades": "^1.21.0", 39 | "@tenderly/hardhat-tenderly": "^1.1.6", 40 | "@typechain/ethers-v5": "^10.1.0", 41 | "@typechain/hardhat": "^6.1.3", 42 | "@types/mocha": "^10.0.0", 43 | "@types/node": "^18.7.23", 44 | "@typescript-eslint/eslint-plugin": "^5.38.1", 45 | "@typescript-eslint/parser": "^5.38.1", 46 | "chai": "^4.3.6", 47 | "dotenv": "^16.0.3", 48 | "eslint": "^8.24.0", 49 | "eslint-config-prettier": "^8.5.0", 50 | "eslint-config-standard": "^17.0.0", 51 | "eslint-plugin-import": "^2.26.0", 52 | "eslint-plugin-mocha-no-only": "^1.1.1", 53 | "eslint-plugin-node": "^11.1.0", 54 | "eslint-plugin-prettier": "^4.2.1", 55 | "eslint-plugin-promise": "^6.0.1", 56 | "eslint-plugin-standard": "^5.0.0", 57 | "ethereum-waffle": "^3.4.4", 58 | "ethers": "^5.7.1", 59 | "ethlint": "^1.2.5", 60 | "hardhat": "2.11.2", 61 | "hardhat-abi-exporter": "^2.10.0", 62 | "hardhat-contract-sizer": "^2.6.1", 63 | "hardhat-gas-reporter": "1.0.9", 64 | "prettier": "^2.7.1", 65 | "prettier-plugin-solidity": "1.0.0-beta.24", 66 | "solidity-coverage": "^0.8.2", 67 | "truffle-flattener": "^1.6.0", 68 | "ts-node": "^10.9.1", 69 | "typechain": "^8.1.0", 70 | "typescript": "^4.8.4" 71 | }, 72 | "dependencies": { 73 | "@openzeppelin/contracts": "^4.7.3" 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /scripts/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | # Build 6 | yarn compile -------------------------------------------------------------------------------- /scripts/coverage: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | yarn compile 6 | npx hardhat coverage $@ -------------------------------------------------------------------------------- /scripts/deploy.ts: -------------------------------------------------------------------------------- 1 | import '@nomiclabs/hardhat-ethers' 2 | import { ethers } from 'hardhat' 3 | 4 | async function main() { 5 | const factory = await ethers.getContractFactory('SimpleToken') 6 | 7 | // If we had constructor arguments, they would be passed into deploy() 8 | const contract = await factory.deploy() 9 | 10 | // The address the Contract WILL have once mined 11 | console.log(contract.address) 12 | 13 | // The transaction that was sent to the network to deploy the Contract 14 | console.log(contract.deployTransaction.hash) 15 | 16 | // The contract is NOT deployed yet; we must wait until it is mined 17 | await contract.deployed() 18 | } 19 | 20 | main() 21 | .then(() => process.exit(0)) 22 | .catch((error) => { 23 | console.error(error) 24 | process.exit(1) 25 | }) 26 | -------------------------------------------------------------------------------- /scripts/flatten: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | OUT_DIR="build/flatten" 4 | 5 | mkdir -p ${OUT_DIR} 6 | 7 | echo "Flattening contracts..." 8 | 9 | FILES=( 10 | "contracts/SimpleToken.sol" 11 | "contracts/Counter.sol" 12 | ) 13 | 14 | for path in ${FILES[@]}; do 15 | IFS='/' 16 | parts=( $path ) 17 | name=${parts[${#parts[@]}-1]} 18 | echo "Flatten > ${name}" 19 | hardhat flatten "${path}" > "${OUT_DIR}/${name}" 20 | done 21 | 22 | echo "Done!" 23 | -------------------------------------------------------------------------------- /scripts/prepublish: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TYPECHAIN_DIR=dist/types 4 | 5 | set -eo pipefail 6 | 7 | # Build contracts 8 | yarn clean 9 | yarn build 10 | 11 | # Refresh distribution folder 12 | rm -rf dist && mkdir -p dist/types/_src 13 | cp -R build/abis/ dist/abis 14 | cp -R build/types/ dist/types/_src 15 | 16 | ### Build Typechain bindings 17 | 18 | # Build and create TS declarations 19 | tsc -d ${TYPECHAIN_DIR}/_src/*.ts --outdir ${TYPECHAIN_DIR} 20 | # Copy back sources 21 | cp ${TYPECHAIN_DIR}/_src/*.ts ${TYPECHAIN_DIR} 22 | # Delete temporary src dir 23 | rm -rf ${TYPECHAIN_DIR}/_src -------------------------------------------------------------------------------- /scripts/security: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## Before running: 4 | # This tool requires to have solc installed. 5 | # Ensure that you have the binaries installed by pip3 in your path. 6 | # Install: https://github.com/crytic/slither#how-to-install 7 | # Usage: https://github.com/crytic/slither/wiki/Usage 8 | 9 | mkdir -p reports 10 | 11 | pip3 install --user slither-analyzer && \ 12 | yarn build && \ 13 | 14 | echo "Analyzing contracts..." 15 | slither . &> reports/analyzer-report.log && \ 16 | 17 | echo "Done!" 18 | -------------------------------------------------------------------------------- /scripts/test: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eo pipefail 4 | 5 | MNEMONIC="myth like bonus scare over problem client lizard pioneer submit female collect" 6 | TESTRPC_PORT=8545 7 | 8 | ### Functions 9 | 10 | evm_running() { 11 | nc -z localhost "$TESTRPC_PORT" 12 | } 13 | 14 | evm_start() { 15 | echo "Starting our own evm instance at port $TESTRPC_PORT" 16 | npx hardhat node --port "$TESTRPC_PORT" > /dev/null & 17 | } 18 | 19 | evm_kill() { 20 | if evm_running; then 21 | echo "Killing evm instance at port $TESTRPC_PORT" 22 | kill -9 $(lsof -i:$TESTRPC_PORT -t) 23 | fi 24 | } 25 | 26 | ### Setup EVM 27 | 28 | # Ensure we compiled sources 29 | 30 | yarn build 31 | 32 | # Gas reporter needs to run in its own evm instance 33 | if [ "$RUN_EVM" = true ]; then 34 | evm_kill 35 | evm_start 36 | sleep 5 37 | fi 38 | 39 | ### Main 40 | 41 | mkdir -p reports 42 | 43 | # Run using the standalone evm instance 44 | npx hardhat test --network hardhat 45 | 46 | ### Cleanup 47 | 48 | # Exit error mode so the evm instance always gets killed 49 | set +e 50 | result=0 51 | 52 | if [ "$RUN_EVM" = true ]; then 53 | evm_kill 54 | fi 55 | 56 | exit $result 57 | -------------------------------------------------------------------------------- /test/counter.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai' 2 | import { ethers } from 'hardhat' 3 | import '@nomiclabs/hardhat-ethers' 4 | 5 | import { Counter__factory, Counter } from '../build/types' 6 | 7 | const { getContractFactory, getSigners } = ethers 8 | 9 | describe('Counter', () => { 10 | let counter: Counter 11 | 12 | beforeEach(async () => { 13 | // 1 14 | const signers = await getSigners() 15 | 16 | // 2 17 | const counterFactory = (await getContractFactory('Counter', signers[0])) as Counter__factory 18 | counter = await counterFactory.deploy() 19 | await counter.deployed() 20 | const initialCount = await counter.getCount() 21 | 22 | // 3 23 | expect(initialCount).to.eq(0) 24 | expect(counter.address).to.properAddress 25 | }) 26 | 27 | // 4 28 | describe('count up', async () => { 29 | it('should count up', async () => { 30 | await counter.countUp() 31 | const count = await counter.getCount() 32 | expect(count).to.eq(1) 33 | }) 34 | }) 35 | 36 | describe('count down', async () => { 37 | // 5 38 | it('should fail due to underflow exception', async () => { 39 | const tx = counter.countDown() 40 | await expect(tx).revertedWith( 41 | 'VM Exception while processing transaction: reverted with panic code 0x11 (Arithmetic operation underflowed or overflowed outside of an unchecked block)', 42 | ) 43 | }) 44 | 45 | it('should count down', async () => { 46 | await counter.countUp() 47 | 48 | await counter.countDown() 49 | const count = await counter.getCount() 50 | expect(count).to.eq(0) 51 | }) 52 | }) 53 | }) 54 | -------------------------------------------------------------------------------- /test/simpletoken.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai' 2 | import { ethers } from 'hardhat' 3 | import '@nomiclabs/hardhat-ethers' 4 | 5 | import { SimpleToken, SimpleToken__factory } from '../build/types' 6 | import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' 7 | import { BigNumber } from 'ethers' 8 | 9 | const { getContractFactory, getSigners } = ethers 10 | 11 | describe('SimpleToken', () => { 12 | let simpleToken: SimpleToken 13 | let signers: SignerWithAddress[] 14 | const initialSupply = BigNumber.from('18000000000000000000') 15 | beforeEach(async () => { 16 | // 1 17 | signers = await getSigners() 18 | 19 | // 2 20 | const simpleTokenFactory = (await getContractFactory('SimpleToken', signers[0])) as SimpleToken__factory 21 | simpleToken = await simpleTokenFactory.deploy() 22 | await simpleToken.deployed() 23 | const initialCount = await simpleToken.totalSupply() 24 | 25 | // 3 26 | expect(initialCount).to.eq(initialSupply) 27 | 28 | expect(simpleToken.address).to.properAddress 29 | }) 30 | 31 | // 4 32 | describe('transfer', async () => { 33 | it('should transfer', async () => { 34 | await simpleToken.transfer(signers[1].address, BigNumber.from('200')) 35 | const expectedBalance = BigNumber.from('200') 36 | expect(await simpleToken.balanceOf(signers[1].address)).to.eq(expectedBalance) 37 | }) 38 | }) 39 | }) 40 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["ES2018", "dom"], 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "target": "ES2018", 7 | "outDir": "dist", 8 | "resolveJsonModule": true, 9 | "esModuleInterop": true 10 | }, 11 | "exclude": ["dist", "node_modules"], 12 | "files": [ 13 | "./hardhat.config.ts", 14 | "./scripts/**/*.ts", 15 | "./test/**/*.ts", 16 | "node_modules/@nomiclabs/hardhat-ethers/internal/type-extensions.d.ts", 17 | "node_modules/@nomiclabs/hardhat-etherscan/dist/src/type-extensions.d.ts", 18 | "node_modules/@nomiclabs/hardhat-waffle/dist/src/type-extensions.d.ts", 19 | "node_modules/@typechain/hardhat/dist/type-extensions.d.ts", 20 | "./index.d.ts" 21 | ] 22 | } 23 | --------------------------------------------------------------------------------