2024-08-02 03:25:16 +08:00
2024-08-02 03:25:16 +08:00
2024-08-02 03:51:49 +08:00
2024-08-02 03:25:16 +08:00
2024-08-02 03:25:16 +08:00
2024-08-02 03:25:16 +08:00
2024-08-02 03:25:16 +08:00
2024-08-02 03:25:16 +08:00

⚡ Ethers.js Simple Storage

A hands-on learning project building, deploying, and interacting with a SimpleStorage smart contract using ethers.js (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 0.8.7 Smart contract language
ethers.js 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

yarn install

2. Set up environment variables

Create a .env file (git-ignored) at the project root:

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

yarn compile

This runs solcjs and generates SimpleStorage_sol_SimpleStorage.abi and .bin in the project root.

4. Deploy & interact

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

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

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 or Foundry 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 (my projects live at 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:

💼 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.

S
Description
Learning project: SimpleStorage Solidity contract deployed & interacted with via ethers.js v5 + solc. My first step from Web2 to Web3.
Readme
52 KiB
Languages
JavaScript 100%