历史是前进的, 从第一个创世区块的产生和以太坊协议的部署开始, 人类社会就迈出了走向未来社会变革的伟大的一步.


CT degens: CT stands for Crypto Twitter, degens refer to a link-minded group who buys crypto asset not because they believe in it, but because they believe someone else would buy it from them.

GM: good morning

GN: good night

GMI / WAGMI: we all gonna make it

NGMI: not gonna make it

Ape: taking a large position in relative to one's portfolio size (related to BAYC?)

Probably Nothing: "Probably Something"

Mint: interact with contract to get something

IYKYK: If You Know, You Know

Few: few understands

Normies: people who don't touch cryptos

Shill: Shilling is when someone is actively promoting a certain behaviour with a hidden motive.

LFG: Let's fucking go. [Rocket] [Rocket] [Rocket]

FOMO: fear of missing out

Cope: opposite of FOMO

Related Topics

Central Bank Digital Currency (CBDC): CBDC Tracker

Decentralized Digital Identifications (DDID): by zero-knowledge proof

Get Anonymous Crypto:

[ENS] Domain: a domain service for wallet address

Mining Cryptocurrency

Mining Pool List

Stale Share: either result send to centralized pool is correct but someone is ahead of you

Mining Software

Biggest Mining Pool

LHR Hack:

Operating System: HiveOS

Bitcoin Technology

Blockchain as a Bookkeeping System in Analogy

Here is a Good Intro Video by 3B1B.

区块链是由比特币创造的, 所以我们先说比特币. 比特币是一种分布式账本. 我们先用一个例子来说明.

假如有这样一个城市, 城市的人民为了节省制造货币的材料而不使用货币, 取而代之的是, 城市中所有的人会把自己和所有其他人的收入和支出记在一个小本本上, 这样一来每人都知道其他人的余额, 以方便日后一对一的交易. 于是, 每个人在买东西的时候都会大叫一声: 嘿, 我要给张三 10 块钱, 这是第 204 笔交易. [前面 203 笔交易的总结文本], [加上这笔交易后的总结文本]. 注意, 嘿, 我要给张三 10 块钱 是数字签名过的信息: 大家都能读取消息的内容并且可以验证这条消息是谁发出的. 其中两个总结文本是所有人钱包余额的总结文本, 这两条文本确保了每个消息只能记录一次. 由以下公式得出. 大多数人纷纷拿起笔抄了下来.

\text{总结文本}_{t+1} = 总结(\text{总结文本}_{t} + \text{新交易})


Here is a deeper dive into mechanics of P2P Network implementation

nonce: Cryptography order of transection, increase by exactly 1 for each transection. If it is the same as historic transection, they are seen as the same transection. Having nonce can invalidate historical un-mined transection and replace it with higher gas fee for quicker mining.


Wallets: a pair of private key and address (without public key). Usually you can find address by using only private key. This process is polynomial time but reverse process is NP-hard.

A public and private key pairs (BTC) generated from online wallet generator

A public and private key pairs (BTC) generated from online wallet generator

Paper Wallet: Paper Wallet is private and public key you can write down on paper.

MetaMask: Open source Ethereum wallet, probably the only wallet on browser.

Blockchain Mining

挖矿: 一种争夺记账权并且通过共识系统获得奖励的方式. 全网总算力越大, 单个服务器收益越小


目前比特币总市值小于黄金(12万亿), 当比特币总市值等于黄金时: 57万美元一枚

手续费奖励 (gas fee): 大约每笔交易 0.0005

PoW: proof of work (显卡计算 difficult computing problem 挖矿) PoC: proof of capacity (硬盘挖矿) PoS: proof of stack (伪随机挖矿, 且概率正比与已有的 coin)

Transection Speed: It feels to me like we can greatly reduce transection speed if we reduce network latency. This way, we can shorten the block length and decrease PoW to the point that it becomes proof of network latency.


ETC: Ethereum classic, the one originally created by Vitalik Buterin, but hard-forked due to people stole a lot of Ethereum and Vitalik suggest a hardfork, making old Ethereum ETC and new Ethereum (where the hack never happened) ETH.


ETH symbol: \Xi

