├── .gitignore ├── .vscode └── settings.json ├── README.md ├── homework_01 └── Score.sol ├── homework_03 ├── Homework_3.pdf └── VolcanoCoin.sol ├── homework_04 ├── Homework_4.pdf └── VolcanoCoin.sol ├── homework_05 ├── Homework_5.pdf └── VolcanoCoin.sol ├── homework_06 ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── .prettierignore ├── .solhint.json ├── .solhintignore ├── Homework_6.pdf ├── README.md ├── contracts │ └── VolcanoCoin.sol ├── hardhat.config.ts ├── package-lock.json ├── package.json ├── tsconfig.json ├── typechain │ ├── ERC165.d.ts │ ├── ERC721.d.ts │ ├── IERC165.d.ts │ ├── IERC721.d.ts │ ├── IERC721Metadata.d.ts │ ├── IERC721Receiver.d.ts │ ├── Ownable.d.ts │ ├── VolcanoCoin.d.ts │ ├── common.d.ts │ ├── factories │ │ ├── ERC165__factory.ts │ │ ├── ERC721__factory.ts │ │ ├── IERC165__factory.ts │ │ ├── IERC721Metadata__factory.ts │ │ ├── IERC721Receiver__factory.ts │ │ ├── IERC721__factory.ts │ │ ├── Ownable__factory.ts │ │ └── VolcanoCoin__factory.ts │ ├── hardhat.d.ts │ └── index.ts └── yarn.lock ├── homework_07 ├── .eslintrc.js ├── .gitignore ├── Homework_7.pdf ├── build.ts ├── package-lock.json ├── package.json ├── src │ ├── Server.ts │ ├── exceptions │ │ └── HttpException.ts │ ├── index.ts │ ├── middlewares │ │ └── error.middleware.ts │ ├── pre-start │ │ ├── env │ │ │ ├── development.env │ │ │ ├── production.env │ │ │ └── test.env │ │ └── index.ts │ ├── public │ │ ├── scripts │ │ │ └── index.js │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.ts │ │ └── storage.controller.ts │ ├── services │ │ └── storage.service.ts │ ├── shared │ │ ├── Logger.ts │ │ └── constants.ts │ └── views │ │ ├── index.html │ │ └── ”https: │ │ └── bundle.run │ │ └── buffer@5.2.1 ├── tsconfig.json └── tsconfig.prod.json ├── homework_08 ├── Homework_8.pdf ├── contracts │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .npmignore │ ├── .prettierignore │ ├── README.md │ ├── cache │ │ ├── solidity-files-cache.json │ │ └── validations.json │ ├── contracts │ │ └── VolcanoCoin.sol │ ├── hardhat.config.ts │ ├── package-lock.json │ ├── package.json │ ├── scripts │ │ └── deploy.ts │ ├── test │ │ └── index.ts │ └── tsconfig.json ├── homework_08.pdf └── web │ ├── .eslintrc.js │ ├── .gitignore │ ├── build.ts │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── Server.ts │ ├── exceptions │ │ └── HttpException.ts │ ├── index.ts │ ├── middlewares │ │ └── error.middleware.ts │ ├── pre-start │ │ ├── env │ │ │ ├── development.env │ │ │ ├── production.env │ │ │ └── test.env │ │ └── index.ts │ ├── public │ │ ├── scripts │ │ │ ├── bundle.js │ │ │ └── index.js │ │ └── stylesheets │ │ │ └── style.css │ ├── routes │ │ ├── index.ts │ │ └── storage.controller.ts │ ├── services │ │ └── storage.service.ts │ ├── shared │ │ ├── Logger.ts │ │ └── constants.ts │ ├── utils │ │ └── contract.js │ └── views │ │ ├── index.html │ │ └── ”https: │ │ └── bundle.run │ │ └── buffer@5.2.1 │ ├── tsconfig.json │ └── tsconfig.prod.json ├── homework_09 ├── .gitignore ├── Homework_9.pdf ├── README.md ├── contracts │ └── VolcanoCoin.sol ├── hardhat.config.js ├── package-lock.json ├── package.json ├── scripts │ └── sample-script.js └── test │ └── volcano.test.js ├── homework_10 ├── .gitignore ├── Homework_10.pdf ├── contracts │ └── VolcanoCoin.sol ├── hardhat.config.js ├── package-lock.json ├── package.json ├── scripts │ ├── deploy.js │ └── tests.js └── test │ └── volcano.test.js ├── homework_11 ├── Level_0.sol ├── Level_1.sol ├── Level_2.sol └── Level_3.sol ├── homework_12 ├── .gitignore ├── .openzeppelin │ └── unknown-31337.json ├── Homework_12.pdf ├── contracts │ ├── VolcanoCoin.sol │ └── VolcanoCoinV2.sol ├── hardhat.config.js ├── package-lock.json ├── package.json ├── scripts │ ├── 00_deploy_v1.js │ └── 01_deploy_v2.js └── test │ └── volcano.test.js ├── homework_13 ├── .gitignore ├── Homework_13.pdf ├── README.md ├── contracts │ └── DeFi.sol ├── hardhat.config.js ├── package-lock.json ├── package.json ├── scripts │ └── sample-script.js └── test │ └── DeFI.test.js └── homework_14 ├── .env.example ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .npmignore ├── .prettierignore ├── .solhint.json ├── .solhintignore ├── README.md ├── contracts ├── Compound.sol └── interfaces │ ├── CERC20.sol │ └── IERC20.sol ├── hardhat.config.ts ├── package-lock.json ├── package.json ├── scripts └── deploy.ts ├── test └── index.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | **/artifacts 3 | .env 4 | .DS_Store 5 | **/**/node_modules -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/.git": true, 4 | "**/.svn": true, 5 | "**/.hg": true, 6 | "**/CVS": true, 7 | "**/.DS_Store": true, 8 | "**/Thumbs.db": true, 9 | "**/.cache": true, 10 | "**/.vs/": true, 11 | "**/*.cs": true, 12 | "**/*.orig": true, 13 | "**/bin/": true, 14 | "**/build/": true, 15 | "**/build/**/*": true, 16 | "**/debug/": true, 17 | "**/dist/": true, 18 | "**/obj": true, 19 | "**/node_modules": true, 20 | "yarn-error.log": true, 21 | "**/yarn-error.log": true, 22 | "packages\\eth-hooks/lib": true, 23 | "**/.yalc": true 24 | }, 25 | "search.exclude": { 26 | "**/.git": true, 27 | "**/.svn": true, 28 | "**/.hg": true, 29 | "**/CVS": true, 30 | "**/.DS_Store": true, 31 | "**/Thumbs.db": true, 32 | "**/.cache": true, 33 | "**/.vs/": true, 34 | "**/*.cs": true, 35 | "**/*.orig": true, 36 | "**/bin/": true, 37 | "**/build/": true, 38 | "**/build/**/*": true, 39 | "**/debug/": true, 40 | "**/dist/": true, 41 | // "**/node_modules/": true, 42 | "**/obj": true, 43 | // "node_modules": true, 44 | // "node_modules/*/**": true, 45 | // "**/node_modules": true, 46 | "yarn-error.log": true, 47 | "**/yarn-error.log": true, 48 | "**/.yalc": true 49 | }, 50 | "solidity.packageDefaultDependenciesDirectory": "homework_12/node_modules", 51 | "editor.formatOnSave": true, 52 | "solidity.formatter": "prettier", 53 | "[solidity]": { 54 | "editor.defaultFormatter": "JuanBlanco.solidity" 55 | }, 56 | "solidity.defaultCompiler": "localNodeModule" 57 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Encode Club - Solidity bootcamp 2 | 3 | A 12 week bootcamp by [Encode club](https://www.encode.club/) 4 | 5 | This repo contains all my solutions for Encode bootcamp homework 6 | 7 | - [x] 1. Score contract 8 | - [x] 2. Etherscan explorer 9 | - [x] 3. VolcanoCoin ERC20 10 | - [x] 4. VolcanoCoin added functionality (payment record, events) 11 | - [x] 5. Add OpenZepplin contracts to VolcanoCoin 12 | - [x] 6. Create ERC721 contract 13 | - [x] 7. Decentralised Storage 14 | - [x] 8. NFT UI 15 | - [x] 9. Unit tests 16 | - [x] 10. Extra functionality to VolcanoCoin 17 | - [x] 11. Hack the levels - solidity security 18 | - [x] 12. Upgradeable contracts with proxy 19 | - [x] 13. DeFi interactions 20 | - [x] 14. Interacting with compound and Chainlink data feeds 21 | - [x] 16-A. Subgraph 22 | - [ ] 16-B. Chainlink 23 | - [ ] 18. Debbug opcodes 24 | -------------------------------------------------------------------------------- /homework_01/Score.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: CC-BY-SA-4.0 2 | // Version of Solidity compiler this program was written for 3 | pragma solidity ^0.8.0; 4 | 5 | contract Score { 6 | 7 | address owner; 8 | uint score; 9 | mapping(address => uint) public score_list; 10 | 11 | event NewUserScore(address _user, uint _newScore); 12 | event NewScore(uint _newScore); 13 | 14 | constructor() { 15 | owner = msg.sender; 16 | } 17 | 18 | modifier onlyOwner { 19 | if(msg.sender == owner) { 20 | _; 21 | } 22 | } 23 | 24 | function getScore() public view returns (uint) { 25 | return score; 26 | } 27 | 28 | function setScore(uint _newScore) public onlyOwner { 29 | score = _newScore; 30 | emit NewScore(score); 31 | } 32 | 33 | function setUserScore(address _user, uint _newScore) public onlyOwner { 34 | score_list[_user] = _newScore; 35 | emit NewUserScore(_user, _newScore); 36 | } 37 | } 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /homework_03/Homework_3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anajuliabit/bootcamp-solidity/4f1352e9ddf6184b8637a5bea2856f73527af356/homework_03/Homework_3.pdf -------------------------------------------------------------------------------- /homework_03/VolcanoCoin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | // Version of Solidity compiler this program was written for 3 | pragma solidity ^0.8.0; 4 | 5 | contract VolcanoCoin { 6 | 7 | uint total_supply; 8 | address owner; 9 | 10 | event NewSupply(uint _newSupply); 11 | 12 | modifier onlyOwner { 13 | if(msg.sender == owner) { 14 | _; 15 | } 16 | } 17 | 18 | constructor() { 19 | owner = msg.sender; 20 | total_supply = 10000; 21 | } 22 | 23 | function increaseSupply() public onlyOwner { 24 | total_supply += 1000; 25 | emit NewSupply(total_supply); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /homework_04/Homework_4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anajuliabit/bootcamp-solidity/4f1352e9ddf6184b8637a5bea2856f73527af356/homework_04/Homework_4.pdf -------------------------------------------------------------------------------- /homework_04/VolcanoCoin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | // Version of Solidity compiler this program was written for 3 | pragma solidity ^0.8.0; 4 | 5 | contract VolcanoCoin { 6 | 7 | uint256 total_supply; 8 | address owner; 9 | mapping(address => uint256) public balances; 10 | mapping(address => Payment[]) public payments; 11 | 12 | event NewSupply(uint256 _newSupply); 13 | event Transfer(address recipient, uint256 amount); 14 | 15 | struct Payment { 16 | address recipient; 17 | uint256 amount; 18 | } 19 | 20 | modifier onlyOwner { 21 | if(msg.sender == owner) { 22 | _; 23 | } 24 | } 25 | 26 | constructor() { 27 | owner = msg.sender; 28 | total_supply = 10000; 29 | balances[owner] = total_supply; 30 | } 31 | 32 | function increaseSupply() public onlyOwner { 33 | total_supply += 1000; 34 | balances[owner] += 1000; 35 | emit NewSupply(total_supply); 36 | } 37 | 38 | function transfer(address _recipient, uint256 _amount) public { 39 | require(balances[msg.sender] >= _amount, "Insufficient funds"); 40 | balances[msg.sender] -= _amount; 41 | balances[_recipient] += _amount; 42 | 43 | payments[msg.sender].push(Payment({ recipient: _recipient, amount: _amount})); 44 | 45 | emit Transfer(_recipient, _amount); 46 | } 47 | 48 | function getPayments(address _sender) public view returns(Payment[] memory) { 49 | return payments[_sender]; 50 | } 51 | } -------------------------------------------------------------------------------- /homework_05/Homework_5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anajuliabit/bootcamp-solidity/4f1352e9ddf6184b8637a5bea2856f73527af356/homework_05/Homework_5.pdf -------------------------------------------------------------------------------- /homework_05/VolcanoCoin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | // Version of Solidity compiler this program was written for 3 | pragma solidity ^0.8.0; 4 | 5 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 6 | import "@openzeppelin/contracts/access/Ownable.sol"; 7 | 8 | contract VolcanoCoin is ERC20, Ownable { 9 | 10 | mapping(address => Payment[]) payments; 11 | 12 | struct Payment { 13 | address recipient; 14 | uint256 amount; 15 | } 16 | 17 | constructor() ERC20("VolcanoCoin", "VOLC") { 18 | _mint(_msgSender(), 10000); 19 | } 20 | 21 | function mintToOwner(uint256 _amount) public onlyOwner { 22 | _mint(_msgSender(), _amount); 23 | } 24 | 25 | function transfer(address recipient, uint256 _amount) public override returns (bool) { 26 | _transfer(_msgSender(), recipient, _amount); 27 | addPayment(_msgSender(), recipient, _amount); 28 | return true; 29 | } 30 | 31 | function addPayment(address _sender, address _receiver, uint256 _amount) internal { 32 | payments[_sender].push(Payment(_receiver, _amount)); 33 | } 34 | 35 | function getPayments(address _user) public view returns(Payment[] memory) { 36 | return payments[_user]; 37 | } 38 | } -------------------------------------------------------------------------------- /homework_06/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | artifacts 3 | cache 4 | coverage 5 | -------------------------------------------------------------------------------- /homework_06/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: false, 4 | es2021: true, 5 | mocha: true, 6 | node: true, 7 | }, 8 | plugins: ["@typescript-eslint"], 9 | extends: [ 10 | "standard", 11 | "plugin:prettier/recommended", 12 | "plugin:node/recommended", 13 | ], 14 | parser: "@typescript-eslint/parser", 15 | parserOptions: { 16 | ecmaVersion: 12, 17 | }, 18 | rules: { 19 | "node/no-unsupported-features/es-syntax": [ 20 | "error", 21 | { ignores: ["modules"] }, 22 | ], 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /homework_06/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | cache/* -------------------------------------------------------------------------------- /homework_06/.npmignore: -------------------------------------------------------------------------------- 1 | hardhat.config.ts 2 | scripts 3 | test 4 | -------------------------------------------------------------------------------- /homework_06/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | artifacts 3 | cache 4 | coverage* 5 | gasReporterOutput.json 6 | -------------------------------------------------------------------------------- /homework_06/.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:recommended", 3 | "rules": { 4 | "compiler-version": ["error", "^0.8.0"], 5 | "func-visibility": ["warn", { "ignoreConstructors": true }] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /homework_06/.solhintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /homework_06/Homework_6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anajuliabit/bootcamp-solidity/4f1352e9ddf6184b8637a5bea2856f73527af356/homework_06/Homework_6.pdf -------------------------------------------------------------------------------- /homework_06/README.md: -------------------------------------------------------------------------------- 1 | # Advanced Sample Hardhat Project 2 | 3 | This project demonstrates an advanced Hardhat use case, integrating other tools commonly used alongside Hardhat in the ecosystem. 4 | 5 | The project comes with a sample contract, a test for that contract, a sample script that deploys that contract, and an example of a task implementation, which simply lists the available accounts. It also comes with a variety of other tools, preconfigured to work with the project code. 6 | 7 | Try running some of the following tasks: 8 | 9 | ```shell 10 | npx hardhat accounts 11 | npx hardhat compile 12 | npx hardhat clean 13 | npx hardhat test 14 | npx hardhat node 15 | npx hardhat help 16 | REPORT_GAS=true npx hardhat test 17 | npx hardhat coverage 18 | npx hardhat run scripts/deploy.ts 19 | TS_NODE_FILES=true npx ts-node scripts/deploy.ts 20 | npx eslint '**/*.{js,ts}' 21 | npx eslint '**/*.{js,ts}' --fix 22 | npx prettier '**/*.{json,sol,md}' --check 23 | npx prettier '**/*.{json,sol,md}' --write 24 | npx solhint 'contracts/**/*.sol' 25 | npx solhint 'contracts/**/*.sol' --fix 26 | ``` 27 | 28 | # Etherscan verification 29 | 30 | To try out Etherscan verification, you first need to deploy a contract to an Ethereum network that's supported by Etherscan, such as Ropsten. 31 | 32 | In this project, copy the .env.example file to a file named .env, and then edit it to fill in the details. Enter your Etherscan API key, your Ropsten node URL (eg from Alchemy), and the private key of the account which will send the deployment transaction. With a valid .env file in place, first deploy your contract: 33 | 34 | ```shell 35 | hardhat run --network ropsten scripts/sample-script.ts 36 | ``` 37 | 38 | Then, copy the deployment address and paste it in to replace `DEPLOYED_CONTRACT_ADDRESS` in this command: 39 | 40 | ```shell 41 | npx hardhat verify --network ropsten DEPLOYED_CONTRACT_ADDRESS "Hello, Hardhat!" 42 | ``` 43 | 44 | # Performance optimizations 45 | 46 | For faster runs of your tests and scripts, consider skipping ts-node's type checking by setting the environment variable `TS_NODE_TRANSPILE_ONLY` to `1` in hardhat's environment. For more details see [the documentation](https://hardhat.org/guides/typescript.html#performance-optimizations). 47 | -------------------------------------------------------------------------------- /homework_06/contracts/VolcanoCoin.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: Unlicense 2 | pragma solidity ^0.8.4; 3 | 4 | import "hardhat/console.sol"; 5 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 6 | import "@openzeppelin/contracts/access/Ownable.sol"; 7 | 8 | contract VolcanoCoin is ERC721, Ownable { 9 | struct Token { 10 | uint256 tokenId; 11 | uint256 timestamp; 12 | string tokenURI; 13 | } 14 | 15 | uint256 token_id; 16 | mapping(address => Token[]) user_tokens; 17 | uint token_counter; 18 | 19 | constructor() ERC721('VolcanoCoin', 'VLC') { 20 | token_counter = 0; 21 | } 22 | 23 | function mint(string memory _tokenURI) public { 24 | Token memory token = Token(token_counter, block.timestamp, _tokenURI); 25 | user_tokens[_msgSender()].push(token); 26 | 27 | _safeMint(_msgSender(), token_counter); 28 | 29 | token_counter += 1; 30 | } 31 | 32 | function burn(uint256 _tokenId) public { 33 | _burn(_tokenId); 34 | deleteToken(_tokenId); 35 | } 36 | 37 | function deleteToken(uint256 _tokenId) internal { 38 | for(uint i = 0; i < user_tokens[_msgSender()].length; i++) { 39 | if(user_tokens[_msgSender()][i].tokenId == _tokenId) { 40 | delete user_tokens[_msgSender()][i]; 41 | break; 42 | } 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /homework_06/hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import * as dotenv from "dotenv"; 2 | 3 | import { HardhatUserConfig, task } from "hardhat/config"; 4 | import "@nomiclabs/hardhat-etherscan"; 5 | import "@nomiclabs/hardhat-waffle"; 6 | import "@typechain/hardhat"; 7 | import "hardhat-gas-reporter"; 8 | import "solidity-coverage"; 9 | import "@openzeppelin/hardhat-upgrades"; 10 | 11 | dotenv.config(); 12 | 13 | // This is a sample Hardhat task. To learn how to create your own go to 14 | // https://hardhat.org/guides/create-task.html 15 | task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { 16 | const accounts = await hre.ethers.getSigners(); 17 | 18 | for (const account of accounts) { 19 | console.log(account.address); 20 | } 21 | }); 22 | 23 | // You need to export an object to set up your config 24 | // Go to https://hardhat.org/config/ to learn more 25 | 26 | const config: HardhatUserConfig = { 27 | solidity: "0.8.4", 28 | networks: { 29 | hardhat: { 30 | chainId: 1337, 31 | }, 32 | ropsten: { 33 | url: process.env.ROPSTEN_URL || "", 34 | accounts: 35 | process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 36 | }, 37 | }, 38 | gasReporter: { 39 | enabled: process.env.REPORT_GAS !== undefined, 40 | currency: "USD", 41 | }, 42 | etherscan: { 43 | apiKey: process.env.ETHERSCAN_API_KEY, 44 | }, 45 | }; 46 | 47 | export default config; 48 | -------------------------------------------------------------------------------- /homework_06/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hardhat-project", 3 | "devDependencies": { 4 | "@nomiclabs/hardhat-ethers": "^2.0.2", 5 | "@nomiclabs/hardhat-etherscan": "^2.1.7", 6 | "@nomiclabs/hardhat-waffle": "^2.0.1", 7 | "@typechain/ethers-v5": "^7.2.0", 8 | "@typechain/hardhat": "^2.3.1", 9 | "@types/chai": "^4.2.22", 10 | "@types/mocha": "^9.0.0", 11 | "@types/node": "^16.11.7", 12 | "@typescript-eslint/eslint-plugin": "^4.33.0", 13 | "@typescript-eslint/parser": "^4.33.0", 14 | "chai": "^4.3.4", 15 | "dotenv": "^10.0.0", 16 | "eslint": "^7.32.0", 17 | "eslint-config-prettier": "^8.3.0", 18 | "eslint-config-standard": "^16.0.3", 19 | "eslint-plugin-import": "^2.25.3", 20 | "eslint-plugin-node": "^11.1.0", 21 | "eslint-plugin-prettier": "^3.4.1", 22 | "eslint-plugin-promise": "^5.1.1", 23 | "ethereum-waffle": "^3.4.0", 24 | "ethers": "^5.5.1", 25 | "hardhat": "^2.6.8", 26 | "hardhat-gas-reporter": "^1.0.4", 27 | "prettier": "^2.4.1", 28 | "prettier-plugin-solidity": "^1.0.0-beta.19", 29 | "solhint": "^3.3.6", 30 | "solidity-coverage": "^0.7.17", 31 | "ts-node": "^10.4.0", 32 | "typechain": "^5.2.0", 33 | "typescript": "^4.5.2" 34 | }, 35 | "dependencies": { 36 | "@openzeppelin/contracts": "^4.3.3", 37 | "@openzeppelin/hardhat-upgrades": "^1.12.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /homework_06/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2018", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "outDir": "dist", 8 | "declaration": true 9 | }, 10 | "include": ["./scripts", "./test", "./typechain"], 11 | "files": ["./hardhat.config.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /homework_06/typechain/ERC165.d.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | 5 | import { 6 | ethers, 7 | EventFilter, 8 | Signer, 9 | BigNumber, 10 | BigNumberish, 11 | PopulatedTransaction, 12 | BaseContract, 13 | ContractTransaction, 14 | CallOverrides, 15 | } from "ethers"; 16 | import { BytesLike } from "@ethersproject/bytes"; 17 | import { Listener, Provider } from "@ethersproject/providers"; 18 | import { FunctionFragment, EventFragment, Result } from "@ethersproject/abi"; 19 | import type { TypedEventFilter, TypedEvent, TypedListener } from "./common"; 20 | 21 | interface ERC165Interface extends ethers.utils.Interface { 22 | functions: { 23 | "supportsInterface(bytes4)": FunctionFragment; 24 | }; 25 | 26 | encodeFunctionData( 27 | functionFragment: "supportsInterface", 28 | values: [BytesLike] 29 | ): string; 30 | 31 | decodeFunctionResult( 32 | functionFragment: "supportsInterface", 33 | data: BytesLike 34 | ): Result; 35 | 36 | events: {}; 37 | } 38 | 39 | export class ERC165 extends BaseContract { 40 | connect(signerOrProvider: Signer | Provider | string): this; 41 | attach(addressOrName: string): this; 42 | deployed(): Promise; 43 | 44 | listeners, EventArgsObject>( 45 | eventFilter?: TypedEventFilter 46 | ): Array>; 47 | off, EventArgsObject>( 48 | eventFilter: TypedEventFilter, 49 | listener: TypedListener 50 | ): this; 51 | on, EventArgsObject>( 52 | eventFilter: TypedEventFilter, 53 | listener: TypedListener 54 | ): this; 55 | once, EventArgsObject>( 56 | eventFilter: TypedEventFilter, 57 | listener: TypedListener 58 | ): this; 59 | removeListener, EventArgsObject>( 60 | eventFilter: TypedEventFilter, 61 | listener: TypedListener 62 | ): this; 63 | removeAllListeners, EventArgsObject>( 64 | eventFilter: TypedEventFilter 65 | ): this; 66 | 67 | listeners(eventName?: string): Array; 68 | off(eventName: string, listener: Listener): this; 69 | on(eventName: string, listener: Listener): this; 70 | once(eventName: string, listener: Listener): this; 71 | removeListener(eventName: string, listener: Listener): this; 72 | removeAllListeners(eventName?: string): this; 73 | 74 | queryFilter, EventArgsObject>( 75 | event: TypedEventFilter, 76 | fromBlockOrBlockhash?: string | number | undefined, 77 | toBlock?: string | number | undefined 78 | ): Promise>>; 79 | 80 | interface: ERC165Interface; 81 | 82 | functions: { 83 | supportsInterface( 84 | interfaceId: BytesLike, 85 | overrides?: CallOverrides 86 | ): Promise<[boolean]>; 87 | }; 88 | 89 | supportsInterface( 90 | interfaceId: BytesLike, 91 | overrides?: CallOverrides 92 | ): Promise; 93 | 94 | callStatic: { 95 | supportsInterface( 96 | interfaceId: BytesLike, 97 | overrides?: CallOverrides 98 | ): Promise; 99 | }; 100 | 101 | filters: {}; 102 | 103 | estimateGas: { 104 | supportsInterface( 105 | interfaceId: BytesLike, 106 | overrides?: CallOverrides 107 | ): Promise; 108 | }; 109 | 110 | populateTransaction: { 111 | supportsInterface( 112 | interfaceId: BytesLike, 113 | overrides?: CallOverrides 114 | ): Promise; 115 | }; 116 | } 117 | -------------------------------------------------------------------------------- /homework_06/typechain/IERC165.d.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | 5 | import { 6 | ethers, 7 | EventFilter, 8 | Signer, 9 | BigNumber, 10 | BigNumberish, 11 | PopulatedTransaction, 12 | BaseContract, 13 | ContractTransaction, 14 | CallOverrides, 15 | } from "ethers"; 16 | import { BytesLike } from "@ethersproject/bytes"; 17 | import { Listener, Provider } from "@ethersproject/providers"; 18 | import { FunctionFragment, EventFragment, Result } from "@ethersproject/abi"; 19 | import type { TypedEventFilter, TypedEvent, TypedListener } from "./common"; 20 | 21 | interface IERC165Interface extends ethers.utils.Interface { 22 | functions: { 23 | "supportsInterface(bytes4)": FunctionFragment; 24 | }; 25 | 26 | encodeFunctionData( 27 | functionFragment: "supportsInterface", 28 | values: [BytesLike] 29 | ): string; 30 | 31 | decodeFunctionResult( 32 | functionFragment: "supportsInterface", 33 | data: BytesLike 34 | ): Result; 35 | 36 | events: {}; 37 | } 38 | 39 | export class IERC165 extends BaseContract { 40 | connect(signerOrProvider: Signer | Provider | string): this; 41 | attach(addressOrName: string): this; 42 | deployed(): Promise; 43 | 44 | listeners, EventArgsObject>( 45 | eventFilter?: TypedEventFilter 46 | ): Array>; 47 | off, EventArgsObject>( 48 | eventFilter: TypedEventFilter, 49 | listener: TypedListener 50 | ): this; 51 | on, EventArgsObject>( 52 | eventFilter: TypedEventFilter, 53 | listener: TypedListener 54 | ): this; 55 | once, EventArgsObject>( 56 | eventFilter: TypedEventFilter, 57 | listener: TypedListener 58 | ): this; 59 | removeListener, EventArgsObject>( 60 | eventFilter: TypedEventFilter, 61 | listener: TypedListener 62 | ): this; 63 | removeAllListeners, EventArgsObject>( 64 | eventFilter: TypedEventFilter 65 | ): this; 66 | 67 | listeners(eventName?: string): Array; 68 | off(eventName: string, listener: Listener): this; 69 | on(eventName: string, listener: Listener): this; 70 | once(eventName: string, listener: Listener): this; 71 | removeListener(eventName: string, listener: Listener): this; 72 | removeAllListeners(eventName?: string): this; 73 | 74 | queryFilter, EventArgsObject>( 75 | event: TypedEventFilter, 76 | fromBlockOrBlockhash?: string | number | undefined, 77 | toBlock?: string | number | undefined 78 | ): Promise>>; 79 | 80 | interface: IERC165Interface; 81 | 82 | functions: { 83 | supportsInterface( 84 | interfaceId: BytesLike, 85 | overrides?: CallOverrides 86 | ): Promise<[boolean]>; 87 | }; 88 | 89 | supportsInterface( 90 | interfaceId: BytesLike, 91 | overrides?: CallOverrides 92 | ): Promise; 93 | 94 | callStatic: { 95 | supportsInterface( 96 | interfaceId: BytesLike, 97 | overrides?: CallOverrides 98 | ): Promise; 99 | }; 100 | 101 | filters: {}; 102 | 103 | estimateGas: { 104 | supportsInterface( 105 | interfaceId: BytesLike, 106 | overrides?: CallOverrides 107 | ): Promise; 108 | }; 109 | 110 | populateTransaction: { 111 | supportsInterface( 112 | interfaceId: BytesLike, 113 | overrides?: CallOverrides 114 | ): Promise; 115 | }; 116 | } 117 | -------------------------------------------------------------------------------- /homework_06/typechain/IERC721Receiver.d.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | 5 | import { 6 | ethers, 7 | EventFilter, 8 | Signer, 9 | BigNumber, 10 | BigNumberish, 11 | PopulatedTransaction, 12 | BaseContract, 13 | ContractTransaction, 14 | Overrides, 15 | CallOverrides, 16 | } from "ethers"; 17 | import { BytesLike } from "@ethersproject/bytes"; 18 | import { Listener, Provider } from "@ethersproject/providers"; 19 | import { FunctionFragment, EventFragment, Result } from "@ethersproject/abi"; 20 | import type { TypedEventFilter, TypedEvent, TypedListener } from "./common"; 21 | 22 | interface IERC721ReceiverInterface extends ethers.utils.Interface { 23 | functions: { 24 | "onERC721Received(address,address,uint256,bytes)": FunctionFragment; 25 | }; 26 | 27 | encodeFunctionData( 28 | functionFragment: "onERC721Received", 29 | values: [string, string, BigNumberish, BytesLike] 30 | ): string; 31 | 32 | decodeFunctionResult( 33 | functionFragment: "onERC721Received", 34 | data: BytesLike 35 | ): Result; 36 | 37 | events: {}; 38 | } 39 | 40 | export class IERC721Receiver extends BaseContract { 41 | connect(signerOrProvider: Signer | Provider | string): this; 42 | attach(addressOrName: string): this; 43 | deployed(): Promise; 44 | 45 | listeners, EventArgsObject>( 46 | eventFilter?: TypedEventFilter 47 | ): Array>; 48 | off, EventArgsObject>( 49 | eventFilter: TypedEventFilter, 50 | listener: TypedListener 51 | ): this; 52 | on, EventArgsObject>( 53 | eventFilter: TypedEventFilter, 54 | listener: TypedListener 55 | ): this; 56 | once, EventArgsObject>( 57 | eventFilter: TypedEventFilter, 58 | listener: TypedListener 59 | ): this; 60 | removeListener, EventArgsObject>( 61 | eventFilter: TypedEventFilter, 62 | listener: TypedListener 63 | ): this; 64 | removeAllListeners, EventArgsObject>( 65 | eventFilter: TypedEventFilter 66 | ): this; 67 | 68 | listeners(eventName?: string): Array; 69 | off(eventName: string, listener: Listener): this; 70 | on(eventName: string, listener: Listener): this; 71 | once(eventName: string, listener: Listener): this; 72 | removeListener(eventName: string, listener: Listener): this; 73 | removeAllListeners(eventName?: string): this; 74 | 75 | queryFilter, EventArgsObject>( 76 | event: TypedEventFilter, 77 | fromBlockOrBlockhash?: string | number | undefined, 78 | toBlock?: string | number | undefined 79 | ): Promise>>; 80 | 81 | interface: IERC721ReceiverInterface; 82 | 83 | functions: { 84 | onERC721Received( 85 | operator: string, 86 | from: string, 87 | tokenId: BigNumberish, 88 | data: BytesLike, 89 | overrides?: Overrides & { from?: string | Promise } 90 | ): Promise; 91 | }; 92 | 93 | onERC721Received( 94 | operator: string, 95 | from: string, 96 | tokenId: BigNumberish, 97 | data: BytesLike, 98 | overrides?: Overrides & { from?: string | Promise } 99 | ): Promise; 100 | 101 | callStatic: { 102 | onERC721Received( 103 | operator: string, 104 | from: string, 105 | tokenId: BigNumberish, 106 | data: BytesLike, 107 | overrides?: CallOverrides 108 | ): Promise; 109 | }; 110 | 111 | filters: {}; 112 | 113 | estimateGas: { 114 | onERC721Received( 115 | operator: string, 116 | from: string, 117 | tokenId: BigNumberish, 118 | data: BytesLike, 119 | overrides?: Overrides & { from?: string | Promise } 120 | ): Promise; 121 | }; 122 | 123 | populateTransaction: { 124 | onERC721Received( 125 | operator: string, 126 | from: string, 127 | tokenId: BigNumberish, 128 | data: BytesLike, 129 | overrides?: Overrides & { from?: string | Promise } 130 | ): Promise; 131 | }; 132 | } 133 | -------------------------------------------------------------------------------- /homework_06/typechain/Ownable.d.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | 5 | import { 6 | ethers, 7 | EventFilter, 8 | Signer, 9 | BigNumber, 10 | BigNumberish, 11 | PopulatedTransaction, 12 | BaseContract, 13 | ContractTransaction, 14 | Overrides, 15 | CallOverrides, 16 | } from "ethers"; 17 | import { BytesLike } from "@ethersproject/bytes"; 18 | import { Listener, Provider } from "@ethersproject/providers"; 19 | import { FunctionFragment, EventFragment, Result } from "@ethersproject/abi"; 20 | import type { TypedEventFilter, TypedEvent, TypedListener } from "./common"; 21 | 22 | interface OwnableInterface extends ethers.utils.Interface { 23 | functions: { 24 | "owner()": FunctionFragment; 25 | "renounceOwnership()": FunctionFragment; 26 | "transferOwnership(address)": FunctionFragment; 27 | }; 28 | 29 | encodeFunctionData(functionFragment: "owner", values?: undefined): string; 30 | encodeFunctionData( 31 | functionFragment: "renounceOwnership", 32 | values?: undefined 33 | ): string; 34 | encodeFunctionData( 35 | functionFragment: "transferOwnership", 36 | values: [string] 37 | ): string; 38 | 39 | decodeFunctionResult(functionFragment: "owner", data: BytesLike): Result; 40 | decodeFunctionResult( 41 | functionFragment: "renounceOwnership", 42 | data: BytesLike 43 | ): Result; 44 | decodeFunctionResult( 45 | functionFragment: "transferOwnership", 46 | data: BytesLike 47 | ): Result; 48 | 49 | events: { 50 | "OwnershipTransferred(address,address)": EventFragment; 51 | }; 52 | 53 | getEvent(nameOrSignatureOrTopic: "OwnershipTransferred"): EventFragment; 54 | } 55 | 56 | export type OwnershipTransferredEvent = TypedEvent< 57 | [string, string] & { previousOwner: string; newOwner: string } 58 | >; 59 | 60 | export class Ownable extends BaseContract { 61 | connect(signerOrProvider: Signer | Provider | string): this; 62 | attach(addressOrName: string): this; 63 | deployed(): Promise; 64 | 65 | listeners, EventArgsObject>( 66 | eventFilter?: TypedEventFilter 67 | ): Array>; 68 | off, EventArgsObject>( 69 | eventFilter: TypedEventFilter, 70 | listener: TypedListener 71 | ): this; 72 | on, EventArgsObject>( 73 | eventFilter: TypedEventFilter, 74 | listener: TypedListener 75 | ): this; 76 | once, EventArgsObject>( 77 | eventFilter: TypedEventFilter, 78 | listener: TypedListener 79 | ): this; 80 | removeListener, EventArgsObject>( 81 | eventFilter: TypedEventFilter, 82 | listener: TypedListener 83 | ): this; 84 | removeAllListeners, EventArgsObject>( 85 | eventFilter: TypedEventFilter 86 | ): this; 87 | 88 | listeners(eventName?: string): Array; 89 | off(eventName: string, listener: Listener): this; 90 | on(eventName: string, listener: Listener): this; 91 | once(eventName: string, listener: Listener): this; 92 | removeListener(eventName: string, listener: Listener): this; 93 | removeAllListeners(eventName?: string): this; 94 | 95 | queryFilter, EventArgsObject>( 96 | event: TypedEventFilter, 97 | fromBlockOrBlockhash?: string | number | undefined, 98 | toBlock?: string | number | undefined 99 | ): Promise>>; 100 | 101 | interface: OwnableInterface; 102 | 103 | functions: { 104 | owner(overrides?: CallOverrides): Promise<[string]>; 105 | 106 | renounceOwnership( 107 | overrides?: Overrides & { from?: string | Promise } 108 | ): Promise; 109 | 110 | transferOwnership( 111 | newOwner: string, 112 | overrides?: Overrides & { from?: string | Promise } 113 | ): Promise; 114 | }; 115 | 116 | owner(overrides?: CallOverrides): Promise; 117 | 118 | renounceOwnership( 119 | overrides?: Overrides & { from?: string | Promise } 120 | ): Promise; 121 | 122 | transferOwnership( 123 | newOwner: string, 124 | overrides?: Overrides & { from?: string | Promise } 125 | ): Promise; 126 | 127 | callStatic: { 128 | owner(overrides?: CallOverrides): Promise; 129 | 130 | renounceOwnership(overrides?: CallOverrides): Promise; 131 | 132 | transferOwnership( 133 | newOwner: string, 134 | overrides?: CallOverrides 135 | ): Promise; 136 | }; 137 | 138 | filters: { 139 | "OwnershipTransferred(address,address)"( 140 | previousOwner?: string | null, 141 | newOwner?: string | null 142 | ): TypedEventFilter< 143 | [string, string], 144 | { previousOwner: string; newOwner: string } 145 | >; 146 | 147 | OwnershipTransferred( 148 | previousOwner?: string | null, 149 | newOwner?: string | null 150 | ): TypedEventFilter< 151 | [string, string], 152 | { previousOwner: string; newOwner: string } 153 | >; 154 | }; 155 | 156 | estimateGas: { 157 | owner(overrides?: CallOverrides): Promise; 158 | 159 | renounceOwnership( 160 | overrides?: Overrides & { from?: string | Promise } 161 | ): Promise; 162 | 163 | transferOwnership( 164 | newOwner: string, 165 | overrides?: Overrides & { from?: string | Promise } 166 | ): Promise; 167 | }; 168 | 169 | populateTransaction: { 170 | owner(overrides?: CallOverrides): Promise; 171 | 172 | renounceOwnership( 173 | overrides?: Overrides & { from?: string | Promise } 174 | ): Promise; 175 | 176 | transferOwnership( 177 | newOwner: string, 178 | overrides?: Overrides & { from?: string | Promise } 179 | ): Promise; 180 | }; 181 | } 182 | -------------------------------------------------------------------------------- /homework_06/typechain/common.d.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | import { EventFilter, Event } from "ethers"; 5 | import { Result } from "@ethersproject/abi"; 6 | 7 | export interface TypedEventFilter<_EventArgsArray, _EventArgsObject> 8 | extends EventFilter {} 9 | 10 | export interface TypedEvent extends Event { 11 | args: EventArgs; 12 | } 13 | 14 | export type TypedListener< 15 | EventArgsArray extends Array, 16 | EventArgsObject 17 | > = ( 18 | ...listenerArg: [ 19 | ...EventArgsArray, 20 | TypedEvent 21 | ] 22 | ) => void; 23 | 24 | export type MinEthersFactory = { 25 | deploy(...a: ARGS[]): Promise; 26 | }; 27 | export type GetContractTypeFromFactory = F extends MinEthersFactory< 28 | infer C, 29 | any 30 | > 31 | ? C 32 | : never; 33 | export type GetARGsTypeFromFactory = F extends MinEthersFactory 34 | ? Parameters 35 | : never; 36 | -------------------------------------------------------------------------------- /homework_06/typechain/factories/ERC165__factory.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | 5 | import { Contract, Signer, utils } from "ethers"; 6 | import { Provider } from "@ethersproject/providers"; 7 | import type { ERC165, ERC165Interface } from "../ERC165"; 8 | 9 | const _abi = [ 10 | { 11 | inputs: [ 12 | { 13 | internalType: "bytes4", 14 | name: "interfaceId", 15 | type: "bytes4", 16 | }, 17 | ], 18 | name: "supportsInterface", 19 | outputs: [ 20 | { 21 | internalType: "bool", 22 | name: "", 23 | type: "bool", 24 | }, 25 | ], 26 | stateMutability: "view", 27 | type: "function", 28 | }, 29 | ]; 30 | 31 | export class ERC165__factory { 32 | static readonly abi = _abi; 33 | static createInterface(): ERC165Interface { 34 | return new utils.Interface(_abi) as ERC165Interface; 35 | } 36 | static connect(address: string, signerOrProvider: Signer | Provider): ERC165 { 37 | return new Contract(address, _abi, signerOrProvider) as ERC165; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /homework_06/typechain/factories/IERC165__factory.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | 5 | import { Contract, Signer, utils } from "ethers"; 6 | import { Provider } from "@ethersproject/providers"; 7 | import type { IERC165, IERC165Interface } from "../IERC165"; 8 | 9 | const _abi = [ 10 | { 11 | inputs: [ 12 | { 13 | internalType: "bytes4", 14 | name: "interfaceId", 15 | type: "bytes4", 16 | }, 17 | ], 18 | name: "supportsInterface", 19 | outputs: [ 20 | { 21 | internalType: "bool", 22 | name: "", 23 | type: "bool", 24 | }, 25 | ], 26 | stateMutability: "view", 27 | type: "function", 28 | }, 29 | ]; 30 | 31 | export class IERC165__factory { 32 | static readonly abi = _abi; 33 | static createInterface(): IERC165Interface { 34 | return new utils.Interface(_abi) as IERC165Interface; 35 | } 36 | static connect( 37 | address: string, 38 | signerOrProvider: Signer | Provider 39 | ): IERC165 { 40 | return new Contract(address, _abi, signerOrProvider) as IERC165; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /homework_06/typechain/factories/IERC721Metadata__factory.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | 5 | import { Contract, Signer, utils } from "ethers"; 6 | import { Provider } from "@ethersproject/providers"; 7 | import type { 8 | IERC721Metadata, 9 | IERC721MetadataInterface, 10 | } from "../IERC721Metadata"; 11 | 12 | const _abi = [ 13 | { 14 | anonymous: false, 15 | inputs: [ 16 | { 17 | indexed: true, 18 | internalType: "address", 19 | name: "owner", 20 | type: "address", 21 | }, 22 | { 23 | indexed: true, 24 | internalType: "address", 25 | name: "approved", 26 | type: "address", 27 | }, 28 | { 29 | indexed: true, 30 | internalType: "uint256", 31 | name: "tokenId", 32 | type: "uint256", 33 | }, 34 | ], 35 | name: "Approval", 36 | type: "event", 37 | }, 38 | { 39 | anonymous: false, 40 | inputs: [ 41 | { 42 | indexed: true, 43 | internalType: "address", 44 | name: "owner", 45 | type: "address", 46 | }, 47 | { 48 | indexed: true, 49 | internalType: "address", 50 | name: "operator", 51 | type: "address", 52 | }, 53 | { 54 | indexed: false, 55 | internalType: "bool", 56 | name: "approved", 57 | type: "bool", 58 | }, 59 | ], 60 | name: "ApprovalForAll", 61 | type: "event", 62 | }, 63 | { 64 | anonymous: false, 65 | inputs: [ 66 | { 67 | indexed: true, 68 | internalType: "address", 69 | name: "from", 70 | type: "address", 71 | }, 72 | { 73 | indexed: true, 74 | internalType: "address", 75 | name: "to", 76 | type: "address", 77 | }, 78 | { 79 | indexed: true, 80 | internalType: "uint256", 81 | name: "tokenId", 82 | type: "uint256", 83 | }, 84 | ], 85 | name: "Transfer", 86 | type: "event", 87 | }, 88 | { 89 | inputs: [ 90 | { 91 | internalType: "address", 92 | name: "to", 93 | type: "address", 94 | }, 95 | { 96 | internalType: "uint256", 97 | name: "tokenId", 98 | type: "uint256", 99 | }, 100 | ], 101 | name: "approve", 102 | outputs: [], 103 | stateMutability: "nonpayable", 104 | type: "function", 105 | }, 106 | { 107 | inputs: [ 108 | { 109 | internalType: "address", 110 | name: "owner", 111 | type: "address", 112 | }, 113 | ], 114 | name: "balanceOf", 115 | outputs: [ 116 | { 117 | internalType: "uint256", 118 | name: "balance", 119 | type: "uint256", 120 | }, 121 | ], 122 | stateMutability: "view", 123 | type: "function", 124 | }, 125 | { 126 | inputs: [ 127 | { 128 | internalType: "uint256", 129 | name: "tokenId", 130 | type: "uint256", 131 | }, 132 | ], 133 | name: "getApproved", 134 | outputs: [ 135 | { 136 | internalType: "address", 137 | name: "operator", 138 | type: "address", 139 | }, 140 | ], 141 | stateMutability: "view", 142 | type: "function", 143 | }, 144 | { 145 | inputs: [ 146 | { 147 | internalType: "address", 148 | name: "owner", 149 | type: "address", 150 | }, 151 | { 152 | internalType: "address", 153 | name: "operator", 154 | type: "address", 155 | }, 156 | ], 157 | name: "isApprovedForAll", 158 | outputs: [ 159 | { 160 | internalType: "bool", 161 | name: "", 162 | type: "bool", 163 | }, 164 | ], 165 | stateMutability: "view", 166 | type: "function", 167 | }, 168 | { 169 | inputs: [], 170 | name: "name", 171 | outputs: [ 172 | { 173 | internalType: "string", 174 | name: "", 175 | type: "string", 176 | }, 177 | ], 178 | stateMutability: "view", 179 | type: "function", 180 | }, 181 | { 182 | inputs: [ 183 | { 184 | internalType: "uint256", 185 | name: "tokenId", 186 | type: "uint256", 187 | }, 188 | ], 189 | name: "ownerOf", 190 | outputs: [ 191 | { 192 | internalType: "address", 193 | name: "owner", 194 | type: "address", 195 | }, 196 | ], 197 | stateMutability: "view", 198 | type: "function", 199 | }, 200 | { 201 | inputs: [ 202 | { 203 | internalType: "address", 204 | name: "from", 205 | type: "address", 206 | }, 207 | { 208 | internalType: "address", 209 | name: "to", 210 | type: "address", 211 | }, 212 | { 213 | internalType: "uint256", 214 | name: "tokenId", 215 | type: "uint256", 216 | }, 217 | ], 218 | name: "safeTransferFrom", 219 | outputs: [], 220 | stateMutability: "nonpayable", 221 | type: "function", 222 | }, 223 | { 224 | inputs: [ 225 | { 226 | internalType: "address", 227 | name: "from", 228 | type: "address", 229 | }, 230 | { 231 | internalType: "address", 232 | name: "to", 233 | type: "address", 234 | }, 235 | { 236 | internalType: "uint256", 237 | name: "tokenId", 238 | type: "uint256", 239 | }, 240 | { 241 | internalType: "bytes", 242 | name: "data", 243 | type: "bytes", 244 | }, 245 | ], 246 | name: "safeTransferFrom", 247 | outputs: [], 248 | stateMutability: "nonpayable", 249 | type: "function", 250 | }, 251 | { 252 | inputs: [ 253 | { 254 | internalType: "address", 255 | name: "operator", 256 | type: "address", 257 | }, 258 | { 259 | internalType: "bool", 260 | name: "_approved", 261 | type: "bool", 262 | }, 263 | ], 264 | name: "setApprovalForAll", 265 | outputs: [], 266 | stateMutability: "nonpayable", 267 | type: "function", 268 | }, 269 | { 270 | inputs: [ 271 | { 272 | internalType: "bytes4", 273 | name: "interfaceId", 274 | type: "bytes4", 275 | }, 276 | ], 277 | name: "supportsInterface", 278 | outputs: [ 279 | { 280 | internalType: "bool", 281 | name: "", 282 | type: "bool", 283 | }, 284 | ], 285 | stateMutability: "view", 286 | type: "function", 287 | }, 288 | { 289 | inputs: [], 290 | name: "symbol", 291 | outputs: [ 292 | { 293 | internalType: "string", 294 | name: "", 295 | type: "string", 296 | }, 297 | ], 298 | stateMutability: "view", 299 | type: "function", 300 | }, 301 | { 302 | inputs: [ 303 | { 304 | internalType: "uint256", 305 | name: "tokenId", 306 | type: "uint256", 307 | }, 308 | ], 309 | name: "tokenURI", 310 | outputs: [ 311 | { 312 | internalType: "string", 313 | name: "", 314 | type: "string", 315 | }, 316 | ], 317 | stateMutability: "view", 318 | type: "function", 319 | }, 320 | { 321 | inputs: [ 322 | { 323 | internalType: "address", 324 | name: "from", 325 | type: "address", 326 | }, 327 | { 328 | internalType: "address", 329 | name: "to", 330 | type: "address", 331 | }, 332 | { 333 | internalType: "uint256", 334 | name: "tokenId", 335 | type: "uint256", 336 | }, 337 | ], 338 | name: "transferFrom", 339 | outputs: [], 340 | stateMutability: "nonpayable", 341 | type: "function", 342 | }, 343 | ]; 344 | 345 | export class IERC721Metadata__factory { 346 | static readonly abi = _abi; 347 | static createInterface(): IERC721MetadataInterface { 348 | return new utils.Interface(_abi) as IERC721MetadataInterface; 349 | } 350 | static connect( 351 | address: string, 352 | signerOrProvider: Signer | Provider 353 | ): IERC721Metadata { 354 | return new Contract(address, _abi, signerOrProvider) as IERC721Metadata; 355 | } 356 | } 357 | -------------------------------------------------------------------------------- /homework_06/typechain/factories/IERC721Receiver__factory.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | 5 | import { Contract, Signer, utils } from "ethers"; 6 | import { Provider } from "@ethersproject/providers"; 7 | import type { 8 | IERC721Receiver, 9 | IERC721ReceiverInterface, 10 | } from "../IERC721Receiver"; 11 | 12 | const _abi = [ 13 | { 14 | inputs: [ 15 | { 16 | internalType: "address", 17 | name: "operator", 18 | type: "address", 19 | }, 20 | { 21 | internalType: "address", 22 | name: "from", 23 | type: "address", 24 | }, 25 | { 26 | internalType: "uint256", 27 | name: "tokenId", 28 | type: "uint256", 29 | }, 30 | { 31 | internalType: "bytes", 32 | name: "data", 33 | type: "bytes", 34 | }, 35 | ], 36 | name: "onERC721Received", 37 | outputs: [ 38 | { 39 | internalType: "bytes4", 40 | name: "", 41 | type: "bytes4", 42 | }, 43 | ], 44 | stateMutability: "nonpayable", 45 | type: "function", 46 | }, 47 | ]; 48 | 49 | export class IERC721Receiver__factory { 50 | static readonly abi = _abi; 51 | static createInterface(): IERC721ReceiverInterface { 52 | return new utils.Interface(_abi) as IERC721ReceiverInterface; 53 | } 54 | static connect( 55 | address: string, 56 | signerOrProvider: Signer | Provider 57 | ): IERC721Receiver { 58 | return new Contract(address, _abi, signerOrProvider) as IERC721Receiver; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /homework_06/typechain/factories/IERC721__factory.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | 5 | import { Contract, Signer, utils } from "ethers"; 6 | import { Provider } from "@ethersproject/providers"; 7 | import type { IERC721, IERC721Interface } from "../IERC721"; 8 | 9 | const _abi = [ 10 | { 11 | anonymous: false, 12 | inputs: [ 13 | { 14 | indexed: true, 15 | internalType: "address", 16 | name: "owner", 17 | type: "address", 18 | }, 19 | { 20 | indexed: true, 21 | internalType: "address", 22 | name: "approved", 23 | type: "address", 24 | }, 25 | { 26 | indexed: true, 27 | internalType: "uint256", 28 | name: "tokenId", 29 | type: "uint256", 30 | }, 31 | ], 32 | name: "Approval", 33 | type: "event", 34 | }, 35 | { 36 | anonymous: false, 37 | inputs: [ 38 | { 39 | indexed: true, 40 | internalType: "address", 41 | name: "owner", 42 | type: "address", 43 | }, 44 | { 45 | indexed: true, 46 | internalType: "address", 47 | name: "operator", 48 | type: "address", 49 | }, 50 | { 51 | indexed: false, 52 | internalType: "bool", 53 | name: "approved", 54 | type: "bool", 55 | }, 56 | ], 57 | name: "ApprovalForAll", 58 | type: "event", 59 | }, 60 | { 61 | anonymous: false, 62 | inputs: [ 63 | { 64 | indexed: true, 65 | internalType: "address", 66 | name: "from", 67 | type: "address", 68 | }, 69 | { 70 | indexed: true, 71 | internalType: "address", 72 | name: "to", 73 | type: "address", 74 | }, 75 | { 76 | indexed: true, 77 | internalType: "uint256", 78 | name: "tokenId", 79 | type: "uint256", 80 | }, 81 | ], 82 | name: "Transfer", 83 | type: "event", 84 | }, 85 | { 86 | inputs: [ 87 | { 88 | internalType: "address", 89 | name: "to", 90 | type: "address", 91 | }, 92 | { 93 | internalType: "uint256", 94 | name: "tokenId", 95 | type: "uint256", 96 | }, 97 | ], 98 | name: "approve", 99 | outputs: [], 100 | stateMutability: "nonpayable", 101 | type: "function", 102 | }, 103 | { 104 | inputs: [ 105 | { 106 | internalType: "address", 107 | name: "owner", 108 | type: "address", 109 | }, 110 | ], 111 | name: "balanceOf", 112 | outputs: [ 113 | { 114 | internalType: "uint256", 115 | name: "balance", 116 | type: "uint256", 117 | }, 118 | ], 119 | stateMutability: "view", 120 | type: "function", 121 | }, 122 | { 123 | inputs: [ 124 | { 125 | internalType: "uint256", 126 | name: "tokenId", 127 | type: "uint256", 128 | }, 129 | ], 130 | name: "getApproved", 131 | outputs: [ 132 | { 133 | internalType: "address", 134 | name: "operator", 135 | type: "address", 136 | }, 137 | ], 138 | stateMutability: "view", 139 | type: "function", 140 | }, 141 | { 142 | inputs: [ 143 | { 144 | internalType: "address", 145 | name: "owner", 146 | type: "address", 147 | }, 148 | { 149 | internalType: "address", 150 | name: "operator", 151 | type: "address", 152 | }, 153 | ], 154 | name: "isApprovedForAll", 155 | outputs: [ 156 | { 157 | internalType: "bool", 158 | name: "", 159 | type: "bool", 160 | }, 161 | ], 162 | stateMutability: "view", 163 | type: "function", 164 | }, 165 | { 166 | inputs: [ 167 | { 168 | internalType: "uint256", 169 | name: "tokenId", 170 | type: "uint256", 171 | }, 172 | ], 173 | name: "ownerOf", 174 | outputs: [ 175 | { 176 | internalType: "address", 177 | name: "owner", 178 | type: "address", 179 | }, 180 | ], 181 | stateMutability: "view", 182 | type: "function", 183 | }, 184 | { 185 | inputs: [ 186 | { 187 | internalType: "address", 188 | name: "from", 189 | type: "address", 190 | }, 191 | { 192 | internalType: "address", 193 | name: "to", 194 | type: "address", 195 | }, 196 | { 197 | internalType: "uint256", 198 | name: "tokenId", 199 | type: "uint256", 200 | }, 201 | ], 202 | name: "safeTransferFrom", 203 | outputs: [], 204 | stateMutability: "nonpayable", 205 | type: "function", 206 | }, 207 | { 208 | inputs: [ 209 | { 210 | internalType: "address", 211 | name: "from", 212 | type: "address", 213 | }, 214 | { 215 | internalType: "address", 216 | name: "to", 217 | type: "address", 218 | }, 219 | { 220 | internalType: "uint256", 221 | name: "tokenId", 222 | type: "uint256", 223 | }, 224 | { 225 | internalType: "bytes", 226 | name: "data", 227 | type: "bytes", 228 | }, 229 | ], 230 | name: "safeTransferFrom", 231 | outputs: [], 232 | stateMutability: "nonpayable", 233 | type: "function", 234 | }, 235 | { 236 | inputs: [ 237 | { 238 | internalType: "address", 239 | name: "operator", 240 | type: "address", 241 | }, 242 | { 243 | internalType: "bool", 244 | name: "_approved", 245 | type: "bool", 246 | }, 247 | ], 248 | name: "setApprovalForAll", 249 | outputs: [], 250 | stateMutability: "nonpayable", 251 | type: "function", 252 | }, 253 | { 254 | inputs: [ 255 | { 256 | internalType: "bytes4", 257 | name: "interfaceId", 258 | type: "bytes4", 259 | }, 260 | ], 261 | name: "supportsInterface", 262 | outputs: [ 263 | { 264 | internalType: "bool", 265 | name: "", 266 | type: "bool", 267 | }, 268 | ], 269 | stateMutability: "view", 270 | type: "function", 271 | }, 272 | { 273 | inputs: [ 274 | { 275 | internalType: "address", 276 | name: "from", 277 | type: "address", 278 | }, 279 | { 280 | internalType: "address", 281 | name: "to", 282 | type: "address", 283 | }, 284 | { 285 | internalType: "uint256", 286 | name: "tokenId", 287 | type: "uint256", 288 | }, 289 | ], 290 | name: "transferFrom", 291 | outputs: [], 292 | stateMutability: "nonpayable", 293 | type: "function", 294 | }, 295 | ]; 296 | 297 | export class IERC721__factory { 298 | static readonly abi = _abi; 299 | static createInterface(): IERC721Interface { 300 | return new utils.Interface(_abi) as IERC721Interface; 301 | } 302 | static connect( 303 | address: string, 304 | signerOrProvider: Signer | Provider 305 | ): IERC721 { 306 | return new Contract(address, _abi, signerOrProvider) as IERC721; 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /homework_06/typechain/factories/Ownable__factory.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | 5 | import { Contract, Signer, utils } from "ethers"; 6 | import { Provider } from "@ethersproject/providers"; 7 | import type { Ownable, OwnableInterface } from "../Ownable"; 8 | 9 | const _abi = [ 10 | { 11 | anonymous: false, 12 | inputs: [ 13 | { 14 | indexed: true, 15 | internalType: "address", 16 | name: "previousOwner", 17 | type: "address", 18 | }, 19 | { 20 | indexed: true, 21 | internalType: "address", 22 | name: "newOwner", 23 | type: "address", 24 | }, 25 | ], 26 | name: "OwnershipTransferred", 27 | type: "event", 28 | }, 29 | { 30 | inputs: [], 31 | name: "owner", 32 | outputs: [ 33 | { 34 | internalType: "address", 35 | name: "", 36 | type: "address", 37 | }, 38 | ], 39 | stateMutability: "view", 40 | type: "function", 41 | }, 42 | { 43 | inputs: [], 44 | name: "renounceOwnership", 45 | outputs: [], 46 | stateMutability: "nonpayable", 47 | type: "function", 48 | }, 49 | { 50 | inputs: [ 51 | { 52 | internalType: "address", 53 | name: "newOwner", 54 | type: "address", 55 | }, 56 | ], 57 | name: "transferOwnership", 58 | outputs: [], 59 | stateMutability: "nonpayable", 60 | type: "function", 61 | }, 62 | ]; 63 | 64 | export class Ownable__factory { 65 | static readonly abi = _abi; 66 | static createInterface(): OwnableInterface { 67 | return new utils.Interface(_abi) as OwnableInterface; 68 | } 69 | static connect( 70 | address: string, 71 | signerOrProvider: Signer | Provider 72 | ): Ownable { 73 | return new Contract(address, _abi, signerOrProvider) as Ownable; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /homework_06/typechain/hardhat.d.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | 5 | import { ethers } from "ethers"; 6 | import { 7 | FactoryOptions, 8 | HardhatEthersHelpers as HardhatEthersHelpersBase, 9 | } from "@nomiclabs/hardhat-ethers/types"; 10 | 11 | import * as Contracts from "."; 12 | 13 | declare module "hardhat/types/runtime" { 14 | interface HardhatEthersHelpers extends HardhatEthersHelpersBase { 15 | getContractFactory( 16 | name: "Ownable", 17 | signerOrOptions?: ethers.Signer | FactoryOptions 18 | ): Promise; 19 | getContractFactory( 20 | name: "ERC721", 21 | signerOrOptions?: ethers.Signer | FactoryOptions 22 | ): Promise; 23 | getContractFactory( 24 | name: "IERC721Metadata", 25 | signerOrOptions?: ethers.Signer | FactoryOptions 26 | ): Promise; 27 | getContractFactory( 28 | name: "IERC721", 29 | signerOrOptions?: ethers.Signer | FactoryOptions 30 | ): Promise; 31 | getContractFactory( 32 | name: "IERC721Receiver", 33 | signerOrOptions?: ethers.Signer | FactoryOptions 34 | ): Promise; 35 | getContractFactory( 36 | name: "ERC165", 37 | signerOrOptions?: ethers.Signer | FactoryOptions 38 | ): Promise; 39 | getContractFactory( 40 | name: "IERC165", 41 | signerOrOptions?: ethers.Signer | FactoryOptions 42 | ): Promise; 43 | getContractFactory( 44 | name: "VolcanoCoin", 45 | signerOrOptions?: ethers.Signer | FactoryOptions 46 | ): Promise; 47 | 48 | getContractAt( 49 | name: "Ownable", 50 | address: string, 51 | signer?: ethers.Signer 52 | ): Promise; 53 | getContractAt( 54 | name: "ERC721", 55 | address: string, 56 | signer?: ethers.Signer 57 | ): Promise; 58 | getContractAt( 59 | name: "IERC721Metadata", 60 | address: string, 61 | signer?: ethers.Signer 62 | ): Promise; 63 | getContractAt( 64 | name: "IERC721", 65 | address: string, 66 | signer?: ethers.Signer 67 | ): Promise; 68 | getContractAt( 69 | name: "IERC721Receiver", 70 | address: string, 71 | signer?: ethers.Signer 72 | ): Promise; 73 | getContractAt( 74 | name: "ERC165", 75 | address: string, 76 | signer?: ethers.Signer 77 | ): Promise; 78 | getContractAt( 79 | name: "IERC165", 80 | address: string, 81 | signer?: ethers.Signer 82 | ): Promise; 83 | getContractAt( 84 | name: "VolcanoCoin", 85 | address: string, 86 | signer?: ethers.Signer 87 | ): Promise; 88 | 89 | // default types 90 | getContractFactory( 91 | name: string, 92 | signerOrOptions?: ethers.Signer | FactoryOptions 93 | ): Promise; 94 | getContractFactory( 95 | abi: any[], 96 | bytecode: ethers.utils.BytesLike, 97 | signer?: ethers.Signer 98 | ): Promise; 99 | getContractAt( 100 | nameOrAbi: string | any[], 101 | address: string, 102 | signer?: ethers.Signer 103 | ): Promise; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /homework_06/typechain/index.ts: -------------------------------------------------------------------------------- 1 | /* Autogenerated file. Do not edit manually. */ 2 | /* tslint:disable */ 3 | /* eslint-disable */ 4 | export type { Ownable } from "./Ownable"; 5 | export type { ERC721 } from "./ERC721"; 6 | export type { IERC721Metadata } from "./IERC721Metadata"; 7 | export type { IERC721 } from "./IERC721"; 8 | export type { IERC721Receiver } from "./IERC721Receiver"; 9 | export type { ERC165 } from "./ERC165"; 10 | export type { IERC165 } from "./IERC165"; 11 | export type { VolcanoCoin } from "./VolcanoCoin"; 12 | 13 | export { Ownable__factory } from "./factories/Ownable__factory"; 14 | export { ERC721__factory } from "./factories/ERC721__factory"; 15 | export { IERC721Metadata__factory } from "./factories/IERC721Metadata__factory"; 16 | export { IERC721__factory } from "./factories/IERC721__factory"; 17 | export { IERC721Receiver__factory } from "./factories/IERC721Receiver__factory"; 18 | export { ERC165__factory } from "./factories/ERC165__factory"; 19 | export { IERC165__factory } from "./factories/IERC165__factory"; 20 | export { VolcanoCoin__factory } from "./factories/VolcanoCoin__factory"; 21 | -------------------------------------------------------------------------------- /homework_07/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es2021: true, 5 | }, 6 | extends: [ 7 | 'airbnb-base', 8 | ], 9 | parser: '@typescript-eslint/parser', 10 | parserOptions: { 11 | ecmaVersion: 13, 12 | sourceType: 'module', 13 | tsconfigRootDir: './', 14 | project: './tsconfig.json', 15 | }, 16 | plugins: [ 17 | '@typescript-eslint', 18 | 'import', 19 | ], 20 | rules: { 21 | '@typescript-eslint/no-unused-vars': 'error', 22 | 'linebreak-style': 0, 23 | }, 24 | settings: { 25 | 'import/resolver': { 26 | 'typescript': {} 27 | }, 28 | extends: [ 29 | "plugin:@typescript-eslint/recommended", 30 | "plugin:@typescript-eslint/recommended-requiring-type-checking"] 31 | }; 32 | -------------------------------------------------------------------------------- /homework_07/.gitignore: -------------------------------------------------------------------------------- 1 | dist/* -------------------------------------------------------------------------------- /homework_07/Homework_7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anajuliabit/bootcamp-solidity/4f1352e9ddf6184b8637a5bea2856f73527af356/homework_07/Homework_7.pdf -------------------------------------------------------------------------------- /homework_07/build.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Remove old files, copy front-end ones. 3 | */ 4 | 5 | import childProcess from 'child_process'; 6 | import fs from 'fs-extra'; 7 | import Logger from 'jet-logger'; 8 | 9 | // Setup logger 10 | const logger = new Logger(); 11 | logger.timestamp = false; 12 | 13 | (async () => { 14 | try { 15 | // Remove current build 16 | await remove('./dist/'); 17 | // Copy front-end files 18 | await copy('./src/public', './dist/public'); 19 | await copy('./src/views', './dist/views'); 20 | // Copy production env file 21 | await copy('./src/pre-start/env/production.env', './dist/pre-start/env/production.env'); 22 | // Copy back-end files 23 | await exec('tsc --build tsconfig.prod.json', './') 24 | } catch (err) { 25 | logger.err(err); 26 | } 27 | })(); 28 | 29 | 30 | function remove(loc: string): Promise { 31 | return new Promise((res, rej) => { 32 | return fs.remove(loc, (err) => { 33 | return (!!err ? rej(err) : res()); 34 | }); 35 | }); 36 | } 37 | 38 | 39 | function copy(src: string, dest: string): Promise { 40 | return new Promise((res, rej) => { 41 | return fs.copy(src, dest, (err) => { 42 | return (!!err ? rej(err) : res()); 43 | }); 44 | }); 45 | } 46 | 47 | 48 | function exec(cmd: string, loc: string): Promise { 49 | return new Promise((res, rej) => { 50 | return childProcess.exec(cmd, {cwd: loc}, (err, stdout, stderr) => { 51 | if (!!stdout) { 52 | logger.info(stdout); 53 | } 54 | if (!!stderr) { 55 | logger.warn(stderr); 56 | } 57 | return (!!err ? rej(err) : res()); 58 | }); 59 | }); 60 | } 61 | -------------------------------------------------------------------------------- /homework_07/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lesson_07", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "build": "./node_modules/.bin/ts-node build.ts", 6 | "lint": "eslint . --ext .ts", 7 | "start": "node -r module-alias/register ./dist --env=production", 8 | "start:dev": "nodemon" 9 | }, 10 | "nodemonConfig": { 11 | "watch": [ 12 | "src" 13 | ], 14 | "ext": "ts, html", 15 | "ignore": [ 16 | "src/public" 17 | ], 18 | "exec": "./node_modules/.bin/ts-node -r tsconfig-paths/register ./src" 19 | }, 20 | "_moduleAliases": { 21 | "@daos": "dist/daos", 22 | "@entities": "dist/entities", 23 | "@shared": "dist/shared", 24 | "@server": "dist/Server" 25 | }, 26 | "eslintConfig": { 27 | "parser": "@typescript-eslint/parser", 28 | "plugins": [ 29 | "@typescript-eslint" 30 | ], 31 | "extends": [ 32 | "eslint:recommended", 33 | "plugin:@typescript-eslint/recommended", 34 | "plugin:@typescript-eslint/recommended-requiring-type-checking" 35 | ], 36 | "parserOptions": { 37 | "project": "./tsconfig.json" 38 | }, 39 | "rules": { 40 | "max-len": [ 41 | "error", 42 | { 43 | "code": 100 44 | } 45 | ], 46 | "no-console": 1, 47 | "no-extra-boolean-cast": 0, 48 | "@typescript-eslint/restrict-plus-operands": 0, 49 | "@typescript-eslint/explicit-module-boundary-types": 0, 50 | "@typescript-eslint/no-explicit-any": 0, 51 | "@typescript-eslint/no-floating-promises": 0, 52 | "@typescript-eslint/no-unsafe-member-access": 0, 53 | "@typescript-eslint/no-unsafe-assignment": 0 54 | } 55 | }, 56 | "eslintIgnore": [ 57 | "src/public/", 58 | "build.ts" 59 | ], 60 | "dependencies": { 61 | "@types/axios": "^0.14.0", 62 | "axios": "^0.24.0", 63 | "command-line-args": "^5.2.0", 64 | "cookie-parser": "^1.4.6", 65 | "dotenv": "^10.0.0", 66 | "express": "^4.17.1", 67 | "express-async-errors": "^3.1.1", 68 | "helmet": "^4.6.0", 69 | "http-status-codes": "^2.1.4", 70 | "ipfs-core": "^0.12.1", 71 | "it-all": "^1.0.6", 72 | "jet-logger": "^1.0.6", 73 | "jsonfile": "^6.1.0", 74 | "module-alias": "^2.2.2", 75 | "morgan": "^1.10.0" 76 | }, 77 | "devDependencies": { 78 | "@types/command-line-args": "^5.2.0", 79 | "@types/cookie-parser": "^1.4.2", 80 | "@types/express": "^4.17.13", 81 | "@types/find": "^0.2.1", 82 | "@types/fs-extra": "^9.0.13", 83 | "@types/jasmine": "^3.10.2", 84 | "@types/jsonfile": "^6.0.1", 85 | "@types/morgan": "^1.9.3", 86 | "@types/node": "^16.11.9", 87 | "@types/supertest": "^2.0.11", 88 | "@typescript-eslint/eslint-plugin": "^5.4.0", 89 | "@typescript-eslint/parser": "^5.4.0", 90 | "eslint": "^8.3.0", 91 | "eslint-config-airbnb-base": "^15.0.0", 92 | "eslint-import-resolver-typescript": "^2.5.0", 93 | "eslint-plugin-import": "^2.25.3", 94 | "find": "^0.3.0", 95 | "fs-extra": "^10.0.0", 96 | "jasmine": "^3.10.0", 97 | "nodemon": "^2.0.15", 98 | "supertest": "^6.1.6", 99 | "ts-node": "^10.4.0", 100 | "tsconfig-paths": "^3.12.0", 101 | "typescript": "^4.5.2" 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /homework_07/src/Server.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-unused-vars */ 2 | /* eslint-disable @typescript-eslint/no-unsafe-call */ 3 | import cookieParser from 'cookie-parser'; 4 | import express, { Express, Request, Response } from 'express'; 5 | import 'express-async-errors'; 6 | import helmet from 'helmet'; 7 | import morgan from 'morgan'; 8 | import path from 'path'; 9 | import errorMiddleware from './middlewares/error.middleware'; 10 | import BaseRouter from './routes'; 11 | 12 | const app: Express = express(); 13 | 14 | app.use(express.json({ limit: '50mb'})); 15 | app.use(express.urlencoded({ extended: true, limit: '50mb' })); 16 | app.use(cookieParser()); 17 | 18 | // Show routes called in console during development 19 | if (process.env.NODE_ENV === 'development') { 20 | app.use(morgan('dev')); 21 | } 22 | 23 | // Security 24 | if (process.env.NODE_ENV === 'production') { 25 | app.use(helmet()); 26 | } 27 | 28 | app.use('/api', BaseRouter); 29 | app.use(errorMiddleware); 30 | 31 | /** ********************************************************************************** 32 | * Serve front-end content 33 | ********************************************************************************** */ 34 | 35 | const viewsDir = path.join(__dirname, 'views'); 36 | app.set('views', viewsDir); 37 | const staticDir = path.join(__dirname, 'public'); 38 | app.use(express.static(staticDir)); 39 | app.get('*', (_req: Request, res: Response) => { 40 | res.sendFile('index.html', { root: viewsDir }); 41 | }); 42 | 43 | export default app; 44 | -------------------------------------------------------------------------------- /homework_07/src/exceptions/HttpException.ts: -------------------------------------------------------------------------------- 1 | class HttpException extends Error { 2 | status: number; 3 | message: string; 4 | constructor(status: number, message: string) { 5 | super(message); 6 | this.status = status; 7 | this.message = message; 8 | } 9 | } 10 | 11 | export default HttpException; -------------------------------------------------------------------------------- /homework_07/src/index.ts: -------------------------------------------------------------------------------- 1 | import app from '@server'; 2 | import logger from '@shared/Logger'; 3 | import './pre-start'; // Must be the first import 4 | import { StorageService } from './services/storage.service'; 5 | 6 | const port = Number(process.env.PORT || 3000); 7 | export const storage = new StorageService(); 8 | 9 | const init = async () => { 10 | await storage.init(); 11 | await app.listen(port); 12 | } 13 | 14 | init().then(() => logger.info('Express server started on port: ' + port)); -------------------------------------------------------------------------------- /homework_07/src/middlewares/error.middleware.ts: -------------------------------------------------------------------------------- 1 | import logger from '@shared/Logger'; 2 | import { NextFunction, Request, Response } from 'express'; 3 | import StatusCodes from 'http-status-codes'; 4 | import HttpException from '../exceptions/HttpException'; 5 | 6 | const { BAD_REQUEST } = StatusCodes; 7 | 8 | function errorMiddleware(err: HttpException, _request: Request, response: Response, next: NextFunction) { 9 | logger.err(err, true); 10 | return response.status(BAD_REQUEST).json({ 11 | error: err.message, 12 | }); 13 | } 14 | 15 | export default errorMiddleware; -------------------------------------------------------------------------------- /homework_07/src/pre-start/env/development.env: -------------------------------------------------------------------------------- 1 | ## Environment ## 2 | NODE_ENV=development 3 | 4 | 5 | ## Server ## 6 | PORT=3000 7 | HOST=localhost 8 | 9 | 10 | ## Setup jet-logger ## 11 | JET_LOGGER_MODE=CONSOLE 12 | JET_LOGGER_FILEPATH=jet-logger.log 13 | JET_LOGGER_TIMESTAMP=TRUE 14 | JET_LOGGER_FORMAT=LINE 15 | -------------------------------------------------------------------------------- /homework_07/src/pre-start/env/production.env: -------------------------------------------------------------------------------- 1 | ## Environment ## 2 | NODE_ENV=production 3 | 4 | 5 | ## Server ## 6 | PORT=8081 7 | HOST=localhost 8 | 9 | 10 | ## Setup jet-logger ## 11 | JET_LOGGER_MODE=FILE 12 | JET_LOGGER_FILEPATH=jet-logger.log 13 | JET_LOGGER_TIMESTAMP=TRUE 14 | JET_LOGGER_FORMAT=LINE 15 | -------------------------------------------------------------------------------- /homework_07/src/pre-start/env/test.env: -------------------------------------------------------------------------------- 1 | ## Environment ## 2 | NODE_ENV=test 3 | 4 | 5 | ## Server ## 6 | PORT=4000 7 | HOST=localhost 8 | 9 | 10 | ## Setup jet-logger ## 11 | JET_LOGGER_MODE=CONSOLE 12 | JET_LOGGER_FILEPATH=jet-logger.log 13 | JET_LOGGER_TIMESTAMP=TRUE 14 | JET_LOGGER_FORMAT=LINE 15 | -------------------------------------------------------------------------------- /homework_07/src/pre-start/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/restrict-template-expressions */ 2 | /** 3 | * Pre-start is where we want to place things that must run BEFORE the express server is started. 4 | * This is useful for environment variables, command-line arguments, and cron-jobs. 5 | */ 6 | 7 | import path from 'path'; 8 | import dotenv from 'dotenv'; 9 | import commandLineArgs from 'command-line-args'; 10 | 11 | 12 | 13 | (() => { 14 | // Setup command line options 15 | const options = commandLineArgs([ 16 | { 17 | name: 'env', 18 | alias: 'e', 19 | defaultValue: 'development', 20 | type: String, 21 | }, 22 | ]); 23 | // Set the env file 24 | const result2 = dotenv.config({ 25 | path: path.join(__dirname, `env/${options.env}.env`), 26 | }); 27 | if (result2.error) { 28 | throw result2.error; 29 | } 30 | })(); 31 | -------------------------------------------------------------------------------- /homework_07/src/public/scripts/index.js: -------------------------------------------------------------------------------- 1 | document.addEventListener('click', async (event) => { 2 | const ele = event.target; 3 | if (ele.matches('#add-text-btn')) { 4 | await addText(); 5 | } else if (ele.matches('#add-image-btn')) { 6 | addImage(); 7 | } else if (ele.matches('#get-data-btn')) { 8 | getText(); 9 | } else if (ele.matches('#get-image-btn')) { 10 | getImage(); 11 | } 12 | }, false) 13 | 14 | async function addText() { 15 | const textInput = document.getElementById('text-input'); 16 | const { data }= await axios.post('/api/ipfs', { text: textInput.value }); 17 | displayText(data); 18 | } 19 | 20 | 21 | async function addImage() { 22 | const imageInput = document.getElementById('image-input'); 23 | const reader = new FileReader(); 24 | 25 | reader.onloadend = async () => { 26 | const buff = buffer.Buffer(reader.result) // Convert data into buffer 27 | const { data } = await axios.post('/api/ipfs', { image: buff }); 28 | displayText(data); 29 | } 30 | reader.readAsArrayBuffer(imageInput.files[0]); 31 | } 32 | 33 | async function getText() { 34 | const data = await getData(); 35 | displayText(data); 36 | } 37 | 38 | 39 | async function getImage() { 40 | const data = await getData(); 41 | displayImage(data); 42 | } 43 | 44 | async function getData() { 45 | const cid = getCid(); 46 | const { data } = await axios.get(`/api/ipfs/${cid}`); 47 | 48 | return data; 49 | } 50 | 51 | function getCid() { 52 | const cidInput = document.getElementById('cid-input'); 53 | return cidInput.value; 54 | } 55 | 56 | function displayText(text) { 57 | const data = document.getElementById('data-anchor'); 58 | data.innerHTML = ` ${text} `; 59 | }; 60 | 61 | function displayImage(buffer) { 62 | const data = document.getElementById('data-anchor'); 63 | data.innerHTML = ``; 64 | } 65 | 66 | 67 | -------------------------------------------------------------------------------- /homework_07/src/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 100px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | body .content { 7 | display: flex; 8 | } 9 | 10 | body .input { 11 | display: flex; 12 | flex-direction: column; 13 | padding: 10px; 14 | margin-right: 20px; 15 | border: 1px solid #ccc; 16 | border-radius: 4px; 17 | margin-bottom: 10px; 18 | color: #333; 19 | } 20 | 21 | body .input .input-column { 22 | display: flex; 23 | flex-direction: column; 24 | margin-bottom: 10px; 25 | } 26 | 27 | body .input .input-column > * { 28 | margin-bottom: 5px; 29 | } 30 | -------------------------------------------------------------------------------- /homework_07/src/routes/index.ts: -------------------------------------------------------------------------------- 1 | import { Router } from 'express'; 2 | import { addData, get } from './storage.controller'; 3 | 4 | const router = Router(); 5 | router.get('/:cid', get); 6 | router.post('/', addData); 7 | 8 | const baseRouter = Router(); 9 | baseRouter.use('/ipfs', router); 10 | export default baseRouter; 11 | -------------------------------------------------------------------------------- /homework_07/src/routes/storage.controller.ts: -------------------------------------------------------------------------------- 1 | import { paramMissingError } from '@shared/constants'; 2 | import { Request, Response } from 'express'; 3 | import StatusCodes from 'http-status-codes'; 4 | import { storage } from '../index'; 5 | 6 | const { BAD_REQUEST, CREATED, INTERNAL_SERVER_ERROR } = StatusCodes; 7 | 8 | export async function addData(req: Request, res: Response) { 9 | const { text, image }: { text: string, image: Buffer } = req.body; 10 | if (!text && !image) { 11 | return res.status(BAD_REQUEST).json({ 12 | error: paramMissingError, 13 | }); 14 | } 15 | let result = undefined; 16 | if (text) { 17 | result = await storage.addText(text); 18 | } else if(image) { 19 | result = await storage.addImage(image); 20 | } 21 | 22 | if(!result) { 23 | return res.status(INTERNAL_SERVER_ERROR).json({ 24 | error: result, 25 | }); 26 | } 27 | 28 | return res.status(CREATED).json(result).end(); 29 | } 30 | 31 | export async function get(req: Request, res: Response) { 32 | const cid = req.params.cid; 33 | if (!cid) { 34 | return res.status(BAD_REQUEST).json({ 35 | error: paramMissingError, 36 | }); 37 | } 38 | const result = await storage.get(cid); 39 | return res.status(CREATED).json(result).end(); 40 | } 41 | 42 | -------------------------------------------------------------------------------- /homework_07/src/services/storage.service.ts: -------------------------------------------------------------------------------- 1 | import { ipfsNotInitializedError } from '@shared/constants'; 2 | import { create, IPFS } from 'ipfs-core'; 3 | import all from 'it-all'; 4 | 5 | export class StorageService { 6 | public ipfs: IPFS | null = null; 7 | 8 | async init() { 9 | this.ipfs = await create(); 10 | } 11 | 12 | async addText(text: string): Promise { 13 | if(!this.ipfs) { 14 | throw new Error(ipfsNotInitializedError); 15 | } 16 | 17 | const result = await this.ipfs.add(text); 18 | return result.cid.toString(); 19 | } 20 | 21 | async addImage(image: Buffer): Promise { 22 | if(!this.ipfs) { 23 | throw new Error(ipfsNotInitializedError); 24 | } 25 | const buff = Buffer.from(image) 26 | const result = await this.ipfs.add(buff); 27 | return result.cid.toString(); 28 | } 29 | 30 | async get(cid: string): Promise { 31 | if(!this.ipfs) { 32 | throw new Error(ipfsNotInitializedError); 33 | } 34 | 35 | const result = await all(this.ipfs.cat(cid)); 36 | return Buffer.concat(result).toString('base64'); 37 | } 38 | 39 | async getImage(cid: string): Promise { 40 | if(!this.ipfs) { 41 | throw new Error(ipfsNotInitializedError); 42 | } 43 | 44 | const result = await all(this.ipfs.cat(cid)); 45 | return Buffer.concat(result).toString('base64'); 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /homework_07/src/shared/Logger.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Setup the jet-logger. 3 | * 4 | * Documentation: https://github.com/seanpmaxwell/jet-logger 5 | */ 6 | 7 | import Logger from 'jet-logger'; 8 | 9 | const logger = new Logger(); 10 | 11 | export default logger; 12 | -------------------------------------------------------------------------------- /homework_07/src/shared/constants.ts: -------------------------------------------------------------------------------- 1 | export const paramMissingError = 'One or more of the required parameters was missing.'; 2 | export const ipfsNotInitializedError = 'IPFS is not initialized.'; -------------------------------------------------------------------------------- /homework_07/src/views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Descentralized Storage 6 | 7 | 8 | 9 | 12 |
13 |
14 |
15 | Add text: 16 | 17 | 18 |
19 | 20 |
21 | Add image: 22 | 23 | 24 |
25 | 26 |
27 | Get data: 28 | 29 | 30 | 31 |
32 |
33 | 34 | 35 |
36 |
Result:
37 |
38 |
39 |
40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /homework_07/src/views/”https:/bundle.run/buffer@5.2.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anajuliabit/bootcamp-solidity/4f1352e9ddf6184b8637a5bea2856f73527af356/homework_07/src/views/”https:/bundle.run/buffer@5.2.1 -------------------------------------------------------------------------------- /homework_07/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Basic Options */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 8 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 9 | // "lib": [], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 13 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | "outDir": "dist", /* Redirect output structure to the directory. */ 18 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | 27 | /* Strict Type-Checking Options */ 28 | "strict": true, /* Enable all strict type-checking options. */ 29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 30 | // "strictNullChecks": true, /* Enable strict null checks. */ 31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 36 | 37 | /* Additional Checks */ 38 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 42 | 43 | /* Module Resolution Options */ 44 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 45 | "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 46 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 47 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 48 | // "typeRoots": [], /* List of folders to include type definitions from. */ 49 | // "types": [], /* Type declaration files to be included in compilation. */ 50 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 51 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 52 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 53 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 54 | 55 | /* Source Map Options */ 56 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 59 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 60 | 61 | /* Experimental Options */ 62 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 63 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 64 | 65 | /* Advanced Options */ 66 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 67 | "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ 68 | "paths": { 69 | "@shared/*": [ 70 | "src/shared/*" 71 | ], 72 | "@server": [ 73 | "src/Server" 74 | ] 75 | }, 76 | }, 77 | "include": [ 78 | "src/**/*.ts", 79 | "spec/**/*.ts" 80 | ], 81 | "exclude": [ 82 | "src/public/" 83 | ] 84 | } -------------------------------------------------------------------------------- /homework_07/tsconfig.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "sourceMap": false 5 | }, 6 | "exclude": [ 7 | "spec", 8 | "src/**/*.mock.ts", 9 | "src/public/" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /homework_08/Homework_8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anajuliabit/bootcamp-solidity/4f1352e9ddf6184b8637a5bea2856f73527af356/homework_08/Homework_8.pdf -------------------------------------------------------------------------------- /homework_08/contracts/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | artifacts 3 | cache 4 | coverage 5 | -------------------------------------------------------------------------------- /homework_08/contracts/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: false, 4 | es2021: true, 5 | mocha: true, 6 | node: true, 7 | }, 8 | plugins: ["@typescript-eslint"], 9 | extends: [ 10 | "standard", 11 | "plugin:prettier/recommended", 12 | "plugin:node/recommended", 13 | ], 14 | parser: "@typescript-eslint/parser", 15 | parserOptions: { 16 | ecmaVersion: 12, 17 | }, 18 | rules: { 19 | "node/no-unsupported-features/es-syntax": [ 20 | "error", 21 | { ignores: ["modules"] }, 22 | ], 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /homework_08/contracts/.npmignore: -------------------------------------------------------------------------------- 1 | hardhat.config.ts 2 | scripts 3 | test 4 | -------------------------------------------------------------------------------- /homework_08/contracts/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | artifacts 3 | cache 4 | coverage* 5 | gasReporterOutput.json 6 | -------------------------------------------------------------------------------- /homework_08/contracts/README.md: -------------------------------------------------------------------------------- 1 | # Advanced Sample Hardhat Project 2 | 3 | This project demonstrates an advanced Hardhat use case, integrating other tools commonly used alongside Hardhat in the ecosystem. 4 | 5 | The project comes with a sample contract, a test for that contract, a sample script that deploys that contract, and an example of a task implementation, which simply lists the available accounts. It also comes with a variety of other tools, preconfigured to work with the project code. 6 | 7 | Try running some of the following tasks: 8 | 9 | ```shell 10 | npx hardhat accounts 11 | npx hardhat compile 12 | npx hardhat clean 13 | npx hardhat test 14 | npx hardhat node 15 | npx hardhat help 16 | REPORT_GAS=true npx hardhat test 17 | npx hardhat coverage 18 | npx hardhat run scripts/deploy.ts 19 | TS_NODE_FILES=true npx ts-node scripts/deploy.ts 20 | npx eslint '**/*.{js,ts}' 21 | npx eslint '**/*.{js,ts}' --fix 22 | npx prettier '**/*.{json,sol,md}' --check 23 | npx prettier '**/*.{json,sol,md}' --write 24 | npx solhint 'contracts/**/*.sol' 25 | npx solhint 'contracts/**/*.sol' --fix 26 | ``` 27 | 28 | # Etherscan verification 29 | 30 | To try out Etherscan verification, you first need to deploy a contract to an Ethereum network that's supported by Etherscan, such as Ropsten. 31 | 32 | In this project, copy the .env.example file to a file named .env, and then edit it to fill in the details. Enter your Etherscan API key, your Ropsten node URL (eg from Alchemy), and the private key of the account which will send the deployment transaction. With a valid .env file in place, first deploy your contract: 33 | 34 | ```shell 35 | hardhat run --network ropsten scripts/sample-script.ts 36 | ``` 37 | 38 | Then, copy the deployment address and paste it in to replace `DEPLOYED_CONTRACT_ADDRESS` in this command: 39 | 40 | ```shell 41 | npx hardhat verify --network ropsten DEPLOYED_CONTRACT_ADDRESS "Hello, Hardhat!" 42 | ``` 43 | 44 | # Performance optimizations 45 | 46 | For faster runs of your tests and scripts, consider skipping ts-node's type checking by setting the environment variable `TS_NODE_TRANSPILE_ONLY` to `1` in hardhat's environment. For more details see [the documentation](https://hardhat.org/guides/typescript.html#performance-optimizations). 47 | -------------------------------------------------------------------------------- /homework_08/contracts/contracts/VolcanoCoin.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: Unlicense 2 | pragma solidity ^0.8.4; 3 | 4 | import "hardhat/console.sol"; 5 | import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; 6 | import "@openzeppelin/contracts/access/Ownable.sol"; 7 | import "@openzeppelin/contracts/utils/Counters.sol"; 8 | 9 | contract VolcanoCoin is ERC721, Ownable { 10 | using Counters for Counters.Counter; 11 | 12 | struct Token { 13 | uint256 tokenId; 14 | uint256 timestamp; 15 | string tokenURI; 16 | } 17 | 18 | string public baseURI; 19 | uint256 token_id; 20 | mapping(address => Token[]) user_tokens; 21 | Counters.Counter private _tokenIds; 22 | 23 | constructor(string memory _initBaseURI) ERC721("VolcanoCoin", "VLC") { 24 | setBaseURI(_initBaseURI); 25 | } 26 | 27 | function _baseURI() internal view virtual override returns (string memory) { 28 | return baseURI; 29 | } 30 | 31 | function mint(address owner, string memory _tokenURI) 32 | public 33 | returns (uint256) 34 | { 35 | _tokenIds.increment(); 36 | uint256 newItemId = _tokenIds.current(); 37 | _safeMint(owner, newItemId); 38 | 39 | Token memory token = Token(newItemId, block.timestamp, _tokenURI); 40 | user_tokens[owner].push(token); 41 | 42 | return newItemId; 43 | } 44 | 45 | function accountTokens(address _owner) 46 | public 47 | view 48 | returns (Token[] memory) 49 | { 50 | return user_tokens[_owner]; 51 | } 52 | 53 | function _transfer(address to, uint256 tokenId) public { 54 | safeTransferFrom(_msgSender(), to, tokenId); 55 | } 56 | 57 | function setBaseURI(string memory _newBaseURI) public onlyOwner { 58 | baseURI = _newBaseURI; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /homework_08/contracts/hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import "@nomiclabs/hardhat-ethers"; 2 | import * as dotenv from "dotenv"; 3 | import { HardhatUserConfig, task } from "hardhat/config"; 4 | dotenv.config(); 5 | 6 | // This is a sample Hardhat task. To learn how to create your own go to 7 | // https://hardhat.org/guides/create-task.html 8 | task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { 9 | const accounts = await hre.ethers.getSigners(); 10 | 11 | for (const account of accounts) { 12 | console.log(account.address); 13 | } 14 | }); 15 | 16 | // You need to export an object to set up your config 17 | // Go to https://hardhat.org/config/ to learn more 18 | const config: HardhatUserConfig = { 19 | solidity: "0.8.4", 20 | networks: { 21 | hardhat: { 22 | chainId: 31337, 23 | }, 24 | ropsten: { 25 | url: process.env.ROPSTEN_URL || "", 26 | accounts: 27 | process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 28 | }, 29 | rinkeby: { 30 | url: process.env.RINKEBY_URL || "", 31 | accounts: 32 | process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], 33 | }, 34 | }, 35 | }; 36 | 37 | export default config; 38 | -------------------------------------------------------------------------------- /homework_08/contracts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hardhat-project", 3 | "devDependencies": { 4 | "@nomiclabs/hardhat-ethers": "^2.0.2", 5 | "@nomiclabs/hardhat-etherscan": "^2.1.7", 6 | "@nomiclabs/hardhat-waffle": "^2.0.1", 7 | "@typechain/ethers-v5": "^7.2.0", 8 | "@typechain/hardhat": "^2.3.1", 9 | "@types/chai": "^4.2.22", 10 | "@types/mocha": "^9.0.0", 11 | "@types/node": "^16.11.7", 12 | "@typescript-eslint/eslint-plugin": "^4.33.0", 13 | "@typescript-eslint/parser": "^4.33.0", 14 | "chai": "^4.3.4", 15 | "dotenv": "^10.0.0", 16 | "eslint": "^7.32.0", 17 | "eslint-config-prettier": "^8.3.0", 18 | "eslint-config-standard": "^16.0.3", 19 | "eslint-plugin-import": "^2.25.3", 20 | "eslint-plugin-node": "^11.1.0", 21 | "eslint-plugin-prettier": "^3.4.1", 22 | "eslint-plugin-promise": "^5.1.1", 23 | "ethereum-waffle": "^3.4.0", 24 | "ethers": "^5.5.1", 25 | "hardhat": "^2.6.8", 26 | "hardhat-gas-reporter": "^1.0.4", 27 | "prettier": "^2.4.1", 28 | "prettier-plugin-solidity": "^1.0.0-beta.19", 29 | "solhint": "^3.3.6", 30 | "solidity-coverage": "^0.7.17", 31 | "ts-node": "^10.4.0", 32 | "typechain": "^5.2.0", 33 | "typescript": "^4.5.2" 34 | }, 35 | "dependencies": { 36 | "@openzeppelin/contracts": "^4.3.3", 37 | "@openzeppelin/hardhat-upgrades": "^1.12.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /homework_08/contracts/scripts/deploy.ts: -------------------------------------------------------------------------------- 1 | // We require the Hardhat Runtime Environment explicitly here. This is optional 2 | // but useful for running the script in a standalone fashion through `node 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /homework_08/web/src/views/”https:/bundle.run/buffer@5.2.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anajuliabit/bootcamp-solidity/4f1352e9ddf6184b8637a5bea2856f73527af356/homework_08/web/src/views/”https:/bundle.run/buffer@5.2.1 -------------------------------------------------------------------------------- /homework_08/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Basic Options */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 8 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 9 | // "lib": [], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 13 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | "outDir": "dist", /* Redirect output structure to the directory. */ 18 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | 27 | /* Strict Type-Checking Options */ 28 | "strict": true, /* Enable all strict type-checking options. */ 29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 30 | // "strictNullChecks": true, /* Enable strict null checks. */ 31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 36 | 37 | /* Additional Checks */ 38 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 42 | 43 | /* Module Resolution Options */ 44 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 45 | "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 46 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 47 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 48 | // "typeRoots": [], /* List of folders to include type definitions from. */ 49 | // "types": [], /* Type declaration files to be included in compilation. */ 50 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 51 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 52 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 53 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 54 | 55 | /* Source Map Options */ 56 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 59 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 60 | 61 | /* Experimental Options */ 62 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 63 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 64 | 65 | /* Advanced Options */ 66 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 67 | "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ 68 | "paths": { 69 | "@shared/*": [ 70 | "src/shared/*" 71 | ], 72 | "@server": [ 73 | "src/Server" 74 | ] 75 | }, 76 | }, 77 | "include": [ 78 | "src/**/*.ts", 79 | "spec/**/*.ts" 80 | ], 81 | "exclude": [ 82 | "src/public/" 83 | ] 84 | } -------------------------------------------------------------------------------- /homework_08/web/tsconfig.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "sourceMap": false 5 | }, 6 | "exclude": [ 7 | "spec", 8 | "src/**/*.mock.ts", 9 | "src/public/" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /homework_09/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | coverage 4 | coverage.json 5 | typechain 6 | 7 | #Hardhat files 8 | cache 9 | artifacts 10 | -------------------------------------------------------------------------------- /homework_09/Homework_9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anajuliabit/bootcamp-solidity/4f1352e9ddf6184b8637a5bea2856f73527af356/homework_09/Homework_9.pdf -------------------------------------------------------------------------------- /homework_09/README.md: -------------------------------------------------------------------------------- 1 | # Ethers example project 2 | 3 | This project demonstrates a basic Hardhat and Ethers.js use case. 4 | 5 | Run 6 | 7 | ``` 8 | npm i 9 | npx hardhat node 10 | ``` 11 | 12 | to install required packages and start local blockchain. 13 | 14 | For running the tests(separate terminal): 15 | 16 | ``` 17 | npx hardhat test --network hardhat 18 | ``` 19 | 20 | Try running some of the following tasks: 21 | 22 | ```shell 23 | npx hardhat accounts 24 | npx hardhat compile 25 | npx hardhat clean 26 | npx hardhat test 27 | npx hardhat node 28 | node scripts/sample-script.js 29 | npx hardhat help 30 | ``` 31 | 32 | # Ether.js 33 | 34 | https://docs.ethers.io/v5/ 35 | 36 | ### Providers 37 | 38 | A generic API for **account-less** blockchain interaction, regardless of backend 39 | 40 | getDefaultProvider() choices randomly 2/5 nodes and validate values - fallback provider 41 | 42 | ### Signer 43 | 44 | A generic API for creating trusted(i.e. signed) **account-based** data 45 | The most common Signers you will encounter are: 46 | 47 | Wallet, which is a class which knows its private key and can execute any operations with it 48 | JsonRpcSigner, which is connected to a JsonRpcProvider (or sub-class) and is acquired using getSigner 49 | 50 | ### Other differences 51 | 52 | Human Readable ABI 53 | 54 | ``` 55 | const humanReadableAbi = [ 56 | "function transferFrom(address from, address to, uint value)", 57 | "function balanceOf(address owner) view returns (uint balance)", 58 | "event Transfer(address indexed from, address indexed to, address value)" 59 | ]; 60 | ``` 61 | 62 | ENS is a first-class citizen 63 | 64 | ### Setup 65 | 66 | ``` 67 | npm innit -y 68 | npm install --save-dev hardhat 69 | npx hardhat 70 | npm install --save ethers 71 | npm install --save-dev "hardhat@^2.7.0" "@nomiclabs/hardhat-waffle@^2.0.0" "ethereum-waffle@^3.0.0" "chai@^4.2.0" "@nomiclabs/hardhat-ethers@^2.0.0" "ethers@^5.0.0" 72 | 73 | npm install @openzeppelin/contracts 74 | npm install --save-dev @openzeppelin/test-helpers 75 | ``` 76 | 77 | ``` 78 | npx hardhat node 79 | npx hardhat run scripts/your-script.js --network hardhat 80 | npx hardhat test --network hardhat 81 | ``` 82 | -------------------------------------------------------------------------------- /homework_09/contracts/VolcanoCoin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.0; 3 | import "@openzeppelin/contracts/access/Ownable.sol"; 4 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 | import "@openzeppelin/contracts/utils/Strings.sol"; 6 | 7 | contract VolcanoCoin is ERC20("Volcano Coin", "VLC"), Ownable { 8 | 9 | uint256 constant initialSupply = 100000; 10 | 11 | struct Payment{ 12 | uint amount; 13 | address recipient; 14 | } 15 | 16 | mapping (address => Payment[]) public payments; 17 | event supplyChanged(uint256); 18 | 19 | constructor() { 20 | _mint(msg.sender, initialSupply); 21 | } 22 | 23 | function transfer(address _recipient, uint _amount) public virtual override returns (bool) { 24 | _transfer(msg.sender, _recipient, _amount); 25 | addPaymentRecord(msg.sender, _recipient, _amount); 26 | return true; 27 | } 28 | 29 | function addPaymentRecord(address _sender, address _recipient, uint _amount) internal { 30 | payments[_sender].push(Payment(_amount,_recipient )); 31 | } 32 | 33 | function addToTotalSupply(uint256 _quantity) public onlyOwner { 34 | _mint(msg.sender,_quantity); 35 | emit supplyChanged(_quantity); 36 | } 37 | 38 | function getPayments(address _user) public view returns (Payment[] memory) { 39 | return payments[_user]; 40 | } 41 | } -------------------------------------------------------------------------------- /homework_09/hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("@nomiclabs/hardhat-waffle"); 2 | 3 | // This is a sample Hardhat task. To learn how to create your own go to 4 | // https://hardhat.org/guides/create-task.html 5 | task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { 6 | const accounts = await hre.ethers.getSigners(); 7 | 8 | for (const account of accounts) { 9 | console.log(account.address); 10 | } 11 | }); 12 | 13 | // You need to export an object to set up your config 14 | // Go to https://hardhat.org/config/ to learn more 15 | 16 | /** 17 | * @type import('hardhat/config').HardhatUserConfig 18 | */ 19 | module.exports = { 20 | solidity: "0.8.4", 21 | networks: { 22 | hardhat: {}, 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /homework_09/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ethersbitdao", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@nomiclabs/hardhat-ethers": "^2.0.2", 14 | "@nomiclabs/hardhat-waffle": "^2.0.1", 15 | "@openzeppelin/test-helpers": "^0.5.15", 16 | "chai": "^4.3.4", 17 | "ethereum-waffle": "^3.4.0", 18 | "ethers": "^5.5.1", 19 | "hardhat": "^2.7.0" 20 | }, 21 | "dependencies": { 22 | "@openzeppelin/contracts": "^4.4.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /homework_09/scripts/sample-script.js: -------------------------------------------------------------------------------- 1 | // We require the Hardhat Runtime Environment explicitly here. This is optional 2 | // but useful for running the script in a standalone fashion through `node