# ⚑ Ethers.js Simple Storage A hands-on learning project building, deploying, and interacting with a `SimpleStorage` smart contract using [ethers.js](https://docs.ethers.org/v5/) (v5) and the Solidity compiler (`solc`). This repo documents my first step from traditional Web2 development toward **Web3 / blockchain development** β€” writing Solidity, compiling it, and driving a contract on-chain *without* a heavyweight framework like Hardhat or Foundry. Just Node.js, `ethers.js`, and `solc`. --- ## 🧠 What I Learned This project was built to learn the **fundamentals of smart-contract development**, one concept at a time: - βœ… **Solidity basics** β€” state variables, `struct`, `array`, `mapping`, `function` visibility & purity (`public`, `view`). - βœ… **Compiling Solidity manually** with `solc` to produce the ABI + bytecode (`.abi` & `.bin` files). - βœ… **ethers.js Provider & Wallet** β€” connecting to an RPC endpoint and signing with a raw private key. - βœ… **Deploying a contract** via a `ContractFactory` (ABI + bytecode + signer). - βœ… **Reading & writing the blockchain** β€” calling a state-changing `store()` (sends a transaction, waits for confirmation) vs. reading with `retrieve()` (free, no gas). - βœ… **Async JavaScript** β€” the `Promise` lifecycle (`pending` β†’ `fulfilled` / `rejected`) that powers all on-chain interaction. - βœ… **Environment variables (`dotenv`)** β€” keeping secrets out of the code. - βœ… **Secure key handling** β€” `encryptKey.js` encrypts a private key into an encrypted JSON keystore (using `PRIVATE_KEY_PASSWORD`) for production-style deployment. ## πŸ› οΈ Tech Stack | Tool | Purpose | |------|---------| | [Solidity](https://soliditylang.org/) `0.8.7` | Smart contract language | | [ethers.js](https://docs.ethers.org/v5/) `5.7.2` | Ethereum/blockchain library (Provider, Wallet, ContractFactory) | | `solc` `0.8.7` | Solidity compiler (CLI) | | `dotenv` | Environment variables / secrets | | `fs-extra` | File system helpers (read ABI / bytecode, write keystore) | | `prettier` + `prettier-plugin-solidity` | Code formatting | ## πŸ“ Project Structure ``` ethers-simple-storage/ β”œβ”€β”€ SimpleStorage.sol # The smart contract β”œβ”€β”€ simpleStorage_*.abi / .bin # Compiled output (ABI + bytecode) β”œβ”€β”€ deploy.js # Compile β†’ deploy β†’ read/write on-chain β”œβ”€β”€ encryptKey.js # Encrypt a private key into a JSON keystore β”œβ”€β”€ package.json # Dependencies + scripts └── .env # Local only (git-ignored): RPC_URL, PRIVATE_KEY ``` ## πŸš€ Getting Started ### 1. Install dependencies ```bash yarn install ``` ### 2. Set up environment variables Create a `.env` file (git-ignored) at the project root: ```ini RPC_URL= PRIVATE_KEY= # TEST NETWORK ONLY PRIVATE_KEY_PASSWORD= # used by encryptKey.js ``` > ⚠️ **Security note:** never commit a real private key. Use a **test network** (e.g. Sepolia) or a local node (e.g. Ganache at `http://192.168.1.10:7545`). For production, prefer an encrypted keystore (see below). ### 3. Compile the contract ```bash yarn compile ``` This runs `solcjs` and generates `SimpleStorage_sol_SimpleStorage.abi` and `.bin` in the project root. ### 4. Deploy & interact ```bash node deploy.js ``` You'll see the contract address, the current favorite number, then the updated favorite number after calling `store(7)`. ### (Optional) Secure key storage ```bash node encryptKey.js ``` Writes a password-encrypted keystore to `.encryptedKey.json` (git-ignored). Switch the commented-out code in `deploy.js` to use it instead of a raw private key. --- ## πŸ’‘ About the Contract β€” `SimpleStorage` ```solidity contract SimpleStorage { uint256 favoriteNumber; struct People { uint256 favoriteNumber; string name; } People[] public people; mapping(string => uint256) public nameToFavoriteNumber; function store(uint256 _favoriteNumber) public { ... } // write (costs gas) function retrieve() public view returns (uint256) { ... } // read (free) function addPerson(string memory _name, uint256 _favoriteNumber) public { ... } // write } ``` - **`store()` / `retrieve()`** β€” a state variable you can write and read. - **`addPerson()`** β€” demonstrates a `struct` pushed into a dynamic `array`, plus a `mapping` from name β†’ favorite number (your first taste of more realistic on-chain data patterns). ## πŸ—ΊοΈ Roadmap / Next Steps - [ ] Refactor to a production structure (separate compile / deploy scripts). - [ ] Try a real framework like [Hardhat](https://hardhat.org/) or [Foundry](https://book.getfoundry.sh/) for testing & tooling. - [ ] Add tests (e.g. with Foundry or Chai) to lock in contract behavior. - [ ] Deploy to a real network and verify the contract on a block explorer. --- ## πŸ‘¨πŸ’» About the Author Hello! I'm **Hoelee** β€” a hands-on developer and self-hoster based in Malaysia, currently making the leap from Web2 toward **Web3 / blockchain development**. My Web2 background spans **PHP/CodeIgniter**, **Java/Spring**, **JavaScript/Node.js**, and WordPress (Kadence/Elementor) SME sites β€” and I run my own email hosting business at [SifuMail](https://sifumail.com) (my projects live at [hoelee.com](https://hoelee.com)). I'm building real projects to learn, and I welcome comments, feedback, and contributions. This repo is part of my journey toward on-chain development, and I'm always happy to connect: - 🌐 Portfolio: **https://hoelee.com** - βœ‰οΈ Email: **me@hoelee.com** - πŸ’¬ WhatsApp: **012-797 2969** > **πŸ’Ό Open to remote opportunities** in Web3 / blockchain development (Solidity, ethers.js, Hardhat/Foundry, smart-contract security) and full-stack web. If you're hiring a self-taught, self-hosted developer who ships and learns fast β€” I'd love to talk. --- ## πŸ“œ License MIT β€” free to learn from, fork, and build on. --- *Built for learning. Simple, honest, and incrementally improved β€” the same way I approach every new technology.*