142 lines
6.1 KiB
Markdown
142 lines
6.1 KiB
Markdown
# ⚡ 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=<your_ethereum_rpc_endpoint_here>
|
|
PRIVATE_KEY=<your_private_key_here> # TEST NETWORK ONLY
|
|
PRIVATE_KEY_PASSWORD=<your_keystore_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: **[email protected]**
|
|
- 💬 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.*
|