forked from CryptozombiesHQ/cryptozombie-lessons
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New lessons and path in frontmatter (CryptozombiesHQ#425)
New lessons and path in frontmatter
- Loading branch information
Showing
56 changed files
with
6,563 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
--- | ||
title: "Deploying Ethereum DApps with Truffle" | ||
header: "Deploying Ethereum DApps with Truffle" | ||
roadmap: roadmap.jpg | ||
path: solidity_advanced | ||
position: 2 | ||
--- | ||
|
||
Remember that we promised to teach you how to deploy smart contracts to **_Ethereum_**? | ||
|
||
It's been a while, but the time has come! | ||
|
||
In this lesson, we will be teaching you how to deploy to **_Ethereum_** using **_Truffle_**. | ||
|
||
And this is not all. You are going to learn how to deploy your smart contracts to **Loom**, and how to interact with them using **_web3.js_**. | ||
|
||
Why deploy to **Loom**? After all, **_Ethereum_** is the most secure network. | ||
|
||
Yes, we totally agree with that. But on Ethereum each transaction costs _gas_, so your users will have to pay fees for each and every transaction. Also, they will have to wait at least 10 seconds for each transaction to be confirmed. | ||
|
||
In a nutshell, **_on Ethereum, all transactions benefit from the same security guarantees_**. For something like a game, this level of security isn't a requirement. In fact, it just harms the user experience. | ||
|
||
On **Loom**, users will have access to much speedier and gas-free transactions. This makes DAppChains a much better fit for something like a game or a user-facing DApp. | ||
|
||
Enough talking! Let's get started😉 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
--- | ||
title: Introduction | ||
actions: ['checkAnswer', 'hints'] | ||
requireLogin: true | ||
material: | ||
terminal: | ||
help: | ||
You should probably run `npm install truffle -g`. | ||
commands: | ||
"npm install truffle -g": | ||
hint: npm install truffle -g | ||
output: | | ||
/usr/local/bin/truffle -> /usr/local/lib/node_modules/truffle/build/cli.bundled.js | ||
+ [email protected] | ||
added 81 packages from 311 contributors in 5.104s | ||
--- | ||
|
||
If you're new to **CryptoZombies**, it's highly recommended that you go over the first six lessons before starting this one. Please take the time to get familiar with writing a smart contract and interacting with it using `Web3.js`. Otherwise, it will be quite hard to follow this lesson. | ||
|
||
## The Missing Piece | ||
|
||
So you've worked your way through our previous lessons. Awesome! This means you've almost mastered the art of building DApps. | ||
|
||
But an important piece of the puzzle is still missing. | ||
|
||
That's right... you still have to learn how to **_deploy a smart contract to Ethereum_**. | ||
|
||
Now, if you have a background in front-end development, you are probably well accustomed to the multitude of tools like *Webpack, Gulp, or Browserify* that make a developer's life simpler. | ||
|
||
But what tools do `Solidity` developers use? | ||
|
||
## Truffle | ||
|
||
`Truffle` is the most popular blockchain development framework for good reason - it's packed with lots of useful features: | ||
|
||
- easy smart contract compilation | ||
- automated ABI generation | ||
- integrated smart contract testing - there's even support for `Mocha` and `Chai`! | ||
- support for multiple networks - code can be deployed to Rinkeby, **_Ethereum_** or even to **Loom**. We'll walk you through this later😉 | ||
|
||
Provided that `npm` and `node` have been installed, we'll want you to install `truffle` and make it available globally. | ||
|
||
# Put It to the Test | ||
|
||
We'll start with the basics. Fire up a new terminal window, create a directory called "CryptoZombies", and `cd` into it. | ||
|
||
1. Now, let's install `truffle` and make it available globally. | ||
|
||
>Note: Here's how you can use `npm` to install a package and make it available globally: | ||
```bash | ||
npm install package_name -g | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
--- | ||
title: Getting Started with Truffle | ||
actions: ['checkAnswer', 'hints'] | ||
requireLogin: true | ||
material: | ||
terminal: | ||
help: | | ||
First, you should probably run `truffle init`. Next, execute `npm install truffle-hdwallet-provider` | ||
commands: | ||
"truffle init": | ||
hint: truffle init | ||
output: | | ||
Downloading... | ||
Unpacking... | ||
Setting up... | ||
Unbox successful. Sweet! | ||
Commands: | ||
Compile: truffle compile | ||
Migrate: truffle migrate | ||
Test contracts: truffle test | ||
"npm install truffle-hdwallet-provider": | ||
hint: npm install truffle-hdwallet-provider | ||
output: | | ||
+ [email protected] | ||
added 1 package from 1 contributor and audited 71402 packages in 5.612s | ||
found 0 vulnerabilities | ||
--- | ||
|
||
Now that we've installed `truffle`, it's time to initialize our new project by running `truffle init`. All it is doing is to create a set of folders and config files with the following structure: | ||
|
||
``` | ||
├── contracts | ||
├── Migrations.sol | ||
├── migrations | ||
├── 1_initial_migration.js | ||
└── test | ||
truffle-config.js | ||
truffle.js | ||
``` | ||
|
||
Contracts, migrations, tests... this is pretty complicated😟 | ||
|
||
Don't worry, learning to use `truffle` won't eat your brains. This chapter will walk you through `truffle`'s default project structure, and once you know how to use `truffle`, deploying smart contracts will be a breeze. | ||
|
||
## Truffle's Default Directory Structure | ||
|
||
So, inside of "CryptoZombies" directory, `truffle init` should create several directories and some JavaScript and Solidity files. Let's have a closer look: | ||
|
||
- **_contracts_**: this is the place where `truffle` expects to find all our smart contracts. To keep the code organized, we can even create nested folders such as `contracts/tokens`. Pretty neat😉. | ||
>Note: `truffle init` should automatically add a contract called `Migrations.sol` and the corresponding migration file. We'll explain them a bit later. | ||
- **_migrations_**: a migration is a JavaScript file that tells `truffle` how to deploy the smart contract. | ||
|
||
- **_test_**: here we are expected to put the unit tests which will be JavaScript or Solidity files. Remember, once a contract is deployed it can't be changed, making it essential that we test our smart contracts before we deploy them. | ||
|
||
- **_truffle.js_** and **_truffle-config.js_**: config files used to store the network settings for deployment. `Truffle` needs two config files because on Windows having both `truffle.js` and `truffle.exe` in the same folder might generate conflicts. Long story short - if you are running Windows, it is advised to delete `truffle.js` and use `truffle-config.js` as the default config file. Check out _Truffle's_ official <a href="https://truffleframework.com/docs/truffle/reference/configuration" target=_blank>documentation</a> to further your understanding. | ||
|
||
|
||
But why should I use this directory structure? I'm not used to it and it looks complicated... | ||
|
||
Well, there's are a few good reasons. First, `Truffle` will not work as expected if you change the names of these folders. | ||
|
||
Second, by adhering to this convention your projects will be easily understood by other developers. To put it short, using standard folder structures and code conventions make it easier if you expand or change your team in the future. | ||
|
||
## truffle-hdwallet-provider | ||
|
||
In this lesson, we will be using _Infura_ to deploy our code to **_Ethereum_**. This way, our users will be allowed to run the application without needing to set up their own **_Ethereum_** node or wallet. | ||
However, to keep things secure, _Infura_ does not manage private keys, which means it can't sign transactions on our behalf. Since deploying a smart contract requires `truffle` to sign transactions, we are going to need a tool called `truffle-hdwallet-provider`. Its only purpose is to handle the transaction signing. | ||
|
||
>Note: Maybe you are asking why we chose not to install `truffle-hdwallet-provider` in the previous chapter using something like: | ||
```JavaScript | ||
npm install truffle truffle-hdwallet-provider -g | ||
``` | ||
|
||
Well... `truffle init` expects to find an empty directory. If there's any file there, it will error out, so we need to do everything in the correct order and install `truffle-hdwallet-provider` after we run `truffle init`. | ||
|
||
|
||
# Put it to the test: | ||
|
||
1. Run `truffle init`. This command generates the directory structure that we've discussed. | ||
|
||
2. Run `npm install truffle-hdwallet-provider`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
--- | ||
title: Compiling the Source Code | ||
actions: ['checkAnswer', 'hints'] | ||
requireLogin: true | ||
material: | ||
terminal: | ||
help: | ||
You should probably run `truffle compile`. | ||
commands: | ||
"truffle compile": | ||
hint: truffle compile | ||
output: | | ||
Compiling ./contracts/Migrations.sol... | ||
Compiling ./contracts/CryptoZombies.sol... | ||
Compiling ./contracts/erc721.sol... | ||
Compiling ./contracts/ownable.sol... | ||
Compiling ./contracts/safemath.sol... | ||
Compiling ./contracts/zombieattack.sol... | ||
Compiling ./contracts/zombiefactory.sol... | ||
Compiling ./contracts/zombiefeeding.sol... | ||
Compiling ./contracts/zombiehelper.sol... | ||
Compiling ./contracts/zombieownership.sol... | ||
Writing artifacts to ./build/contracts | ||
--- | ||
|
||
Congratulations! Now that we've put the project structure in place and set up `truffle-hdwallet-provider`, let's compile our contracts. | ||
|
||
Why do we need to compile, you ask? | ||
|
||
The _Ethereum Virtual Machine_ can't directly understand Solidity source code as we write it. Thus, we need to run a compiler that will "translate" our smart contract into machine-readable **_bytecode_**. The virtual machine then executes the bytecode, and completes the actions required by our smart contract. | ||
|
||
Curious about how does the bytecode look like? Let's take a look: | ||
|
||
``` | ||
"0x60806040526010600155600154600a0a6002556201518060035566038d7ea4c6800060085560006009556046600a55336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1..." | ||
``` | ||
|
||
A you can see, a human is about as likely to be able to read bytecode as a real life zombie! | ||
|
||
## Using the Solidity Compiler | ||
|
||
Now that we're talking about the Solidity compiler, we should mention that the devs managed to bake in some nifty features. | ||
|
||
Let's pretend we'd want to modify the definition of the `add` function included in `SafeMath`: | ||
|
||
``` | ||
function add(uint16 a, uint16 b) internal returns (uint16) { | ||
uint16 c = a + b; | ||
assert(c >= a); | ||
return c; | ||
} | ||
``` | ||
|
||
If we're going to compile this function, the Solidity compiler will throw a **_warning_**: | ||
|
||
``` | ||
safemath.sol:110:11: Warning: Function state mutability can be restricted to pure | ||
function add(uint16 a, uint16 b) internal returns (uint16) { | ||
^ (Relevant source part starts here and spans across multiple lines). | ||
``` | ||
|
||
What the compiler is trying to say is that our function does not read or write to the blockchain and that we should use the `pure` modifier. | ||
|
||
Why is this important? | ||
|
||
Well, making a function `pure` or `view` will save us gas. Since these functions are not going to modify the state of the blockchain, there is no need for miners to execute them. To put it in a few words, `pure` and `view` functions can be `call`ed for free. | ||
|
||
|
||
## CryptoZombies- The Game | ||
|
||
Remember, we've embedded our logic in a smart contract called `ZombieOwnership.sol`. | ||
|
||
Hmmm... not a great name for a game. | ||
|
||
Fortunately, this isn't a problem. We can use inheritance to create a smart contract with the same actions and features with whatever name we choose. | ||
|
||
Let's create a new smart contract named `CryptoZombies` that inherits from `ZombieOwnership.sol`: | ||
|
||
```solidity | ||
pragma solidity ^0.4.24; | ||
import "./zombieownership.sol"; | ||
contract CryptoZombies is ZombieOwnership | ||
{ | ||
} | ||
``` | ||
|
||
Next, we copied all our smart contracts into the `./contracts` folder. Now the project structure should look like this: | ||
|
||
``` | ||
. | ||
├── contracts | ||
├── Migrations.sol | ||
├── CryptoZombies.sol | ||
├── erc721.sol | ||
├── ownable.sol | ||
├── safemath.sol | ||
├── zombieattack.sol | ||
├── zombiefactory.sol | ||
├── zombiefeeding.sol | ||
├── zombiehelper.sol | ||
├── zombieownership.sol | ||
├── migrations | ||
└── test | ||
``` | ||
|
||
Everything is set up properly. Let's compile our project. | ||
|
||
# Put it to the test: | ||
|
||
1. Execute `truffle compile`. This command should create the "build artifacts" and place them in the `./build/contracts` directory. | ||
|
||
>Note: The build artifacts are comprised of the "bytecode" versions of the smart contracts, ABIs, and some internal data `truffle` is using to correctly deploy the code. Avoid editing these files, or `truffle` might stop working correctly. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
--- | ||
title: Migrations | ||
actions: ['checkAnswer', 'hints'] | ||
requireLogin: true | ||
material: | ||
editor: | ||
language: JavaScript | ||
startingCode: | ||
"./contracts/2_crypto_zombies.js": | | ||
var Migrations = artifacts.require("./Migrations.sol"); | ||
module.exports = function(deployer) { | ||
deployer.deploy(Migrations); | ||
}; | ||
answer: | | ||
var CryptoZombies = artifacts.require("./CryptoZombies.sol"); | ||
module.exports = function(deployer) { | ||
deployer.deploy(CryptoZombies); | ||
}; | ||
--- | ||
|
||
Normally at this point, before deploying to **_Ethereum_**, you would want to test your smart contract locally. You can do this using a tool called <a href="https://truffleframework.com/ganache" target=”_blank”>Ganache</a>, which sets up a local **_Ethereum_** network. | ||
|
||
However, while testing is very important, it would require an entire lesson to cover — so we’re just going to stick to deployment in this lesson. | ||
|
||
To deploy to **_Ethereum_** we will have to create something called a **migration**. | ||
|
||
Migrations are JavaScript files that help `truffle` deploy the code to **_Ethereum_**. Note that `truffle init` created a special contract called `Migrations.sol` that keeps track of the changes you're making to your code. The way it works is that the history of changes is saved onchain. Thus, there's no way you will ever deploy the same code twice. | ||
|
||
## Creating a New Migration | ||
|
||
We'll start from the file `truffle init` already created for us- `./contracts/1_initial_migration.js`. | ||
Let's take a look at what's inside: | ||
|
||
```javascript | ||
var Migrations = artifacts.require("./Migrations.sol"); | ||
module.exports = function(deployer) { | ||
deployer.deploy(Migrations); | ||
}; | ||
``` | ||
|
||
Pretty straightforward, isn't it? | ||
|
||
First, the script tells `truffle` that we'd want to interact with the `Migrations` contract. | ||
|
||
Next, it exports a function that accepts an object called `deployer` as a parameter. This object acts as an interface between you (the developer) and `truffle`'s deployment engine. Even though the `deployer` provides a multitude of useful functions, we won't be using them in the scope of this lesson. Once you've finished, feel free to check out Truffle's <a href="https://truffleframework.com/docs/truffle/getting-started/running-migrations" target=”_blank”>documentation</a> if you're inclined to learn more about _Truffle's_ abilities. | ||
|
||
To get everything ready for deployment, we've gone ahead and created a new file `./contracts/2_crypto_zombies.js`, and copied and pasted the content from `./contracts/1_initial_migration.js`. | ||
|
||
# Put it to the test: | ||
|
||
1. Modify `./contracts/2_crypto_zombies.js` to this: | ||
|
||
```JavaScript | ||
var CryptoZombies = artifacts.require("./CryptoZombies.sol"); | ||
module.exports = function(deployer) { | ||
deployer.deploy(CryptoZombies); | ||
}; | ||
``` |
Oops, something went wrong.