Dynamic Blocksize in EIP 1599

Dynamic Blocksize in EIP 1599

EIP 1559:

ETH2 Serenity Mechanics

Time line

Beacon Chain

Beacon Chain

Slots, Blocks, and Validator

Slots, Blocks, and Validator

The Beacon Chain enforces consensus on a pseudorandom process called RANDAO. At every epoch, a pseudorandom process RANDAO selects proposers for each slot, and shuffles validators to committees.

The Beacon Chain enforces consensus on a pseudorandom process called RANDAO. At every epoch, a pseudorandom process RANDAO selects proposers for each slot, and shuffles validators to committees.

ETH2 (Serenity): beacon and shards chain


Blockchain Application and Ecosystem


DAO: 是一个分布式的盈利组织



KYC: Know your customer (调查用户身份)

DAOMaker: DAO Maker creates growth technologies and funding frameworks for startups, while simultaneously reducing risks for investors.

PeopleDAO: buy constitution



In the eyes of banks and regulations, these terms are used

There is a small difference between the word "coin" and "token". See Regulations and Distinguish Between Coin and Token.

pre-mine and allocation

pre-mine and allocation

Token Properties

Wrapped Token:

Oracle Machine: get off-chain information including deterministic random number

DAI: a stable currency manipulated by MakerDAO, unlike USDT whose controlled by a company.

USDT: non-algorithmic stable coin (centralized, like USDC, PACKS), backed by company called "Tether", on multiple chains. The company promise to exchange 1 USD to 1 USDT back and forth.

算法稳定币: 创造需求并通过市场信任而无背书的与法币挂钩的货币. 详见 这篇文章分析

Ren: Enable you to switch asset on different main chain, pay both ETH miner and BTC miner with insane gas fee and will probably fail because you don't own any ETH to pay the miners.

UNI (Uniswap): a liquidity pool-based currency (on Ethereum) that is used to exchange between currency (ETH and any ERC20 currency) (source)

Compound: A lending, borrowing contract, currency that implements variable supply / borrow APY (annual percentage yield) depending on borrowing supply and demand. Source

AAVE: Like Compound aTOKEN, but in top of variable supply / borrow APY, also offer stable borrow APY (fixed in short term, variable in long term) and flash loan (borrow for a time of 1 ETH transaction).

Arbitrage with Flask Loans

Arbitrage with Flask Loans

Collateral Swap with Flask Loans

Collateral Swap with Flask Loans

Self-liquidation with Flask Loans

Self-liquidation with Flask Loans

Flash Loans: borrow money in one automic transaction (AAVE and dy/dx protocol)

Ordered Book Based: loopring, idex

Derivative: contracts that depends on other (future) variables. syntheticx (provide on-chain exposure to different currency)

Margin Trading: using borrowed fund to increase position (dy/dx, fulcrum)

Insurance: guarantee or compensation, protection of smart contract failure and deposit. (nexus mutual, opyn)

Risk of DeFi:

  1. Bugs in protocol
  2. How decentralized they are
  3. Admin key and on-chain governor, influencer
  4. Network fee
  5. Liquidation
  6. Subtle change in other protocol
  7. Attacks on liquidity pool
  8. leverage: borrow more token with borrowed token

Yield Farming: make max profit out of compound, uniswap, curve, synthetics, balancer by move funds around (crop rotation). They can profited by fees and extra incentive mechanics of a currency.

Cross-Chain Transfer:


The NFT stack as of 2021/08 from

The NFT stack as of 2021/08 from

Opensea: biggest and centralized NFT trading platform with instane fee OpenDao: DAO created for NFT community, may be protest against Opensea.

Minecraft Voxel home plot:


Axie: 卡牌对战游戏, 需要购买 3 只 AXIE 启动资金.

Here is a good article about GameFi in 2022

BlokTopia: Metaverse for news exchange and publication

DarkForest: hidden information game, with its zkSNARKs

DarkForest is probably the only game I aspire in the blockchain world. For game developers, Here are articles on how to make on-chain game competitive.

Stepn: Stepn run to earn. Gamify running.

Nouns: Nouns, mint one avatar every day, bid for on-chain identity.

Wolf Game: Wolf // TODO

