1. Lesson 1: CryptoZombies
    1. Chapter 2 Contracts
    2. Chapter 3: State Variables & Integers
    3. Chapter 4: Math Operations
    4. Chapter 5: Structs
    5. Chapter 6: Arrays
    6. Chapter 7: Function Declarations
    7. Chapter 8: Working With Structs and Arrays
    8. Chapter 9: Private / Public Functions
    9. Chapter 10: More on Functions
    10. Chapter 11: Keccak256 and Typecasting
    11. Chapter 12: Putting It Together
    12. Chapter 13: Events
    13. Chapter 14: Web3.js
  2. Lesson 2: Zombies Attack Their Victims
    1. Chapter 2: Mappings and Addresses
    2. Chapter 3: Msg.sender
    3. Chapter 4: Require
    4. Chapter 5: Inheritance
    5. Chapter 6: Import
    6. Chapter 7: Storage vs Memory
    7. Chapter 8: Zombie DNA
    8. Chapter 9: More on Function Visibility
    9. Chapter 10: What Do Zombies Eat?
    10. Chapter 11: Using an Interface
    11. Chapter 12: Handling Multiple Return Values
    12. Chapter 13: Bonus: Kitty Genes
    13. Chapter 14: Wrapping It Up
  3. Lesson 3: Advanced Solidity Concepts
    1. Chapter 2: Ownable Contracts
    2. Chapter 3: onlyOwner Function Modifier
    3. Chapter 4: Gas
    4. Chapter 5: Time Units
    5. Chapter 6: Zombie Cooldowns
    6. Chapter 7: Public Functions & Security
    7. Chapter 8: More on Function Modifiers
    8. Chapter 9: Zombie Modifiers
    9. Chapter 10: Saving Gas With 'View' Functions
    10. Chapter 11: Storage is Expensive
    11. Chapter 12: For Loops
    12. Chapter 13: Wrapping It Up
  4. Lesson 4: Zombie Battle System
    1. Chapter 1: Payable
    2. Chapter 2: Withdraws
    3. Chapter 3: Zombie Battles
    4. Chapter 4: Random Numbers
    5. Chapter 5: Zombie Fightin'
    6. Chapter 6: Refactoring Common Logic
    7. Chapter 7: More Refactoring
    8. Chapter 8: Back to Attack!
    9. Chapter 9: Zombie Wins and Losses
    10. Chapter 10: Zombie Victory 😄
    11. Chapter 11: Zombie Loss 😞
  5. Lesson 5: ERC721 & Crypto-Collectibles
    1. Chapter 1: Tokens on Ethereum
    2. Chapter 2: ERC721 Standard, Multiple Inheritance
    3. Chapter 3: balanceOf & ownerOf
    4. Chapter 4: Refactoring
    5. Chapter 5: ERC721: Transfer Logic
    6. Chapter 6: ERC721: Transfer Cont'd
    7. Chapter 7: ERC721: Approve
    8. Chapter 8: ERC721: Approve
    9. Chapter 9: Preventing Overflows
    10. Chapter 10: SafeMath Part 2
    11. Chapter 11: SafeMath Part 3
    12. Chapter 12: SafeMath Part 4
    13. Chapter 13: Comments
    14. Chapter 14: Wrapping It Up
  6. App Front-ends & Web3.js
    1. Chapter 1: Intro to Web3.js
    2. Chapter 2: Web3 Providers
    3. Chapter 3: Talking to Contracts
    4. Chapter 4: Calling Contract Functions
    5. Chapter 5: Metamask & Accounts
    6. Chapter 6: Displaying our Zombie Army
    7. Chapter 7: Sending Transactions
    8. Chapter 8: Calling Payable Functions
    9. Chapter 9: Subscribing to Events
    10. Chapter 10: Wrapping It Up

Chapter 1: Tokens on Ethereum

Chapter 1: Tokens on Ethereum

Let's talk about tokens.
If you've been in the Ethereum space for any amount of time, you've probably heard people talking about tokens — specifically ERC20 tokens.
A token on Ethereum is basically just a smart contract that follows some common rules — namely it implements a standard set of functions that all other token contracts share, such as transferFrom(address _from, address _to, uint256 _tokenId) and balanceOf(address _owner).
Internally the smart contract usually has a mapping, mapping(address => uint256) balances, that keeps track of how much balance each address has.
So basically a token is just a contract that keeps track of who owns how much of that token, and some functions so those users can transfer their tokens to other addresses.

Why does it matter?

Since all ERC20 tokens share the same set of functions with the same names, they can all be interacted with in the same ways.
This means if you build an application that is capable of interacting with one ERC20 token, it's also capable of interacting with any ERC20 token. That way more tokens can easily be added to your app in the future without needing to be custom coded. You could simply plug in the new token contract address, and boom, your app has another token it can use.
One example of this would be an exchange. When an exchange adds a new ERC20 token, really it just needs to add another smart contract it talks to. Users can tell that contract to send tokens to the exchange's wallet address, and the exchange can tell the contract to send the tokens back out to users when they request a withdraw.
The exchange only needs to implement this transfer logic once, then when it wants to add a new ERC20 token, it's simply a matter of adding the new contract address to its database.

Other token standards

ERC20 tokens are really cool for tokens that act like currencies. But they're not particularly useful for representing zombies in our zombie game.
For one, zombies aren't divisible like currencies — I can send you 0.237 ETH, but transfering you 0.237 of a zombie doesn't really make sense.
Secondly, all zombies are not created equal. Your Level 2 zombie "Steve" is totally not equal to my Level 732 zombie "H4XF13LD MORRIS 💯💯😎💯💯". (Not even close, Steve).
There's another token standard that's a much better fit for crypto-collectibles like CryptoZombies — and they're called ERC721 tokens.
ERC721 tokens are not interchangeable since each one is assumed to be unique, and are not divisible. You can only trade them in whole units, and each one has a unique ID. So these are a perfect fit for making our zombies tradeable.
Note that using a standard like ERC721 has the benefit that we don't have to implement the auction or escrow logic within our contract that determines how players can trade / sell our zombies. If we conform to the spec, someone else could build an exchange platform for crypto-tradable ERC721 assets, and our ERC721 zombies would be usable on that platform. So there are clear benefits to using a token standard instead of rolling your own trading logic.

Putting it to the Test

We're going to dive into the ERC721 implementation in the next chapter. But first, let's set up our file structure for this lesson.
We're going to store all the ERC721 logic in a contract called ZombieOwnership.
1. Declare our pragma version at the top of the file (check previous lessons' files for the syntax).

2. This file should import from zombieattack.sol.

3. Declare a new contract, ZombieOwnership, that inherits from ZombieAttack. Leave the body of the contract empty for now.

pragma solidity ^0.4.25;

import "./zombieattack.sol";

contract ZombieOwnership is ZombieAttack {