Kantan Game: Kantanainu, play-2-earn battle PC game

The Crypt Game: Crypt, Loot-based Dungeon Raiding for Forbidden NFT Relics. Twitter Topology, developing on-chain physics on StarkNet chain. Twitter

Special Gaming Mechanisms:

Game Making Resources

Resources Website:

Some Free 3D Models & Textures:

Free Skyboxes:

OpenGL Documentation

Dark Forest

Dark Forest

Planet Types:

Planet Utility:

Dark Forest Plugin Development

npm install --global yarn npm install -g @darkforest_eth/gamelogic npm install -g @projectsophon/df-plugin-dev-server

Metaverse Games

以我的观点, Metaverse 可以是一个游戏平台, 一个社交平台, 一个购物平台, 但绝对不是一个生活平台, 而且 VR 不是必须 (除非它是一个增强版本的 AR 世界).


New Launchpad on The BLOK on BlockTopia:

Sipher: game with good vision and roadmap

Sunflower Farmers: Plant, Craft, Chop, Mine, Fight, Earn. Sunflower Farmers, Open source, no pre-sale and no premine.

Other Projects

Application Project

// TODO ENS: Decentralized naming for wallets and websites, selling .eth domain owned by Ethiopia. They have their token named ENS for its DAO.

Classification of Goods

Classification of Goods

Quadratic Funding: a proposed smart way to distribute funding money by quadratic formula that says your voice is square root of your money. Video

Opensource Project Funding:

Metafora // TODO: ...

Technical Projects


Side Chain: independent chain, but will update once awhile on Ethereum main chain

Plasma Network: kinda like beacon, shard to the extreme? // TODO

Rollups: based on EVM start contract, batched transection - ZkRollups: transections are by default guilty unless proved innocent - OptimisticRollups: assume correct unless (fraud) proved guilty, has a dispute period

Loopring: lower gas fee layer 2 solution

Polygon (MATIC): side chain PoS solution with plasma network

Optimism: main-net with optimistic roll up

Arbitrum: optimistic roll up

Layer-2 Solutions:

Diem: Diem (formerly known as Libra) is a permissioned (regulated) blockchain-based payment system proposed by the Meta (formally Facebook). It is regulated with Libra Association (later renamed to Diem Association) founded in Geneva, Switzerland. The currency and network do not yet exist. The launch was originally planned to be in 2020,[3][4] but only rudimentary experimental code has been released.

Worldcoin (ERC20): use iris tracing (scanning eyes) to give people basic income. Personal info will be collected and the idea of basic income may be a flaw. See Youtube

MetaHero: bring on the next 10 million new users to cryptocurrency

Good tech to research:// TODO

Web3, DApp Contracts Development

Web3: Web3 increase data accessability from individual companies to everyone while stress data ownership to individuals.

Application Examples

Subgraph: how it works

Subgraph: how it works

Subgraph: an oracle of blockchain historical data provider

Learning Material

How to learn?

  1. CryptoZombies
  2. BuildSpace
  3. Personal Toy Projects
  4. Join a team/DAO


Chainlink Starter Kits:

From BuildSpace

Intro to web3 -- build a web3 version of Twitter:
Mint your own, custom NFT collection: Note: This is one is perfect if you’re confident in your web dev skills.
Ship an epic Web3 app on Solana with React/ Rust:
Build your own DAO with just Javascript:
Build a turn-based, NFT browser game on Ethereum:
Build an NFT collection Solana with just Javascript:

// You can take the projects in any order you want, can even sign-up for all 3. But, if you're not super confident in picking up new tech -- we'd recommend taking the "Intro to Web3" project first. If you're pretty confident in your ability to pick up new tech, the NFT or game project would be good!
// Each project will probably take you like 5-10 hours. Depends on your skill level.
// Learn JS:, Learn React:



Example Project: BBoxDAO by @daoleno#1135

Contracts Development Knowledge

EVM: Ethereum Virtual Machine

ERC20: A interface protocol for creating new currency on ETH using smart contract. There is a unintended behavior in which implementations of ERC20 only accept a certain currency to exchange for the implementation. If wrong currency is used, those tokens in wrong currency will be lost.

ERC223: The above problem is fixed in this new protocol. (source: ERC20 tokens - Simply Explained

ERC1155: Mix of ERC20 and ERC223 by creating metadata field. You can create it in one contract and transfer once. Here is a good video explaning the concept.

Good Stuff to Read:

Frontend Libraries: web3.js, ethers.js connect MetaMask

Backend Libraries: Hardhat and Truffle Suite (for localhost contract testing with MetaMask), Ganache (for simulating blockchain locally), Openzeppelin (for template), Waffle (automatic unit test)

Offchain Storage: IPFS (decentralized file sharing), OrbitDB and ThreadDB (database built on top of IPFS)

WebIDE: Remix IDE

Mirror: write articles on chain



Fantom: deployment DApp

Tutorials Series: // TODO: clean up

Truffle Environment

Node Environment

npm stands for node package manager. However, npm has multiple versions, so it is suggested to install nvm to comtrol the versions of npm and node. To install nvm:

curl -o- | bash
nvm install

If nvm not found, you should add path to ~/.bashrc. Sometimes reopening terminal does not work, this typically happen when you are using ~/.zshrc instead of ~/.bashrc (strangely bash does not run ~/.bashrc too). In this case, you need to run the following command or add the following command to your ~/.zshrc:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/" ] && \. "$NVM_DIR/"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completio

After installed, you should be able to use node --version to find out your current version of npm. Other often used commands of nvm are:

When you first install, it will make your first installation default version:

Now using node v16.17.0 (npm v8.15.0)
Creating default alias: default -> 16 (-> v16.17.0)

Note that nvm don't switch version for every opening of terminals. To set default behavior: do nvm alias default 16.14.0

Trouble Shooting NPM Install

To check system-wide installation: npm list -g --depth=0. The place where the install package is is npm bin -g.

If you encountered errors about nvm is not compatible with the npm config "prefix":

npm config delete prefix
npm config set prefix $NVM_DIR/versions/node/v[YOUR_VERSION]

If you installed package using nvm provided npm, you should see those package in /home/koke_cacao/.nvm/versions/node/v16.14.0 where ${NVM_DIR} = /home/koke_cacao/.nvm. If you don't see them, and find out that you nvm use 16 and it installed to /home/koke_cacao/.nvm/versions/node/v17.5.0 instead, then it is your .npmrc made this behavior. You can solve this simply by removing .npmrc. This behavior is documented here

Yarn Environment

We install yarn globally npm install --global yarn.

Sometimes, when you do yarn global add [package], you cannot find the package you installed. You need to add yarn's package directory to path. Normally, you can do PATH=/home/$USER/.yarn/bin:$PATH

Now, npm is not a good package manager, to migrate from npm to yarn, simply run yarn in project directory. See migration guide for detail.

Solidity Environment

We have node, nvm, npm, yarn, corepack

Normally, you do not need standalone version of solidity. Your Truffle or Hardhat (and even VSCode) will provide solidity versions for you.

Install Solidity Using Hardhat or Truffle (Recommanded)

Just install hardhat or truffle. Those libraries will automatically detect the version of solidity you need and install them when you try to compile.

Install Solidity Using VSCode (Not Recommanded)

You can download solidity VSCode plugin at configure it to use remote. Note that this VSCode's solidity is a online version of solidity.

Install Solidity Using NPM (Not Recommanded)

If you insist, to globally install solidity compiler, you do: npm install -g solc.

Now you have solc package, try soljs --help.

Truffle and Ganache Environment

npm install -g truffle: install truffle test suit npm install -g ganache: install ganache for EVM server (recommanded, its the same as ganache-cli on Linux. Set port to HTTP:// when using graphical interface) npm install -g ganache-cli: install ganache command line interface for EVM server truffle create test Egg: create sample tests for Egg contract truffle console --network development: running truffle server for debug (good with ganache). You can get accounts with let accounts = await web3.eth.getAccounts(). truffle develop: spawn a EVM at port 9545

When testing, run ganache-cli or ganache to start the EVM server. And then deploy contract using truffle migrate (you can use --reset to run all your migrations from the beginning) and test contract using truffle test. Note that truffle also comes with a solidity version.

If you are on linux, use ganache server if you wish to use command line. Use .AppImage version if you need graphical interface.

Hardhat Environment

Setup Project:

Then, you can use these commands:

yarn hardhat accounts
yarn hardhat compile
yarn hardhat clean
yarn hardhat test
yarn hardhat node
node scripts/sample-script.js
yarn hardhat help
yarn hardhat run scripts/deploy.js --network localhost

All the settings are in hardhat.config.js. Here is a Good Hardhat Workflow Tutorial

Frontend Environment

Node.js is a Javascript engine. It is not a framework.

There are a few important package for web server:

  1. yarn add express: express minimalist framework (here is a good Express Tutorial)
  2. yarn global add nodemon: automatic refresh webpage upon change

Complete Architecture and Testing Environment

Using NPM

npm init -y: run in the project directory to init package.json file for node project after doing touch index.js

  "name": "cryptoeggs_frontend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  "keywords": [],
  "author": "",
  "license": "ISC"

Using Yarn

Just replace every npm with yarn and install with add.

Using PM2

PM2 runs our node.js application as a background process in production environment.

To install PM2: yarn global add pm2 (yarn install -g pm2 is depricated) To run PM2 server: pm2 start app.js Show all apps running: pm2 status Rstart apps: pm2 restart app.js Stop apps: pm2 stop app.js Show logs: pm2 logs Flush logs: pm2 flush Setup automatic launch when server starts: pm2 startup ubuntu

When automatically setup init script, pm2 may tell you do to the following command.

sudo env PATH=$PATH:/home/ubuntu/.nvm/versions/node/v16.17.0/bin /home/ubuntu/.config/yarn/global/node_modules/pm2/bin/pm2 startup ubuntu -u www-data --hp /home/ubuntu

The -u flag is to specify which user you want to execute pm2 as and the --hp flag is to specify home directory. env PATH=$PATH:/home/ubuntu/.nvm/versions/node/v16.17.0/bin /home/ubuntu/.config/yarn/global/ is just run pm2 command with some environment variables. After you run the command, it will create /etc/systemd/system/pm2-ubuntu.service for you.

Here is a full tutorial on how to depoy npm apps.

Module Bundlers

If you try to install dependency for front end, you are in trouble because browser parser don't understand import or require. You need to use some sort of Module Bundlers for frontend development. Here is a good overview on what is module bundler

There are choices:

Web Assembly

Videos To Learn

Contract Programming Notes

ether: 1 ETH wei: there are 10^{18} wei in one ether event: A ethereum logging system, for front end to listen (instead of constantly refresh). Data in logging can't be access by contracts, but are emitted by contracts. I guess servers don't need to store them if they don't want. For detailed explanation: Events and Deployment

```solidity zombiefactory.sol pragma solidity 0.4.19; // engine version, don't use [^] since it may create bug

// with "@chainlink/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol"; you can import code from Github import "./ownable.sol";

contract ZombieFactory is Ownable{ event NewZombie(uint zombieId, string name, uint dna);

  // 通常情况下我们不会考虑使用 uint 变种, 因为无论如何定义 uint 的大小
  // Solidity 为它保留 256 位的存储空间. 例如, 使用 uint8 而不是 uint (uint256) 不会为你节省任何 gas.
  // 除非把 uint 绑定到 struct 里面
  uint dnaDigits = 16; // globals
  uint dnaModulus = 10 ** dnaDigits;

  struct Zombie {
      string name;
      uint dna;

  // dynamic array
  // public will automatically create a public getter function
  Zombie[] public zombies; // read only

  // mapping to user data
  mapping (uint => address) public zombieToOwner;
  mapping (address => uint) ownerZombieCount;

  // private means no user can call this function, for contract internal use, not even child contract
  // internal 和 private 类似, 不过, 如果某个合约继承自其父合约, 这个合约即可以访问父合约中定义的 "内部" 函数.
  // external 与 public 类似, 只不过这些函数只能在合约之外调用 - 它们不能被合约内的其他函数调用.
  // private < internal < public < external
  function _createZombie(string _name, uint _dna) internal {
      // in some cases, [push] will not increase array length
      uint id = zombies.push(Zombie(_name, _dna)) - 1;
      // add to mapping
      // msg.sender here is internal function, address of contract signer
      zombieToOwner[id] = msg.sender;
      // broadcast
      NewZombie(id, _name, _dna);

  // view: can access contract data, cannot write. Does not cost gas (when called externally, or internally with no non-view parents) because it only queries 1 node instead of all.
  // pure: cannot read, cannot write
  // keccak256: a function that generates 256位的16进制数字. Unsafe for blockchain.
  function _generateRandomDna(string _str) private view returns (uint) {
      uint rand = uint(keccak256(_str));
      return rand % dnaModulus;

  // require: will refund gas fee to caller
  // assert: will not refund, something horrible goes wrong (like overflow when using SafeMath library)
  function createRandomZombie(string _name) public {
      require(ownerZombieCount[msg.sender] == 0);
      uint randDna = _generateRandomDna(_name);
      _createZombie(_name, randDna);


```solidity zombiefeeding.sol
pragma solidity ^0.4.19;

import "./zombiefactory.sol";

// interface: just a code template for the interpreter. No real connection.
contract KittyInterface {
  function getKitty(uint256 _id) external view returns (
    bool isGestating,
    bool isReady,
    uint256 cooldownIndex,
    uint256 nextActionAt,
    uint256 siringWithId,
    uint256 birthTime,
    uint256 matronId,
    uint256 sireId,
    uint256 generation,
    uint256 genes

// inheritage: literally adding code from ZombieFactory to ZombieFeeding
contract ZombieFeeding is ZombieFactory {

  // Below implementation would not resist new contract version of Kitty
  // address ckAddress = 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d;
  // referencing a contract instance by its address (remember, there is only one instance for every contract)
  //KittyInterface kittyContract = KittyInterface(ckAddress);

  KittyInterface kittyContract;
  // use [onlyOwner] decorator, see [ownable.sol]
  function setKittyContractAddress(address _address) external onlyOwner {
    kittyContract = KittyInterface(_address);

  function feedAndMultiply(uint _zombieId, uint _targetDna, string _species) public {
    require(msg.sender == zombieToOwner[_zombieId]);
    Zombie storage myZombie = zombies[_zombieId];
    _targetDna = _targetDna % dnaModulus;
    uint newDna = (myZombie.dna + _targetDna) / 2;
    // Note: solidity does not support string comparison
    // to compare content of string, use `require(keccak256(_name) == keccak256("Vitalik"));`
    if (keccak256(_species) == keccak256("kitty")) {
      newDna = newDna - newDna % 100 + 99;
    _createZombie("NoName", newDna);

  function feedOnKitty(uint _zombieId, uint _kittyId) public {
    uint kittyDna;
    (,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);
    feedAndMultiply(_zombieId, kittyDna, "kitty");


```solidity ownable.sol contract Ownable { address public owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

// constructor, only execute once when contract first created
function Ownable() public {
  owner = msg.sender;

// create a new decorator to use to decorate other functions
modifier onlyOwner() {
  require(msg.sender == owner);

function transferOwnership(address newOwner) public onlyOwner {
  require(newOwner != address(0));
  OwnershipTransferred(owner, newOwner);
  owner = newOwner;


The machine run one instance of the program, therefore globals are used as storage. When creating local variable from globals, you either specify `memory` to receive a copy of specify `storage` to receive the actual instance. `storage` is a magnitude more expensive than `memory` since `storage` need to be synced with all nodes (regardless of `view`?).

Different Places to Store: [Youtube](

- storage: when changed, will change block data

- memory: when changed, will not change block data, big struct

- stack: stack, small storage like integers

- calldata: data passed to contract during transmission

Payable: a function can be marked as `payable` to accept money. This can be achieved in `web3.js` with `OnlineStore.buySomething().send(from: web3.eth.defaultAccount, value: web3.utils.toWei(0.001))`. And in the backend `require(msg.value == 0.001 ether);`. The contract has an account (contract address) which stores those money to maintain balance. In a function to buy stuff from the seller, buyer will execute the code `seller.transfer(msg.value)`

To get money as a owner from the locked value in contract: Note that the value of `ETH` will change and therefore it is a good idea to allow the owner of the contract to change certain price.
contract GetPaid is Ownable {
  function withdraw() external onlyOwner {
    address payable _owner = address(uint160(owner()));

Unsafe Random Number: this will result miner to selectively include transection until random number gives desired outcome

// Generate a random number between 1 and 100:
uint randNonce = 0;
uint random = uint(keccak256(abi.encodePacked(now, msg.sender, randNonce))) % 100;
uint random2 = uint(keccak256(abi.encodePacked(now, msg.sender, randNonce))) % 100;

Safely Generate Random Number: read StackOverflow. One idea is to use off-chain oracle.

ERC721 Token: a collection of non-identical tokens

contract ERC721 {
  event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
  event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);

  function balanceOf(address _owner) external view returns (uint256); // how many distinct tokens owner has
  function ownerOf(uint256 _tokenId) external view returns (address); // who own this token
  function transferFrom(address _from, address _to, uint256 _tokenId) external payable; // either called by [_from] or approved address; emit Transfer
  function approve(address _approved, uint256 _tokenId) external payable; // caller approve [_approved] to take [_tokenId] from caller; emit Approval

Library: in a contract, call using SafeMath for uint256; will add extra functions to native datatype.

natspec: commenting style

/// @title A contract for basic math operations
/// @author H4XF13LD MORRIS 💯💯😎💯💯
/// @notice explains to a user what the contract / function does. For now, this contract just adds a multiply function
contract Math {
  /// @notice Multiplies 2 numbers together
  /// @param x the first uint.
  /// @param y the second uint.
  /// @return z the product of (x * y)
  /// @dev for explaining extra details to developers. This function does not currently check for overflows
  function multiply(uint x, uint y) returns (uint z) {
    // This is just a normal comment, and won't get picked up by natspec
    z = x * y;

To PERMANENTLY remove contract code: doc

function kill() public onlyOwner {
   selfdestruct(owner()); // remaining ether goes to owner

[selfdestruct] is the only way for code at a certain address to be removed from the blockchain. This makes it a pretty important feature! Even if a contract’s code does not contain a call to [selfdestruct], it can still perform that operation using [delegatecall] or [callcode].

Front-end Programming Note

Here is a good API tutorial.

There are two libraries to use for front end:


window.addEventListener('load', function() {
  // Checking if Web3 has been injected by the browser (Mist/MetaMask)
  if (typeof web3 !== 'undefined') {
    // Use Mist/MetaMask's provider
    web3js = new Web3(web3.currentProvider);
  } else {
    // Handle the case where the user doesn't have web3. Probably show them a message telling them to install Metamask in order to use our app.
  // Now you can start your app & access web3js freely:

Note: Metamask uses Infura's servers under the hood as a web3 provider, just like we did above — but it also gives the user the option to choose their own web3 provider. So by using Metamask's web3 provider, you're giving the user a choice, and it's one less thing you have to worry about in your app.

To "listen" to change account event:

var userAccount;
var accountInterval = setInterval(function() {
  if (web3.eth.accounts[0] !== userAccount) { // Check if account has changed
    userAccount = web3.eth.accounts[0];
    updateInterface(); // Call some function to update the UI with the new account
}, 100);

To send:

function createRandomZombie(name) {
  $("#txStatus").text("Creating new zombie on the blockchain. This may take a while...");
  return cryptoZombies.methods.createRandomZombie(name)
  // [gas], [gasPrice] are optional, if blank, MetaMask will let the user choose these values.
  // [value] is only for [payable] functions
  // or use `web3js.utils.toWei("1");`
  .send({ from: userAccount, gas: 300000, gasPrice: 140, value: web3js.utils.toWei("0.001", "ether") })
  .on("receipt", function(receipt) {
    $("#txStatus").text("Successfully created " + name + "!");
  }).on("error", function(error) { $("#txStatus").text(error); });

To subscribe an event of the contract:
.on("data", function(event) {
  let zombie = event.returnValues;
  console.log("A new zombie was born!", zombie.zombieId,, zombie.dna);
}).on("error", console.error);

To get past event:

cryptoZombies.getPastEvents("NewZombie", { fromBlock: 0, toBlock: "latest" })
.then(function(events) {
  // `events` is an array of `event` objects that we can iterate, like we did above
  // This code will get us a list of every zombie that was ever created

Contract Testing Note

Project structure:

├── build
  ├── contracts
      ├── Migrations.json
      ├── CryptoZombies.json
      ├── erc721.json
      ├── ownable.json
      ├── safemath.json
      ├── zombieattack.json
      ├── zombiefactory.json
      ├── zombiefeeding.json
      ├── zombiehelper.json
      ├── zombieownership.json
├── contracts
  ├── Migrations.sol
  ├── CryptoZombies.sol
  ├── erc721.sol
  ├── ownable.sol
  ├── safemath.sol
  ├── zombieattack.sol
  ├── zombiefactory.sol
  ├── zombiefeeding.sol
  ├── zombiehelper.sol
  ├── zombieownership.sol
├── migrations
└── test
. package-lock.json
. truffle-config.js
. truffle.js


Sample Test Code

const CryptoZombies = artifacts.require("CryptoZombies"); // contract name
const zombieNames = ["Zombie 1", "Zombie 2"];
contract("CryptoZombies", (accounts) => {
    let [alice, bob] = accounts; // Ganache function
    let contractInstance;
    beforeEach(async () => { // hook that execute in front of every [it]
        contractInstance = await;
    it("should be able to create a new zombie", async () => {
        const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice}); // [from] is contract sender
        // These log are automatically created by Truffle as fake events
        // [result.tx]: the transaction hash
        // [result.receipt]: an object containing the transaction receipt. If [result.receipt.status] is equal to true it means that the transaction was successful. Otherwise, it means that the transaction failed.
        assert.equal(result.receipt.status, true); // we can also use [deepEqual()]
    it("should not allow two zombies", async () => {
        await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
        await utils.shouldThrow(contractInstance.createRandomZombie(zombieNames[1], {from: alice}));
    // [context] is to group tests together
    context("with the two-step transfer scenario", async () => {
        it("should approve and then transfer a zombie when the approved address calls transferFrom", async () => {
            const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice});
            const zombieId = result.logs[0].args.zombieId.toNumber();
            await contractInstance.approve(bob, zombieId, {from: alice});
            await contractInstance.transferFrom(alice, bob, zombieId, {from: bob});
            const newOwner = await contractInstance.ownerOf(zombieId);
        // will not run [xit]
        xit("should approve and then transfer a zombie when the owner calls transferFrom", async () => {
    afterEach(async () => {
        await contractInstance.kill();

To use time-travel:

javascript tests/helper/utils.js async function shouldThrow(promise) { try { await promise; assert(true); } catch (err) { return; } assert(false, "The contract did not throw."); } module.exports = { shouldThrow, };

Contract Deployment Note

Compile and Deploy

Some Bad Hardhat Tutorial:

Verifying Contract Code

Because we uploaded only machine readable bytecode to blockchain, in order to make people trust our code (Json) and use our code (ContractABI)

Verifying Contract Using Blockscout: Here

Verifying Contract Using Hardhat and Etherscan: Here

Traditional Development

Choosing a stack: StackShare


Tutorials on using tools


DeFi Info

Testnet Explorer:

Sokol(SPOA) Testnet: The Sokol Testnet provides an application testing environment for developers planning to use the Ethereum POA Core network.

Blockchain Explorer:


- Gnosis / Polygon Bridge

Opensource Explorer: BlockScout

Token Sniffer: TokenSniffer

Contract Apprival Checker: check wallet approved which contract for how much money

General Explorer:

Gas Fee Explorer:

Trading Bot: Pionex

Swaps Pool:

Token allocation checker:

ETH Merge Simulation: Ultrasound

NFT Platform

L2-Projects: L2Beats - Ethereum L2 systems


News Feed


Timeline: Web3IsGreat

Charts of Blockchain Ecosystem: CryptoDiffer (They maybe outdated)

Rapid News Feed: Telegram

Airdrop Opportunity


Comments and Problems with Blockchain

Short-term Problem

Long-term Problem

Reading Lists

Future Applications:

Table of Content