From 69c21ead02b0b99e8caf342c460986e9461c0c5f Mon Sep 17 00:00:00 2001 From: Luigi Date: Tue, 19 Nov 2024 10:42:49 +0700 Subject: [PATCH 001/797] Update Merkle Airdrop written lesson setup to be consistent with video --- .../4-merkle-airdrop/2-project-setup/+page.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/courses/advanced-foundry/4-merkle-airdrop/2-project-setup/+page.md b/courses/advanced-foundry/4-merkle-airdrop/2-project-setup/+page.md index eaf390aa3..4c35d947a 100644 --- a/courses/advanced-foundry/4-merkle-airdrop/2-project-setup/+page.md +++ b/courses/advanced-foundry/4-merkle-airdrop/2-project-setup/+page.md @@ -38,13 +38,13 @@ contract BagelToken is ERC20, Ownable { ### MerkleAirdrop -We can then create a new file named `MarkleAirdrop.sol`, where we will have a list of addresses and someone from that list who can claim ERC20 tokens. +We can then create a new file named `MerkleAirdrop.sol`, where we will have a list of addresses and someone from that list who can claim ERC20 tokens. ```js // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -contract MerkleAirdrop is EIP712 { +contract MerkleAirdrop { // list of addresses that can receive tokens // allow someone in the list to claim some tokens } From 42eb9d8e0b0ca2874e36177745961f4cf72c1657 Mon Sep 17 00:00:00 2001 From: Luigi Date: Tue, 19 Nov 2024 10:52:57 +0700 Subject: [PATCH 002/797] Update written lesson's demo filename to match video's --- .../4-merkle-airdrop/4-base-airdrop-contract/+page.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/courses/advanced-foundry/4-merkle-airdrop/4-base-airdrop-contract/+page.md b/courses/advanced-foundry/4-merkle-airdrop/4-base-airdrop-contract/+page.md index eb3ac51a7..00e4e2109 100644 --- a/courses/advanced-foundry/4-merkle-airdrop/4-base-airdrop-contract/+page.md +++ b/courses/advanced-foundry/4-merkle-airdrop/4-base-airdrop-contract/+page.md @@ -8,7 +8,7 @@ _Follow along with the video_ ### Introduction -In this lesson, we are going to implement Merkle proofs and Merkle trees in our `MerkleTree.sol` contract by setting up the _constructor_ and creating a _claim_ function. +In this lesson, we are going to implement Merkle proofs and Merkle trees in our `MerkleAirdrop.sol` contract by setting up the _constructor_ and creating a _claim_ function. ### Constructor From 2cb263fc6db475f9ce501ae4a3d600f33fd7424b Mon Sep 17 00:00:00 2001 From: Luigi Date: Thu, 21 Nov 2024 01:43:56 +0700 Subject: [PATCH 003/797] Update written lesson to use named imports like the video lesson --- .../4-merkle-airdrop/8-deployment-script/+page.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/courses/advanced-foundry/4-merkle-airdrop/8-deployment-script/+page.md b/courses/advanced-foundry/4-merkle-airdrop/8-deployment-script/+page.md index dcd98c15f..a3de9c409 100644 --- a/courses/advanced-foundry/4-merkle-airdrop/8-deployment-script/+page.md +++ b/courses/advanced-foundry/4-merkle-airdrop/8-deployment-script/+page.md @@ -16,10 +16,10 @@ Inside the `script` directory, we can start coding the deployment contract by im // SPDX-License-Identifier: MIT pragma solidity ^0.8.24; -import "MerkleAirdrop.sol"; -import "BagelToken.sol"; -import "forge-std/Script.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {MerkleAirdrop} from "src/MerkleAirdrop.sol"; +import {BagelToken} from "src/BagelToken.sol"; +import {Script} from "forge-std/Script.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; ``` Next, create the deployment function to deploy the contracts, mint tokens, and transfer them to the airdrop contract: From 1334e8cc33aab51d5f404ea70fade4478ed9c22e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:21:45 -0700 Subject: [PATCH 004/797] Equious updated courses/vyper-101/1-favorites/1-welcome/+page.md. --- courses/vyper-101/1-favorites/1-welcome/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/1-welcome/+page.md diff --git a/courses/vyper-101/1-favorites/1-welcome/+page.md b/courses/vyper-101/1-favorites/1-welcome/+page.md new file mode 100644 index 000000000..cc19b2514 --- /dev/null +++ b/courses/vyper-101/1-favorites/1-welcome/+page.md @@ -0,0 +1,3 @@ +--- + title: Welcome + --- \ No newline at end of file From da77564c6a6124c15be71fc8b7621c5d834bde2b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:21:58 -0700 Subject: [PATCH 005/797] Equious updated courses/vyper-101/1-favorites/10-contract-design/+page.md. --- courses/vyper-101/1-favorites/10-contract-design/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/10-contract-design/+page.md diff --git a/courses/vyper-101/1-favorites/10-contract-design/+page.md b/courses/vyper-101/1-favorites/10-contract-design/+page.md new file mode 100644 index 000000000..6ce60ddce --- /dev/null +++ b/courses/vyper-101/1-favorites/10-contract-design/+page.md @@ -0,0 +1,3 @@ +--- + title: Contract Design + --- \ No newline at end of file From 85a69478ad1cd53f089040ada64fdb493882388a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:22:12 -0700 Subject: [PATCH 006/797] Equious updated courses/vyper-101/1-favorites/11-vyper-types/+page.md. --- courses/vyper-101/1-favorites/11-vyper-types/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/11-vyper-types/+page.md diff --git a/courses/vyper-101/1-favorites/11-vyper-types/+page.md b/courses/vyper-101/1-favorites/11-vyper-types/+page.md new file mode 100644 index 000000000..59975b7b9 --- /dev/null +++ b/courses/vyper-101/1-favorites/11-vyper-types/+page.md @@ -0,0 +1,3 @@ +--- + title: Vyper Types + --- \ No newline at end of file From 5be98a29de88e3c2b93e9cb979eeb82e6715a422 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:22:26 -0700 Subject: [PATCH 007/797] Equious updated courses/vyper-101/1-favorites/12-visibilitiy/+page.md. --- courses/vyper-101/1-favorites/12-visibilitiy/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/12-visibilitiy/+page.md diff --git a/courses/vyper-101/1-favorites/12-visibilitiy/+page.md b/courses/vyper-101/1-favorites/12-visibilitiy/+page.md new file mode 100644 index 000000000..ff9091e2d --- /dev/null +++ b/courses/vyper-101/1-favorites/12-visibilitiy/+page.md @@ -0,0 +1,3 @@ +--- + title: Visibilitiy + --- \ No newline at end of file From f44a9fb86f3ff4ebe9e3ff2c405854976e1d1b50 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:22:39 -0700 Subject: [PATCH 008/797] Equious updated courses/vyper-101/1-favorites/13-functions/+page.md. --- courses/vyper-101/1-favorites/13-functions/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/13-functions/+page.md diff --git a/courses/vyper-101/1-favorites/13-functions/+page.md b/courses/vyper-101/1-favorites/13-functions/+page.md new file mode 100644 index 000000000..acfd89f66 --- /dev/null +++ b/courses/vyper-101/1-favorites/13-functions/+page.md @@ -0,0 +1,3 @@ +--- + title: Functions + --- \ No newline at end of file From c428d3a541cc1c1ad04eac36d94b71d63812a5ad Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:22:53 -0700 Subject: [PATCH 009/797] Equious updated courses/vyper-101/1-favorites/14-func-visibility/+page.md. --- courses/vyper-101/1-favorites/14-func-visibility/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/14-func-visibility/+page.md diff --git a/courses/vyper-101/1-favorites/14-func-visibility/+page.md b/courses/vyper-101/1-favorites/14-func-visibility/+page.md new file mode 100644 index 000000000..72f026d4e --- /dev/null +++ b/courses/vyper-101/1-favorites/14-func-visibility/+page.md @@ -0,0 +1,3 @@ +--- + title: Func Visibility + --- \ No newline at end of file From 1d84cbebd0229d747d4c2f6242640624d5376352 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:23:19 -0700 Subject: [PATCH 010/797] Equious updated courses/vyper-101/1-favorites/15-view-and-pure/+page.md. --- courses/vyper-101/1-favorites/15-view-and-pure/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/15-view-and-pure/+page.md diff --git a/courses/vyper-101/1-favorites/15-view-and-pure/+page.md b/courses/vyper-101/1-favorites/15-view-and-pure/+page.md new file mode 100644 index 000000000..8fa895385 --- /dev/null +++ b/courses/vyper-101/1-favorites/15-view-and-pure/+page.md @@ -0,0 +1,3 @@ +--- + title: View And Pure + --- \ No newline at end of file From 4fcc22852ee1bf0208a5bbbb29a9438946a8d4a0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:23:33 -0700 Subject: [PATCH 011/797] Equious updated courses/vyper-101/1-favorites/16-constructor/+page.md. --- courses/vyper-101/1-favorites/16-constructor/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/16-constructor/+page.md diff --git a/courses/vyper-101/1-favorites/16-constructor/+page.md b/courses/vyper-101/1-favorites/16-constructor/+page.md new file mode 100644 index 000000000..60d42e12a --- /dev/null +++ b/courses/vyper-101/1-favorites/16-constructor/+page.md @@ -0,0 +1,3 @@ +--- + title: Constructor + --- \ No newline at end of file From 8770784cabce9df1abac8e29a08b4b54d8c8e680 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:23:47 -0700 Subject: [PATCH 012/797] Equious updated courses/vyper-101/1-favorites/17-advanced-funcs/+page.md. --- courses/vyper-101/1-favorites/17-advanced-funcs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/17-advanced-funcs/+page.md diff --git a/courses/vyper-101/1-favorites/17-advanced-funcs/+page.md b/courses/vyper-101/1-favorites/17-advanced-funcs/+page.md new file mode 100644 index 000000000..410ca3f45 --- /dev/null +++ b/courses/vyper-101/1-favorites/17-advanced-funcs/+page.md @@ -0,0 +1,3 @@ +--- + title: Advanced Funcs + --- \ No newline at end of file From 40f0d3d1a80bbc80d17d0bc8596b1b0dc12d7a99 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:24:12 -0700 Subject: [PATCH 013/797] Equious updated courses/vyper-101/1-favorites/18-ref-types/+page.md. --- courses/vyper-101/1-favorites/18-ref-types/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/18-ref-types/+page.md diff --git a/courses/vyper-101/1-favorites/18-ref-types/+page.md b/courses/vyper-101/1-favorites/18-ref-types/+page.md new file mode 100644 index 000000000..8483d0bb6 --- /dev/null +++ b/courses/vyper-101/1-favorites/18-ref-types/+page.md @@ -0,0 +1,3 @@ +--- + title: Ref Types + --- \ No newline at end of file From a54a11d077a5b93cdc9ceb6c0feffca7d833064c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:24:25 -0700 Subject: [PATCH 014/797] Equious updated courses/vyper-101/1-favorites/19-claude/+page.md. --- courses/vyper-101/1-favorites/19-claude/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/19-claude/+page.md diff --git a/courses/vyper-101/1-favorites/19-claude/+page.md b/courses/vyper-101/1-favorites/19-claude/+page.md new file mode 100644 index 000000000..272f5e0b5 --- /dev/null +++ b/courses/vyper-101/1-favorites/19-claude/+page.md @@ -0,0 +1,3 @@ +--- + title: Claude + --- \ No newline at end of file From 7dae412d8a38dc9e6fdf436d3e1c306d59125647 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:24:41 -0700 Subject: [PATCH 015/797] Equious updated courses/vyper-101/1-favorites/2-best-practices/+page.md. --- courses/vyper-101/1-favorites/2-best-practices/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/2-best-practices/+page.md diff --git a/courses/vyper-101/1-favorites/2-best-practices/+page.md b/courses/vyper-101/1-favorites/2-best-practices/+page.md new file mode 100644 index 000000000..7c54c2de2 --- /dev/null +++ b/courses/vyper-101/1-favorites/2-best-practices/+page.md @@ -0,0 +1,3 @@ +--- + title: Best Practices + --- \ No newline at end of file From a0fb6ca6e4a72fdce4d3404db299513fbc6e58b6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:25:07 -0700 Subject: [PATCH 016/797] Equious updated courses/vyper-101/1-favorites/20-arrays-lists/+page.md. --- courses/vyper-101/1-favorites/20-arrays-lists/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/20-arrays-lists/+page.md diff --git a/courses/vyper-101/1-favorites/20-arrays-lists/+page.md b/courses/vyper-101/1-favorites/20-arrays-lists/+page.md new file mode 100644 index 000000000..3650aa247 --- /dev/null +++ b/courses/vyper-101/1-favorites/20-arrays-lists/+page.md @@ -0,0 +1,3 @@ +--- + title: Arrays Lists + --- \ No newline at end of file From 32447e5757f637b8bddce0912a74893eb531869d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:25:33 -0700 Subject: [PATCH 017/797] Equious updated courses/vyper-101/1-favorites/21-idk/+page.md. --- courses/vyper-101/1-favorites/21-idk/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/21-idk/+page.md diff --git a/courses/vyper-101/1-favorites/21-idk/+page.md b/courses/vyper-101/1-favorites/21-idk/+page.md new file mode 100644 index 000000000..d226208fe --- /dev/null +++ b/courses/vyper-101/1-favorites/21-idk/+page.md @@ -0,0 +1,3 @@ +--- + title: Idk + --- \ No newline at end of file From 19881373f74b4b940ef02855dbc4fd1d52c0dfd5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:25:46 -0700 Subject: [PATCH 018/797] Equious updated courses/vyper-101/1-favorites/22-workshop/+page.md. --- courses/vyper-101/1-favorites/22-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/22-workshop/+page.md diff --git a/courses/vyper-101/1-favorites/22-workshop/+page.md b/courses/vyper-101/1-favorites/22-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/vyper-101/1-favorites/22-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From c39c00e43ac9f9716d7b75b0470e0add9446d21a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:26:00 -0700 Subject: [PATCH 019/797] Equious updated courses/vyper-101/1-favorites/23-hash-map/+page.md. --- courses/vyper-101/1-favorites/23-hash-map/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/23-hash-map/+page.md diff --git a/courses/vyper-101/1-favorites/23-hash-map/+page.md b/courses/vyper-101/1-favorites/23-hash-map/+page.md new file mode 100644 index 000000000..94db4a4e4 --- /dev/null +++ b/courses/vyper-101/1-favorites/23-hash-map/+page.md @@ -0,0 +1,3 @@ +--- + title: Hash Map + --- \ No newline at end of file From d2ff29bf1563315a3d4ec1b278e488c9b372042e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:26:14 -0700 Subject: [PATCH 020/797] Equious updated courses/vyper-101/1-favorites/24-recap/+page.md. --- courses/vyper-101/1-favorites/24-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/24-recap/+page.md diff --git a/courses/vyper-101/1-favorites/24-recap/+page.md b/courses/vyper-101/1-favorites/24-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/vyper-101/1-favorites/24-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From f676812e1b6338d306335c8700e42b86b9eb63dd Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:33:20 -0700 Subject: [PATCH 021/797] Equious updated courses/vyper-101/1-favorites/25-tenderly/+page.md. --- courses/vyper-101/1-favorites/25-tenderly/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/25-tenderly/+page.md diff --git a/courses/vyper-101/1-favorites/25-tenderly/+page.md b/courses/vyper-101/1-favorites/25-tenderly/+page.md new file mode 100644 index 000000000..ea1b9ce91 --- /dev/null +++ b/courses/vyper-101/1-favorites/25-tenderly/+page.md @@ -0,0 +1,3 @@ +--- + title: Tenderly + --- \ No newline at end of file From 9ada2f35d072edf3ee6954ce491334716fb28d90 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:33:33 -0700 Subject: [PATCH 022/797] Equious updated courses/vyper-101/1-favorites/26-zksync/+page.md. --- courses/vyper-101/1-favorites/26-zksync/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/26-zksync/+page.md diff --git a/courses/vyper-101/1-favorites/26-zksync/+page.md b/courses/vyper-101/1-favorites/26-zksync/+page.md new file mode 100644 index 000000000..6f25bb3d4 --- /dev/null +++ b/courses/vyper-101/1-favorites/26-zksync/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync + --- \ No newline at end of file From 1da195ffdc3e6a4fa7023120fdf5c4b27e6279d0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:34:28 -0700 Subject: [PATCH 023/797] Equious updated courses/vyper-101/1-favorites/27-share/+page.md. --- courses/vyper-101/1-favorites/27-share/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/27-share/+page.md diff --git a/courses/vyper-101/1-favorites/27-share/+page.md b/courses/vyper-101/1-favorites/27-share/+page.md new file mode 100644 index 000000000..f82ca3a05 --- /dev/null +++ b/courses/vyper-101/1-favorites/27-share/+page.md @@ -0,0 +1,3 @@ +--- + title: Share + --- \ No newline at end of file From a96b0e6612ddfa248cd1014cf1c0c2e9ee5b24e2 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:34:41 -0700 Subject: [PATCH 024/797] Equious updated courses/vyper-101/1-favorites/28-evm/+page.md. --- courses/vyper-101/1-favorites/28-evm/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/28-evm/+page.md diff --git a/courses/vyper-101/1-favorites/28-evm/+page.md b/courses/vyper-101/1-favorites/28-evm/+page.md new file mode 100644 index 000000000..4e09d4688 --- /dev/null +++ b/courses/vyper-101/1-favorites/28-evm/+page.md @@ -0,0 +1,3 @@ +--- + title: Evm + --- \ No newline at end of file From b6072bf6d82c187e6e0ebf34b380f582cc8dbf2e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:34:54 -0700 Subject: [PATCH 025/797] Equious updated courses/vyper-101/1-favorites/29-pure-and-view/+page.md. --- courses/vyper-101/1-favorites/29-pure-and-view/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/29-pure-and-view/+page.md diff --git a/courses/vyper-101/1-favorites/29-pure-and-view/+page.md b/courses/vyper-101/1-favorites/29-pure-and-view/+page.md new file mode 100644 index 000000000..91881a69e --- /dev/null +++ b/courses/vyper-101/1-favorites/29-pure-and-view/+page.md @@ -0,0 +1,3 @@ +--- + title: Pure And View + --- \ No newline at end of file From d4c4567e231b7101552633788075f2329eda5c89 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:36:11 -0700 Subject: [PATCH 026/797] Equious updated courses/vyper-101/1-favorites/3-mox-best-practices/+page.md. --- courses/vyper-101/1-favorites/3-mox-best-practices/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/3-mox-best-practices/+page.md diff --git a/courses/vyper-101/1-favorites/3-mox-best-practices/+page.md b/courses/vyper-101/1-favorites/3-mox-best-practices/+page.md new file mode 100644 index 000000000..92169430e --- /dev/null +++ b/courses/vyper-101/1-favorites/3-mox-best-practices/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Best Practices + --- \ No newline at end of file From 538e484c91ee87f1596c31f43ad07477349bda25 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:36:24 -0700 Subject: [PATCH 027/797] Equious updated courses/vyper-101/1-favorites/30-conditionals/+page.md. --- courses/vyper-101/1-favorites/30-conditionals/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/30-conditionals/+page.md diff --git a/courses/vyper-101/1-favorites/30-conditionals/+page.md b/courses/vyper-101/1-favorites/30-conditionals/+page.md new file mode 100644 index 000000000..1d57c9ca3 --- /dev/null +++ b/courses/vyper-101/1-favorites/30-conditionals/+page.md @@ -0,0 +1,3 @@ +--- + title: Conditionals + --- \ No newline at end of file From d542f123ab1f935381afde27257a10388ee08273 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:36:40 -0700 Subject: [PATCH 028/797] Equious updated courses/vyper-101/1-favorites/31-workshop/+page.md. --- courses/vyper-101/1-favorites/31-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/31-workshop/+page.md diff --git a/courses/vyper-101/1-favorites/31-workshop/+page.md b/courses/vyper-101/1-favorites/31-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/vyper-101/1-favorites/31-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 759d9eb421d9d1e9f63b2c0ed5cc0677db9d02e8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:38:48 -0700 Subject: [PATCH 029/797] Equious updated courses/vyper-101/1-favorites/32-recap/+page.md. --- courses/vyper-101/1-favorites/32-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/32-recap/+page.md diff --git a/courses/vyper-101/1-favorites/32-recap/+page.md b/courses/vyper-101/1-favorites/32-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/vyper-101/1-favorites/32-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 97c9456bf66cf2b5f88c7aaae2d0b36fa82d18be Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:39:02 -0700 Subject: [PATCH 030/797] Equious updated courses/vyper-101/1-favorites/4-walkthrough/+page.md. --- courses/vyper-101/1-favorites/4-walkthrough/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/4-walkthrough/+page.md diff --git a/courses/vyper-101/1-favorites/4-walkthrough/+page.md b/courses/vyper-101/1-favorites/4-walkthrough/+page.md new file mode 100644 index 000000000..e9d2a2138 --- /dev/null +++ b/courses/vyper-101/1-favorites/4-walkthrough/+page.md @@ -0,0 +1,3 @@ +--- + title: Walkthrough + --- \ No newline at end of file From fcb2db92767f888fc88d9621b24213a66019c6a5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:39:17 -0700 Subject: [PATCH 031/797] Equious updated courses/vyper-101/1-favorites/5-welcome-to-remix/+page.md. --- courses/vyper-101/1-favorites/5-welcome-to-remix/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/5-welcome-to-remix/+page.md diff --git a/courses/vyper-101/1-favorites/5-welcome-to-remix/+page.md b/courses/vyper-101/1-favorites/5-welcome-to-remix/+page.md new file mode 100644 index 000000000..b5a5d1364 --- /dev/null +++ b/courses/vyper-101/1-favorites/5-welcome-to-remix/+page.md @@ -0,0 +1,3 @@ +--- + title: Welcome To Remix + --- \ No newline at end of file From a8e96d5ca8087ee642ce760d48919e3d4b905fb3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:39:30 -0700 Subject: [PATCH 032/797] Equious updated courses/vyper-101/1-favorites/6-pragma-version/+page.md. --- courses/vyper-101/1-favorites/6-pragma-version/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/6-pragma-version/+page.md diff --git a/courses/vyper-101/1-favorites/6-pragma-version/+page.md b/courses/vyper-101/1-favorites/6-pragma-version/+page.md new file mode 100644 index 000000000..5ebef9151 --- /dev/null +++ b/courses/vyper-101/1-favorites/6-pragma-version/+page.md @@ -0,0 +1,3 @@ +--- + title: Pragma Version + --- \ No newline at end of file From 484a04226a777031e85eb8a704a6040b2fb1e7f0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:39:42 -0700 Subject: [PATCH 033/797] Equious updated courses/vyper-101/1-favorites/7-comments/+page.md. --- courses/vyper-101/1-favorites/7-comments/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/7-comments/+page.md diff --git a/courses/vyper-101/1-favorites/7-comments/+page.md b/courses/vyper-101/1-favorites/7-comments/+page.md new file mode 100644 index 000000000..d42c6c4b2 --- /dev/null +++ b/courses/vyper-101/1-favorites/7-comments/+page.md @@ -0,0 +1,3 @@ +--- + title: Comments + --- \ No newline at end of file From 844411347076bb7e26b231a33601fef2afb4b02c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:39:55 -0700 Subject: [PATCH 034/797] Equious updated courses/vyper-101/1-favorites/8-license/+page.md. --- courses/vyper-101/1-favorites/8-license/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/8-license/+page.md diff --git a/courses/vyper-101/1-favorites/8-license/+page.md b/courses/vyper-101/1-favorites/8-license/+page.md new file mode 100644 index 000000000..6f900f5b0 --- /dev/null +++ b/courses/vyper-101/1-favorites/8-license/+page.md @@ -0,0 +1,3 @@ +--- + title: License + --- \ No newline at end of file From dde1bd9a89b3898c5637decc9c1fbdfef688c90f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:40:08 -0700 Subject: [PATCH 035/797] Equious updated courses/vyper-101/1-favorites/9-compiling/+page.md. --- courses/vyper-101/1-favorites/9-compiling/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/1-favorites/9-compiling/+page.md diff --git a/courses/vyper-101/1-favorites/9-compiling/+page.md b/courses/vyper-101/1-favorites/9-compiling/+page.md new file mode 100644 index 000000000..4c9310136 --- /dev/null +++ b/courses/vyper-101/1-favorites/9-compiling/+page.md @@ -0,0 +1,3 @@ +--- + title: Compiling + --- \ No newline at end of file From f499cc67b93eda6e1d42d810533d3d886f718e33 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:40:34 -0700 Subject: [PATCH 036/797] Equious updated courses/vyper-101/2-remix-coffee/1-introduction/+page.md. --- courses/vyper-101/2-remix-coffee/1-introduction/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/1-introduction/+page.md diff --git a/courses/vyper-101/2-remix-coffee/1-introduction/+page.md b/courses/vyper-101/2-remix-coffee/1-introduction/+page.md new file mode 100644 index 000000000..c21ef2ce7 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/1-introduction/+page.md @@ -0,0 +1,3 @@ +--- + title: Introduction + --- \ No newline at end of file From efa9b4d0951ccca606397d53552b3cae5894b0ee Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:42:42 -0700 Subject: [PATCH 037/797] Equious updated courses/vyper-101/2-remix-coffee/10-chainlink-in-vyper/+page.md. --- .../vyper-101/2-remix-coffee/10-chainlink-in-vyper/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/10-chainlink-in-vyper/+page.md diff --git a/courses/vyper-101/2-remix-coffee/10-chainlink-in-vyper/+page.md b/courses/vyper-101/2-remix-coffee/10-chainlink-in-vyper/+page.md new file mode 100644 index 000000000..54423f9d5 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/10-chainlink-in-vyper/+page.md @@ -0,0 +1,3 @@ +--- + title: Chainlink In Vyper + --- \ No newline at end of file From 688f2ffa3061fe960fabe2e79a4e0174f5bb8f1c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:42:55 -0700 Subject: [PATCH 038/797] Equious updated courses/vyper-101/2-remix-coffee/11-abi/+page.md. --- courses/vyper-101/2-remix-coffee/11-abi/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/11-abi/+page.md diff --git a/courses/vyper-101/2-remix-coffee/11-abi/+page.md b/courses/vyper-101/2-remix-coffee/11-abi/+page.md new file mode 100644 index 000000000..25fb9c94d --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/11-abi/+page.md @@ -0,0 +1,3 @@ +--- + title: Abi + --- \ No newline at end of file From bb90ab3baea5f2c53b4743b8292d0076f070aeca Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:43:10 -0700 Subject: [PATCH 039/797] Equious updated courses/vyper-101/2-remix-coffee/12-in-line-inter/+page.md. --- courses/vyper-101/2-remix-coffee/12-in-line-inter/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/12-in-line-inter/+page.md diff --git a/courses/vyper-101/2-remix-coffee/12-in-line-inter/+page.md b/courses/vyper-101/2-remix-coffee/12-in-line-inter/+page.md new file mode 100644 index 000000000..60e5ba549 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/12-in-line-inter/+page.md @@ -0,0 +1,3 @@ +--- + title: In Line Inter + --- \ No newline at end of file From 7d350a9a00c3603879541e4c4ee4f13a69b31c5a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:43:23 -0700 Subject: [PATCH 040/797] Equious updated courses/vyper-101/2-remix-coffee/13-staticcall/+page.md. --- courses/vyper-101/2-remix-coffee/13-staticcall/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/13-staticcall/+page.md diff --git a/courses/vyper-101/2-remix-coffee/13-staticcall/+page.md b/courses/vyper-101/2-remix-coffee/13-staticcall/+page.md new file mode 100644 index 000000000..c3c2f772c --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/13-staticcall/+page.md @@ -0,0 +1,3 @@ +--- + title: Staticcall + --- \ No newline at end of file From 8ba9f1f823b8005d6147439c328f06917dd5fd1e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:43:37 -0700 Subject: [PATCH 041/797] Equious updated courses/vyper-101/2-remix-coffee/14-tenderly/+page.md. --- courses/vyper-101/2-remix-coffee/14-tenderly/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/14-tenderly/+page.md diff --git a/courses/vyper-101/2-remix-coffee/14-tenderly/+page.md b/courses/vyper-101/2-remix-coffee/14-tenderly/+page.md new file mode 100644 index 000000000..ea1b9ce91 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/14-tenderly/+page.md @@ -0,0 +1,3 @@ +--- + title: Tenderly + --- \ No newline at end of file From 46fed1d519e0bc388f8e248a1950b10b48a26370 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:43:53 -0700 Subject: [PATCH 042/797] Equious updated courses/vyper-101/2-remix-coffee/15-ai/+page.md. --- courses/vyper-101/2-remix-coffee/15-ai/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/15-ai/+page.md diff --git a/courses/vyper-101/2-remix-coffee/15-ai/+page.md b/courses/vyper-101/2-remix-coffee/15-ai/+page.md new file mode 100644 index 000000000..b9e433f65 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/15-ai/+page.md @@ -0,0 +1,3 @@ +--- + title: Ai + --- \ No newline at end of file From 68167ef8b50615c26649e95482e329f44891b169 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:44:06 -0700 Subject: [PATCH 043/797] Equious updated courses/vyper-101/2-remix-coffee/16-deploy-parameter/+page.md. --- courses/vyper-101/2-remix-coffee/16-deploy-parameter/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/16-deploy-parameter/+page.md diff --git a/courses/vyper-101/2-remix-coffee/16-deploy-parameter/+page.md b/courses/vyper-101/2-remix-coffee/16-deploy-parameter/+page.md new file mode 100644 index 000000000..26d4517bd --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/16-deploy-parameter/+page.md @@ -0,0 +1,3 @@ +--- + title: Deploy Parameter + --- \ No newline at end of file From 360f4173997349f9cb58c564733698e3ad739d72 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:44:20 -0700 Subject: [PATCH 044/797] Equious updated courses/vyper-101/2-remix-coffee/17-integer-precision/+page.md. --- courses/vyper-101/2-remix-coffee/17-integer-precision/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/17-integer-precision/+page.md diff --git a/courses/vyper-101/2-remix-coffee/17-integer-precision/+page.md b/courses/vyper-101/2-remix-coffee/17-integer-precision/+page.md new file mode 100644 index 000000000..9e85fbc71 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/17-integer-precision/+page.md @@ -0,0 +1,3 @@ +--- + title: Integer Precision + --- \ No newline at end of file From 27ce5d7d0cb4255eaac3dcc84b814ce928aa7911 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:44:33 -0700 Subject: [PATCH 045/797] Equious updated courses/vyper-101/2-remix-coffee/18-converting-types/+page.md. --- courses/vyper-101/2-remix-coffee/18-converting-types/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/18-converting-types/+page.md diff --git a/courses/vyper-101/2-remix-coffee/18-converting-types/+page.md b/courses/vyper-101/2-remix-coffee/18-converting-types/+page.md new file mode 100644 index 000000000..7e8858a8c --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/18-converting-types/+page.md @@ -0,0 +1,3 @@ +--- + title: Converting Types + --- \ No newline at end of file From dc6aade16ca289acf11c331c476745247f3d41b1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:45:00 -0700 Subject: [PATCH 046/797] Equious updated courses/vyper-101/2-remix-coffee/19-integer-division/+page.md. --- courses/vyper-101/2-remix-coffee/19-integer-division/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/19-integer-division/+page.md diff --git a/courses/vyper-101/2-remix-coffee/19-integer-division/+page.md b/courses/vyper-101/2-remix-coffee/19-integer-division/+page.md new file mode 100644 index 000000000..8bc547921 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/19-integer-division/+page.md @@ -0,0 +1,3 @@ +--- + title: Integer Division + --- \ No newline at end of file From 8b323039bbcdd026b5175b21c9fff05cf8aa7a5a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:45:23 -0700 Subject: [PATCH 047/797] Equious updated courses/vyper-101/2-remix-coffee/2-setup/+page.md. --- courses/vyper-101/2-remix-coffee/2-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/2-setup/+page.md diff --git a/courses/vyper-101/2-remix-coffee/2-setup/+page.md b/courses/vyper-101/2-remix-coffee/2-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/2-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From 64d7bebc208f01177a6871bcca939967219290ac Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:45:37 -0700 Subject: [PATCH 048/797] Equious updated courses/vyper-101/2-remix-coffee/20-as-wei-value/+page.md. --- courses/vyper-101/2-remix-coffee/20-as-wei-value/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/20-as-wei-value/+page.md diff --git a/courses/vyper-101/2-remix-coffee/20-as-wei-value/+page.md b/courses/vyper-101/2-remix-coffee/20-as-wei-value/+page.md new file mode 100644 index 000000000..f08ba5668 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/20-as-wei-value/+page.md @@ -0,0 +1,3 @@ +--- + title: As Wei Value + --- \ No newline at end of file From c32106ba27419c6a22bb8ab16f2505a7f4395638 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:45:51 -0700 Subject: [PATCH 049/797] Equious updated courses/vyper-101/2-remix-coffee/21-send-eth-in-tx/+page.md. --- courses/vyper-101/2-remix-coffee/21-send-eth-in-tx/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/21-send-eth-in-tx/+page.md diff --git a/courses/vyper-101/2-remix-coffee/21-send-eth-in-tx/+page.md b/courses/vyper-101/2-remix-coffee/21-send-eth-in-tx/+page.md new file mode 100644 index 000000000..979795eac --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/21-send-eth-in-tx/+page.md @@ -0,0 +1,3 @@ +--- + title: Send Eth In Tx + --- \ No newline at end of file From adba88962546ab878709a4c8daa783ee579da6fe Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:46:04 -0700 Subject: [PATCH 050/797] Equious updated courses/vyper-101/2-remix-coffee/22-contract-to-contract/+page.md. --- .../vyper-101/2-remix-coffee/22-contract-to-contract/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/22-contract-to-contract/+page.md diff --git a/courses/vyper-101/2-remix-coffee/22-contract-to-contract/+page.md b/courses/vyper-101/2-remix-coffee/22-contract-to-contract/+page.md new file mode 100644 index 000000000..f6e4e2888 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/22-contract-to-contract/+page.md @@ -0,0 +1,3 @@ +--- + title: Contract To Contract + --- \ No newline at end of file From fe495d5dd49357973480d79cfc92c78bae3c3e7c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:46:18 -0700 Subject: [PATCH 051/797] Equious updated courses/vyper-101/2-remix-coffee/23-getting-revert/+page.md. --- courses/vyper-101/2-remix-coffee/23-getting-revert/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/23-getting-revert/+page.md diff --git a/courses/vyper-101/2-remix-coffee/23-getting-revert/+page.md b/courses/vyper-101/2-remix-coffee/23-getting-revert/+page.md new file mode 100644 index 000000000..8dc8d171f --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/23-getting-revert/+page.md @@ -0,0 +1,3 @@ +--- + title: Getting Revert + --- \ No newline at end of file From c463ec82df523ff510dfad9cd453c048ec5ae9cc Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:46:37 -0700 Subject: [PATCH 052/797] Equious updated courses/vyper-101/2-remix-coffee/24-msg-sender/+page.md. --- courses/vyper-101/2-remix-coffee/24-msg-sender/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/24-msg-sender/+page.md diff --git a/courses/vyper-101/2-remix-coffee/24-msg-sender/+page.md b/courses/vyper-101/2-remix-coffee/24-msg-sender/+page.md new file mode 100644 index 000000000..d00f579be --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/24-msg-sender/+page.md @@ -0,0 +1,3 @@ +--- + title: Msg Sender + --- \ No newline at end of file From f9c36a44fb24b9abc67d965b7368cb7bee9438d3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:46:52 -0700 Subject: [PATCH 053/797] Equious updated courses/vyper-101/2-remix-coffee/25-withdraw-eth/+page.md. --- courses/vyper-101/2-remix-coffee/25-withdraw-eth/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/25-withdraw-eth/+page.md diff --git a/courses/vyper-101/2-remix-coffee/25-withdraw-eth/+page.md b/courses/vyper-101/2-remix-coffee/25-withdraw-eth/+page.md new file mode 100644 index 000000000..adffc9a9e --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/25-withdraw-eth/+page.md @@ -0,0 +1,3 @@ +--- + title: Withdraw Eth + --- \ No newline at end of file From a0f2b067c4af3804fe0e3f58920576ce1ff2e9a3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:47:18 -0700 Subject: [PATCH 054/797] Equious updated courses/vyper-101/2-remix-coffee/26-dynamic-vs-fixed-array/+page.md. --- .../2-remix-coffee/26-dynamic-vs-fixed-array/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/26-dynamic-vs-fixed-array/+page.md diff --git a/courses/vyper-101/2-remix-coffee/26-dynamic-vs-fixed-array/+page.md b/courses/vyper-101/2-remix-coffee/26-dynamic-vs-fixed-array/+page.md new file mode 100644 index 000000000..88419ab64 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/26-dynamic-vs-fixed-array/+page.md @@ -0,0 +1,3 @@ +--- + title: Dynamic Vs Fixed Array + --- \ No newline at end of file From 91157f1396dac2de50f6581427958b429d0a404a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:47:32 -0700 Subject: [PATCH 055/797] Equious updated courses/vyper-101/2-remix-coffee/27-resetting-array/+page.md. --- courses/vyper-101/2-remix-coffee/27-resetting-array/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/27-resetting-array/+page.md diff --git a/courses/vyper-101/2-remix-coffee/27-resetting-array/+page.md b/courses/vyper-101/2-remix-coffee/27-resetting-array/+page.md new file mode 100644 index 000000000..e7f9f5fbf --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/27-resetting-array/+page.md @@ -0,0 +1,3 @@ +--- + title: Resetting Array + --- \ No newline at end of file From 96012e570513ecf8e7700dc80d99cbea9e14d550 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:47:45 -0700 Subject: [PATCH 056/797] Equious updated courses/vyper-101/2-remix-coffee/28-plus-equals/+page.md. --- courses/vyper-101/2-remix-coffee/28-plus-equals/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/28-plus-equals/+page.md diff --git a/courses/vyper-101/2-remix-coffee/28-plus-equals/+page.md b/courses/vyper-101/2-remix-coffee/28-plus-equals/+page.md new file mode 100644 index 000000000..762f63235 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/28-plus-equals/+page.md @@ -0,0 +1,3 @@ +--- + title: Plus Equals + --- \ No newline at end of file From c67b7517dd146fdadea9dfc447d3e8923cacbb9a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:48:11 -0700 Subject: [PATCH 057/797] Equious updated courses/vyper-101/2-remix-coffee/29-for-loops/+page.md. --- courses/vyper-101/2-remix-coffee/29-for-loops/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/29-for-loops/+page.md diff --git a/courses/vyper-101/2-remix-coffee/29-for-loops/+page.md b/courses/vyper-101/2-remix-coffee/29-for-loops/+page.md new file mode 100644 index 000000000..186c15878 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/29-for-loops/+page.md @@ -0,0 +1,3 @@ +--- + title: For Loops + --- \ No newline at end of file From bc6c509bc82756594a314ea02bcc9704d258dd20 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:48:24 -0700 Subject: [PATCH 058/797] Equious updated courses/vyper-101/2-remix-coffee/3-doc-strings/+page.md. --- courses/vyper-101/2-remix-coffee/3-doc-strings/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/3-doc-strings/+page.md diff --git a/courses/vyper-101/2-remix-coffee/3-doc-strings/+page.md b/courses/vyper-101/2-remix-coffee/3-doc-strings/+page.md new file mode 100644 index 000000000..328343a0d --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/3-doc-strings/+page.md @@ -0,0 +1,3 @@ +--- + title: Doc Strings + --- \ No newline at end of file From 1b3c2728aa4cdfde63e9d837cd633e7d3f6d3fa7 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:48:50 -0700 Subject: [PATCH 059/797] Equious updated courses/vyper-101/2-remix-coffee/30-tenderly_/+page.md. --- courses/vyper-101/2-remix-coffee/30-tenderly_/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/30-tenderly_/+page.md diff --git a/courses/vyper-101/2-remix-coffee/30-tenderly_/+page.md b/courses/vyper-101/2-remix-coffee/30-tenderly_/+page.md new file mode 100644 index 000000000..92d2c2d94 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/30-tenderly_/+page.md @@ -0,0 +1,3 @@ +--- + title: Tenderly_ + --- \ No newline at end of file From 1987dc6c0db8eb75bd28a90343dffb4131e759d4 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:49:04 -0700 Subject: [PATCH 060/797] Equious updated courses/vyper-101/2-remix-coffee/31-idk/+page.md. --- courses/vyper-101/2-remix-coffee/31-idk/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/31-idk/+page.md diff --git a/courses/vyper-101/2-remix-coffee/31-idk/+page.md b/courses/vyper-101/2-remix-coffee/31-idk/+page.md new file mode 100644 index 000000000..d226208fe --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/31-idk/+page.md @@ -0,0 +1,3 @@ +--- + title: Idk + --- \ No newline at end of file From 3df81e8c174ff3ec185dc0fdb8ecfc849d2b9eb1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:49:18 -0700 Subject: [PATCH 061/797] Equious updated courses/vyper-101/2-remix-coffee/32-natspec/+page.md. --- courses/vyper-101/2-remix-coffee/32-natspec/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/32-natspec/+page.md diff --git a/courses/vyper-101/2-remix-coffee/32-natspec/+page.md b/courses/vyper-101/2-remix-coffee/32-natspec/+page.md new file mode 100644 index 000000000..092dcef15 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/32-natspec/+page.md @@ -0,0 +1,3 @@ +--- + title: Natspec + --- \ No newline at end of file From 99ec3de42d85823e0982aecdee3d5f8daea1ce56 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:49:58 -0700 Subject: [PATCH 062/797] Equious updated courses/vyper-101/2-remix-coffee/33-update-immute/+page.md. --- courses/vyper-101/2-remix-coffee/33-update-immute/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/33-update-immute/+page.md diff --git a/courses/vyper-101/2-remix-coffee/33-update-immute/+page.md b/courses/vyper-101/2-remix-coffee/33-update-immute/+page.md new file mode 100644 index 000000000..d1e653aa9 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/33-update-immute/+page.md @@ -0,0 +1,3 @@ +--- + title: Update Immute + --- \ No newline at end of file From ce347b2153edd65fdc99cfafe996cb3bae4d0293 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:50:11 -0700 Subject: [PATCH 063/797] Equious updated courses/vyper-101/2-remix-coffee/34-magic/+page.md. --- courses/vyper-101/2-remix-coffee/34-magic/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/34-magic/+page.md diff --git a/courses/vyper-101/2-remix-coffee/34-magic/+page.md b/courses/vyper-101/2-remix-coffee/34-magic/+page.md new file mode 100644 index 000000000..5bc4b4213 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/34-magic/+page.md @@ -0,0 +1,3 @@ +--- + title: Magic + --- \ No newline at end of file From f7cdb600a0c417eb65dbcd8298ec4e97ede36c2e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:50:37 -0700 Subject: [PATCH 064/797] Equious updated courses/vyper-101/2-remix-coffee/35-gas/+page.md. --- courses/vyper-101/2-remix-coffee/35-gas/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/35-gas/+page.md diff --git a/courses/vyper-101/2-remix-coffee/35-gas/+page.md b/courses/vyper-101/2-remix-coffee/35-gas/+page.md new file mode 100644 index 000000000..ef4aef09d --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/35-gas/+page.md @@ -0,0 +1,3 @@ +--- + title: Gas + --- \ No newline at end of file From a69ca4f0f5e994fe7d5335411413b2a2e1341ffb Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:53:28 -0700 Subject: [PATCH 065/797] Equious updated courses/vyper-101/2-remix-coffee/36-fallback/+page.md. --- courses/vyper-101/2-remix-coffee/36-fallback/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/36-fallback/+page.md diff --git a/courses/vyper-101/2-remix-coffee/36-fallback/+page.md b/courses/vyper-101/2-remix-coffee/36-fallback/+page.md new file mode 100644 index 000000000..ea13f6a83 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/36-fallback/+page.md @@ -0,0 +1,3 @@ +--- + title: Fallback + --- \ No newline at end of file From 7d93db2e75af3745901d85135db96253d46266b6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:53:42 -0700 Subject: [PATCH 066/797] Equious updated courses/vyper-101/2-remix-coffee/37-better-way-to-send/+page.md. --- .../vyper-101/2-remix-coffee/37-better-way-to-send/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/37-better-way-to-send/+page.md diff --git a/courses/vyper-101/2-remix-coffee/37-better-way-to-send/+page.md b/courses/vyper-101/2-remix-coffee/37-better-way-to-send/+page.md new file mode 100644 index 000000000..63fa80df2 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/37-better-way-to-send/+page.md @@ -0,0 +1,3 @@ +--- + title: Better Way To Send + --- \ No newline at end of file From e1c6d2616a5a5150692103c7f14a204fb7c83f68 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:58:27 -0700 Subject: [PATCH 067/797] Equious updated courses/vyper-101/2-remix-coffee/38-recap/+page.md. --- courses/vyper-101/2-remix-coffee/38-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/38-recap/+page.md diff --git a/courses/vyper-101/2-remix-coffee/38-recap/+page.md b/courses/vyper-101/2-remix-coffee/38-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/38-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 22402fc22eaf1dff6b77f0a70c52e78fd9cc4e60 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:58:41 -0700 Subject: [PATCH 068/797] Equious updated courses/vyper-101/2-remix-coffee/4-sending-eth/+page.md. --- courses/vyper-101/2-remix-coffee/4-sending-eth/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/4-sending-eth/+page.md diff --git a/courses/vyper-101/2-remix-coffee/4-sending-eth/+page.md b/courses/vyper-101/2-remix-coffee/4-sending-eth/+page.md new file mode 100644 index 000000000..2a8f120b6 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/4-sending-eth/+page.md @@ -0,0 +1,3 @@ +--- + title: Sending Eth + --- \ No newline at end of file From b8407b9d2f632d75a7171c557d3e6e46dda56fdb Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:58:55 -0700 Subject: [PATCH 069/797] Equious updated courses/vyper-101/2-remix-coffee/5-gwei-wei-eth/+page.md. --- courses/vyper-101/2-remix-coffee/5-gwei-wei-eth/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/5-gwei-wei-eth/+page.md diff --git a/courses/vyper-101/2-remix-coffee/5-gwei-wei-eth/+page.md b/courses/vyper-101/2-remix-coffee/5-gwei-wei-eth/+page.md new file mode 100644 index 000000000..9baa35504 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/5-gwei-wei-eth/+page.md @@ -0,0 +1,3 @@ +--- + title: Gwei Wei Eth + --- \ No newline at end of file From 10537e843265b68be83daf7407f4497fa0394dde Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:59:08 -0700 Subject: [PATCH 070/797] Equious updated courses/vyper-101/2-remix-coffee/6-send-tx/+page.md. --- courses/vyper-101/2-remix-coffee/6-send-tx/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/6-send-tx/+page.md diff --git a/courses/vyper-101/2-remix-coffee/6-send-tx/+page.md b/courses/vyper-101/2-remix-coffee/6-send-tx/+page.md new file mode 100644 index 000000000..5b4867baa --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/6-send-tx/+page.md @@ -0,0 +1,3 @@ +--- + title: Send Tx + --- \ No newline at end of file From 257cf9209e74f333611f44f25aca4a9fe2a38608 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:59:34 -0700 Subject: [PATCH 071/797] Equious updated courses/vyper-101/2-remix-coffee/7-reverts/+page.md. --- courses/vyper-101/2-remix-coffee/7-reverts/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/7-reverts/+page.md diff --git a/courses/vyper-101/2-remix-coffee/7-reverts/+page.md b/courses/vyper-101/2-remix-coffee/7-reverts/+page.md new file mode 100644 index 000000000..b1dc9fd85 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/7-reverts/+page.md @@ -0,0 +1,3 @@ +--- + title: Reverts + --- \ No newline at end of file From 81f7bdf281bf2394cca743da6cce2468d9c15cd5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:05:53 -0700 Subject: [PATCH 072/797] Equious updated courses/vyper-101/2-remix-coffee/8-chainlink/+page.md. --- courses/vyper-101/2-remix-coffee/8-chainlink/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/8-chainlink/+page.md diff --git a/courses/vyper-101/2-remix-coffee/8-chainlink/+page.md b/courses/vyper-101/2-remix-coffee/8-chainlink/+page.md new file mode 100644 index 000000000..6dd518502 --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/8-chainlink/+page.md @@ -0,0 +1,3 @@ +--- + title: Chainlink + --- \ No newline at end of file From 8be4e3e033ba694daed3a62cbde1c2b2773e4365 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:06:06 -0700 Subject: [PATCH 073/797] Equious updated courses/vyper-101/2-remix-coffee/9-mid-recap/+page.md. --- courses/vyper-101/2-remix-coffee/9-mid-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/2-remix-coffee/9-mid-recap/+page.md diff --git a/courses/vyper-101/2-remix-coffee/9-mid-recap/+page.md b/courses/vyper-101/2-remix-coffee/9-mid-recap/+page.md new file mode 100644 index 000000000..074b2dd9f --- /dev/null +++ b/courses/vyper-101/2-remix-coffee/9-mid-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Mid Recap + --- \ No newline at end of file From f325bb7108e647eed0d368201f998f140fb033b5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:06:20 -0700 Subject: [PATCH 074/797] Equious updated courses/vyper-101/3-ai/1-intro/+page.md. --- courses/vyper-101/3-ai/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/3-ai/1-intro/+page.md diff --git a/courses/vyper-101/3-ai/1-intro/+page.md b/courses/vyper-101/3-ai/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/vyper-101/3-ai/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From cda09d720a6806da30e5dfe81bf3da21f0be6e2a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:08:37 -0700 Subject: [PATCH 075/797] Equious updated courses/vyper-101/3-ai/2-vid/+page.md. --- courses/vyper-101/3-ai/2-vid/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/3-ai/2-vid/+page.md diff --git a/courses/vyper-101/3-ai/2-vid/+page.md b/courses/vyper-101/3-ai/2-vid/+page.md new file mode 100644 index 000000000..cd52348ae --- /dev/null +++ b/courses/vyper-101/3-ai/2-vid/+page.md @@ -0,0 +1,3 @@ +--- + title: Vid + --- \ No newline at end of file From a4bc4524c4d7997f6c3902dc0bdd01a1e8329172 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:09:03 -0700 Subject: [PATCH 076/797] Equious updated courses/vyper-101/3-ai/3-triage/+page.md. --- courses/vyper-101/3-ai/3-triage/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/3-ai/3-triage/+page.md diff --git a/courses/vyper-101/3-ai/3-triage/+page.md b/courses/vyper-101/3-ai/3-triage/+page.md new file mode 100644 index 000000000..8ea84026c --- /dev/null +++ b/courses/vyper-101/3-ai/3-triage/+page.md @@ -0,0 +1,3 @@ +--- + title: Triage + --- \ No newline at end of file From ed241b2e1cfce0e34ec15595933a811a01b845ef Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:09:17 -0700 Subject: [PATCH 077/797] Equious updated courses/vyper-101/3-ai/4-formatting-qs/+page.md. --- courses/vyper-101/3-ai/4-formatting-qs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/3-ai/4-formatting-qs/+page.md diff --git a/courses/vyper-101/3-ai/4-formatting-qs/+page.md b/courses/vyper-101/3-ai/4-formatting-qs/+page.md new file mode 100644 index 000000000..5d1732912 --- /dev/null +++ b/courses/vyper-101/3-ai/4-formatting-qs/+page.md @@ -0,0 +1,3 @@ +--- + title: Formatting Qs + --- \ No newline at end of file From db440ca438c0c8bca043b524929ed791530251df Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:11:03 -0700 Subject: [PATCH 078/797] Equious updated courses/vyper-101/3-ai/5-workshop/+page.md. --- courses/vyper-101/3-ai/5-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/vyper-101/3-ai/5-workshop/+page.md diff --git a/courses/vyper-101/3-ai/5-workshop/+page.md b/courses/vyper-101/3-ai/5-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/vyper-101/3-ai/5-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From b66c56b20806a349a15ea9c4e27be7f6ba042bf8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:27:30 -0700 Subject: [PATCH 079/797] Equious updated courses/moccasin-101/1-python-on-updraft/1-intro/+page.md. --- courses/moccasin-101/1-python-on-updraft/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/1-intro/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/1-intro/+page.md b/courses/moccasin-101/1-python-on-updraft/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 90121c0373c7e5d884791564837ed4e3d9b9000b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:27:44 -0700 Subject: [PATCH 080/797] Equious updated courses/moccasin-101/1-python-on-updraft/10-math/+page.md. --- courses/moccasin-101/1-python-on-updraft/10-math/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/10-math/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/10-math/+page.md b/courses/moccasin-101/1-python-on-updraft/10-math/+page.md new file mode 100644 index 000000000..d246d700c --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/10-math/+page.md @@ -0,0 +1,3 @@ +--- + title: Math + --- \ No newline at end of file From 49654d4ece1bb50f4755d9e7e7e7ce18ff1d8acf Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:27:58 -0700 Subject: [PATCH 081/797] Equious updated courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md. --- courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md b/courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md new file mode 100644 index 000000000..52de64c11 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md @@ -0,0 +1,3 @@ +--- + title: More Math + --- \ No newline at end of file From d72ff2efa92a58161d125581e8f1bc2d3805ab4b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:28:34 -0700 Subject: [PATCH 082/797] Equious updated courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md. --- courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md b/courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md new file mode 100644 index 000000000..125b3fa6b --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md @@ -0,0 +1,3 @@ +--- + title: Funcs + --- \ No newline at end of file From 1929ebb3b49af9d3dab8a289efa2320173982927 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:29:14 -0700 Subject: [PATCH 083/797] Equious updated courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md. --- .../moccasin-101/1-python-on-updraft/13-conditionals/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md b/courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md new file mode 100644 index 000000000..1d57c9ca3 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md @@ -0,0 +1,3 @@ +--- + title: Conditionals + --- \ No newline at end of file From ffba64966cd1cffc11566271626cc151f878869e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:29:51 -0700 Subject: [PATCH 084/797] Equious updated courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md. --- .../moccasin-101/1-python-on-updraft/14-while-loops/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md b/courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md new file mode 100644 index 000000000..9e54beace --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md @@ -0,0 +1,3 @@ +--- + title: While Loops + --- \ No newline at end of file From bfcaaf2b33002e507b12d33494f96fe6c140cd45 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:30:04 -0700 Subject: [PATCH 085/797] Equious updated courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md. --- courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md b/courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md new file mode 100644 index 000000000..1633a4fcb --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md @@ -0,0 +1,3 @@ +--- + title: Loops 2 + --- \ No newline at end of file From 71c87a8dd68873b129fa0eef0a1adfd7aadb6875 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:30:18 -0700 Subject: [PATCH 086/797] Equious updated courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md. --- courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md b/courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md new file mode 100644 index 000000000..3e226d5ca --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md @@ -0,0 +1,3 @@ +--- + title: Loops 3 + --- \ No newline at end of file From c023b7829c9767f4110d0288bbf610207fc2c78f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:31:15 -0700 Subject: [PATCH 087/797] Equious updated courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md. --- courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md b/courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 0b2bf37315c658275ef29259fb8849dd8649bbbd Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:31:42 -0700 Subject: [PATCH 088/797] Equious updated courses/moccasin-101/1-python-on-updraft/18-recap/+page.md. --- courses/moccasin-101/1-python-on-updraft/18-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/18-recap/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/18-recap/+page.md b/courses/moccasin-101/1-python-on-updraft/18-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/18-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 1aca68f87e3de0bd8cb55bb081e2a31035e1a019 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:32:58 -0700 Subject: [PATCH 089/797] Equious updated courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md. --- .../moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md b/courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md new file mode 100644 index 000000000..82dee4ad0 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Dev Env Setup + --- \ No newline at end of file From ba38d147012acdae30f92393b54471c91b7853cb Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:34:34 -0700 Subject: [PATCH 090/797] Equious updated courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md. --- .../moccasin-101/1-python-on-updraft/2-google-collab/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md b/courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md new file mode 100644 index 000000000..735bc3c07 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md @@ -0,0 +1,3 @@ +--- + title: Google Collab + --- \ No newline at end of file From 1b0bc70b87b5041fc0ba5f4dabd460f27332620d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:34:48 -0700 Subject: [PATCH 091/797] Equious updated courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md. --- .../1-python-on-updraft/20-install-vscode-macos-linux/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md b/courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md new file mode 100644 index 000000000..29e695218 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Vscode Macos Linux + --- \ No newline at end of file From 9e221221555e63dc273f6d12d6d9cff8646a70c9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:38:14 -0700 Subject: [PATCH 092/797] Equious updated courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md. --- .../moccasin-101/1-python-on-updraft/21-install-wsl/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md b/courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md new file mode 100644 index 000000000..475d38e9a --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Wsl + --- \ No newline at end of file From f2398791578ce03f0bc0be1b41f9ad7c2c2c3e89 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:41:27 -0700 Subject: [PATCH 093/797] Equious updated courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md. --- .../1-python-on-updraft/22-vscode-windows-install/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md b/courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md new file mode 100644 index 000000000..a09ad1944 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Windows Install + --- \ No newline at end of file From fdc624b64dd8f42511110be556aaeb3e40cae988 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:41:52 -0700 Subject: [PATCH 094/797] Equious updated courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md. --- .../23-vscode-windows-wsl-extension/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md b/courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md new file mode 100644 index 000000000..2acc9a55f --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Windows Wsl Extension + --- \ No newline at end of file From aa457292c3dd200b50a1243a4508d346c0838305 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:42:10 -0700 Subject: [PATCH 095/797] Equious updated courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md. --- .../1-python-on-updraft/24-vscode-quickstart/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md b/courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md new file mode 100644 index 000000000..3ab104359 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Quickstart + --- \ No newline at end of file From e29a729e77519da3844694a195c64bc09a2aa5d6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:43:19 -0700 Subject: [PATCH 096/797] Equious updated courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md. --- .../1-python-on-updraft/25-install-python-macos/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md b/courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md new file mode 100644 index 000000000..d2148949d --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Python Macos + --- \ No newline at end of file From 490dca8ac5e7ca6c2bfed05da3cc5ea605450c41 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:47:37 -0700 Subject: [PATCH 097/797] Equious updated courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md. --- .../1-python-on-updraft/26-install-python-wsl-linux/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md b/courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md new file mode 100644 index 000000000..d18275288 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Python Wsl Linux + --- \ No newline at end of file From 872aec7434e42638b33a33feb09f5d31d9c1c950 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:48:03 -0700 Subject: [PATCH 098/797] Equious updated courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md. --- .../1-python-on-updraft/27-vscode-quickstart-2/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md b/courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md new file mode 100644 index 000000000..7d3ad9c57 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Quickstart 2 + --- \ No newline at end of file From 756bed3171c321117b83f4f2204d2c1b3baa280e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:48:24 -0700 Subject: [PATCH 099/797] Equious updated courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md. --- .../moccasin-101/1-python-on-updraft/28-mental-prep/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md b/courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md new file mode 100644 index 000000000..cfcec4377 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md @@ -0,0 +1,3 @@ +--- + title: Mental Prep + --- \ No newline at end of file From b7625c1054f124efdd95475b749d099ad093e010 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:48:39 -0700 Subject: [PATCH 100/797] Equious updated courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md. --- courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md b/courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md new file mode 100644 index 000000000..8c591a536 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md @@ -0,0 +1,3 @@ +--- + title: Local Py + --- \ No newline at end of file From 9bf71e6acd20e9a9854eda63af8a8a2b9c30d5d7 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:48:53 -0700 Subject: [PATCH 101/797] Equious updated courses/moccasin-101/1-python-on-updraft/3-setup/+page.md. --- courses/moccasin-101/1-python-on-updraft/3-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/3-setup/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/3-setup/+page.md b/courses/moccasin-101/1-python-on-updraft/3-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/3-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From 4470628f8a3fd0c405a62ffc06ff8e7ef414af3f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:49:06 -0700 Subject: [PATCH 102/797] Equious updated courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md. --- .../moccasin-101/1-python-on-updraft/30-python-shell/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md b/courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md new file mode 100644 index 000000000..9c47c3f3e --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md @@ -0,0 +1,3 @@ +--- + title: Python Shell + --- \ No newline at end of file From 7363746a84ee5b376653c3d92de8864df1392587 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:49:26 -0700 Subject: [PATCH 103/797] Equious updated courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md. --- .../1-python-on-updraft/31-python-extensions-vscode/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md b/courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md new file mode 100644 index 000000000..85f6eb88c --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md @@ -0,0 +1,3 @@ +--- + title: Python Extensions Vscode + --- \ No newline at end of file From 11a15a22561a3d6fef92660d36d2ba5f396806b0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:49:40 -0700 Subject: [PATCH 104/797] Equious updated courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md. --- .../1-python-on-updraft/32-our-first-python/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md b/courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md new file mode 100644 index 000000000..f790b0411 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md @@ -0,0 +1,3 @@ +--- + title: Our First Python + --- \ No newline at end of file From bbf45c96ab4d78fa128073e5cec4e0d5ebc8d6d9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:51:27 -0700 Subject: [PATCH 105/797] Equious updated courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md. --- .../1-python-on-updraft/33-python-imports/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md b/courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md new file mode 100644 index 000000000..fae7a0f96 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md @@ -0,0 +1,3 @@ +--- + title: Python Imports + --- \ No newline at end of file From d3762d6d98c182f70dd460805f687c3785e8e681 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:51:52 -0700 Subject: [PATCH 106/797] Equious updated courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md. --- .../moccasin-101/1-python-on-updraft/34-installing-uv/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md b/courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md new file mode 100644 index 000000000..ef00c9919 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md @@ -0,0 +1,3 @@ +--- + title: Installing Uv + --- \ No newline at end of file From 4e48417aaf6ce16669e977f0928d1a3eedef3e60 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:52:07 -0700 Subject: [PATCH 107/797] Equious updated courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md. --- .../1-python-on-updraft/35-uv-python-version/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md b/courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md new file mode 100644 index 000000000..84d31ea64 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md @@ -0,0 +1,3 @@ +--- + title: Uv Python Version + --- \ No newline at end of file From f97c4692cff6141427f5c0d5ec0191b21e1cef64 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:52:21 -0700 Subject: [PATCH 108/797] Equious updated courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md. --- .../1-python-on-updraft/36-adding-packages-uv/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md b/courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md new file mode 100644 index 000000000..d2268f193 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md @@ -0,0 +1,3 @@ +--- + title: Adding Packages Uv + --- \ No newline at end of file From 18a9bf444b44744ed2d5b5a5d55b5b1e602dc5cb Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:52:35 -0700 Subject: [PATCH 109/797] Equious updated courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md. --- .../moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md b/courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md new file mode 100644 index 000000000..c211b8e01 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md @@ -0,0 +1,3 @@ +--- + title: Virtual Envs + --- \ No newline at end of file From 5c9f7c320ae663f0c50632eb22e09852d24d25b6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:55:35 -0700 Subject: [PATCH 110/797] Equious updated courses/moccasin-101/1-python-on-updraft/38-recap/+page.md. --- courses/moccasin-101/1-python-on-updraft/38-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/38-recap/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/38-recap/+page.md b/courses/moccasin-101/1-python-on-updraft/38-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/38-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 89f01530a0546aecb42e4396e400304922492926 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:55:48 -0700 Subject: [PATCH 111/797] Equious updated courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md. --- courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md b/courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md new file mode 100644 index 000000000..e4cab53fa --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md @@ -0,0 +1,3 @@ +--- + title: Notebook + --- \ No newline at end of file From b09af74cfdef8c95e7d231ea7146567d23636c5e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:56:02 -0700 Subject: [PATCH 112/797] Equious updated courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md. --- courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md b/courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md new file mode 100644 index 000000000..faa0a0f12 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md @@ -0,0 +1,3 @@ +--- + title: Google Ai + --- \ No newline at end of file From 12b16f1927b7a4cb3ecceabcdaaff2ff01538310 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:56:15 -0700 Subject: [PATCH 113/797] Equious updated courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md. --- .../moccasin-101/1-python-on-updraft/6-python-vars/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md b/courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md new file mode 100644 index 000000000..9d8367c72 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md @@ -0,0 +1,3 @@ +--- + title: Python Vars + --- \ No newline at end of file From 0226edd108fcb7c92ed56fd54322c353b1c6828c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:56:28 -0700 Subject: [PATCH 114/797] Equious updated courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md. --- courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md b/courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md new file mode 100644 index 000000000..3f01df5ef --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md @@ -0,0 +1,3 @@ +--- + title: Type Hints + --- \ No newline at end of file From dc363caef6434cd362a535d9cceddfa5894a0389 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:56:42 -0700 Subject: [PATCH 115/797] Equious updated courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md. --- courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md b/courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md new file mode 100644 index 000000000..267733150 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md @@ -0,0 +1,3 @@ +--- + title: Arrays + --- \ No newline at end of file From b20d76c6eceac79fa12912e6e68e35cd54e6e7ce Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:56:56 -0700 Subject: [PATCH 116/797] Equious updated courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md. --- courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md b/courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md new file mode 100644 index 000000000..8a90dbef7 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md @@ -0,0 +1,3 @@ +--- + title: Inputs + --- \ No newline at end of file From 2a92d729ff37eb5877915305a44815aeb1c8133f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 07:57:10 -0700 Subject: [PATCH 117/797] Equious updated courses/moccasin-101/1-python-on-updraft/9-types/+page.md. --- courses/moccasin-101/1-python-on-updraft/9-types/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/9-types/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/9-types/+page.md b/courses/moccasin-101/1-python-on-updraft/9-types/+page.md new file mode 100644 index 000000000..c6210ebf1 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/9-types/+page.md @@ -0,0 +1,3 @@ +--- + title: Types + --- \ No newline at end of file From 6704f7f3ddd3e5292448bd610f24a616c53b801d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:00:29 -0700 Subject: [PATCH 118/797] Equious updated courses/moccasin-101/2-web3py/1-intro/+page.md. --- courses/moccasin-101/2-web3py/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/1-intro/+page.md diff --git a/courses/moccasin-101/2-web3py/1-intro/+page.md b/courses/moccasin-101/2-web3py/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/2-web3py/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 10e0799a5191a2710e1878425b63e6785b8550d4 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:00:46 -0700 Subject: [PATCH 119/797] Equious updated courses/moccasin-101/2-web3py/18-pkey-promise/+page.md. --- courses/moccasin-101/2-web3py/18-pkey-promise/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/18-pkey-promise/+page.md diff --git a/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md b/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md new file mode 100644 index 000000000..08c6274da --- /dev/null +++ b/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md @@ -0,0 +1,3 @@ +--- + title: Pkey Promise + --- \ No newline at end of file From fd17f1a720f531a13b01c1ab565e5f553f5ad7ec Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:01:21 -0700 Subject: [PATCH 120/797] Equious updated courses/moccasin-101/2-web3py/19-env-vars/+page.md. --- courses/moccasin-101/2-web3py/19-env-vars/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/19-env-vars/+page.md diff --git a/courses/moccasin-101/2-web3py/19-env-vars/+page.md b/courses/moccasin-101/2-web3py/19-env-vars/+page.md new file mode 100644 index 000000000..e97071bde --- /dev/null +++ b/courses/moccasin-101/2-web3py/19-env-vars/+page.md @@ -0,0 +1,3 @@ +--- + title: Env Vars + --- \ No newline at end of file From 2f43e212b153b6e4f0e757fa217eb4d47155663d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:01:38 -0700 Subject: [PATCH 121/797] Equious updated courses/moccasin-101/2-web3py/2-setup/+page.md. --- courses/moccasin-101/2-web3py/2-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/2-setup/+page.md diff --git a/courses/moccasin-101/2-web3py/2-setup/+page.md b/courses/moccasin-101/2-web3py/2-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/2-web3py/2-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From 186ee6a4f1fa5112006a620daa3b9d2144e8d343 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:01:53 -0700 Subject: [PATCH 122/797] Equious updated courses/moccasin-101/2-web3py/20-send-tx/+page.md. --- courses/moccasin-101/2-web3py/20-send-tx/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/20-send-tx/+page.md diff --git a/courses/moccasin-101/2-web3py/20-send-tx/+page.md b/courses/moccasin-101/2-web3py/20-send-tx/+page.md new file mode 100644 index 000000000..5b4867baa --- /dev/null +++ b/courses/moccasin-101/2-web3py/20-send-tx/+page.md @@ -0,0 +1,3 @@ +--- + title: Send Tx + --- \ No newline at end of file From 765bbbf4565986a174c8d2fa00b2e7bd275a5bea Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:02:21 -0700 Subject: [PATCH 123/797] Equious updated courses/moccasin-101/2-web3py/21-encrypt/+page.md. --- courses/moccasin-101/2-web3py/21-encrypt/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/21-encrypt/+page.md diff --git a/courses/moccasin-101/2-web3py/21-encrypt/+page.md b/courses/moccasin-101/2-web3py/21-encrypt/+page.md new file mode 100644 index 000000000..56ef26d1d --- /dev/null +++ b/courses/moccasin-101/2-web3py/21-encrypt/+page.md @@ -0,0 +1,3 @@ +--- + title: Encrypt + --- \ No newline at end of file From 142435ff7f3a93b009dbdd7e6a11cc547ec4e8c0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:02:51 -0700 Subject: [PATCH 124/797] Equious updated courses/moccasin-101/2-web3py/22-decrypt/+page.md. --- courses/moccasin-101/2-web3py/22-decrypt/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/22-decrypt/+page.md diff --git a/courses/moccasin-101/2-web3py/22-decrypt/+page.md b/courses/moccasin-101/2-web3py/22-decrypt/+page.md new file mode 100644 index 000000000..19a99651f --- /dev/null +++ b/courses/moccasin-101/2-web3py/22-decrypt/+page.md @@ -0,0 +1,3 @@ +--- + title: Decrypt + --- \ No newline at end of file From cc7e64115052e6ac2b1732130019433cc5cd8880 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:06:45 -0700 Subject: [PATCH 125/797] Equious updated courses/moccasin-101/2-web3py/23-pledge/+page.md. --- courses/moccasin-101/2-web3py/23-pledge/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/23-pledge/+page.md diff --git a/courses/moccasin-101/2-web3py/23-pledge/+page.md b/courses/moccasin-101/2-web3py/23-pledge/+page.md new file mode 100644 index 000000000..dea23512b --- /dev/null +++ b/courses/moccasin-101/2-web3py/23-pledge/+page.md @@ -0,0 +1,3 @@ +--- + title: Pledge + --- \ No newline at end of file From 0b7258cfde5d0d81024feb293dcba262a1428b65 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:07:01 -0700 Subject: [PATCH 126/797] Equious updated courses/moccasin-101/2-web3py/24-workshop/+page.md. --- courses/moccasin-101/2-web3py/24-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/24-workshop/+page.md diff --git a/courses/moccasin-101/2-web3py/24-workshop/+page.md b/courses/moccasin-101/2-web3py/24-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/2-web3py/24-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 60cf744fde90f8cf871f97a2439c35cba2beb686 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:13:31 -0700 Subject: [PATCH 127/797] Equious updated courses/moccasin-101/2-web3py/25-recap/+page.md. --- courses/moccasin-101/2-web3py/25-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/25-recap/+page.md diff --git a/courses/moccasin-101/2-web3py/25-recap/+page.md b/courses/moccasin-101/2-web3py/25-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/2-web3py/25-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 3eb0c34cb8ad90d9f55f0f00535928ab3b3d4777 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:13:45 -0700 Subject: [PATCH 128/797] Equious updated courses/moccasin-101/2-web3py/3-vyper-extension/+page.md. --- courses/moccasin-101/2-web3py/3-vyper-extension/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/3-vyper-extension/+page.md diff --git a/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md b/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md new file mode 100644 index 000000000..e1b9b773a --- /dev/null +++ b/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md @@ -0,0 +1,3 @@ +--- + title: Vyper Extension + --- \ No newline at end of file From 35fb6384344cf6e065fcfc8af02e2613dc7e547c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:16:46 -0700 Subject: [PATCH 129/797] Equious updated courses/moccasin-101/3-boa-favs/1-intro/+page.md. --- courses/moccasin-101/3-boa-favs/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/1-intro/+page.md diff --git a/courses/moccasin-101/3-boa-favs/1-intro/+page.md b/courses/moccasin-101/3-boa-favs/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 89e24aebdaf55c99f16f5a800af8bc69c6a761a8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:17:00 -0700 Subject: [PATCH 130/797] Equious updated courses/moccasin-101/3-boa-favs/10-add-person/+page.md. --- courses/moccasin-101/3-boa-favs/10-add-person/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/10-add-person/+page.md diff --git a/courses/moccasin-101/3-boa-favs/10-add-person/+page.md b/courses/moccasin-101/3-boa-favs/10-add-person/+page.md new file mode 100644 index 000000000..ec6f71030 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/10-add-person/+page.md @@ -0,0 +1,3 @@ +--- + title: Add Person + --- \ No newline at end of file From 23abd930726ad71ac41a66d41604836b46c41831 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:17:22 -0700 Subject: [PATCH 131/797] Equious updated courses/moccasin-101/3-boa-favs/11-workshop/+page.md. --- courses/moccasin-101/3-boa-favs/11-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/11-workshop/+page.md diff --git a/courses/moccasin-101/3-boa-favs/11-workshop/+page.md b/courses/moccasin-101/3-boa-favs/11-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/11-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 1ac5363fb16f612eeb1f7d37fdcde16aae289d4f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:20:54 -0700 Subject: [PATCH 132/797] Equious updated courses/moccasin-101/3-boa-favs/12-recap/+page.md. --- courses/moccasin-101/3-boa-favs/12-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/12-recap/+page.md diff --git a/courses/moccasin-101/3-boa-favs/12-recap/+page.md b/courses/moccasin-101/3-boa-favs/12-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/12-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 04befdefdb99df1b9d4b4e523251a4138388086f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:21:12 -0700 Subject: [PATCH 133/797] Equious updated courses/moccasin-101/3-boa-favs/2-setup/+page.md. --- courses/moccasin-101/3-boa-favs/2-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/2-setup/+page.md diff --git a/courses/moccasin-101/3-boa-favs/2-setup/+page.md b/courses/moccasin-101/3-boa-favs/2-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/2-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From b86b61aab04541f95d8940060a078b50ce37e81c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:22:01 -0700 Subject: [PATCH 134/797] Equious updated courses/moccasin-101/3-boa-favs/3-pyevm/+page.md. --- courses/moccasin-101/3-boa-favs/3-pyevm/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/3-pyevm/+page.md diff --git a/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md b/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md new file mode 100644 index 000000000..cbbb50791 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md @@ -0,0 +1,3 @@ +--- + title: Pyevm + --- \ No newline at end of file From c3cc23a19c2326ab528bf9ac4f35631d080fcc12 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:22:21 -0700 Subject: [PATCH 135/797] Equious updated courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md. --- courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md diff --git a/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md b/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md new file mode 100644 index 000000000..51f4c8a80 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md @@ -0,0 +1,3 @@ +--- + title: Vypercontract + --- \ No newline at end of file From 59f81494b6085f2c1db2178f74a6eb410457cbfc Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:22:38 -0700 Subject: [PATCH 136/797] Equious updated courses/moccasin-101/3-boa-favs/5-debug/+page.md. --- courses/moccasin-101/3-boa-favs/5-debug/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/5-debug/+page.md diff --git a/courses/moccasin-101/3-boa-favs/5-debug/+page.md b/courses/moccasin-101/3-boa-favs/5-debug/+page.md new file mode 100644 index 000000000..746a037b4 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/5-debug/+page.md @@ -0,0 +1,3 @@ +--- + title: Debug + --- \ No newline at end of file From c8ef044aa0b95385e34408803d1226291ea38794 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:22:52 -0700 Subject: [PATCH 137/797] Equious updated courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md. --- courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md diff --git a/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md b/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md new file mode 100644 index 000000000..5f76de142 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md @@ -0,0 +1,3 @@ +--- + title: Pyevm_ + --- \ No newline at end of file From 51bd67c7f9b9829282ddbb1111da863d831704cf Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:23:20 -0700 Subject: [PATCH 138/797] Equious updated courses/moccasin-101/3-boa-favs/7-anvil/+page.md. --- courses/moccasin-101/3-boa-favs/7-anvil/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/7-anvil/+page.md diff --git a/courses/moccasin-101/3-boa-favs/7-anvil/+page.md b/courses/moccasin-101/3-boa-favs/7-anvil/+page.md new file mode 100644 index 000000000..0c0a4fdfe --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/7-anvil/+page.md @@ -0,0 +1,3 @@ +--- + title: Anvil + --- \ No newline at end of file From 32c7d2844f29bf5e6606f7a7ca24cdbea82b8439 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:23:34 -0700 Subject: [PATCH 139/797] Equious updated courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md. --- courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md diff --git a/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md b/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md new file mode 100644 index 000000000..85923930c --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md @@ -0,0 +1,3 @@ +--- + title: Interacting Anvil + --- \ No newline at end of file From 2c9603d4538f39805ee019198b127c24bcb0f2d9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:24:03 -0700 Subject: [PATCH 140/797] Equious updated courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md. --- courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md diff --git a/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md b/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md new file mode 100644 index 000000000..87d3f90ba --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md @@ -0,0 +1,3 @@ +--- + title: Interact Prevs + --- \ No newline at end of file From 779ccecd863fc3f5682186e804beb90684d980bc Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:24:39 -0700 Subject: [PATCH 141/797] Equious updated courses/moccasin-101/4-mox-favs/1-intro/+page.md. --- courses/moccasin-101/4-mox-favs/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/1-intro/+page.md diff --git a/courses/moccasin-101/4-mox-favs/1-intro/+page.md b/courses/moccasin-101/4-mox-favs/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 27cfe84499bdcebd01a653054129fe3027fe74a1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:28:24 -0700 Subject: [PATCH 142/797] Equious updated courses/moccasin-101/4-mox-favs/10-account-cli/+page.md. --- courses/moccasin-101/4-mox-favs/10-account-cli/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/10-account-cli/+page.md diff --git a/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md b/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md new file mode 100644 index 000000000..0984dc172 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md @@ -0,0 +1,3 @@ +--- + title: Account Cli + --- \ No newline at end of file From a2ea3e9dd2c4f2338860f4a65711413082d37ea5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:28:49 -0700 Subject: [PATCH 143/797] Equious updated courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md. --- courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md diff --git a/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md b/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md new file mode 100644 index 000000000..7cc9872a4 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Testing + --- \ No newline at end of file From 65754b85baea9f3929fc58d2eccd0be28916534d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:29:20 -0700 Subject: [PATCH 144/797] Equious updated courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md. --- .../moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md diff --git a/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md b/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md new file mode 100644 index 000000000..19850ca6b --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md @@ -0,0 +1,3 @@ +--- + title: Testing Deploy Script + --- \ No newline at end of file From b547a65870df68753c64c0ed0839bbc183411cba Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:29:34 -0700 Subject: [PATCH 145/797] Equious updated courses/moccasin-101/4-mox-favs/13-aaa/+page.md. --- courses/moccasin-101/4-mox-favs/13-aaa/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/13-aaa/+page.md diff --git a/courses/moccasin-101/4-mox-favs/13-aaa/+page.md b/courses/moccasin-101/4-mox-favs/13-aaa/+page.md new file mode 100644 index 000000000..ff929f638 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/13-aaa/+page.md @@ -0,0 +1,3 @@ +--- + title: Aaa + --- \ No newline at end of file From e811799a4bc875258c4ef311f9a4b10da7c3fff9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:30:02 -0700 Subject: [PATCH 146/797] Equious updated courses/moccasin-101/4-mox-favs/14-fixtures/+page.md. --- courses/moccasin-101/4-mox-favs/14-fixtures/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/14-fixtures/+page.md diff --git a/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md b/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md new file mode 100644 index 000000000..48ccb103c --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md @@ -0,0 +1,3 @@ +--- + title: Fixtures + --- \ No newline at end of file From c849a1a69a53df8176fbeaeceec613b14b3fcaa8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:30:18 -0700 Subject: [PATCH 147/797] Equious updated courses/moccasin-101/4-mox-favs/15-conftest/+page.md. --- courses/moccasin-101/4-mox-favs/15-conftest/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/15-conftest/+page.md diff --git a/courses/moccasin-101/4-mox-favs/15-conftest/+page.md b/courses/moccasin-101/4-mox-favs/15-conftest/+page.md new file mode 100644 index 000000000..d47333a69 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/15-conftest/+page.md @@ -0,0 +1,3 @@ +--- + title: Conftest + --- \ No newline at end of file From 65653fac1e31a8fd1d09cd8c35d00d1f249a664f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:37:02 -0700 Subject: [PATCH 148/797] Equious updated courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md. --- courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md diff --git a/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md b/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md new file mode 100644 index 000000000..ad5a0b3ab --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md @@ -0,0 +1,3 @@ +--- + title: Sepolia Deploy + --- \ No newline at end of file From 45abdaf471c360d18e68d721dc9632d3b9ae4109 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:37:15 -0700 Subject: [PATCH 149/797] Equious updated courses/moccasin-101/4-mox-favs/18-verify/+page.md. --- courses/moccasin-101/4-mox-favs/18-verify/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/18-verify/+page.md diff --git a/courses/moccasin-101/4-mox-favs/18-verify/+page.md b/courses/moccasin-101/4-mox-favs/18-verify/+page.md new file mode 100644 index 000000000..0878aa404 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/18-verify/+page.md @@ -0,0 +1,3 @@ +--- + title: Verify + --- \ No newline at end of file From 8dbbec1b2ae5d516d5b57ce1a6d93e2b3255cbc5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:47:15 -0700 Subject: [PATCH 150/797] Equious updated courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md. --- courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md diff --git a/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md b/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md new file mode 100644 index 000000000..e03eaddb9 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync Setup + --- \ No newline at end of file From cfd027fbf369773b6e49130aa76004aa6756cb13 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:47:29 -0700 Subject: [PATCH 151/797] Equious updated courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md. --- courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md diff --git a/courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md b/courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md new file mode 100644 index 000000000..a4d6415c2 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md @@ -0,0 +1,3 @@ +--- + title: Instlal Mox + --- \ No newline at end of file From 95633a8f3b11ad0b7f406fc3c6c03855592772ee Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:50:21 -0700 Subject: [PATCH 152/797] Equious updated courses/moccasin-101/4-mox-favs/20-eravm/+page.md. --- courses/moccasin-101/4-mox-favs/20-eravm/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/20-eravm/+page.md diff --git a/courses/moccasin-101/4-mox-favs/20-eravm/+page.md b/courses/moccasin-101/4-mox-favs/20-eravm/+page.md new file mode 100644 index 000000000..fef1da72f --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/20-eravm/+page.md @@ -0,0 +1,3 @@ +--- + title: Eravm + --- \ No newline at end of file From 320fa995cd224bc7af1762255776029a4ab0e688 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:51:15 -0700 Subject: [PATCH 153/797] Equious updated courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md. --- courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md diff --git a/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md b/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md new file mode 100644 index 000000000..a515e5e34 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md @@ -0,0 +1,3 @@ +--- + title: Setting Up Zksync + --- \ No newline at end of file From 6d707ca14d360c3069704a2d0cfbc64e92bba873 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:51:29 -0700 Subject: [PATCH 154/797] Equious updated courses/moccasin-101/4-mox-favs/22-bridging/+page.md. --- courses/moccasin-101/4-mox-favs/22-bridging/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/22-bridging/+page.md diff --git a/courses/moccasin-101/4-mox-favs/22-bridging/+page.md b/courses/moccasin-101/4-mox-favs/22-bridging/+page.md new file mode 100644 index 000000000..1b24a95e4 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/22-bridging/+page.md @@ -0,0 +1,3 @@ +--- + title: Bridging + --- \ No newline at end of file From 77c3087e15c32d3190c5afa31dd2ac870db7f5e8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:52:56 -0700 Subject: [PATCH 155/797] Equious updated courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md. --- courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md diff --git a/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md b/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md new file mode 100644 index 000000000..ef6567697 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync Deploy + --- \ No newline at end of file From b99bdb6ecd16e7d374434b8b35b44f95649933f8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:53:12 -0700 Subject: [PATCH 156/797] Equious updated courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md. --- .../4-mox-favs/24-zksync-contract-deployment/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md diff --git a/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md b/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md new file mode 100644 index 000000000..7676d99dc --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync Contract Deployment + --- \ No newline at end of file From 16ed30959d97f8e7caeefe24e3f5e411af8a13b0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:55:01 -0700 Subject: [PATCH 157/797] Equious updated courses/moccasin-101/4-mox-favs/25-tx-types/+page.md. --- courses/moccasin-101/4-mox-favs/25-tx-types/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/25-tx-types/+page.md diff --git a/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md b/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md new file mode 100644 index 000000000..e465b90e1 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md @@ -0,0 +1,3 @@ +--- + title: Tx Types + --- \ No newline at end of file From 27a4879913138346f4ac8a826a9121c69f4cbc48 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:57:39 -0700 Subject: [PATCH 158/797] Equious updated courses/moccasin-101/4-mox-favs/26-workshop/+page.md. --- courses/moccasin-101/4-mox-favs/26-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/26-workshop/+page.md diff --git a/courses/moccasin-101/4-mox-favs/26-workshop/+page.md b/courses/moccasin-101/4-mox-favs/26-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/26-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From c1655e09f8264634ed8ada9651efff2caf99eefb Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:58:04 -0700 Subject: [PATCH 159/797] Equious updated courses/moccasin-101/4-mox-favs/3-create-mox/+page.md. --- courses/moccasin-101/4-mox-favs/3-create-mox/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/3-create-mox/+page.md diff --git a/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md b/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md new file mode 100644 index 000000000..0f542f929 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md @@ -0,0 +1,3 @@ +--- + title: Create Mox + --- \ No newline at end of file From ae5d4b616b38058060cf6ecb9f3c28b0ac98a2fd Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:58:18 -0700 Subject: [PATCH 160/797] Equious updated courses/moccasin-101/4-mox-favs/4-mox-something/+page.md. --- courses/moccasin-101/4-mox-favs/4-mox-something/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/4-mox-something/+page.md diff --git a/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md b/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md new file mode 100644 index 000000000..e56710475 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Something + --- \ No newline at end of file From 5c5d8bde6e377c13db672e2f80593095697ca366 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:58:43 -0700 Subject: [PATCH 161/797] Equious updated courses/moccasin-101/4-mox-favs/5-mox-script/+page.md. --- courses/moccasin-101/4-mox-favs/5-mox-script/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/5-mox-script/+page.md diff --git a/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md b/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md new file mode 100644 index 000000000..9b8bba199 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Script + --- \ No newline at end of file From 9ebe2d39d655b0aacabd854db8493b5beebde917 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:58:57 -0700 Subject: [PATCH 162/797] Equious updated courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md. --- courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md diff --git a/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md b/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md new file mode 100644 index 000000000..7ab4c1ff8 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md @@ -0,0 +1,3 @@ +--- + title: Encrypt Key + --- \ No newline at end of file From 978509e6b297618524fccbf4d67fb13a44e87cc9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:59:11 -0700 Subject: [PATCH 163/797] Equious updated courses/moccasin-101/4-mox-favs/8-shell/+page.md. --- courses/moccasin-101/4-mox-favs/8-shell/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/8-shell/+page.md diff --git a/courses/moccasin-101/4-mox-favs/8-shell/+page.md b/courses/moccasin-101/4-mox-favs/8-shell/+page.md new file mode 100644 index 000000000..00df35f0d --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/8-shell/+page.md @@ -0,0 +1,3 @@ +--- + title: Shell + --- \ No newline at end of file From 53b28379e8af35f15d9c926e9aa2dd9dbddbf93e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 08:59:24 -0700 Subject: [PATCH 164/797] Equious updated courses/moccasin-101/4-mox-favs/9-using-key/+page.md. --- courses/moccasin-101/4-mox-favs/9-using-key/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/9-using-key/+page.md diff --git a/courses/moccasin-101/4-mox-favs/9-using-key/+page.md b/courses/moccasin-101/4-mox-favs/9-using-key/+page.md new file mode 100644 index 000000000..dd0adc820 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/9-using-key/+page.md @@ -0,0 +1,3 @@ +--- + title: Using Key + --- \ No newline at end of file From e4fd75ceff0d3519ecc2bcd1dc72433276dabd7b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:01:01 -0700 Subject: [PATCH 165/797] Equious updated courses/moccasin-101/5-mox-five/1-intro/+page.md. --- courses/moccasin-101/5-mox-five/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/1-intro/+page.md diff --git a/courses/moccasin-101/5-mox-five/1-intro/+page.md b/courses/moccasin-101/5-mox-five/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 6cf406b0769e737259c7c6ee9d5dd67759c3c248 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:03:54 -0700 Subject: [PATCH 166/797] Equious updated courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md. --- .../5-mox-five/11-initializes-module-state/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md diff --git a/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md b/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md new file mode 100644 index 000000000..7096200f7 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md @@ -0,0 +1,3 @@ +--- + title: Initializes Module State + --- \ No newline at end of file From cbe421bc686db84637401b62cb33ee05227c72fa Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:05:58 -0700 Subject: [PATCH 167/797] Equious updated courses/moccasin-101/5-mox-five/13-workshop/+page.md. --- courses/moccasin-101/5-mox-five/13-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/13-workshop/+page.md diff --git a/courses/moccasin-101/5-mox-five/13-workshop/+page.md b/courses/moccasin-101/5-mox-five/13-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/13-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 9208f133fbe71b3e468a74ed7ab12a2d6bf9ad3a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:07:59 -0700 Subject: [PATCH 168/797] Equious updated courses/moccasin-101/5-mox-five/14-recap/+page.md. --- courses/moccasin-101/5-mox-five/14-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/14-recap/+page.md diff --git a/courses/moccasin-101/5-mox-five/14-recap/+page.md b/courses/moccasin-101/5-mox-five/14-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/5-mox-five/14-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From e250400e8c6952091d9e567d2a0512cbd29272f0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:11:30 -0700 Subject: [PATCH 169/797] Equious updated courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md. --- courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md diff --git a/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md b/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md new file mode 100644 index 000000000..a391afc59 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md @@ -0,0 +1,3 @@ +--- + title: Create Copy Of + --- \ No newline at end of file From 8195245e0e617a23a0d46b22ccfe3db45ac69288 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:11:48 -0700 Subject: [PATCH 170/797] Equious updated courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md. --- courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md diff --git a/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md b/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md new file mode 100644 index 000000000..e5dcc0071 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md @@ -0,0 +1,3 @@ +--- + title: Static Ext Call + --- \ No newline at end of file From 2726a6e9724d11f9095cfa3935cad754e0ee3f5d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:12:16 -0700 Subject: [PATCH 171/797] Equious updated courses/moccasin-101/5-mox-five/5-vyi/+page.md. --- courses/moccasin-101/5-mox-five/5-vyi/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/5-vyi/+page.md diff --git a/courses/moccasin-101/5-mox-five/5-vyi/+page.md b/courses/moccasin-101/5-mox-five/5-vyi/+page.md new file mode 100644 index 000000000..62bd446ed --- /dev/null +++ b/courses/moccasin-101/5-mox-five/5-vyi/+page.md @@ -0,0 +1,3 @@ +--- + title: Vyi + --- \ No newline at end of file From 261a3aaad29c861e1374130dadfb350a60233173 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:12:42 -0700 Subject: [PATCH 172/797] Equious updated courses/moccasin-101/5-mox-five/6-idk/+page.md. --- courses/moccasin-101/5-mox-five/6-idk/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/6-idk/+page.md diff --git a/courses/moccasin-101/5-mox-five/6-idk/+page.md b/courses/moccasin-101/5-mox-five/6-idk/+page.md new file mode 100644 index 000000000..d226208fe --- /dev/null +++ b/courses/moccasin-101/5-mox-five/6-idk/+page.md @@ -0,0 +1,3 @@ +--- + title: Idk + --- \ No newline at end of file From 5c667f90c06334aa53017503cbaeade9fd16ccaa Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:12:57 -0700 Subject: [PATCH 173/797] Equious updated courses/moccasin-101/5-mox-five/7-extcall/+page.md. --- courses/moccasin-101/5-mox-five/7-extcall/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/7-extcall/+page.md diff --git a/courses/moccasin-101/5-mox-five/7-extcall/+page.md b/courses/moccasin-101/5-mox-five/7-extcall/+page.md new file mode 100644 index 000000000..36c841a81 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/7-extcall/+page.md @@ -0,0 +1,3 @@ +--- + title: Extcall + --- \ No newline at end of file From e11d5fb177610ca3f478b5d9040a9374c398b531 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:13:10 -0700 Subject: [PATCH 174/797] Equious updated courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md. --- .../5-mox-five/8-store-contract-by-interface/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md diff --git a/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md b/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md new file mode 100644 index 000000000..d79d0e7af --- /dev/null +++ b/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md @@ -0,0 +1,3 @@ +--- + title: Store Contract By Interface + --- \ No newline at end of file From 8977c3467ab020e9ce9833f56abf94f41b1cbfeb Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:13:25 -0700 Subject: [PATCH 175/797] Equious updated courses/moccasin-101/5-mox-five/9-method-chaining/+page.md. --- courses/moccasin-101/5-mox-five/9-method-chaining/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/9-method-chaining/+page.md diff --git a/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md b/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md new file mode 100644 index 000000000..2aa8fbe12 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md @@ -0,0 +1,3 @@ +--- + title: Method Chaining + --- \ No newline at end of file From c6f51f636892df46fd32d3d2b6cd9ec52603c392 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:16:04 -0700 Subject: [PATCH 176/797] Equious updated courses/moccasin-101/6-mox-coffee/1-intro/+page.md. --- courses/moccasin-101/6-mox-coffee/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/1-intro/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/1-intro/+page.md b/courses/moccasin-101/6-mox-coffee/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 7ea5467a631888e850abb086edca6c65544e5fb8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:17:41 -0700 Subject: [PATCH 177/797] Equious updated courses/moccasin-101/6-mox-coffee/10-kinds/+page.md. --- courses/moccasin-101/6-mox-coffee/10-kinds/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/10-kinds/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md b/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md new file mode 100644 index 000000000..3a20eb491 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md @@ -0,0 +1,3 @@ +--- + title: Kinds + --- \ No newline at end of file From b6d58370f0acf63f8accba6e8ad362d36000eca5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:18:13 -0700 Subject: [PATCH 178/797] Equious updated courses/moccasin-101/6-mox-coffee/11-unit/+page.md. --- courses/moccasin-101/6-mox-coffee/11-unit/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/11-unit/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/11-unit/+page.md b/courses/moccasin-101/6-mox-coffee/11-unit/+page.md new file mode 100644 index 000000000..ef3d00c8c --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/11-unit/+page.md @@ -0,0 +1,3 @@ +--- + title: Unit + --- \ No newline at end of file From da2a367793642c8908eb36d8c648d9c15dd6ffd4 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:18:29 -0700 Subject: [PATCH 179/797] Equious updated courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md. --- courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md b/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md new file mode 100644 index 000000000..66d5d3331 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md @@ -0,0 +1,3 @@ +--- + title: Test Revert + --- \ No newline at end of file From ecdd4e9afa9ebc632520069e2b3839e2e23b500b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:18:45 -0700 Subject: [PATCH 180/797] Equious updated courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md. --- courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md b/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md new file mode 100644 index 000000000..b44c55fda --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md @@ -0,0 +1,3 @@ +--- + title: Set Balance + --- \ No newline at end of file From c6762f13ff794d434fe8f8b18e6c0a2f6b988c85 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:19:00 -0700 Subject: [PATCH 181/797] Equious updated courses/moccasin-101/6-mox-coffee/14-prank/+page.md. --- courses/moccasin-101/6-mox-coffee/14-prank/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/14-prank/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/14-prank/+page.md b/courses/moccasin-101/6-mox-coffee/14-prank/+page.md new file mode 100644 index 000000000..024a80546 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/14-prank/+page.md @@ -0,0 +1,3 @@ +--- + title: Prank + --- \ No newline at end of file From 667d7a7167d733557f8bb1ebb9e1ad0345d3fe77 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:19:15 -0700 Subject: [PATCH 182/797] Equious updated courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md. --- courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md b/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md new file mode 100644 index 000000000..510c15538 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md @@ -0,0 +1,3 @@ +--- + title: Mid Sec Work + --- \ No newline at end of file From 3e808e48591ccbd1131be57d8a17ca0ed92b2c46 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:19:29 -0700 Subject: [PATCH 183/797] Equious updated courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md. --- courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md b/courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md new file mode 100644 index 000000000..e5d0bc24e --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md @@ -0,0 +1,3 @@ +--- + title: More Fixtures + --- \ No newline at end of file From 3db920fb4f08019a3edf5cd73de81e8ffd3828b4 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:19:44 -0700 Subject: [PATCH 184/797] Equious updated courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md. --- courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md b/courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md new file mode 100644 index 000000000..25317a24e --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md @@ -0,0 +1,3 @@ +--- + title: Test Coverage + --- \ No newline at end of file From 9615176749861d59a7f033d7cac9fbc8173346ea Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:21:33 -0700 Subject: [PATCH 185/797] Equious updated courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md. --- courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md b/courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md new file mode 100644 index 000000000..88ca818ae --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md @@ -0,0 +1,3 @@ +--- + title: Gas Profile + --- \ No newline at end of file From c72b900c4b445033151b4dc0176cd552493773e5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:22:12 -0700 Subject: [PATCH 186/797] Equious updated courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md. --- courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md b/courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md new file mode 100644 index 000000000..2c00fcac4 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md @@ -0,0 +1,3 @@ +--- + title: Fork Tests + --- \ No newline at end of file From 67087fa766efb06b9a7fb17b2c45d3ebfc1cca2f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:22:39 -0700 Subject: [PATCH 187/797] Equious updated courses/moccasin-101/6-mox-coffee/19-staging/+page.md. --- courses/moccasin-101/6-mox-coffee/19-staging/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/19-staging/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/19-staging/+page.md b/courses/moccasin-101/6-mox-coffee/19-staging/+page.md new file mode 100644 index 000000000..f2de04c12 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/19-staging/+page.md @@ -0,0 +1,3 @@ +--- + title: Staging + --- \ No newline at end of file From 91e4f91a2b0434c0dc57a514ae26b30931e300f6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:23:08 -0700 Subject: [PATCH 188/797] Equious updated courses/moccasin-101/6-mox-coffee/2-setup/+page.md. --- courses/moccasin-101/6-mox-coffee/2-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/2-setup/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/2-setup/+page.md b/courses/moccasin-101/6-mox-coffee/2-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/2-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From 2a08477498cfa4ed50dfd1ac2bf07e5b63b46a5c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:23:35 -0700 Subject: [PATCH 189/797] Equious updated courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md. --- courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md b/courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md new file mode 100644 index 000000000..d1459d73d --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md @@ -0,0 +1,3 @@ +--- + title: Deployments Db + --- \ No newline at end of file From 1d695a9f55e8f2b4bfb8e9bb0c7d7450c18facde Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:23:50 -0700 Subject: [PATCH 190/797] Equious updated courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md. --- courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md b/courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md new file mode 100644 index 000000000..4f5922387 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync Testing + --- \ No newline at end of file From b1bfb6ae3b399c199397f6c98df897f3db2511be Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:31:14 -0700 Subject: [PATCH 191/797] Equious updated courses/moccasin-101/6-mox-coffee/22-github/+page.md. --- courses/moccasin-101/6-mox-coffee/22-github/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/22-github/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/22-github/+page.md b/courses/moccasin-101/6-mox-coffee/22-github/+page.md new file mode 100644 index 000000000..759cfde0e --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/22-github/+page.md @@ -0,0 +1,3 @@ +--- + title: Github + --- \ No newline at end of file From 99989ded99707cdd6ea3bf76957a1752eb8f5f32 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:32:35 -0700 Subject: [PATCH 192/797] Equious updated courses/moccasin-101/6-mox-coffee/23-clone/+page.md. --- courses/moccasin-101/6-mox-coffee/23-clone/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/23-clone/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/23-clone/+page.md b/courses/moccasin-101/6-mox-coffee/23-clone/+page.md new file mode 100644 index 000000000..bdc0c631b --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/23-clone/+page.md @@ -0,0 +1,3 @@ +--- + title: Clone + --- \ No newline at end of file From 2c165946fae10dcd282d4a5254fb14b03df66ff8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:33:49 -0700 Subject: [PATCH 193/797] Equious updated courses/moccasin-101/6-mox-coffee/24-workshop/+page.md. --- courses/moccasin-101/6-mox-coffee/24-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/24-workshop/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/24-workshop/+page.md b/courses/moccasin-101/6-mox-coffee/24-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/24-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 0c31eb3367b8351955c367e43cd9a34b874ace17 Mon Sep 17 00:00:00 2001 From: hunter <104146303+solhosty@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:13:10 -0500 Subject: [PATCH 194/797] changes --- courses/moccasin-101/1-python-on-updraft/1-intro/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/10-math/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/13-conditionals/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/14-while-loops/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/18-recap/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/2-google-collab/+page.md | 3 --- .../1-python-on-updraft/20-install-vscode-macos-linux/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/21-install-wsl/+page.md | 3 --- .../1-python-on-updraft/22-vscode-windows-install/+page.md | 3 --- .../23-vscode-windows-wsl-extension/+page.md | 3 --- .../1-python-on-updraft/24-vscode-quickstart/+page.md | 3 --- .../1-python-on-updraft/25-install-python-macos/+page.md | 3 --- .../1-python-on-updraft/26-install-python-wsl-linux/+page.md | 3 --- .../1-python-on-updraft/27-vscode-quickstart-2/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/28-mental-prep/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/3-setup/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/30-python-shell/+page.md | 3 --- .../1-python-on-updraft/31-python-extensions-vscode/+page.md | 3 --- .../1-python-on-updraft/32-our-first-python/+page.md | 3 --- .../1-python-on-updraft/33-python-imports/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/34-installing-uv/+page.md | 3 --- .../1-python-on-updraft/35-uv-python-version/+page.md | 3 --- .../1-python-on-updraft/36-adding-packages-uv/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/38-recap/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/6-python-vars/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/9-types/+page.md | 3 --- courses/moccasin-101/2-web3py/1-intro/+page.md | 3 --- courses/moccasin-101/2-web3py/18-pkey-promise/+page.md | 3 --- courses/moccasin-101/2-web3py/19-env-vars/+page.md | 3 --- courses/moccasin-101/2-web3py/2-setup/+page.md | 3 --- courses/moccasin-101/2-web3py/20-send-tx/+page.md | 3 --- courses/moccasin-101/2-web3py/21-encrypt/+page.md | 3 --- courses/moccasin-101/2-web3py/22-decrypt/+page.md | 3 --- courses/moccasin-101/2-web3py/23-pledge/+page.md | 3 --- courses/moccasin-101/2-web3py/24-workshop/+page.md | 3 --- courses/moccasin-101/2-web3py/25-recap/+page.md | 3 --- courses/moccasin-101/2-web3py/3-vyper-extension/+page.md | 3 --- courses/moccasin-101/3-boa-favs/1-intro/+page.md | 3 --- courses/moccasin-101/3-boa-favs/10-add-person/+page.md | 3 --- courses/moccasin-101/3-boa-favs/11-workshop/+page.md | 3 --- courses/moccasin-101/3-boa-favs/12-recap/+page.md | 3 --- courses/moccasin-101/3-boa-favs/2-setup/+page.md | 3 --- courses/moccasin-101/3-boa-favs/3-pyevm/+page.md | 3 --- courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md | 3 --- courses/moccasin-101/3-boa-favs/5-debug/+page.md | 3 --- courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md | 3 --- courses/moccasin-101/3-boa-favs/7-anvil/+page.md | 3 --- courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md | 3 --- courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md | 3 --- courses/moccasin-101/4-mox-favs/1-intro/+page.md | 3 --- courses/moccasin-101/4-mox-favs/10-account-cli/+page.md | 3 --- courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md | 3 --- .../moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md | 3 --- courses/moccasin-101/4-mox-favs/13-aaa/+page.md | 3 --- courses/moccasin-101/4-mox-favs/14-fixtures/+page.md | 3 --- courses/moccasin-101/4-mox-favs/15-conftest/+page.md | 3 --- courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md | 3 --- courses/moccasin-101/4-mox-favs/18-verify/+page.md | 3 --- courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md | 3 --- courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md | 3 --- courses/moccasin-101/4-mox-favs/20-eravm/+page.md | 3 --- courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md | 3 --- courses/moccasin-101/4-mox-favs/22-bridging/+page.md | 3 --- courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md | 3 --- .../4-mox-favs/24-zksync-contract-deployment/+page.md | 3 --- courses/moccasin-101/4-mox-favs/25-tx-types/+page.md | 3 --- courses/moccasin-101/4-mox-favs/26-workshop/+page.md | 3 --- courses/moccasin-101/4-mox-favs/3-create-mox/+page.md | 3 --- courses/moccasin-101/4-mox-favs/4-mox-something/+page.md | 3 --- courses/moccasin-101/4-mox-favs/5-mox-script/+page.md | 3 --- courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md | 3 --- courses/moccasin-101/4-mox-favs/8-shell/+page.md | 3 --- courses/moccasin-101/4-mox-favs/9-using-key/+page.md | 3 --- courses/moccasin-101/5-mox-five/1-intro/+page.md | 3 --- .../5-mox-five/11-initializes-module-state/+page.md | 3 --- courses/moccasin-101/5-mox-five/13-workshop/+page.md | 3 --- courses/moccasin-101/5-mox-five/14-recap/+page.md | 3 --- courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md | 3 --- courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md | 3 --- courses/moccasin-101/5-mox-five/5-vyi/+page.md | 3 --- courses/moccasin-101/5-mox-five/6-idk/+page.md | 3 --- courses/moccasin-101/5-mox-five/7-extcall/+page.md | 3 --- .../5-mox-five/8-store-contract-by-interface/+page.md | 3 --- courses/moccasin-101/5-mox-five/9-method-chaining/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/1-intro/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/10-kinds/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/11-unit/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/14-prank/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/19-staging/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/2-setup/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/22-github/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/23-clone/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/24-workshop/+page.md | 3 --- 115 files changed, 345 deletions(-) delete mode 100644 courses/moccasin-101/1-python-on-updraft/1-intro/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/10-math/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/18-recap/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/3-setup/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/38-recap/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/9-types/+page.md delete mode 100644 courses/moccasin-101/2-web3py/1-intro/+page.md delete mode 100644 courses/moccasin-101/2-web3py/18-pkey-promise/+page.md delete mode 100644 courses/moccasin-101/2-web3py/19-env-vars/+page.md delete mode 100644 courses/moccasin-101/2-web3py/2-setup/+page.md delete mode 100644 courses/moccasin-101/2-web3py/20-send-tx/+page.md delete mode 100644 courses/moccasin-101/2-web3py/21-encrypt/+page.md delete mode 100644 courses/moccasin-101/2-web3py/22-decrypt/+page.md delete mode 100644 courses/moccasin-101/2-web3py/23-pledge/+page.md delete mode 100644 courses/moccasin-101/2-web3py/24-workshop/+page.md delete mode 100644 courses/moccasin-101/2-web3py/25-recap/+page.md delete mode 100644 courses/moccasin-101/2-web3py/3-vyper-extension/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/1-intro/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/10-add-person/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/11-workshop/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/12-recap/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/2-setup/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/3-pyevm/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/5-debug/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/7-anvil/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/1-intro/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/10-account-cli/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/13-aaa/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/14-fixtures/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/15-conftest/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/18-verify/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/20-eravm/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/22-bridging/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/25-tx-types/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/26-workshop/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/3-create-mox/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/4-mox-something/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/5-mox-script/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/8-shell/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/9-using-key/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/1-intro/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/13-workshop/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/14-recap/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/5-vyi/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/6-idk/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/7-extcall/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/9-method-chaining/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/1-intro/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/10-kinds/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/11-unit/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/14-prank/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/19-staging/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/2-setup/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/22-github/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/23-clone/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/24-workshop/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/1-intro/+page.md b/courses/moccasin-101/1-python-on-updraft/1-intro/+page.md deleted file mode 100644 index b7e64e913..000000000 --- a/courses/moccasin-101/1-python-on-updraft/1-intro/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Intro - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/10-math/+page.md b/courses/moccasin-101/1-python-on-updraft/10-math/+page.md deleted file mode 100644 index d246d700c..000000000 --- a/courses/moccasin-101/1-python-on-updraft/10-math/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Math - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md b/courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md deleted file mode 100644 index 52de64c11..000000000 --- a/courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: More Math - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md b/courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md deleted file mode 100644 index 125b3fa6b..000000000 --- a/courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Funcs - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md b/courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md deleted file mode 100644 index 1d57c9ca3..000000000 --- a/courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Conditionals - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md b/courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md deleted file mode 100644 index 9e54beace..000000000 --- a/courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: While Loops - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md b/courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md deleted file mode 100644 index 1633a4fcb..000000000 --- a/courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Loops 2 - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md b/courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md deleted file mode 100644 index 3e226d5ca..000000000 --- a/courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Loops 3 - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md b/courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md deleted file mode 100644 index 789149836..000000000 --- a/courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Workshop - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/18-recap/+page.md b/courses/moccasin-101/1-python-on-updraft/18-recap/+page.md deleted file mode 100644 index 385e6edfe..000000000 --- a/courses/moccasin-101/1-python-on-updraft/18-recap/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Recap - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md b/courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md deleted file mode 100644 index 82dee4ad0..000000000 --- a/courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Dev Env Setup - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md b/courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md deleted file mode 100644 index 735bc3c07..000000000 --- a/courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Google Collab - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md b/courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md deleted file mode 100644 index 29e695218..000000000 --- a/courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Install Vscode Macos Linux - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md b/courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md deleted file mode 100644 index 475d38e9a..000000000 --- a/courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Install Wsl - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md b/courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md deleted file mode 100644 index a09ad1944..000000000 --- a/courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vscode Windows Install - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md b/courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md deleted file mode 100644 index 2acc9a55f..000000000 --- a/courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vscode Windows Wsl Extension - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md b/courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md deleted file mode 100644 index 3ab104359..000000000 --- a/courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vscode Quickstart - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md b/courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md deleted file mode 100644 index d2148949d..000000000 --- a/courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Install Python Macos - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md b/courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md deleted file mode 100644 index d18275288..000000000 --- a/courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Install Python Wsl Linux - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md b/courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md deleted file mode 100644 index 7d3ad9c57..000000000 --- a/courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vscode Quickstart 2 - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md b/courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md deleted file mode 100644 index cfcec4377..000000000 --- a/courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Mental Prep - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md b/courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md deleted file mode 100644 index 8c591a536..000000000 --- a/courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Local Py - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/3-setup/+page.md b/courses/moccasin-101/1-python-on-updraft/3-setup/+page.md deleted file mode 100644 index fcc7a149d..000000000 --- a/courses/moccasin-101/1-python-on-updraft/3-setup/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Setup - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md b/courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md deleted file mode 100644 index 9c47c3f3e..000000000 --- a/courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Python Shell - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md b/courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md deleted file mode 100644 index 85f6eb88c..000000000 --- a/courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Python Extensions Vscode - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md b/courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md deleted file mode 100644 index f790b0411..000000000 --- a/courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Our First Python - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md b/courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md deleted file mode 100644 index fae7a0f96..000000000 --- a/courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Python Imports - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md b/courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md deleted file mode 100644 index ef00c9919..000000000 --- a/courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Installing Uv - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md b/courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md deleted file mode 100644 index 84d31ea64..000000000 --- a/courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Uv Python Version - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md b/courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md deleted file mode 100644 index d2268f193..000000000 --- a/courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Adding Packages Uv - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md b/courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md deleted file mode 100644 index c211b8e01..000000000 --- a/courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Virtual Envs - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/38-recap/+page.md b/courses/moccasin-101/1-python-on-updraft/38-recap/+page.md deleted file mode 100644 index 385e6edfe..000000000 --- a/courses/moccasin-101/1-python-on-updraft/38-recap/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Recap - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md b/courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md deleted file mode 100644 index e4cab53fa..000000000 --- a/courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Notebook - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md b/courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md deleted file mode 100644 index faa0a0f12..000000000 --- a/courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Google Ai - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md b/courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md deleted file mode 100644 index 9d8367c72..000000000 --- a/courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Python Vars - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md b/courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md deleted file mode 100644 index 3f01df5ef..000000000 --- a/courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Type Hints - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md b/courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md deleted file mode 100644 index 267733150..000000000 --- a/courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Arrays - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md b/courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md deleted file mode 100644 index 8a90dbef7..000000000 --- a/courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Inputs - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/9-types/+page.md b/courses/moccasin-101/1-python-on-updraft/9-types/+page.md deleted file mode 100644 index c6210ebf1..000000000 --- a/courses/moccasin-101/1-python-on-updraft/9-types/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Types - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/1-intro/+page.md b/courses/moccasin-101/2-web3py/1-intro/+page.md deleted file mode 100644 index b7e64e913..000000000 --- a/courses/moccasin-101/2-web3py/1-intro/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Intro - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md b/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md deleted file mode 100644 index 08c6274da..000000000 --- a/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Pkey Promise - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/19-env-vars/+page.md b/courses/moccasin-101/2-web3py/19-env-vars/+page.md deleted file mode 100644 index e97071bde..000000000 --- a/courses/moccasin-101/2-web3py/19-env-vars/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Env Vars - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/2-setup/+page.md b/courses/moccasin-101/2-web3py/2-setup/+page.md deleted file mode 100644 index fcc7a149d..000000000 --- a/courses/moccasin-101/2-web3py/2-setup/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Setup - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/20-send-tx/+page.md b/courses/moccasin-101/2-web3py/20-send-tx/+page.md deleted file mode 100644 index 5b4867baa..000000000 --- a/courses/moccasin-101/2-web3py/20-send-tx/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Send Tx - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/21-encrypt/+page.md b/courses/moccasin-101/2-web3py/21-encrypt/+page.md deleted file mode 100644 index 56ef26d1d..000000000 --- a/courses/moccasin-101/2-web3py/21-encrypt/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Encrypt - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/22-decrypt/+page.md b/courses/moccasin-101/2-web3py/22-decrypt/+page.md deleted file mode 100644 index 19a99651f..000000000 --- a/courses/moccasin-101/2-web3py/22-decrypt/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Decrypt - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/23-pledge/+page.md b/courses/moccasin-101/2-web3py/23-pledge/+page.md deleted file mode 100644 index dea23512b..000000000 --- a/courses/moccasin-101/2-web3py/23-pledge/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Pledge - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/24-workshop/+page.md b/courses/moccasin-101/2-web3py/24-workshop/+page.md deleted file mode 100644 index 789149836..000000000 --- a/courses/moccasin-101/2-web3py/24-workshop/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Workshop - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/25-recap/+page.md b/courses/moccasin-101/2-web3py/25-recap/+page.md deleted file mode 100644 index 385e6edfe..000000000 --- a/courses/moccasin-101/2-web3py/25-recap/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Recap - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md b/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md deleted file mode 100644 index e1b9b773a..000000000 --- a/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vyper Extension - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/1-intro/+page.md b/courses/moccasin-101/3-boa-favs/1-intro/+page.md deleted file mode 100644 index b7e64e913..000000000 --- a/courses/moccasin-101/3-boa-favs/1-intro/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Intro - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/10-add-person/+page.md b/courses/moccasin-101/3-boa-favs/10-add-person/+page.md deleted file mode 100644 index ec6f71030..000000000 --- a/courses/moccasin-101/3-boa-favs/10-add-person/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Add Person - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/11-workshop/+page.md b/courses/moccasin-101/3-boa-favs/11-workshop/+page.md deleted file mode 100644 index 789149836..000000000 --- a/courses/moccasin-101/3-boa-favs/11-workshop/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Workshop - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/12-recap/+page.md b/courses/moccasin-101/3-boa-favs/12-recap/+page.md deleted file mode 100644 index 385e6edfe..000000000 --- a/courses/moccasin-101/3-boa-favs/12-recap/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Recap - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/2-setup/+page.md b/courses/moccasin-101/3-boa-favs/2-setup/+page.md deleted file mode 100644 index fcc7a149d..000000000 --- a/courses/moccasin-101/3-boa-favs/2-setup/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Setup - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md b/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md deleted file mode 100644 index cbbb50791..000000000 --- a/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Pyevm - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md b/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md deleted file mode 100644 index 51f4c8a80..000000000 --- a/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vypercontract - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/5-debug/+page.md b/courses/moccasin-101/3-boa-favs/5-debug/+page.md deleted file mode 100644 index 746a037b4..000000000 --- a/courses/moccasin-101/3-boa-favs/5-debug/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Debug - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md b/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md deleted file mode 100644 index 5f76de142..000000000 --- a/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Pyevm_ - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/7-anvil/+page.md b/courses/moccasin-101/3-boa-favs/7-anvil/+page.md deleted file mode 100644 index 0c0a4fdfe..000000000 --- a/courses/moccasin-101/3-boa-favs/7-anvil/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Anvil - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md b/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md deleted file mode 100644 index 85923930c..000000000 --- a/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Interacting Anvil - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md b/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md deleted file mode 100644 index 87d3f90ba..000000000 --- a/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Interact Prevs - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/1-intro/+page.md b/courses/moccasin-101/4-mox-favs/1-intro/+page.md deleted file mode 100644 index b7e64e913..000000000 --- a/courses/moccasin-101/4-mox-favs/1-intro/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Intro - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md b/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md deleted file mode 100644 index 0984dc172..000000000 --- a/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Account Cli - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md b/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md deleted file mode 100644 index 7cc9872a4..000000000 --- a/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Mox Testing - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md b/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md deleted file mode 100644 index 19850ca6b..000000000 --- a/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Testing Deploy Script - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/13-aaa/+page.md b/courses/moccasin-101/4-mox-favs/13-aaa/+page.md deleted file mode 100644 index ff929f638..000000000 --- a/courses/moccasin-101/4-mox-favs/13-aaa/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Aaa - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md b/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md deleted file mode 100644 index 48ccb103c..000000000 --- a/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Fixtures - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/15-conftest/+page.md b/courses/moccasin-101/4-mox-favs/15-conftest/+page.md deleted file mode 100644 index d47333a69..000000000 --- a/courses/moccasin-101/4-mox-favs/15-conftest/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Conftest - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md b/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md deleted file mode 100644 index ad5a0b3ab..000000000 --- a/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Sepolia Deploy - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/18-verify/+page.md b/courses/moccasin-101/4-mox-favs/18-verify/+page.md deleted file mode 100644 index 0878aa404..000000000 --- a/courses/moccasin-101/4-mox-favs/18-verify/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Verify - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md b/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md deleted file mode 100644 index e03eaddb9..000000000 --- a/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Zksync Setup - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md b/courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md deleted file mode 100644 index a4d6415c2..000000000 --- a/courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Instlal Mox - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/20-eravm/+page.md b/courses/moccasin-101/4-mox-favs/20-eravm/+page.md deleted file mode 100644 index fef1da72f..000000000 --- a/courses/moccasin-101/4-mox-favs/20-eravm/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Eravm - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md b/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md deleted file mode 100644 index a515e5e34..000000000 --- a/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Setting Up Zksync - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/22-bridging/+page.md b/courses/moccasin-101/4-mox-favs/22-bridging/+page.md deleted file mode 100644 index 1b24a95e4..000000000 --- a/courses/moccasin-101/4-mox-favs/22-bridging/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Bridging - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md b/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md deleted file mode 100644 index ef6567697..000000000 --- a/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Zksync Deploy - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md b/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md deleted file mode 100644 index 7676d99dc..000000000 --- a/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Zksync Contract Deployment - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md b/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md deleted file mode 100644 index e465b90e1..000000000 --- a/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Tx Types - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/26-workshop/+page.md b/courses/moccasin-101/4-mox-favs/26-workshop/+page.md deleted file mode 100644 index 789149836..000000000 --- a/courses/moccasin-101/4-mox-favs/26-workshop/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Workshop - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md b/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md deleted file mode 100644 index 0f542f929..000000000 --- a/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Create Mox - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md b/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md deleted file mode 100644 index e56710475..000000000 --- a/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Mox Something - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md b/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md deleted file mode 100644 index 9b8bba199..000000000 --- a/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Mox Script - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md b/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md deleted file mode 100644 index 7ab4c1ff8..000000000 --- a/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Encrypt Key - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/8-shell/+page.md b/courses/moccasin-101/4-mox-favs/8-shell/+page.md deleted file mode 100644 index 00df35f0d..000000000 --- a/courses/moccasin-101/4-mox-favs/8-shell/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Shell - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/9-using-key/+page.md b/courses/moccasin-101/4-mox-favs/9-using-key/+page.md deleted file mode 100644 index dd0adc820..000000000 --- a/courses/moccasin-101/4-mox-favs/9-using-key/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Using Key - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/1-intro/+page.md b/courses/moccasin-101/5-mox-five/1-intro/+page.md deleted file mode 100644 index b7e64e913..000000000 --- a/courses/moccasin-101/5-mox-five/1-intro/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Intro - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md b/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md deleted file mode 100644 index 7096200f7..000000000 --- a/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Initializes Module State - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/13-workshop/+page.md b/courses/moccasin-101/5-mox-five/13-workshop/+page.md deleted file mode 100644 index 789149836..000000000 --- a/courses/moccasin-101/5-mox-five/13-workshop/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Workshop - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/14-recap/+page.md b/courses/moccasin-101/5-mox-five/14-recap/+page.md deleted file mode 100644 index 385e6edfe..000000000 --- a/courses/moccasin-101/5-mox-five/14-recap/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Recap - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md b/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md deleted file mode 100644 index a391afc59..000000000 --- a/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Create Copy Of - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md b/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md deleted file mode 100644 index e5dcc0071..000000000 --- a/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Static Ext Call - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/5-vyi/+page.md b/courses/moccasin-101/5-mox-five/5-vyi/+page.md deleted file mode 100644 index 62bd446ed..000000000 --- a/courses/moccasin-101/5-mox-five/5-vyi/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vyi - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/6-idk/+page.md b/courses/moccasin-101/5-mox-five/6-idk/+page.md deleted file mode 100644 index d226208fe..000000000 --- a/courses/moccasin-101/5-mox-five/6-idk/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Idk - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/7-extcall/+page.md b/courses/moccasin-101/5-mox-five/7-extcall/+page.md deleted file mode 100644 index 36c841a81..000000000 --- a/courses/moccasin-101/5-mox-five/7-extcall/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Extcall - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md b/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md deleted file mode 100644 index d79d0e7af..000000000 --- a/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Store Contract By Interface - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md b/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md deleted file mode 100644 index 2aa8fbe12..000000000 --- a/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Method Chaining - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/1-intro/+page.md b/courses/moccasin-101/6-mox-coffee/1-intro/+page.md deleted file mode 100644 index b7e64e913..000000000 --- a/courses/moccasin-101/6-mox-coffee/1-intro/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Intro - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md b/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md deleted file mode 100644 index 3a20eb491..000000000 --- a/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Kinds - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/11-unit/+page.md b/courses/moccasin-101/6-mox-coffee/11-unit/+page.md deleted file mode 100644 index ef3d00c8c..000000000 --- a/courses/moccasin-101/6-mox-coffee/11-unit/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Unit - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md b/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md deleted file mode 100644 index 66d5d3331..000000000 --- a/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Test Revert - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md b/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md deleted file mode 100644 index b44c55fda..000000000 --- a/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Set Balance - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/14-prank/+page.md b/courses/moccasin-101/6-mox-coffee/14-prank/+page.md deleted file mode 100644 index 024a80546..000000000 --- a/courses/moccasin-101/6-mox-coffee/14-prank/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Prank - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md b/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md deleted file mode 100644 index 510c15538..000000000 --- a/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Mid Sec Work - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md b/courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md deleted file mode 100644 index e5d0bc24e..000000000 --- a/courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: More Fixtures - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md b/courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md deleted file mode 100644 index 25317a24e..000000000 --- a/courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Test Coverage - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md b/courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md deleted file mode 100644 index 88ca818ae..000000000 --- a/courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Gas Profile - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md b/courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md deleted file mode 100644 index 2c00fcac4..000000000 --- a/courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Fork Tests - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/19-staging/+page.md b/courses/moccasin-101/6-mox-coffee/19-staging/+page.md deleted file mode 100644 index f2de04c12..000000000 --- a/courses/moccasin-101/6-mox-coffee/19-staging/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Staging - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/2-setup/+page.md b/courses/moccasin-101/6-mox-coffee/2-setup/+page.md deleted file mode 100644 index fcc7a149d..000000000 --- a/courses/moccasin-101/6-mox-coffee/2-setup/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Setup - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md b/courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md deleted file mode 100644 index d1459d73d..000000000 --- a/courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Deployments Db - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md b/courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md deleted file mode 100644 index 4f5922387..000000000 --- a/courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Zksync Testing - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/22-github/+page.md b/courses/moccasin-101/6-mox-coffee/22-github/+page.md deleted file mode 100644 index 759cfde0e..000000000 --- a/courses/moccasin-101/6-mox-coffee/22-github/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Github - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/23-clone/+page.md b/courses/moccasin-101/6-mox-coffee/23-clone/+page.md deleted file mode 100644 index bdc0c631b..000000000 --- a/courses/moccasin-101/6-mox-coffee/23-clone/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Clone - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/24-workshop/+page.md b/courses/moccasin-101/6-mox-coffee/24-workshop/+page.md deleted file mode 100644 index 789149836..000000000 --- a/courses/moccasin-101/6-mox-coffee/24-workshop/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Workshop - --- \ No newline at end of file From 1c8f896112b28bf124b83d29242ea64d275b95b8 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:22 -0500 Subject: [PATCH 195/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/4-vscode-setup-windows/+page.md. --- .../1-foundry-simple-storage/4-vscode-setup-windows/+page.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 courses/foundry/1-foundry-simple-storage/4-vscode-setup-windows/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/4-vscode-setup-windows/+page.md b/courses/foundry/1-foundry-simple-storage/4-vscode-setup-windows/+page.md new file mode 100644 index 000000000..e69de29bb From 2feb7a31b577596f14e11e3ef692d549cd047105 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:23 -0500 Subject: [PATCH 196/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/5-vscode-wsl-extension/+page.md. --- .../1-foundry-simple-storage/5-vscode-wsl-extension/+page.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 courses/foundry/1-foundry-simple-storage/5-vscode-wsl-extension/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/5-vscode-wsl-extension/+page.md b/courses/foundry/1-foundry-simple-storage/5-vscode-wsl-extension/+page.md new file mode 100644 index 000000000..e69de29bb From 3f391426b6d9ae1480adbec0f2322ca1a7f0deb0 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:24 -0500 Subject: [PATCH 197/797] PatrickAlphaC removing file due to editing --- .../8-create-a-new-foundry-project/+page.md | 86 ------------------- 1 file changed, 86 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/8-create-a-new-foundry-project/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/8-create-a-new-foundry-project/+page.md b/courses/foundry/1-foundry-simple-storage/8-create-a-new-foundry-project/+page.md deleted file mode 100644 index 818e66f52..000000000 --- a/courses/foundry/1-foundry-simple-storage/8-create-a-new-foundry-project/+page.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Create a new Foundry project ---- - -_Follow along with this video:_ - ---- - -### More setup - -Make sure we are in the folder we created in the previous lesson. - -**Reminder**: We ran the following commands - -``` -mkdir foundry-f23 -cd foundry-f23 -``` - -Now type the following commands: - -``` -mkdir foundry-simple-storage-f23 -cd foundry-simple-storage-f23 -``` - -You can always make the `cd` command faster by pressing the `Tab` key after you type the first couple of letters from the destination name. `Tab` lets you autocomplete a lot of commands/paths. - -If you type `code .` a new instance of VS Code will open, having the `foundry-simple-storage-f23` as the default path. - -You can see the contents of this folder on the left sidebar. Try the following command: - -``` -touch randomFile.txt -``` - -This will create a `randomFile.txt` - -If you want to delete it type: - -``` -rm randomFile.txt -``` - -The terminal is pretty slick when it comes to moving/opening/creating directories/files, changing paths and generally running things. I recommend going through [this tutorial](https://ubuntu.com/tutorials/command-line-for-beginners#1-overview) if you want to learn how to move extra fast. - -### Creating a New Project - -The way you [create a new Foundry project](https://book.getfoundry.sh/projects/creating-a-new-project) is by running the `forge init` command. This will create a new Foundry project in your current working directory. - -If you want Foundry to create the new project in a new folder type `forge init nameOfNewFolder`. - -Keep in mind that by default `forge init` expects an empty folder. If your folder is not empty you must run `forge init --force .` - -Be sure to configure your username and email if you encounter errors related to Git configuration. - -``` -git config --global user.email "yourEmail@provider.com" -git config --global user.name "yourUsername" -``` - -And that's it, your folder should look as follows: - -::image{src='/foundry-simply-storage/7-create-a-new-foundry-project/Image1.PNG' style='width: 75%; height: auto;'} - -**But what does all this mean?** - -`lib` is the folder where all your dependencies are installed, here you'll find things like: - -- `forge-std` (the forge library used for testing and scripting) -- `openzeppelin-contracts` is the most battle-tested library of smart contracts -- and many more, depending on what you need/install - -`scripts` is a folder that houses all your scripts - -`src` is the folder where you put all your smart contracts - -`test` is the folder that houses all your tests - -`foundry.toml` - gives configuration parameters for Foundry - -More on these folders and files later. - -Please right-click `src`, click on `New File` and name it `SimpleStorage.sol`. Copy the code available [here](https://github.com/Cyfrin/foundry-simple-storage-f23/blob/main/src/SimpleStorage.sol). - -One last thing, please delete `Counter.s.sol`, `Counter.sol` and `Counter.t.sol`. These files are a set of basic smart contracts that Foundry provides as a default when you create a new Foundry project. From 58c31a715a48e3bbc0f437e899607990ff369830 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:25 -0500 Subject: [PATCH 198/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/10-create-a-new-foundry-project/+page.md. --- .../10-create-a-new-foundry-project/+page.md | 86 +++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/10-create-a-new-foundry-project/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/10-create-a-new-foundry-project/+page.md b/courses/foundry/1-foundry-simple-storage/10-create-a-new-foundry-project/+page.md new file mode 100644 index 000000000..818e66f52 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/10-create-a-new-foundry-project/+page.md @@ -0,0 +1,86 @@ +--- +title: Create a new Foundry project +--- + +_Follow along with this video:_ + +--- + +### More setup + +Make sure we are in the folder we created in the previous lesson. + +**Reminder**: We ran the following commands + +``` +mkdir foundry-f23 +cd foundry-f23 +``` + +Now type the following commands: + +``` +mkdir foundry-simple-storage-f23 +cd foundry-simple-storage-f23 +``` + +You can always make the `cd` command faster by pressing the `Tab` key after you type the first couple of letters from the destination name. `Tab` lets you autocomplete a lot of commands/paths. + +If you type `code .` a new instance of VS Code will open, having the `foundry-simple-storage-f23` as the default path. + +You can see the contents of this folder on the left sidebar. Try the following command: + +``` +touch randomFile.txt +``` + +This will create a `randomFile.txt` + +If you want to delete it type: + +``` +rm randomFile.txt +``` + +The terminal is pretty slick when it comes to moving/opening/creating directories/files, changing paths and generally running things. I recommend going through [this tutorial](https://ubuntu.com/tutorials/command-line-for-beginners#1-overview) if you want to learn how to move extra fast. + +### Creating a New Project + +The way you [create a new Foundry project](https://book.getfoundry.sh/projects/creating-a-new-project) is by running the `forge init` command. This will create a new Foundry project in your current working directory. + +If you want Foundry to create the new project in a new folder type `forge init nameOfNewFolder`. + +Keep in mind that by default `forge init` expects an empty folder. If your folder is not empty you must run `forge init --force .` + +Be sure to configure your username and email if you encounter errors related to Git configuration. + +``` +git config --global user.email "yourEmail@provider.com" +git config --global user.name "yourUsername" +``` + +And that's it, your folder should look as follows: + +::image{src='/foundry-simply-storage/7-create-a-new-foundry-project/Image1.PNG' style='width: 75%; height: auto;'} + +**But what does all this mean?** + +`lib` is the folder where all your dependencies are installed, here you'll find things like: + +- `forge-std` (the forge library used for testing and scripting) +- `openzeppelin-contracts` is the most battle-tested library of smart contracts +- and many more, depending on what you need/install + +`scripts` is a folder that houses all your scripts + +`src` is the folder where you put all your smart contracts + +`test` is the folder that houses all your tests + +`foundry.toml` - gives configuration parameters for Foundry + +More on these folders and files later. + +Please right-click `src`, click on `New File` and name it `SimpleStorage.sol`. Copy the code available [here](https://github.com/Cyfrin/foundry-simple-storage-f23/blob/main/src/SimpleStorage.sol). + +One last thing, please delete `Counter.s.sol`, `Counter.sol` and `Counter.t.sol`. These files are a set of basic smart contracts that Foundry provides as a default when you create a new Foundry project. From ed99eacd69050b701f4c16ec4a6d5d4022ceb86b Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:26 -0500 Subject: [PATCH 199/797] PatrickAlphaC removing file due to editing --- .../+page.md | 31 ------------------- 1 file changed, 31 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/9-create-a-new-foundry-project-wsl/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/9-create-a-new-foundry-project-wsl/+page.md b/courses/foundry/1-foundry-simple-storage/9-create-a-new-foundry-project-wsl/+page.md deleted file mode 100644 index 8753fcd6c..000000000 --- a/courses/foundry/1-foundry-simple-storage/9-create-a-new-foundry-project-wsl/+page.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: WSL setup ---- - -_Follow along with the video_ - ---- - -### Introduction - -Hallo 👋🏻, I'm Vasily and I'll be your instructor for all Windows development. You'll see me frequently as I guide you through installing, running, and configuring various Windows tools. - -### WSL setup - -Microsoft has significantly improved its development environment support in recent years. However, for _smart contract development_, installing dependencies can sometimes be tricky. To streamline this process, we will use the **Windows Subsystem for Linux (WSL)**: this is a better option because it enables a full-fledged _unix-like console_ on your Windows machine, simplifying the use of tools and utilities commonly found in unix-based environments. This setup ensures compatibility with all the code that runs on unix-based systems like macOS and Linux. - -To install WSL, you can begin by opening the Windows terminal. On Windows 11, press the Windows key, type "terminal," and hit `enter`. On Windows 10, you need to install the Windows terminal from the Microsoft Store (select the official app from Microsoft Corporation). - -Once installed, open the terminal and type `wsl --install`. This command will initiate the installation process. Afterward, restart your computer. Upon reboot, the terminal will appear again, prompting you to select a Unix username and set a password. WSL will be then successfully installed ✅. - -### Visual Studio Code - -After installing WSL, we need to install a code editor. We will use Visual Studio Code (VS Code), and there are three different methods to install it: - -1. **Using the Terminal**: Utilize `winget`, a package manager pre-installed on Windows 11. Open the terminal and type `winget search VS Code` to find the desired package. Then, execute `winget install Microsoft.VisualStudioCode` to install VS Code. - -2. **Via Web Browser**: Search for "Visual Studio Code" in your web browser, select the official Microsoft link and download the installer. Follow the prompts, accept the user agreement and customize all the installation options. - -3. **Using VSCodium**: For those who prefer more independence and privacy, there is an open-source alternative called **VSCodium**. It is similar to VS Code but without Microsoft's telemetry. Download the [VSCodium installer](https://github.com/VSCodium/vscodium/releases) from GitHub and follow its similar installation steps. - -Choose the method that best suits your needs. For this course, I will use the official Visual Studio Code from Microsoft. From bbb15bb07f5e919124ce9b9d40b9fa1d4722af67 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:27 -0500 Subject: [PATCH 200/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/11-create-a-new-foundry-project-wsl/+page.md. --- .../+page.md | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/11-create-a-new-foundry-project-wsl/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/11-create-a-new-foundry-project-wsl/+page.md b/courses/foundry/1-foundry-simple-storage/11-create-a-new-foundry-project-wsl/+page.md new file mode 100644 index 000000000..8753fcd6c --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/11-create-a-new-foundry-project-wsl/+page.md @@ -0,0 +1,31 @@ +--- +title: WSL setup +--- + +_Follow along with the video_ + +--- + +### Introduction + +Hallo 👋🏻, I'm Vasily and I'll be your instructor for all Windows development. You'll see me frequently as I guide you through installing, running, and configuring various Windows tools. + +### WSL setup + +Microsoft has significantly improved its development environment support in recent years. However, for _smart contract development_, installing dependencies can sometimes be tricky. To streamline this process, we will use the **Windows Subsystem for Linux (WSL)**: this is a better option because it enables a full-fledged _unix-like console_ on your Windows machine, simplifying the use of tools and utilities commonly found in unix-based environments. This setup ensures compatibility with all the code that runs on unix-based systems like macOS and Linux. + +To install WSL, you can begin by opening the Windows terminal. On Windows 11, press the Windows key, type "terminal," and hit `enter`. On Windows 10, you need to install the Windows terminal from the Microsoft Store (select the official app from Microsoft Corporation). + +Once installed, open the terminal and type `wsl --install`. This command will initiate the installation process. Afterward, restart your computer. Upon reboot, the terminal will appear again, prompting you to select a Unix username and set a password. WSL will be then successfully installed ✅. + +### Visual Studio Code + +After installing WSL, we need to install a code editor. We will use Visual Studio Code (VS Code), and there are three different methods to install it: + +1. **Using the Terminal**: Utilize `winget`, a package manager pre-installed on Windows 11. Open the terminal and type `winget search VS Code` to find the desired package. Then, execute `winget install Microsoft.VisualStudioCode` to install VS Code. + +2. **Via Web Browser**: Search for "Visual Studio Code" in your web browser, select the official Microsoft link and download the installer. Follow the prompts, accept the user agreement and customize all the installation options. + +3. **Using VSCodium**: For those who prefer more independence and privacy, there is an open-source alternative called **VSCodium**. It is similar to VS Code but without Microsoft's telemetry. Download the [VSCodium installer](https://github.com/VSCodium/vscodium/releases) from GitHub and follow its similar installation steps. + +Choose the method that best suits your needs. For this course, I will use the official Visual Studio Code from Microsoft. From 03de366b7c78ddfb4f91a8100a7241c8a648c304 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:28 -0500 Subject: [PATCH 201/797] PatrickAlphaC removing file due to editing --- .../10-vscode-solidity-setup/+page.md | 64 ------------------- 1 file changed, 64 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/10-vscode-solidity-setup/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/10-vscode-solidity-setup/+page.md b/courses/foundry/1-foundry-simple-storage/10-vscode-solidity-setup/+page.md deleted file mode 100644 index ae3566759..000000000 --- a/courses/foundry/1-foundry-simple-storage/10-vscode-solidity-setup/+page.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: VSCode Solidity setup ---- - -_Follow along with this video:_ - ---- - -### Improving Code Format in Visual Studio Code - -When you first start, your code might just look like a whole bunch of dull, lifeless, white text. - -This can be easily fixed by using one of the `Solidity` extensions. Out of all the Solidity extensions available in the Extensions tab (CTRL/CMD + SHIFT + X) the following are worth mentioning: - -1. [Solidity by Juan Blanco](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity), the most used Solidity extension out there. -2. [Solidity by Nomic Foundation](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity) is Patrick's favorite Solidity extension. The rest of the course will be displaying this extension. -3. [Solidity Visual Developer](https://marketplace.visualstudio.com/items?itemName=tintinweb.solidity-visual-auditor) is another popular choice. - -**NOTE**: If the code remains unhighlighted despite having installed the extension, there's a quick solution to that. Press `Command + Shift + P`, or `Control + Shift + P` on Windows. This opens up the command bar. In the command bar, type in "Settings" and select "Preferences: Open User Settings (JSON)". - -If you have nothing in there, create a new setting by typing in: - -``` -{ - "editor.defaultFormatter": "NomicFoundation.hardhat" -} -``` - -Use: - -`"editor.defaultFormatter": "tintinweb.solidity-visual-auditor"` for Solidity Visual Developer - -or - -`"editor.defaultFormatter": "JuanBlanco.solidity"` for Solidity by Juan Blanco - -### Other interesting extensions - -In the previous lesson, we mentioned a file called `foundry.toml`. This also has an extension that formats it to make it easier to read. Please install [Even Better TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml). - -Another indispensable extension is [Inline Bookmarks](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-inline-bookmarks). - -The Inline Bookmarks plugin facilitates bookmarking the actual code. The extension can be used for document review, auditing, log analysis, and keeping track of development notes and to-do lists. You may share your notes and bookmarks with others with ease because they are saved with your files. - -The following default trigger words/tags are configured by default: -``` -@todo - (blue) General ToDo remark. -@note - (blue) General remark. -@remind - (blue) General remark. -@follow-up - (blue) General remark. -@audit - (red) General bookmark for potential issues. -@audit-info - (blue) General bookmark for information to be noted for later use. -@audit-ok - (green) Add a note that a specific line is not an issue even though it might look like. -@audit-issue - (purple) Reference a code location an issue was filed for. -``` - -You can fully customize the colors! - -Remember these! They will be very handy in developing and especially in auditing projects. - -More details are available [here](https://github.com/tintinweb/vscode-inline-bookmarks). - -Next comes the fun part! Let's compile our contract using Foundry! - From 722d809ee8850fbc334530788c824b6eee3f1195 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:28 -0500 Subject: [PATCH 202/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/12-vscode-solidity-setup/+page.md. --- .../12-vscode-solidity-setup/+page.md | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/12-vscode-solidity-setup/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/12-vscode-solidity-setup/+page.md b/courses/foundry/1-foundry-simple-storage/12-vscode-solidity-setup/+page.md new file mode 100644 index 000000000..ae3566759 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/12-vscode-solidity-setup/+page.md @@ -0,0 +1,64 @@ +--- +title: VSCode Solidity setup +--- + +_Follow along with this video:_ + +--- + +### Improving Code Format in Visual Studio Code + +When you first start, your code might just look like a whole bunch of dull, lifeless, white text. + +This can be easily fixed by using one of the `Solidity` extensions. Out of all the Solidity extensions available in the Extensions tab (CTRL/CMD + SHIFT + X) the following are worth mentioning: + +1. [Solidity by Juan Blanco](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity), the most used Solidity extension out there. +2. [Solidity by Nomic Foundation](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity) is Patrick's favorite Solidity extension. The rest of the course will be displaying this extension. +3. [Solidity Visual Developer](https://marketplace.visualstudio.com/items?itemName=tintinweb.solidity-visual-auditor) is another popular choice. + +**NOTE**: If the code remains unhighlighted despite having installed the extension, there's a quick solution to that. Press `Command + Shift + P`, or `Control + Shift + P` on Windows. This opens up the command bar. In the command bar, type in "Settings" and select "Preferences: Open User Settings (JSON)". + +If you have nothing in there, create a new setting by typing in: + +``` +{ + "editor.defaultFormatter": "NomicFoundation.hardhat" +} +``` + +Use: + +`"editor.defaultFormatter": "tintinweb.solidity-visual-auditor"` for Solidity Visual Developer + +or + +`"editor.defaultFormatter": "JuanBlanco.solidity"` for Solidity by Juan Blanco + +### Other interesting extensions + +In the previous lesson, we mentioned a file called `foundry.toml`. This also has an extension that formats it to make it easier to read. Please install [Even Better TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml). + +Another indispensable extension is [Inline Bookmarks](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-inline-bookmarks). + +The Inline Bookmarks plugin facilitates bookmarking the actual code. The extension can be used for document review, auditing, log analysis, and keeping track of development notes and to-do lists. You may share your notes and bookmarks with others with ease because they are saved with your files. + +The following default trigger words/tags are configured by default: +``` +@todo - (blue) General ToDo remark. +@note - (blue) General remark. +@remind - (blue) General remark. +@follow-up - (blue) General remark. +@audit - (red) General bookmark for potential issues. +@audit-info - (blue) General bookmark for information to be noted for later use. +@audit-ok - (green) Add a note that a specific line is not an issue even though it might look like. +@audit-issue - (purple) Reference a code location an issue was filed for. +``` + +You can fully customize the colors! + +Remember these! They will be very handy in developing and especially in auditing projects. + +More details are available [here](https://github.com/tintinweb/vscode-inline-bookmarks). + +Next comes the fun part! Let's compile our contract using Foundry! + From 2df660830aedd5e84105c21ef93357b7cdcdd7f1 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:29 -0500 Subject: [PATCH 203/797] PatrickAlphaC removing file due to editing --- .../+page.md | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/11-compile-a-smart-contract-using-foundry/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/11-compile-a-smart-contract-using-foundry/+page.md b/courses/foundry/1-foundry-simple-storage/11-compile-a-smart-contract-using-foundry/+page.md deleted file mode 100644 index 6b820ad04..000000000 --- a/courses/foundry/1-foundry-simple-storage/11-compile-a-smart-contract-using-foundry/+page.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Compile a smart contract using Foundry ---- - -_Follow along with this video:_ - ---- - -### Compiling Smart Contracts: A Guide to the Foundry Console Compilation Process - -Open a new terminal. Type in `forge build` or `forge compile` to compile the smart contracts in your project. - -Once the compiling is finished, you'll see some new folders in the Explorer tab on the left side. One of them is a folder called `out`. Here you'll be able to find the [ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) of the smart contract together with the [Bytecode](https://www.geeksforgeeks.org/introduction-to-bytecode-and-opcode-in-solidity/) and a lot of useful information. - -The `cache` folder also appears. Generally, this folder is used to store temporary system files facilitating the compilation process. But for this course, you can safely ignore it. - -### More terminal wizardry - -Throughout your solidity development/audit journey you will type a lot of terminal commands, every time to make a change that you want tested you'll probably have to rerun the `forge build` then maybe you test it with `forge test` or run a script with `forge script` and many more. Typing all these over and over again is inefficient and time-consuming. The better way is to use the `up` and `down` arrow keys. Type the following commands: - -``` -echo "I like Foundry" -echo "I love Cyfrin" -echo "Auditing is great" -``` - -Now press the `up` and `down` arrow keys to cycle through the 3 commands. - -Ok, cool! We learned how to compile a contract, but how does one deploy a smart contract? \ No newline at end of file From b92b412870edf2eec5c06206cdd56bcaff5063a3 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:30 -0500 Subject: [PATCH 204/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/13-compile-a-smart-contract-using-foundry/+page.md. --- .../+page.md | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/13-compile-a-smart-contract-using-foundry/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/13-compile-a-smart-contract-using-foundry/+page.md b/courses/foundry/1-foundry-simple-storage/13-compile-a-smart-contract-using-foundry/+page.md new file mode 100644 index 000000000..6b820ad04 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/13-compile-a-smart-contract-using-foundry/+page.md @@ -0,0 +1,29 @@ +--- +title: Compile a smart contract using Foundry +--- + +_Follow along with this video:_ + +--- + +### Compiling Smart Contracts: A Guide to the Foundry Console Compilation Process + +Open a new terminal. Type in `forge build` or `forge compile` to compile the smart contracts in your project. + +Once the compiling is finished, you'll see some new folders in the Explorer tab on the left side. One of them is a folder called `out`. Here you'll be able to find the [ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) of the smart contract together with the [Bytecode](https://www.geeksforgeeks.org/introduction-to-bytecode-and-opcode-in-solidity/) and a lot of useful information. + +The `cache` folder also appears. Generally, this folder is used to store temporary system files facilitating the compilation process. But for this course, you can safely ignore it. + +### More terminal wizardry + +Throughout your solidity development/audit journey you will type a lot of terminal commands, every time to make a change that you want tested you'll probably have to rerun the `forge build` then maybe you test it with `forge test` or run a script with `forge script` and many more. Typing all these over and over again is inefficient and time-consuming. The better way is to use the `up` and `down` arrow keys. Type the following commands: + +``` +echo "I like Foundry" +echo "I love Cyfrin" +echo "Auditing is great" +``` + +Now press the `up` and `down` arrow keys to cycle through the 3 commands. + +Ok, cool! We learned how to compile a contract, but how does one deploy a smart contract? \ No newline at end of file From fcd5f1528e8944843c328e9658d0016c043ad117 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:31 -0500 Subject: [PATCH 205/797] PatrickAlphaC removing file due to editing --- .../+page.md | 93 ------------------- 1 file changed, 93 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/12-deploy-a-smart-contract-locally-using-ganache/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/12-deploy-a-smart-contract-locally-using-ganache/+page.md b/courses/foundry/1-foundry-simple-storage/12-deploy-a-smart-contract-locally-using-ganache/+page.md deleted file mode 100644 index bc9d5ae7c..000000000 --- a/courses/foundry/1-foundry-simple-storage/12-deploy-a-smart-contract-locally-using-ganache/+page.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: Deploy a smart contract locally using Ganache ---- - -_Follow along with this video:_ - - -### Deploying a smart contract - -There are multiple ways and multiple places where you could deploy a smart contract. - -While developing using the Foundry framework the easiest and most readily available place for deployment is Anvil. - -Anvil is a local testnet node shipped with Foundry. You can use it for testing your contracts from frontends or for interacting over RPC. - -To run Anvil you simply have to type `anvil` in the terminal. - -::image{src='/foundry-simply-storage/10-deploy-a-smart-contract-locally-using-ganache/Image1.PNG' style='width: 75%; height: auto;'} - -You now have access to 10 test addresses funded with 10_000 ETH each, with their associated private keys. - -This testnet node always listens on `127.0.0.1:8545` this will be our `RPC_URL` parameter when we deploy smart contracts here. More on this later! - -More info about Anvil is available [here](https://book.getfoundry.sh/reference/anvil/). - -Please press `Ctrl/CMD + C` to close Anvil. - -Anvil will be used throughout the course to deploy and test our smart contracts, but before that, let's quickly check an intermediary step. - -### Ganache - -_Ganache is a glaze, icing, sauce, or filling for pastries usually made by heating equal parts weight of cream and chopped chocolate, warming the cream first, then pouring it over the chocolate._ - -Wait, not that ganache! The other ganache: - -Ganache is a personal blockchain for rapid Ethereum and Filecoin distributed application development. You can use Ganache across the entire development cycle; enabling you to develop, deploy, and test your dApps in a safe and deterministic environment. - -Better! - -Please download Ganache from [here](https://archive.trufflesuite.com/ganache/). - -For people using Windows WSL please read [this](https://github.com/Cyfrin/foundry-simple-storage-f23?tab=readme-ov-file#windows-wsl--ganache). Using Ganache in this environment is not the easiest thing to do. We are not going to use this in the future, so don't worry if you can't configure it properly. - -Hit `Quickstart Ethereum`. Voila! A brand new blockchain. We get some addresses, that have balances and private keys. - -### Configuring MetaMask - -To deploy to a custom network (like your localhost), you'll need MetaMask. MetaMask is a popular cryptocurrency wallet and browser extension that allows users to interact with the Ethereum blockchain and its ecosystem. If you don't have it download it from [here](https://metamask.io/download/) - -Follow these steps: - -1. Open MetaMask. - -2. Click the three little dots and select 'Expand View'. - -3. Go to 'Settings', then 'Networks'. - -4. Here, you'll see the list of networks (Ethereum, Mainnet, etc.) with plenty of details about each one. Locate the RPC URL - this is key. - -The RPC URL is essentially the endpoint we make API calls to when sending transactions. For every blockchain transaction you execute, you're making an API to whatever is in here. -To send a transaction to your custom blockchain, you need to add it as a network: - -1. Click on 'Add a Network' - -2. Scroll to the bottom of the list of networks. - -3. Hit 'Add a Network manually'. - -4. Enter the details of your local network - - Network name: `Localhost` - - New RPC URL: Ganache`http://127.0.0.1:7545` or Anvil `http://127.0.0.1:8545` (make sure you always add `http://`) - these two could differ on your machine, please consult the Ganache UI or Anvil terminal for the exact RPC URL. - - Chain ID: Ganache `5777`(sometimes `1337`) or Anvil `31337` - these two could differ on your machine, please consult the Ganache UI or Anvil terminal for the exact Chain ID. - - Currency symbol: ETH - - Block explorer URL: - (we don't have a block explorer for our newly created blockchain, which will most likely disappear when we close the VS Code / Ganache app) - -Great! Now that we configured our local network, the next step is to add one of the accounts available in Ganche or Anvil into our MetaMask. [This is done as follows](https://support.metamask.io/hc/en-us/articles/360015489331-How-to-import-an-account#h_01G01W07NV7Q94M7P1EBD5BYM4): - -1. Click the account selector at the top of your wallet. - -2. Click `Add account or hardware wallet`. - -3. Click `Import account` - -4. You will be directed to the Import page. Paste your Ganache/Anvil private key. Click `Import`. - -**NOTE: Do not use this account for anything else, do not interact with it or send things to it on mainnet or any other real blockchain, use it locally, for testing purposes. Everyone has access to it.** - -Next up we shall talk more about adding a new network to MetaMask. From b96ac235b03d5dba0b02c822945743399d061f16 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:32 -0500 Subject: [PATCH 206/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-ganache/+page.md. --- .../+page.md | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-ganache/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-ganache/+page.md b/courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-ganache/+page.md new file mode 100644 index 000000000..bc9d5ae7c --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-ganache/+page.md @@ -0,0 +1,93 @@ +--- +title: Deploy a smart contract locally using Ganache +--- + +_Follow along with this video:_ + + +### Deploying a smart contract + +There are multiple ways and multiple places where you could deploy a smart contract. + +While developing using the Foundry framework the easiest and most readily available place for deployment is Anvil. + +Anvil is a local testnet node shipped with Foundry. You can use it for testing your contracts from frontends or for interacting over RPC. + +To run Anvil you simply have to type `anvil` in the terminal. + +::image{src='/foundry-simply-storage/10-deploy-a-smart-contract-locally-using-ganache/Image1.PNG' style='width: 75%; height: auto;'} + +You now have access to 10 test addresses funded with 10_000 ETH each, with their associated private keys. + +This testnet node always listens on `127.0.0.1:8545` this will be our `RPC_URL` parameter when we deploy smart contracts here. More on this later! + +More info about Anvil is available [here](https://book.getfoundry.sh/reference/anvil/). + +Please press `Ctrl/CMD + C` to close Anvil. + +Anvil will be used throughout the course to deploy and test our smart contracts, but before that, let's quickly check an intermediary step. + +### Ganache + +_Ganache is a glaze, icing, sauce, or filling for pastries usually made by heating equal parts weight of cream and chopped chocolate, warming the cream first, then pouring it over the chocolate._ + +Wait, not that ganache! The other ganache: + +Ganache is a personal blockchain for rapid Ethereum and Filecoin distributed application development. You can use Ganache across the entire development cycle; enabling you to develop, deploy, and test your dApps in a safe and deterministic environment. + +Better! + +Please download Ganache from [here](https://archive.trufflesuite.com/ganache/). + +For people using Windows WSL please read [this](https://github.com/Cyfrin/foundry-simple-storage-f23?tab=readme-ov-file#windows-wsl--ganache). Using Ganache in this environment is not the easiest thing to do. We are not going to use this in the future, so don't worry if you can't configure it properly. + +Hit `Quickstart Ethereum`. Voila! A brand new blockchain. We get some addresses, that have balances and private keys. + +### Configuring MetaMask + +To deploy to a custom network (like your localhost), you'll need MetaMask. MetaMask is a popular cryptocurrency wallet and browser extension that allows users to interact with the Ethereum blockchain and its ecosystem. If you don't have it download it from [here](https://metamask.io/download/) + +Follow these steps: + +1. Open MetaMask. + +2. Click the three little dots and select 'Expand View'. + +3. Go to 'Settings', then 'Networks'. + +4. Here, you'll see the list of networks (Ethereum, Mainnet, etc.) with plenty of details about each one. Locate the RPC URL - this is key. + +The RPC URL is essentially the endpoint we make API calls to when sending transactions. For every blockchain transaction you execute, you're making an API to whatever is in here. +To send a transaction to your custom blockchain, you need to add it as a network: + +1. Click on 'Add a Network' + +2. Scroll to the bottom of the list of networks. + +3. Hit 'Add a Network manually'. + +4. Enter the details of your local network + + Network name: `Localhost` + + New RPC URL: Ganache`http://127.0.0.1:7545` or Anvil `http://127.0.0.1:8545` (make sure you always add `http://`) - these two could differ on your machine, please consult the Ganache UI or Anvil terminal for the exact RPC URL. + + Chain ID: Ganache `5777`(sometimes `1337`) or Anvil `31337` - these two could differ on your machine, please consult the Ganache UI or Anvil terminal for the exact Chain ID. + + Currency symbol: ETH + + Block explorer URL: - (we don't have a block explorer for our newly created blockchain, which will most likely disappear when we close the VS Code / Ganache app) + +Great! Now that we configured our local network, the next step is to add one of the accounts available in Ganche or Anvil into our MetaMask. [This is done as follows](https://support.metamask.io/hc/en-us/articles/360015489331-How-to-import-an-account#h_01G01W07NV7Q94M7P1EBD5BYM4): + +1. Click the account selector at the top of your wallet. + +2. Click `Add account or hardware wallet`. + +3. Click `Import account` + +4. You will be directed to the Import page. Paste your Ganache/Anvil private key. Click `Import`. + +**NOTE: Do not use this account for anything else, do not interact with it or send things to it on mainnet or any other real blockchain, use it locally, for testing purposes. Everyone has access to it.** + +Next up we shall talk more about adding a new network to MetaMask. From 50b6a483228168e745766bce6c6f2568ed14fdf3 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:33 -0500 Subject: [PATCH 207/797] PatrickAlphaC removing file due to editing --- .../+page.md | 24 ------------------- 1 file changed, 24 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/13-how-to-add-a-new-network-to-metamask/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/13-how-to-add-a-new-network-to-metamask/+page.md b/courses/foundry/1-foundry-simple-storage/13-how-to-add-a-new-network-to-metamask/+page.md deleted file mode 100644 index 2e69eac1b..000000000 --- a/courses/foundry/1-foundry-simple-storage/13-how-to-add-a-new-network-to-metamask/+page.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: How to add a new network to Metamask ---- - -_Follow along with this video:_ - ---- - -### Adding New Networks Using MetaMask - -Conveniently, MetaMask provides an easy way to add EVM-compatible chains. By pre-configuring a host of them, you can add a chain such as the Arbitrum One by simply clicking on the `Networks` button on the top left, then `Add Network` and proceeding to `Add`. The pleasing part is that MetaMask does all the grunt work, filling in all the necessary information for you. A click on Approve Network ensures the successful addition of the network. - -Steps: - -1. Click on the Networks button on the top left -2. Click on Add Network -3. Choose your desired EVM-compatible chain -4. Click on Add -5. After ensuring all necessary information is already filled in, click on Approve Network - -But what can you do if the chain you want to add is not pre-configured? - -Simple! You employ the same process we just used to add our new Ganache local chain in the [previous lesson](https://updraft.cyfrin.io/courses/foundry/foundry-simple-storage/deploy-smart-contract-locally) - From 55f06b4dae21408abf27b183c8961fa9ca0bbeda Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:34 -0500 Subject: [PATCH 208/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/15-how-to-add-a-new-network-to-metamask/+page.md. --- .../+page.md | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/15-how-to-add-a-new-network-to-metamask/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/15-how-to-add-a-new-network-to-metamask/+page.md b/courses/foundry/1-foundry-simple-storage/15-how-to-add-a-new-network-to-metamask/+page.md new file mode 100644 index 000000000..2e69eac1b --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/15-how-to-add-a-new-network-to-metamask/+page.md @@ -0,0 +1,24 @@ +--- +title: How to add a new network to Metamask +--- + +_Follow along with this video:_ + +--- + +### Adding New Networks Using MetaMask + +Conveniently, MetaMask provides an easy way to add EVM-compatible chains. By pre-configuring a host of them, you can add a chain such as the Arbitrum One by simply clicking on the `Networks` button on the top left, then `Add Network` and proceeding to `Add`. The pleasing part is that MetaMask does all the grunt work, filling in all the necessary information for you. A click on Approve Network ensures the successful addition of the network. + +Steps: + +1. Click on the Networks button on the top left +2. Click on Add Network +3. Choose your desired EVM-compatible chain +4. Click on Add +5. After ensuring all necessary information is already filled in, click on Approve Network + +But what can you do if the chain you want to add is not pre-configured? + +Simple! You employ the same process we just used to add our new Ganache local chain in the [previous lesson](https://updraft.cyfrin.io/courses/foundry/foundry-simple-storage/deploy-smart-contract-locally) + From 863699741cd722a608bb363d9befc414129da5cb Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:35 -0500 Subject: [PATCH 209/797] PatrickAlphaC removing file due to editing --- .../+page.md | 88 ------------------- 1 file changed, 88 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-forge/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-forge/+page.md b/courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-forge/+page.md deleted file mode 100644 index ab3a762ce..000000000 --- a/courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-forge/+page.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Deploy a smart contract locally using Forge ---- - -_Follow along with this video:_ - ---- - -### Deploying to a local blockchain - -To find out more about forge's capabilities type - -``` -forge --help -``` - -Out of the resulting list, we are going to use the `create` command. - -Type `forge create --help` in the terminal or go [here](https://book.getfoundry.sh/reference/forge/forge-create) to find out more about the available configuration options. - -Try running `forge create SimpleStorage`. It should fail because we haven't specified a couple of required parameters: - -1. `Where do we deploy?` - -2. `Who's paying the gas fees/signing the transaction?` - -Let's tackle both these questions. - -As you've learned in the previous lessons, each blockchain (private or public) has an RPC URL (RPC SERVER) that acts as an endpoint. When we tried to deploy our smart contract, forge tried to use `http://localhost:8545/`, which doesn't host any blockchain. Thus, let's try to deploy our smart contract specifying the place where we want to deploy it. - -Please start Ganache and press `Quickstart Ethereum`. Copy the RPC Server `HTTP://127.0.0.1:7545`. Let's run our forge create again specifying the correct rpc url. - -``` -forge create SimpleStorage --rpc-url http://127.0.0.1:7545 -``` - -This again failed, indicating the following: - -``` -Error accessing local wallet. Did you set a private key, mnemonic or keystore? -``` - -Try the following command: - -``` -forge create SimpleStorage --rpc-url http://127.0.0.1:7545 --interactive -``` - -You will be asked to enter a private key, please paste one of the private keys available in Ganache. When you paste a key you won't see the text or any placeholder symbols, just press CTRL(CMD) + V and then ENTER. - -Voila! - -::image{src='/foundry-simply-storage/12-deploy-a-smart-contract-locally-using-forge/Image1.PNG' style='width: 75%; height: auto;'} - -You can go to Ganache and check the `Blocks` and `Transactions` tabs to see more info about what you just did. - -From now on, everything we deploy shall be done on Anvil. But if you like Ganache more, feel free to use that. - -Do the following: - -1. Run `clear` -2. Run `anvil` -3. Create a new terminal by pressing the `+` button -4. Copy one of the private keys from the anvil terminal -5. Run `forge create SimpleStorage --interactive` - We don't need to specify an `--rpc-url` this time because forge defaults to Anvil's RPC URL. -6. Go to the Anvil terminal and check the deployment details: - -``` - Transaction: 0x40d2ca8f0d680f098c7d5e3c127ef1ce1207ef439ba6e163c2042483e15998a6 - Contract created: 0x5fbdb2315678afecb367f032d93f642f64180aa3 - Gas used: 357076 - - Block Number: 1 - Block Hash: 0x85a56c0b8f166e86d1cce65412615e0d9a72972e04b2488023275131ea27330a - Block Time: "Mon, 15 Apr 2024 11:50:55 +0000" - -``` - -The more explicit way to deploy using `forge create` is as follows: - -``` -forge create SimpleStorage --rpc-url http://127.0.0.1:8545 --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -``` - -We included the `--rpc-url` to not count on the default and the `--private-key` to not use the `--interactive` option anymore. - -Pfew! That was a lot, but we learned a very important thing, how to deploy a smart contract on two local blockchains. But what comes next is one of the most important if not the **_MOST IMPORTANT_** aspects you will learn here: **_Private key safety_** From 3cba48e3092bde6d535100e99f230349a31080c0 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:35 -0500 Subject: [PATCH 210/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-forge/+page.md. --- .../+page.md | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-forge/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-forge/+page.md b/courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-forge/+page.md new file mode 100644 index 000000000..ab3a762ce --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-forge/+page.md @@ -0,0 +1,88 @@ +--- +title: Deploy a smart contract locally using Forge +--- + +_Follow along with this video:_ + +--- + +### Deploying to a local blockchain + +To find out more about forge's capabilities type + +``` +forge --help +``` + +Out of the resulting list, we are going to use the `create` command. + +Type `forge create --help` in the terminal or go [here](https://book.getfoundry.sh/reference/forge/forge-create) to find out more about the available configuration options. + +Try running `forge create SimpleStorage`. It should fail because we haven't specified a couple of required parameters: + +1. `Where do we deploy?` + +2. `Who's paying the gas fees/signing the transaction?` + +Let's tackle both these questions. + +As you've learned in the previous lessons, each blockchain (private or public) has an RPC URL (RPC SERVER) that acts as an endpoint. When we tried to deploy our smart contract, forge tried to use `http://localhost:8545/`, which doesn't host any blockchain. Thus, let's try to deploy our smart contract specifying the place where we want to deploy it. + +Please start Ganache and press `Quickstart Ethereum`. Copy the RPC Server `HTTP://127.0.0.1:7545`. Let's run our forge create again specifying the correct rpc url. + +``` +forge create SimpleStorage --rpc-url http://127.0.0.1:7545 +``` + +This again failed, indicating the following: + +``` +Error accessing local wallet. Did you set a private key, mnemonic or keystore? +``` + +Try the following command: + +``` +forge create SimpleStorage --rpc-url http://127.0.0.1:7545 --interactive +``` + +You will be asked to enter a private key, please paste one of the private keys available in Ganache. When you paste a key you won't see the text or any placeholder symbols, just press CTRL(CMD) + V and then ENTER. + +Voila! + +::image{src='/foundry-simply-storage/12-deploy-a-smart-contract-locally-using-forge/Image1.PNG' style='width: 75%; height: auto;'} + +You can go to Ganache and check the `Blocks` and `Transactions` tabs to see more info about what you just did. + +From now on, everything we deploy shall be done on Anvil. But if you like Ganache more, feel free to use that. + +Do the following: + +1. Run `clear` +2. Run `anvil` +3. Create a new terminal by pressing the `+` button +4. Copy one of the private keys from the anvil terminal +5. Run `forge create SimpleStorage --interactive` + We don't need to specify an `--rpc-url` this time because forge defaults to Anvil's RPC URL. +6. Go to the Anvil terminal and check the deployment details: + +``` + Transaction: 0x40d2ca8f0d680f098c7d5e3c127ef1ce1207ef439ba6e163c2042483e15998a6 + Contract created: 0x5fbdb2315678afecb367f032d93f642f64180aa3 + Gas used: 357076 + + Block Number: 1 + Block Hash: 0x85a56c0b8f166e86d1cce65412615e0d9a72972e04b2488023275131ea27330a + Block Time: "Mon, 15 Apr 2024 11:50:55 +0000" + +``` + +The more explicit way to deploy using `forge create` is as follows: + +``` +forge create SimpleStorage --rpc-url http://127.0.0.1:8545 --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +``` + +We included the `--rpc-url` to not count on the default and the `--private-key` to not use the `--interactive` option anymore. + +Pfew! That was a lot, but we learned a very important thing, how to deploy a smart contract on two local blockchains. But what comes next is one of the most important if not the **_MOST IMPORTANT_** aspects you will learn here: **_Private key safety_** From 2e0a0a525ba2344b311ac107a9072e66310076f5 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:36 -0500 Subject: [PATCH 211/797] PatrickAlphaC removing file due to editing --- .../+page.md | 43 ------------------- 1 file changed, 43 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/15-important-private-key-safety-pt-1/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/15-important-private-key-safety-pt-1/+page.md b/courses/foundry/1-foundry-simple-storage/15-important-private-key-safety-pt-1/+page.md deleted file mode 100644 index 45cf0530f..000000000 --- a/courses/foundry/1-foundry-simple-storage/15-important-private-key-safety-pt-1/+page.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Important - private key safety pt.1 ---- - -_Follow along with this video:_ - ---- - -### Practicing Private Key Safety - -Having a private key in plain text is extremely bad. The private key(s) we used in the last lesson are well-known keys for local testing, you shouldn't use those on mainnet and keeping them in plain text is ok, but any other private key should be kept hidden, especially your production key or key's associated with accounts that hold crypto. - -Moreover, it's very bad to have private keys in bash history (hit the up arrow and see the key you used to deploy). - -You can delete your history by typing: - -``` -history -c -``` - -We will teach you more about how to secure private keys in one of the next lessons. - -### Your Safety Promise - -It's time now to articulate your promise for maintaining private key safety. Create a file titled `Promise.md`. In this file, make it a point to write down your promise: - -``` -I promise to never use my private key associated with real money in plain text. -``` - -If you feel comfortable doing so, consider tweeting this to affirm and secure your pledge. Make sure to tag [@PatrickAlphaC](https://twitter.com/PatrickAlphaC) and [@CyfrinUpdraft](https://twitter.com/CyfrinUpdraft) or any other professional in this field to hold yourself accountable. - -Hacking private keys is one of the most important reasons people and projects lose absurd amounts. You don't even need to look that deep to find titles like this: - -[The Ronin hack](https://www.halborn.com/blog/post/explained-the-ronin-hack-march-2022) - Social engineering of private keys - -[Early Crypto Investor Bo Shen Says He Lost $42 Million in Wallet Hack](https://www.bnnbloomberg.ca/early-crypto-investor-bo-shen-says-he-lost-42-million-in-wallet-hack-1.1850446) - -[The \$477 million FTX hack](https://www.elliptic.co/blog/the-477-million-ftx-hack-following-the-blockchain-trail) where `The new CEO of FTX revealed that private keys allowing access to the firm’s crypto assets were stored in unencrypted form, and a former employee disclosed that over $150 million was stolen from Alameda Research, due to poor security. ` - -Don't be like that! Maybe you are not holding millions, but what you hold is yours, don't let it become theirs! - -In the following lessons, we'll learn how to access RPC URLs for free using Alchemy for any blockchain. We will also delve into exploring safer methodologies for dealing with private keys. Stay tuned! From f6a61da24993aac5c78f961810b5d78dd98ec599 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:37 -0500 Subject: [PATCH 212/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/17-important-private-key-safety-pt-1/+page.md. --- .../+page.md | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/17-important-private-key-safety-pt-1/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/17-important-private-key-safety-pt-1/+page.md b/courses/foundry/1-foundry-simple-storage/17-important-private-key-safety-pt-1/+page.md new file mode 100644 index 000000000..45cf0530f --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/17-important-private-key-safety-pt-1/+page.md @@ -0,0 +1,43 @@ +--- +title: Important - private key safety pt.1 +--- + +_Follow along with this video:_ + +--- + +### Practicing Private Key Safety + +Having a private key in plain text is extremely bad. The private key(s) we used in the last lesson are well-known keys for local testing, you shouldn't use those on mainnet and keeping them in plain text is ok, but any other private key should be kept hidden, especially your production key or key's associated with accounts that hold crypto. + +Moreover, it's very bad to have private keys in bash history (hit the up arrow and see the key you used to deploy). + +You can delete your history by typing: + +``` +history -c +``` + +We will teach you more about how to secure private keys in one of the next lessons. + +### Your Safety Promise + +It's time now to articulate your promise for maintaining private key safety. Create a file titled `Promise.md`. In this file, make it a point to write down your promise: + +``` +I promise to never use my private key associated with real money in plain text. +``` + +If you feel comfortable doing so, consider tweeting this to affirm and secure your pledge. Make sure to tag [@PatrickAlphaC](https://twitter.com/PatrickAlphaC) and [@CyfrinUpdraft](https://twitter.com/CyfrinUpdraft) or any other professional in this field to hold yourself accountable. + +Hacking private keys is one of the most important reasons people and projects lose absurd amounts. You don't even need to look that deep to find titles like this: + +[The Ronin hack](https://www.halborn.com/blog/post/explained-the-ronin-hack-march-2022) - Social engineering of private keys + +[Early Crypto Investor Bo Shen Says He Lost $42 Million in Wallet Hack](https://www.bnnbloomberg.ca/early-crypto-investor-bo-shen-says-he-lost-42-million-in-wallet-hack-1.1850446) + +[The \$477 million FTX hack](https://www.elliptic.co/blog/the-477-million-ftx-hack-following-the-blockchain-trail) where `The new CEO of FTX revealed that private keys allowing access to the firm’s crypto assets were stored in unencrypted form, and a former employee disclosed that over $150 million was stolen from Alameda Research, due to poor security. ` + +Don't be like that! Maybe you are not holding millions, but what you hold is yours, don't let it become theirs! + +In the following lessons, we'll learn how to access RPC URLs for free using Alchemy for any blockchain. We will also delve into exploring safer methodologies for dealing with private keys. Stay tuned! From a8676c9357f4a819943f648a2a959fa82ef92fb7 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:38 -0500 Subject: [PATCH 213/797] PatrickAlphaC removing file due to editing --- .../+page.md | 187 ------------------ 1 file changed, 187 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-anvil/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-anvil/+page.md b/courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-anvil/+page.md deleted file mode 100644 index f3106f2ce..000000000 --- a/courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-anvil/+page.md +++ /dev/null @@ -1,187 +0,0 @@ ---- -title: Deploy a smart contract locally using Anvil ---- - -_Follow along with this video:_ - ---- - -### Deploy a smart contract locally using Anvil via scripts - -Deploying a smart contract via scripting is particularly handy because it provides a consistent and repeatable way to deploy reliably and its features enhance the testing of both the deployment processes and the code itself. - -There's a strong chance that you like the command-line approach, but scripting enriches the whole deployment process, bringing in more functionality and an ease of use second to none. - -Foundry eases the whole process since it is written in Solidity. This means our deployment scripts will also be written in Solidity. It is essential to distinguish Solidity as a contract language from Solidity as a scripting language. Foundry also incorporates elements that enhance our Solidity experience beyond the smart contracts realm. So, let's get started on creating a script to deploy our simple storage contract. - -In Foundry we keep our scripts in the `script` folder. - -Please create a new file called `DeploySimpleStorage.s.sol`. - -Using `.s.sol` as a suffix is a naming convention for Foundry scripts, in future lessons, when we'll write Foundry tests, these will bear the suffix of `.t.sol`. - -For more best practice info regarding Foundry scripts please click [here](https://book.getfoundry.sh/tutorials/best-practices#scripts). - -Open the newly created file. Here we'll write a solidity script for deploying our SimpleStorage contract. - -Type the following: - -```solidity -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.19; - -contract DeploySimpleStorage { - -} -``` - -The first two lines are pretty self-explanatory. - -We declare the new contract, named `DeploySimpleStorage` - -For it to be considered a Foundry script and to be able to access the extended functionality Foundry is bringing to the table we need to import `Script` from `"forge-std/Script.sol"` and make `DeploySimpleStorage` inherit `Script`. - -**NOTE**: `forge-std` also called Forge Standard Library is a collection of pre-written Solidity contracts designed to simplify and enhance scripting and testing within the Foundry development framework. - -Furthermore, to be able to deploy `SimpleStorage` we also need to import it by typing `import {SimpleStorage} from "../src/SimpleStorage.sol";` - -```solidity -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.19; - -import {Script} from "forge-std/Script.sol"; -import {SimpleStorage} from "../src/SimpleStorage.sol"; - -contract DeploySimpleStorage is Script { - -} -``` - -Every script needs a main function, which, according to the best practice linked above is called `run`. Whenever you run `forge script` this is the function that gets called. - -```solidity -// SPDX-License-Identifier: MIT - -pragma solidity 0.8.19; - -import {Script} from "forge-std/Script.sol"; -import {SimpleStorage} from "../src/SimpleStorage.sol"; - -contract DeploySimpleStorage is Script { - function run() external returns (SimpleStorage) { - vm.startBroadcast(); - - SimpleStorage simpleStorage = new SimpleStorage(); - - vm.stopBroadcast(); - return simpleStorage; - } -} -``` -`run` is an external function that will return the `SimpleStorage` contract. - -In the Run function, we are going to use a distinctive keyword: `vm`. Foundry has a distinctive feature known as cheat codes. The `vm` keyword is a cheat code in Foundry, and thereby only works in Foundry. - -`vm.startBroadcast` indicates the starting point for the list of transactions that get to be sent to the `RPC URL`; - -Similarly, `vm.stopBroadcast` indicates the ending point of the list of transactions that get to be sent to the `RPC URL`; - -Between those two we write: - -`SimpleStorage simpleStorage = new SimpleStorage();` - -The `new` keyword is used to create a new smart contract in Solidity. - -We end the function with `return simpleStorage;`. - -Please select the `Anvil` terminal and press `CTRL(CMD) + C` to stop it. Now run the following command: - -```bash -forge script script/DeploySimpleStorage.s.sol -``` - -This should go through without any errors, but if you hit some errors related to `incompatible solidity versions in various files` please ensure that both the `SimpleStorage.sol` and `DeploySimpleStorage.s.sol` use `pragma solidity 0.8.19;` - -If you want to further extend your knowledge about scripting please go [here](https://book.getfoundry.sh/tutorials/solidity-scripting?highlight=scr#solidity-scripting) - -You should get the following output: - -```text -[⠆] Compiling... -[⠔] Compiling 2 files with 0.8.19 -[⠒] Solc 0.8.19 finished in 1.08s -Compiler run successful! -Script ran successfully. -Gas used: 338569 - -== Return == -0: contract SimpleStorage 0x90193C961A926261B756D1E5bb255e67ff9498A1 - -If you wish to simulate on-chain transactions pass a RPC URL. -``` - -**The million-dollar question**: If we didn't pass an RPC URL, where did this deploy to? - -If the RPC URL is not specified, Foundry automatically launches an Anvil instance, runs your script (in our case deployed the contract) and then terminates the Anvil instance. - -Run the `anvil` command in the terminal, open up a new terminal and type the following: - -```bash -forge script script/DeploySimpleStorage.s.sol --rpc-url http://127.0.0.1:8545 -``` - -To get the following output: - -```text -No files changed, compilation skipped -EIP-3855 is not supported in one or more of the RPCs used. -Unsupported Chain IDs: 31337. -Contracts deployed with a Solidity version equal or higher than 0.8.20 might not work properly. -For more information, please see https://eips.ethereum.org/EIPS/eip-3855 -Script ran successfully. - -== Return == -0: contract SimpleStorage 0x34A1D3fff3958843C43aD80F30b94c510645C316 - -## Setting up 1 EVM. - -========================== - -Chain 31337 - -Estimated gas price: 2 gwei - -Estimated total gas used for script: 464097 - -Estimated amount required: 0.000928194 ETH - -========================== - -SIMULATION COMPLETE. To broadcast these transactions, add --broadcast and wallet configuration(s) to the previous command. See forge script --help for more. -``` - -**Another million-dollar question**: Is it deployed now? - -Answer: No, the output indicates this was a simulation. But, we got a new folder out of this, the `broadcast` folder contains information about different script runs in case we forget details. - -Hit the up arrow key and add `--broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80` at the end. - -Our contract is now successfully deployed! Fantastic! - -Switch to the `anvil` terminal where you'll see: - -```text - Transaction: 0x73eb9fb4ef7b159e03c50d669c42e2ec4eeaa9358bea0a710cb07168e5192570 - Contract created: 0x5fbdb2315678afecb367f032d93f642f64180aa3 - Gas used: 357088 - - Block Number: 1 - Block Hash: 0x8ea564f146e04bb36fc27f0b491223a023b5882d2fcfce3ff85e0dd152e611e4 - Block Time: "Tue, 16 Apr 2024 13:39:51 +0000" -``` - -Awesome! - -Through this lesson we kept talking about a thing called `transaction`, but what is a `transaction`? Tune in the next lesson to find out. From aae2991dbeaabd09b8fb7c8e3472464ec3f7cd8d Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:38 -0500 Subject: [PATCH 214/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/18-deploy-a-smart-contract-locally-using-anvil/+page.md. --- .../+page.md | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/18-deploy-a-smart-contract-locally-using-anvil/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/18-deploy-a-smart-contract-locally-using-anvil/+page.md b/courses/foundry/1-foundry-simple-storage/18-deploy-a-smart-contract-locally-using-anvil/+page.md new file mode 100644 index 000000000..f3106f2ce --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/18-deploy-a-smart-contract-locally-using-anvil/+page.md @@ -0,0 +1,187 @@ +--- +title: Deploy a smart contract locally using Anvil +--- + +_Follow along with this video:_ + +--- + +### Deploy a smart contract locally using Anvil via scripts + +Deploying a smart contract via scripting is particularly handy because it provides a consistent and repeatable way to deploy reliably and its features enhance the testing of both the deployment processes and the code itself. + +There's a strong chance that you like the command-line approach, but scripting enriches the whole deployment process, bringing in more functionality and an ease of use second to none. + +Foundry eases the whole process since it is written in Solidity. This means our deployment scripts will also be written in Solidity. It is essential to distinguish Solidity as a contract language from Solidity as a scripting language. Foundry also incorporates elements that enhance our Solidity experience beyond the smart contracts realm. So, let's get started on creating a script to deploy our simple storage contract. + +In Foundry we keep our scripts in the `script` folder. + +Please create a new file called `DeploySimpleStorage.s.sol`. + +Using `.s.sol` as a suffix is a naming convention for Foundry scripts, in future lessons, when we'll write Foundry tests, these will bear the suffix of `.t.sol`. + +For more best practice info regarding Foundry scripts please click [here](https://book.getfoundry.sh/tutorials/best-practices#scripts). + +Open the newly created file. Here we'll write a solidity script for deploying our SimpleStorage contract. + +Type the following: + +```solidity +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +contract DeploySimpleStorage { + +} +``` + +The first two lines are pretty self-explanatory. + +We declare the new contract, named `DeploySimpleStorage` + +For it to be considered a Foundry script and to be able to access the extended functionality Foundry is bringing to the table we need to import `Script` from `"forge-std/Script.sol"` and make `DeploySimpleStorage` inherit `Script`. + +**NOTE**: `forge-std` also called Forge Standard Library is a collection of pre-written Solidity contracts designed to simplify and enhance scripting and testing within the Foundry development framework. + +Furthermore, to be able to deploy `SimpleStorage` we also need to import it by typing `import {SimpleStorage} from "../src/SimpleStorage.sol";` + +```solidity +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import {Script} from "forge-std/Script.sol"; +import {SimpleStorage} from "../src/SimpleStorage.sol"; + +contract DeploySimpleStorage is Script { + +} +``` + +Every script needs a main function, which, according to the best practice linked above is called `run`. Whenever you run `forge script` this is the function that gets called. + +```solidity +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import {Script} from "forge-std/Script.sol"; +import {SimpleStorage} from "../src/SimpleStorage.sol"; + +contract DeploySimpleStorage is Script { + function run() external returns (SimpleStorage) { + vm.startBroadcast(); + + SimpleStorage simpleStorage = new SimpleStorage(); + + vm.stopBroadcast(); + return simpleStorage; + } +} +``` +`run` is an external function that will return the `SimpleStorage` contract. + +In the Run function, we are going to use a distinctive keyword: `vm`. Foundry has a distinctive feature known as cheat codes. The `vm` keyword is a cheat code in Foundry, and thereby only works in Foundry. + +`vm.startBroadcast` indicates the starting point for the list of transactions that get to be sent to the `RPC URL`; + +Similarly, `vm.stopBroadcast` indicates the ending point of the list of transactions that get to be sent to the `RPC URL`; + +Between those two we write: + +`SimpleStorage simpleStorage = new SimpleStorage();` + +The `new` keyword is used to create a new smart contract in Solidity. + +We end the function with `return simpleStorage;`. + +Please select the `Anvil` terminal and press `CTRL(CMD) + C` to stop it. Now run the following command: + +```bash +forge script script/DeploySimpleStorage.s.sol +``` + +This should go through without any errors, but if you hit some errors related to `incompatible solidity versions in various files` please ensure that both the `SimpleStorage.sol` and `DeploySimpleStorage.s.sol` use `pragma solidity 0.8.19;` + +If you want to further extend your knowledge about scripting please go [here](https://book.getfoundry.sh/tutorials/solidity-scripting?highlight=scr#solidity-scripting) + +You should get the following output: + +```text +[⠆] Compiling... +[⠔] Compiling 2 files with 0.8.19 +[⠒] Solc 0.8.19 finished in 1.08s +Compiler run successful! +Script ran successfully. +Gas used: 338569 + +== Return == +0: contract SimpleStorage 0x90193C961A926261B756D1E5bb255e67ff9498A1 + +If you wish to simulate on-chain transactions pass a RPC URL. +``` + +**The million-dollar question**: If we didn't pass an RPC URL, where did this deploy to? + +If the RPC URL is not specified, Foundry automatically launches an Anvil instance, runs your script (in our case deployed the contract) and then terminates the Anvil instance. + +Run the `anvil` command in the terminal, open up a new terminal and type the following: + +```bash +forge script script/DeploySimpleStorage.s.sol --rpc-url http://127.0.0.1:8545 +``` + +To get the following output: + +```text +No files changed, compilation skipped +EIP-3855 is not supported in one or more of the RPCs used. +Unsupported Chain IDs: 31337. +Contracts deployed with a Solidity version equal or higher than 0.8.20 might not work properly. +For more information, please see https://eips.ethereum.org/EIPS/eip-3855 +Script ran successfully. + +== Return == +0: contract SimpleStorage 0x34A1D3fff3958843C43aD80F30b94c510645C316 + +## Setting up 1 EVM. + +========================== + +Chain 31337 + +Estimated gas price: 2 gwei + +Estimated total gas used for script: 464097 + +Estimated amount required: 0.000928194 ETH + +========================== + +SIMULATION COMPLETE. To broadcast these transactions, add --broadcast and wallet configuration(s) to the previous command. See forge script --help for more. +``` + +**Another million-dollar question**: Is it deployed now? + +Answer: No, the output indicates this was a simulation. But, we got a new folder out of this, the `broadcast` folder contains information about different script runs in case we forget details. + +Hit the up arrow key and add `--broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80` at the end. + +Our contract is now successfully deployed! Fantastic! + +Switch to the `anvil` terminal where you'll see: + +```text + Transaction: 0x73eb9fb4ef7b159e03c50d669c42e2ec4eeaa9358bea0a710cb07168e5192570 + Contract created: 0x5fbdb2315678afecb367f032d93f642f64180aa3 + Gas used: 357088 + + Block Number: 1 + Block Hash: 0x8ea564f146e04bb36fc27f0b491223a023b5882d2fcfce3ff85e0dd152e611e4 + Block Time: "Tue, 16 Apr 2024 13:39:51 +0000" +``` + +Awesome! + +Through this lesson we kept talking about a thing called `transaction`, but what is a `transaction`? Tune in the next lesson to find out. From dd0ab34c96c1ca84834b184ceba30dbcb65807b8 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:39 -0500 Subject: [PATCH 215/797] PatrickAlphaC removing file due to editing --- .../17-what-is-a-transaction/+page.md | 56 ------------------- 1 file changed, 56 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/17-what-is-a-transaction/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/17-what-is-a-transaction/+page.md b/courses/foundry/1-foundry-simple-storage/17-what-is-a-transaction/+page.md deleted file mode 100644 index 2ae821403..000000000 --- a/courses/foundry/1-foundry-simple-storage/17-what-is-a-transaction/+page.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: What is a transaction ---- - -_Follow along with this video:_ - ---- - -### More about blockchain transactions - -In the previous lesson we kept talking about transactions, but we never explained what a transaction is. In simple terms, a transaction captures details of an activity that has taken place on a blockchain. - -On the left side of your screen, in the Explorer tab, you'll find a folder called `broadcast`. Foundry saves all your blockchain interactions here. The `dry-run` folder is used for interactions you made when you didn't have a blockchain running (remember that time when we deployed our contract without specifying an `--rpc-url`). Moreover, the recordings here are separated by `chainId`. - -**Note**: The `chainId` is a unique identifier assigned to a specific blockchain network. It is used to distinguish one blockchain from another and is a crucial parameter for ensuring the security and integrity of transactions and interactions on the blockchain. - -Click on `run-latest.json`. -Here we can find more details about the last deployment script we ran in our previous lesson. It will show things like `transactionType`, `contractName` and `contractAddress`. Moreover, in the `transaction` section, you can see what we actually sent over to the RPC URL: - -```javaScript - "transaction": { - "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", - "to": null, - "gas": "0x714e1", - "value": "0x0", - "input": "0x608060...c63430008130033", - "nonce": "0x0", - "chainId": "0x7a69", - "accessList": null, - "type": null - } -``` - -Let's go through each of these: - -- `from` is self-explanatory, it's the address we used to sign the transaction; -- `to` is the recipient, in our case is null or address(0), this is the standard destination for when new smart contracts are deployed; -- `gas` is the amount of gas spent. You will see the hex value `0x714e1` (or any other value represented in hex format); - -**Quick tip**: Normal humans can't understand hex values like the one indicated above, but there's a quick way to convert these into usual numbers. Run the following command in your terminal: `cast --to-base 0x714e1 dec`. `cast` is a very versatile tool provided by Foundry, type `cast --help` in your terminal to find out more, or go [here](https://book.getfoundry.sh/reference/cast/cast). - -- `value` is the transaction value, or the amount of ETH we are sending over. Given that this transaction was made to deploy a contract, the value here is `0x0` or `0`, but we could have specified a value and that would have been the initial balance of the newly deployed contract; - -- `data` in this case is the contract deployment code and the contract code. In the excerpt above this was truncated; - -- `nonce` is a unique identifier assigned to each transaction sent from a specific account. The nonce is used to ensure that each transaction is processed only once and to prevent replay attacks. `nonce` is incremented with every single transaction; - -- `accessList` is a feature of Ethereum to optimize the gas cost of transactions. It contains a list of addresses and associated storage keys that the transaction is likely to access, allowing the EVM to more efficiently compute the gas cost of storage access during the transaction's execution; - -- `type` please ignore this for now. - -There are other values that play an important part that weren't presented in that list, namely the `v`, `r`, and `s`. These are components of a transaction's signature, which are used to validate the authenticity and integrity of the transaction. - -Whenever we send a transaction over the blockchain there's a signature happening, that's where we use our `private key`. - -**Important:** Every time you change the state of the blockchain you do it using a transaction. The thing that indicates the change is the `data` field of a transaction. Deployment bytecode, contract bytecode and OPCODEs will be tackled in a future lesson. From ef79aed36013e1aef170bd40346b961d487107b8 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:40 -0500 Subject: [PATCH 216/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/19-what-is-a-transaction/+page.md. --- .../19-what-is-a-transaction/+page.md | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/19-what-is-a-transaction/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/19-what-is-a-transaction/+page.md b/courses/foundry/1-foundry-simple-storage/19-what-is-a-transaction/+page.md new file mode 100644 index 000000000..2ae821403 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/19-what-is-a-transaction/+page.md @@ -0,0 +1,56 @@ +--- +title: What is a transaction +--- + +_Follow along with this video:_ + +--- + +### More about blockchain transactions + +In the previous lesson we kept talking about transactions, but we never explained what a transaction is. In simple terms, a transaction captures details of an activity that has taken place on a blockchain. + +On the left side of your screen, in the Explorer tab, you'll find a folder called `broadcast`. Foundry saves all your blockchain interactions here. The `dry-run` folder is used for interactions you made when you didn't have a blockchain running (remember that time when we deployed our contract without specifying an `--rpc-url`). Moreover, the recordings here are separated by `chainId`. + +**Note**: The `chainId` is a unique identifier assigned to a specific blockchain network. It is used to distinguish one blockchain from another and is a crucial parameter for ensuring the security and integrity of transactions and interactions on the blockchain. + +Click on `run-latest.json`. +Here we can find more details about the last deployment script we ran in our previous lesson. It will show things like `transactionType`, `contractName` and `contractAddress`. Moreover, in the `transaction` section, you can see what we actually sent over to the RPC URL: + +```javaScript + "transaction": { + "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "to": null, + "gas": "0x714e1", + "value": "0x0", + "input": "0x608060...c63430008130033", + "nonce": "0x0", + "chainId": "0x7a69", + "accessList": null, + "type": null + } +``` + +Let's go through each of these: + +- `from` is self-explanatory, it's the address we used to sign the transaction; +- `to` is the recipient, in our case is null or address(0), this is the standard destination for when new smart contracts are deployed; +- `gas` is the amount of gas spent. You will see the hex value `0x714e1` (or any other value represented in hex format); + +**Quick tip**: Normal humans can't understand hex values like the one indicated above, but there's a quick way to convert these into usual numbers. Run the following command in your terminal: `cast --to-base 0x714e1 dec`. `cast` is a very versatile tool provided by Foundry, type `cast --help` in your terminal to find out more, or go [here](https://book.getfoundry.sh/reference/cast/cast). + +- `value` is the transaction value, or the amount of ETH we are sending over. Given that this transaction was made to deploy a contract, the value here is `0x0` or `0`, but we could have specified a value and that would have been the initial balance of the newly deployed contract; + +- `data` in this case is the contract deployment code and the contract code. In the excerpt above this was truncated; + +- `nonce` is a unique identifier assigned to each transaction sent from a specific account. The nonce is used to ensure that each transaction is processed only once and to prevent replay attacks. `nonce` is incremented with every single transaction; + +- `accessList` is a feature of Ethereum to optimize the gas cost of transactions. It contains a list of addresses and associated storage keys that the transaction is likely to access, allowing the EVM to more efficiently compute the gas cost of storage access during the transaction's execution; + +- `type` please ignore this for now. + +There are other values that play an important part that weren't presented in that list, namely the `v`, `r`, and `s`. These are components of a transaction's signature, which are used to validate the authenticity and integrity of the transaction. + +Whenever we send a transaction over the blockchain there's a signature happening, that's where we use our `private key`. + +**Important:** Every time you change the state of the blockchain you do it using a transaction. The thing that indicates the change is the `data` field of a transaction. Deployment bytecode, contract bytecode and OPCODEs will be tackled in a future lesson. From 3717eec61e4ce3f184183e6c7af15aab2c4e6b00 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:41 -0500 Subject: [PATCH 217/797] PatrickAlphaC removing file due to editing --- .../+page.md | 53 ------------------- 1 file changed, 53 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/18-important-private-key-safety-pt-2/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/18-important-private-key-safety-pt-2/+page.md b/courses/foundry/1-foundry-simple-storage/18-important-private-key-safety-pt-2/+page.md deleted file mode 100644 index 251c30c62..000000000 --- a/courses/foundry/1-foundry-simple-storage/18-important-private-key-safety-pt-2/+page.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Important - private key safety pt.2 ---- - -_Follow along with this video:_ - ---- - -### How to not have your private key in the command line - -Some lessons ago we deployed `SimpleStorage` using the following command: - -``` -forge script script/DeploySimpleStorage.s.sol --rpc-url http://127.0.0.1:8545 --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -``` - -Having our private key in plain text is very bad, as we've explained in [Lesson 13](https://updraft.cyfrin.io/courses/foundry/foundry-simple-storage/private-key-safety). What can we do to avoid this, except using the `--interactive` parameter, because we don't want to keep copy-pasting our private key? - -**BIG BOLDED DISCLAIMER: What we are about to do is fine for development purposes, do not put a real key here, it very terrible for production purposes.** - -Create a new file in the root of your project called `.env`. Then, go the `.gitignore` file and make sure `.env` is in there. - -The `.env` file will host environment variables. Variables that are of a sensitive nature that we don't want to expose in public. - -Open the file and put the following in it: - -``` -PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -RPC_URL=http://127.0.0.1:8545 -``` - -Next run `source .env`. This adds the above-mentioned environment variables into our shell. Now run `echo $PRIVATE_KEY` or `echo $RPC_URL` to check if the values are stored in the shell. - -Now we can safely replace the parameters in our `forge script` command: - -``` -forge script script/DeploySimpleStorage.s.sol --rpc-url $RPC_URL --broadcast --private-key $PRIVATE_KEY -``` - -This doesn't only hide your private key from plain sight in the command line but also facilitates faster terminal usage, imagine you'd have to copy-paste the `http://127.0.0.1:8545` RPC URL over and over again. It's cleaner this way. - -But yes, now we have the private key in plain text in the `.env` file, that's not good. - -### How to handle this problem with production code? - -Foundry has a very nice option called `keystore`. To read more about it type `forge script --help` in your terminal. Using `forge script --keystore ` allows you to specify a path to an encrypted store file, encrypted by a password. Thus your private key would never be available in plain text. - -Let's agree to the following: - -1. For testing purposes use a `$PRIVATE_KEY` in an `.env` file as long as you don't expose that `.env` file anywhere. -2. Where real money is involved use the `--interactive` option or a [keystore file protected by a password](https://github.com/Cyfrin/foundry-full-course-f23?tab=readme-ov-file#can-you-encrypt-a-private-key---a-keystore-in-foundry-yet). - -There's one more thing about storing keys in a `.env` file. Please take a look at the ["THE .ENV PLEDGE"](https://github.com/Cyfrin/foundry-full-course-f23/discussions/5). Read it, understand it and comment `I WILL BE SAFE`. Tweet it, Tiktok it, blog about it, make an Insta story about it, print it and put it on your fridge and share some copies with your neighbors. Please stay safe! From 225b9fa96dab7148fdf3abcd14d77ce25305871b Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:42 -0500 Subject: [PATCH 218/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/20-important-private-key-safety-pt-2/+page.md. --- .../+page.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/20-important-private-key-safety-pt-2/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/20-important-private-key-safety-pt-2/+page.md b/courses/foundry/1-foundry-simple-storage/20-important-private-key-safety-pt-2/+page.md new file mode 100644 index 000000000..251c30c62 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/20-important-private-key-safety-pt-2/+page.md @@ -0,0 +1,53 @@ +--- +title: Important - private key safety pt.2 +--- + +_Follow along with this video:_ + +--- + +### How to not have your private key in the command line + +Some lessons ago we deployed `SimpleStorage` using the following command: + +``` +forge script script/DeploySimpleStorage.s.sol --rpc-url http://127.0.0.1:8545 --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +``` + +Having our private key in plain text is very bad, as we've explained in [Lesson 13](https://updraft.cyfrin.io/courses/foundry/foundry-simple-storage/private-key-safety). What can we do to avoid this, except using the `--interactive` parameter, because we don't want to keep copy-pasting our private key? + +**BIG BOLDED DISCLAIMER: What we are about to do is fine for development purposes, do not put a real key here, it very terrible for production purposes.** + +Create a new file in the root of your project called `.env`. Then, go the `.gitignore` file and make sure `.env` is in there. + +The `.env` file will host environment variables. Variables that are of a sensitive nature that we don't want to expose in public. + +Open the file and put the following in it: + +``` +PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +RPC_URL=http://127.0.0.1:8545 +``` + +Next run `source .env`. This adds the above-mentioned environment variables into our shell. Now run `echo $PRIVATE_KEY` or `echo $RPC_URL` to check if the values are stored in the shell. + +Now we can safely replace the parameters in our `forge script` command: + +``` +forge script script/DeploySimpleStorage.s.sol --rpc-url $RPC_URL --broadcast --private-key $PRIVATE_KEY +``` + +This doesn't only hide your private key from plain sight in the command line but also facilitates faster terminal usage, imagine you'd have to copy-paste the `http://127.0.0.1:8545` RPC URL over and over again. It's cleaner this way. + +But yes, now we have the private key in plain text in the `.env` file, that's not good. + +### How to handle this problem with production code? + +Foundry has a very nice option called `keystore`. To read more about it type `forge script --help` in your terminal. Using `forge script --keystore ` allows you to specify a path to an encrypted store file, encrypted by a password. Thus your private key would never be available in plain text. + +Let's agree to the following: + +1. For testing purposes use a `$PRIVATE_KEY` in an `.env` file as long as you don't expose that `.env` file anywhere. +2. Where real money is involved use the `--interactive` option or a [keystore file protected by a password](https://github.com/Cyfrin/foundry-full-course-f23?tab=readme-ov-file#can-you-encrypt-a-private-key---a-keystore-in-foundry-yet). + +There's one more thing about storing keys in a `.env` file. Please take a look at the ["THE .ENV PLEDGE"](https://github.com/Cyfrin/foundry-full-course-f23/discussions/5). Read it, understand it and comment `I WILL BE SAFE`. Tweet it, Tiktok it, blog about it, make an Insta story about it, print it and put it on your fridge and share some copies with your neighbors. Please stay safe! From fb528e7a8932c8c9cd3bbbf809b2feac722811ba Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:43 -0500 Subject: [PATCH 219/797] PatrickAlphaC removing file due to editing --- .../19-never-use-a-env-file/+page.md | 44 ------------------- 1 file changed, 44 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/19-never-use-a-env-file/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/19-never-use-a-env-file/+page.md b/courses/foundry/1-foundry-simple-storage/19-never-use-a-env-file/+page.md deleted file mode 100644 index 266369548..000000000 --- a/courses/foundry/1-foundry-simple-storage/19-never-use-a-env-file/+page.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Never Use A Env File ---- - -_Follow along with this video:_ - ---- - -### Meanwhile, some things have changed - -In our previous lesson, we showed you how to configure and use a `.env` file to hold your private key and rpc url, some developments have taken place since that lesson was made so ... You should never use a `.env` again. - -### Encrypting your Keys Using ERC2335 - -For now, let's pretend our private key is this: - -`0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80` (key 0 from Anvil) - -Type the following command in your terminal: -``` -cast wallet import nameOfAccountGoesHere --interactive -``` - -Ideally, you don't do this in your VS Code. - -You will be asked for your private key and a password to secure it. You will do this only once, which is amazing! - -If you remember, last lesson we deployed running the following command: -``` -forge script script/DeploySimpleStorage.s.sol --rpc-url $RPC_URL --broadcast --private-key $PRIVATE_KEY -``` - -Now that we configured our wallet we can deploy as following: - -``` -forge script script/DeploySimpleStorage.s.sol --rpc-url http://127.0.0.1:8545 --broadcast --account nameOfAccountGoesHere --sender 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 -``` -You will be asked for your password. You won't be able to deploy without your password. - -To see all the configured wallets you can call the following: `cast wallet list`. - -Clear your history so your private key won't randomly remain there using the following command: `history -c`. - -***Stay safe! Stay froggy! Don't lose your keys. If you are seeing your private key in plain text, you are doing something wrong.*** From 581abf1dd32e03845e1e6b0a0e9a453195c5243a Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:43 -0500 Subject: [PATCH 220/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/21-never-use-a-env-file/+page.md. --- .../21-never-use-a-env-file/+page.md | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/21-never-use-a-env-file/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/21-never-use-a-env-file/+page.md b/courses/foundry/1-foundry-simple-storage/21-never-use-a-env-file/+page.md new file mode 100644 index 000000000..266369548 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/21-never-use-a-env-file/+page.md @@ -0,0 +1,44 @@ +--- +title: Never Use A Env File +--- + +_Follow along with this video:_ + +--- + +### Meanwhile, some things have changed + +In our previous lesson, we showed you how to configure and use a `.env` file to hold your private key and rpc url, some developments have taken place since that lesson was made so ... You should never use a `.env` again. + +### Encrypting your Keys Using ERC2335 + +For now, let's pretend our private key is this: + +`0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80` (key 0 from Anvil) + +Type the following command in your terminal: +``` +cast wallet import nameOfAccountGoesHere --interactive +``` + +Ideally, you don't do this in your VS Code. + +You will be asked for your private key and a password to secure it. You will do this only once, which is amazing! + +If you remember, last lesson we deployed running the following command: +``` +forge script script/DeploySimpleStorage.s.sol --rpc-url $RPC_URL --broadcast --private-key $PRIVATE_KEY +``` + +Now that we configured our wallet we can deploy as following: + +``` +forge script script/DeploySimpleStorage.s.sol --rpc-url http://127.0.0.1:8545 --broadcast --account nameOfAccountGoesHere --sender 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 +``` +You will be asked for your password. You won't be able to deploy without your password. + +To see all the configured wallets you can call the following: `cast wallet list`. + +Clear your history so your private key won't randomly remain there using the following command: `history -c`. + +***Stay safe! Stay froggy! Don't lose your keys. If you are seeing your private key in plain text, you are doing something wrong.*** From 152d9ef6d350e45a5574d7a3040d205c9af90970 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:44 -0500 Subject: [PATCH 221/797] PatrickAlphaC removing file due to editing --- .../+page.md | 64 ------------------- 1 file changed, 64 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/20-interact-with-a-smart-contract-using-the-cli/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/20-interact-with-a-smart-contract-using-the-cli/+page.md b/courses/foundry/1-foundry-simple-storage/20-interact-with-a-smart-contract-using-the-cli/+page.md deleted file mode 100644 index 308709c7c..000000000 --- a/courses/foundry/1-foundry-simple-storage/20-interact-with-a-smart-contract-using-the-cli/+page.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Interact with a smart contract using the CLI ---- - -_Follow along with this video:_ - ---- - -### Interacting With Contract Addresses via Command Line & Foundry's Cast Tool - -This lesson builds on top of previous lessons where we deployed `SimpleStorage` via `forge script`. We have `Anvil` running and the smart contract is deployed. - -Copy the contract address. - -### Sending information to the blockchain - -Foundry has a built-in tool known as `Cast`. `Cast` comes loaded with numerous commands to interact with. Learn more about them by typing `cast --help`. One such useful command is `send` which is designed to sign and publish a transaction. To view help about `send`, type `cast send --help`. - -To use `send` we need a signature and some arguments. - -Please call the following in your terminal: - -**Note**: Down below use the address you copy-pasted from your terminal, there's a chance it will be different than the one mine was deployed. - -``` -cast send 0x5FbDB2315678afecb367f032d93F642f64180aa3 "store(uint256)" 1337 --rpc-url $RPC_URL --private-key $PRIVATE_KEY -``` - -**What did we just do?** - -Let's break it down: -- `cast send` is the command we used to sign and publish our transaction; -- `0x5FbDB2315678afecb367f032d93F642f64180aa3` or any other address is the target of our `cast send`, the contract we are interacting with; -- `"store(uint256)"` is the [signature of the function](https://ethereum.stackexchange.com/questions/135205/what-is-a-function-signature-and-function-selector-in-solidity-and-evm-language) we are calling. -- `1337` is the number we pass to the `store` function. As we can see in the function signature, we are expected to provide an `uint256` input. You can obviously provide any number you want, as long as it fits `uint256`. -- you already know what `--rpc-url $RPC_URL --private-key $PRIVATE_KEY` are. The place where we send and the private key we use to sign. - -### Reading information from the blockchain - -`cast` conveniently provides a way to read information stored on the blockchain. Type `cast call --help` in your terminal to find out more. It works similarly to `send`, where you have to provide a signature and some arguments. The difference is you are only peering into the storage, not modifying it. - -Call the following command in your terminal: - -``` -cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "retrieve()" -``` - -We receive back the following: -``` -0x0000000000000000000000000000000000000000000000000000000000000539 -``` -This represents a hex value. In the previous lessons, we learned how to convert this to a normal number. - -Type the following command in your terminal: -``` -cast --to-base 0x0000000000000000000000000000000000000000000000000000000000000539 dec -``` -And surprise, surprise, `1337` came back. - -I recommend you play around and send multiple transactions with different numbers and then read them from the blockchain. - -Awesome! We've learned something very valuable. You are going to use this more times than you can count. - -**Up next:** Deploying a smart contract on Sepolia From e67f12013fc897d9c347552bf064493b9ef8a834 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:45 -0500 Subject: [PATCH 222/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/22-interact-with-a-smart-contract-using-the-cli/+page.md. --- .../+page.md | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/22-interact-with-a-smart-contract-using-the-cli/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/22-interact-with-a-smart-contract-using-the-cli/+page.md b/courses/foundry/1-foundry-simple-storage/22-interact-with-a-smart-contract-using-the-cli/+page.md new file mode 100644 index 000000000..308709c7c --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/22-interact-with-a-smart-contract-using-the-cli/+page.md @@ -0,0 +1,64 @@ +--- +title: Interact with a smart contract using the CLI +--- + +_Follow along with this video:_ + +--- + +### Interacting With Contract Addresses via Command Line & Foundry's Cast Tool + +This lesson builds on top of previous lessons where we deployed `SimpleStorage` via `forge script`. We have `Anvil` running and the smart contract is deployed. + +Copy the contract address. + +### Sending information to the blockchain + +Foundry has a built-in tool known as `Cast`. `Cast` comes loaded with numerous commands to interact with. Learn more about them by typing `cast --help`. One such useful command is `send` which is designed to sign and publish a transaction. To view help about `send`, type `cast send --help`. + +To use `send` we need a signature and some arguments. + +Please call the following in your terminal: + +**Note**: Down below use the address you copy-pasted from your terminal, there's a chance it will be different than the one mine was deployed. + +``` +cast send 0x5FbDB2315678afecb367f032d93F642f64180aa3 "store(uint256)" 1337 --rpc-url $RPC_URL --private-key $PRIVATE_KEY +``` + +**What did we just do?** + +Let's break it down: +- `cast send` is the command we used to sign and publish our transaction; +- `0x5FbDB2315678afecb367f032d93F642f64180aa3` or any other address is the target of our `cast send`, the contract we are interacting with; +- `"store(uint256)"` is the [signature of the function](https://ethereum.stackexchange.com/questions/135205/what-is-a-function-signature-and-function-selector-in-solidity-and-evm-language) we are calling. +- `1337` is the number we pass to the `store` function. As we can see in the function signature, we are expected to provide an `uint256` input. You can obviously provide any number you want, as long as it fits `uint256`. +- you already know what `--rpc-url $RPC_URL --private-key $PRIVATE_KEY` are. The place where we send and the private key we use to sign. + +### Reading information from the blockchain + +`cast` conveniently provides a way to read information stored on the blockchain. Type `cast call --help` in your terminal to find out more. It works similarly to `send`, where you have to provide a signature and some arguments. The difference is you are only peering into the storage, not modifying it. + +Call the following command in your terminal: + +``` +cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "retrieve()" +``` + +We receive back the following: +``` +0x0000000000000000000000000000000000000000000000000000000000000539 +``` +This represents a hex value. In the previous lessons, we learned how to convert this to a normal number. + +Type the following command in your terminal: +``` +cast --to-base 0x0000000000000000000000000000000000000000000000000000000000000539 dec +``` +And surprise, surprise, `1337` came back. + +I recommend you play around and send multiple transactions with different numbers and then read them from the blockchain. + +Awesome! We've learned something very valuable. You are going to use this more times than you can count. + +**Up next:** Deploying a smart contract on Sepolia From 87be5f31f74e4dc7b9ca942d68736ec434a14674 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:46 -0500 Subject: [PATCH 223/797] PatrickAlphaC removing file due to editing --- .../21-deploying-to-a-testnet/+page.md | 56 ------------------- 1 file changed, 56 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/21-deploying-to-a-testnet/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/21-deploying-to-a-testnet/+page.md b/courses/foundry/1-foundry-simple-storage/21-deploying-to-a-testnet/+page.md deleted file mode 100644 index ef4e1332d..000000000 --- a/courses/foundry/1-foundry-simple-storage/21-deploying-to-a-testnet/+page.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Deploying to a Testnet ---- - -_Follow along the course with this video._ - - - ---- - -## Deploying our Contract to Testnet or Live Network with Foundry and Alchemy - -Hi, everyone! Are you curious about what your contract would look like on a testnet or a live network? If so, buckle up because this blog post will cover exactly that! We'll walk through the process of updating our Environment Variable (.env) file for an actual testnet. - -Clearly, we need an actual testnet for a real network. But our trusty MetaMask has built-in Infura connections that are incompatible. Why? Because they're tailored specifically for MetaMask. Hence, we need our own Remote Procedure Call (RPC) URL. - -## Creating our Own RPC URL for a Testnet - -_To create one, we could run our own blockchain node, but let's be honest — many folks prefer avoiding that route. Instead, we utilize Node as a Service (NaaS) applications to expedite the process._ - -One promising option is using Alchemy - a free NaaS platform that we can send the transactions to. This procedure resides within the _Deploying to Testnet or Mainnnet_ section in the full course repo of the Foundry. - -::image{src='/foundry/19-testnet-deploy/testnet1.png' style='width: 100%; height: auto;'} - -To access the Alchemy platform, we simply click on the aforementioned function. On the platform, we sign up (I used Google sign-in for this demo). - -Our next step is creating a new app in the Alchemy user interface. I named mine _Sepolia Testing_ and kept the description the same, given that our chain will be an Ethereum one based on Ethiopia. - -We can bypass advanced features for now and finalize our app. Now we have the app details needed for our node, including frequency of calls and other details. We also have a new https endpoint by clicking view key, which functions exactly the same way as our ganache or MetaMask endpoint. - -## Altering our Private Key - -Next, let's do something about our private keys. Our ganache private key will no longer cut it — it has neither real money nor any testnet ETH in it. - -Our solution is to use one of our MetaMask private keys. To do this, we switch back to Sepolia in our MetaMask, choose an account with money in it, click on account details, and export the private key. _Remember, never share your real private key!_ - -Upon confirmation with your password, copy the private key and omit the line in the env file — hashtag or pound sign denoting comments. - -## Executing the Transaction - -With our Sepolia RPC URL and private key from MetaMask, executing a transaction now becomes tremendously easier. - -```bash -source .env -forge script script/deploySimpleStorage.s.sol --rpc-url=$Sepolia_RPC_URL --private-key=$PRIVATE_KEY --broadcast -``` - -This command deploys our contract to the testnet, and we can monitor the transaction on our Alchemy dashboard. - -We soon find that our contract, Simple Storage, has been deployed on the Sepolia chain. We can grab our transaction hash and input it into Sepolia etherscan IO to confirm the successful transaction. - -After we refresh our Alchemy dashboard, we'll verify the requests sent and track the ETH send raw transaction that transmitted our transaction to the blockchain. - -So, this is how we deploy our contract on a real testnet leveraging Foundry and Alchemy! - -Our next step will explore adding real-world components to the mix. Stay tuned! From c769e3cc86254c9c57ad3d86178fc330850600ae Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:46 -0500 Subject: [PATCH 224/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/23-deploying-to-a-testnet/+page.md. --- .../23-deploying-to-a-testnet/+page.md | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/23-deploying-to-a-testnet/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/23-deploying-to-a-testnet/+page.md b/courses/foundry/1-foundry-simple-storage/23-deploying-to-a-testnet/+page.md new file mode 100644 index 000000000..ef4e1332d --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/23-deploying-to-a-testnet/+page.md @@ -0,0 +1,56 @@ +--- +title: Deploying to a Testnet +--- + +_Follow along the course with this video._ + + + +--- + +## Deploying our Contract to Testnet or Live Network with Foundry and Alchemy + +Hi, everyone! Are you curious about what your contract would look like on a testnet or a live network? If so, buckle up because this blog post will cover exactly that! We'll walk through the process of updating our Environment Variable (.env) file for an actual testnet. + +Clearly, we need an actual testnet for a real network. But our trusty MetaMask has built-in Infura connections that are incompatible. Why? Because they're tailored specifically for MetaMask. Hence, we need our own Remote Procedure Call (RPC) URL. + +## Creating our Own RPC URL for a Testnet + +_To create one, we could run our own blockchain node, but let's be honest — many folks prefer avoiding that route. Instead, we utilize Node as a Service (NaaS) applications to expedite the process._ + +One promising option is using Alchemy - a free NaaS platform that we can send the transactions to. This procedure resides within the _Deploying to Testnet or Mainnnet_ section in the full course repo of the Foundry. + +::image{src='/foundry/19-testnet-deploy/testnet1.png' style='width: 100%; height: auto;'} + +To access the Alchemy platform, we simply click on the aforementioned function. On the platform, we sign up (I used Google sign-in for this demo). + +Our next step is creating a new app in the Alchemy user interface. I named mine _Sepolia Testing_ and kept the description the same, given that our chain will be an Ethereum one based on Ethiopia. + +We can bypass advanced features for now and finalize our app. Now we have the app details needed for our node, including frequency of calls and other details. We also have a new https endpoint by clicking view key, which functions exactly the same way as our ganache or MetaMask endpoint. + +## Altering our Private Key + +Next, let's do something about our private keys. Our ganache private key will no longer cut it — it has neither real money nor any testnet ETH in it. + +Our solution is to use one of our MetaMask private keys. To do this, we switch back to Sepolia in our MetaMask, choose an account with money in it, click on account details, and export the private key. _Remember, never share your real private key!_ + +Upon confirmation with your password, copy the private key and omit the line in the env file — hashtag or pound sign denoting comments. + +## Executing the Transaction + +With our Sepolia RPC URL and private key from MetaMask, executing a transaction now becomes tremendously easier. + +```bash +source .env +forge script script/deploySimpleStorage.s.sol --rpc-url=$Sepolia_RPC_URL --private-key=$PRIVATE_KEY --broadcast +``` + +This command deploys our contract to the testnet, and we can monitor the transaction on our Alchemy dashboard. + +We soon find that our contract, Simple Storage, has been deployed on the Sepolia chain. We can grab our transaction hash and input it into Sepolia etherscan IO to confirm the successful transaction. + +After we refresh our Alchemy dashboard, we'll verify the requests sent and track the ETH send raw transaction that transmitted our transaction to the blockchain. + +So, this is how we deploy our contract on a real testnet leveraging Foundry and Alchemy! + +Our next step will explore adding real-world components to the mix. Stay tuned! From 8e38cf16e6a5d3c43ca1eb4dab557527deab8ca5 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:47 -0500 Subject: [PATCH 225/797] PatrickAlphaC removing file due to editing --- .../+page.md | 43 ------------------- 1 file changed, 43 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/22-verify-a-smart-contract-on-etherscan/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/22-verify-a-smart-contract-on-etherscan/+page.md b/courses/foundry/1-foundry-simple-storage/22-verify-a-smart-contract-on-etherscan/+page.md deleted file mode 100644 index bd2ca42c5..000000000 --- a/courses/foundry/1-foundry-simple-storage/22-verify-a-smart-contract-on-etherscan/+page.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Verify a smart contract on Etherscan ---- - -_Follow along with this video:_ - ---- - -### Manually verify a smart contract on Etherscan - -Soooo ... we just deployed our smart contract on Sepolia, let's check it out! - -We go [here](https://sepolia.etherscan.io/address/0x1093560Fe9029c4fB9044AbF2fC94288970D98Db#code) click on `Contract` and find this: - -::image{src='/foundry-simply-storage/21-verify-a-smart-contract-on-etherscan/Image1.PNG' style='width: 75%; height: auto;'} - -This bytecode looks horrendous. We need to do something to improve the readability (which currently is non-existent). - -Etherscan is prompting us to do something about it via the message: `Are you the contract creator? Verify and Publish your contract source code today!` - -So, let's click on `Verify and Publish`. - -The address of the Contract comes prepopulated, if not please paste it from your terminal. - -Select `Solidity(Single file)` because we are using solidity and we have only one file. - -Select your Compiler Version. My contract used solidity 0.8.19. - -The license type we used is MIT. - -On the next page, paste your Solidity Contract. Select `Yes` in `Optimization`, and leave everything else as is. - -Finish up the `verify` process. If you get this message: - -``` -Successfully generated Bytecode and ABI for Contract Address [0x1093560Fe9029c4fB9044AbF2fC94288970D98Db] -``` - -you did it right! - -Now you have access to the `Read Contract` and `Write Contract`. This lets you interact directly with your contract through etherscan. - -Congratz! You just learned how to verify a smart contract on etherscan, the manual way. This is not the ideal way, in the future, we will teach you how to verify them programmatically. From effbcaa6aa448b09dd94c8865147c4f0ba283323 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:48 -0500 Subject: [PATCH 226/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/24-verify-a-smart-contract-on-etherscan/+page.md. --- .../+page.md | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/24-verify-a-smart-contract-on-etherscan/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/24-verify-a-smart-contract-on-etherscan/+page.md b/courses/foundry/1-foundry-simple-storage/24-verify-a-smart-contract-on-etherscan/+page.md new file mode 100644 index 000000000..bd2ca42c5 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/24-verify-a-smart-contract-on-etherscan/+page.md @@ -0,0 +1,43 @@ +--- +title: Verify a smart contract on Etherscan +--- + +_Follow along with this video:_ + +--- + +### Manually verify a smart contract on Etherscan + +Soooo ... we just deployed our smart contract on Sepolia, let's check it out! + +We go [here](https://sepolia.etherscan.io/address/0x1093560Fe9029c4fB9044AbF2fC94288970D98Db#code) click on `Contract` and find this: + +::image{src='/foundry-simply-storage/21-verify-a-smart-contract-on-etherscan/Image1.PNG' style='width: 75%; height: auto;'} + +This bytecode looks horrendous. We need to do something to improve the readability (which currently is non-existent). + +Etherscan is prompting us to do something about it via the message: `Are you the contract creator? Verify and Publish your contract source code today!` + +So, let's click on `Verify and Publish`. + +The address of the Contract comes prepopulated, if not please paste it from your terminal. + +Select `Solidity(Single file)` because we are using solidity and we have only one file. + +Select your Compiler Version. My contract used solidity 0.8.19. + +The license type we used is MIT. + +On the next page, paste your Solidity Contract. Select `Yes` in `Optimization`, and leave everything else as is. + +Finish up the `verify` process. If you get this message: + +``` +Successfully generated Bytecode and ABI for Contract Address [0x1093560Fe9029c4fB9044AbF2fC94288970D98Db] +``` + +you did it right! + +Now you have access to the `Read Contract` and `Write Contract`. This lets you interact directly with your contract through etherscan. + +Congratz! You just learned how to verify a smart contract on etherscan, the manual way. This is not the ideal way, in the future, we will teach you how to verify them programmatically. From a8f43fd6624ee6399aa0907fd8dfbc22a923ed0c Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:49 -0500 Subject: [PATCH 227/797] PatrickAlphaC removing file due to editing --- .../23-cleaning-up-the-project/+page.md | 62 ------------------- 1 file changed, 62 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/23-cleaning-up-the-project/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/23-cleaning-up-the-project/+page.md b/courses/foundry/1-foundry-simple-storage/23-cleaning-up-the-project/+page.md deleted file mode 100644 index 7a00e1b6a..000000000 --- a/courses/foundry/1-foundry-simple-storage/23-cleaning-up-the-project/+page.md +++ /dev/null @@ -1,62 +0,0 @@ -## Cleaning Up the Project - -We've covered a lot of ground in this project. We learned how to write our first Solidity contract, how to deploy it to a test network, and how to interact with it using Forge. Before we move on to more complex projects, let's take a moment to clean things up and make sure our project is well-organized. - -### Formatting - -One important aspect of any project is consistency in formatting. We've been using VS Code's auto-formatter to help us with this, but it's important to make sure that anyone else working on the project is following the same formatting rules. - -Forge has a built-in format command that we can use to ensure consistent formatting across the project. We can run this command in our terminal with: - -```bash -forge fmt -``` - -This command will automatically format all our Solidity files according to Forge's default style. - -### README.md - -Another important file to include in any project is a `README.md` file. This file serves as a guide for anyone who wants to learn about your project, how to use it, or how to contribute to it. - -The `README.md` file is written in Markdown, which is a lightweight markup language that's easy to read and write. - -Here's an example of what you might include in your `README.md` file: - -````markdown -# SimpleStorage - -This is a simple Solidity contract that stores a single uint256 value. - -## Getting Started - -1. Clone this repository. -2. Install Forge using the instructions found at [https://github.com/foundry-rs/foundry](https://github.com/foundry-rs/foundry). -3. Run the following command to compile the contract: - -```bash -forge build -``` - -4. Run the following command to deploy the contract to a test network: - -```bash -forge create -``` - -5. Interact with the contract using Forge's interactive console. - -```bash -forge console -``` - -## Contributing - -We welcome contributions to this project. If you're interested in contributing, please open an issue or submit a pull request. -``` -We can preview our `README.md` file in VS Code by going to the `View` menu and selecting `Open Preview to the Side`. This will open a new window showing what the `README.md` file will look like when it's rendered on GitHub. - -### Using AI for Markdown Formatting - -If you find that formatting Markdown is a bit tedious, you can use an AI tool like ChatGPT to help you out. Just copy and paste the text you want to format into ChatGPT and ask it to format it in Markdown. It will do a pretty good job of converting your plain text into Markdown, and you can then review and edit it as needed. - -```` From 27ad98caf88261052c3399a09508c959f848258a Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:50 -0500 Subject: [PATCH 228/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/25-cleaning-up-the-project/+page.md. --- .../25-cleaning-up-the-project/+page.md | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/25-cleaning-up-the-project/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/25-cleaning-up-the-project/+page.md b/courses/foundry/1-foundry-simple-storage/25-cleaning-up-the-project/+page.md new file mode 100644 index 000000000..7a00e1b6a --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/25-cleaning-up-the-project/+page.md @@ -0,0 +1,62 @@ +## Cleaning Up the Project + +We've covered a lot of ground in this project. We learned how to write our first Solidity contract, how to deploy it to a test network, and how to interact with it using Forge. Before we move on to more complex projects, let's take a moment to clean things up and make sure our project is well-organized. + +### Formatting + +One important aspect of any project is consistency in formatting. We've been using VS Code's auto-formatter to help us with this, but it's important to make sure that anyone else working on the project is following the same formatting rules. + +Forge has a built-in format command that we can use to ensure consistent formatting across the project. We can run this command in our terminal with: + +```bash +forge fmt +``` + +This command will automatically format all our Solidity files according to Forge's default style. + +### README.md + +Another important file to include in any project is a `README.md` file. This file serves as a guide for anyone who wants to learn about your project, how to use it, or how to contribute to it. + +The `README.md` file is written in Markdown, which is a lightweight markup language that's easy to read and write. + +Here's an example of what you might include in your `README.md` file: + +````markdown +# SimpleStorage + +This is a simple Solidity contract that stores a single uint256 value. + +## Getting Started + +1. Clone this repository. +2. Install Forge using the instructions found at [https://github.com/foundry-rs/foundry](https://github.com/foundry-rs/foundry). +3. Run the following command to compile the contract: + +```bash +forge build +``` + +4. Run the following command to deploy the contract to a test network: + +```bash +forge create +``` + +5. Interact with the contract using Forge's interactive console. + +```bash +forge console +``` + +## Contributing + +We welcome contributions to this project. If you're interested in contributing, please open an issue or submit a pull request. +``` +We can preview our `README.md` file in VS Code by going to the `View` menu and selecting `Open Preview to the Side`. This will open a new window showing what the `README.md` file will look like when it's rendered on GitHub. + +### Using AI for Markdown Formatting + +If you find that formatting Markdown is a bit tedious, you can use an AI tool like ChatGPT to help you out. Just copy and paste the text you want to format into ChatGPT and ask it to format it in Markdown. It will do a pretty good job of converting your plain text into Markdown, and you can then review and edit it as needed. + +```` From ad12f33dff803919956275559157d508497726cb Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:51 -0500 Subject: [PATCH 229/797] PatrickAlphaC removing file due to editing --- .../24-foundry-zksync/+page.md | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/24-foundry-zksync/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/24-foundry-zksync/+page.md b/courses/foundry/1-foundry-simple-storage/24-foundry-zksync/+page.md deleted file mode 100644 index accf8bb0f..000000000 --- a/courses/foundry/1-foundry-simple-storage/24-foundry-zksync/+page.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Foundry ZKsync ---- - -_Follow along with the video_ - ---- - -In this lesson, we'll explore Layer 2 deployment on ZKsync, which involves a different compilation method compared to Ethereum. This difference arises because ZKsync uses unique opcodes. While Solidity code behaves similarly on both platforms, the low-level outputs generated by Foundry in the `/out` folder will not be entirely compatible with the ZKsync VM. - -### Foundry ZKsync - -To get started with ZKsync, we will follow these three steps: - -1. 🛠️ Install `foundry-zksync` -2. 🧑‍💻 Compile the Solidity contract with the `--zksync` flag -3. 🔄🏠 Reinstall the original Vanilla Foundry - -> 👀❗**IMPORTANT**:br -> Installing `foundry-zksync` will override any existing Foundry binaries, such as `forge` and `cast`. - -The GitHub resources for this course contain a link to the [Foundry ZKsync repository](https://github.com/Cyfrin/foundry-full-course-cu?tab=readme-ov-file#compiling-to-zksync-in-foundry-zksync). `foundry-zksync` is a fork of Foundry tailored for the ZKsync environment. The [repository](https://github.com/matter-labs/foundry-zksync) includes quick install instructions to help you set up the tool. - -- First, clone the Foundry ZKsync repository in a different directory from your Foundry project. Use the `git clone` command to clone the repository locally on your computer. - -- Once cloned, navigate to the created Foundry ZKsync directory and run the installation command: - - ``` - ./install-foundry-zksync - ``` - - This command requires a Unix-like environment, such as WSL on Windows, or a Mac or Linux system. After running the command, verify the installation by checking the version with `forge --version`. A different version number will indicate the successful installation of Foundry ZKsync. - -- To keep your environment flexible, you can switch to Foundry ZKsync by running `foundryup-zksync`. After using it, it's recommended to switch back to Vanilla Foundry by running the `foundryup` command. This removes ZKsync-specific flags and settings, allowing you to easily toggle between Foundry ZKsync and Vanilla Foundry as needed. From 0925483a2ec56f58096ff3d8549fc6177192f84e Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:51 -0500 Subject: [PATCH 230/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/26-foundry-zksync/+page.md. --- .../26-foundry-zksync/+page.md | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/26-foundry-zksync/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/26-foundry-zksync/+page.md b/courses/foundry/1-foundry-simple-storage/26-foundry-zksync/+page.md new file mode 100644 index 000000000..accf8bb0f --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/26-foundry-zksync/+page.md @@ -0,0 +1,34 @@ +--- +title: Foundry ZKsync +--- + +_Follow along with the video_ + +--- + +In this lesson, we'll explore Layer 2 deployment on ZKsync, which involves a different compilation method compared to Ethereum. This difference arises because ZKsync uses unique opcodes. While Solidity code behaves similarly on both platforms, the low-level outputs generated by Foundry in the `/out` folder will not be entirely compatible with the ZKsync VM. + +### Foundry ZKsync + +To get started with ZKsync, we will follow these three steps: + +1. 🛠️ Install `foundry-zksync` +2. 🧑‍💻 Compile the Solidity contract with the `--zksync` flag +3. 🔄🏠 Reinstall the original Vanilla Foundry + +> 👀❗**IMPORTANT**:br +> Installing `foundry-zksync` will override any existing Foundry binaries, such as `forge` and `cast`. + +The GitHub resources for this course contain a link to the [Foundry ZKsync repository](https://github.com/Cyfrin/foundry-full-course-cu?tab=readme-ov-file#compiling-to-zksync-in-foundry-zksync). `foundry-zksync` is a fork of Foundry tailored for the ZKsync environment. The [repository](https://github.com/matter-labs/foundry-zksync) includes quick install instructions to help you set up the tool. + +- First, clone the Foundry ZKsync repository in a different directory from your Foundry project. Use the `git clone` command to clone the repository locally on your computer. + +- Once cloned, navigate to the created Foundry ZKsync directory and run the installation command: + + ``` + ./install-foundry-zksync + ``` + + This command requires a Unix-like environment, such as WSL on Windows, or a Mac or Linux system. After running the command, verify the installation by checking the version with `forge --version`. A different version number will indicate the successful installation of Foundry ZKsync. + +- To keep your environment flexible, you can switch to Foundry ZKsync by running `foundryup-zksync`. After using it, it's recommended to switch back to Vanilla Foundry by running the `foundryup` command. This removes ZKsync-specific flags and settings, allowing you to easily toggle between Foundry ZKsync and Vanilla Foundry as needed. From f63f6eab1b1df093c0fb0de89ce4638f33dd942c Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:52 -0500 Subject: [PATCH 231/797] PatrickAlphaC removing file due to editing --- .../25-compiling-foundry-zksync/+page.md | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/25-compiling-foundry-zksync/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/25-compiling-foundry-zksync/+page.md b/courses/foundry/1-foundry-simple-storage/25-compiling-foundry-zksync/+page.md deleted file mode 100644 index 9d06c5c60..000000000 --- a/courses/foundry/1-foundry-simple-storage/25-compiling-foundry-zksync/+page.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Compiling foundry ZKsync ---- - -_Follow along with the video_ - ---- - -> Previously, when we ran the `forge build` command, it generated an `/out` folder in the root project directory. This folder contains all the compilation details related the Ethereum Virtual Machine (EVM) and Vanilla Foundry. To compile for the ZKsync chain instead, we use the command `forge build --zksync`. This command creates a new folder in our project root called `/zkout`, and contains all the compiled code compatible to the ZKsync Era VM. - -If we need to revert to vanilla Foundry for deployment on the EVM, we simply run the command `foundryup` and then use `forge build`, which builds a standard Foundry project. Unless otherwise specified, we should continue using this method. From ca9d5c52f5b5a82d7cc11baa1f82dde40c61b9b0 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:53 -0500 Subject: [PATCH 232/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/27-compiling-foundry-zksync/+page.md. --- .../27-compiling-foundry-zksync/+page.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/27-compiling-foundry-zksync/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/27-compiling-foundry-zksync/+page.md b/courses/foundry/1-foundry-simple-storage/27-compiling-foundry-zksync/+page.md new file mode 100644 index 000000000..9d06c5c60 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/27-compiling-foundry-zksync/+page.md @@ -0,0 +1,11 @@ +--- +title: Compiling foundry ZKsync +--- + +_Follow along with the video_ + +--- + +> Previously, when we ran the `forge build` command, it generated an `/out` folder in the root project directory. This folder contains all the compilation details related the Ethereum Virtual Machine (EVM) and Vanilla Foundry. To compile for the ZKsync chain instead, we use the command `forge build --zksync`. This command creates a new folder in our project root called `/zkout`, and contains all the compiled code compatible to the ZKsync Era VM. + +If we need to revert to vanilla Foundry for deployment on the EVM, we simply run the command `foundryup` and then use `forge build`, which builds a standard Foundry project. Unless otherwise specified, we should continue using this method. From afd8b79a22fb1f3ddc69b2ef9b07e62d7aa41315 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:54 -0500 Subject: [PATCH 233/797] PatrickAlphaC removing file due to editing --- .../26-zksync-local-node/+page.md | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/26-zksync-local-node/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/26-zksync-local-node/+page.md b/courses/foundry/1-foundry-simple-storage/26-zksync-local-node/+page.md deleted file mode 100644 index fbf8cbf1c..000000000 --- a/courses/foundry/1-foundry-simple-storage/26-zksync-local-node/+page.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: ZKsync Setting up Local Node ---- - -_Follow along with the video_ - ---- - -### Introduction - -> 👀❗**IMPORTANT**:br -> This lesson is optional. If you encounter difficulties installing or understanding the required tools, feel free to proceed to the next section and continue using Anvil to test your smart contract locally. - -In the previous lessons, we learned about deploying smart contracts with the `forge create` and `forge script` commands on our **local Anvil chain**. In this lesson, we will set up and run a **ZKsync local environment**. - -### Local Node Setup - -To deploy locally on a ZKsync local chain, you'll need additional tools: Docker, Node.js, and zksync-cli. - -1. **Docker**: Start the [Docker](https://www.docker.com/) daemon. On Mac OS, you can start it using the Docker application interface. On Linux, use commands like `sudo systemctl start docker` and `sudo systemctl stop docker` will manage Docker lifecycles. Verify the installation with `docker --version` and `docker ps` commands. - -2. **Node.js and npm**: Install [Node.js](https://nodejs.org/en) and [npm](https://www.npmjs.com/). Follow the Node.js documentation to install the right version for your operating system. Verify the installations with `npm --version` and `node --version` commands. - -3. **zksync-cli**: Once Docker and Node.js are installed, you can install the [zksync-cli](https://www.npmjs.com/package/zksync-cli) to manage your local ZKsync development environment. Run `npx zksync-cli dev config` to set up your configuration. Choose the `in-memory` node option for a quick startup without persistent state and avoid additional options like a portal or block explorer unless you want to explore them independently. - -To start your local ZKsync node, run `npx zksync-cli dev start`. This command spins up a ZKsync node in Docker and runs it in the background. Verify the process is running with `docker ps`. - -> 🗒️ **NOTE**:br -> If Docker isn’t running, the `npx zksync-cli dev start` command will fail. Ensure Docker is running before attempting to start the ZKsync node again. - -### Deployment - -The ZKsync deployment process is similar to previous deployments. We will use the same commands, but this time, we will append the `--zksync` and `--legacy` flags. Note that the `forge script` command is not well supported in ZKsync, so we will use `forge create` instead. - -### Conclusion - -Setting up a local ZKsync node involves a few additional tools, including Docker, Node.js, npm, and zksync-cli: they will help creating a robust ZKsync development environment and allowing test and deployment of smart contracts on a ZKsync local chain. From 5e7a7745c1098396df656dba476ba363f28a050d Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:55 -0500 Subject: [PATCH 234/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/28-zksync-local-node/+page.md. --- .../28-zksync-local-node/+page.md | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/28-zksync-local-node/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/28-zksync-local-node/+page.md b/courses/foundry/1-foundry-simple-storage/28-zksync-local-node/+page.md new file mode 100644 index 000000000..fbf8cbf1c --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/28-zksync-local-node/+page.md @@ -0,0 +1,37 @@ +--- +title: ZKsync Setting up Local Node +--- + +_Follow along with the video_ + +--- + +### Introduction + +> 👀❗**IMPORTANT**:br +> This lesson is optional. If you encounter difficulties installing or understanding the required tools, feel free to proceed to the next section and continue using Anvil to test your smart contract locally. + +In the previous lessons, we learned about deploying smart contracts with the `forge create` and `forge script` commands on our **local Anvil chain**. In this lesson, we will set up and run a **ZKsync local environment**. + +### Local Node Setup + +To deploy locally on a ZKsync local chain, you'll need additional tools: Docker, Node.js, and zksync-cli. + +1. **Docker**: Start the [Docker](https://www.docker.com/) daemon. On Mac OS, you can start it using the Docker application interface. On Linux, use commands like `sudo systemctl start docker` and `sudo systemctl stop docker` will manage Docker lifecycles. Verify the installation with `docker --version` and `docker ps` commands. + +2. **Node.js and npm**: Install [Node.js](https://nodejs.org/en) and [npm](https://www.npmjs.com/). Follow the Node.js documentation to install the right version for your operating system. Verify the installations with `npm --version` and `node --version` commands. + +3. **zksync-cli**: Once Docker and Node.js are installed, you can install the [zksync-cli](https://www.npmjs.com/package/zksync-cli) to manage your local ZKsync development environment. Run `npx zksync-cli dev config` to set up your configuration. Choose the `in-memory` node option for a quick startup without persistent state and avoid additional options like a portal or block explorer unless you want to explore them independently. + +To start your local ZKsync node, run `npx zksync-cli dev start`. This command spins up a ZKsync node in Docker and runs it in the background. Verify the process is running with `docker ps`. + +> 🗒️ **NOTE**:br +> If Docker isn’t running, the `npx zksync-cli dev start` command will fail. Ensure Docker is running before attempting to start the ZKsync node again. + +### Deployment + +The ZKsync deployment process is similar to previous deployments. We will use the same commands, but this time, we will append the `--zksync` and `--legacy` flags. Note that the `forge script` command is not well supported in ZKsync, so we will use `forge create` instead. + +### Conclusion + +Setting up a local ZKsync node involves a few additional tools, including Docker, Node.js, npm, and zksync-cli: they will help creating a robust ZKsync development environment and allowing test and deployment of smart contracts on a ZKsync local chain. From 688bec7be88559bbb3e1cf70f061ec8fa45e0232 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:55 -0500 Subject: [PATCH 235/797] PatrickAlphaC removing file due to editing --- .../27-zksync-local-deploy/+page.md | 30 ------------------- 1 file changed, 30 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/27-zksync-local-deploy/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/27-zksync-local-deploy/+page.md b/courses/foundry/1-foundry-simple-storage/27-zksync-local-deploy/+page.md deleted file mode 100644 index 2d2ea270a..000000000 --- a/courses/foundry/1-foundry-simple-storage/27-zksync-local-deploy/+page.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: ZKsync Local Deployment ---- - -_Follow along with the video_ - ---- - -In this lesson, we are going to deploy the contract `SimpleStorage.sol` on a **ZKsync local chain**. - -We start by verifying that the Forge version we are using is correct. By running the `forge --version` command it confirms that we are on version 0.2: this indicates we are using the right Foundry ZKsync edition. - -Next, we proceed with creating a `SimpleStorage` contract using the command: - -```bash -forge create src/SimpleStorage.sol:SimpleStorage --rpc_url --private_key --legacy --zksync -``` - -Here, `` represents ZKsync node address, such as `http://127.0.0.1:8011`. - -> 👀❗**IMPORTANT**:br -> Including private keys directly in commands is not a safe practice. - -This command instructs Foundry to locate the `SimpleStorage` contract in the `src/SimpleStorage.sol` file and deploy it. Upon execution, the contract compiles and deploys successfully. The output will display details such as the deployer, the deployed contract address, and the transaction hash. - -::image{src='/foundry-simply-storage/27-zksync-local-deploy/deployment-successful.png' style='width: 50%; height: auto;'} - -Using the `--legacy` flag is recommended for deploying simple contracts, while more complex codebases may require different approaches. Attempting to deploy without the `--legacy` flag might result in errors like `failed to serialize transaction, address to address is null`, which will be covered in future lessons. - -Once you are finished, you can close Docker Desktop and revert to the Vanilla Foundry environment using the `foundryup` command. From ecb8c7ed0674ea50845b300c281ed61f57b8726b Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:56 -0500 Subject: [PATCH 236/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/29-zksync-local-deploy/+page.md. --- .../29-zksync-local-deploy/+page.md | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/29-zksync-local-deploy/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/29-zksync-local-deploy/+page.md b/courses/foundry/1-foundry-simple-storage/29-zksync-local-deploy/+page.md new file mode 100644 index 000000000..2d2ea270a --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/29-zksync-local-deploy/+page.md @@ -0,0 +1,30 @@ +--- +title: ZKsync Local Deployment +--- + +_Follow along with the video_ + +--- + +In this lesson, we are going to deploy the contract `SimpleStorage.sol` on a **ZKsync local chain**. + +We start by verifying that the Forge version we are using is correct. By running the `forge --version` command it confirms that we are on version 0.2: this indicates we are using the right Foundry ZKsync edition. + +Next, we proceed with creating a `SimpleStorage` contract using the command: + +```bash +forge create src/SimpleStorage.sol:SimpleStorage --rpc_url --private_key --legacy --zksync +``` + +Here, `` represents ZKsync node address, such as `http://127.0.0.1:8011`. + +> 👀❗**IMPORTANT**:br +> Including private keys directly in commands is not a safe practice. + +This command instructs Foundry to locate the `SimpleStorage` contract in the `src/SimpleStorage.sol` file and deploy it. Upon execution, the contract compiles and deploys successfully. The output will display details such as the deployer, the deployed contract address, and the transaction hash. + +::image{src='/foundry-simply-storage/27-zksync-local-deploy/deployment-successful.png' style='width: 50%; height: auto;'} + +Using the `--legacy` flag is recommended for deploying simple contracts, while more complex codebases may require different approaches. Attempting to deploy without the `--legacy` flag might result in errors like `failed to serialize transaction, address to address is null`, which will be covered in future lessons. + +Once you are finished, you can close Docker Desktop and revert to the Vanilla Foundry environment using the `foundryup` command. From 1ddaee3775f3afaf51d65d064dd79ce48b8fa3c6 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:57 -0500 Subject: [PATCH 237/797] PatrickAlphaC removing file due to editing --- .../28-tx-types/+page.md | 36 ------------------- 1 file changed, 36 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/28-tx-types/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/28-tx-types/+page.md b/courses/foundry/1-foundry-simple-storage/28-tx-types/+page.md deleted file mode 100644 index e1565ff20..000000000 --- a/courses/foundry/1-foundry-simple-storage/28-tx-types/+page.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: Transaction Types ---- - -_Follow along with the video_ - ---- - -### Introduction - -In this lesson, we will explore the different transaction types within the ZKsync VM and EVM ecosystems. - -### `/broadcast` Folder - -When deploying to a ZKsync local node, a `/broadcast` folder will be created and it will contain detailed information about the **deployment transactions**. Inside this folder, you will find subfolders named after specific deployment chain IDs, such as **`260`** for ZKsync and **`31337`** for Anvil. These subfolders store the data of the transactions executed during the deployment process. - -By examining both the `run-latest.json` file in these folders, we can observe different **transaction types** for each transaction within a chain. For instance, transactions on the Anvil chain might be labeled as type **`0x2`**, while those on the ZKsync chain will be of type **`0x0`**. Deploying a smart contract on the EVM without the `--legacy` flag results in a default transaction type of `0x2`. Adding the `--legacy` flag changes it to type `0x0`. - -The EVM and ZKsync ecosystems support multiple transaction types to accommodate various Ethereum Improvement Proposals (EIPs). Initially, Ethereum had only one transaction type (`0x0` legacy), but as the ecosystem evolved, multiple types were introduced through various EIPs. Subsequent types include type 1, which introduces an _access list_ of addresses and keys, and type 2, also known as [EIP 1559](https://eips.ethereum.org/EIPS/eip-1559) transactions. - -> 👀❗**IMPORTANT**:br -> This `0x2` type is the current default type for the EVM. - -Additionally, ZKsync introduces its [unique transaction type](https://docs.zksync.io/zk-stack/concepts/transaction-lifecycle#eip-712-0x71), the type `113` (`0x71` in hex), which can enable features like [account abstraction](https://docs.zksync.io/build/developer-reference/account-abstraction/). - -> 💡 **TIP**:br -> The `forge script` command will work in some scenarios, but it’s not entirely clear where it might fail. For the purpose of this course, we will assume scripting does not work while working with ZKsync. - -### Resources - -- [ZKsync documentation](https://docs.zksync.io/zk-stack/concepts/transaction-lifecycle#transaction-types) about transaction types -- [Cyfrin Blog on EIP-4844](https://www.cyfrin.io/blog/what-is-eip-4844-proto-danksharding-and-blob-transactions) - -### Conclusion - -The ZKsync VM and EVM ecosystems support various transaction types to meet different EIP requirements. By examining deployment folders and understanding the use of flags like `--legacy`, we can effectively distinguish between these transaction types. From c7f07bac3f4aa83afeeaef29038ae7893588e992 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:58 -0500 Subject: [PATCH 238/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/30-tx-types/+page.md. --- .../30-tx-types/+page.md | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/30-tx-types/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/30-tx-types/+page.md b/courses/foundry/1-foundry-simple-storage/30-tx-types/+page.md new file mode 100644 index 000000000..e1565ff20 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/30-tx-types/+page.md @@ -0,0 +1,36 @@ +--- +title: Transaction Types +--- + +_Follow along with the video_ + +--- + +### Introduction + +In this lesson, we will explore the different transaction types within the ZKsync VM and EVM ecosystems. + +### `/broadcast` Folder + +When deploying to a ZKsync local node, a `/broadcast` folder will be created and it will contain detailed information about the **deployment transactions**. Inside this folder, you will find subfolders named after specific deployment chain IDs, such as **`260`** for ZKsync and **`31337`** for Anvil. These subfolders store the data of the transactions executed during the deployment process. + +By examining both the `run-latest.json` file in these folders, we can observe different **transaction types** for each transaction within a chain. For instance, transactions on the Anvil chain might be labeled as type **`0x2`**, while those on the ZKsync chain will be of type **`0x0`**. Deploying a smart contract on the EVM without the `--legacy` flag results in a default transaction type of `0x2`. Adding the `--legacy` flag changes it to type `0x0`. + +The EVM and ZKsync ecosystems support multiple transaction types to accommodate various Ethereum Improvement Proposals (EIPs). Initially, Ethereum had only one transaction type (`0x0` legacy), but as the ecosystem evolved, multiple types were introduced through various EIPs. Subsequent types include type 1, which introduces an _access list_ of addresses and keys, and type 2, also known as [EIP 1559](https://eips.ethereum.org/EIPS/eip-1559) transactions. + +> 👀❗**IMPORTANT**:br +> This `0x2` type is the current default type for the EVM. + +Additionally, ZKsync introduces its [unique transaction type](https://docs.zksync.io/zk-stack/concepts/transaction-lifecycle#eip-712-0x71), the type `113` (`0x71` in hex), which can enable features like [account abstraction](https://docs.zksync.io/build/developer-reference/account-abstraction/). + +> 💡 **TIP**:br +> The `forge script` command will work in some scenarios, but it’s not entirely clear where it might fail. For the purpose of this course, we will assume scripting does not work while working with ZKsync. + +### Resources + +- [ZKsync documentation](https://docs.zksync.io/zk-stack/concepts/transaction-lifecycle#transaction-types) about transaction types +- [Cyfrin Blog on EIP-4844](https://www.cyfrin.io/blog/what-is-eip-4844-proto-danksharding-and-blob-transactions) + +### Conclusion + +The ZKsync VM and EVM ecosystems support various transaction types to meet different EIP requirements. By examining deployment folders and understanding the use of flags like `--legacy`, we can effectively distinguish between these transaction types. From 81963c1c6f42207cece1e2c048da511edb482910 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:59 -0500 Subject: [PATCH 239/797] PatrickAlphaC removing file due to editing --- .../29-why-l2/+page.md | 30 ------------------- 1 file changed, 30 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/29-why-l2/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/29-why-l2/+page.md b/courses/foundry/1-foundry-simple-storage/29-why-l2/+page.md deleted file mode 100644 index ceaa6b3fc..000000000 --- a/courses/foundry/1-foundry-simple-storage/29-why-l2/+page.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: L2s ---- - -_Follow along with the video_ - ---- - -### Introduction - -In previous lessons, we deployed to the Sepolia testnet and started working with the Layer 2 solution ZKsync. Deploying to Sepolia simulates deployment to the Ethereum mainnet, offering a comprehensive understanding of Layer 1 deployments. However, it's important to note that most projects today prefer deploying to Layer 2 solutions rather than directly to Ethereum due to the high costs associated with deployments. - -### Gas Usage - -When deploying to a ZKsync local node, a `/broadcast` folder is created, containing a lot of detailed deployment transaction information. For instance, in our `run-latest.json` file, we can see the `gasUsed` value and we can convert this hexadecimal number `0x5747A` to its decimal equivalent by typing `cast to base 0x5747A dec`. This conversion allows us to estimate the deployment cost on the Ethereum mainnet. By checking recent gas prices on Etherscan, we can calculate the total cost using the formula: - -``` -Total Cost = Gas Used * Gas Price -``` - -We can see this total cost in the deployment transaction on [Sepolia Etherscan](https://sepolia.etherscan.io/tx/0xc496b9d30df33aa9285ddd384c14ce2a58eef470898b5cda001d0f4a21b017f6), under the `Transaction Fee` section. In this case, `357,498` gas will costs `0.000279288255846978` ETH, which today is equivalent to $7. - -Deploying even a minimal contract like `SimpleStorage` on Ethereum can be expensive. Larger contracts, with thousands of lines of code, can cost thousands of dollars. This is why many developers prefer deploying to Layer 2 solutions like ZKsync, which offer the same security as Ethereum but at a fraction of the cost. - -### Deploying to ZKsync Sepolia - -Deploying to ZKsync Sepolia is similar to deploying to a ZKsync local node. You can retrieve a ZKsync Sepolia RPC URL from [Alchemy](https://www.alchemy.com/) by creating a new app based on the ZKsepolia network. Then, you can proceed to add the `ZKSYNC_RPC_URL` to your `.env` configuration. - -> 🗒️ **NOTE**:br -> To understand the cost benefits of Layer 2 solutions, visit [L2Fees.info](https://l2fees.info) and compare the significant cost differences between sending a transaction on Ethereum and ZKsync Era. From 1c6188906c6bc258a3319bc6a9aee51765ce45fd Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:59 -0500 Subject: [PATCH 240/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/31-why-l2/+page.md. --- .../31-why-l2/+page.md | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/31-why-l2/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/31-why-l2/+page.md b/courses/foundry/1-foundry-simple-storage/31-why-l2/+page.md new file mode 100644 index 000000000..ceaa6b3fc --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/31-why-l2/+page.md @@ -0,0 +1,30 @@ +--- +title: L2s +--- + +_Follow along with the video_ + +--- + +### Introduction + +In previous lessons, we deployed to the Sepolia testnet and started working with the Layer 2 solution ZKsync. Deploying to Sepolia simulates deployment to the Ethereum mainnet, offering a comprehensive understanding of Layer 1 deployments. However, it's important to note that most projects today prefer deploying to Layer 2 solutions rather than directly to Ethereum due to the high costs associated with deployments. + +### Gas Usage + +When deploying to a ZKsync local node, a `/broadcast` folder is created, containing a lot of detailed deployment transaction information. For instance, in our `run-latest.json` file, we can see the `gasUsed` value and we can convert this hexadecimal number `0x5747A` to its decimal equivalent by typing `cast to base 0x5747A dec`. This conversion allows us to estimate the deployment cost on the Ethereum mainnet. By checking recent gas prices on Etherscan, we can calculate the total cost using the formula: + +``` +Total Cost = Gas Used * Gas Price +``` + +We can see this total cost in the deployment transaction on [Sepolia Etherscan](https://sepolia.etherscan.io/tx/0xc496b9d30df33aa9285ddd384c14ce2a58eef470898b5cda001d0f4a21b017f6), under the `Transaction Fee` section. In this case, `357,498` gas will costs `0.000279288255846978` ETH, which today is equivalent to $7. + +Deploying even a minimal contract like `SimpleStorage` on Ethereum can be expensive. Larger contracts, with thousands of lines of code, can cost thousands of dollars. This is why many developers prefer deploying to Layer 2 solutions like ZKsync, which offer the same security as Ethereum but at a fraction of the cost. + +### Deploying to ZKsync Sepolia + +Deploying to ZKsync Sepolia is similar to deploying to a ZKsync local node. You can retrieve a ZKsync Sepolia RPC URL from [Alchemy](https://www.alchemy.com/) by creating a new app based on the ZKsepolia network. Then, you can proceed to add the `ZKSYNC_RPC_URL` to your `.env` configuration. + +> 🗒️ **NOTE**:br +> To understand the cost benefits of Layer 2 solutions, visit [L2Fees.info](https://l2fees.info) and compare the significant cost differences between sending a transaction on Ethereum and ZKsync Era. From 5a141d20f85569ecdcff6be4401bb1a8d8309882 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:38:00 -0500 Subject: [PATCH 241/797] PatrickAlphaC removing file due to editing --- .../30-alchemy-mempool/+page.md | 82 ------------------- 1 file changed, 82 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/30-alchemy-mempool/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/30-alchemy-mempool/+page.md b/courses/foundry/1-foundry-simple-storage/30-alchemy-mempool/+page.md deleted file mode 100644 index 03a1dcb3b..000000000 --- a/courses/foundry/1-foundry-simple-storage/30-alchemy-mempool/+page.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: Alchemy & The Mempool ---- - -_Follow along the course with this video._ - - - ---- - -## Alchemy: A Game Changer for Decentralized Application Development - -Innovation in the blockchain industry has come a long way, with powerful tools making their way into the ecosystem to support developers and bring efficiency to their workflows. Among these tools is Alchemy, and today we have Vito, the lead developer experience at Alchemy, to walk us through the platform, its features, and how you can leverage it to exponentially increase your productivity. - -## What is Alchemy? - -Alchemy is a platform equipped with APIs, SDKs, and libraries to enhance your developer experience while working on Web3 projects. Think of Alchemy as the AWS of Web3. It functions as a node provider and developer tooling platform predominantly used in thousands of Web3 and Web2 applications, including large Web2 corporations like Adobe, Shopify, and Stripe. - -The need for platforms such as Alchemy arises from the fact that, as a developer, you don't usually have to worry about running the servers your code operates on or developing the deployment and integration pipelines for your application. Instead, you use services such as AWS, Azure, and Google Cloud for that—Alchemy does the same but for Web3. - -## How Does Alchemy Work? - -Alchemy enhances your developer experience through a combination of features. The platform's primary component is the _Supernode_, a proprietary blockchain engine that works as a load balancer on top of your node. - -Like its name suggests, the Supernode ensures data from the blockchain is always up-to-date and readily available. Using the Supernode as a foundation, Alchemy has built the _Enhanced APIs_—a set of APIs that makes pulling data from the blockchain a breeze. - -To put it simply, the Alchemy Supernode sits at the core of its ecosystem, powering up functionalities like Enhanced APIs and monitoring tools while supporting multiple chains. - -What follows is a step-by-step guide on how to create a new account on Alchemy and leverage this platform to its full extent: - -## Creating a New Account on Alchemy - -Creating an account on Alchemy is not only easy but also completely free. You can also freely scale your applications up using the platform's generous premium plans. - -#### Step 1: Navigate to Alchemy.com - -Head over to [Alchemy.com](https://www.alchemy.com/) and create a new account. - -#### Step 2: Create a New Application - -Once you have signed in, create a new application. - -Next, give your application a name and a description. Then, select a chain and network. Alchemy currently supports the majority of EVM-compatible chains, including: - -- Ethereum -- Polygon PoS -- Polygon zkEVM -- Optimism -- Arbitrum -- Solana (non-EVM chain) - -## The Application-Specific Dashboard - -Once your application is up and running, you will have access to the application-specific dashboard. This dashboard provides crucial insights into your application and infrastructure health, such as latency, compute units, and transaction success rate, which can be valuable for debugging and identifying issues. - -If you observe a lower success rate for your transactions, go to the "Recent Invalid Request" tab. This will list all unsuccessful requests along with the reasons for their failure, making it easier for you to debug and fix issues. - -::image{src='/foundry/22-alchemy/alchemy1.png' style='width: 100%; height: auto;'} - -## Mempool Watcher - -Another powerful tool provided by Alchemy is the Mempool watcher. Picture it as Ethereum's mempool, where all pending transactions reside waiting for validation or mining. - -The Mempool watcher provides extensive details about your transactions, such as: - -- Transaction status (mined, pending, dropped, replaced) -- Gas used -- Time taken for validation -- Transaction value -- Sender's and receiver's address - -This detailed transaction tracking allows you to have a better understanding of each transaction and aids immensely in debugging specific issues related to individual transactions. - -## Wrapping Up - -To sum up, Alchemy is a revolutionary platform that brings a plethora of tools to aid your Web3 development experience. From Supernode to Enhanced APIs and crucial troubleshooting tools, Alchemy is undeniably a game changer in the world of decentralized applications. - -"Alchemy can be a powerful asset to any blockchain developer, offering a simplified experience in an inherently complicated Web3 environment." – Vito, Lead Developer Experience at Alchemy. - -Vito suggests that you check out Alchemy's [documentation](https://docs.alchemy.com/) to explore more about the platform, its APIs, SDKs, libraries, and tools. Also, don't forget to follow them on Twitter at [@AlchemyPlatform](https://twitter.com/alchemyplatform) and [@AlchemyLearn](https://twitter.com/alchemyLearn). And if you want to connect directly with Vito, feel free to reach out to him on Twitter at [@VitoStack](https://twitter.com/VittoStack). - -Alchemy is revolutionizing the landscape of blockchain development and making it more accessible and efficient for everyone involved. Happy building with Alchemy! From 023b0a29c5ea1580184373df838bf9a118015d0e Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:38:01 -0500 Subject: [PATCH 242/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/32-alchemy-mempool/+page.md. --- .../32-alchemy-mempool/+page.md | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/32-alchemy-mempool/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/32-alchemy-mempool/+page.md b/courses/foundry/1-foundry-simple-storage/32-alchemy-mempool/+page.md new file mode 100644 index 000000000..03a1dcb3b --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/32-alchemy-mempool/+page.md @@ -0,0 +1,82 @@ +--- +title: Alchemy & The Mempool +--- + +_Follow along the course with this video._ + + + +--- + +## Alchemy: A Game Changer for Decentralized Application Development + +Innovation in the blockchain industry has come a long way, with powerful tools making their way into the ecosystem to support developers and bring efficiency to their workflows. Among these tools is Alchemy, and today we have Vito, the lead developer experience at Alchemy, to walk us through the platform, its features, and how you can leverage it to exponentially increase your productivity. + +## What is Alchemy? + +Alchemy is a platform equipped with APIs, SDKs, and libraries to enhance your developer experience while working on Web3 projects. Think of Alchemy as the AWS of Web3. It functions as a node provider and developer tooling platform predominantly used in thousands of Web3 and Web2 applications, including large Web2 corporations like Adobe, Shopify, and Stripe. + +The need for platforms such as Alchemy arises from the fact that, as a developer, you don't usually have to worry about running the servers your code operates on or developing the deployment and integration pipelines for your application. Instead, you use services such as AWS, Azure, and Google Cloud for that—Alchemy does the same but for Web3. + +## How Does Alchemy Work? + +Alchemy enhances your developer experience through a combination of features. The platform's primary component is the _Supernode_, a proprietary blockchain engine that works as a load balancer on top of your node. + +Like its name suggests, the Supernode ensures data from the blockchain is always up-to-date and readily available. Using the Supernode as a foundation, Alchemy has built the _Enhanced APIs_—a set of APIs that makes pulling data from the blockchain a breeze. + +To put it simply, the Alchemy Supernode sits at the core of its ecosystem, powering up functionalities like Enhanced APIs and monitoring tools while supporting multiple chains. + +What follows is a step-by-step guide on how to create a new account on Alchemy and leverage this platform to its full extent: + +## Creating a New Account on Alchemy + +Creating an account on Alchemy is not only easy but also completely free. You can also freely scale your applications up using the platform's generous premium plans. + +#### Step 1: Navigate to Alchemy.com + +Head over to [Alchemy.com](https://www.alchemy.com/) and create a new account. + +#### Step 2: Create a New Application + +Once you have signed in, create a new application. + +Next, give your application a name and a description. Then, select a chain and network. Alchemy currently supports the majority of EVM-compatible chains, including: + +- Ethereum +- Polygon PoS +- Polygon zkEVM +- Optimism +- Arbitrum +- Solana (non-EVM chain) + +## The Application-Specific Dashboard + +Once your application is up and running, you will have access to the application-specific dashboard. This dashboard provides crucial insights into your application and infrastructure health, such as latency, compute units, and transaction success rate, which can be valuable for debugging and identifying issues. + +If you observe a lower success rate for your transactions, go to the "Recent Invalid Request" tab. This will list all unsuccessful requests along with the reasons for their failure, making it easier for you to debug and fix issues. + +::image{src='/foundry/22-alchemy/alchemy1.png' style='width: 100%; height: auto;'} + +## Mempool Watcher + +Another powerful tool provided by Alchemy is the Mempool watcher. Picture it as Ethereum's mempool, where all pending transactions reside waiting for validation or mining. + +The Mempool watcher provides extensive details about your transactions, such as: + +- Transaction status (mined, pending, dropped, replaced) +- Gas used +- Time taken for validation +- Transaction value +- Sender's and receiver's address + +This detailed transaction tracking allows you to have a better understanding of each transaction and aids immensely in debugging specific issues related to individual transactions. + +## Wrapping Up + +To sum up, Alchemy is a revolutionary platform that brings a plethora of tools to aid your Web3 development experience. From Supernode to Enhanced APIs and crucial troubleshooting tools, Alchemy is undeniably a game changer in the world of decentralized applications. + +"Alchemy can be a powerful asset to any blockchain developer, offering a simplified experience in an inherently complicated Web3 environment." – Vito, Lead Developer Experience at Alchemy. + +Vito suggests that you check out Alchemy's [documentation](https://docs.alchemy.com/) to explore more about the platform, its APIs, SDKs, libraries, and tools. Also, don't forget to follow them on Twitter at [@AlchemyPlatform](https://twitter.com/alchemyplatform) and [@AlchemyLearn](https://twitter.com/alchemyLearn). And if you want to connect directly with Vito, feel free to reach out to him on Twitter at [@VitoStack](https://twitter.com/VittoStack). + +Alchemy is revolutionizing the landscape of blockchain development and making it more accessible and efficient for everyone involved. Happy building with Alchemy! From b5b98a99dbb201c79aed55115d0e6f6a26989b15 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:38:02 -0500 Subject: [PATCH 243/797] PatrickAlphaC removing file due to editing --- .../31-summary-congratulations/+page.md | 47 ------------------- 1 file changed, 47 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/31-summary-congratulations/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/31-summary-congratulations/+page.md b/courses/foundry/1-foundry-simple-storage/31-summary-congratulations/+page.md deleted file mode 100644 index fdffe8891..000000000 --- a/courses/foundry/1-foundry-simple-storage/31-summary-congratulations/+page.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Summary & Congratulations ---- - -_Follow along the course with this video._ - - - ---- - -## Celebrating Milestones in Foundry: A Complete Walkthrough of Our Recent Project - -You should feel a warm sense of accomplishment envelop you. Completing an entire project in Foundry is no mean feat. A hearty congratulation is in order for such an indomitable effort. This article serves as a quick, yet comprehensive, recap of everything we learnt in our project, proceeding into our next engagement. From the onset, rest assured, we are set to advance our Foundry skills, push upcoming projects on GitHub, and familiarize ourselves with advanced tooling. - -## A Quick Trip Down Memory Lane: Key Takeaways from the Project - -Firstly, we journeyed through the process of creating a new Foundry project using Forge and Knit. These essential tools afforded us a structured, professional environment complete with folders to keep our work organized. - -We not only learnt about Foundry’s basic commands but also their specific functionalities such as: - -- **Cast**: interacts with contracts that have been previously deployed. -- **Forge**: compiles and interacts with our contracts. -- **Anvil**: deploys a local blockchain, similar to another tool we used, Ganache. - -A pivotal part of our learning process was comprehending that sending a transaction via our MetaMask is tantamount to making an HTTP post request to a particular RPC URL. A similar RPC URL can be obtained from a node-as-a-service provider like [Alchemy](https://www.alchemyapi.io/) and used to send transactions directly from our Foundry projects. - -We obtained practical knowledge on how to compile code in Foundry and write a Solidity script for its subsequent deployment. We also find it critical to ensure the security of our private keys. Hence, throughout this course, we will be using an `.env` file. But be warned when dealing with real money, having your private key in plain text is not advisable. - -## Understanding Contract Deployment and Interaction on the Blockchain - -We delved into the automation of contract deployments to a blockchain. Post-deployment, we interacted with them using the `cast` keyword and `send` to make transactions, then `cast call` to read from those contracts. - -Moreover, the knowledge on how to auto format contracts with `Forge format` was acquired. We also learnt the painstaking yet rewarding manual method of verifying our contracts on the blockchain. - -```bash -forge format my_contract.sol -``` - -::image{src='/foundry/23-summary/summary1.png' style='width: 100%; height: auto;'} - -## Looking Ahead - -With these tools in your web development arsenal, you've performed exceptionally well – and yes, you should be incredibly proud. Remember, even something as small as installing tools like `Vs code` and `Foundry` can pose great difficulties, so, you're doing fantastic. - -Take a breather. Remember, breaks enhance productivity. Till next time, continue to strive for greatness in every line of code you write! - -::image{src='/foundry/23-summary/summary2.png' style='width: 100%; height: auto;'} From 8b7efebfd473cb0fbda2903dd71c45d6d346a349 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:38:03 -0500 Subject: [PATCH 244/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/33-summary-congratulations/+page.md. --- .../33-summary-congratulations/+page.md | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/33-summary-congratulations/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/33-summary-congratulations/+page.md b/courses/foundry/1-foundry-simple-storage/33-summary-congratulations/+page.md new file mode 100644 index 000000000..fdffe8891 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/33-summary-congratulations/+page.md @@ -0,0 +1,47 @@ +--- +title: Summary & Congratulations +--- + +_Follow along the course with this video._ + + + +--- + +## Celebrating Milestones in Foundry: A Complete Walkthrough of Our Recent Project + +You should feel a warm sense of accomplishment envelop you. Completing an entire project in Foundry is no mean feat. A hearty congratulation is in order for such an indomitable effort. This article serves as a quick, yet comprehensive, recap of everything we learnt in our project, proceeding into our next engagement. From the onset, rest assured, we are set to advance our Foundry skills, push upcoming projects on GitHub, and familiarize ourselves with advanced tooling. + +## A Quick Trip Down Memory Lane: Key Takeaways from the Project + +Firstly, we journeyed through the process of creating a new Foundry project using Forge and Knit. These essential tools afforded us a structured, professional environment complete with folders to keep our work organized. + +We not only learnt about Foundry’s basic commands but also their specific functionalities such as: + +- **Cast**: interacts with contracts that have been previously deployed. +- **Forge**: compiles and interacts with our contracts. +- **Anvil**: deploys a local blockchain, similar to another tool we used, Ganache. + +A pivotal part of our learning process was comprehending that sending a transaction via our MetaMask is tantamount to making an HTTP post request to a particular RPC URL. A similar RPC URL can be obtained from a node-as-a-service provider like [Alchemy](https://www.alchemyapi.io/) and used to send transactions directly from our Foundry projects. + +We obtained practical knowledge on how to compile code in Foundry and write a Solidity script for its subsequent deployment. We also find it critical to ensure the security of our private keys. Hence, throughout this course, we will be using an `.env` file. But be warned when dealing with real money, having your private key in plain text is not advisable. + +## Understanding Contract Deployment and Interaction on the Blockchain + +We delved into the automation of contract deployments to a blockchain. Post-deployment, we interacted with them using the `cast` keyword and `send` to make transactions, then `cast call` to read from those contracts. + +Moreover, the knowledge on how to auto format contracts with `Forge format` was acquired. We also learnt the painstaking yet rewarding manual method of verifying our contracts on the blockchain. + +```bash +forge format my_contract.sol +``` + +::image{src='/foundry/23-summary/summary1.png' style='width: 100%; height: auto;'} + +## Looking Ahead + +With these tools in your web development arsenal, you've performed exceptionally well – and yes, you should be incredibly proud. Remember, even something as small as installing tools like `Vs code` and `Foundry` can pose great difficulties, so, you're doing fantastic. + +Take a breather. Remember, breaks enhance productivity. Till next time, continue to strive for greatness in every line of code you write! + +::image{src='/foundry/23-summary/summary2.png' style='width: 100%; height: auto;'} From cbc1449ee3276c3829278df4d7f3a4e6ac35e232 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:38:04 -0500 Subject: [PATCH 245/797] PatrickAlphaC removing file due to editing --- .../4-develop-in-cloud-using-gitpod/+page.md | 21 ------------------- 1 file changed, 21 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/4-develop-in-cloud-using-gitpod/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/4-develop-in-cloud-using-gitpod/+page.md b/courses/foundry/1-foundry-simple-storage/4-develop-in-cloud-using-gitpod/+page.md deleted file mode 100644 index 11d4b0033..000000000 --- a/courses/foundry/1-foundry-simple-storage/4-develop-in-cloud-using-gitpod/+page.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Develop in the cloud using Gitpod ---- - -_Follow along with this video:_ - ---- - -### Develop in the cloud using Gitpod - -**BIG BOLDED DISCLAIMER: This is not the ideal way to develop smart contracts. While using Gitpod you should never share private information, like a key or a secret phrase. That's if you like to continue being the owner of the associated accounts.** - -Gitpod is an online platform that provides cloud-based, pre-configured development environments specifically designed for working with Git repositories. It's similar to Remix IDE, but it allows you to run VS Code in a browser, on a remote server. - -Go to [Gitpod's website](https://gitpod.io/login/) and click `Continue with Github`. After that, you'll be able to create a new workspace, starting from a Github repository, using a stable version of VS Code. - -You'll be amazed to find out it looks exactly like VS Code. There's also an option to open Gitpod into your VS Code desktop version. - -Everything works like in VS Code and thus you should be able to run anything using the same commands. - -Gitpod has some [fantastic resources](https://www.gitpod.io/docs/introduction/getting-started) to get you started. From 3b1a884c2efbe50e587f55ca27b8d695e7f35cc8 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:38:04 -0500 Subject: [PATCH 246/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/6-develop-in-cloud-using-gitpod/+page.md. --- .../6-develop-in-cloud-using-gitpod/+page.md | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/6-develop-in-cloud-using-gitpod/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/6-develop-in-cloud-using-gitpod/+page.md b/courses/foundry/1-foundry-simple-storage/6-develop-in-cloud-using-gitpod/+page.md new file mode 100644 index 000000000..11d4b0033 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/6-develop-in-cloud-using-gitpod/+page.md @@ -0,0 +1,21 @@ +--- +title: Develop in the cloud using Gitpod +--- + +_Follow along with this video:_ + +--- + +### Develop in the cloud using Gitpod + +**BIG BOLDED DISCLAIMER: This is not the ideal way to develop smart contracts. While using Gitpod you should never share private information, like a key or a secret phrase. That's if you like to continue being the owner of the associated accounts.** + +Gitpod is an online platform that provides cloud-based, pre-configured development environments specifically designed for working with Git repositories. It's similar to Remix IDE, but it allows you to run VS Code in a browser, on a remote server. + +Go to [Gitpod's website](https://gitpod.io/login/) and click `Continue with Github`. After that, you'll be able to create a new workspace, starting from a Github repository, using a stable version of VS Code. + +You'll be amazed to find out it looks exactly like VS Code. There's also an option to open Gitpod into your VS Code desktop version. + +Everything works like in VS Code and thus you should be able to run anything using the same commands. + +Gitpod has some [fantastic resources](https://www.gitpod.io/docs/introduction/getting-started) to get you started. From 2e4d2aec85d3c516c73d4bc42ec329f4a1e70508 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:38:05 -0500 Subject: [PATCH 247/797] PatrickAlphaC removing file due to editing --- .../1-foundry-simple-storage/5-local-setup/+page.md | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/5-local-setup/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/5-local-setup/+page.md b/courses/foundry/1-foundry-simple-storage/5-local-setup/+page.md deleted file mode 100644 index 217dcbee6..000000000 --- a/courses/foundry/1-foundry-simple-storage/5-local-setup/+page.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Local Setup ---- -_Follow along with the video_ ---- - -To maintain a clean terminal, especially when it becomes cluttered, you can type the command "clear" and press Enter. Alternatively, use the shortcut `command + k` on a Mac or `control + k` on Linux or Windows. - -It's important to understand the difference between the **`trash can`** and the **`x`** icons in your VS code terminal: clicking the **`x`** icon it will _hide/show the terminal_, keeping all previous content visible when reopened. Clicking on the **`trash can`** icon instead, _terminates the current terminal session_. When you reopen it, you’ll see a fresh, empty session. \ No newline at end of file From a62e66ca30eb7f188e59c6f1b924a940ed12359c Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:38:06 -0500 Subject: [PATCH 248/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/7-local-setup/+page.md. --- .../1-foundry-simple-storage/7-local-setup/+page.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/7-local-setup/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/7-local-setup/+page.md b/courses/foundry/1-foundry-simple-storage/7-local-setup/+page.md new file mode 100644 index 000000000..217dcbee6 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/7-local-setup/+page.md @@ -0,0 +1,9 @@ +--- +title: Local Setup +--- +_Follow along with the video_ +--- + +To maintain a clean terminal, especially when it becomes cluttered, you can type the command "clear" and press Enter. Alternatively, use the shortcut `command + k` on a Mac or `control + k` on Linux or Windows. + +It's important to understand the difference between the **`trash can`** and the **`x`** icons in your VS code terminal: clicking the **`x`** icon it will _hide/show the terminal_, keeping all previous content visible when reopened. Clicking on the **`trash can`** icon instead, _terminates the current terminal session_. When you reopen it, you’ll see a fresh, empty session. \ No newline at end of file From 38a6c40491ba1294162871fa7c5f6d6830cfd4cf Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:38:07 -0500 Subject: [PATCH 249/797] PatrickAlphaC removing file due to editing --- .../6-foundry-install/+page.md | 87 ------------------- 1 file changed, 87 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/6-foundry-install/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/6-foundry-install/+page.md b/courses/foundry/1-foundry-simple-storage/6-foundry-install/+page.md deleted file mode 100644 index 2868dbb5a..000000000 --- a/courses/foundry/1-foundry-simple-storage/6-foundry-install/+page.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Foundry Install ---- - -_Follow along the course with this video._ - - - ---- - -Welcome to this handy guide on installing and operating Foundry, a versatile tool that will add a new level of command-line ease to your developer journey. Whether you're running Windows, Linux or MacOS, we've got you covered with instructions and tips. So sit back, grab a cup of coffee, and let's dive in. - -## Prepping your Terminal - -First things first. Before we dive into installing Foundry, make sure you have your terminal set up correctly. - -If you are using Windows, you should see something like `WSL` or `Ubuntu`. Once you have your terminal environment ready, it’s time for some quick tips to help streamline your workflow. - -### Keeping your Terminal Clutter-free - -When commands pile up in your terminal, things can get a little overwhelming. Clear it up by simply typing `clear` and hitting `Enter`. Alternatively, use `Command K` if you're on a Mac or `Control K` if you're on Linux or Windows. - -**Pro tip:** This is one of my favorite keyboard shortcuts that I use all the time. - -### Understanding the Trash Can and the X - -::image{src='/foundry/5-foundryinstall/foundryinstall1.png' style='width: 100%; height: auto;'} - -The trash can and the X buttons in your terminal perform distinct functions. Hitting `X` simply hides your terminal but retains all the previous lines of code. On the other hand, trashing it essentially deletes whatever is running in it. To open up a clean terminal, hit the trash can and then pull it back using `Toggle` or `Terminal > New Terminal`. - -## Installing Foundry - -With our terminal set and some tips up our sleeve, let's progress to installing Foundry. Navigate to the [Foundry website](https://book.getfoundry.sh/getting-started/installation) and from the installation tab, fetch the command to install Foundry. - -The command would look something like this: - -```bash -curl -L https://foundry.paradigm.xyz | bash -``` - -Hit `Enter` after pasting this in your terminal. - -**Note:** You must have Internet access for this to work as it's downloading Foundry from their official website. - -## Verifying Your Installation - -After running the `curl` command, an output will appear at the bottom of your terminal indicating the detected shell and the fact that Foundry has been added to your `Path`. - -For instance, the output can be something like this: - -```bash -Detected your preferred shell is bashrc and added Foundry to Path run:source /home/user/.bashrcStart -a new terminal session to use Foundry -``` - -Now, simply type `foundryup` and `Enter` to install and update Foundry to the latest version. Whenever you want to install an update for Foundry, simply run `foundryup` again. - -This will install four components: forge, cast, anvil, and chisel. To confirm the successful installation, run `forge --version`. You should get an output indicating the Forge version as shown below. - -```bash -Forge version x.x.x -``` - -Now, here's something to remember: when you hit the trash can in the top right, it literally 'removes' the terminal. The X button, in contrast, simply hides it. - -### Is Foundry Up Not Running? - -Don't panic if this command doesn't run. You might have an issue with your path, and you might need to add Foundry to your path. In case you run into this issue, check lesson 6 of the GitHub repo associated with this course. If no debugging tips are available there, feel free to start a discussion on the course's GitHub repo. Before doing so, make sure to check if a similar discussion already exists. - -Try typing `forge --version` into your terminal. Have you received an unwelcome output saying `Forge command found`? This implies that you have to rerun the `source` command that Foundry offered during installation. - -Note: Most of the time the `bashrc` file gets loaded automatically. However, if this doesn't apply to your setup, the following lines can add the required command to the end of your `Bash profile`. This will ensure that your `bashrc` file loads by default. - -```bash -cd ~ -echo 'source /home/user/.bashrc' >> ~/.bash_profile -``` - -> this depends on your operating system, please check foundry docs to see detailed instructions. - -## Wrapping Up - -And there we have it! Congratulations on installing Foundry and prepping your terminal to work seamlessly with it. Remember, hitting snags during installation is normal, especially if you're new to this. Don't hesitate to engage with the course community via GitHub if you run into issues. - -::image{src='/foundry/5-foundryinstall/foundryinstall2.png' style='width: 100%; height: auto;'} - -Here's to many hassle-free coding sessions with Foundry! From ca8d3897a39a65621793c8f90f6bc75d613b07c3 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:38:07 -0500 Subject: [PATCH 250/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/8-foundry-install/+page.md. --- .../8-foundry-install/+page.md | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/8-foundry-install/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/8-foundry-install/+page.md b/courses/foundry/1-foundry-simple-storage/8-foundry-install/+page.md new file mode 100644 index 000000000..2868dbb5a --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/8-foundry-install/+page.md @@ -0,0 +1,87 @@ +--- +title: Foundry Install +--- + +_Follow along the course with this video._ + + + +--- + +Welcome to this handy guide on installing and operating Foundry, a versatile tool that will add a new level of command-line ease to your developer journey. Whether you're running Windows, Linux or MacOS, we've got you covered with instructions and tips. So sit back, grab a cup of coffee, and let's dive in. + +## Prepping your Terminal + +First things first. Before we dive into installing Foundry, make sure you have your terminal set up correctly. + +If you are using Windows, you should see something like `WSL` or `Ubuntu`. Once you have your terminal environment ready, it’s time for some quick tips to help streamline your workflow. + +### Keeping your Terminal Clutter-free + +When commands pile up in your terminal, things can get a little overwhelming. Clear it up by simply typing `clear` and hitting `Enter`. Alternatively, use `Command K` if you're on a Mac or `Control K` if you're on Linux or Windows. + +**Pro tip:** This is one of my favorite keyboard shortcuts that I use all the time. + +### Understanding the Trash Can and the X + +::image{src='/foundry/5-foundryinstall/foundryinstall1.png' style='width: 100%; height: auto;'} + +The trash can and the X buttons in your terminal perform distinct functions. Hitting `X` simply hides your terminal but retains all the previous lines of code. On the other hand, trashing it essentially deletes whatever is running in it. To open up a clean terminal, hit the trash can and then pull it back using `Toggle` or `Terminal > New Terminal`. + +## Installing Foundry + +With our terminal set and some tips up our sleeve, let's progress to installing Foundry. Navigate to the [Foundry website](https://book.getfoundry.sh/getting-started/installation) and from the installation tab, fetch the command to install Foundry. + +The command would look something like this: + +```bash +curl -L https://foundry.paradigm.xyz | bash +``` + +Hit `Enter` after pasting this in your terminal. + +**Note:** You must have Internet access for this to work as it's downloading Foundry from their official website. + +## Verifying Your Installation + +After running the `curl` command, an output will appear at the bottom of your terminal indicating the detected shell and the fact that Foundry has been added to your `Path`. + +For instance, the output can be something like this: + +```bash +Detected your preferred shell is bashrc and added Foundry to Path run:source /home/user/.bashrcStart +a new terminal session to use Foundry +``` + +Now, simply type `foundryup` and `Enter` to install and update Foundry to the latest version. Whenever you want to install an update for Foundry, simply run `foundryup` again. + +This will install four components: forge, cast, anvil, and chisel. To confirm the successful installation, run `forge --version`. You should get an output indicating the Forge version as shown below. + +```bash +Forge version x.x.x +``` + +Now, here's something to remember: when you hit the trash can in the top right, it literally 'removes' the terminal. The X button, in contrast, simply hides it. + +### Is Foundry Up Not Running? + +Don't panic if this command doesn't run. You might have an issue with your path, and you might need to add Foundry to your path. In case you run into this issue, check lesson 6 of the GitHub repo associated with this course. If no debugging tips are available there, feel free to start a discussion on the course's GitHub repo. Before doing so, make sure to check if a similar discussion already exists. + +Try typing `forge --version` into your terminal. Have you received an unwelcome output saying `Forge command found`? This implies that you have to rerun the `source` command that Foundry offered during installation. + +Note: Most of the time the `bashrc` file gets loaded automatically. However, if this doesn't apply to your setup, the following lines can add the required command to the end of your `Bash profile`. This will ensure that your `bashrc` file loads by default. + +```bash +cd ~ +echo 'source /home/user/.bashrc' >> ~/.bash_profile +``` + +> this depends on your operating system, please check foundry docs to see detailed instructions. + +## Wrapping Up + +And there we have it! Congratulations on installing Foundry and prepping your terminal to work seamlessly with it. Remember, hitting snags during installation is normal, especially if you're new to this. Don't hesitate to engage with the course community via GitHub if you run into issues. + +::image{src='/foundry/5-foundryinstall/foundryinstall2.png' style='width: 100%; height: auto;'} + +Here's to many hassle-free coding sessions with Foundry! From 4b97d4582794e36bf20a35838fc0d15e4ce8790b Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:38:08 -0500 Subject: [PATCH 251/797] PatrickAlphaC removing file due to editing --- .../7-setup-your-vscode/+page.md | 67 ------------------- 1 file changed, 67 deletions(-) delete mode 100644 courses/foundry/1-foundry-simple-storage/7-setup-your-vscode/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/7-setup-your-vscode/+page.md b/courses/foundry/1-foundry-simple-storage/7-setup-your-vscode/+page.md deleted file mode 100644 index 48f14854c..000000000 --- a/courses/foundry/1-foundry-simple-storage/7-setup-your-vscode/+page.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: Setup your VSCode ---- - -_Follow along with this video:_ - ---- - -## VS Code setup - -### Installing VS Code extensions - -1. Open the Extensions view: - -There are two ways to do this: - -Click the Extensions icon in the Activity Bar on the left side of VS Code. - -Use the shortcut Ctrl+Shift+X (Windows/Linux) or Cmd+Shift+X (Mac). - -2. Browse or search for extensions: - -The Extensions view displays featured extensions by default. - -Use the search bar to find a specific extension by name. - -3. Install the extension: - -Once you've found the extension you want, click the "Install" button. -VS Code will handle the download and installation process. - -**That's it! The extension should be ready to use within VS Code.** - - -### Integrating AI into our work - -One of the best extensions that integrates AI in our development is GitHub Copilot - -Although it's a premium service, its intuitive AI-powered code autocomplete feature could be a game-changer for you. Of course, you can choose to go with other AI extensions based on your preferences. - -You can download GitHub Copilot [here](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot). More details and answers for your GitHub Copilot-related questions are available [here](https://github.com/features/copilot/?editor=vscode#faq). - - -### Other important VS Code Tips - -***Beware the white dot***, if you see it, your work is not saved, which means your project won't behave the way you want it to behave. - -```CTRL(CMD) + ` ```opens/closes your terminal. It's the equivalent of pressing the `X` button on the top right part of your terminal. - -The `trash can` button, on the left side of the `X` button destroys the terminal, make sure you always remember the difference between these two buttons. - -Hooray! This concludes the setup part of this course. Now we get to the fun part, actually developing a project using solidity and foundry. - - -### More setup ... - -Run the following commands in your terminal: - -``` -mkdir foundry-f23 -cd foundry-f23 -``` - -`mkdir` creates a directory or subdirectory. -`cd` changes the directory. - -Moving forward, it's advisable to keep all your repositories in this folder. Thus, you'll always have a place to reference all your code. From a47ac17685a2d596e326d0215f3fd15bf5a33fe1 Mon Sep 17 00:00:00 2001 From: PatrickAlphaC <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:38:09 -0500 Subject: [PATCH 252/797] PatrickAlphaC updated courses/foundry/1-foundry-simple-storage/9-setup-your-vscode/+page.md. --- .../9-setup-your-vscode/+page.md | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/9-setup-your-vscode/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/9-setup-your-vscode/+page.md b/courses/foundry/1-foundry-simple-storage/9-setup-your-vscode/+page.md new file mode 100644 index 000000000..48f14854c --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/9-setup-your-vscode/+page.md @@ -0,0 +1,67 @@ +--- +title: Setup your VSCode +--- + +_Follow along with this video:_ + +--- + +## VS Code setup + +### Installing VS Code extensions + +1. Open the Extensions view: + +There are two ways to do this: + +Click the Extensions icon in the Activity Bar on the left side of VS Code. + +Use the shortcut Ctrl+Shift+X (Windows/Linux) or Cmd+Shift+X (Mac). + +2. Browse or search for extensions: + +The Extensions view displays featured extensions by default. + +Use the search bar to find a specific extension by name. + +3. Install the extension: + +Once you've found the extension you want, click the "Install" button. +VS Code will handle the download and installation process. + +**That's it! The extension should be ready to use within VS Code.** + + +### Integrating AI into our work + +One of the best extensions that integrates AI in our development is GitHub Copilot + +Although it's a premium service, its intuitive AI-powered code autocomplete feature could be a game-changer for you. Of course, you can choose to go with other AI extensions based on your preferences. + +You can download GitHub Copilot [here](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot). More details and answers for your GitHub Copilot-related questions are available [here](https://github.com/features/copilot/?editor=vscode#faq). + + +### Other important VS Code Tips + +***Beware the white dot***, if you see it, your work is not saved, which means your project won't behave the way you want it to behave. + +```CTRL(CMD) + ` ```opens/closes your terminal. It's the equivalent of pressing the `X` button on the top right part of your terminal. + +The `trash can` button, on the left side of the `X` button destroys the terminal, make sure you always remember the difference between these two buttons. + +Hooray! This concludes the setup part of this course. Now we get to the fun part, actually developing a project using solidity and foundry. + + +### More setup ... + +Run the following commands in your terminal: + +``` +mkdir foundry-f23 +cd foundry-f23 +``` + +`mkdir` creates a directory or subdirectory. +`cd` changes the directory. + +Moving forward, it's advisable to keep all your repositories in this folder. Thus, you'll always have a place to reference all your code. From 5d41bbdc631e3e73b88d6d969be46ca526867776 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:47:34 -0700 Subject: [PATCH 253/797] Equious updated courses/moccasin-101/1-python-on-updraft/1-intro/+page.md. --- courses/moccasin-101/1-python-on-updraft/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/1-intro/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/1-intro/+page.md b/courses/moccasin-101/1-python-on-updraft/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 05248aca15ad4057667bd44ce5d68934367140ed Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:47:47 -0700 Subject: [PATCH 254/797] Equious updated courses/moccasin-101/1-python-on-updraft/10-math/+page.md. --- courses/moccasin-101/1-python-on-updraft/10-math/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/10-math/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/10-math/+page.md b/courses/moccasin-101/1-python-on-updraft/10-math/+page.md new file mode 100644 index 000000000..d246d700c --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/10-math/+page.md @@ -0,0 +1,3 @@ +--- + title: Math + --- \ No newline at end of file From 030a5b1475986a8c30152c84e15df2a25e171429 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:48:01 -0700 Subject: [PATCH 255/797] Equious updated courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md. --- courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md b/courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md new file mode 100644 index 000000000..52de64c11 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md @@ -0,0 +1,3 @@ +--- + title: More Math + --- \ No newline at end of file From a808104f98355acd147961e6313304e38ac27fbb Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:48:17 -0700 Subject: [PATCH 256/797] Equious updated courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md. --- courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md b/courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md new file mode 100644 index 000000000..125b3fa6b --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md @@ -0,0 +1,3 @@ +--- + title: Funcs + --- \ No newline at end of file From 2dea46ee42eb62af2e83284712c2aab5fe8a8b4e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:48:30 -0700 Subject: [PATCH 257/797] Equious updated courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md. --- .../moccasin-101/1-python-on-updraft/13-conditionals/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md b/courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md new file mode 100644 index 000000000..1d57c9ca3 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md @@ -0,0 +1,3 @@ +--- + title: Conditionals + --- \ No newline at end of file From 92b7e21afed309b9bcabed285f57bb346102b54f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:48:46 -0700 Subject: [PATCH 258/797] Equious updated courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md. --- .../moccasin-101/1-python-on-updraft/14-while-loops/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md b/courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md new file mode 100644 index 000000000..9e54beace --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md @@ -0,0 +1,3 @@ +--- + title: While Loops + --- \ No newline at end of file From 72bd327750efd19c557c8a5d5c7af703e7629720 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:48:59 -0700 Subject: [PATCH 259/797] Equious updated courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md. --- courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md b/courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md new file mode 100644 index 000000000..1633a4fcb --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md @@ -0,0 +1,3 @@ +--- + title: Loops 2 + --- \ No newline at end of file From 3cbf4d34831d0d0bcf46b614a6152d9cdb378068 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:49:14 -0700 Subject: [PATCH 260/797] Equious updated courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md. --- courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md b/courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md new file mode 100644 index 000000000..3e226d5ca --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md @@ -0,0 +1,3 @@ +--- + title: Loops 3 + --- \ No newline at end of file From 8626a66c28e40274c0168e75e48728054842aeea Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:49:28 -0700 Subject: [PATCH 261/797] Equious updated courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md. --- courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md b/courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 54c64964c5a33617814b9c0627233ac6d94a4c75 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:49:48 -0700 Subject: [PATCH 262/797] Equious updated courses/moccasin-101/1-python-on-updraft/18-recap/+page.md. --- courses/moccasin-101/1-python-on-updraft/18-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/18-recap/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/18-recap/+page.md b/courses/moccasin-101/1-python-on-updraft/18-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/18-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 67fd41de175404c1766d9b36b2a427bc02116ad3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:51:04 -0700 Subject: [PATCH 263/797] Equious updated courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md. --- .../moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md b/courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md new file mode 100644 index 000000000..82dee4ad0 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Dev Env Setup + --- \ No newline at end of file From 0b5fd8c566283a8ad6868660bcb428b20b2cb292 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:52:52 -0700 Subject: [PATCH 264/797] Equious updated courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md. --- .../moccasin-101/1-python-on-updraft/2-google-collab/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md b/courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md new file mode 100644 index 000000000..735bc3c07 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md @@ -0,0 +1,3 @@ +--- + title: Google Collab + --- \ No newline at end of file From 2a532496953e58f52542d2113b61c32cc4ab129c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:53:05 -0700 Subject: [PATCH 265/797] Equious updated courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md. --- .../1-python-on-updraft/20-install-vscode-macos-linux/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md b/courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md new file mode 100644 index 000000000..29e695218 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Vscode Macos Linux + --- \ No newline at end of file From 7b637a1cdc9013ae54d3e8c42c40b0a23cb555d5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:55:28 -0700 Subject: [PATCH 266/797] Equious updated courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md. --- .../moccasin-101/1-python-on-updraft/21-install-wsl/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md b/courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md new file mode 100644 index 000000000..475d38e9a --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Wsl + --- \ No newline at end of file From bced5c50d9e891aceaf70111f0d6e5d7f29a5a56 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 10:59:51 -0700 Subject: [PATCH 267/797] Equious updated courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md. --- .../1-python-on-updraft/22-vscode-windows-install/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md b/courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md new file mode 100644 index 000000000..a09ad1944 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Windows Install + --- \ No newline at end of file From 1c8acad16f459d2afaad9b5664a916faa069a366 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:00:15 -0700 Subject: [PATCH 268/797] Equious updated courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md. --- .../23-vscode-windows-wsl-extension/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md b/courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md new file mode 100644 index 000000000..2acc9a55f --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Windows Wsl Extension + --- \ No newline at end of file From 27bddd8eb893cd3329f790f0ef1d5f121be904f9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:00:31 -0700 Subject: [PATCH 269/797] Equious updated courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md. --- .../1-python-on-updraft/24-vscode-quickstart/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md b/courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md new file mode 100644 index 000000000..3ab104359 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Quickstart + --- \ No newline at end of file From 297026e628a8b4818d42fc99b684b9d4626ba76a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:00:49 -0700 Subject: [PATCH 270/797] Equious updated courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md. --- .../1-python-on-updraft/25-install-python-macos/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md b/courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md new file mode 100644 index 000000000..d2148949d --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Python Macos + --- \ No newline at end of file From 4dcad6bf2a46f089fae850a2d711029ee542b16b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:05:03 -0700 Subject: [PATCH 271/797] Equious updated courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md. --- .../1-python-on-updraft/26-install-python-wsl-linux/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md b/courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md new file mode 100644 index 000000000..d18275288 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Python Wsl Linux + --- \ No newline at end of file From 9e7f250699573b5705be30cac797f13851794650 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:05:35 -0700 Subject: [PATCH 272/797] Equious updated courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md. --- .../1-python-on-updraft/27-vscode-quickstart-2/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md b/courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md new file mode 100644 index 000000000..7d3ad9c57 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Quickstart 2 + --- \ No newline at end of file From 1a0e14059f2045a445af8bf8b156bfe9172e25bf Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:05:53 -0700 Subject: [PATCH 273/797] Equious updated courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md. --- .../moccasin-101/1-python-on-updraft/28-mental-prep/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md b/courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md new file mode 100644 index 000000000..cfcec4377 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md @@ -0,0 +1,3 @@ +--- + title: Mental Prep + --- \ No newline at end of file From 817bb18396fb79520928b6ebfe4715c74af16af6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:06:07 -0700 Subject: [PATCH 274/797] Equious updated courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md. --- courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md b/courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md new file mode 100644 index 000000000..8c591a536 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md @@ -0,0 +1,3 @@ +--- + title: Local Py + --- \ No newline at end of file From d713f142585b13fdf5bcc1a3047cd4a919fb78de Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:06:26 -0700 Subject: [PATCH 275/797] Equious updated courses/moccasin-101/1-python-on-updraft/3-setup/+page.md. --- courses/moccasin-101/1-python-on-updraft/3-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/3-setup/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/3-setup/+page.md b/courses/moccasin-101/1-python-on-updraft/3-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/3-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From 57a7fed867d9f8635718f2f0c7069fe4dbbf194b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:06:42 -0700 Subject: [PATCH 276/797] Equious updated courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md. --- .../moccasin-101/1-python-on-updraft/30-python-shell/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md b/courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md new file mode 100644 index 000000000..9c47c3f3e --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md @@ -0,0 +1,3 @@ +--- + title: Python Shell + --- \ No newline at end of file From 77fa6df748dee4170dd99ccc652779f7c37b39de Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:06:56 -0700 Subject: [PATCH 277/797] Equious updated courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md. --- .../1-python-on-updraft/31-python-extensions-vscode/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md b/courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md new file mode 100644 index 000000000..85f6eb88c --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md @@ -0,0 +1,3 @@ +--- + title: Python Extensions Vscode + --- \ No newline at end of file From c3e5acc34797207c02777fd7528f04030f294c52 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:07:10 -0700 Subject: [PATCH 278/797] Equious updated courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md. --- .../1-python-on-updraft/32-our-first-python/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md b/courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md new file mode 100644 index 000000000..f790b0411 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md @@ -0,0 +1,3 @@ +--- + title: Our First Python + --- \ No newline at end of file From 2be819cc2130f019943a7075ec9954cbb9d9d50b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:08:51 -0700 Subject: [PATCH 279/797] Equious updated courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md. --- .../1-python-on-updraft/33-python-imports/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md b/courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md new file mode 100644 index 000000000..fae7a0f96 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md @@ -0,0 +1,3 @@ +--- + title: Python Imports + --- \ No newline at end of file From d2b6434bf706c9f3b6c1eaeb693407199442ade9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:09:05 -0700 Subject: [PATCH 280/797] Equious updated courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md. --- .../moccasin-101/1-python-on-updraft/34-installing-uv/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md b/courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md new file mode 100644 index 000000000..ef00c9919 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md @@ -0,0 +1,3 @@ +--- + title: Installing Uv + --- \ No newline at end of file From c6bdbfc5f9d652be36bb8c8f6c5044d655c7ae7d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:09:35 -0700 Subject: [PATCH 281/797] Equious updated courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md. --- .../1-python-on-updraft/35-uv-python-version/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md b/courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md new file mode 100644 index 000000000..84d31ea64 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md @@ -0,0 +1,3 @@ +--- + title: Uv Python Version + --- \ No newline at end of file From 19fcc335644646f3947d4aaeee1110b464fee7a0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:09:49 -0700 Subject: [PATCH 282/797] Equious updated courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md. --- .../1-python-on-updraft/36-adding-packages-uv/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md b/courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md new file mode 100644 index 000000000..d2268f193 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md @@ -0,0 +1,3 @@ +--- + title: Adding Packages Uv + --- \ No newline at end of file From 6bae5f61aa3e6c4e2fd530f0102da3a48c84f805 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:10:04 -0700 Subject: [PATCH 283/797] Equious updated courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md. --- .../moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md b/courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md new file mode 100644 index 000000000..c211b8e01 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md @@ -0,0 +1,3 @@ +--- + title: Virtual Envs + --- \ No newline at end of file From 018c8138b4c613c6a43e5072533cc7fd7a736ba9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:13:18 -0700 Subject: [PATCH 284/797] Equious updated courses/moccasin-101/1-python-on-updraft/38-recap/+page.md. --- courses/moccasin-101/1-python-on-updraft/38-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/38-recap/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/38-recap/+page.md b/courses/moccasin-101/1-python-on-updraft/38-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/38-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From c1f44d0c236ae3afa663b2ff837f35da4101e900 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:13:32 -0700 Subject: [PATCH 285/797] Equious updated courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md. --- courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md b/courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md new file mode 100644 index 000000000..e4cab53fa --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md @@ -0,0 +1,3 @@ +--- + title: Notebook + --- \ No newline at end of file From c985e7ea6d6ed6bca44995e4606fd3e829fa352e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:13:45 -0700 Subject: [PATCH 286/797] Equious updated courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md. --- courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md b/courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md new file mode 100644 index 000000000..faa0a0f12 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md @@ -0,0 +1,3 @@ +--- + title: Google Ai + --- \ No newline at end of file From d0cff4b9c766ce5580820d1ef09f28a777c792de Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:13:58 -0700 Subject: [PATCH 287/797] Equious updated courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md. --- .../moccasin-101/1-python-on-updraft/6-python-vars/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md b/courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md new file mode 100644 index 000000000..9d8367c72 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md @@ -0,0 +1,3 @@ +--- + title: Python Vars + --- \ No newline at end of file From ffeca78e9c3db86ecd28a64b19e69dc9fe617852 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:14:11 -0700 Subject: [PATCH 288/797] Equious updated courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md. --- courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md b/courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md new file mode 100644 index 000000000..3f01df5ef --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md @@ -0,0 +1,3 @@ +--- + title: Type Hints + --- \ No newline at end of file From ca315392716a17d836fd383be6c6589cd677bf3c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:14:27 -0700 Subject: [PATCH 289/797] Equious updated courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md. --- courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md b/courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md new file mode 100644 index 000000000..267733150 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md @@ -0,0 +1,3 @@ +--- + title: Arrays + --- \ No newline at end of file From 76b65bbd9f0e8cb0bd617a311c8445dc3c0797ef Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:14:40 -0700 Subject: [PATCH 290/797] Equious updated courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md. --- courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md b/courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md new file mode 100644 index 000000000..8a90dbef7 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md @@ -0,0 +1,3 @@ +--- + title: Inputs + --- \ No newline at end of file From e781bcf43665ee9372649f8f5b0a3ae1e7937c2d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:14:54 -0700 Subject: [PATCH 291/797] Equious updated courses/moccasin-101/1-python-on-updraft/9-types/+page.md. --- courses/moccasin-101/1-python-on-updraft/9-types/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-on-updraft/9-types/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/9-types/+page.md b/courses/moccasin-101/1-python-on-updraft/9-types/+page.md new file mode 100644 index 000000000..c6210ebf1 --- /dev/null +++ b/courses/moccasin-101/1-python-on-updraft/9-types/+page.md @@ -0,0 +1,3 @@ +--- + title: Types + --- \ No newline at end of file From d11637851ede5286b004f77cc4a7953195df4039 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:17:44 -0700 Subject: [PATCH 292/797] Equious updated courses/moccasin-101/2-web3py/1-intro/+page.md. --- courses/moccasin-101/2-web3py/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/1-intro/+page.md diff --git a/courses/moccasin-101/2-web3py/1-intro/+page.md b/courses/moccasin-101/2-web3py/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/2-web3py/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 8bbf7f1424284b4fc4c879a37c10a35a279734e9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:17:58 -0700 Subject: [PATCH 293/797] Equious updated courses/moccasin-101/2-web3py/18-pkey-promise/+page.md. --- courses/moccasin-101/2-web3py/18-pkey-promise/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/18-pkey-promise/+page.md diff --git a/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md b/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md new file mode 100644 index 000000000..08c6274da --- /dev/null +++ b/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md @@ -0,0 +1,3 @@ +--- + title: Pkey Promise + --- \ No newline at end of file From afa8d00db35ecaa4ebb35979b8d95795d399a38f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:18:13 -0700 Subject: [PATCH 294/797] Equious updated courses/moccasin-101/2-web3py/19-env-vars/+page.md. --- courses/moccasin-101/2-web3py/19-env-vars/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/19-env-vars/+page.md diff --git a/courses/moccasin-101/2-web3py/19-env-vars/+page.md b/courses/moccasin-101/2-web3py/19-env-vars/+page.md new file mode 100644 index 000000000..e97071bde --- /dev/null +++ b/courses/moccasin-101/2-web3py/19-env-vars/+page.md @@ -0,0 +1,3 @@ +--- + title: Env Vars + --- \ No newline at end of file From ea77a9815323cf4c385acbc153203b6c5871c3e0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:18:27 -0700 Subject: [PATCH 295/797] Equious updated courses/moccasin-101/2-web3py/2-setup/+page.md. --- courses/moccasin-101/2-web3py/2-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/2-setup/+page.md diff --git a/courses/moccasin-101/2-web3py/2-setup/+page.md b/courses/moccasin-101/2-web3py/2-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/2-web3py/2-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From fdc794e4eae79560be6b11be81023fc4b002bb2b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:18:42 -0700 Subject: [PATCH 296/797] Equious updated courses/moccasin-101/2-web3py/20-send-tx/+page.md. --- courses/moccasin-101/2-web3py/20-send-tx/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/20-send-tx/+page.md diff --git a/courses/moccasin-101/2-web3py/20-send-tx/+page.md b/courses/moccasin-101/2-web3py/20-send-tx/+page.md new file mode 100644 index 000000000..5b4867baa --- /dev/null +++ b/courses/moccasin-101/2-web3py/20-send-tx/+page.md @@ -0,0 +1,3 @@ +--- + title: Send Tx + --- \ No newline at end of file From d8cd7f25f9d34795e285886b37e1c66d0182512c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:19:33 -0700 Subject: [PATCH 297/797] Equious updated courses/moccasin-101/2-web3py/21-encrypt/+page.md. --- courses/moccasin-101/2-web3py/21-encrypt/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/21-encrypt/+page.md diff --git a/courses/moccasin-101/2-web3py/21-encrypt/+page.md b/courses/moccasin-101/2-web3py/21-encrypt/+page.md new file mode 100644 index 000000000..56ef26d1d --- /dev/null +++ b/courses/moccasin-101/2-web3py/21-encrypt/+page.md @@ -0,0 +1,3 @@ +--- + title: Encrypt + --- \ No newline at end of file From 44d21994af3e3252b1cdeabd16e56fa37251b0bd Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:19:49 -0700 Subject: [PATCH 298/797] Equious updated courses/moccasin-101/2-web3py/22-decrypt/+page.md. --- courses/moccasin-101/2-web3py/22-decrypt/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/22-decrypt/+page.md diff --git a/courses/moccasin-101/2-web3py/22-decrypt/+page.md b/courses/moccasin-101/2-web3py/22-decrypt/+page.md new file mode 100644 index 000000000..19a99651f --- /dev/null +++ b/courses/moccasin-101/2-web3py/22-decrypt/+page.md @@ -0,0 +1,3 @@ +--- + title: Decrypt + --- \ No newline at end of file From 4c0b1c4131c08f4ba708e019a6b4c6894dda65b0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:23:33 -0700 Subject: [PATCH 299/797] Equious updated courses/moccasin-101/2-web3py/23-pledge/+page.md. --- courses/moccasin-101/2-web3py/23-pledge/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/23-pledge/+page.md diff --git a/courses/moccasin-101/2-web3py/23-pledge/+page.md b/courses/moccasin-101/2-web3py/23-pledge/+page.md new file mode 100644 index 000000000..dea23512b --- /dev/null +++ b/courses/moccasin-101/2-web3py/23-pledge/+page.md @@ -0,0 +1,3 @@ +--- + title: Pledge + --- \ No newline at end of file From 6728c48fd093fc6a6653154ce3d9d4bf581cb783 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:23:55 -0700 Subject: [PATCH 300/797] Equious updated courses/moccasin-101/2-web3py/24-workshop/+page.md. --- courses/moccasin-101/2-web3py/24-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/24-workshop/+page.md diff --git a/courses/moccasin-101/2-web3py/24-workshop/+page.md b/courses/moccasin-101/2-web3py/24-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/2-web3py/24-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 47148d039d46ebf42097588aa7b27aa18cdbc4ad Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:27:29 -0700 Subject: [PATCH 301/797] Equious updated courses/moccasin-101/2-web3py/25-recap/+page.md. --- courses/moccasin-101/2-web3py/25-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/25-recap/+page.md diff --git a/courses/moccasin-101/2-web3py/25-recap/+page.md b/courses/moccasin-101/2-web3py/25-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/2-web3py/25-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 3704ddea67707c660614bd9ec0ae1b3d48c74069 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:27:42 -0700 Subject: [PATCH 302/797] Equious updated courses/moccasin-101/2-web3py/3-vyper-extension/+page.md. --- courses/moccasin-101/2-web3py/3-vyper-extension/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/3-vyper-extension/+page.md diff --git a/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md b/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md new file mode 100644 index 000000000..e1b9b773a --- /dev/null +++ b/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md @@ -0,0 +1,3 @@ +--- + title: Vyper Extension + --- \ No newline at end of file From d4fb2d317d8c41cbbea2c7b16553ced81b9b6b84 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:30:34 -0700 Subject: [PATCH 303/797] Equious updated courses/moccasin-101/3-boa-favs/1-intro/+page.md. --- courses/moccasin-101/3-boa-favs/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/1-intro/+page.md diff --git a/courses/moccasin-101/3-boa-favs/1-intro/+page.md b/courses/moccasin-101/3-boa-favs/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From ee0a74797486b8042f9912a4b838ff09a71e79ad Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:31:01 -0700 Subject: [PATCH 304/797] Equious updated courses/moccasin-101/3-boa-favs/10-add-person/+page.md. --- courses/moccasin-101/3-boa-favs/10-add-person/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/10-add-person/+page.md diff --git a/courses/moccasin-101/3-boa-favs/10-add-person/+page.md b/courses/moccasin-101/3-boa-favs/10-add-person/+page.md new file mode 100644 index 000000000..ec6f71030 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/10-add-person/+page.md @@ -0,0 +1,3 @@ +--- + title: Add Person + --- \ No newline at end of file From 2407022ed6db46b29675d4bffba81e52c2d0c59c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:31:22 -0700 Subject: [PATCH 305/797] Equious updated courses/moccasin-101/3-boa-favs/11-workshop/+page.md. --- courses/moccasin-101/3-boa-favs/11-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/11-workshop/+page.md diff --git a/courses/moccasin-101/3-boa-favs/11-workshop/+page.md b/courses/moccasin-101/3-boa-favs/11-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/11-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 0a9ad2c0d305c60b31380534a977f7375bda1cb6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:34:36 -0700 Subject: [PATCH 306/797] Equious updated courses/moccasin-101/3-boa-favs/12-recap/+page.md. --- courses/moccasin-101/3-boa-favs/12-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/12-recap/+page.md diff --git a/courses/moccasin-101/3-boa-favs/12-recap/+page.md b/courses/moccasin-101/3-boa-favs/12-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/12-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 76738903d59d96b35582a68fa6d3cc53923f74ff Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:34:50 -0700 Subject: [PATCH 307/797] Equious updated courses/moccasin-101/3-boa-favs/2-setup/+page.md. --- courses/moccasin-101/3-boa-favs/2-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/2-setup/+page.md diff --git a/courses/moccasin-101/3-boa-favs/2-setup/+page.md b/courses/moccasin-101/3-boa-favs/2-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/2-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From ac19d74f541c99bb92f66104fc3eeb95acd7d146 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:35:16 -0700 Subject: [PATCH 308/797] Equious updated courses/moccasin-101/3-boa-favs/3-pyevm/+page.md. --- courses/moccasin-101/3-boa-favs/3-pyevm/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/3-pyevm/+page.md diff --git a/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md b/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md new file mode 100644 index 000000000..cbbb50791 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md @@ -0,0 +1,3 @@ +--- + title: Pyevm + --- \ No newline at end of file From bac511e2176663e39d227625ace75d2dbf294097 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:35:30 -0700 Subject: [PATCH 309/797] Equious updated courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md. --- courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md diff --git a/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md b/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md new file mode 100644 index 000000000..51f4c8a80 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md @@ -0,0 +1,3 @@ +--- + title: Vypercontract + --- \ No newline at end of file From e608268c4cadb0715c6f603f230655f760b5bf24 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:35:45 -0700 Subject: [PATCH 310/797] Equious updated courses/moccasin-101/3-boa-favs/5-debug/+page.md. --- courses/moccasin-101/3-boa-favs/5-debug/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/5-debug/+page.md diff --git a/courses/moccasin-101/3-boa-favs/5-debug/+page.md b/courses/moccasin-101/3-boa-favs/5-debug/+page.md new file mode 100644 index 000000000..746a037b4 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/5-debug/+page.md @@ -0,0 +1,3 @@ +--- + title: Debug + --- \ No newline at end of file From bb116fb6b01ac2862565270f2581b01bfd3b0ba4 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:35:59 -0700 Subject: [PATCH 311/797] Equious updated courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md. --- courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md diff --git a/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md b/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md new file mode 100644 index 000000000..5f76de142 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md @@ -0,0 +1,3 @@ +--- + title: Pyevm_ + --- \ No newline at end of file From 050ef42d744236dea7894b7ae2dcf95bf907488c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:36:25 -0700 Subject: [PATCH 312/797] Equious updated courses/moccasin-101/3-boa-favs/7-anvil/+page.md. --- courses/moccasin-101/3-boa-favs/7-anvil/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/7-anvil/+page.md diff --git a/courses/moccasin-101/3-boa-favs/7-anvil/+page.md b/courses/moccasin-101/3-boa-favs/7-anvil/+page.md new file mode 100644 index 000000000..0c0a4fdfe --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/7-anvil/+page.md @@ -0,0 +1,3 @@ +--- + title: Anvil + --- \ No newline at end of file From 40d4b09d4d4e2582e239774d9a8bd517eb32eac7 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:36:39 -0700 Subject: [PATCH 313/797] Equious updated courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md. --- courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md diff --git a/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md b/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md new file mode 100644 index 000000000..85923930c --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md @@ -0,0 +1,3 @@ +--- + title: Interacting Anvil + --- \ No newline at end of file From 0bc3d025532dc024609f595fd075a449c059ba6f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:37:06 -0700 Subject: [PATCH 314/797] Equious updated courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md. --- courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md diff --git a/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md b/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md new file mode 100644 index 000000000..87d3f90ba --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md @@ -0,0 +1,3 @@ +--- + title: Interact Prevs + --- \ No newline at end of file From 277080ad9ce1fb9bd10f9771ae08b9cffa551b1b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:37:34 -0700 Subject: [PATCH 315/797] Equious updated courses/moccasin-101/4-mox-favs/1-intro/+page.md. --- courses/moccasin-101/4-mox-favs/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/1-intro/+page.md diff --git a/courses/moccasin-101/4-mox-favs/1-intro/+page.md b/courses/moccasin-101/4-mox-favs/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 4d23e1c368101f5d99ad610614b4a79d7d3a9f49 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:40:35 -0700 Subject: [PATCH 316/797] Equious updated courses/moccasin-101/4-mox-favs/10-account-cli/+page.md. --- courses/moccasin-101/4-mox-favs/10-account-cli/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/10-account-cli/+page.md diff --git a/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md b/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md new file mode 100644 index 000000000..0984dc172 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md @@ -0,0 +1,3 @@ +--- + title: Account Cli + --- \ No newline at end of file From e272532cbeef8d3e6c97675ba55e33d574660b99 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:40:49 -0700 Subject: [PATCH 317/797] Equious updated courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md. --- courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md diff --git a/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md b/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md new file mode 100644 index 000000000..7cc9872a4 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Testing + --- \ No newline at end of file From 0e8975a307c50d37dd87d4f60e5b488126ca8e0d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:41:04 -0700 Subject: [PATCH 318/797] Equious updated courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md. --- .../moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md diff --git a/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md b/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md new file mode 100644 index 000000000..19850ca6b --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md @@ -0,0 +1,3 @@ +--- + title: Testing Deploy Script + --- \ No newline at end of file From 04e6953cb1a990f8f4f10f1c59deef328b55b080 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:41:18 -0700 Subject: [PATCH 319/797] Equious updated courses/moccasin-101/4-mox-favs/13-aaa/+page.md. --- courses/moccasin-101/4-mox-favs/13-aaa/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/13-aaa/+page.md diff --git a/courses/moccasin-101/4-mox-favs/13-aaa/+page.md b/courses/moccasin-101/4-mox-favs/13-aaa/+page.md new file mode 100644 index 000000000..ff929f638 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/13-aaa/+page.md @@ -0,0 +1,3 @@ +--- + title: Aaa + --- \ No newline at end of file From 8e2f6237fc6ce5741885b6be9d653926ae7387ba Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:41:44 -0700 Subject: [PATCH 320/797] Equious updated courses/moccasin-101/4-mox-favs/14-fixtures/+page.md. --- courses/moccasin-101/4-mox-favs/14-fixtures/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/14-fixtures/+page.md diff --git a/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md b/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md new file mode 100644 index 000000000..48ccb103c --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md @@ -0,0 +1,3 @@ +--- + title: Fixtures + --- \ No newline at end of file From 1c95f1acd1497f7fdd4895faafab4ee0ab83e3de Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:42:02 -0700 Subject: [PATCH 321/797] Equious updated courses/moccasin-101/4-mox-favs/15-conftest/+page.md. --- courses/moccasin-101/4-mox-favs/15-conftest/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/15-conftest/+page.md diff --git a/courses/moccasin-101/4-mox-favs/15-conftest/+page.md b/courses/moccasin-101/4-mox-favs/15-conftest/+page.md new file mode 100644 index 000000000..d47333a69 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/15-conftest/+page.md @@ -0,0 +1,3 @@ +--- + title: Conftest + --- \ No newline at end of file From a9b2fd94bb71f4c6e9209b2f092ef5a1909f916a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:48:52 -0700 Subject: [PATCH 322/797] Equious updated courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md. --- courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md diff --git a/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md b/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md new file mode 100644 index 000000000..ad5a0b3ab --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md @@ -0,0 +1,3 @@ +--- + title: Sepolia Deploy + --- \ No newline at end of file From 0bb20e5a5d004c1fabb4ad59fa1001dd5275b55f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:49:05 -0700 Subject: [PATCH 323/797] Equious updated courses/moccasin-101/4-mox-favs/18-verify/+page.md. --- courses/moccasin-101/4-mox-favs/18-verify/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/18-verify/+page.md diff --git a/courses/moccasin-101/4-mox-favs/18-verify/+page.md b/courses/moccasin-101/4-mox-favs/18-verify/+page.md new file mode 100644 index 000000000..0878aa404 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/18-verify/+page.md @@ -0,0 +1,3 @@ +--- + title: Verify + --- \ No newline at end of file From 2c9ea475e847d92c65c52edabac499cc47594348 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 11:59:45 -0700 Subject: [PATCH 324/797] Equious updated courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md. --- courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md diff --git a/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md b/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md new file mode 100644 index 000000000..e03eaddb9 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync Setup + --- \ No newline at end of file From c5ed8f1a15c1f425948fadae153bfe2ee1fb336e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:00:01 -0700 Subject: [PATCH 325/797] Equious updated courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md. --- courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md diff --git a/courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md b/courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md new file mode 100644 index 000000000..a4d6415c2 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md @@ -0,0 +1,3 @@ +--- + title: Instlal Mox + --- \ No newline at end of file From 061332dc59b47ce1abc0ec7bf7e9818c981ccafa Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:02:55 -0700 Subject: [PATCH 326/797] Equious updated courses/moccasin-101/4-mox-favs/20-eravm/+page.md. --- courses/moccasin-101/4-mox-favs/20-eravm/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/20-eravm/+page.md diff --git a/courses/moccasin-101/4-mox-favs/20-eravm/+page.md b/courses/moccasin-101/4-mox-favs/20-eravm/+page.md new file mode 100644 index 000000000..fef1da72f --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/20-eravm/+page.md @@ -0,0 +1,3 @@ +--- + title: Eravm + --- \ No newline at end of file From 6a6d54323de044e28a9095f9add4e04a8a3fc04f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:03:23 -0700 Subject: [PATCH 327/797] Equious updated courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md. --- courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md diff --git a/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md b/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md new file mode 100644 index 000000000..a515e5e34 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md @@ -0,0 +1,3 @@ +--- + title: Setting Up Zksync + --- \ No newline at end of file From 355023064c02db5fc5cf11dd8ef995a96843cfc2 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:03:37 -0700 Subject: [PATCH 328/797] Equious updated courses/moccasin-101/4-mox-favs/22-bridging/+page.md. --- courses/moccasin-101/4-mox-favs/22-bridging/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/22-bridging/+page.md diff --git a/courses/moccasin-101/4-mox-favs/22-bridging/+page.md b/courses/moccasin-101/4-mox-favs/22-bridging/+page.md new file mode 100644 index 000000000..1b24a95e4 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/22-bridging/+page.md @@ -0,0 +1,3 @@ +--- + title: Bridging + --- \ No newline at end of file From 65427870b445720af9dcb30ef3ecc6a8159baa1e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:05:35 -0700 Subject: [PATCH 329/797] Equious updated courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md. --- courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md diff --git a/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md b/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md new file mode 100644 index 000000000..ef6567697 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync Deploy + --- \ No newline at end of file From 276b6648b0affc43b64d34155051a6c827b74bb6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:06:05 -0700 Subject: [PATCH 330/797] Equious updated courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md. --- .../4-mox-favs/24-zksync-contract-deployment/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md diff --git a/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md b/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md new file mode 100644 index 000000000..7676d99dc --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync Contract Deployment + --- \ No newline at end of file From 0af46f56cb9efb3e13a52fd04fad528128469464 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:08:14 -0700 Subject: [PATCH 331/797] Equious updated courses/moccasin-101/4-mox-favs/25-tx-types/+page.md. --- courses/moccasin-101/4-mox-favs/25-tx-types/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/25-tx-types/+page.md diff --git a/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md b/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md new file mode 100644 index 000000000..e465b90e1 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md @@ -0,0 +1,3 @@ +--- + title: Tx Types + --- \ No newline at end of file From 275f7214d425daf21bdee76985917480857ee4e3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:11:39 -0700 Subject: [PATCH 332/797] Equious updated courses/moccasin-101/4-mox-favs/26-workshop/+page.md. --- courses/moccasin-101/4-mox-favs/26-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/26-workshop/+page.md diff --git a/courses/moccasin-101/4-mox-favs/26-workshop/+page.md b/courses/moccasin-101/4-mox-favs/26-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/26-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 06ee6038a62124cbff1b5d1fe7a68e30e65c0b8a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:12:04 -0700 Subject: [PATCH 333/797] Equious updated courses/moccasin-101/4-mox-favs/3-create-mox/+page.md. --- courses/moccasin-101/4-mox-favs/3-create-mox/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/3-create-mox/+page.md diff --git a/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md b/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md new file mode 100644 index 000000000..0f542f929 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md @@ -0,0 +1,3 @@ +--- + title: Create Mox + --- \ No newline at end of file From ab1a8b49c3a5dd6319376381b14a89d9be7bfcf8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:12:18 -0700 Subject: [PATCH 334/797] Equious updated courses/moccasin-101/4-mox-favs/4-mox-something/+page.md. --- courses/moccasin-101/4-mox-favs/4-mox-something/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/4-mox-something/+page.md diff --git a/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md b/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md new file mode 100644 index 000000000..e56710475 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Something + --- \ No newline at end of file From 87944f7d9059b1f90adf886c91984246870ac097 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:12:34 -0700 Subject: [PATCH 335/797] Equious updated courses/moccasin-101/4-mox-favs/5-mox-script/+page.md. --- courses/moccasin-101/4-mox-favs/5-mox-script/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/5-mox-script/+page.md diff --git a/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md b/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md new file mode 100644 index 000000000..9b8bba199 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Script + --- \ No newline at end of file From d398b8cbf4de4e0246b318f3c1d028aa9fb8c84d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:12:47 -0700 Subject: [PATCH 336/797] Equious updated courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md. --- courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md diff --git a/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md b/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md new file mode 100644 index 000000000..7ab4c1ff8 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md @@ -0,0 +1,3 @@ +--- + title: Encrypt Key + --- \ No newline at end of file From b5a4ea4b7048de844e06e89b6fa57474d4dfb14a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:13:01 -0700 Subject: [PATCH 337/797] Equious updated courses/moccasin-101/4-mox-favs/8-shell/+page.md. --- courses/moccasin-101/4-mox-favs/8-shell/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/8-shell/+page.md diff --git a/courses/moccasin-101/4-mox-favs/8-shell/+page.md b/courses/moccasin-101/4-mox-favs/8-shell/+page.md new file mode 100644 index 000000000..00df35f0d --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/8-shell/+page.md @@ -0,0 +1,3 @@ +--- + title: Shell + --- \ No newline at end of file From 75e27d9b662bb5e6ba755331af9871a41654faf2 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:13:15 -0700 Subject: [PATCH 338/797] Equious updated courses/moccasin-101/4-mox-favs/9-using-key/+page.md. --- courses/moccasin-101/4-mox-favs/9-using-key/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/9-using-key/+page.md diff --git a/courses/moccasin-101/4-mox-favs/9-using-key/+page.md b/courses/moccasin-101/4-mox-favs/9-using-key/+page.md new file mode 100644 index 000000000..dd0adc820 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/9-using-key/+page.md @@ -0,0 +1,3 @@ +--- + title: Using Key + --- \ No newline at end of file From 0932a3e71766cb6abc7315a1e5448767f73f6c02 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:14:52 -0700 Subject: [PATCH 339/797] Equious updated courses/moccasin-101/5-mox-five/1-intro/+page.md. --- courses/moccasin-101/5-mox-five/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/1-intro/+page.md diff --git a/courses/moccasin-101/5-mox-five/1-intro/+page.md b/courses/moccasin-101/5-mox-five/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 2edd3bb86b98494821a72c635be988fff67d25e0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:18:44 -0700 Subject: [PATCH 340/797] Equious updated courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md. --- .../5-mox-five/11-initializes-module-state/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md diff --git a/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md b/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md new file mode 100644 index 000000000..7096200f7 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md @@ -0,0 +1,3 @@ +--- + title: Initializes Module State + --- \ No newline at end of file From 1c42f54cb5809d2e6e59cd6851d8dcd26a444965 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:20:21 -0700 Subject: [PATCH 341/797] Equious updated courses/moccasin-101/5-mox-five/13-workshop/+page.md. --- courses/moccasin-101/5-mox-five/13-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/13-workshop/+page.md diff --git a/courses/moccasin-101/5-mox-five/13-workshop/+page.md b/courses/moccasin-101/5-mox-five/13-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/13-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 472d935a5f82eda3a3b5a4f1560dae1eb2e4fb86 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:22:14 -0700 Subject: [PATCH 342/797] Equious updated courses/moccasin-101/5-mox-five/14-recap/+page.md. --- courses/moccasin-101/5-mox-five/14-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/14-recap/+page.md diff --git a/courses/moccasin-101/5-mox-five/14-recap/+page.md b/courses/moccasin-101/5-mox-five/14-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/5-mox-five/14-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From f9e599ecc4c55fe9bf71211ead40fd303fdfd8ad Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:25:14 -0700 Subject: [PATCH 343/797] Equious updated courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md. --- courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md diff --git a/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md b/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md new file mode 100644 index 000000000..a391afc59 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md @@ -0,0 +1,3 @@ +--- + title: Create Copy Of + --- \ No newline at end of file From 3d212406025ad48218d60a4cd2da1e72a1fa4253 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:25:40 -0700 Subject: [PATCH 344/797] Equious updated courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md. --- courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md diff --git a/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md b/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md new file mode 100644 index 000000000..e5dcc0071 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md @@ -0,0 +1,3 @@ +--- + title: Static Ext Call + --- \ No newline at end of file From f8ef56a4b2725cdadc38c20911287f76944a4429 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:26:22 -0700 Subject: [PATCH 345/797] Equious updated courses/moccasin-101/5-mox-five/5-vyi/+page.md. --- courses/moccasin-101/5-mox-five/5-vyi/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/5-vyi/+page.md diff --git a/courses/moccasin-101/5-mox-five/5-vyi/+page.md b/courses/moccasin-101/5-mox-five/5-vyi/+page.md new file mode 100644 index 000000000..62bd446ed --- /dev/null +++ b/courses/moccasin-101/5-mox-five/5-vyi/+page.md @@ -0,0 +1,3 @@ +--- + title: Vyi + --- \ No newline at end of file From badae5a7aeed4cc488cc6d07d8c1dc1e2be2f99f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:26:48 -0700 Subject: [PATCH 346/797] Equious updated courses/moccasin-101/5-mox-five/6-idk/+page.md. --- courses/moccasin-101/5-mox-five/6-idk/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/6-idk/+page.md diff --git a/courses/moccasin-101/5-mox-five/6-idk/+page.md b/courses/moccasin-101/5-mox-five/6-idk/+page.md new file mode 100644 index 000000000..d226208fe --- /dev/null +++ b/courses/moccasin-101/5-mox-five/6-idk/+page.md @@ -0,0 +1,3 @@ +--- + title: Idk + --- \ No newline at end of file From c65f0afb2be7478ff1373755e6c6641780bc9c6e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:27:02 -0700 Subject: [PATCH 347/797] Equious updated courses/moccasin-101/5-mox-five/7-extcall/+page.md. --- courses/moccasin-101/5-mox-five/7-extcall/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/7-extcall/+page.md diff --git a/courses/moccasin-101/5-mox-five/7-extcall/+page.md b/courses/moccasin-101/5-mox-five/7-extcall/+page.md new file mode 100644 index 000000000..36c841a81 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/7-extcall/+page.md @@ -0,0 +1,3 @@ +--- + title: Extcall + --- \ No newline at end of file From 9274e8b31546e6d520aa2015cd0cf9e2645f78ef Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:27:19 -0700 Subject: [PATCH 348/797] Equious updated courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md. --- .../5-mox-five/8-store-contract-by-interface/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md diff --git a/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md b/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md new file mode 100644 index 000000000..d79d0e7af --- /dev/null +++ b/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md @@ -0,0 +1,3 @@ +--- + title: Store Contract By Interface + --- \ No newline at end of file From 57d37d4e1f173e57a5e05f48a98cc4c6458d969a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:27:45 -0700 Subject: [PATCH 349/797] Equious updated courses/moccasin-101/5-mox-five/9-method-chaining/+page.md. --- courses/moccasin-101/5-mox-five/9-method-chaining/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/9-method-chaining/+page.md diff --git a/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md b/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md new file mode 100644 index 000000000..2aa8fbe12 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md @@ -0,0 +1,3 @@ +--- + title: Method Chaining + --- \ No newline at end of file From e210435b68d3f86bbbb738ab6dad30413504563a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:30:35 -0700 Subject: [PATCH 350/797] Equious updated courses/moccasin-101/6-mox-coffee/1-intro/+page.md. --- courses/moccasin-101/6-mox-coffee/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/1-intro/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/1-intro/+page.md b/courses/moccasin-101/6-mox-coffee/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 29b5bda1d69590c11fb8aebb55393758938ad597 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:32:12 -0700 Subject: [PATCH 351/797] Equious updated courses/moccasin-101/6-mox-coffee/10-kinds/+page.md. --- courses/moccasin-101/6-mox-coffee/10-kinds/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/10-kinds/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md b/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md new file mode 100644 index 000000000..3a20eb491 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md @@ -0,0 +1,3 @@ +--- + title: Kinds + --- \ No newline at end of file From 2c025433366313bd32c447d18e00762c4c4781c1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:32:38 -0700 Subject: [PATCH 352/797] Equious updated courses/moccasin-101/6-mox-coffee/11-unit/+page.md. --- courses/moccasin-101/6-mox-coffee/11-unit/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/11-unit/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/11-unit/+page.md b/courses/moccasin-101/6-mox-coffee/11-unit/+page.md new file mode 100644 index 000000000..ef3d00c8c --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/11-unit/+page.md @@ -0,0 +1,3 @@ +--- + title: Unit + --- \ No newline at end of file From 119b3b88915fa38394660d3604cbe0d28e21d8d8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:32:52 -0700 Subject: [PATCH 353/797] Equious updated courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md. --- courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md b/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md new file mode 100644 index 000000000..66d5d3331 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md @@ -0,0 +1,3 @@ +--- + title: Test Revert + --- \ No newline at end of file From ee8b023bc952d58327b1de829f0744b20bcb3755 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:33:07 -0700 Subject: [PATCH 354/797] Equious updated courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md. --- courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md b/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md new file mode 100644 index 000000000..b44c55fda --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md @@ -0,0 +1,3 @@ +--- + title: Set Balance + --- \ No newline at end of file From 8a503f69218ecba84e8999de1700f08cc53b2436 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:33:21 -0700 Subject: [PATCH 355/797] Equious updated courses/moccasin-101/6-mox-coffee/14-prank/+page.md. --- courses/moccasin-101/6-mox-coffee/14-prank/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/14-prank/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/14-prank/+page.md b/courses/moccasin-101/6-mox-coffee/14-prank/+page.md new file mode 100644 index 000000000..024a80546 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/14-prank/+page.md @@ -0,0 +1,3 @@ +--- + title: Prank + --- \ No newline at end of file From 1555ea19cf05439d8176a97648ae1b090b4afef9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:33:36 -0700 Subject: [PATCH 356/797] Equious updated courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md. --- courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md b/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md new file mode 100644 index 000000000..510c15538 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md @@ -0,0 +1,3 @@ +--- + title: Mid Sec Work + --- \ No newline at end of file From 02f772e3e99c4a18146d14ec9efaedd769d8b726 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:33:50 -0700 Subject: [PATCH 357/797] Equious updated courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md. --- courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md b/courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md new file mode 100644 index 000000000..e5d0bc24e --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md @@ -0,0 +1,3 @@ +--- + title: More Fixtures + --- \ No newline at end of file From 23c417369b79cf9f3745f013e5d3515bb419ce88 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:34:04 -0700 Subject: [PATCH 358/797] Equious updated courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md. --- courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md b/courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md new file mode 100644 index 000000000..25317a24e --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md @@ -0,0 +1,3 @@ +--- + title: Test Coverage + --- \ No newline at end of file From c4f89322ecc78b1cde5322c7cc07cd79afcb9463 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:35:32 -0700 Subject: [PATCH 359/797] Equious updated courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md. --- courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md b/courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md new file mode 100644 index 000000000..88ca818ae --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md @@ -0,0 +1,3 @@ +--- + title: Gas Profile + --- \ No newline at end of file From d4947eba9a96a8827347da5c2be72aade057402c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:35:57 -0700 Subject: [PATCH 360/797] Equious updated courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md. --- courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md b/courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md new file mode 100644 index 000000000..2c00fcac4 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md @@ -0,0 +1,3 @@ +--- + title: Fork Tests + --- \ No newline at end of file From 54d653ed40e558cd32a36f2326e170b58c585a79 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:36:24 -0700 Subject: [PATCH 361/797] Equious updated courses/moccasin-101/6-mox-coffee/19-staging/+page.md. --- courses/moccasin-101/6-mox-coffee/19-staging/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/19-staging/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/19-staging/+page.md b/courses/moccasin-101/6-mox-coffee/19-staging/+page.md new file mode 100644 index 000000000..f2de04c12 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/19-staging/+page.md @@ -0,0 +1,3 @@ +--- + title: Staging + --- \ No newline at end of file From 2a71a7de5a5dd1dc7da0f0dba80dd54f9c451a81 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:36:38 -0700 Subject: [PATCH 362/797] Equious updated courses/moccasin-101/6-mox-coffee/2-setup/+page.md. --- courses/moccasin-101/6-mox-coffee/2-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/2-setup/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/2-setup/+page.md b/courses/moccasin-101/6-mox-coffee/2-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/2-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From c4f1b9876b2cd7539abb273b91de1a450a4e5672 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:05 -0700 Subject: [PATCH 363/797] Equious updated courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md. --- courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md b/courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md new file mode 100644 index 000000000..d1459d73d --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md @@ -0,0 +1,3 @@ +--- + title: Deployments Db + --- \ No newline at end of file From ea7be293dee98feef334e706fd38409f878f8b5c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:37:18 -0700 Subject: [PATCH 364/797] Equious updated courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md. --- courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md b/courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md new file mode 100644 index 000000000..4f5922387 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync Testing + --- \ No newline at end of file From 32f5aa01fe3b04d4245f2efb0d7591c5558375aa Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:45:13 -0700 Subject: [PATCH 365/797] Equious updated courses/moccasin-101/6-mox-coffee/22-github/+page.md. --- courses/moccasin-101/6-mox-coffee/22-github/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/22-github/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/22-github/+page.md b/courses/moccasin-101/6-mox-coffee/22-github/+page.md new file mode 100644 index 000000000..759cfde0e --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/22-github/+page.md @@ -0,0 +1,3 @@ +--- + title: Github + --- \ No newline at end of file From 4b28271bd03443301ba85d4cc2b26a294b5b0a69 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:46:40 -0700 Subject: [PATCH 366/797] Equious updated courses/moccasin-101/6-mox-coffee/23-clone/+page.md. --- courses/moccasin-101/6-mox-coffee/23-clone/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/23-clone/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/23-clone/+page.md b/courses/moccasin-101/6-mox-coffee/23-clone/+page.md new file mode 100644 index 000000000..bdc0c631b --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/23-clone/+page.md @@ -0,0 +1,3 @@ +--- + title: Clone + --- \ No newline at end of file From 5c82b20ed315d88aaeb4fcd2f0a8b3a025dcf142 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:47:46 -0700 Subject: [PATCH 367/797] Equious updated courses/moccasin-101/6-mox-coffee/24-workshop/+page.md. --- courses/moccasin-101/6-mox-coffee/24-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/24-workshop/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/24-workshop/+page.md b/courses/moccasin-101/6-mox-coffee/24-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/24-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 6657859e7fc127cceddd9b9fcb444b9f8f5b3579 Mon Sep 17 00:00:00 2001 From: hunter <104146303+solhosty@users.noreply.github.com> Date: Thu, 21 Nov 2024 18:57:26 -0500 Subject: [PATCH 368/797] rm --- courses/moccasin-101/1-python-on-updraft/1-intro/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/10-math/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/13-conditionals/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/14-while-loops/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/18-recap/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/2-google-collab/+page.md | 3 --- .../1-python-on-updraft/20-install-vscode-macos-linux/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/21-install-wsl/+page.md | 3 --- .../1-python-on-updraft/22-vscode-windows-install/+page.md | 3 --- .../23-vscode-windows-wsl-extension/+page.md | 3 --- .../1-python-on-updraft/24-vscode-quickstart/+page.md | 3 --- .../1-python-on-updraft/25-install-python-macos/+page.md | 3 --- .../1-python-on-updraft/26-install-python-wsl-linux/+page.md | 3 --- .../1-python-on-updraft/27-vscode-quickstart-2/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/28-mental-prep/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/3-setup/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/30-python-shell/+page.md | 3 --- .../1-python-on-updraft/31-python-extensions-vscode/+page.md | 3 --- .../1-python-on-updraft/32-our-first-python/+page.md | 3 --- .../1-python-on-updraft/33-python-imports/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/34-installing-uv/+page.md | 3 --- .../1-python-on-updraft/35-uv-python-version/+page.md | 3 --- .../1-python-on-updraft/36-adding-packages-uv/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/38-recap/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md | 3 --- .../moccasin-101/1-python-on-updraft/6-python-vars/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md | 3 --- courses/moccasin-101/1-python-on-updraft/9-types/+page.md | 3 --- courses/moccasin-101/2-web3py/1-intro/+page.md | 3 --- courses/moccasin-101/2-web3py/18-pkey-promise/+page.md | 3 --- courses/moccasin-101/2-web3py/19-env-vars/+page.md | 3 --- courses/moccasin-101/2-web3py/2-setup/+page.md | 3 --- courses/moccasin-101/2-web3py/20-send-tx/+page.md | 3 --- courses/moccasin-101/2-web3py/21-encrypt/+page.md | 3 --- courses/moccasin-101/2-web3py/22-decrypt/+page.md | 3 --- courses/moccasin-101/2-web3py/23-pledge/+page.md | 3 --- courses/moccasin-101/2-web3py/24-workshop/+page.md | 3 --- courses/moccasin-101/2-web3py/25-recap/+page.md | 3 --- courses/moccasin-101/2-web3py/3-vyper-extension/+page.md | 3 --- courses/moccasin-101/3-boa-favs/1-intro/+page.md | 3 --- courses/moccasin-101/3-boa-favs/10-add-person/+page.md | 3 --- courses/moccasin-101/3-boa-favs/11-workshop/+page.md | 3 --- courses/moccasin-101/3-boa-favs/12-recap/+page.md | 3 --- courses/moccasin-101/3-boa-favs/2-setup/+page.md | 3 --- courses/moccasin-101/3-boa-favs/3-pyevm/+page.md | 3 --- courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md | 3 --- courses/moccasin-101/3-boa-favs/5-debug/+page.md | 3 --- courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md | 3 --- courses/moccasin-101/3-boa-favs/7-anvil/+page.md | 3 --- courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md | 3 --- courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md | 3 --- courses/moccasin-101/4-mox-favs/1-intro/+page.md | 3 --- courses/moccasin-101/4-mox-favs/10-account-cli/+page.md | 3 --- courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md | 3 --- .../moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md | 3 --- courses/moccasin-101/4-mox-favs/13-aaa/+page.md | 3 --- courses/moccasin-101/4-mox-favs/14-fixtures/+page.md | 3 --- courses/moccasin-101/4-mox-favs/15-conftest/+page.md | 3 --- courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md | 3 --- courses/moccasin-101/4-mox-favs/18-verify/+page.md | 3 --- courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md | 3 --- courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md | 3 --- courses/moccasin-101/4-mox-favs/20-eravm/+page.md | 3 --- courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md | 3 --- courses/moccasin-101/4-mox-favs/22-bridging/+page.md | 3 --- courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md | 3 --- .../4-mox-favs/24-zksync-contract-deployment/+page.md | 3 --- courses/moccasin-101/4-mox-favs/25-tx-types/+page.md | 3 --- courses/moccasin-101/4-mox-favs/26-workshop/+page.md | 3 --- courses/moccasin-101/4-mox-favs/3-create-mox/+page.md | 3 --- courses/moccasin-101/4-mox-favs/4-mox-something/+page.md | 3 --- courses/moccasin-101/4-mox-favs/5-mox-script/+page.md | 3 --- courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md | 3 --- courses/moccasin-101/4-mox-favs/8-shell/+page.md | 3 --- courses/moccasin-101/4-mox-favs/9-using-key/+page.md | 3 --- courses/moccasin-101/5-mox-five/1-intro/+page.md | 3 --- .../5-mox-five/11-initializes-module-state/+page.md | 3 --- courses/moccasin-101/5-mox-five/13-workshop/+page.md | 3 --- courses/moccasin-101/5-mox-five/14-recap/+page.md | 3 --- courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md | 3 --- courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md | 3 --- courses/moccasin-101/5-mox-five/5-vyi/+page.md | 3 --- courses/moccasin-101/5-mox-five/6-idk/+page.md | 3 --- courses/moccasin-101/5-mox-five/7-extcall/+page.md | 3 --- .../5-mox-five/8-store-contract-by-interface/+page.md | 3 --- courses/moccasin-101/5-mox-five/9-method-chaining/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/1-intro/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/10-kinds/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/11-unit/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/14-prank/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/19-staging/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/2-setup/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/22-github/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/23-clone/+page.md | 3 --- courses/moccasin-101/6-mox-coffee/24-workshop/+page.md | 3 --- 115 files changed, 345 deletions(-) delete mode 100644 courses/moccasin-101/1-python-on-updraft/1-intro/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/10-math/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/18-recap/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/3-setup/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/38-recap/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md delete mode 100644 courses/moccasin-101/1-python-on-updraft/9-types/+page.md delete mode 100644 courses/moccasin-101/2-web3py/1-intro/+page.md delete mode 100644 courses/moccasin-101/2-web3py/18-pkey-promise/+page.md delete mode 100644 courses/moccasin-101/2-web3py/19-env-vars/+page.md delete mode 100644 courses/moccasin-101/2-web3py/2-setup/+page.md delete mode 100644 courses/moccasin-101/2-web3py/20-send-tx/+page.md delete mode 100644 courses/moccasin-101/2-web3py/21-encrypt/+page.md delete mode 100644 courses/moccasin-101/2-web3py/22-decrypt/+page.md delete mode 100644 courses/moccasin-101/2-web3py/23-pledge/+page.md delete mode 100644 courses/moccasin-101/2-web3py/24-workshop/+page.md delete mode 100644 courses/moccasin-101/2-web3py/25-recap/+page.md delete mode 100644 courses/moccasin-101/2-web3py/3-vyper-extension/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/1-intro/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/10-add-person/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/11-workshop/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/12-recap/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/2-setup/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/3-pyevm/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/5-debug/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/7-anvil/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md delete mode 100644 courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/1-intro/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/10-account-cli/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/13-aaa/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/14-fixtures/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/15-conftest/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/18-verify/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/20-eravm/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/22-bridging/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/25-tx-types/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/26-workshop/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/3-create-mox/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/4-mox-something/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/5-mox-script/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/8-shell/+page.md delete mode 100644 courses/moccasin-101/4-mox-favs/9-using-key/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/1-intro/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/13-workshop/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/14-recap/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/5-vyi/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/6-idk/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/7-extcall/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md delete mode 100644 courses/moccasin-101/5-mox-five/9-method-chaining/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/1-intro/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/10-kinds/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/11-unit/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/14-prank/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/19-staging/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/2-setup/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/22-github/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/23-clone/+page.md delete mode 100644 courses/moccasin-101/6-mox-coffee/24-workshop/+page.md diff --git a/courses/moccasin-101/1-python-on-updraft/1-intro/+page.md b/courses/moccasin-101/1-python-on-updraft/1-intro/+page.md deleted file mode 100644 index b7e64e913..000000000 --- a/courses/moccasin-101/1-python-on-updraft/1-intro/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Intro - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/10-math/+page.md b/courses/moccasin-101/1-python-on-updraft/10-math/+page.md deleted file mode 100644 index d246d700c..000000000 --- a/courses/moccasin-101/1-python-on-updraft/10-math/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Math - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md b/courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md deleted file mode 100644 index 52de64c11..000000000 --- a/courses/moccasin-101/1-python-on-updraft/11-more-math/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: More Math - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md b/courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md deleted file mode 100644 index 125b3fa6b..000000000 --- a/courses/moccasin-101/1-python-on-updraft/12-funcs/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Funcs - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md b/courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md deleted file mode 100644 index 1d57c9ca3..000000000 --- a/courses/moccasin-101/1-python-on-updraft/13-conditionals/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Conditionals - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md b/courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md deleted file mode 100644 index 9e54beace..000000000 --- a/courses/moccasin-101/1-python-on-updraft/14-while-loops/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: While Loops - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md b/courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md deleted file mode 100644 index 1633a4fcb..000000000 --- a/courses/moccasin-101/1-python-on-updraft/15-loops-2/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Loops 2 - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md b/courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md deleted file mode 100644 index 3e226d5ca..000000000 --- a/courses/moccasin-101/1-python-on-updraft/16-loops-3/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Loops 3 - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md b/courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md deleted file mode 100644 index 789149836..000000000 --- a/courses/moccasin-101/1-python-on-updraft/17-workshop/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Workshop - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/18-recap/+page.md b/courses/moccasin-101/1-python-on-updraft/18-recap/+page.md deleted file mode 100644 index 385e6edfe..000000000 --- a/courses/moccasin-101/1-python-on-updraft/18-recap/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Recap - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md b/courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md deleted file mode 100644 index 82dee4ad0..000000000 --- a/courses/moccasin-101/1-python-on-updraft/19-dev-env-setup/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Dev Env Setup - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md b/courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md deleted file mode 100644 index 735bc3c07..000000000 --- a/courses/moccasin-101/1-python-on-updraft/2-google-collab/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Google Collab - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md b/courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md deleted file mode 100644 index 29e695218..000000000 --- a/courses/moccasin-101/1-python-on-updraft/20-install-vscode-macos-linux/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Install Vscode Macos Linux - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md b/courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md deleted file mode 100644 index 475d38e9a..000000000 --- a/courses/moccasin-101/1-python-on-updraft/21-install-wsl/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Install Wsl - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md b/courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md deleted file mode 100644 index a09ad1944..000000000 --- a/courses/moccasin-101/1-python-on-updraft/22-vscode-windows-install/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vscode Windows Install - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md b/courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md deleted file mode 100644 index 2acc9a55f..000000000 --- a/courses/moccasin-101/1-python-on-updraft/23-vscode-windows-wsl-extension/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vscode Windows Wsl Extension - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md b/courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md deleted file mode 100644 index 3ab104359..000000000 --- a/courses/moccasin-101/1-python-on-updraft/24-vscode-quickstart/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vscode Quickstart - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md b/courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md deleted file mode 100644 index d2148949d..000000000 --- a/courses/moccasin-101/1-python-on-updraft/25-install-python-macos/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Install Python Macos - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md b/courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md deleted file mode 100644 index d18275288..000000000 --- a/courses/moccasin-101/1-python-on-updraft/26-install-python-wsl-linux/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Install Python Wsl Linux - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md b/courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md deleted file mode 100644 index 7d3ad9c57..000000000 --- a/courses/moccasin-101/1-python-on-updraft/27-vscode-quickstart-2/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vscode Quickstart 2 - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md b/courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md deleted file mode 100644 index cfcec4377..000000000 --- a/courses/moccasin-101/1-python-on-updraft/28-mental-prep/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Mental Prep - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md b/courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md deleted file mode 100644 index 8c591a536..000000000 --- a/courses/moccasin-101/1-python-on-updraft/29-local-py/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Local Py - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/3-setup/+page.md b/courses/moccasin-101/1-python-on-updraft/3-setup/+page.md deleted file mode 100644 index fcc7a149d..000000000 --- a/courses/moccasin-101/1-python-on-updraft/3-setup/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Setup - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md b/courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md deleted file mode 100644 index 9c47c3f3e..000000000 --- a/courses/moccasin-101/1-python-on-updraft/30-python-shell/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Python Shell - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md b/courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md deleted file mode 100644 index 85f6eb88c..000000000 --- a/courses/moccasin-101/1-python-on-updraft/31-python-extensions-vscode/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Python Extensions Vscode - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md b/courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md deleted file mode 100644 index f790b0411..000000000 --- a/courses/moccasin-101/1-python-on-updraft/32-our-first-python/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Our First Python - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md b/courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md deleted file mode 100644 index fae7a0f96..000000000 --- a/courses/moccasin-101/1-python-on-updraft/33-python-imports/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Python Imports - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md b/courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md deleted file mode 100644 index ef00c9919..000000000 --- a/courses/moccasin-101/1-python-on-updraft/34-installing-uv/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Installing Uv - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md b/courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md deleted file mode 100644 index 84d31ea64..000000000 --- a/courses/moccasin-101/1-python-on-updraft/35-uv-python-version/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Uv Python Version - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md b/courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md deleted file mode 100644 index d2268f193..000000000 --- a/courses/moccasin-101/1-python-on-updraft/36-adding-packages-uv/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Adding Packages Uv - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md b/courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md deleted file mode 100644 index c211b8e01..000000000 --- a/courses/moccasin-101/1-python-on-updraft/37-virtual-envs/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Virtual Envs - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/38-recap/+page.md b/courses/moccasin-101/1-python-on-updraft/38-recap/+page.md deleted file mode 100644 index 385e6edfe..000000000 --- a/courses/moccasin-101/1-python-on-updraft/38-recap/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Recap - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md b/courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md deleted file mode 100644 index e4cab53fa..000000000 --- a/courses/moccasin-101/1-python-on-updraft/4-notebook/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Notebook - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md b/courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md deleted file mode 100644 index faa0a0f12..000000000 --- a/courses/moccasin-101/1-python-on-updraft/5-google-ai/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Google Ai - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md b/courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md deleted file mode 100644 index 9d8367c72..000000000 --- a/courses/moccasin-101/1-python-on-updraft/6-python-vars/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Python Vars - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md b/courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md deleted file mode 100644 index 3f01df5ef..000000000 --- a/courses/moccasin-101/1-python-on-updraft/6-type-hints/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Type Hints - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md b/courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md deleted file mode 100644 index 267733150..000000000 --- a/courses/moccasin-101/1-python-on-updraft/7-arrays/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Arrays - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md b/courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md deleted file mode 100644 index 8a90dbef7..000000000 --- a/courses/moccasin-101/1-python-on-updraft/8-inputs/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Inputs - --- \ No newline at end of file diff --git a/courses/moccasin-101/1-python-on-updraft/9-types/+page.md b/courses/moccasin-101/1-python-on-updraft/9-types/+page.md deleted file mode 100644 index c6210ebf1..000000000 --- a/courses/moccasin-101/1-python-on-updraft/9-types/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Types - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/1-intro/+page.md b/courses/moccasin-101/2-web3py/1-intro/+page.md deleted file mode 100644 index b7e64e913..000000000 --- a/courses/moccasin-101/2-web3py/1-intro/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Intro - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md b/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md deleted file mode 100644 index 08c6274da..000000000 --- a/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Pkey Promise - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/19-env-vars/+page.md b/courses/moccasin-101/2-web3py/19-env-vars/+page.md deleted file mode 100644 index e97071bde..000000000 --- a/courses/moccasin-101/2-web3py/19-env-vars/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Env Vars - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/2-setup/+page.md b/courses/moccasin-101/2-web3py/2-setup/+page.md deleted file mode 100644 index fcc7a149d..000000000 --- a/courses/moccasin-101/2-web3py/2-setup/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Setup - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/20-send-tx/+page.md b/courses/moccasin-101/2-web3py/20-send-tx/+page.md deleted file mode 100644 index 5b4867baa..000000000 --- a/courses/moccasin-101/2-web3py/20-send-tx/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Send Tx - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/21-encrypt/+page.md b/courses/moccasin-101/2-web3py/21-encrypt/+page.md deleted file mode 100644 index 56ef26d1d..000000000 --- a/courses/moccasin-101/2-web3py/21-encrypt/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Encrypt - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/22-decrypt/+page.md b/courses/moccasin-101/2-web3py/22-decrypt/+page.md deleted file mode 100644 index 19a99651f..000000000 --- a/courses/moccasin-101/2-web3py/22-decrypt/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Decrypt - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/23-pledge/+page.md b/courses/moccasin-101/2-web3py/23-pledge/+page.md deleted file mode 100644 index dea23512b..000000000 --- a/courses/moccasin-101/2-web3py/23-pledge/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Pledge - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/24-workshop/+page.md b/courses/moccasin-101/2-web3py/24-workshop/+page.md deleted file mode 100644 index 789149836..000000000 --- a/courses/moccasin-101/2-web3py/24-workshop/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Workshop - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/25-recap/+page.md b/courses/moccasin-101/2-web3py/25-recap/+page.md deleted file mode 100644 index 385e6edfe..000000000 --- a/courses/moccasin-101/2-web3py/25-recap/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Recap - --- \ No newline at end of file diff --git a/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md b/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md deleted file mode 100644 index e1b9b773a..000000000 --- a/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vyper Extension - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/1-intro/+page.md b/courses/moccasin-101/3-boa-favs/1-intro/+page.md deleted file mode 100644 index b7e64e913..000000000 --- a/courses/moccasin-101/3-boa-favs/1-intro/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Intro - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/10-add-person/+page.md b/courses/moccasin-101/3-boa-favs/10-add-person/+page.md deleted file mode 100644 index ec6f71030..000000000 --- a/courses/moccasin-101/3-boa-favs/10-add-person/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Add Person - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/11-workshop/+page.md b/courses/moccasin-101/3-boa-favs/11-workshop/+page.md deleted file mode 100644 index 789149836..000000000 --- a/courses/moccasin-101/3-boa-favs/11-workshop/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Workshop - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/12-recap/+page.md b/courses/moccasin-101/3-boa-favs/12-recap/+page.md deleted file mode 100644 index 385e6edfe..000000000 --- a/courses/moccasin-101/3-boa-favs/12-recap/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Recap - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/2-setup/+page.md b/courses/moccasin-101/3-boa-favs/2-setup/+page.md deleted file mode 100644 index fcc7a149d..000000000 --- a/courses/moccasin-101/3-boa-favs/2-setup/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Setup - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md b/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md deleted file mode 100644 index cbbb50791..000000000 --- a/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Pyevm - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md b/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md deleted file mode 100644 index 51f4c8a80..000000000 --- a/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vypercontract - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/5-debug/+page.md b/courses/moccasin-101/3-boa-favs/5-debug/+page.md deleted file mode 100644 index 746a037b4..000000000 --- a/courses/moccasin-101/3-boa-favs/5-debug/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Debug - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md b/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md deleted file mode 100644 index 5f76de142..000000000 --- a/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Pyevm_ - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/7-anvil/+page.md b/courses/moccasin-101/3-boa-favs/7-anvil/+page.md deleted file mode 100644 index 0c0a4fdfe..000000000 --- a/courses/moccasin-101/3-boa-favs/7-anvil/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Anvil - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md b/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md deleted file mode 100644 index 85923930c..000000000 --- a/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Interacting Anvil - --- \ No newline at end of file diff --git a/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md b/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md deleted file mode 100644 index 87d3f90ba..000000000 --- a/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Interact Prevs - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/1-intro/+page.md b/courses/moccasin-101/4-mox-favs/1-intro/+page.md deleted file mode 100644 index b7e64e913..000000000 --- a/courses/moccasin-101/4-mox-favs/1-intro/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Intro - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md b/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md deleted file mode 100644 index 0984dc172..000000000 --- a/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Account Cli - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md b/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md deleted file mode 100644 index 7cc9872a4..000000000 --- a/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Mox Testing - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md b/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md deleted file mode 100644 index 19850ca6b..000000000 --- a/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Testing Deploy Script - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/13-aaa/+page.md b/courses/moccasin-101/4-mox-favs/13-aaa/+page.md deleted file mode 100644 index ff929f638..000000000 --- a/courses/moccasin-101/4-mox-favs/13-aaa/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Aaa - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md b/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md deleted file mode 100644 index 48ccb103c..000000000 --- a/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Fixtures - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/15-conftest/+page.md b/courses/moccasin-101/4-mox-favs/15-conftest/+page.md deleted file mode 100644 index d47333a69..000000000 --- a/courses/moccasin-101/4-mox-favs/15-conftest/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Conftest - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md b/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md deleted file mode 100644 index ad5a0b3ab..000000000 --- a/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Sepolia Deploy - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/18-verify/+page.md b/courses/moccasin-101/4-mox-favs/18-verify/+page.md deleted file mode 100644 index 0878aa404..000000000 --- a/courses/moccasin-101/4-mox-favs/18-verify/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Verify - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md b/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md deleted file mode 100644 index e03eaddb9..000000000 --- a/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Zksync Setup - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md b/courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md deleted file mode 100644 index a4d6415c2..000000000 --- a/courses/moccasin-101/4-mox-favs/2-instlal -mox/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Instlal Mox - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/20-eravm/+page.md b/courses/moccasin-101/4-mox-favs/20-eravm/+page.md deleted file mode 100644 index fef1da72f..000000000 --- a/courses/moccasin-101/4-mox-favs/20-eravm/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Eravm - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md b/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md deleted file mode 100644 index a515e5e34..000000000 --- a/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Setting Up Zksync - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/22-bridging/+page.md b/courses/moccasin-101/4-mox-favs/22-bridging/+page.md deleted file mode 100644 index 1b24a95e4..000000000 --- a/courses/moccasin-101/4-mox-favs/22-bridging/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Bridging - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md b/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md deleted file mode 100644 index ef6567697..000000000 --- a/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Zksync Deploy - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md b/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md deleted file mode 100644 index 7676d99dc..000000000 --- a/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Zksync Contract Deployment - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md b/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md deleted file mode 100644 index e465b90e1..000000000 --- a/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Tx Types - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/26-workshop/+page.md b/courses/moccasin-101/4-mox-favs/26-workshop/+page.md deleted file mode 100644 index 789149836..000000000 --- a/courses/moccasin-101/4-mox-favs/26-workshop/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Workshop - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md b/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md deleted file mode 100644 index 0f542f929..000000000 --- a/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Create Mox - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md b/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md deleted file mode 100644 index e56710475..000000000 --- a/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Mox Something - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md b/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md deleted file mode 100644 index 9b8bba199..000000000 --- a/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Mox Script - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md b/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md deleted file mode 100644 index 7ab4c1ff8..000000000 --- a/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Encrypt Key - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/8-shell/+page.md b/courses/moccasin-101/4-mox-favs/8-shell/+page.md deleted file mode 100644 index 00df35f0d..000000000 --- a/courses/moccasin-101/4-mox-favs/8-shell/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Shell - --- \ No newline at end of file diff --git a/courses/moccasin-101/4-mox-favs/9-using-key/+page.md b/courses/moccasin-101/4-mox-favs/9-using-key/+page.md deleted file mode 100644 index dd0adc820..000000000 --- a/courses/moccasin-101/4-mox-favs/9-using-key/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Using Key - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/1-intro/+page.md b/courses/moccasin-101/5-mox-five/1-intro/+page.md deleted file mode 100644 index b7e64e913..000000000 --- a/courses/moccasin-101/5-mox-five/1-intro/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Intro - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md b/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md deleted file mode 100644 index 7096200f7..000000000 --- a/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Initializes Module State - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/13-workshop/+page.md b/courses/moccasin-101/5-mox-five/13-workshop/+page.md deleted file mode 100644 index 789149836..000000000 --- a/courses/moccasin-101/5-mox-five/13-workshop/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Workshop - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/14-recap/+page.md b/courses/moccasin-101/5-mox-five/14-recap/+page.md deleted file mode 100644 index 385e6edfe..000000000 --- a/courses/moccasin-101/5-mox-five/14-recap/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Recap - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md b/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md deleted file mode 100644 index a391afc59..000000000 --- a/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Create Copy Of - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md b/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md deleted file mode 100644 index e5dcc0071..000000000 --- a/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Static Ext Call - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/5-vyi/+page.md b/courses/moccasin-101/5-mox-five/5-vyi/+page.md deleted file mode 100644 index 62bd446ed..000000000 --- a/courses/moccasin-101/5-mox-five/5-vyi/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Vyi - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/6-idk/+page.md b/courses/moccasin-101/5-mox-five/6-idk/+page.md deleted file mode 100644 index d226208fe..000000000 --- a/courses/moccasin-101/5-mox-five/6-idk/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Idk - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/7-extcall/+page.md b/courses/moccasin-101/5-mox-five/7-extcall/+page.md deleted file mode 100644 index 36c841a81..000000000 --- a/courses/moccasin-101/5-mox-five/7-extcall/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Extcall - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md b/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md deleted file mode 100644 index d79d0e7af..000000000 --- a/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Store Contract By Interface - --- \ No newline at end of file diff --git a/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md b/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md deleted file mode 100644 index 2aa8fbe12..000000000 --- a/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Method Chaining - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/1-intro/+page.md b/courses/moccasin-101/6-mox-coffee/1-intro/+page.md deleted file mode 100644 index b7e64e913..000000000 --- a/courses/moccasin-101/6-mox-coffee/1-intro/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Intro - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md b/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md deleted file mode 100644 index 3a20eb491..000000000 --- a/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Kinds - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/11-unit/+page.md b/courses/moccasin-101/6-mox-coffee/11-unit/+page.md deleted file mode 100644 index ef3d00c8c..000000000 --- a/courses/moccasin-101/6-mox-coffee/11-unit/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Unit - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md b/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md deleted file mode 100644 index 66d5d3331..000000000 --- a/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Test Revert - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md b/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md deleted file mode 100644 index b44c55fda..000000000 --- a/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Set Balance - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/14-prank/+page.md b/courses/moccasin-101/6-mox-coffee/14-prank/+page.md deleted file mode 100644 index 024a80546..000000000 --- a/courses/moccasin-101/6-mox-coffee/14-prank/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Prank - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md b/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md deleted file mode 100644 index 510c15538..000000000 --- a/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Mid Sec Work - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md b/courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md deleted file mode 100644 index e5d0bc24e..000000000 --- a/courses/moccasin-101/6-mox-coffee/15-more-fixtures/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: More Fixtures - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md b/courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md deleted file mode 100644 index 25317a24e..000000000 --- a/courses/moccasin-101/6-mox-coffee/16-test-coverage/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Test Coverage - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md b/courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md deleted file mode 100644 index 88ca818ae..000000000 --- a/courses/moccasin-101/6-mox-coffee/17-gas-profile/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Gas Profile - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md b/courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md deleted file mode 100644 index 2c00fcac4..000000000 --- a/courses/moccasin-101/6-mox-coffee/18-fork-tests/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Fork Tests - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/19-staging/+page.md b/courses/moccasin-101/6-mox-coffee/19-staging/+page.md deleted file mode 100644 index f2de04c12..000000000 --- a/courses/moccasin-101/6-mox-coffee/19-staging/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Staging - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/2-setup/+page.md b/courses/moccasin-101/6-mox-coffee/2-setup/+page.md deleted file mode 100644 index fcc7a149d..000000000 --- a/courses/moccasin-101/6-mox-coffee/2-setup/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Setup - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md b/courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md deleted file mode 100644 index d1459d73d..000000000 --- a/courses/moccasin-101/6-mox-coffee/20-deployments-db/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Deployments Db - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md b/courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md deleted file mode 100644 index 4f5922387..000000000 --- a/courses/moccasin-101/6-mox-coffee/21-zksync-testing/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Zksync Testing - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/22-github/+page.md b/courses/moccasin-101/6-mox-coffee/22-github/+page.md deleted file mode 100644 index 759cfde0e..000000000 --- a/courses/moccasin-101/6-mox-coffee/22-github/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Github - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/23-clone/+page.md b/courses/moccasin-101/6-mox-coffee/23-clone/+page.md deleted file mode 100644 index bdc0c631b..000000000 --- a/courses/moccasin-101/6-mox-coffee/23-clone/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Clone - --- \ No newline at end of file diff --git a/courses/moccasin-101/6-mox-coffee/24-workshop/+page.md b/courses/moccasin-101/6-mox-coffee/24-workshop/+page.md deleted file mode 100644 index 789149836..000000000 --- a/courses/moccasin-101/6-mox-coffee/24-workshop/+page.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - title: Workshop - --- \ No newline at end of file From 2d7a1bf37a52ed2071fc7a110e47e8ac864d8480 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:16:09 -0700 Subject: [PATCH 369/797] Equious updated courses/moccasin-101/1-python-in-updraft/1-intro/+page.md. --- courses/moccasin-101/1-python-in-updraft/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/1-intro/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/1-intro/+page.md b/courses/moccasin-101/1-python-in-updraft/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 00e3e4b93aee0fb0c8bbeeedbe5f4385f58ca10a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:16:23 -0700 Subject: [PATCH 370/797] Equious updated courses/moccasin-101/1-python-in-updraft/10-math/+page.md. --- courses/moccasin-101/1-python-in-updraft/10-math/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/10-math/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/10-math/+page.md b/courses/moccasin-101/1-python-in-updraft/10-math/+page.md new file mode 100644 index 000000000..d246d700c --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/10-math/+page.md @@ -0,0 +1,3 @@ +--- + title: Math + --- \ No newline at end of file From 34a5090258e3c2a543bbe8752ffa6992ef22da4d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:16:40 -0700 Subject: [PATCH 371/797] Equious updated courses/moccasin-101/1-python-in-updraft/11-more-math/+page.md. --- courses/moccasin-101/1-python-in-updraft/11-more-math/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/11-more-math/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/11-more-math/+page.md b/courses/moccasin-101/1-python-in-updraft/11-more-math/+page.md new file mode 100644 index 000000000..52de64c11 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/11-more-math/+page.md @@ -0,0 +1,3 @@ +--- + title: More Math + --- \ No newline at end of file From 6a74a45b76655514f3fb45db885195ae5fa7e3bd Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:17:08 -0700 Subject: [PATCH 372/797] Equious updated courses/moccasin-101/1-python-in-updraft/12-funcs/+page.md. --- courses/moccasin-101/1-python-in-updraft/12-funcs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/12-funcs/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/12-funcs/+page.md b/courses/moccasin-101/1-python-in-updraft/12-funcs/+page.md new file mode 100644 index 000000000..125b3fa6b --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/12-funcs/+page.md @@ -0,0 +1,3 @@ +--- + title: Funcs + --- \ No newline at end of file From 1852bd83d742947e9062dfa37d58a32578eedf75 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:17:21 -0700 Subject: [PATCH 373/797] Equious updated courses/moccasin-101/1-python-in-updraft/13-conditionals/+page.md. --- .../moccasin-101/1-python-in-updraft/13-conditionals/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/13-conditionals/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/13-conditionals/+page.md b/courses/moccasin-101/1-python-in-updraft/13-conditionals/+page.md new file mode 100644 index 000000000..1d57c9ca3 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/13-conditionals/+page.md @@ -0,0 +1,3 @@ +--- + title: Conditionals + --- \ No newline at end of file From 982ee69eea4413b0229a4aed457dda8eadd36981 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:17:35 -0700 Subject: [PATCH 374/797] Equious updated courses/moccasin-101/1-python-in-updraft/14-while-loops/+page.md. --- .../moccasin-101/1-python-in-updraft/14-while-loops/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/14-while-loops/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/14-while-loops/+page.md b/courses/moccasin-101/1-python-in-updraft/14-while-loops/+page.md new file mode 100644 index 000000000..9e54beace --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/14-while-loops/+page.md @@ -0,0 +1,3 @@ +--- + title: While Loops + --- \ No newline at end of file From a67a0f7167a1815bd953d32f696493ac17a4949e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:17:48 -0700 Subject: [PATCH 375/797] Equious updated courses/moccasin-101/1-python-in-updraft/15-loops-2/+page.md. --- courses/moccasin-101/1-python-in-updraft/15-loops-2/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/15-loops-2/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/15-loops-2/+page.md b/courses/moccasin-101/1-python-in-updraft/15-loops-2/+page.md new file mode 100644 index 000000000..1633a4fcb --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/15-loops-2/+page.md @@ -0,0 +1,3 @@ +--- + title: Loops 2 + --- \ No newline at end of file From 9ca04ba60757c7d6032e317ad5b9e64374f7946b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:18:02 -0700 Subject: [PATCH 376/797] Equious updated courses/moccasin-101/1-python-in-updraft/16-loops-3/+page.md. --- courses/moccasin-101/1-python-in-updraft/16-loops-3/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/16-loops-3/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/16-loops-3/+page.md b/courses/moccasin-101/1-python-in-updraft/16-loops-3/+page.md new file mode 100644 index 000000000..3e226d5ca --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/16-loops-3/+page.md @@ -0,0 +1,3 @@ +--- + title: Loops 3 + --- \ No newline at end of file From c5faa56e97b8fba8f8d8ca8be1aee4ee77017d2a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:19:04 -0700 Subject: [PATCH 377/797] Equious updated courses/moccasin-101/1-python-in-updraft/17-workshop/+page.md. --- courses/moccasin-101/1-python-in-updraft/17-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/17-workshop/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/17-workshop/+page.md b/courses/moccasin-101/1-python-in-updraft/17-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/17-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 417aec21a4dd4978397e06b0ae5382366062fbfe Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:19:19 -0700 Subject: [PATCH 378/797] Equious updated courses/moccasin-101/1-python-in-updraft/18-recap/+page.md. --- courses/moccasin-101/1-python-in-updraft/18-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/18-recap/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/18-recap/+page.md b/courses/moccasin-101/1-python-in-updraft/18-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/18-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 62ccd1cf965abeeb7dd1e829038f0fb4a5cec84d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:20:24 -0700 Subject: [PATCH 379/797] Equious updated courses/moccasin-101/1-python-in-updraft/19-dev-env-setup/+page.md. --- .../moccasin-101/1-python-in-updraft/19-dev-env-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/19-dev-env-setup/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/19-dev-env-setup/+page.md b/courses/moccasin-101/1-python-in-updraft/19-dev-env-setup/+page.md new file mode 100644 index 000000000..82dee4ad0 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/19-dev-env-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Dev Env Setup + --- \ No newline at end of file From 1e61df6366d6021793faed1a073f6c175ecab901 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:22:01 -0700 Subject: [PATCH 380/797] Equious updated courses/moccasin-101/1-python-in-updraft/2-google-collab/+page.md. --- .../moccasin-101/1-python-in-updraft/2-google-collab/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/2-google-collab/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/2-google-collab/+page.md b/courses/moccasin-101/1-python-in-updraft/2-google-collab/+page.md new file mode 100644 index 000000000..735bc3c07 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/2-google-collab/+page.md @@ -0,0 +1,3 @@ +--- + title: Google Collab + --- \ No newline at end of file From 52deaebaa05416d31a48cb6a5e58ef6566897fe8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:22:14 -0700 Subject: [PATCH 381/797] Equious updated courses/moccasin-101/1-python-in-updraft/20-install-vscode-macos-linux/+page.md. --- .../1-python-in-updraft/20-install-vscode-macos-linux/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/20-install-vscode-macos-linux/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/20-install-vscode-macos-linux/+page.md b/courses/moccasin-101/1-python-in-updraft/20-install-vscode-macos-linux/+page.md new file mode 100644 index 000000000..29e695218 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/20-install-vscode-macos-linux/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Vscode Macos Linux + --- \ No newline at end of file From e5b29d357069296fe908a06eb6abe297a239e06b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:24:57 -0700 Subject: [PATCH 382/797] Equious updated courses/moccasin-101/1-python-in-updraft/21-install-wsl/+page.md. --- .../moccasin-101/1-python-in-updraft/21-install-wsl/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/21-install-wsl/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/21-install-wsl/+page.md b/courses/moccasin-101/1-python-in-updraft/21-install-wsl/+page.md new file mode 100644 index 000000000..475d38e9a --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/21-install-wsl/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Wsl + --- \ No newline at end of file From 23efd5149c90f372d1cb5b0968e2e503317c7a0e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:28:26 -0700 Subject: [PATCH 383/797] Equious updated courses/moccasin-101/1-python-in-updraft/22-vscode-windows-install/+page.md. --- .../1-python-in-updraft/22-vscode-windows-install/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/22-vscode-windows-install/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/22-vscode-windows-install/+page.md b/courses/moccasin-101/1-python-in-updraft/22-vscode-windows-install/+page.md new file mode 100644 index 000000000..a09ad1944 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/22-vscode-windows-install/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Windows Install + --- \ No newline at end of file From e23a118647ada5607ca532e5413c85846667fb30 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:28:40 -0700 Subject: [PATCH 384/797] Equious updated courses/moccasin-101/1-python-in-updraft/23-vscode-windows-wsl-extension/+page.md. --- .../23-vscode-windows-wsl-extension/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/23-vscode-windows-wsl-extension/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/23-vscode-windows-wsl-extension/+page.md b/courses/moccasin-101/1-python-in-updraft/23-vscode-windows-wsl-extension/+page.md new file mode 100644 index 000000000..2acc9a55f --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/23-vscode-windows-wsl-extension/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Windows Wsl Extension + --- \ No newline at end of file From 16024917bdabd19c690e8a7a22a7af3359459991 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:28:54 -0700 Subject: [PATCH 385/797] Equious updated courses/moccasin-101/1-python-in-updraft/24-vscode-quickstart/+page.md. --- .../1-python-in-updraft/24-vscode-quickstart/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/24-vscode-quickstart/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/24-vscode-quickstart/+page.md b/courses/moccasin-101/1-python-in-updraft/24-vscode-quickstart/+page.md new file mode 100644 index 000000000..3ab104359 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/24-vscode-quickstart/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Quickstart + --- \ No newline at end of file From 178fdeced9229b2d7574d3dacd20f745bb180c1b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:29:08 -0700 Subject: [PATCH 386/797] Equious updated courses/moccasin-101/1-python-in-updraft/25-install-python-macos/+page.md. --- .../1-python-in-updraft/25-install-python-macos/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/25-install-python-macos/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/25-install-python-macos/+page.md b/courses/moccasin-101/1-python-in-updraft/25-install-python-macos/+page.md new file mode 100644 index 000000000..d2148949d --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/25-install-python-macos/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Python Macos + --- \ No newline at end of file From 4cbcb6aa1cc72ed890ac4c7dcd8a0cb28fc771b2 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:33:12 -0700 Subject: [PATCH 387/797] Equious updated courses/moccasin-101/1-python-in-updraft/26-install-python-wsl-linux/+page.md. --- .../1-python-in-updraft/26-install-python-wsl-linux/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/26-install-python-wsl-linux/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/26-install-python-wsl-linux/+page.md b/courses/moccasin-101/1-python-in-updraft/26-install-python-wsl-linux/+page.md new file mode 100644 index 000000000..d18275288 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/26-install-python-wsl-linux/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Python Wsl Linux + --- \ No newline at end of file From d07f21cee28bf07fddb671b881f736c4d6234338 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:33:51 -0700 Subject: [PATCH 388/797] Equious updated courses/moccasin-101/1-python-in-updraft/27-vscode-quickstart-2/+page.md. --- .../1-python-in-updraft/27-vscode-quickstart-2/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/27-vscode-quickstart-2/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/27-vscode-quickstart-2/+page.md b/courses/moccasin-101/1-python-in-updraft/27-vscode-quickstart-2/+page.md new file mode 100644 index 000000000..7d3ad9c57 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/27-vscode-quickstart-2/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Quickstart 2 + --- \ No newline at end of file From 8d8dd041b420cd9d463d50caa20e1118f8e8ba82 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:34:05 -0700 Subject: [PATCH 389/797] Equious updated courses/moccasin-101/1-python-in-updraft/28-mental-prep/+page.md. --- .../moccasin-101/1-python-in-updraft/28-mental-prep/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/28-mental-prep/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/28-mental-prep/+page.md b/courses/moccasin-101/1-python-in-updraft/28-mental-prep/+page.md new file mode 100644 index 000000000..cfcec4377 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/28-mental-prep/+page.md @@ -0,0 +1,3 @@ +--- + title: Mental Prep + --- \ No newline at end of file From e58c666e4c27c5864594b21480a59348140a06f6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:34:18 -0700 Subject: [PATCH 390/797] Equious updated courses/moccasin-101/1-python-in-updraft/29-local-py/+page.md. --- courses/moccasin-101/1-python-in-updraft/29-local-py/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/29-local-py/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/29-local-py/+page.md b/courses/moccasin-101/1-python-in-updraft/29-local-py/+page.md new file mode 100644 index 000000000..8c591a536 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/29-local-py/+page.md @@ -0,0 +1,3 @@ +--- + title: Local Py + --- \ No newline at end of file From cd23e3d9951a023fd5463adf7dbbd41e88c13d26 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:34:32 -0700 Subject: [PATCH 391/797] Equious updated courses/moccasin-101/1-python-in-updraft/3-setup/+page.md. --- courses/moccasin-101/1-python-in-updraft/3-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/3-setup/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/3-setup/+page.md b/courses/moccasin-101/1-python-in-updraft/3-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/3-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From 17a1b5f924def9daab482510797c05158812cf07 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:34:45 -0700 Subject: [PATCH 392/797] Equious updated courses/moccasin-101/1-python-in-updraft/30-python-shell/+page.md. --- .../moccasin-101/1-python-in-updraft/30-python-shell/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/30-python-shell/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/30-python-shell/+page.md b/courses/moccasin-101/1-python-in-updraft/30-python-shell/+page.md new file mode 100644 index 000000000..9c47c3f3e --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/30-python-shell/+page.md @@ -0,0 +1,3 @@ +--- + title: Python Shell + --- \ No newline at end of file From b579c72342883e56ccb8ba89ad3550ec005858d6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:34:59 -0700 Subject: [PATCH 393/797] Equious updated courses/moccasin-101/1-python-in-updraft/31-python-extensions-vscode/+page.md. --- .../1-python-in-updraft/31-python-extensions-vscode/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/31-python-extensions-vscode/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/31-python-extensions-vscode/+page.md b/courses/moccasin-101/1-python-in-updraft/31-python-extensions-vscode/+page.md new file mode 100644 index 000000000..85f6eb88c --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/31-python-extensions-vscode/+page.md @@ -0,0 +1,3 @@ +--- + title: Python Extensions Vscode + --- \ No newline at end of file From 31c071b45cd2226db0a3dc5378e5ef9cbd62252a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:35:12 -0700 Subject: [PATCH 394/797] Equious updated courses/moccasin-101/1-python-in-updraft/32-our-first-python/+page.md. --- .../1-python-in-updraft/32-our-first-python/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/32-our-first-python/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/32-our-first-python/+page.md b/courses/moccasin-101/1-python-in-updraft/32-our-first-python/+page.md new file mode 100644 index 000000000..f790b0411 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/32-our-first-python/+page.md @@ -0,0 +1,3 @@ +--- + title: Our First Python + --- \ No newline at end of file From 43de3035a0aed9cd248ecdf9c886cdfd71f303d8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:36:59 -0700 Subject: [PATCH 395/797] Equious updated courses/moccasin-101/1-python-in-updraft/33-python-imports/+page.md. --- .../1-python-in-updraft/33-python-imports/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/33-python-imports/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/33-python-imports/+page.md b/courses/moccasin-101/1-python-in-updraft/33-python-imports/+page.md new file mode 100644 index 000000000..fae7a0f96 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/33-python-imports/+page.md @@ -0,0 +1,3 @@ +--- + title: Python Imports + --- \ No newline at end of file From a0f17e978da16fce1e552fd81ed84a5dfc6f582a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:37:18 -0700 Subject: [PATCH 396/797] Equious updated courses/moccasin-101/1-python-in-updraft/34-installing-uv/+page.md. --- .../moccasin-101/1-python-in-updraft/34-installing-uv/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/34-installing-uv/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/34-installing-uv/+page.md b/courses/moccasin-101/1-python-in-updraft/34-installing-uv/+page.md new file mode 100644 index 000000000..ef00c9919 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/34-installing-uv/+page.md @@ -0,0 +1,3 @@ +--- + title: Installing Uv + --- \ No newline at end of file From 87ebbd242e2d3dd696aed2e933854f9f352280e8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:37:38 -0700 Subject: [PATCH 397/797] Equious updated courses/moccasin-101/1-python-in-updraft/35-uv-python-version/+page.md. --- .../1-python-in-updraft/35-uv-python-version/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/35-uv-python-version/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/35-uv-python-version/+page.md b/courses/moccasin-101/1-python-in-updraft/35-uv-python-version/+page.md new file mode 100644 index 000000000..84d31ea64 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/35-uv-python-version/+page.md @@ -0,0 +1,3 @@ +--- + title: Uv Python Version + --- \ No newline at end of file From 32076439b0e0b52e5556c215290a64dd3d8bea3c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:37:51 -0700 Subject: [PATCH 398/797] Equious updated courses/moccasin-101/1-python-in-updraft/36-adding-packages-uv/+page.md. --- .../1-python-in-updraft/36-adding-packages-uv/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/36-adding-packages-uv/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/36-adding-packages-uv/+page.md b/courses/moccasin-101/1-python-in-updraft/36-adding-packages-uv/+page.md new file mode 100644 index 000000000..d2268f193 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/36-adding-packages-uv/+page.md @@ -0,0 +1,3 @@ +--- + title: Adding Packages Uv + --- \ No newline at end of file From 366b7ec251b1b9415d73b8bf35c17db1d1c0b9a1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:38:06 -0700 Subject: [PATCH 399/797] Equious updated courses/moccasin-101/1-python-in-updraft/37-virtual-envs/+page.md. --- .../moccasin-101/1-python-in-updraft/37-virtual-envs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/37-virtual-envs/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/37-virtual-envs/+page.md b/courses/moccasin-101/1-python-in-updraft/37-virtual-envs/+page.md new file mode 100644 index 000000000..c211b8e01 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/37-virtual-envs/+page.md @@ -0,0 +1,3 @@ +--- + title: Virtual Envs + --- \ No newline at end of file From 9d716873747beee69899408c9ef5953476df985d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:41:07 -0700 Subject: [PATCH 400/797] Equious updated courses/moccasin-101/1-python-in-updraft/38-recap/+page.md. --- courses/moccasin-101/1-python-in-updraft/38-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/38-recap/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/38-recap/+page.md b/courses/moccasin-101/1-python-in-updraft/38-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/38-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 6f2a375632f267afa98a14649b96dbd805a0472d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:41:41 -0700 Subject: [PATCH 401/797] Equious updated courses/moccasin-101/1-python-in-updraft/4-notebook/+page.md. --- courses/moccasin-101/1-python-in-updraft/4-notebook/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/4-notebook/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/4-notebook/+page.md b/courses/moccasin-101/1-python-in-updraft/4-notebook/+page.md new file mode 100644 index 000000000..e4cab53fa --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/4-notebook/+page.md @@ -0,0 +1,3 @@ +--- + title: Notebook + --- \ No newline at end of file From 47eebb8d5f55a4c0b078eb29f073e7ec74f1deb5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:41:55 -0700 Subject: [PATCH 402/797] Equious updated courses/moccasin-101/1-python-in-updraft/5-google-ai/+page.md. --- courses/moccasin-101/1-python-in-updraft/5-google-ai/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/5-google-ai/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/5-google-ai/+page.md b/courses/moccasin-101/1-python-in-updraft/5-google-ai/+page.md new file mode 100644 index 000000000..faa0a0f12 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/5-google-ai/+page.md @@ -0,0 +1,3 @@ +--- + title: Google Ai + --- \ No newline at end of file From 75566670eab3bf146816f88dc94b3b440a81a855 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:42:08 -0700 Subject: [PATCH 403/797] Equious updated courses/moccasin-101/1-python-in-updraft/6-python-vars/+page.md. --- .../moccasin-101/1-python-in-updraft/6-python-vars/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/6-python-vars/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/6-python-vars/+page.md b/courses/moccasin-101/1-python-in-updraft/6-python-vars/+page.md new file mode 100644 index 000000000..9d8367c72 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/6-python-vars/+page.md @@ -0,0 +1,3 @@ +--- + title: Python Vars + --- \ No newline at end of file From da0d6e85185af5db95150a1a16dd5266c6d2389b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:42:23 -0700 Subject: [PATCH 404/797] Equious updated courses/moccasin-101/1-python-in-updraft/6-type-hints/+page.md. --- courses/moccasin-101/1-python-in-updraft/6-type-hints/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/6-type-hints/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/6-type-hints/+page.md b/courses/moccasin-101/1-python-in-updraft/6-type-hints/+page.md new file mode 100644 index 000000000..3f01df5ef --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/6-type-hints/+page.md @@ -0,0 +1,3 @@ +--- + title: Type Hints + --- \ No newline at end of file From 0a79c2ae6758da282a947f2d68f5d7e360d406b4 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:42:36 -0700 Subject: [PATCH 405/797] Equious updated courses/moccasin-101/1-python-in-updraft/7-arrays/+page.md. --- courses/moccasin-101/1-python-in-updraft/7-arrays/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/7-arrays/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/7-arrays/+page.md b/courses/moccasin-101/1-python-in-updraft/7-arrays/+page.md new file mode 100644 index 000000000..267733150 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/7-arrays/+page.md @@ -0,0 +1,3 @@ +--- + title: Arrays + --- \ No newline at end of file From a40db81e0d3f435158e1a0c6763a1a054c2f199a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:42:50 -0700 Subject: [PATCH 406/797] Equious updated courses/moccasin-101/1-python-in-updraft/8-inputs/+page.md. --- courses/moccasin-101/1-python-in-updraft/8-inputs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/8-inputs/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/8-inputs/+page.md b/courses/moccasin-101/1-python-in-updraft/8-inputs/+page.md new file mode 100644 index 000000000..8a90dbef7 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/8-inputs/+page.md @@ -0,0 +1,3 @@ +--- + title: Inputs + --- \ No newline at end of file From 2e85d53d8818d41fbe3963f5a3c159e78a31e087 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:43:03 -0700 Subject: [PATCH 407/797] Equious updated courses/moccasin-101/1-python-in-updraft/9-types/+page.md. --- courses/moccasin-101/1-python-in-updraft/9-types/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/1-python-in-updraft/9-types/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/9-types/+page.md b/courses/moccasin-101/1-python-in-updraft/9-types/+page.md new file mode 100644 index 000000000..c6210ebf1 --- /dev/null +++ b/courses/moccasin-101/1-python-in-updraft/9-types/+page.md @@ -0,0 +1,3 @@ +--- + title: Types + --- \ No newline at end of file From f414a549bc30f7cc0b4b5009cee1c096c0a23321 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:45:33 -0700 Subject: [PATCH 408/797] Equious updated courses/moccasin-101/2-web3py/1-intro/+page.md. --- courses/moccasin-101/2-web3py/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/1-intro/+page.md diff --git a/courses/moccasin-101/2-web3py/1-intro/+page.md b/courses/moccasin-101/2-web3py/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/2-web3py/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From d84fe4e933135b6c9c10dc5c5e2176652634e382 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:45:53 -0700 Subject: [PATCH 409/797] Equious updated courses/moccasin-101/2-web3py/10-breakpoint/+page.md. --- courses/moccasin-101/2-web3py/10-breakpoint/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/10-breakpoint/+page.md diff --git a/courses/moccasin-101/2-web3py/10-breakpoint/+page.md b/courses/moccasin-101/2-web3py/10-breakpoint/+page.md new file mode 100644 index 000000000..36f5e29c7 --- /dev/null +++ b/courses/moccasin-101/2-web3py/10-breakpoint/+page.md @@ -0,0 +1,3 @@ +--- + title: Breakpoint + --- \ No newline at end of file From 99e732444ce8359b93c25511ce80f7416f6ecc34 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:46:08 -0700 Subject: [PATCH 410/797] Equious updated courses/moccasin-101/2-web3py/11-anvil/+page.md. --- courses/moccasin-101/2-web3py/11-anvil/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/11-anvil/+page.md diff --git a/courses/moccasin-101/2-web3py/11-anvil/+page.md b/courses/moccasin-101/2-web3py/11-anvil/+page.md new file mode 100644 index 000000000..0c0a4fdfe --- /dev/null +++ b/courses/moccasin-101/2-web3py/11-anvil/+page.md @@ -0,0 +1,3 @@ +--- + title: Anvil + --- \ No newline at end of file From d20ff5280abcdeceb3e63fd7085fb0f482b82f44 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:46:22 -0700 Subject: [PATCH 411/797] Equious updated courses/moccasin-101/2-web3py/12-anvil2/+page.md. --- courses/moccasin-101/2-web3py/12-anvil2/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/12-anvil2/+page.md diff --git a/courses/moccasin-101/2-web3py/12-anvil2/+page.md b/courses/moccasin-101/2-web3py/12-anvil2/+page.md new file mode 100644 index 000000000..e4860c609 --- /dev/null +++ b/courses/moccasin-101/2-web3py/12-anvil2/+page.md @@ -0,0 +1,3 @@ +--- + title: Anvil2 + --- \ No newline at end of file From 26da69ea8702620ebf6ef08a78e5aafcfc304e00 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:46:38 -0700 Subject: [PATCH 412/797] Equious updated courses/moccasin-101/2-web3py/13-tx/+page.md. --- courses/moccasin-101/2-web3py/13-tx/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/13-tx/+page.md diff --git a/courses/moccasin-101/2-web3py/13-tx/+page.md b/courses/moccasin-101/2-web3py/13-tx/+page.md new file mode 100644 index 000000000..e19dee8e5 --- /dev/null +++ b/courses/moccasin-101/2-web3py/13-tx/+page.md @@ -0,0 +1,3 @@ +--- + title: Tx + --- \ No newline at end of file From e5b440af27634d7a06e9f6d21c1e3fe253246f72 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:46:54 -0700 Subject: [PATCH 413/797] Equious updated courses/moccasin-101/2-web3py/14-tx/+page.md. --- courses/moccasin-101/2-web3py/14-tx/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/14-tx/+page.md diff --git a/courses/moccasin-101/2-web3py/14-tx/+page.md b/courses/moccasin-101/2-web3py/14-tx/+page.md new file mode 100644 index 000000000..e19dee8e5 --- /dev/null +++ b/courses/moccasin-101/2-web3py/14-tx/+page.md @@ -0,0 +1,3 @@ +--- + title: Tx + --- \ No newline at end of file From fc850e26d39bbf018cf22509581de289baf57721 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:47:08 -0700 Subject: [PATCH 414/797] Equious updated courses/moccasin-101/2-web3py/15-tx/+page.md. --- courses/moccasin-101/2-web3py/15-tx/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/15-tx/+page.md diff --git a/courses/moccasin-101/2-web3py/15-tx/+page.md b/courses/moccasin-101/2-web3py/15-tx/+page.md new file mode 100644 index 000000000..e19dee8e5 --- /dev/null +++ b/courses/moccasin-101/2-web3py/15-tx/+page.md @@ -0,0 +1,3 @@ +--- + title: Tx + --- \ No newline at end of file From ff9b0752c9dfa25d2ea3ca671fb19f9a588700cc Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:47:35 -0700 Subject: [PATCH 415/797] Equious updated courses/moccasin-101/2-web3py/16-nonce/+page.md. --- courses/moccasin-101/2-web3py/16-nonce/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/16-nonce/+page.md diff --git a/courses/moccasin-101/2-web3py/16-nonce/+page.md b/courses/moccasin-101/2-web3py/16-nonce/+page.md new file mode 100644 index 000000000..660543f43 --- /dev/null +++ b/courses/moccasin-101/2-web3py/16-nonce/+page.md @@ -0,0 +1,3 @@ +--- + title: Nonce + --- \ No newline at end of file From 2f47a5a1038aadd0f57fdbc3761cb7d74c1070f3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:47:54 -0700 Subject: [PATCH 416/797] Equious updated courses/moccasin-101/2-web3py/17-sign-tx/+page.md. --- courses/moccasin-101/2-web3py/17-sign-tx/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/17-sign-tx/+page.md diff --git a/courses/moccasin-101/2-web3py/17-sign-tx/+page.md b/courses/moccasin-101/2-web3py/17-sign-tx/+page.md new file mode 100644 index 000000000..d526ebfa3 --- /dev/null +++ b/courses/moccasin-101/2-web3py/17-sign-tx/+page.md @@ -0,0 +1,3 @@ +--- + title: Sign Tx + --- \ No newline at end of file From 62986d607cbcbb971d5082d9367372c811e65afc Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:48:08 -0700 Subject: [PATCH 417/797] Equious updated courses/moccasin-101/2-web3py/18-pkey-promise/+page.md. --- courses/moccasin-101/2-web3py/18-pkey-promise/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/18-pkey-promise/+page.md diff --git a/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md b/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md new file mode 100644 index 000000000..08c6274da --- /dev/null +++ b/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md @@ -0,0 +1,3 @@ +--- + title: Pkey Promise + --- \ No newline at end of file From 80c738532bf2d755f47db1a33fa3b642003e664f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:48:38 -0700 Subject: [PATCH 418/797] Equious updated courses/moccasin-101/2-web3py/19-env-vars/+page.md. --- courses/moccasin-101/2-web3py/19-env-vars/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/19-env-vars/+page.md diff --git a/courses/moccasin-101/2-web3py/19-env-vars/+page.md b/courses/moccasin-101/2-web3py/19-env-vars/+page.md new file mode 100644 index 000000000..e97071bde --- /dev/null +++ b/courses/moccasin-101/2-web3py/19-env-vars/+page.md @@ -0,0 +1,3 @@ +--- + title: Env Vars + --- \ No newline at end of file From 0e7caee6e69dd68914e0358df8c7b3f9ec88f91d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:49:03 -0700 Subject: [PATCH 419/797] Equious updated courses/moccasin-101/2-web3py/2-setup/+page.md. --- courses/moccasin-101/2-web3py/2-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/2-setup/+page.md diff --git a/courses/moccasin-101/2-web3py/2-setup/+page.md b/courses/moccasin-101/2-web3py/2-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/2-web3py/2-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From d23bcf67c509365c53f2006dff4fc40736db7b87 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:49:17 -0700 Subject: [PATCH 420/797] Equious updated courses/moccasin-101/2-web3py/20-send-tx/+page.md. --- courses/moccasin-101/2-web3py/20-send-tx/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/20-send-tx/+page.md diff --git a/courses/moccasin-101/2-web3py/20-send-tx/+page.md b/courses/moccasin-101/2-web3py/20-send-tx/+page.md new file mode 100644 index 000000000..5b4867baa --- /dev/null +++ b/courses/moccasin-101/2-web3py/20-send-tx/+page.md @@ -0,0 +1,3 @@ +--- + title: Send Tx + --- \ No newline at end of file From 2c07b57b463a9c3d986982c18382c87581fa8bc4 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:49:43 -0700 Subject: [PATCH 421/797] Equious updated courses/moccasin-101/2-web3py/21-encrypt/+page.md. --- courses/moccasin-101/2-web3py/21-encrypt/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/21-encrypt/+page.md diff --git a/courses/moccasin-101/2-web3py/21-encrypt/+page.md b/courses/moccasin-101/2-web3py/21-encrypt/+page.md new file mode 100644 index 000000000..56ef26d1d --- /dev/null +++ b/courses/moccasin-101/2-web3py/21-encrypt/+page.md @@ -0,0 +1,3 @@ +--- + title: Encrypt + --- \ No newline at end of file From 84fc0cf2f8133e1b41e73d6d91dacb4a8ff8ee08 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:52:39 -0700 Subject: [PATCH 422/797] Equious updated courses/moccasin-101/2-web3py/22-pledge/+page.md. --- courses/moccasin-101/2-web3py/22-pledge/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/22-pledge/+page.md diff --git a/courses/moccasin-101/2-web3py/22-pledge/+page.md b/courses/moccasin-101/2-web3py/22-pledge/+page.md new file mode 100644 index 000000000..dea23512b --- /dev/null +++ b/courses/moccasin-101/2-web3py/22-pledge/+page.md @@ -0,0 +1,3 @@ +--- + title: Pledge + --- \ No newline at end of file From 4edc920975f611dd2f14f11700a608d195c4af7b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:53:09 -0700 Subject: [PATCH 423/797] Equious updated courses/moccasin-101/2-web3py/23-workshop/+page.md. --- courses/moccasin-101/2-web3py/23-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/23-workshop/+page.md diff --git a/courses/moccasin-101/2-web3py/23-workshop/+page.md b/courses/moccasin-101/2-web3py/23-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/2-web3py/23-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From ecaebe8ffde9df8176f9fe7b96a2c6cf249bb40f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:56:23 -0700 Subject: [PATCH 424/797] Equious updated courses/moccasin-101/2-web3py/24-recap/+page.md. --- courses/moccasin-101/2-web3py/24-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/24-recap/+page.md diff --git a/courses/moccasin-101/2-web3py/24-recap/+page.md b/courses/moccasin-101/2-web3py/24-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/2-web3py/24-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 4eacbac1987fea0e0b2842aec138b59fd9459774 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:56:37 -0700 Subject: [PATCH 425/797] Equious updated courses/moccasin-101/2-web3py/3-vyper-extension/+page.md. --- courses/moccasin-101/2-web3py/3-vyper-extension/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/3-vyper-extension/+page.md diff --git a/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md b/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md new file mode 100644 index 000000000..e1b9b773a --- /dev/null +++ b/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md @@ -0,0 +1,3 @@ +--- + title: Vyper Extension + --- \ No newline at end of file From 5b7cfa92f3cd0ef1b9258a28d7301979af6a87cf Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:58:27 -0700 Subject: [PATCH 426/797] Equious updated courses/moccasin-101/2-web3py/4-compile-python/+page.md. --- courses/moccasin-101/2-web3py/4-compile-python/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/4-compile-python/+page.md diff --git a/courses/moccasin-101/2-web3py/4-compile-python/+page.md b/courses/moccasin-101/2-web3py/4-compile-python/+page.md new file mode 100644 index 000000000..83a888fe0 --- /dev/null +++ b/courses/moccasin-101/2-web3py/4-compile-python/+page.md @@ -0,0 +1,3 @@ +--- + title: Compile Python + --- \ No newline at end of file From 3e74e67b9a11a0d4d6bfc66ebf806451f408b32c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:59:02 -0700 Subject: [PATCH 427/797] Equious updated courses/moccasin-101/2-web3py/5-idk/+page.md. --- courses/moccasin-101/2-web3py/5-idk/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/5-idk/+page.md diff --git a/courses/moccasin-101/2-web3py/5-idk/+page.md b/courses/moccasin-101/2-web3py/5-idk/+page.md new file mode 100644 index 000000000..d226208fe --- /dev/null +++ b/courses/moccasin-101/2-web3py/5-idk/+page.md @@ -0,0 +1,3 @@ +--- + title: Idk + --- \ No newline at end of file From 64581e24b3066372da6c6479278a561dd26abc64 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:59:16 -0700 Subject: [PATCH 428/797] Equious updated courses/moccasin-101/2-web3py/6-__nam__/+page.md. --- courses/moccasin-101/2-web3py/6-__nam__/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/6-__nam__/+page.md diff --git a/courses/moccasin-101/2-web3py/6-__nam__/+page.md b/courses/moccasin-101/2-web3py/6-__nam__/+page.md new file mode 100644 index 000000000..295422d17 --- /dev/null +++ b/courses/moccasin-101/2-web3py/6-__nam__/+page.md @@ -0,0 +1,3 @@ +--- + title: __nam__ + --- \ No newline at end of file From 9653a86df07d0771af4b67b84bae4759739698a1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:59:30 -0700 Subject: [PATCH 429/797] Equious updated courses/moccasin-101/2-web3py/7-vyper-package/+page.md. --- courses/moccasin-101/2-web3py/7-vyper-package/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/7-vyper-package/+page.md diff --git a/courses/moccasin-101/2-web3py/7-vyper-package/+page.md b/courses/moccasin-101/2-web3py/7-vyper-package/+page.md new file mode 100644 index 000000000..9c7c32ed9 --- /dev/null +++ b/courses/moccasin-101/2-web3py/7-vyper-package/+page.md @@ -0,0 +1,3 @@ +--- + title: Vyper Package + --- \ No newline at end of file From 652240a92d9b826561ae32bcee4de62e10fe4b02 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:59:44 -0700 Subject: [PATCH 430/797] Equious updated courses/moccasin-101/2-web3py/8-vscode-py/+page.md. --- courses/moccasin-101/2-web3py/8-vscode-py/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/8-vscode-py/+page.md diff --git a/courses/moccasin-101/2-web3py/8-vscode-py/+page.md b/courses/moccasin-101/2-web3py/8-vscode-py/+page.md new file mode 100644 index 000000000..59d1378ea --- /dev/null +++ b/courses/moccasin-101/2-web3py/8-vscode-py/+page.md @@ -0,0 +1,3 @@ +--- + title: Vscode Py + --- \ No newline at end of file From dd1c0050a63b5434c758fb0055ec6a05e25b7bdb Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:02:58 -0700 Subject: [PATCH 431/797] Equious updated courses/moccasin-101/2-web3py/9-web3-py/+page.md. --- courses/moccasin-101/2-web3py/9-web3-py/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/2-web3py/9-web3-py/+page.md diff --git a/courses/moccasin-101/2-web3py/9-web3-py/+page.md b/courses/moccasin-101/2-web3py/9-web3-py/+page.md new file mode 100644 index 000000000..6177e0c1f --- /dev/null +++ b/courses/moccasin-101/2-web3py/9-web3-py/+page.md @@ -0,0 +1,3 @@ +--- + title: Web3 Py + --- \ No newline at end of file From 766c645baf891ebd2c2bbd5c7d780856ceafe8e0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:06:30 -0700 Subject: [PATCH 432/797] Equious updated courses/moccasin-101/3-boa-favs/1-intro/+page.md. --- courses/moccasin-101/3-boa-favs/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/1-intro/+page.md diff --git a/courses/moccasin-101/3-boa-favs/1-intro/+page.md b/courses/moccasin-101/3-boa-favs/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 4a9ee5e900bbd988873adf107d5bb0c1d1191161 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:07:04 -0700 Subject: [PATCH 433/797] Equious updated courses/moccasin-101/3-boa-favs/10-add-person/+page.md. --- courses/moccasin-101/3-boa-favs/10-add-person/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/10-add-person/+page.md diff --git a/courses/moccasin-101/3-boa-favs/10-add-person/+page.md b/courses/moccasin-101/3-boa-favs/10-add-person/+page.md new file mode 100644 index 000000000..ec6f71030 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/10-add-person/+page.md @@ -0,0 +1,3 @@ +--- + title: Add Person + --- \ No newline at end of file From 75d832b96877e65df58f62c5ef2efb4425782736 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:07:18 -0700 Subject: [PATCH 434/797] Equious updated courses/moccasin-101/3-boa-favs/11-workshop/+page.md. --- courses/moccasin-101/3-boa-favs/11-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/11-workshop/+page.md diff --git a/courses/moccasin-101/3-boa-favs/11-workshop/+page.md b/courses/moccasin-101/3-boa-favs/11-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/11-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From ced901a16d41fdd61087f4ff408fafc756d9e100 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:10:49 -0700 Subject: [PATCH 435/797] Equious updated courses/moccasin-101/3-boa-favs/12-recap/+page.md. --- courses/moccasin-101/3-boa-favs/12-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/12-recap/+page.md diff --git a/courses/moccasin-101/3-boa-favs/12-recap/+page.md b/courses/moccasin-101/3-boa-favs/12-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/12-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From ea19e66e3472d694b4938554708ac9a561fad8a9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:11:06 -0700 Subject: [PATCH 436/797] Equious updated courses/moccasin-101/3-boa-favs/2-setup/+page.md. --- courses/moccasin-101/3-boa-favs/2-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/2-setup/+page.md diff --git a/courses/moccasin-101/3-boa-favs/2-setup/+page.md b/courses/moccasin-101/3-boa-favs/2-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/2-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From 6769fab7d8bf82658191e55b83da7387df707c6e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:11:22 -0700 Subject: [PATCH 437/797] Equious updated courses/moccasin-101/3-boa-favs/3-pyevm/+page.md. --- courses/moccasin-101/3-boa-favs/3-pyevm/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/3-pyevm/+page.md diff --git a/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md b/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md new file mode 100644 index 000000000..cbbb50791 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md @@ -0,0 +1,3 @@ +--- + title: Pyevm + --- \ No newline at end of file From 21b3f6f3da6dd682af4131582f57ad336965991e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:11:42 -0700 Subject: [PATCH 438/797] Equious updated courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md. --- courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md diff --git a/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md b/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md new file mode 100644 index 000000000..51f4c8a80 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md @@ -0,0 +1,3 @@ +--- + title: Vypercontract + --- \ No newline at end of file From f3dfbf35b6ff5f2bd87fbfee96f4cd37795d4511 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:11:56 -0700 Subject: [PATCH 439/797] Equious updated courses/moccasin-101/3-boa-favs/5-debug/+page.md. --- courses/moccasin-101/3-boa-favs/5-debug/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/5-debug/+page.md diff --git a/courses/moccasin-101/3-boa-favs/5-debug/+page.md b/courses/moccasin-101/3-boa-favs/5-debug/+page.md new file mode 100644 index 000000000..746a037b4 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/5-debug/+page.md @@ -0,0 +1,3 @@ +--- + title: Debug + --- \ No newline at end of file From bd10d9f5d068b0c0cd806620b7dcbf832e0d0d80 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:12:13 -0700 Subject: [PATCH 440/797] Equious updated courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md. --- courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md diff --git a/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md b/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md new file mode 100644 index 000000000..5f76de142 --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md @@ -0,0 +1,3 @@ +--- + title: Pyevm_ + --- \ No newline at end of file From b0542a7ec2001bb2676e4574d7bb7e608b7dcd70 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:12:40 -0700 Subject: [PATCH 441/797] Equious updated courses/moccasin-101/3-boa-favs/7-anvil/+page.md. --- courses/moccasin-101/3-boa-favs/7-anvil/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/7-anvil/+page.md diff --git a/courses/moccasin-101/3-boa-favs/7-anvil/+page.md b/courses/moccasin-101/3-boa-favs/7-anvil/+page.md new file mode 100644 index 000000000..0c0a4fdfe --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/7-anvil/+page.md @@ -0,0 +1,3 @@ +--- + title: Anvil + --- \ No newline at end of file From ba15d3a7c3e9f6a4d72756ef14c132dbc8712525 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:12:58 -0700 Subject: [PATCH 442/797] Equious updated courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md. --- courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md diff --git a/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md b/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md new file mode 100644 index 000000000..85923930c --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md @@ -0,0 +1,3 @@ +--- + title: Interacting Anvil + --- \ No newline at end of file From 535dab70620c54e74736d172a985c54ae991351c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:13:26 -0700 Subject: [PATCH 443/797] Equious updated courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md. --- courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md diff --git a/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md b/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md new file mode 100644 index 000000000..87d3f90ba --- /dev/null +++ b/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md @@ -0,0 +1,3 @@ +--- + title: Interact Prevs + --- \ No newline at end of file From e6627985647bbc285a1ee02a28d2d75774162c81 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:13:55 -0700 Subject: [PATCH 444/797] Equious updated courses/moccasin-101/4-mox-favs/1-intro/+page.md. --- courses/moccasin-101/4-mox-favs/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/1-intro/+page.md diff --git a/courses/moccasin-101/4-mox-favs/1-intro/+page.md b/courses/moccasin-101/4-mox-favs/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From ee8b3cf447156f2e9f3d09be2809dac913ba2355 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:17:08 -0700 Subject: [PATCH 445/797] Equious updated courses/moccasin-101/4-mox-favs/10-account-cli/+page.md. --- courses/moccasin-101/4-mox-favs/10-account-cli/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/10-account-cli/+page.md diff --git a/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md b/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md new file mode 100644 index 000000000..0984dc172 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md @@ -0,0 +1,3 @@ +--- + title: Account Cli + --- \ No newline at end of file From f79f30105b99b3d698b9b4ea48a66ba9173327ac Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:17:32 -0700 Subject: [PATCH 446/797] Equious updated courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md. --- courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md diff --git a/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md b/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md new file mode 100644 index 000000000..7cc9872a4 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Testing + --- \ No newline at end of file From c3694229b3c7f6e3d3499ee9282fa5712f00c51e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:18:23 -0700 Subject: [PATCH 447/797] Equious updated courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md. --- .../moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md diff --git a/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md b/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md new file mode 100644 index 000000000..19850ca6b --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md @@ -0,0 +1,3 @@ +--- + title: Testing Deploy Script + --- \ No newline at end of file From ca57e5d5d573dcd6ab01aff48d3b404275957269 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:18:37 -0700 Subject: [PATCH 448/797] Equious updated courses/moccasin-101/4-mox-favs/13-aaa/+page.md. --- courses/moccasin-101/4-mox-favs/13-aaa/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/13-aaa/+page.md diff --git a/courses/moccasin-101/4-mox-favs/13-aaa/+page.md b/courses/moccasin-101/4-mox-favs/13-aaa/+page.md new file mode 100644 index 000000000..ff929f638 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/13-aaa/+page.md @@ -0,0 +1,3 @@ +--- + title: Aaa + --- \ No newline at end of file From 106300cb78b17c6b31732d30785d72b19a110a1a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:19:04 -0700 Subject: [PATCH 449/797] Equious updated courses/moccasin-101/4-mox-favs/14-fixtures/+page.md. --- courses/moccasin-101/4-mox-favs/14-fixtures/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/14-fixtures/+page.md diff --git a/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md b/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md new file mode 100644 index 000000000..48ccb103c --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md @@ -0,0 +1,3 @@ +--- + title: Fixtures + --- \ No newline at end of file From 2e95c66a9e5c6ca6488c3df23ac1acf9d3aa95ad Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:19:19 -0700 Subject: [PATCH 450/797] Equious updated courses/moccasin-101/4-mox-favs/15-conftest/+page.md. --- courses/moccasin-101/4-mox-favs/15-conftest/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/15-conftest/+page.md diff --git a/courses/moccasin-101/4-mox-favs/15-conftest/+page.md b/courses/moccasin-101/4-mox-favs/15-conftest/+page.md new file mode 100644 index 000000000..d47333a69 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/15-conftest/+page.md @@ -0,0 +1,3 @@ +--- + title: Conftest + --- \ No newline at end of file From 9b0107e5afb66f026a1b9e1f5eb7491f8a4feaaa Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:19:33 -0700 Subject: [PATCH 451/797] Equious updated courses/moccasin-101/4-mox-favs/16-type-hints/+page.md. --- courses/moccasin-101/4-mox-favs/16-type-hints/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/16-type-hints/+page.md diff --git a/courses/moccasin-101/4-mox-favs/16-type-hints/+page.md b/courses/moccasin-101/4-mox-favs/16-type-hints/+page.md new file mode 100644 index 000000000..3f01df5ef --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/16-type-hints/+page.md @@ -0,0 +1,3 @@ +--- + title: Type Hints + --- \ No newline at end of file From b2e6b899fea9de7ffd4a60010a25efd957ab1d89 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:25:44 -0700 Subject: [PATCH 452/797] Equious updated courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md. --- courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md diff --git a/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md b/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md new file mode 100644 index 000000000..ad5a0b3ab --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md @@ -0,0 +1,3 @@ +--- + title: Sepolia Deploy + --- \ No newline at end of file From 77968a6e611b9a7c29246fca176ccef1f9580c10 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:25:57 -0700 Subject: [PATCH 453/797] Equious updated courses/moccasin-101/4-mox-favs/18-verify/+page.md. --- courses/moccasin-101/4-mox-favs/18-verify/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/18-verify/+page.md diff --git a/courses/moccasin-101/4-mox-favs/18-verify/+page.md b/courses/moccasin-101/4-mox-favs/18-verify/+page.md new file mode 100644 index 000000000..0878aa404 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/18-verify/+page.md @@ -0,0 +1,3 @@ +--- + title: Verify + --- \ No newline at end of file From a362d7d39d2f5edf979ae4db6bfa246f5d165050 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:34:53 -0700 Subject: [PATCH 454/797] Equious updated courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md. --- courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md diff --git a/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md b/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md new file mode 100644 index 000000000..e03eaddb9 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync Setup + --- \ No newline at end of file From 1c2a16be9be319dde2a827b87fb0196d5422f57e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:35:25 -0700 Subject: [PATCH 455/797] Equious updated courses/moccasin-101/4-mox-favs/2-install-mox/+page.md. --- courses/moccasin-101/4-mox-favs/2-install-mox/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/2-install-mox/+page.md diff --git a/courses/moccasin-101/4-mox-favs/2-install-mox/+page.md b/courses/moccasin-101/4-mox-favs/2-install-mox/+page.md new file mode 100644 index 000000000..ef3c34f98 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/2-install-mox/+page.md @@ -0,0 +1,3 @@ +--- + title: Install Mox + --- \ No newline at end of file From 4974a57505fb31ef37df32e57f959da274cebb43 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:39:32 -0700 Subject: [PATCH 456/797] Equious updated courses/moccasin-101/4-mox-favs/20-eravm/+page.md. --- courses/moccasin-101/4-mox-favs/20-eravm/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/20-eravm/+page.md diff --git a/courses/moccasin-101/4-mox-favs/20-eravm/+page.md b/courses/moccasin-101/4-mox-favs/20-eravm/+page.md new file mode 100644 index 000000000..fef1da72f --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/20-eravm/+page.md @@ -0,0 +1,3 @@ +--- + title: Eravm + --- \ No newline at end of file From 6c44bd3a4e7d010d08c740b21176db8559cf5c96 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:40:33 -0700 Subject: [PATCH 457/797] Equious updated courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md. --- courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md diff --git a/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md b/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md new file mode 100644 index 000000000..a515e5e34 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md @@ -0,0 +1,3 @@ +--- + title: Setting Up Zksync + --- \ No newline at end of file From 04a4c1a012d8601b5d82727e7e38205d9413a77a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:40:48 -0700 Subject: [PATCH 458/797] Equious updated courses/moccasin-101/4-mox-favs/22-bridging/+page.md. --- courses/moccasin-101/4-mox-favs/22-bridging/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/22-bridging/+page.md diff --git a/courses/moccasin-101/4-mox-favs/22-bridging/+page.md b/courses/moccasin-101/4-mox-favs/22-bridging/+page.md new file mode 100644 index 000000000..1b24a95e4 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/22-bridging/+page.md @@ -0,0 +1,3 @@ +--- + title: Bridging + --- \ No newline at end of file From 586189abd5a0c9fd2549b69ab482f53a0d292e29 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:42:17 -0700 Subject: [PATCH 459/797] Equious updated courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md. --- courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md diff --git a/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md b/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md new file mode 100644 index 000000000..ef6567697 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync Deploy + --- \ No newline at end of file From dd2e3734d018058e0c5f31c0979661c27c73c150 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:42:36 -0700 Subject: [PATCH 460/797] Equious updated courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md. --- .../4-mox-favs/24-zksync-contract-deployment/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md diff --git a/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md b/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md new file mode 100644 index 000000000..7676d99dc --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync Contract Deployment + --- \ No newline at end of file From 8b44487648e9a41d9f3fa0a70e860988bba800ff Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:44:14 -0700 Subject: [PATCH 461/797] Equious updated courses/moccasin-101/4-mox-favs/25-tx-types/+page.md. --- courses/moccasin-101/4-mox-favs/25-tx-types/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/25-tx-types/+page.md diff --git a/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md b/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md new file mode 100644 index 000000000..e465b90e1 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md @@ -0,0 +1,3 @@ +--- + title: Tx Types + --- \ No newline at end of file From 951c2318a92c54ea2fe3a7fb5aac3be7898b70d1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:46:59 -0700 Subject: [PATCH 462/797] Equious updated courses/moccasin-101/4-mox-favs/26-workshop/+page.md. --- courses/moccasin-101/4-mox-favs/26-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/26-workshop/+page.md diff --git a/courses/moccasin-101/4-mox-favs/26-workshop/+page.md b/courses/moccasin-101/4-mox-favs/26-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/26-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 151038bceff1c0efcfab8fee6d8a362a167279a1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:49:34 -0700 Subject: [PATCH 463/797] Equious updated courses/moccasin-101/4-mox-favs/27-recap/+page.md. --- courses/moccasin-101/4-mox-favs/27-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/27-recap/+page.md diff --git a/courses/moccasin-101/4-mox-favs/27-recap/+page.md b/courses/moccasin-101/4-mox-favs/27-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/27-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 901b026e154778cfcc1bb63fdd36529cb9ad8f4f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:50:06 -0700 Subject: [PATCH 464/797] Equious updated courses/moccasin-101/4-mox-favs/3-create-mox/+page.md. --- courses/moccasin-101/4-mox-favs/3-create-mox/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/3-create-mox/+page.md diff --git a/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md b/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md new file mode 100644 index 000000000..0f542f929 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md @@ -0,0 +1,3 @@ +--- + title: Create Mox + --- \ No newline at end of file From dd848aaf2e399a1def1b7e019b0054bd12c82e03 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:50:20 -0700 Subject: [PATCH 465/797] Equious updated courses/moccasin-101/4-mox-favs/4-mox-something/+page.md. --- courses/moccasin-101/4-mox-favs/4-mox-something/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/4-mox-something/+page.md diff --git a/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md b/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md new file mode 100644 index 000000000..e56710475 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Something + --- \ No newline at end of file From edcfebab44c762164e366e8d5226b96068479ea8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:50:35 -0700 Subject: [PATCH 466/797] Equious updated courses/moccasin-101/4-mox-favs/5-mox-script/+page.md. --- courses/moccasin-101/4-mox-favs/5-mox-script/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/5-mox-script/+page.md diff --git a/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md b/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md new file mode 100644 index 000000000..9b8bba199 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Script + --- \ No newline at end of file From 1e792c7af62e979d834090d09697aa8b05b4f335 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:53:36 -0700 Subject: [PATCH 467/797] Equious updated courses/moccasin-101/4-mox-favs/6-other-net/+page.md. --- courses/moccasin-101/4-mox-favs/6-other-net/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/6-other-net/+page.md diff --git a/courses/moccasin-101/4-mox-favs/6-other-net/+page.md b/courses/moccasin-101/4-mox-favs/6-other-net/+page.md new file mode 100644 index 000000000..19588553c --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/6-other-net/+page.md @@ -0,0 +1,3 @@ +--- + title: Other Net + --- \ No newline at end of file From 814edcea2eb21a98eb249199968b09ebae2f9179 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:53:50 -0700 Subject: [PATCH 468/797] Equious updated courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md. --- courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md diff --git a/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md b/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md new file mode 100644 index 000000000..7ab4c1ff8 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md @@ -0,0 +1,3 @@ +--- + title: Encrypt Key + --- \ No newline at end of file From 4c396ae4167867aeb6eba043b39f11d9d1cdb1fe Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:54:12 -0700 Subject: [PATCH 469/797] Equious updated courses/moccasin-101/4-mox-favs/8-shell/+page.md. --- courses/moccasin-101/4-mox-favs/8-shell/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/8-shell/+page.md diff --git a/courses/moccasin-101/4-mox-favs/8-shell/+page.md b/courses/moccasin-101/4-mox-favs/8-shell/+page.md new file mode 100644 index 000000000..00df35f0d --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/8-shell/+page.md @@ -0,0 +1,3 @@ +--- + title: Shell + --- \ No newline at end of file From 93336cb6459897e1137e76c288b67f4ea1bfcd48 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:54:24 -0700 Subject: [PATCH 470/797] Equious updated courses/moccasin-101/4-mox-favs/9-using-key/+page.md. --- courses/moccasin-101/4-mox-favs/9-using-key/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/4-mox-favs/9-using-key/+page.md diff --git a/courses/moccasin-101/4-mox-favs/9-using-key/+page.md b/courses/moccasin-101/4-mox-favs/9-using-key/+page.md new file mode 100644 index 000000000..dd0adc820 --- /dev/null +++ b/courses/moccasin-101/4-mox-favs/9-using-key/+page.md @@ -0,0 +1,3 @@ +--- + title: Using Key + --- \ No newline at end of file From 6ea1a5f4e28192e62d3347c7fcbaf2a04cfccf92 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:56:05 -0700 Subject: [PATCH 471/797] Equious updated courses/moccasin-101/5-mox-five/1-intro/+page.md. --- courses/moccasin-101/5-mox-five/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/1-intro/+page.md diff --git a/courses/moccasin-101/5-mox-five/1-intro/+page.md b/courses/moccasin-101/5-mox-five/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From bc8b2ab9e20ebf31b0de60f3d722872f6fa98eca Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:56:36 -0700 Subject: [PATCH 472/797] Equious updated courses/moccasin-101/5-mox-five/10-vyper-modules/+page.md. --- courses/moccasin-101/5-mox-five/10-vyper-modules/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/10-vyper-modules/+page.md diff --git a/courses/moccasin-101/5-mox-five/10-vyper-modules/+page.md b/courses/moccasin-101/5-mox-five/10-vyper-modules/+page.md new file mode 100644 index 000000000..92ee2de81 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/10-vyper-modules/+page.md @@ -0,0 +1,3 @@ +--- + title: Vyper Modules + --- \ No newline at end of file From ce5a792319af3aa65657c93e0cb2e4dd2210455a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 01:59:28 -0700 Subject: [PATCH 473/797] Equious updated courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md. --- .../5-mox-five/11-initializes-module-state/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md diff --git a/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md b/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md new file mode 100644 index 000000000..7096200f7 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md @@ -0,0 +1,3 @@ +--- + title: Initializes Module State + --- \ No newline at end of file From 5789cc7cb1fff979c4bf991dd850011326c6e3fb Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:00:31 -0700 Subject: [PATCH 474/797] Equious updated courses/moccasin-101/5-mox-five/12-exports/+page.md. --- courses/moccasin-101/5-mox-five/12-exports/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/12-exports/+page.md diff --git a/courses/moccasin-101/5-mox-five/12-exports/+page.md b/courses/moccasin-101/5-mox-five/12-exports/+page.md new file mode 100644 index 000000000..cd5b9a644 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/12-exports/+page.md @@ -0,0 +1,3 @@ +--- + title: Exports + --- \ No newline at end of file From 80868271e8bd2d6e519ae2312d52a185d7c6bc41 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:02:08 -0700 Subject: [PATCH 475/797] Equious updated courses/moccasin-101/5-mox-five/13-workshop/+page.md. --- courses/moccasin-101/5-mox-five/13-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/13-workshop/+page.md diff --git a/courses/moccasin-101/5-mox-five/13-workshop/+page.md b/courses/moccasin-101/5-mox-five/13-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/13-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 09013b076ee378283c8e6c628bf167e3c3e3e58b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:03:45 -0700 Subject: [PATCH 476/797] Equious updated courses/moccasin-101/5-mox-five/14-recap/+page.md. --- courses/moccasin-101/5-mox-five/14-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/14-recap/+page.md diff --git a/courses/moccasin-101/5-mox-five/14-recap/+page.md b/courses/moccasin-101/5-mox-five/14-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/5-mox-five/14-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 4cb4a3e2a5c5e5f20b57b5599e829198ec866318 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:06:42 -0700 Subject: [PATCH 477/797] Equious updated courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md. --- courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md diff --git a/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md b/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md new file mode 100644 index 000000000..a391afc59 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md @@ -0,0 +1,3 @@ +--- + title: Create Copy Of + --- \ No newline at end of file From d458ea3aba2ce346eb479e153731acc63f5cf054 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:07:01 -0700 Subject: [PATCH 478/797] Equious updated courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md. --- courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md diff --git a/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md b/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md new file mode 100644 index 000000000..e5dcc0071 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md @@ -0,0 +1,3 @@ +--- + title: Static Ext Call + --- \ No newline at end of file From 613cd3df04434008c6ffbb8514b407c37e1ee826 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:08:12 -0700 Subject: [PATCH 479/797] Equious updated courses/moccasin-101/5-mox-five/5-vyi/+page.md. --- courses/moccasin-101/5-mox-five/5-vyi/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/5-vyi/+page.md diff --git a/courses/moccasin-101/5-mox-five/5-vyi/+page.md b/courses/moccasin-101/5-mox-five/5-vyi/+page.md new file mode 100644 index 000000000..62bd446ed --- /dev/null +++ b/courses/moccasin-101/5-mox-five/5-vyi/+page.md @@ -0,0 +1,3 @@ +--- + title: Vyi + --- \ No newline at end of file From cb0e36021535e0594e5a2e63a02e8bf0e7952744 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:08:28 -0700 Subject: [PATCH 480/797] Equious updated courses/moccasin-101/5-mox-five/6-idk/+page.md. --- courses/moccasin-101/5-mox-five/6-idk/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/6-idk/+page.md diff --git a/courses/moccasin-101/5-mox-five/6-idk/+page.md b/courses/moccasin-101/5-mox-five/6-idk/+page.md new file mode 100644 index 000000000..d226208fe --- /dev/null +++ b/courses/moccasin-101/5-mox-five/6-idk/+page.md @@ -0,0 +1,3 @@ +--- + title: Idk + --- \ No newline at end of file From 5dc67219509debebc8754333581b58ed11d2716c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:09:23 -0700 Subject: [PATCH 481/797] Equious updated courses/moccasin-101/5-mox-five/7-extcall/+page.md. --- courses/moccasin-101/5-mox-five/7-extcall/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/7-extcall/+page.md diff --git a/courses/moccasin-101/5-mox-five/7-extcall/+page.md b/courses/moccasin-101/5-mox-five/7-extcall/+page.md new file mode 100644 index 000000000..36c841a81 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/7-extcall/+page.md @@ -0,0 +1,3 @@ +--- + title: Extcall + --- \ No newline at end of file From 0c53de5250b1a16cae20e0cdc5431400e96d2e9f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:09:37 -0700 Subject: [PATCH 482/797] Equious updated courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md. --- .../5-mox-five/8-store-contract-by-interface/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md diff --git a/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md b/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md new file mode 100644 index 000000000..d79d0e7af --- /dev/null +++ b/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md @@ -0,0 +1,3 @@ +--- + title: Store Contract By Interface + --- \ No newline at end of file From 60ca58f8f15dd98d6af89cc2baf4dec595cc2772 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:10:05 -0700 Subject: [PATCH 483/797] Equious updated courses/moccasin-101/5-mox-five/9-method-chaining/+page.md. --- courses/moccasin-101/5-mox-five/9-method-chaining/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/5-mox-five/9-method-chaining/+page.md diff --git a/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md b/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md new file mode 100644 index 000000000..2aa8fbe12 --- /dev/null +++ b/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md @@ -0,0 +1,3 @@ +--- + title: Method Chaining + --- \ No newline at end of file From bc6ec0e82455e293ea84b2e69094b7e228efdada Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:12:08 -0700 Subject: [PATCH 484/797] Equious updated courses/moccasin-101/6-mox-coffee/1-intro/+page.md. --- courses/moccasin-101/6-mox-coffee/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/1-intro/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/1-intro/+page.md b/courses/moccasin-101/6-mox-coffee/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From 58aa57c5d82a11390a28195b07ca67dc9f6d3185 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:13:43 -0700 Subject: [PATCH 485/797] Equious updated courses/moccasin-101/6-mox-coffee/10-kinds/+page.md. --- courses/moccasin-101/6-mox-coffee/10-kinds/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/10-kinds/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md b/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md new file mode 100644 index 000000000..3a20eb491 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md @@ -0,0 +1,3 @@ +--- + title: Kinds + --- \ No newline at end of file From b901e9273d544fac8bc44e50d4d0d3b2b8bdcbee Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:14:15 -0700 Subject: [PATCH 486/797] Equious updated courses/moccasin-101/6-mox-coffee/11-unit/+page.md. --- courses/moccasin-101/6-mox-coffee/11-unit/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/11-unit/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/11-unit/+page.md b/courses/moccasin-101/6-mox-coffee/11-unit/+page.md new file mode 100644 index 000000000..ef3d00c8c --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/11-unit/+page.md @@ -0,0 +1,3 @@ +--- + title: Unit + --- \ No newline at end of file From af3b3da42f404a9bcd2775779d9b8279fec80fb4 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:14:30 -0700 Subject: [PATCH 487/797] Equious updated courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md. --- courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md b/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md new file mode 100644 index 000000000..66d5d3331 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md @@ -0,0 +1,3 @@ +--- + title: Test Revert + --- \ No newline at end of file From 478ef14757f734a3392c0f5ad67fa1b44ecb09a6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:14:44 -0700 Subject: [PATCH 488/797] Equious updated courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md. --- courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md b/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md new file mode 100644 index 000000000..b44c55fda --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md @@ -0,0 +1,3 @@ +--- + title: Set Balance + --- \ No newline at end of file From a359a9f74ff6643c1c416443070c9caf699ab7e0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:15:01 -0700 Subject: [PATCH 489/797] Equious updated courses/moccasin-101/6-mox-coffee/14-prank/+page.md. --- courses/moccasin-101/6-mox-coffee/14-prank/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/14-prank/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/14-prank/+page.md b/courses/moccasin-101/6-mox-coffee/14-prank/+page.md new file mode 100644 index 000000000..024a80546 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/14-prank/+page.md @@ -0,0 +1,3 @@ +--- + title: Prank + --- \ No newline at end of file From 22b00939317596e680a9e3888e79f89cc22c4a10 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:15:16 -0700 Subject: [PATCH 490/797] Equious updated courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md. --- courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md b/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md new file mode 100644 index 000000000..510c15538 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md @@ -0,0 +1,3 @@ +--- + title: Mid Sec Work + --- \ No newline at end of file From 9e5dcbd352520c6d0a3bac4cfda420499ffdfcaf Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:15:30 -0700 Subject: [PATCH 491/797] Equious updated courses/moccasin-101/6-mox-coffee/16-more-fixtures/+page.md. --- courses/moccasin-101/6-mox-coffee/16-more-fixtures/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/16-more-fixtures/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/16-more-fixtures/+page.md b/courses/moccasin-101/6-mox-coffee/16-more-fixtures/+page.md new file mode 100644 index 000000000..e5d0bc24e --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/16-more-fixtures/+page.md @@ -0,0 +1,3 @@ +--- + title: More Fixtures + --- \ No newline at end of file From 339965a84bb18415b3a2ba43ade0ad778e9b1088 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:15:44 -0700 Subject: [PATCH 492/797] Equious updated courses/moccasin-101/6-mox-coffee/17-test-coverage/+page.md. --- courses/moccasin-101/6-mox-coffee/17-test-coverage/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/17-test-coverage/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/17-test-coverage/+page.md b/courses/moccasin-101/6-mox-coffee/17-test-coverage/+page.md new file mode 100644 index 000000000..25317a24e --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/17-test-coverage/+page.md @@ -0,0 +1,3 @@ +--- + title: Test Coverage + --- \ No newline at end of file From 7906f4fb494ade528e9000e951bf8b2d62f708d8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:17:22 -0700 Subject: [PATCH 493/797] Equious updated courses/moccasin-101/6-mox-coffee/18-gas-profile/+page.md. --- courses/moccasin-101/6-mox-coffee/18-gas-profile/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/18-gas-profile/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/18-gas-profile/+page.md b/courses/moccasin-101/6-mox-coffee/18-gas-profile/+page.md new file mode 100644 index 000000000..88ca818ae --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/18-gas-profile/+page.md @@ -0,0 +1,3 @@ +--- + title: Gas Profile + --- \ No newline at end of file From c59514d692bcb74ffc39b83018a45dabb1e9f28d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:19:02 -0700 Subject: [PATCH 494/797] Equious updated courses/moccasin-101/6-mox-coffee/19-fork-tests/+page.md. --- courses/moccasin-101/6-mox-coffee/19-fork-tests/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/19-fork-tests/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/19-fork-tests/+page.md b/courses/moccasin-101/6-mox-coffee/19-fork-tests/+page.md new file mode 100644 index 000000000..2c00fcac4 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/19-fork-tests/+page.md @@ -0,0 +1,3 @@ +--- + title: Fork Tests + --- \ No newline at end of file From cb484bfc4cb8a6ff3ec0d6c4a0b085fc56497194 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:19:16 -0700 Subject: [PATCH 495/797] Equious updated courses/moccasin-101/6-mox-coffee/2-setup/+page.md. --- courses/moccasin-101/6-mox-coffee/2-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/2-setup/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/2-setup/+page.md b/courses/moccasin-101/6-mox-coffee/2-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/2-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From f690330569c68f94e5b98c98ff512b559943f1de Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:19:32 -0700 Subject: [PATCH 496/797] Equious updated courses/moccasin-101/6-mox-coffee/20-staging/+page.md. --- courses/moccasin-101/6-mox-coffee/20-staging/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/20-staging/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/20-staging/+page.md b/courses/moccasin-101/6-mox-coffee/20-staging/+page.md new file mode 100644 index 000000000..f2de04c12 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/20-staging/+page.md @@ -0,0 +1,3 @@ +--- + title: Staging + --- \ No newline at end of file From 6e40a3af896144208c560d1ceec47a1651810b6c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:19:59 -0700 Subject: [PATCH 497/797] Equious updated courses/moccasin-101/6-mox-coffee/21-deployments-db/+page.md. --- courses/moccasin-101/6-mox-coffee/21-deployments-db/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/21-deployments-db/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/21-deployments-db/+page.md b/courses/moccasin-101/6-mox-coffee/21-deployments-db/+page.md new file mode 100644 index 000000000..d1459d73d --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/21-deployments-db/+page.md @@ -0,0 +1,3 @@ +--- + title: Deployments Db + --- \ No newline at end of file From 75fb7416a5e3d19a706dcb16b5dd3b0d90aee121 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:20:14 -0700 Subject: [PATCH 498/797] Equious updated courses/moccasin-101/6-mox-coffee/22-zksync-testing/+page.md. --- courses/moccasin-101/6-mox-coffee/22-zksync-testing/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/22-zksync-testing/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/22-zksync-testing/+page.md b/courses/moccasin-101/6-mox-coffee/22-zksync-testing/+page.md new file mode 100644 index 000000000..4f5922387 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/22-zksync-testing/+page.md @@ -0,0 +1,3 @@ +--- + title: Zksync Testing + --- \ No newline at end of file From 799c199e336f457055aa72923f6fbc0a0e87663f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:27:43 -0700 Subject: [PATCH 499/797] Equious updated courses/moccasin-101/6-mox-coffee/23-github/+page.md. --- courses/moccasin-101/6-mox-coffee/23-github/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/23-github/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/23-github/+page.md b/courses/moccasin-101/6-mox-coffee/23-github/+page.md new file mode 100644 index 000000000..759cfde0e --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/23-github/+page.md @@ -0,0 +1,3 @@ +--- + title: Github + --- \ No newline at end of file From 02f3f05e6c013e9c631d8c045b6873d36b32804f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:28:51 -0700 Subject: [PATCH 500/797] Equious updated courses/moccasin-101/6-mox-coffee/24-clone/+page.md. --- courses/moccasin-101/6-mox-coffee/24-clone/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/24-clone/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/24-clone/+page.md b/courses/moccasin-101/6-mox-coffee/24-clone/+page.md new file mode 100644 index 000000000..bdc0c631b --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/24-clone/+page.md @@ -0,0 +1,3 @@ +--- + title: Clone + --- \ No newline at end of file From c838b6b6bb1b49a015da82ad31d9ff649d9e6a85 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:30:14 -0700 Subject: [PATCH 501/797] Equious updated courses/moccasin-101/6-mox-coffee/25-workshop/+page.md. --- courses/moccasin-101/6-mox-coffee/25-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/25-workshop/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/25-workshop/+page.md b/courses/moccasin-101/6-mox-coffee/25-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/25-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From a92965a9c3a4e9f7332e6a8c1c7b73ea2d229034 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:32:41 -0700 Subject: [PATCH 502/797] Equious updated courses/moccasin-101/6-mox-coffee/26-recap/+page.md. --- courses/moccasin-101/6-mox-coffee/26-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/26-recap/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/26-recap/+page.md b/courses/moccasin-101/6-mox-coffee/26-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/26-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From cdfd7e6e14c3679107ef35c3ee1bcd5be499c766 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:33:12 -0700 Subject: [PATCH 503/797] Equious updated courses/moccasin-101/6-mox-coffee/3-refactor/+page.md. --- courses/moccasin-101/6-mox-coffee/3-refactor/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/3-refactor/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/3-refactor/+page.md b/courses/moccasin-101/6-mox-coffee/3-refactor/+page.md new file mode 100644 index 000000000..fc4ec237d --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/3-refactor/+page.md @@ -0,0 +1,3 @@ +--- + title: Refactor + --- \ No newline at end of file From 63602cf2aa9689f6053d671763fa687f07012e30 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:39:24 -0700 Subject: [PATCH 504/797] Equious updated courses/moccasin-101/6-mox-coffee/4-storage/+page.md. --- courses/moccasin-101/6-mox-coffee/4-storage/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/4-storage/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/4-storage/+page.md b/courses/moccasin-101/6-mox-coffee/4-storage/+page.md new file mode 100644 index 000000000..841e6f34e --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/4-storage/+page.md @@ -0,0 +1,3 @@ +--- + title: Storage + --- \ No newline at end of file From 8a71ed51a5c6096dda96633cb5a36747bec61644 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:39:37 -0700 Subject: [PATCH 505/797] Equious updated courses/moccasin-101/6-mox-coffee/5-refactor-2/+page.md. --- courses/moccasin-101/6-mox-coffee/5-refactor-2/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/5-refactor-2/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/5-refactor-2/+page.md b/courses/moccasin-101/6-mox-coffee/5-refactor-2/+page.md new file mode 100644 index 000000000..b558ca50c --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/5-refactor-2/+page.md @@ -0,0 +1,3 @@ +--- + title: Refactor 2 + --- \ No newline at end of file From 9691cc2d4c2c3d3b0c7615319f66b22237dd0f9f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:40:03 -0700 Subject: [PATCH 506/797] Equious updated courses/moccasin-101/6-mox-coffee/6-script/+page.md. --- courses/moccasin-101/6-mox-coffee/6-script/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/6-script/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/6-script/+page.md b/courses/moccasin-101/6-mox-coffee/6-script/+page.md new file mode 100644 index 000000000..dfe2f7e16 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/6-script/+page.md @@ -0,0 +1,3 @@ +--- + title: Script + --- \ No newline at end of file From 5d1a78459407caca618e30854f6e573c9b16e099 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:40:30 -0700 Subject: [PATCH 507/797] Equious updated courses/moccasin-101/6-mox-coffee/7-mocks/+page.md. --- courses/moccasin-101/6-mox-coffee/7-mocks/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/7-mocks/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/7-mocks/+page.md b/courses/moccasin-101/6-mox-coffee/7-mocks/+page.md new file mode 100644 index 000000000..672e8594e --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/7-mocks/+page.md @@ -0,0 +1,3 @@ +--- + title: Mocks + --- \ No newline at end of file From 271b35499a2b46885f539d5978f9487e54c0f843 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:45:16 -0700 Subject: [PATCH 508/797] Equious updated courses/moccasin-101/6-mox-coffee/8-manifest/+page.md. --- courses/moccasin-101/6-mox-coffee/8-manifest/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/8-manifest/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/8-manifest/+page.md b/courses/moccasin-101/6-mox-coffee/8-manifest/+page.md new file mode 100644 index 000000000..94d3524f0 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/8-manifest/+page.md @@ -0,0 +1,3 @@ +--- + title: Manifest + --- \ No newline at end of file From cf8747fe06beddcd4a9375299c6225d5378d4394 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:45:32 -0700 Subject: [PATCH 509/797] Equious updated courses/moccasin-101/6-mox-coffee/9-top-level/+page.md. --- courses/moccasin-101/6-mox-coffee/9-top-level/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/6-mox-coffee/9-top-level/+page.md diff --git a/courses/moccasin-101/6-mox-coffee/9-top-level/+page.md b/courses/moccasin-101/6-mox-coffee/9-top-level/+page.md new file mode 100644 index 000000000..1006fc842 --- /dev/null +++ b/courses/moccasin-101/6-mox-coffee/9-top-level/+page.md @@ -0,0 +1,3 @@ +--- + title: Top Level + --- \ No newline at end of file From a1db84c90a853525297894f1cd48e3b8b8c00611 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:45:46 -0700 Subject: [PATCH 510/797] Equious updated courses/moccasin-101/7-mox-html/1-mox-intro/+page.md. --- courses/moccasin-101/7-mox-html/1-mox-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/7-mox-html/1-mox-intro/+page.md diff --git a/courses/moccasin-101/7-mox-html/1-mox-intro/+page.md b/courses/moccasin-101/7-mox-html/1-mox-intro/+page.md new file mode 100644 index 000000000..f82ad97f5 --- /dev/null +++ b/courses/moccasin-101/7-mox-html/1-mox-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Intro + --- \ No newline at end of file From 3bae74d90abb41910c156f10447a0400d01d001a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:45:59 -0700 Subject: [PATCH 511/797] Equious updated courses/moccasin-101/7-mox-html/2-introduction/+page.md. --- courses/moccasin-101/7-mox-html/2-introduction/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/7-mox-html/2-introduction/+page.md diff --git a/courses/moccasin-101/7-mox-html/2-introduction/+page.md b/courses/moccasin-101/7-mox-html/2-introduction/+page.md new file mode 100644 index 000000000..c21ef2ce7 --- /dev/null +++ b/courses/moccasin-101/7-mox-html/2-introduction/+page.md @@ -0,0 +1,3 @@ +--- + title: Introduction + --- \ No newline at end of file From 84c46e3bca9801cbeca731e83229bbdf6c13d919 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:46:12 -0700 Subject: [PATCH 512/797] Equious updated courses/moccasin-101/7-mox-html/3-setup/+page.md. --- courses/moccasin-101/7-mox-html/3-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/7-mox-html/3-setup/+page.md diff --git a/courses/moccasin-101/7-mox-html/3-setup/+page.md b/courses/moccasin-101/7-mox-html/3-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/7-mox-html/3-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From 23ac52c044851c0806237483daf15c9d717a858f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:46:36 -0700 Subject: [PATCH 513/797] Equious updated courses/moccasin-101/7-mox-html/4-metamask/+page.md. --- courses/moccasin-101/7-mox-html/4-metamask/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/7-mox-html/4-metamask/+page.md diff --git a/courses/moccasin-101/7-mox-html/4-metamask/+page.md b/courses/moccasin-101/7-mox-html/4-metamask/+page.md new file mode 100644 index 000000000..e823921f3 --- /dev/null +++ b/courses/moccasin-101/7-mox-html/4-metamask/+page.md @@ -0,0 +1,3 @@ +--- + title: Metamask + --- \ No newline at end of file From 23b36fe61cd5ce6c0ccd67e0c0584dbecb467120 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:46:52 -0700 Subject: [PATCH 514/797] Equious updated courses/moccasin-101/7-mox-html/5-function-selectors/+page.md. --- courses/moccasin-101/7-mox-html/5-function-selectors/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/7-mox-html/5-function-selectors/+page.md diff --git a/courses/moccasin-101/7-mox-html/5-function-selectors/+page.md b/courses/moccasin-101/7-mox-html/5-function-selectors/+page.md new file mode 100644 index 000000000..73abb7ab1 --- /dev/null +++ b/courses/moccasin-101/7-mox-html/5-function-selectors/+page.md @@ -0,0 +1,3 @@ +--- + title: Function Selectors + --- \ No newline at end of file From bf77ca7a12631dcbde4259bd2a82b3d11df16a8a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:47:06 -0700 Subject: [PATCH 515/797] Equious updated courses/moccasin-101/7-mox-html/6-summary/+page.md. --- courses/moccasin-101/7-mox-html/6-summary/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/7-mox-html/6-summary/+page.md diff --git a/courses/moccasin-101/7-mox-html/6-summary/+page.md b/courses/moccasin-101/7-mox-html/6-summary/+page.md new file mode 100644 index 000000000..f68223117 --- /dev/null +++ b/courses/moccasin-101/7-mox-html/6-summary/+page.md @@ -0,0 +1,3 @@ +--- + title: Summary + --- \ No newline at end of file From 15e075d22b192711b47d0a9d4ef0a3ebc1f1b9f9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:49:37 -0700 Subject: [PATCH 516/797] Equious updated courses/moccasin-101/8-mox-erc20/1-intro/+page.md. --- courses/moccasin-101/8-mox-erc20/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/1-intro/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/1-intro/+page.md b/courses/moccasin-101/8-mox-erc20/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From b08ac2127405470bc62c091c5538be929e542388 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:49:51 -0700 Subject: [PATCH 517/797] Equious updated courses/moccasin-101/8-mox-erc20/10-built-in-interfaces/+page.md. --- .../moccasin-101/8-mox-erc20/10-built-in-interfaces/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/10-built-in-interfaces/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/10-built-in-interfaces/+page.md b/courses/moccasin-101/8-mox-erc20/10-built-in-interfaces/+page.md new file mode 100644 index 000000000..8aa752e0f --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/10-built-in-interfaces/+page.md @@ -0,0 +1,3 @@ +--- + title: Built In Interfaces + --- \ No newline at end of file From ee5cdf40b57c4629b0112a1ffb84980c64903d37 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:50:04 -0700 Subject: [PATCH 518/797] Equious updated courses/moccasin-101/8-mox-erc20/11-deploy-scripts/+page.md. --- courses/moccasin-101/8-mox-erc20/11-deploy-scripts/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/11-deploy-scripts/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/11-deploy-scripts/+page.md b/courses/moccasin-101/8-mox-erc20/11-deploy-scripts/+page.md new file mode 100644 index 000000000..5d5d180f8 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/11-deploy-scripts/+page.md @@ -0,0 +1,3 @@ +--- + title: Deploy Scripts + --- \ No newline at end of file From bb12dff77a864eebf93e02d930250c6215199d26 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:50:18 -0700 Subject: [PATCH 519/797] Equious updated courses/moccasin-101/8-mox-erc20/12-tests/+page.md. --- courses/moccasin-101/8-mox-erc20/12-tests/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/12-tests/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/12-tests/+page.md b/courses/moccasin-101/8-mox-erc20/12-tests/+page.md new file mode 100644 index 000000000..564ea6dda --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/12-tests/+page.md @@ -0,0 +1,3 @@ +--- + title: Tests + --- \ No newline at end of file From 871861b80462852f81c8e3c343a1621f4cc3efc4 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:55:04 -0700 Subject: [PATCH 520/797] Equious updated courses/moccasin-101/8-mox-erc20/13-events/+page.md. --- courses/moccasin-101/8-mox-erc20/13-events/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/13-events/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/13-events/+page.md b/courses/moccasin-101/8-mox-erc20/13-events/+page.md new file mode 100644 index 000000000..9e8e1b107 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/13-events/+page.md @@ -0,0 +1,3 @@ +--- + title: Events + --- \ No newline at end of file From b445bd6793ac0e1b2c0a2a5b8fecf1efe7769875 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:55:19 -0700 Subject: [PATCH 521/797] Equious updated courses/moccasin-101/8-mox-erc20/14-testing-events/+page.md. --- courses/moccasin-101/8-mox-erc20/14-testing-events/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/14-testing-events/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/14-testing-events/+page.md b/courses/moccasin-101/8-mox-erc20/14-testing-events/+page.md new file mode 100644 index 000000000..61a1a8118 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/14-testing-events/+page.md @@ -0,0 +1,3 @@ +--- + title: Testing Events + --- \ No newline at end of file From 17bce02a2c2cf3998dc5e50131ff56bce44e2b69 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:55:33 -0700 Subject: [PATCH 522/797] Equious updated courses/moccasin-101/8-mox-erc20/15-formatting/+page.md. --- courses/moccasin-101/8-mox-erc20/15-formatting/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/15-formatting/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/15-formatting/+page.md b/courses/moccasin-101/8-mox-erc20/15-formatting/+page.md new file mode 100644 index 000000000..33a74c43a --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/15-formatting/+page.md @@ -0,0 +1,3 @@ +--- + title: Formatting + --- \ No newline at end of file From da6b2a77492c853ca5f58384a749d44892ee9ce5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:55:48 -0700 Subject: [PATCH 523/797] Equious updated courses/moccasin-101/8-mox-erc20/16-justfile/+page.md. --- courses/moccasin-101/8-mox-erc20/16-justfile/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/16-justfile/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/16-justfile/+page.md b/courses/moccasin-101/8-mox-erc20/16-justfile/+page.md new file mode 100644 index 000000000..1c66d6614 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/16-justfile/+page.md @@ -0,0 +1,3 @@ +--- + title: Justfile + --- \ No newline at end of file From d949dfaf14260d52b9fa70e0b403526755c3f966 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 02:56:03 -0700 Subject: [PATCH 524/797] Equious updated courses/moccasin-101/8-mox-erc20/17-vheaders/+page.md. --- courses/moccasin-101/8-mox-erc20/17-vheaders/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/17-vheaders/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/17-vheaders/+page.md b/courses/moccasin-101/8-mox-erc20/17-vheaders/+page.md new file mode 100644 index 000000000..f03fb7dd5 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/17-vheaders/+page.md @@ -0,0 +1,3 @@ +--- + title: Vheaders + --- \ No newline at end of file From bf8cfe48e4425eb495a3b9756d94db35457cf5f0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:02:13 -0700 Subject: [PATCH 525/797] Equious updated courses/moccasin-101/8-mox-erc20/18-fuzzing/+page.md. --- courses/moccasin-101/8-mox-erc20/18-fuzzing/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/18-fuzzing/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/18-fuzzing/+page.md b/courses/moccasin-101/8-mox-erc20/18-fuzzing/+page.md new file mode 100644 index 000000000..a52eae390 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/18-fuzzing/+page.md @@ -0,0 +1,3 @@ +--- + title: Fuzzing + --- \ No newline at end of file From 68606bc95ba626d0c5fd0b142b0ba9595367a912 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:05:15 -0700 Subject: [PATCH 526/797] Equious updated courses/moccasin-101/8-mox-erc20/19-stateless-fuzz/+page.md. --- courses/moccasin-101/8-mox-erc20/19-stateless-fuzz/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/19-stateless-fuzz/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/19-stateless-fuzz/+page.md b/courses/moccasin-101/8-mox-erc20/19-stateless-fuzz/+page.md new file mode 100644 index 000000000..0b6bd8f45 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/19-stateless-fuzz/+page.md @@ -0,0 +1,3 @@ +--- + title: Stateless Fuzz + --- \ No newline at end of file From 20f9c14a1e60b178328b8f1bd37032648a285e3c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:05:35 -0700 Subject: [PATCH 527/797] Equious updated courses/moccasin-101/8-mox-erc20/2-setup/+page.md. --- courses/moccasin-101/8-mox-erc20/2-setup/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/2-setup/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/2-setup/+page.md b/courses/moccasin-101/8-mox-erc20/2-setup/+page.md new file mode 100644 index 000000000..fcc7a149d --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/2-setup/+page.md @@ -0,0 +1,3 @@ +--- + title: Setup + --- \ No newline at end of file From f5a90153b644a907cc7891626ac9bba103e101ab Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:12:38 -0700 Subject: [PATCH 528/797] Equious updated courses/moccasin-101/8-mox-erc20/20-stateful-fuzz/+page.md. --- courses/moccasin-101/8-mox-erc20/20-stateful-fuzz/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/20-stateful-fuzz/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/20-stateful-fuzz/+page.md b/courses/moccasin-101/8-mox-erc20/20-stateful-fuzz/+page.md new file mode 100644 index 000000000..44c25f29a --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/20-stateful-fuzz/+page.md @@ -0,0 +1,3 @@ +--- + title: Stateful Fuzz + --- \ No newline at end of file From cdbf3a8f51f2e5b5ce29349641416bc5b8081736 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:13:53 -0700 Subject: [PATCH 529/797] Equious updated courses/moccasin-101/8-mox-erc20/21-workshop/+page.md. --- courses/moccasin-101/8-mox-erc20/21-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/21-workshop/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/21-workshop/+page.md b/courses/moccasin-101/8-mox-erc20/21-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/21-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From f05968c572a8577de48463adb3013540189535ba Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:14:06 -0700 Subject: [PATCH 530/797] Equious updated courses/moccasin-101/8-mox-erc20/22-rng/+page.md. --- courses/moccasin-101/8-mox-erc20/22-rng/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/22-rng/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/22-rng/+page.md b/courses/moccasin-101/8-mox-erc20/22-rng/+page.md new file mode 100644 index 000000000..353327f11 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/22-rng/+page.md @@ -0,0 +1,3 @@ +--- + title: Rng + --- \ No newline at end of file From 201e9adf4017eb064297212ca044ab737f47af10 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:14:20 -0700 Subject: [PATCH 531/797] Equious updated courses/moccasin-101/8-mox-erc20/23-cei/+page.md. --- courses/moccasin-101/8-mox-erc20/23-cei/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/23-cei/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/23-cei/+page.md b/courses/moccasin-101/8-mox-erc20/23-cei/+page.md new file mode 100644 index 000000000..fa728fee9 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/23-cei/+page.md @@ -0,0 +1,3 @@ +--- + title: Cei + --- \ No newline at end of file From 836ba643f62ffb756a6917bb5f5efd8b1eb139e8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:14:33 -0700 Subject: [PATCH 532/797] Equious updated courses/moccasin-101/8-mox-erc20/24-mox-console/+page.md. --- courses/moccasin-101/8-mox-erc20/24-mox-console/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/24-mox-console/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/24-mox-console/+page.md b/courses/moccasin-101/8-mox-erc20/24-mox-console/+page.md new file mode 100644 index 000000000..14036c356 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/24-mox-console/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Console + --- \ No newline at end of file From e23effa57336df5986b9d9d44eed89aacf574a3a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:16:00 -0700 Subject: [PATCH 533/797] Equious updated courses/moccasin-101/8-mox-erc20/25-recap/+page.md. --- courses/moccasin-101/8-mox-erc20/25-recap/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/25-recap/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/25-recap/+page.md b/courses/moccasin-101/8-mox-erc20/25-recap/+page.md new file mode 100644 index 000000000..385e6edfe --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/25-recap/+page.md @@ -0,0 +1,3 @@ +--- + title: Recap + --- \ No newline at end of file From 580aa34075256fbf88c7f9063733ceb61b1e432c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:17:16 -0700 Subject: [PATCH 534/797] Equious updated courses/moccasin-101/8-mox-erc20/3-custom-pyproject/+page.md. --- courses/moccasin-101/8-mox-erc20/3-custom-pyproject/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/3-custom-pyproject/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/3-custom-pyproject/+page.md b/courses/moccasin-101/8-mox-erc20/3-custom-pyproject/+page.md new file mode 100644 index 000000000..d9e46800a --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/3-custom-pyproject/+page.md @@ -0,0 +1,3 @@ +--- + title: Custom Pyproject + --- \ No newline at end of file From 61e8ff74b054906670723f68101930a5dc76fbbd Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:19:57 -0700 Subject: [PATCH 535/797] Equious updated courses/moccasin-101/8-mox-erc20/4-what-is-erc20/+page.md. --- courses/moccasin-101/8-mox-erc20/4-what-is-erc20/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/4-what-is-erc20/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/4-what-is-erc20/+page.md b/courses/moccasin-101/8-mox-erc20/4-what-is-erc20/+page.md new file mode 100644 index 000000000..b099a949d --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/4-what-is-erc20/+page.md @@ -0,0 +1,3 @@ +--- + title: What Is Erc20 + --- \ No newline at end of file From d34a36b81389a2517def2c3abd6c79b86a353483 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:20:52 -0700 Subject: [PATCH 536/797] Equious updated courses/moccasin-101/8-mox-erc20/5-build-it/+page.md. --- courses/moccasin-101/8-mox-erc20/5-build-it/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/5-build-it/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/5-build-it/+page.md b/courses/moccasin-101/8-mox-erc20/5-build-it/+page.md new file mode 100644 index 000000000..dcfcc37bb --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/5-build-it/+page.md @@ -0,0 +1,3 @@ +--- + title: Build It + --- \ No newline at end of file From 19c82052010e9d89ec3710008810ccffafedbc63 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:24:07 -0700 Subject: [PATCH 537/797] Equious updated courses/moccasin-101/8-mox-erc20/6-mox-libs-git/+page.md. --- courses/moccasin-101/8-mox-erc20/6-mox-libs-git/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/6-mox-libs-git/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/6-mox-libs-git/+page.md b/courses/moccasin-101/8-mox-erc20/6-mox-libs-git/+page.md new file mode 100644 index 000000000..98e5b17b8 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/6-mox-libs-git/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Libs Git + --- \ No newline at end of file From b421b8fd27a7c2bcbbd287dbb1f0b9e06a788f9e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:24:34 -0700 Subject: [PATCH 538/797] Equious updated courses/moccasin-101/8-mox-erc20/7-mox-libs-pypi/+page.md. --- courses/moccasin-101/8-mox-erc20/7-mox-libs-pypi/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/7-mox-libs-pypi/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/7-mox-libs-pypi/+page.md b/courses/moccasin-101/8-mox-erc20/7-mox-libs-pypi/+page.md new file mode 100644 index 000000000..ce3cbc423 --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/7-mox-libs-pypi/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Libs Pypi + --- \ No newline at end of file From f2c507c0b20751b5753c0fe59d7c6a7e24e63fcf Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:25:01 -0700 Subject: [PATCH 539/797] Equious updated courses/moccasin-101/8-mox-erc20/8-mox-idk/+page.md. --- courses/moccasin-101/8-mox-erc20/8-mox-idk/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/8-mox-idk/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/8-mox-idk/+page.md b/courses/moccasin-101/8-mox-erc20/8-mox-idk/+page.md new file mode 100644 index 000000000..9ee318b3d --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/8-mox-idk/+page.md @@ -0,0 +1,3 @@ +--- + title: Mox Idk + --- \ No newline at end of file From ef8833cd707e388493daa423afced3844d5089cd Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:25:15 -0700 Subject: [PATCH 540/797] Equious updated courses/moccasin-101/8-mox-erc20/9-init-supply/+page.md. --- courses/moccasin-101/8-mox-erc20/9-init-supply/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/8-mox-erc20/9-init-supply/+page.md diff --git a/courses/moccasin-101/8-mox-erc20/9-init-supply/+page.md b/courses/moccasin-101/8-mox-erc20/9-init-supply/+page.md new file mode 100644 index 000000000..9121611ae --- /dev/null +++ b/courses/moccasin-101/8-mox-erc20/9-init-supply/+page.md @@ -0,0 +1,3 @@ +--- + title: Init Supply + --- \ No newline at end of file From 3e6e84024bda36af3d260a01c2c855cd99df4d0b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:30:00 -0700 Subject: [PATCH 541/797] Equious updated courses/moccasin-101/9-how-to-get-hired/1-intro/+page.md. --- courses/moccasin-101/9-how-to-get-hired/1-intro/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/9-how-to-get-hired/1-intro/+page.md diff --git a/courses/moccasin-101/9-how-to-get-hired/1-intro/+page.md b/courses/moccasin-101/9-how-to-get-hired/1-intro/+page.md new file mode 100644 index 000000000..b7e64e913 --- /dev/null +++ b/courses/moccasin-101/9-how-to-get-hired/1-intro/+page.md @@ -0,0 +1,3 @@ +--- + title: Intro + --- \ No newline at end of file From d39fe57e93b2e04175815f0dd54f7949ae4dda3c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 03:35:17 -0700 Subject: [PATCH 542/797] Equious updated courses/moccasin-101/9-how-to-get-hired/2-workshop/+page.md. --- courses/moccasin-101/9-how-to-get-hired/2-workshop/+page.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 courses/moccasin-101/9-how-to-get-hired/2-workshop/+page.md diff --git a/courses/moccasin-101/9-how-to-get-hired/2-workshop/+page.md b/courses/moccasin-101/9-how-to-get-hired/2-workshop/+page.md new file mode 100644 index 000000000..789149836 --- /dev/null +++ b/courses/moccasin-101/9-how-to-get-hired/2-workshop/+page.md @@ -0,0 +1,3 @@ +--- + title: Workshop + --- \ No newline at end of file From 4f34db58913c8433ae803533a610ef64fe8822ab Mon Sep 17 00:00:00 2001 From: hunter <104146303+solhosty@users.noreply.github.com> Date: Fri, 22 Nov 2024 07:02:57 -0500 Subject: [PATCH 543/797] changes to folder --- .../1-favorites/{31-workshop => 31-workshop-pt-2}/+page.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename courses/vyper-101/1-favorites/{31-workshop => 31-workshop-pt-2}/+page.md (100%) diff --git a/courses/vyper-101/1-favorites/31-workshop/+page.md b/courses/vyper-101/1-favorites/31-workshop-pt-2/+page.md similarity index 100% rename from courses/vyper-101/1-favorites/31-workshop/+page.md rename to courses/vyper-101/1-favorites/31-workshop-pt-2/+page.md From 895c758b274321d90e717e305dea24437254a56b Mon Sep 17 00:00:00 2001 From: hunter <104146303+solhosty@users.noreply.github.com> Date: Fri, 22 Nov 2024 14:42:28 -0500 Subject: [PATCH 544/797] rename 32 --- .../vyper-101/1-favorites/{32-recap => 32-recap-pt-2}/+page.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename courses/vyper-101/1-favorites/{32-recap => 32-recap-pt-2}/+page.md (100%) diff --git a/courses/vyper-101/1-favorites/32-recap/+page.md b/courses/vyper-101/1-favorites/32-recap-pt-2/+page.md similarity index 100% rename from courses/vyper-101/1-favorites/32-recap/+page.md rename to courses/vyper-101/1-favorites/32-recap-pt-2/+page.md From 34e21a315951c348d7ebf23bef67b25b713334a3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:44:50 -0700 Subject: [PATCH 545/797] Equious updated courses/vyper-101/1-favorites/1-welcome/+page.md. --- .../vyper-101/1-favorites/1-welcome/+page.md | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/1-welcome/+page.md b/courses/vyper-101/1-favorites/1-welcome/+page.md index cc19b2514..6960b3f5a 100644 --- a/courses/vyper-101/1-favorites/1-welcome/+page.md +++ b/courses/vyper-101/1-favorites/1-welcome/+page.md @@ -1,3 +1,27 @@ ---- - title: Welcome - --- \ No newline at end of file +## Welcome to Vyper Fundamentals + +This course is especially exciting to us because this is the Python and Vyper edition. Something we haven't done before in the past. In the past 5 years that we've been doing this, we've done Python, but never Vyper. Now Python is positioning itself to be one of the most important languages to learn in the coming years. In the age of AI. + +When it comes to financial technology companies like hedge funds or asset managers, all the portfolio managers or traders, they're using Python. Why? Because Python is very easy to read, easy to script, and it's a production language to build very powerful applications with. And additionally, looking at the AI landscape, Python is dominant there as well with tools like PyTorch and TensorFlow, and all these libraries and packages built specifically around the AI landscape. + +We're also looking forward to advancements in languages like Mojo, which are going to be languages literally built to run in the AI environment. + +So, you, who is watching this video right now, you are setting yourself up to have an edge over all these waves of people coming in, because you are learning this technology of the future with Python, and specifically with Vyper. + +Now we'll learn more about Vyper in the coming videos, but basically, Vyper is a smart contract development language. So, we're actually going to learn Vyper, and learning Vyper, you will learn Python along the way, which is very nice. + +So, if you have zero Python experience, us teaching you Vyper here will also teach you some Python. Now there are some differences between the languages, between Vyper and Python. However, a lot of the syntax is going to be very similar. So, whether you're brand new to Python, whether you're brand new to Vyper, this is the course for you. Now, it would be beneficial if you had a little bit of Python experience before jumping into this. That's going to make your life a lot easier, you're going to move a lot quicker. There are plenty of courses on Free Code Camp that will teach you these things along the way. + +However, we're going to assume that you know nothing about Python. We're going to assume that you're a beginner Python developer. That way, you can follow along, and you can learn production professional Python code as well in this curriculum, too. Now, that being said, if you do already know Python, which that's great as well, you can skip over some of the sections where we teach you Python, and at the beginning of those videos I will label them, saying hey, we're going to teach some Python skills in this lesson, feel free to skip. + +Now a question that you're probably asking is, "Why Vyper? Why would I learn Vyper over Solidity?" + +Looking at this chart here as of recording, Vyper has around 3% of the total TVL of smart contracts. Basically, what this means is not a whole lot of money is in Vyper smart contracts. However, the reason you would want to do this is, because there are a couple applications that have a ton of money in Vyper smart contracts. Curve, one of the largest DEXs out there is built exclusively on Vyper. Lido, one of the largest staking platforms, is built with a lot of Vyper. Yearn Finance as well has a lot of Vyper. Vyper, by its nature, is meant to be easy to learn, easy to read, easy to write, and very easy for AIs to understand. And importantly, very easy for security researchers to understand, so that your smart contracts have fewer bugs in them. Which, in the smart contracts space, is incredibly important, because a single bug can mean you lose millions of dollars. + +And additionally, because Vyper is in this Python tooling world, you are going to step into the AI, to the finance, to the fintech world, and have all these powerful Pythonic tools and libraries at your disposal already. + +So, jumping into the Python and Vyper landscape, will set you up for this future of AI and finance. So I am incredibly excited for you to be on this journey with us here, learning Vyper, learning smart contract development because we've got a lot in store for you. + +At the end of Vyper Fundamentals, you will understand the basics of Vyper, you'll even learn a little bit of Python without even knowing it. You'll learn some tools and techniques for interacting with AI to help you write your smart contracts, help you write your code. You will have deployed your first three smart contracts yourself, and you'll be ready to move into a more professional environment, and just by you being here, just by you writing your first line of code, you are a smart contract developer and welcome to Web3. + +And if you missed this section during Blockchain Basics, let's go ahead and get started with some best practices so that we can set you up for success for learning here. From 5ce51d6eb9b29e876bfe9c419decf7bdd3b89d07 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:49:36 -0700 Subject: [PATCH 546/797] Equious updated courses/vyper-101/1-favorites/10-contract-design/+page.md. --- .../1-favorites/10-contract-design/+page.md | 99 ++++++++++++++++++- 1 file changed, 96 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/10-contract-design/+page.md b/courses/vyper-101/1-favorites/10-contract-design/+page.md index 6ce60ddce..ae4696ec7 100644 --- a/courses/vyper-101/1-favorites/10-contract-design/+page.md +++ b/courses/vyper-101/1-favorites/10-contract-design/+page.md @@ -1,3 +1,96 @@ ---- - title: Contract Design - --- \ No newline at end of file +We're going to make a very minimal favorite things list. We want to store favorite numbers and favorite people with their favorite numbers. + +Here is some basic code to get started: + +```python +# favorite things list: +# favorite numbers +# favorite people with their favorite number +``` + +To store these items, we're going to use mappings. A mapping is like a dictionary or hashmap. We'll use the key to be the person and the value to be their favorite number. + +```python +# favorite things list: +# favorite numbers +# favorite people with their favorite number + +favorite_numbers: dict[uint256, uint256] +favorite_people: dict[address, uint256] +``` + +Mappings have a default value. If we don't assign a value, the default value is 0. + +```python +# favorite things list: +# favorite numbers +# favorite people with their favorite number + +favorite_numbers: dict[uint256, uint256] +favorite_people: dict[address, uint256] + +def set_favorite_number(number: uint256): + favorite_numbers[number] = number +``` + +Now we have a function to set a favorite number. This is a pretty simple and straightforward function. We take a number and set it to the same number, but we could change this later. + +```python +# favorite things list: +# favorite numbers +# favorite people with their favorite number + +favorite_numbers: dict[uint256, uint256] +favorite_people: dict[address, uint256] + +def set_favorite_number(number: uint256): + favorite_numbers[number] = number + +def set_favorite_person(person: address, number: uint256): + favorite_people[person] = number +``` + +We have another function to set the favorite person. It takes a person, their address, and their favorite number. We set it to the dictionary where we store the favorite person. + +```python +# favorite things list: +# favorite numbers +# favorite people with their favorite number + +favorite_numbers: dict[uint256, uint256] +favorite_people: dict[address, uint256] + +def set_favorite_number(number: uint256): + favorite_numbers[number] = number + +def set_favorite_person(person: address, number: uint256): + favorite_people[person] = number + +def get_favorite_number(number: uint256) -> uint256: + return favorite_numbers[number] +``` + +Lastly, we have a function to get the favorite number. It takes a number and then it returns the favorite number. It simply returns the value of the number from the dictionary. + +```python +# favorite things list: +# favorite numbers +# favorite people with their favorite number + +favorite_numbers: dict[uint256, uint256] +favorite_people: dict[address, uint256] + +def set_favorite_number(number: uint256): + favorite_numbers[number] = number + +def set_favorite_person(person: address, number: uint256): + favorite_people[person] = number + +def get_favorite_number(number: uint256) -> uint256: + return favorite_numbers[number] + +def get_favorite_person(person: address) -> uint256: + return favorite_people[person] +``` + +We now have a function to get the favorite person, which takes a person's address and returns their favorite number. From 9552eb36423ccb20a1cae8ba99eeddba5f673d36 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:50:01 -0700 Subject: [PATCH 547/797] Equious updated courses/vyper-101/1-favorites/11-vyper-types/+page.md. --- .../1-favorites/11-vyper-types/+page.md | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/11-vyper-types/+page.md b/courses/vyper-101/1-favorites/11-vyper-types/+page.md index 59975b7b9..40c991ed6 100644 --- a/courses/vyper-101/1-favorites/11-vyper-types/+page.md +++ b/courses/vyper-101/1-favorites/11-vyper-types/+page.md @@ -1,3 +1,39 @@ ---- - title: Vyper Types - --- \ No newline at end of file +## Vyper Types + +We're going to learn about types in Vyper, and to get started we're going to need to know how to store different things in our smart contract. We're going to go to the Vyper documentation, which we can find at docs.vyperlang.org. + +If we scroll down the left side here, we can see all the different types that we can create in a smart contract. And to store different values like our favorite number or different people, we'll have to assign each value to a type and then assign it to a variable. + +So, we have a lot of different types in Vyper, and some of the main ones are Booleans, signed integers, unsigned integers, decimals, addresses, byte arrays and then a number of other ones as well. + +For example, if we were to type in here: + +```python +has_favorite_number: bool +``` + +This would mean this `has_favorite_number` could either be `True` or `False` since it's a Boolean. + +Now, if you were to try to compile this right now, by hitting command S, you'd get a little error saying "storage variables cannot have an initial value". So for now, we can't actually give it a value here, but this line would say that `has_favorite_number` is going to be of type Boolean, which means it'll either be `True` or `False`. + +We could also say: + +```python +my_favorite_number: uint256 +``` + +This `uint256` is saying that `my_favorite_number` is an unsigned integer. This means `my_favorite_number` is going to be an unsigned integer of 256 bits. Don't worry too much about the bits part for now, but unsigned just means that this can only be a positive number. + +We can also have an address: + +```python +my_address: address +``` + +An address is going to be an address in the blockchain space. For example, in our Metamask, we can click this little copy button, go back to Remix, and type `my_address: address` and then set it equal to the value that we copied. + +So we have Booleans, signed integers, unsigned integers and we can also do decimals. Which decimals are a more advanced value that we won't be using for quite some time, but you could say `my_decimal: decimal` and you also have to add `enable decimals` to the compiler. + +You can also have an M byte wide fixed size byte array, which we can do something like `my_bytes: byte32` . + +And there are several other more advanced types that we can use to store different things in our smart contract, but those are some of the basics. From 12860f3635da63b7c808f5fc82f6cb7ca56c4422 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:50:38 -0700 Subject: [PATCH 548/797] Equious updated courses/vyper-101/1-favorites/12-visibilitiy/+page.md. --- .../1-favorites/12-visibilitiy/+page.md | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/12-visibilitiy/+page.md b/courses/vyper-101/1-favorites/12-visibilitiy/+page.md index ff9091e2d..60193962a 100644 --- a/courses/vyper-101/1-favorites/12-visibilitiy/+page.md +++ b/courses/vyper-101/1-favorites/12-visibilitiy/+page.md @@ -1,3 +1,43 @@ ---- - title: Visibilitiy - --- \ No newline at end of file +## Variable Visibility & Deploying to the Remix VM + +We've learned about the different types of values that Vyper variables can hold. Now, we'll see how to use these variables in practice by deploying a smart contract. + +We'll start with a simple smart contract that has a single state variable called `my_favorite_number`. This variable will be a `uint256`, which is an unsigned integer. We'll initialize it to 0. + +```python +#pragma version 0.4.0 +@license MIT +my_favorite_number: uint256 = 0 +``` + +The syntax for declaring variables in Vyper is similar to Python. We use a colon to separate the variable name from its type. + +In Vyper, variables declared at the top level of a contract are called _state variables_ or _storage variables_. These variables are stored on the blockchain and can be accessed by anyone. + +To test our smart contract, we'll deploy it to the Remix VM. The Remix VM is a local blockchain simulator that lets us run and test our contracts without deploying them to a real blockchain. + +We'll start by compiling our contract. + +```bash +# In Remix, go to the "Compiler" tab and compile your contract. +``` + +Once the contract is compiled, we can deploy it by going to the "Deploy & Run Transactions" tab. The Remix VM will provide us with a dummy account and gas limit that we can use to deploy the contract. + +We can also delete a deployed contract by clicking the "X" button next to the contract address. + +Since we haven't added any functionality to our contract yet, we only have low-level interactions available. This means we can't see the value of our `my_favorite_number` variable yet. To make it visible, we need to change its _visibility_. + +We can make a variable visible to everyone by adding the keyword `public` before its type. + +```python +#pragma version 0.4.0 +@license MIT +my_favorite_number: public(uint256) = 0 +``` + +By default, variables in Vyper are _internal_, which means they can only be accessed from within the contract. By making our variable public, we allow anyone to access its value. + +Now, if we deploy our contract again and click on the "my_favorite_number" button, we'll be able to see its value. This will confirm that it was initialized to 0. + +The `public` keyword is important for making data on the blockchain accessible to everyone. It's a key part of building decentralized applications, as it allows users to interact with your contract in a secure and transparent way. From 57e7814353b1572ff106cb8d62147dea814f7482 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:51:14 -0700 Subject: [PATCH 549/797] Equious updated courses/vyper-101/1-favorites/13-functions/+page.md. --- .../1-favorites/13-functions/+page.md | 87 ++++++++++++++++++- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/13-functions/+page.md b/courses/vyper-101/1-favorites/13-functions/+page.md index acfd89f66..75a681a1b 100644 --- a/courses/vyper-101/1-favorites/13-functions/+page.md +++ b/courses/vyper-101/1-favorites/13-functions/+page.md @@ -1,3 +1,84 @@ ---- - title: Functions - --- \ No newline at end of file +## Functions: The `def` Keyword + +We can create a function so we can actually save a value to our `my_favorite_number`. The way we declare a function is to use the `def` keyword. + +The `def` keyword can be thought of as standing for definition. + +```python +def store +``` + +We will create a function called `store`. + +```python +def store() +``` + +Next we need to add the parentheses. We put whatever parameters this `store` function is going to take inside the parentheses. For example, we need to tell our `store` function what number we want to update `my_favorite_number` with. + +```python +def store(new_number) +``` + +We will tell our function to update `my_favorite_number` with `new_number`, which will be of type `uint256` as well. + +```python +def store(new_number: uint256) +``` + +Next, we need to add a colon to indicate that the next lines will be the subset of code for our function. + +```python +def store(new_number: uint256): +``` + +We will hit enter and you will notice that we immediately get a tab. Vyper and Python are tab-based languages, and the tab tells our compiler that this line of code is associated with our function. If we were to type over here, the compiler would have a hard time knowing that this code is part of our function. + +```python +def store(new_number: uint256): + adsasdf +``` + +We need to add this tab which tells our compiler that this line of code is part of the function. + +```python +def store(new_number: uint256): + self.my_favorite_number +``` + +We will say: "Okay, self dot my favorite number equals or is set to new number". + +```python +def store(new_number: uint256): + self.my_favorite_number = new_number +``` + +Now, `self` is a very specific keyword in Vyper. It refers to the contract that we are writing. So, when we say `self.my_favorite_number`, we are saying "point to the storage variable or the state variable `my_favorite_number`." + +If we didn't have `self` the compiler would get a little confused. It would say, "Okay, well what are you referring to? Is it my favorite number a new variable, or is it a state variable?" We put `self` in here, and the compiler says, "Ah, that's a state variable you're dealing with, got it. Makes sense." + +So, what this function is going to do is: we are going to pass in a number, like seven, and we're going to save it to `my_favorite_number`. + +```python +@external +def store(new_number: uint256): + self.my_favorite_number = new_number +``` + +Now, similar to how we need the `public` keyword up here so we can actually get that blue button to read `my_favorite_number`, functions have the same concept. If we don't give them some type of visibility, it will automatically be considered internal. + +We need to add `@external` right above our function definition. This is known as a decorator. Once again, these exist in Python as well. The `external` keyword means that this function can be called by us, by people outside of this smart contract. This doesn't quite make sense yet, but just ignore it for now. We will explain it deeper as we go on. + +But, now that we have this kind of boilerplate code, we can make sure to compile this. And we can deploy this. Let's go ahead and remove that other contract and re-hit deploy. Then let's hit the little drop down here. Now, you'll see we have two buttons: we have `my_favorite_number` and we have `store`. + +The reason `store` is greyed out is because we need to give it an input. If we hit `my_favorite_number`, remember this is a `public` variable, so we get this blue button. We add the number `7` in here, and then I hit `store`. + +It will actually send a transaction to store the number seven at `my_favorite_number`. If we look in our little terminal section here, we can actually see that when I click this store button, these little statements show up. These are transactions. + +So, storing seven or their simulated transactions on this little fake Remix environment. So storing the number seven actually is updating the state of this smart contract. And to update state, you actually have to send a transaction. So `my_favorite_number` is being populated with, well, if it's getting started as zero, but then it's getting set to seven. And when we call `my_favorite_number` now, we now get the number seven here. It's really really tiny, but we get a seven back. If I were to add some crazy number, like this, hit the `store` button and then hit `my_favorite_number`, we see it's been updated here. + +```bash +store(1235) +``` + +We see it's been updated here. From 0eb8a249148de320c6fdc5b76fb2f5394734c431 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:51:41 -0700 Subject: [PATCH 550/797] Equious updated courses/vyper-101/1-favorites/14-func-visibility/+page.md. --- .../1-favorites/14-func-visibility/+page.md | 70 ++++++++++++++++++- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/14-func-visibility/+page.md b/courses/vyper-101/1-favorites/14-func-visibility/+page.md index 72f026d4e..0a24251a8 100644 --- a/courses/vyper-101/1-favorites/14-func-visibility/+page.md +++ b/courses/vyper-101/1-favorites/14-func-visibility/+page.md @@ -1,3 +1,67 @@ ---- - title: Func Visibility - --- \ No newline at end of file +## Visibility in Solidity + +In this lesson, we will explore the concept of visibility within Solidity contracts. Visibility is a fundamental aspect of how we control access to different components within a contract. We will focus on the keywords `public` and `internal`. + +The concept of visibility allows us to define the scope of accessibility to different elements in our smart contracts. Let's dive in by examining the code for our `favorites.vy` contract: + +```python +#pragma version 0.4.0 +@license MIT +my_favorite_number: public(uint256) = 0 +@external +def store(new_number: uint256): + self.my_favorite_number = new_number +``` + +We have a state variable `my_favorite_number` that is declared as `public`. This means it is visible and accessible from anywhere. For example, an external user could interact with the `my_favorite_number` variable directly, without having to use any functions. + +We also have a function `store` that is declared as `@external`. This means that this function can only be accessed from outside the contract, via a transaction. No other functions within the contract can call `store` directly. + +Now let's look at how `internal` visibility functions work. We can remove the `public` keyword from our `my_favorite_number` state variable. We can then change the `@external` decorator to `@internal`: + +```python +#pragma version 0.4.0 +@license MIT +my_favorite_number: uint256 = 0 +@internal +def store(new_number: uint256): + self.my_favorite_number = new_number +``` + +We can then compile the code: + +```bash +Compile favorites.vy +``` + +The `internal` keyword means that the function `store` can only be called by other functions within the same contract. Let's add an example: + +```python +#pragma version 0.4.0 +@license MIT +my_favorite_number: uint256 = 0 +@internal +def store(new_number: uint256): + self.my_favorite_number = new_number +def store_other(): + self.store(7) +``` + +When we try to compile this code, we get an error because the `store_other` function is trying to call the `store` function, which is declared as `internal`. + +We can fix this by making the `store` function `external`, which allows it to be called from outside the contract. We can also make `my_favorite_number` `public` again so that it's visible from the outside. + +```python +#pragma version 0.4.0 +@license MIT +my_favorite_number: public(uint256) = 0 +@external +def store(new_number: uint256): + self.my_favorite_number = new_number +def store_other(): + self.store(7) +``` + +We can compile this code and we will see it functions as expected. + +This is a basic introduction to the concept of visibility in Solidity contracts. By mastering the use of keywords like `public` and `internal`, we can create more secure and modular smart contracts. From bf1a0070637c1828189425d32a3843775da75662 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:52:09 -0700 Subject: [PATCH 551/797] Equious updated courses/vyper-101/1-favorites/15-view-and-pure/+page.md. --- .../1-favorites/15-view-and-pure/+page.md | 117 +++++++++++++++++- 1 file changed, 114 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/15-view-and-pure/+page.md b/courses/vyper-101/1-favorites/15-view-and-pure/+page.md index 8fa895385..7c89c6f9f 100644 --- a/courses/vyper-101/1-favorites/15-view-and-pure/+page.md +++ b/courses/vyper-101/1-favorites/15-view-and-pure/+page.md @@ -1,3 +1,114 @@ ---- - title: View And Pure - --- \ No newline at end of file +In this lesson we will learn how to build a view function. + +Firstly, let's go ahead and make a function that returns a value. + +```python +@external +def retrieve() -> uint256: + return self.my_favorite_number +``` + +Then we save and redeploy this: + +```bash +favorites --favorites.vy +``` + +Now we will comment out the store function for now. + +```python +# @external +# def store(new_number: uint256): +# self.my_favorite_number = new_number +``` + +We can now see the value returned in the UI: + +```bash +my_favorite_number --call +``` + +We will now change the retrieve function to return a value: + +```python +@external +def retrieve() -> uint256: + return self.my_favorite_number +``` + +This time we will redeploy and check the UI: + +```bash +favorites --favorites.vy +``` + +Now, if we want to explicitly tell the compiler that this is not a transaction we can simply add the @view decorator to the function: + +```python +@external +@view +def retrieve() -> uint256: + return self.my_favorite_number +``` + +Let's redeploy and see what happens in the UI. + +```bash +favorites --favorites.vy +``` + +The UI will now display a blue button, indicating that the function is a view function. We will now create a second view function which we will call 'retrieve', and we will also include a note within our code explaining how view functions work. + +```python +@external +def store(new_number: uint256): + self.my_favorite_number = new_number + +@external +@view +def retrieve() -> uint256: + return self.my_favorite_number + +# a view function can be called +# by a human for free -- no gas + +# but when a transaction calls +# a view function, it costs gas + +@external +def store(new_number: uint256): + self.my_favorite_number = new_number + +@internal +@view +def retrieve() -> uint256: + return self.my_favorite_number +``` + +Next, we will make the retrieve function an external function, so that we can call it. We will also add a few extra retrieve functions, just to highlight the gas cost differences. + +```python +@external +def store(new_number: uint256): + self.my_favorite_number = new_number + +self.retrieve() +self.retrieve() +self.retrieve() +self.retrieve() + +@internal +@view +def retrieve() -> uint256: + return self.my_favorite_number +``` + +Let's redeploy and see the difference in gas cost between the view function and external retrieve function. + +```bash +favorites --favorites.vy +``` + +If you recall, calling a view function from the UI requires no gas. However, if another transaction calls a view function, then it will incur a gas cost. + +Calling a view function from the UI is essentially the same as calling the 'public' function. From 74a0aebe04a4968b5dd5a28a6bd776cd82209905 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:52:48 -0700 Subject: [PATCH 552/797] Equious updated courses/vyper-101/1-favorites/16-constructor/+page.md. --- .../1-favorites/16-constructor/+page.md | 118 +++++++++++++++++- 1 file changed, 115 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/16-constructor/+page.md b/courses/vyper-101/1-favorites/16-constructor/+page.md index 60d42e12a..676f775d4 100644 --- a/courses/vyper-101/1-favorites/16-constructor/+page.md +++ b/courses/vyper-101/1-favorites/16-constructor/+page.md @@ -1,3 +1,115 @@ ---- - title: Constructor - --- \ No newline at end of file +## Constructors in Vyper + +In this lesson, we'll discuss what a constructor is in Vyper. We'll focus on the mechanics of how the constructor function works and create a constructor to initialize our `favorites` smart contract. + +### Constructors Explained + +A constructor is a special function that's called only once when a smart contract is deployed. The most common use for a constructor is to initialize state variables or to call other functions needed to set up the contract. + +### Defining Constructors + +Let's set up a constructor in a Vyper contract. First, we'll create a state variable named `owner` which will be a public address: + +```python +owner: public(address) +``` + +To define a constructor, we start with the `@deploy` decorator, followed by the definition of a function named `__init__`. Inside the parentheses, we can add any arguments we want to pass to the constructor. For now, we'll leave it empty: + +```python +@deploy +def __init__(): + pass +``` + +### Setting State Variables in Constructors + +One of the most common things we do inside a constructor is to set the `owner` of the contract. We can do this by setting the `owner` state variable to `msg.sender`. The `msg.sender` variable refers to the account that deployed the contract. + +```python +@deploy +def __init__(): + self.owner = msg.sender +``` + +### Passing Parameters to Constructors + +Let's look at some examples of passing parameters to a constructor. + +First, we'll add a state variable named `name` that is a public string with a maximum length of 100 characters: + +```python +name: public(string[100]) +``` + +Now we will pass the parameter `name` to our constructor function: + +```python +@deploy +def __init__(name: string[100]): + self.owner = msg.sender +``` + +We will then use the `name` parameter to set the `name` state variable: + +```python +@deploy +def __init__(name: string[100]): + self.owner = msg.sender + self.name = name +``` + +Now, let's create another state variable named `expiresAt` that will be a public `uint256`: + +```python +expiresAt: public(uint256) +``` + +We will now add a second parameter, `duration`, to our constructor function: + +```python +@deploy +def __init__(name: string[100], duration: uint256): + self.owner = msg.sender + self.name = name +``` + +Finally, we will set the `expiresAt` variable equal to the current block timestamp plus the `duration`: + +```python +@deploy +def __init__(name: string[100], duration: uint256): + self.owner = msg.sender + self.name = name + self.expiresAt = block.timestamp + duration +``` + +Now, let's compile and deploy our contract. We'll go to the `Compile` tab. +We will click the `Compile` button. +We will go to the `Deploy & Run Transactions` tab. +We will click on the `Deploy` button. We will then enter the `name`, which is `Vyper`, and the `duration`, which will be `10`. We'll click the `Transact` button. +We can then check the state variables. +Our `owner` address will be set to the current account. +Our `name` will be set to `Vyper`. +Our `expiresAt` will be set to the current block timestamp plus 10. + +### Another Example + +Let's create a constructor for our `favorites` smart contract to initialize a `my_favorite_number` state variable. Our state variable `my_favorite_number` will be a public `uint256`. + +```python +my_favorite_number: public(uint256) +``` + +Now let's create a constructor: + +```python +@deploy +def __init__(): + self.my_favorite_number = 7 +``` + +To compile and deploy this contract, we will click the `Compile` button. We will then go to the `Deploy & Run Transactions` tab. We will click the `Deploy` button. +We can then interact with our contract by clicking on the `my_favorite_number - call` button, which will return the value 7. + +Great work! From 483c646613e628614aefe17abc8e2e5d9819f362 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:53:17 -0700 Subject: [PATCH 553/797] Equious updated courses/vyper-101/1-favorites/17-advanced-funcs/+page.md. --- .../1-favorites/17-advanced-funcs/+page.md | 133 +++++++++++++++++- 1 file changed, 130 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/17-advanced-funcs/+page.md b/courses/vyper-101/1-favorites/17-advanced-funcs/+page.md index 410ca3f45..2f57587ee 100644 --- a/courses/vyper-101/1-favorites/17-advanced-funcs/+page.md +++ b/courses/vyper-101/1-favorites/17-advanced-funcs/+page.md @@ -1,3 +1,130 @@ ---- - title: Advanced Funcs - --- \ No newline at end of file +## Advanced Vyper Functions + +We will show you some examples of functions in Vyper. All of the examples that I will show you here are called external functions. This means that after we deploy the contract, we will be able to call these functions. + +So, we'll declare as external: + +```python +@external +``` + +Now, there's another keyword called internal, which I will explain in another video, and then I'll put another keyword called pure: + +```python +@pure +``` + +Also, explain this in another video. Here, I just want to show you some syntax for how to write functions in Vyper: + +```python +def; +``` + +Let's call this function multiply: + +```python +def multiply +``` + +And as the name implies it will multiply two uint256, X uint256 and Y uint256. + +```python +def multiply(x: uint256, y: uint256) +``` + +And we want to return the product of X and Y. + +```python +def multiply(x: uint256, y: uint256) -> uint256: +``` + +To do this, we'll say put an arrow, then say we're going to return uint256 uint256. + +```python +def multiply(x: uint256, y: uint256) -> uint256: +return +``` + +And then, call it. Okay, and to multiply two numbers, we will say return. + +```python +def multiply(x: uint256, y: uint256) -> uint256: +return x * y +``` + +So, that's an example of a simple function that takes in two inputs, and then returns the product of the two numbers. + +Let me show you another example. I'm going to copy this. Again, we'll start with external, pure: + +```python +@external +@pure +``` + +Then I'll call this function divide: + +```python +def divide(x: uint256, y: uint256) -> uint256: +``` + +We're going to divide X by Y and it's going to return uint256. + +```python +def divide(x: uint256, y: uint256) -> uint256: +return +``` + +Now, you would think that to divide two numbers, you just have to put a slash. However, in Vyper when you're dividing two integers, then you need to do double slash. + +```python +def divide(x: uint256, y: uint256) -> uint256: +return x // y +``` + +For the next example, sometimes you want to declare a function, but don't want to implement the code yet, you just want to make sure that the contract compiles. In this case, you can use the keyword pass. So, for example, let's say that we have a function external: + +```python +@external +def todo(): +``` + +def, and I'll call this, let's say, todo. And we're not going to return any outputs. It's also not going to take any inputs. What we want to say is we're going to implement the code inside here later. What you can do is type pass: + +```python +@external +def todo(): +pass +``` + +Basically, this function will do nothing. + +Okay, and the last example I'll show you is how do you return multiple outputs? So, let's say external again, and I'll use pure again for this example, and say def return many. + +```python +@external +@pure +def return_many() +``` + +For the input, we'll keep it simple, it's not going to take any inputs. And for the output, how would we return multiple outputs? To do this, you'll need to put the type of the output inside the parentheses. For example, let's say we wanted to return uint256 and some boolean: + +```python +@external +@pure +def return_many() -> (uint256, bool): +``` + +Bool, we'll say return. For the first output, we need to return a uint256. So, let's return 123. And for the second output, we'll need to return a boolean, that's say true. + +```python +@external +@pure +def return_many() -> (uint256, bool): +return (123, True) +``` + +Okay, so those are some examples of how to write functions in Vyper. Let's try compiling and deploying the contract. + +```bash +vyper compile advanced_functions.vy +``` From 375b85f177dc10144c33b1434cb0dbd5d557f44c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:53:48 -0700 Subject: [PATCH 554/797] Equious updated courses/vyper-101/1-favorites/18-ref-types/+page.md. --- .../1-favorites/18-ref-types/+page.md | 130 +++++++++++++++++- 1 file changed, 127 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/18-ref-types/+page.md b/courses/vyper-101/1-favorites/18-ref-types/+page.md index 8483d0bb6..6c7c7fa1d 100644 --- a/courses/vyper-101/1-favorites/18-ref-types/+page.md +++ b/courses/vyper-101/1-favorites/18-ref-types/+page.md @@ -1,3 +1,127 @@ ---- - title: Ref Types - --- \ No newline at end of file +We will be going over reference types in Vyper. These are used to store data, but are not copied when assigned as a value. + +## Reference Data Types + +We will be looking at several reference types in Vyper: fixed-sized list, mappings, and structs. + +### Fixed-Sized List + +We can use a fixed-sized list to store data of a given type. We first declare the type, then put the fixed size in brackets, as follows: + +```vyper +nums: public(uint256[10]) +``` + +We can read and write to this list. To get the value in index 0, we use: + +```vyper +self.nums[0] +``` + +And to set the value in index 0 to 123: + +```vyper +self.nums[0] = 123 +``` + +We can also set another value in index 1 to 456: + +```vyper +self.nums[1] = 456 +``` + +### Mappings + +Mappings store data based on a key value. The first value type will be the key, and the second value type will be the data stored. Let's create a mapping called "myMap": + +```vyper +myMap: public(HashMap[address, uint256]) +``` + +We can access and store data in a mapping. To get the value stored at the address of "msg.sender": + +```vyper +self.myMap[msg.sender] +``` + +Let's store the value 1 in this mapping: + +```vyper +self.myMap[msg.sender] = 1 +``` + +We can also change the value stored at "msg.sender" to 11: + +```vyper +self.myMap[msg.sender] = 11 +``` + +### Structs + +Structs are custom data types. Let's declare a struct called "Person". This struct has a name and an age: + +```vyper +struct Person: + name: String[10] + age: uint256 +``` + +We can declare a state variable of type struct: + +```vyper +person: public(Person) +``` + +Let's store data in this state variable: + +```vyper +self.person.name = "vyper" +self.person.age = 33 +``` + +Then, we can copy this state variable into memory by declaring a variable of type struct and assigning the state variable: + +```vyper +p: Person = self.person +``` + +We can then change the name to "solidity" and the age to 22, but this will only update the value stored in memory, not the state variable. + +```vyper +p.name = "solidity" +p.age = 22 +``` + +We can compile this code using the Vyper compiler and then deploy the contract. + +To compile the code, we can click on the Vyper icon. Then click "Compile Ref.vy". The contract will be compiled. Now, we can deploy the contract. + +We can click on the "Deploy & run transactions" tab. Then we can click on the name of the contract file, which is Ref.vy. Next, we can click on the "Deploy" button to deploy the contract. + +We can see the state variables under the "Deployed Contracts" tab. We have "myMap", "nums", and "person". + +We can call the state variables to check what values are stored. We can call the state variable "nums" with index 0: + +```bash +nums(0) +``` + +We see it returns 0. This is because we did not set any values for index 0. Let's now call the state variable "nums" with index 1: + +```bash +nums(1) +``` + +We get 456, because we set the value for index 1 to 456. + +Next, we can call the state variable "person": + +```bash +person +``` + +We see it returns "name": "vyper" and "age": 33, because we set those values in the state variable. + +## Summary + +This is how we can store data in different reference types in Vyper. Remember that when using structs or mappings, we need to understand how these are copied. We can copy the value in a state variable into memory using a variable, but this only copies the value at that moment in time, not a reference to the state variable. So, if the state variable is updated, the value stored in the memory variable won't be updated. From 92e2cbe1ce4e52acb944310a2fa9401a333d0dfa Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:54:26 -0700 Subject: [PATCH 555/797] Equious updated courses/vyper-101/1-favorites/19-claude/+page.md. --- .../vyper-101/1-favorites/19-claude/+page.md | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/19-claude/+page.md b/courses/vyper-101/1-favorites/19-claude/+page.md index 272f5e0b5..b9ea4869c 100644 --- a/courses/vyper-101/1-favorites/19-claude/+page.md +++ b/courses/vyper-101/1-favorites/19-claude/+page.md @@ -1,3 +1,69 @@ ---- - title: Claude - --- \ No newline at end of file +## AI Tutor: Claude 3.5 + +We are going to start working with AI agents. Claude 3.5 is a great AI agent to get started with, but so is Chat GPT 4.0. + +Claude is especially helpful for beginners, but when things get more advanced it might break down. Let's start with a simple question for Claude: + +```python +What is this line representing in Vyper? +``` + +To tell Claude we are writing a code block, we enter three backticks, then hit Shift-Enter. Then, we paste our code: + +```python +nums: public(uint256[10]) +``` + +and press Enter. + +Claude tells us this line declares a public state variable called `nums`, and that it is an array of 10 unsigned integers. It also tells us that `public` means the array can be read externally and a getter function is automatically generated. + +Next, we ask Claude: + +```python +What even is an array? +``` + +Claude responds: + +An array is a data structure that stores multiple elements of the same type in a contiguous memory location. It allows you to: + +- Store multiple values under a single variable name +- Access elements by their index (position) +- Have a fixed or dynamic size depending on the programming language +- Organize and efficiently manage collections of data + +Claude also gives us an example: + +```python +[10, 20, 30, 40, 50] +``` + +and explains that the first element is 10 and the third element is 30. + +We are going to ask Claude one more question: + +```python +Ok, what's an example of an array of 10 like in the Vyper above? +``` + +Claude gives us this example: + +```python +nums: public(uint256[10]) = [ + 100, # index 0 + 200, # index 1 + 300, # index 2 + 400, # index 3 + 500, # index 4 + 600, # index 5 + 700, # index 6 + 800, # index 7 + 900, # index 8 + 1000 # index 9 +] +``` + +Claude explains that if we wanted to access the element in position 2 we would use `nums[2]` which would return 300. + +There are a lot of different AI agents out there, with different strengths and weaknesses. You can explore the ones that are free and see what you prefer. GitHub Copilot is another great one. From 25980a60dba7961a725343169f9ce0589aa96d1b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:54:51 -0700 Subject: [PATCH 556/797] Equious updated courses/vyper-101/1-favorites/2-best-practices/+page.md. --- .../1-favorites/2-best-practices/+page.md | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/2-best-practices/+page.md b/courses/vyper-101/1-favorites/2-best-practices/+page.md index 7c54c2de2..66a9e0c34 100644 --- a/courses/vyper-101/1-favorites/2-best-practices/+page.md +++ b/courses/vyper-101/1-favorites/2-best-practices/+page.md @@ -1,3 +1,51 @@ ---- - title: Best Practices - --- \ No newline at end of file +## Best Practices (Don't Skip!!) + +We're going to start off by talking about some best practices so that you can get the absolute most out of this course and be as effective as possible. + +You're either watching this on Cyfr.in Updraft or on YouTube. We encourage everyone to watch this on Cyfr.in Updraft, because we've got a ton of features to make the learning experience that much easier for you. + +If you are watching this on Cyfr.in Updraft, though, there's a couple links I need you to be aware of. The first one, in the top right, is going to be the GitHub Resources page. This will bring you over to what's called a GitHub repo, or a GitHub repository, or basically a site that has all the code and all the information and basically all the materials that you're going to need to learn everything in our curriculum. You could basically think of this as your bible for the duration of your blockchain developer journey. + +Additionally, in this GitHub, there's a Discussions tab right here that you can click on, and in here is where you can ask questions, discuss with other people taking the course, interact with members helping out, and it's where you can discuss anything that you're having trouble with. + +Then, on the other side, you'll see this tab called Written Lessons. If you cannot stand the voice coming out of my mouth, you can just flip over to that, and just read the course curriculum as well, if you prefer the written content over the video content. It's good to go over to the written lessons anyway to maybe copy paste some stuff. + +If you scroll down here, right now it's blank, but if anytime there is an update to a video, something's changed in the video, and we haven't swapped out the video yet, you'll see a little Updates section with information saying, "Hey, the video says this, but you should do this instead." + +Now, like I said, this is a very fast-moving industry, and sometimes things change, and sometimes things need to be updated. So, when you're watching one of these videos, be sure to look for the Updates tab at the bottom, and then additionally, whenever you're working with the code that we're working with, I will give you a link to the finalized edition that you can use as a reference as well to make sure that the code that you're working with actually is going to match what we're going to build. + +Additionally, if you think you've found something that is different, or doesn't quite work, be sure to make a discussion for it in that GitHub repo. Like I said, it's going to be your bible. + +Additionally, there's a link to join the GitHub discussions. This is your platform to ask questions, engage with the community, and learn with both other people taking the course, and also our TAs who are going to be helping you out along the way. + +Additionally, there is a link to the Discord for more real-time communication. I urge you to ask questions in the GitHub discussions as well, because those are going to be indexed, going to make them much easier to Google search later and have them show up, as opposed to Discord. Discord is still phenomenal for you to join them. + +For those of you watching on YouTube, hello, you should scroll down to the description, and in the description are going to be links to these resources as well, and additionally, a link to Cyfr.in Updraft. If you've been watching, you've already seen some of the advantages that Cyfr.in Updraft has, including Written Lessons, single videos, and there's also ways to track your progress instead of having to scrub on a giant YouTube video. So, for all of you who are watching this on YouTube, definitely be sure to go over to Cyfr.in Updraft, sign up there and watch the curriculum there because your learning experience will be much better. But, leave this video playing in the background on YouTube, so we get the bump from the YouTube algorithm. Thank you. + +That being said, as we go through this course, we're also going to teach you some best practices on working with artificial intelligence, how to best prompt these AIs, so that they can give you the best results. Just keep in mind, they sometimes get things wrong. And, it's a good idea if you are going to use an AI to fact-check it with a human, or another resource. + +So, be sure to say hi in the discussions and maybe meet some like-minded peers. + +And, additionally, once we do get to the coding portion of this course, it's a good idea to code along with me, as I'm explaining things. So, having the video up, as well as your coding screen, is a good idea, so you can follow along with me, as I'm explaining it. If you're watching this on Cyfr.in Updraft, you can just click the little video pop-out button and have the video pop out as such, and code next to it. + +All of this is to say, if you run into an issue, jump to that GitHub repo, and make a discussion. We will also be giving you some tips very soon about how to best make a discussion. Yes, asking well-formatted questions is not only the secret to being a fantastic AI prompt engineer, but also becoming an incredibly successful developer. We're going to learn how to ask well-formatted questions, and whenever we post on discussions or forums or whatever, we're going to work on formatting them as best as possible. + +Take breaks. I cannot tell you how many people have tried to rush through these courses and be like, "Oh, I'm going to finish in a single weekend!" Your brain doesn't work like that. Your brain needs time to absorb the information, so take breaks. Maybe every 25 minutes to a half hour, take a 5 minute break, or maybe you like working in longer chunks, maybe take a whole hour, and then take a 15-20 minute break. Don't try to rush through the whole video in a day, you're not going to retain the information. Go outside, go for a walk, grab some ice cream, get some coffee, go to the gym. Your brain needs time to have the information settle. Maybe every 2 hours, just step away. Maybe be done for the day. Work at whatever pace makes sense for you. Everyone's going to have a different learning pace. There is no right speed for this course. I've had people take my courses in 2 weeks, in 3 months, in 6 months. It doesn't matter. Pick a pace that you can do, and stick to it. Not only work at your pace, make sure that I'm talking at a pace that makes sense for you. There's a little gear icon in the YouTube video here, where you can change the speed of how I'm talking and how fast the video's going. So, if I'm talking way too fast for you, then you can slow me down. But, if I'm talking too slow, then you can speed me up. + +And, if you're watching this on Cyfr.in Updraft, you have the same dials as well in the bottom right-hand corner. Additionally, if English isn't your native language, we have several different subtitles on the Cyfr.in Updraft video player as well. So, make the adjustments you need to make me go the speed you want me to go. And, of course, this course is modular, so you can bounce around topic to topic, and go to where you want to go. + +You don't want to do any full stack stuff, then skip that section. If you want to go right to the advanced stuff, do that. Like I said, go the pace and take the learnings that you want to do. + +And, after every lesson, it might be a good idea to go back and reflect on each lesson to really make sure the knowledge gets ingrained. Repetition is the mother of skill, and we're going to be repeating a lot of smart contract development. + +Now, the last bit here is in the Cyfr.in Updraft platform. We're going to have quizzes that you can take to help see if you learn the knowledge that you were supposed to learn. + +If you're watching this on YouTube, you don't have that, so go sign up for Cyfr.in Updraft and then play the YouTube video in the background, so the YouTube algorithm bumps this stuff. But, additionally, at the end of every section, if you go to the GitHub repo associated with that section, and you scroll down, there's going to be a bonus NFTs section with a link. This will bring you to a coding challenge on chain that you can actually solve to mint yourself an NFT, a badge of honor proving that you gained the knowledge that you were supposed to. + +These are optional challenges that you can do to try to make sure that you actually learned what was meant to be learned here. + +And, if you do solve them, you get a very cool NFT along with it. Don't know what an NFT is? Don't worry, we'll teach you later. + +Blockchain development and open source development world is incredibly collaborative. So, be sure to use tools like, of course, the GitHub Discussions tab, Ethereum Stack Exchange, the decentralized Q&A forum, Pyra, issues on different GitHubs, artificial intelligence and more. + +And, like I said, we'll give you more tips on how to most effectively use these sites in the future, and the reason I'm putting so much emphasis on this and that I will continue to put so much emphasis on this, is being a successful smart contract developer is more than just knowing how Solidity works. Knowing where to go for information and how to collaborate with people is often more important than your smart contract knowledge, because oftentimes you're going to run into issues you don't know how to solve, so we're going to teach you to unblock yourself on this and really anything in life, plus syncing with other people in this space makes it way more fun. \ No newline at end of file From 75cc77be837a92675e3da9d5543850f9c97265c0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:55:30 -0700 Subject: [PATCH 557/797] Equious updated courses/vyper-101/1-favorites/20-arrays-lists/+page.md. --- .../1-favorites/20-arrays-lists/+page.md | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/20-arrays-lists/+page.md b/courses/vyper-101/1-favorites/20-arrays-lists/+page.md index 3650aa247..fb4536ca6 100644 --- a/courses/vyper-101/1-favorites/20-arrays-lists/+page.md +++ b/courses/vyper-101/1-favorites/20-arrays-lists/+page.md @@ -1,3 +1,40 @@ ---- - title: Arrays Lists - --- \ No newline at end of file +## Arrays / Lists + +We've learned about different reference types, let's add them to our smart contract. We'll start with adding a minimal list of favorite numbers. + +We'll create a new variable called `list_of_numbers`. + +```python +list_of_numbers: public(uint256[5]) = [0, 0, 0, 0, 0] +``` + +We've now created a public array called `list_of_numbers` that is five elements long. + +We can read from this array by interacting with the contract via the terminal, for example: + +```bash +list_of_numbers +``` + +To update this array, we'll create a new function called `add_number`. + +```python +@external +def add_number(favorite_number: uint256): + self.list_of_numbers[self.index] = favorite_number + self.index = self.index + 1 +``` + +This function takes a `favorite_number` as input and updates the `list_of_numbers` at the current index. + +To ensure that our `list_of_numbers` doesn't exceed the length of five, we'll create a new variable `index` at the top of our contract: + +```python +index: public(uint256) = 0 +``` + +We've set this index to zero in our constructor (`init`) function. We can then use this `index` variable to keep track of the next available element in the array. + +**Video Tag:** Show this process in the deployed contract in the terminal, make sure to show it with the updated array. + +We've now found a way to incrementally add numbers to this array. If we try to exceed the length of the array, the transaction will revert. From 36b483d73b1eecd7032045a6c73adb40c14e6eaf Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:56:13 -0700 Subject: [PATCH 558/797] Equious updated courses/vyper-101/1-favorites/21-idk/+page.md. --- courses/vyper-101/1-favorites/21-idk/+page.md | 61 ++++++++++++++++++- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/21-idk/+page.md b/courses/vyper-101/1-favorites/21-idk/+page.md index d226208fe..7ce9c8146 100644 --- a/courses/vyper-101/1-favorites/21-idk/+page.md +++ b/courses/vyper-101/1-favorites/21-idk/+page.md @@ -1,3 +1,58 @@ ---- - title: Idk - --- \ No newline at end of file +We're learning about structs and strings in Vyper. + +Structs are a way for us to create new custom types. They're like blueprints for variables, grouping together related data under a single name. This is how we might create a `Person` struct: + +```vyper +struct Person: + favorite_number: uint256 + name: String[100] +``` + +Strings are a typing we haven't learned about yet. A string is a fixed-size array of characters. For example, here's how we might create a string variable: + +```vyper +example_str: String[100] = "Test String" +``` + +We'll use structs to store data about multiple people in a list, and to accomplish this, we'll use an array of structs. + +To begin, let's create a variable in our `deploy` function: + +```vyper +@deploy +def __init__(): + self.my_favorite_number = 7 + self.index = 0 + self.my_name = "Patrick!" +``` + +We need to make our new `Person` type publicly accessible, so we'll add the keyword `public` before our `String` type: + +```vyper +my_name: public(String[100]) +``` + +We can now create an array of `Person` structs in our contract: + +```vyper +list_of_people: public(Person[5]) +``` + +This is an array of five `Person` structs, which is where we'll store our new `Person` information. + +Next, we'll create an external function to add a new `Person` to our `list_of_people` array: + +```vyper +@external +def add_person(name: String[100], favorite_number: uint256): + # Add favorite number to the numbers list + self.list_of_numbers[self.index] = favorite_number + # Add the person to the person's list + new_person: Person = Person(favorite_number = favorite_number, name = name) + self.list_of_people[self.index] = new_person + self.index = self.index + 1 +``` + +This function takes the `name` and `favorite_number` of a new `Person` and stores that data in our `list_of_people` array. + +We can now compile and deploy this contract. From 34d8987d97cdde2c35a350ee2a32fe449c1f5737 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:56:55 -0700 Subject: [PATCH 559/797] Equious updated courses/vyper-101/1-favorites/22-workshop/+page.md. --- .../1-favorites/22-workshop/+page.md | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/22-workshop/+page.md b/courses/vyper-101/1-favorites/22-workshop/+page.md index 789149836..f3d233c0b 100644 --- a/courses/vyper-101/1-favorites/22-workshop/+page.md +++ b/courses/vyper-101/1-favorites/22-workshop/+page.md @@ -1,3 +1,21 @@ ---- - title: Workshop - --- \ No newline at end of file +## Workshop Challenge + +We've gotten pretty far into our code. Now is a great time to pause and try a challenge. + +Can you get the `list_of_numbers` to return 8, and the `list_of_people` to return Wong instead of 0? + +**Hint:** You might have to add something to the contract, and then interact with the contract. + +**Pause the video and try to figure this out!** + +## Solution + +If your strategy was to just call `add_person` with Wang and 8 a bunch of times, that would work. We'll try that. + +```bash +add_person Wang 8 +``` + +We'll click `add_person` a few times here, and it looks like we are just spamming it! Oh, we've filled up the array! Now the index is too much. + +Well, now we're stuck with a list of people that just says `8 Wong` for every single person. This is definitely one way to do it, but it's not very elegant. We'll look at other, more effective ways to do this in future lessons. From 1b8dbb64d9fe13ca2cb964644970fece739c68c1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:57:20 -0700 Subject: [PATCH 560/797] Equious updated courses/vyper-101/1-favorites/23-hash-map/+page.md. --- .../1-favorites/23-hash-map/+page.md | 49 +++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/23-hash-map/+page.md b/courses/vyper-101/1-favorites/23-hash-map/+page.md index 94db4a4e4..35964fb38 100644 --- a/courses/vyper-101/1-favorites/23-hash-map/+page.md +++ b/courses/vyper-101/1-favorites/23-hash-map/+page.md @@ -1,3 +1,46 @@ ---- - title: Hash Map - --- \ No newline at end of file +## Retrieving Data From a Hashmap + +In the previous lessons, we created a smart contract that allowed us to add people to a list. However, we need to know the index of a person on the list in order to retrieve their data. + +Hashmaps, also known as mappings, are incredibly powerful because they allow us to retrieve data without knowing the index. We can think of a hashmap like a dictionary, with a string key and a uint256 value. + +In our smart contract, we are going to create one more storage variable called `name_to_favorite_number`, which will be a hashmap of type `string` and `uint256`. + +```python +name_to_favorite_number: public(HashMap[string, uint256]) +``` + +For example, we can add the name `Mariah` and associate her with the number 30. + +```python +# name_to_favorite_number: public(HashMap[string, uint256]) +``` + +In the `add_person` function, we are going to add the person to the hashmap. + +```python +@external +def add_person(name: String[100], favorite_number: uint256): + # Add favorite number to the numbers list + self.list_of_numbers[self.index] = favorite_number + # Add the person to the person's list + new_person: Person = Person(favorite_number = favorite_number, name = name) + self.list_of_people[self.index] = new_person + # Add the person to the hashmap + self.name_to_favorite_number[name] = favorite_number + self.index = self.index + 1 +``` + +Now, we can use the `name_to_favorite_number` function to retrieve Mariah's favorite number, without needing to know her index. + +```bash +name_to_fav... mariah +``` + +We can see that Mariah's favorite number is 30. + +```bash +0: uint256:30 +``` + +This is the power of hashmaps, or mappings, in smart contracts. They allow us to quickly retrieve data without knowing the index. As we learn more about smart contract programming, we will understand the trade-offs of each data structure and when to use each one. From 92c9b86a2403653a696c046d408d30fd0ea39896 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:57:58 -0700 Subject: [PATCH 561/797] Equious updated courses/vyper-101/1-favorites/24-recap/+page.md. --- .../vyper-101/1-favorites/24-recap/+page.md | 57 ++++++++++++++++++- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/24-recap/+page.md b/courses/vyper-101/1-favorites/24-recap/+page.md index 385e6edfe..37455df9a 100644 --- a/courses/vyper-101/1-favorites/24-recap/+page.md +++ b/courses/vyper-101/1-favorites/24-recap/+page.md @@ -1,3 +1,54 @@ ---- - title: Recap - --- \ No newline at end of file +In this lesson, we will continue to develop our smart contract which stores favorite numbers. Let's take a look at what we have done so far. + +We have created a new type called a **struct**, called **Person**, which has two variables: + +- **favorite_number**: A public variable to store our favorite number +- **name**: A public string variable to store a name + +We have defined several state variables: + +- **my_name**: A string which stores our name. +- **my_favorite_number**: A public variable to store our favorite number. +- **list_of_numbers**: A public list that will store a list of favorite numbers. +- **list_of_people**: A public list that will store a list of people. +- **index**: A public integer that will track the size of our lists. +- **name_to_favorite_number**: A public hashmap that will store a name and a favorite number as a key value pair. + +The **constructor** function is used to initialize the state variables. In our example, we will set the **my_favorite_number** to 7 and the **index** to 0. We will also set **my_name** to "Patrick". + +We also have two functions, a **store** function to set our favorite number and a **retrieve** function to retrieve our favorite number. + +Here is the code we have written so far: + +```python +# pragma version ^0.4.0 +# @license MIT + +struct Person: + favorite_number: uint256 + name: String[100] + +my_name: public(String[100]) +my_favorite_number: public(uint256) = 7 +list_of_numbers: public(uint256[5]) = [0, 0, 0, 0, 0] +list_of_people: public(Person[5]) +index: public(uint256) +name_to_favorite_number: public(HashMap[String[100], uint256]) + +@deploy +def __init__(): + self.my_favorite_number = 7 + self.index = 0 + self.my_name = "Patrick!" + +@external +def store(new_number: uint256): + self.my_favorite_number = new_number + +@external +@view +def retrieve() -> uint256: + return self.my_favorite_number +``` + +In the next lesson, we will deploy our smart contract and test it. From 20772cea31c37f7f40f76cb497780ce1d48626e3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:58:22 -0700 Subject: [PATCH 562/797] Equious updated courses/vyper-101/1-favorites/25-tenderly/+page.md. --- .../1-favorites/25-tenderly/+page.md | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/25-tenderly/+page.md b/courses/vyper-101/1-favorites/25-tenderly/+page.md index ea1b9ce91..a2afe1d48 100644 --- a/courses/vyper-101/1-favorites/25-tenderly/+page.md +++ b/courses/vyper-101/1-favorites/25-tenderly/+page.md @@ -1,3 +1,34 @@ ---- - title: Tenderly - --- \ No newline at end of file +We're going to learn how to deploy smart contracts with metamask, let's get started. Here's a simple smart contract that we're going to deploy: + +```python +pragma solidity ^0.8.4; + +contract Person { + string name; + uint256 favorite_number; +} +``` + +Let's go ahead and deploy this contract. First, we're going to need to create a new metamask wallet, and then we're going to need to select the network. We're going to select the Sepolia test network. + +Now, let's go through the steps of deploying the smart contract: + +- Click on the Remix **Deploy & Run Transactions** tab. +- Click on the **Deploy** button. +- Next we can hit the **My Favorite Number** +- Let's put Patrick. +- Let's put 7. +- Then we can hit the **Call** button. +- Now let's go ahead and deploy this contract. +- Select our **fake chain**. +- Click the **Deploy** button. We will see a message "Contract ... **compiled by Vyper**". Next, we will see a **green tick** above the **Contract** area. +- Click on the **green tick** to reveal the **deployed contract** details. +- We're going to hit the **index** +- We're going to click the **index** to reveal the **index** tab, +- We're going to hit the **call** button. +- Then, **MetaMask popped up** +- Now, we're going to go ahead and hit **Confirm**. +- We're going to click on **Confirm**. +- It says "Here I'm to help you!" + +That's how you deploy smart contracts with metamask. From ff4997a74a121aa72c7715546a180b6c663793f1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:06:50 -0700 Subject: [PATCH 563/797] Equious updated courses/vyper-101/1-favorites/26-zksync/+page.md. --- .../vyper-101/1-favorites/26-zksync/+page.md | 144 +++++++++++++++++- 1 file changed, 141 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/26-zksync/+page.md b/courses/vyper-101/1-favorites/26-zksync/+page.md index 6f25bb3d4..5470f68dd 100644 --- a/courses/vyper-101/1-favorites/26-zksync/+page.md +++ b/courses/vyper-101/1-favorites/26-zksync/+page.md @@ -1,3 +1,141 @@ ---- - title: Zksync - --- \ No newline at end of file +## Deploying ZkSync Contracts + +We will be exploring deploying contracts with ZkSync to a test net. + +First, we'll go to the plugin manager in Remix. + +If we look up ZkSync, we'll see there's an inactive module. We can go ahead and activate that. + +As of recording, the ZkSync plugin only works with Solidity. So, it doesn't work with Vyper at the moment. + +We are not going to be deploying this to ZkSync through Remix. + +However, when we switch over to Python, we will be deploying to ZkSync. + +First, we'll install `zksync-python`: + +```bash +pip install zksync-python +``` + +Now, we can open a Python script and import the relevant libraries: + +```python +import zksync +from zksync import Account +from zksync.transaction import DeployTransaction +from zksync.signer import PrivateKeySigner +from zksync.utils import to_hex + +from zksync.contracts import ( + zkSyncContract, + zkSyncInterface +) +from zksync.provider import ZkSyncProvider +from zksync.wallet import Wallet +``` + +We'll then initialize an account, which we'll use to deploy the contract. + +```python +PRIVATE_KEY = "0x..." +signer = PrivateKeySigner(PRIVATE_KEY) +wallet = Wallet(signer, ZkSyncProvider(url='https://zksync2-testnet.zksync.io/')) +address = wallet.get_address() +``` + +We'll define the address of the contract. + +```python +contract_address = "0x..." +``` + +Now, we'll set the `bytecode` of the contract: + +```python +bytecode = "0x..." +``` + +And, we'll specify the contract's constructor arguments. + +```python +constructor_args = [] +``` + +We'll instantiate a deploy transaction. + +```python +deploy_tx = DeployTransaction( + address=address, + contract_address=contract_address, + bytecode=bytecode, + constructor_args=constructor_args +) +``` + +We'll then call the `sign_deploy_transaction` method to sign the deploy transaction. + +```python +signed_deploy_tx = wallet.sign_deploy_transaction(deploy_tx) +``` + +Finally, we'll call the `send_deploy_transaction` method to send the transaction to the network. + +```python +wallet.send_deploy_transaction(signed_deploy_tx) +``` + +Now, we can call the deployed contract's functions. We'll define the name of the function and its arguments. + +```python +function_name = "add" +arguments = [10, 20] +``` + +Now, we can use the `zksyncInterface` class to call the `function_name` method. + +```python +zkSyncInterface(wallet.get_address(), wallet.get_signer(), ZkSyncProvider(url='https://zksync2-testnet.zksync.io/')) +``` + +We'll then call the `call_function` method to call the contract's function. + +```python +zksyncInterface.call_function(function_name, arguments) +``` + +We'll then call the `zksyncContract` class to call the `get_balance` method. + +```python +zksyncContract(wallet.get_address(), wallet.get_signer(), ZkSyncProvider(url='https://zksync2-testnet.zksync.io/')) +``` + +We'll then call the `get_balance` method to get the contract's balance. + +```python +zksyncContract.get_balance() +``` + +Now, we'll call the `get_code` method to get the contract's code. + +```python +zksyncContract.get_code() +``` + +Finally, we'll call the `get_transactions` method to get the contract's transactions. + +```python +zksyncContract.get_transactions() +``` + +We'll then print the results. + +```python +print(zksyncContract.get_balance()) +print(zksyncContract.get_code()) +print(zksyncContract.get_transactions()) +``` + +This will print the contract's balance, code, and transactions. + +We've now deployed a ZkSync contract and called its functions. From fe7d40197e318052d00db5c9b3b09ccbcc858079 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:07:16 -0700 Subject: [PATCH 564/797] Equious updated courses/vyper-101/1-favorites/27-share/+page.md. --- .../vyper-101/1-favorites/27-share/+page.md | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/27-share/+page.md b/courses/vyper-101/1-favorites/27-share/+page.md index f82ca3a05..7a9c4b0ea 100644 --- a/courses/vyper-101/1-favorites/27-share/+page.md +++ b/courses/vyper-101/1-favorites/27-share/+page.md @@ -1,3 +1,20 @@ ---- - title: Share - --- \ No newline at end of file +## Sharing your progress + +We're going to talk about the tweet me button on the Moccasin Vyper full course repo. + +Go to the repo on GitHub and scroll down to Vyper 101. + +We'll be talking about the section titled "Welcome to Remix - Favorite's List". + +Click the tweet me button. If you're signed in, this will open a tweet intent. You should see the following text: + +``` +I just deployed a Smart Contract! +Thanks @PatrickAlphaC, @zkSyncdevs, and @CyfrinUpdraft! +``` + +Go ahead and send that tweet. Be sure to say hi, we're so excited you're deploying your first smart contract! + +You can even thank Tenderly for helping make getting Testnet ETH a lot easier. + +We love hearing from all of you, so make sure you tweet out when you deploy your first contract. From 8d47ca5b58d18a812cc24aff202d8f78e3ccf7bd Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:08:23 -0700 Subject: [PATCH 565/797] Equious updated courses/vyper-101/1-favorites/28-evm/+page.md. --- courses/vyper-101/1-favorites/28-evm/+page.md | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/28-evm/+page.md b/courses/vyper-101/1-favorites/28-evm/+page.md index 4e09d4688..cdb563605 100644 --- a/courses/vyper-101/1-favorites/28-evm/+page.md +++ b/courses/vyper-101/1-favorites/28-evm/+page.md @@ -1,3 +1,50 @@ ---- - title: Evm - --- \ No newline at end of file +## Smart Contracts, EVM, and EVM-Compatible Chains + +We will start to look at how smart contracts are actually run. When we compile our smart contract, we are converting it into a format that the EVM can understand. + +The EVM, or Ethereum Virtual Machine, is a set of rules or standards that dictate how compiled smart contract code should look. + +Any blockchain that follows these rules is considered EVM-compatible. Examples of these include: + +- Ethereum +- Arbitrum +- Optimism +- Polygon +- zkSync + +We should be mindful of the chain that we are deploying to. A common mistake is to deploy to a chain that does not support the smart contract language we are using. We will discuss this in more detail later. + +We will be using zkSync in this lesson. Here is the code we will be working with: + +```python +# EVM: Ethereum Virtual Machine +# Ethereum, Arbitrum, Optimism, Polygon, zkSync + +# pragma version 0.4.0 +# @license MIT + +struct Person: + favorite_number: uint256 + name: String[100] + +my_name: public(String[100]) +my_favorite_number: public(uint256) = 7 + +list_of_numbers: public(uint256[5]) = [0, 0, 0, 0, 0] +list_of_people: public(Person[5]) +index: public(uint256) + +name_to_favorite_number: public(HashMap[String[100], uint256]) + +@deploy +def __init__(): + self.my_favorite_number = 7 + self.index = 0 + self.my_name = "Patrick!!" + +@external +def store(new_number: uint256): + self.my_favorite_number = new_number +``` + +This code works correctly with the zkSync compiler, but as we progress through this lesson, we will start to see how certain keywords, for example zkSync, do not work correctly. From b115d98b4a27bc0c72841bc02f54e04fa6cf7d29 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:08:54 -0700 Subject: [PATCH 566/797] Equious updated courses/vyper-101/1-favorites/29-pure-and-view/+page.md. --- .../1-favorites/29-pure-and-view/+page.md | 81 ++++++++++++++++++- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/29-pure-and-view/+page.md b/courses/vyper-101/1-favorites/29-pure-and-view/+page.md index 91881a69e..e5ad08222 100644 --- a/courses/vyper-101/1-favorites/29-pure-and-view/+page.md +++ b/courses/vyper-101/1-favorites/29-pure-and-view/+page.md @@ -1,3 +1,78 @@ ---- - title: Pure And View - --- \ No newline at end of file +## Pure vs. View Functions + +We're going to look at a couple of key concepts in Vyper: `pure` and `view` functions. These are important to know to write better smart contracts. + +We'll use the `@pure` and `@view` decorators in our code. Let's start with the `@pure` decorator. + +**Pure Functions** + +A `pure` function is a function that: + +- **Is read-only:** It doesn't modify the state of the blockchain. +- **Does not read state or global variables:** This means it can't access any data that's stored on the blockchain or in the global scope. + +Let's look at an example: + +```python +@external +@pure +def add(x: uint256, y: uint256) -> uint256: + return x + y +``` + +This function takes two inputs, `x` and `y`, both of which are `uint256` (unsigned integers up to 256 bits). The function returns their sum. Since it's `@pure`, we know it's read-only and doesn't use any state or global variables. + +**View Functions** + +A `view` function is also read-only, but it can read data from the blockchain. This includes state variables and global variables. Global variables are those defined by the EVM like `block` and `msg`. + +For example, we can read from a state variable called `count`: + +```python +@external +@view +def add_to_count(x: uint256) -> uint256: + return x + self.count + block.timestamp +``` + +This `view` function returns the sum of the input `x`, the current value of the state variable `count`, and the current block timestamp. + +Let's recap: + +- **Pure functions** are read-only and don't read any state or global variables. +- **View functions** are read-only but can read state and global variables. + +**Code Example** + +```python +@external +@pure +def add(x: uint256, y: uint256) -> uint256: + return x + y + +count: public(uint256) + +@external +@view +def add_to_count(x: uint256) -> uint256: + return x + self.count + block.timestamp +``` + +In this example, `add` is a `pure` function, and `add_to_count` is a `view` function. + +**Deploying and Interacting with the Contract** + +Let's deploy the contract and try using these functions: + +1. **Compile the contract:** We can compile the code and get the ABI (Application Binary Interface) and bytecode, which are needed to deploy the contract. +2. **Deploy the contract:** We can deploy the contract to the blockchain using a tool like Remix. +3. **Call the `add` function:** This function is `@pure`, so it won't modify any state. We can call it with two inputs, say 2 and 3, and it will return 5. +4. **Call the `add_to_count` function:** This function is `@view`, so it won't modify any state. We can call it with an input, say 2, and it will return a value that's the sum of 2, the current value of the `count` state variable, and the current block timestamp. + +**Important Considerations** + +- Using `@pure` and `@view` functions can make your smart contracts more gas-efficient. This is because they don't need to write data to the blockchain. +- `Pure` functions are deterministic: They always return the same output for the same input. This is useful for functions that are used in calculations or for verifying data. +- `View` functions are useful for reading data from the blockchain and displaying it to users. + +We've just scratched the surface of pure and view functions. There's much more to learn, like their relationship to the EVM and their differences from other function types. But this overview should give you a good starting point. From de1bfbe306c11ada412ae1dbcee89585f5cd45b0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:09:26 -0700 Subject: [PATCH 567/797] Equious updated courses/vyper-101/1-favorites/3-mox-best-practices/+page.md. --- .../1-favorites/3-mox-best-practices/+page.md | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/3-mox-best-practices/+page.md b/courses/vyper-101/1-favorites/3-mox-best-practices/+page.md index 92169430e..34fa8fcd4 100644 --- a/courses/vyper-101/1-favorites/3-mox-best-practices/+page.md +++ b/courses/vyper-101/1-favorites/3-mox-best-practices/+page.md @@ -1,3 +1,36 @@ ---- - title: Mox Best Practices - --- \ No newline at end of file +## Welcome to Solidity Fundamentals: Best Practices + +Let's start by talking about best practices. We will be looking at some best practices that we cover in our Moccasin course. + +If you are viewing this lesson on Cyfrin Updraft, you can head to the **Course Resources** section and you will be taken to the **Cyfrin/mocassin-full-course-cu** GitHub repository. This repository has all the codebase associated with the course. For instance, if we click on **Section 1** of **Vyper 101**, which is titled **Welcome to Remix - Favorite's List**, you will be taken to a repository called **Cyfrin/remix-favorites-cu**. This repository has the code associated with that section in the **Favorites.vy** file. + +If you are watching this on YouTube, the links are provided in the description. + +We can also head back to the **Cyfrin/mocassin-full-course-cu** repository. In here, we can go to the **Discussions** tab. This is a good place to come if you have any questions. We will teach you how to ask questions in a manner that is helpful to both humans and AI. + +We will be using AI throughout the course. As of recording, our favorites include **Claude**, **Cursor**, and **ChatGPT**. + +We recommend that you pause the video and create a GitHub account. GitHub is crucial to your success as a smart contract developer, or even just as a technical person in Web3. + +We also recommend that you check out the **Twitter** and **LinkedIn** links that are provided in the repository. + +One other important tool is **Stack Exchange Ethereum**. This is a good place to go to ask questions about Ethereum in general. + +We will now move on to **Section 1** of **Moccasin Fundamentals**: **Welcome to Python!** + +## Welcome to Python! + +We're going to do a code block here. We're going to make a little Python script. I'm going to start with a **__main__** function, which is a special function in Python that allows code to be run in a top level. + +```python +if __name__ == "__main__": + print("Hello world") +``` + +So, we can copy this code block, and paste it into our terminal. This will print out **Hello world**. + +```bash +python code.py +``` + +And there you have it. Now, we're going to go to the next lesson. From c298c904e4dbe162477735ae19ddcad6e8f9b127 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:11:10 -0700 Subject: [PATCH 568/797] Equious updated courses/vyper-101/1-favorites/30-conditionals/+page.md. --- .../1-favorites/30-conditionals/+page.md | 74 ++++++++++++++++++- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/30-conditionals/+page.md b/courses/vyper-101/1-favorites/30-conditionals/+page.md index 1d57c9ca3..891580126 100644 --- a/courses/vyper-101/1-favorites/30-conditionals/+page.md +++ b/courses/vyper-101/1-favorites/30-conditionals/+page.md @@ -1,3 +1,71 @@ ---- - title: Conditionals - --- \ No newline at end of file +## Conditionals in Vyper + +We'll now cover the conditional statement in Vyper. This statement allows us to control the flow of our code based on different conditions. It's similar to the `if else` statement you might be familiar with in other programming languages. + +Let's create an example of an `if else` conditional statement in Vyper. We'll create an external function, we'll call this function `if_else`, which takes a single input of `uint256`. It will return a `uint256` value as well. + +```python +@external +def if_else(x: uint256) -> uint256: +``` + +Now, we'll write the `if else` conditional statement. Let's say `if` the input `x` is less than or equal to 10, then we'll return 1. + +```python +@external +def if_else(x: uint256) -> uint256: + if x <= 10: + return 1 +``` + +Then we'll add the `else` statement, we'll return 0 for this example. + +```python +@external +def if_else(x: uint256) -> uint256: + if x <= 10: + return 1 + else: + return 0 +``` + +If we wanted another conditional statement in between, we would say `else if`, but in Vyper, we would type `elif`. + +```python +@external +def if_else(x: uint256) -> uint256: + if x <= 10: + return 1 + elif x <= 20: + return 2 + else: + return 0 +``` + +For this example, we forgot to make this a pure function, so let's do that. + +```python +@external +pure +def if_else(x: uint256) -> uint256: + if x <= 10: + return 1 + elif x <= 20: + return 2 + else: + return 0 +``` + +We'll now compile the contract. Click on the Vyper icon, Compile `ifElse.vy`. + +```bash +commands +``` + +We'll now call this function. We'll put 1 for `x` and call the function. We get a 1 back. + +We'll now put 20 for `x` and call the function. We get a 2 back. + +Lastly, we'll put 100 for `x` and call the function. We get a 0 back. + +This has been an introduction to `if else` conditional statements in Vyper. From 6a9fbebb6bf273e14f79b99364352201b4896cbd Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:11:36 -0700 Subject: [PATCH 569/797] Equious updated courses/vyper-101/1-favorites/31-workshop-pt-2/+page.md. --- .../1-favorites/31-workshop-pt-2/+page.md | 49 +++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/31-workshop-pt-2/+page.md b/courses/vyper-101/1-favorites/31-workshop-pt-2/+page.md index 789149836..3ad66fc1d 100644 --- a/courses/vyper-101/1-favorites/31-workshop-pt-2/+page.md +++ b/courses/vyper-101/1-favorites/31-workshop-pt-2/+page.md @@ -1,3 +1,46 @@ ---- - title: Workshop - --- \ No newline at end of file +## Welcome to Remix - Favorite's List + +Congratulations on finishing the "Welcome to Remix - Favorite's List" section! Before we jump off and wrap up this section, we have a workshop for you. On every single section moving forward, at the end, we're going to have a little workshop for you to practice and drill in some of the things that we taught you. + +Here's where AI is incredibly helpful because AI will very often be able to give you the right answer. You can just work with AI and figure out a solution that you like because oftentimes there actually might be multiple solutions. + +For all these workshops, there will be like a little prompt, and what we want you to do is to spend at most 25 minutes on the prompts. If you spend more than 25 minutes, stop, take a break, and then come back and work with an AI that you like to help solve these. Or if an AI is giving you trouble, you can always jump into the discussions, jump to the Discord, etc. + +Here are the three prompts that we want you to do: + +1. Create a function called `add` that adds one to whatever is in `self.favorite_number`. +2. Have the starting favorite number be different from seven and check to make sure it's the number you set. +3. Create a new type using the `struct` keyword and create a function that will save a new variable of that type to a state/storage variable. + +Here are some code blocks to get you started. + +```python +struct Person: + favorite_number: uint256 + name: String[100] + +my_favorite_number: uint256 + +# Static Array/List +list_of_numbers: public(uint256[5]) +list_of_people: public(Person[5]) +list_of_people_index: uint256 + +name_to_favorite_number: HashMap(String[100], uint256) + +@deploy +def __init__(): + self.my_favorite_number = 7 + +@external +def store(favorite_number: uint256): + self.my_favorite_number = favorite_number + +@view +def retrieve() -> uint256: + return self.my_favorite_number +``` + +We have a `struct Person` and a `my_favorite_number` that is a `uint256`. You would have your name as part of your struct, and we have our `deploy` function that is initialized with seven as the favorite number. We also have a `store` function that updates the number and a `retrieve` function to get the current number. + +Repetition is the mother of skill, and we want to make you incredibly skillful. So, pause the video, get cracking on some of these workshop problems. Spend at most 25 minutes on them, and then when you're done, if you still run into issues, work with an AI. From 91372fe623b2ff5219e0dbf8de15aed50a771604 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:12:05 -0700 Subject: [PATCH 570/797] Equious updated courses/vyper-101/1-favorites/32-recap-pt-2/+page.md. --- .../1-favorites/32-recap-pt-2/+page.md | 100 +++++++++++++++++- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/32-recap-pt-2/+page.md b/courses/vyper-101/1-favorites/32-recap-pt-2/+page.md index 385e6edfe..98519135f 100644 --- a/courses/vyper-101/1-favorites/32-recap-pt-2/+page.md +++ b/courses/vyper-101/1-favorites/32-recap-pt-2/+page.md @@ -1,3 +1,97 @@ ---- - title: Recap - --- \ No newline at end of file +We've learned about pragma version or `@version` where we can specify the version of our Vyper code directly on our contract. +We've deployed, and we've compiled and we've worked with the Remix Ethereum IDE, the online integrated development environment which is incredibly powerful for learning and seeing and deploying smart contracts. +We've created this struct Person which is our way of creating a new type. + +```vyper +struct Person: + favorite_number: uint256 + name: String[100] +``` + +We've got a whole bunch of state variables and we've set them all to public visibility so we can have that blue button for them so we can actually call them and actually see what these are when we actually deploy this contract. + +```vyper +my_favorite_number: uint256 +my_name: String[100] +people: Person[5] +index: uint256 +my_mapping: mapping(String[100] => uint256) +``` + +We've got several different types in here. We've got a string, a fixed sized string. We've got a uint256, aka a number. We've got a uint256 array which, similar to this string, this array or this list is saying hey there can be a total of five numbers in this list of numbers. Our string up here, my name, is a string where there can be a total of 100 characters in this string. We've got a list of people. We can even have a list or an array of our custom struct, our custom type Person, and we can have up to five people in this list of people. We also have an index which is just a number to keep track of hey, what number are we on here? And then finally we have this very advanced data structure called a hash map, or a mapping where it takes a key of a string and a value of a number. + +```vyper +my_favorite_number: uint256 +my_name: String[100] +people: Person[5] +index: uint256 +my_mapping: mapping(String[100] => uint256) +``` + +We have a constructor, where we have this deploy section where we set my favorite number to seven. So that once the instance of this contract is deployed, my favorite number gets initialized to seven. We set self. index to zero. If we didn't set it, it would still be zero, but we're explicitly setting it to zero. We have self.my name we're setting it to Patrick with an exclamation mark in here, but you should do your name instead of Patrick. + +```vyper +@version ^0.2.9 +def __init__(): + self.my_favorite_number = 7 + self.index = 0 + self.my_name = "Patrick!" +``` + +We've got a, and we've got a function that we learned with the def keyword, and the external decorator saying anyone outside of this contract can call this store function. If we didn't have this external keyword, it would be internal meaning only other functions inside this contract can actually call it. We're setting my favorite number to the new number that we're passing into store. We know that this is a state variable because we can see the self keyword here. Whenever we see the self keyword, we know we're referring to properties of the contract itself. Whereas this new number is just this temporary number that exists just for the duration of this function call. This self.my favorite number will persist outside of this function call. + +```vyper +@version ^0.2.9 +def __init__(): + self.my_favorite_number = 7 + self.index = 0 + self.my_name = "Patrick!" + +@external +def store(new_number: uint256): + self.my_favorite_number = new_number +``` + +We have a view function which allows us to just view some number instead of + +```vyper +@version ^0.2.9 +def __init__(): + self.my_favorite_number = 7 + self.index = 0 + self.my_name = "Patrick!" + +@external +def store(new_number: uint256): + self.my_favorite_number = new_number + +@external +def retrieve() -> uint256: + return self.my_favorite_number +``` + +And then we have our monstrosity function called add person where it takes a name of type string 100, a favorite number which is a uint256, and it adds this person to our list of numbers using the index, creates a new person using this wonderful struct syntax, it adds that person to our list of people, and then it adds that person to our hash map as well and increments the index. + +```vyper +@version ^0.2.9 +def __init__(): + self.my_favorite_number = 7 + self.index = 0 + self.my_name = "Patrick!" + +@external +def store(new_number: uint256): + self.my_favorite_number = new_number + +@external +def retrieve() -> uint256: + return self.my_favorite_number + +@external +def add_person(name: String[100], favorite_number: uint256): + self.people[self.index] = Person(favorite_number, name) + self.my_mapping[name] = favorite_number + self.index += 1 +``` + +And last but not least, congratulations on your first contract here. Now's the time to go grab a coffee, go grab an ice cream, go to the gym, go for a walk, and take a break because your mind needs it to digest all this wonderful information you just learned. Take that break, and we'll see you soon. From 95052fe1482c81a4cf2b8dbd2a72ad452df61140 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:14:08 -0700 Subject: [PATCH 571/797] Equious updated courses/vyper-101/1-favorites/4-walkthrough/+page.md. --- .../1-favorites/4-walkthrough/+page.md | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/4-walkthrough/+page.md b/courses/vyper-101/1-favorites/4-walkthrough/+page.md index e9d2a2138..3df46e366 100644 --- a/courses/vyper-101/1-favorites/4-walkthrough/+page.md +++ b/courses/vyper-101/1-favorites/4-walkthrough/+page.md @@ -1,3 +1,49 @@ ---- - title: Walkthrough - --- \ No newline at end of file +## Deployment of First Vyper Smart Contract + +In this lesson, we'll be deploying our first Vyper smart contract. We'll be using `remix.ethereum.org` (aka the Remix IDE) to build our code base here. You should follow along coding with us, and even try to do some coding yourself as we go on here. Remember, both on Cyfrin Updraft and on YouTube, you can change the speed of the video so that it matches your pace. + +### Smart Contract Code + +The smart contract code we will be deploying is: + +```python +# I'm a comment! +# SPDX-License-Identifier: MIT +# @version ^0.4.0 + +my_favorite_number: uint256 + +struct Person: + favorite_number: uint256 + name: String[100] + +# Static Array/List +list_of_people: public Person[5] +list_of_people_index: uint256 + +name_to_favorite_number: HashMap[String[100], uint256] + +@external +def store(favorite_number: uint256): + self.my_favorite_number = favorite_number + +@external +@view +def retrieve() -> uint256: + return self.my_favorite_number + +@external +def add_person(name: String[100], favorite_number: uint256): + new_person: Person = Person(favorite_number, name) + self.list_of_people[self.list_of_people_index] = new_person + self.list_of_people_index += 1 + self.name_to_favorite_number[name] = favorite_number +``` + +### Deploying the Smart Contract + +1. **Paste the code:** Open Remix IDE and create a new file. Paste the code from the code block above into the new file. +2. **Compile:** Click the "Compile" button to compile the code. +3. **Deploy:** Click the "Deploy" button to deploy the contract to the blockchain. + +We're excited for you to complete your first smart contract deployment! Remember to check the [Remix Favorites CU GitHub repository](https://github.com/Cyfrin/remix-favorites-cu) for the code and additional resources. From 004431c9bebcd67f8142970666250c3fbc05909e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:14:38 -0700 Subject: [PATCH 572/797] Equious updated courses/vyper-101/1-favorites/5-welcome-to-remix/+page.md. --- .../1-favorites/5-welcome-to-remix/+page.md | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/5-welcome-to-remix/+page.md b/courses/vyper-101/1-favorites/5-welcome-to-remix/+page.md index b5a5d1364..d1ee5b4fc 100644 --- a/courses/vyper-101/1-favorites/5-welcome-to-remix/+page.md +++ b/courses/vyper-101/1-favorites/5-welcome-to-remix/+page.md @@ -1,3 +1,34 @@ ---- - title: Welcome To Remix - --- \ No newline at end of file +## Welcome to Remix! + +We're going to begin by getting familiar with Remix, an Integrated Development Environment, or IDE, that's phenomenal for helping us visualize our smart contracts. We'll be using Remix throughout the course to build smart contracts using Vyper, a popular smart contract language. + +Remix has many features, including a built-in AI assistant that helps us understand concepts. While AI can be very useful, we need to understand the fundamentals of smart contract programming. AI can't always understand or provide accurate information about advanced concepts. + +### Getting Started with Remix + +1. Open the Remix IDE. You can find it at `remix.ethereum.org`. +2. Click on "New File" under the "Solidity/Vyper/EVM" section. +3. Choose "Vyper" as the file type and name your contract, e.g., `MinimalContract.vy`. +4. In this new file, add a basic Vyper smart contract template: + +```python +# Minimal Contract +pragma solidity ^0.6.12; + +contract Minimal: + def hello(self) -> str: + return "Hello World" +``` + +5. Save the file. +6. Go to your IDE's left panel and click on "Deploy" under the "Solidity/Vyper/EVM" section. + +### Working with the Vyper Compiler + +1. Click on the "Plugin Manager" button at the bottom of the Remix IDE. +2. In the search bar, type "vyper." +3. Activate the "Vyper Compiler" module. +4. You will now see the "Vyper Compiler" section on the left-hand side of the Remix IDE. +5. Click the "Compile favorites.vy" button to compile our smart contract. + +You can also access more advanced compiler settings if you click on the "Advanced Compiler Settings" button. This will allow you to set up your own local Vyper Compiler, but we will be using the remote compiler for now. From bd5d82e7e25909c62d1026e907745947b19c352e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:15:23 -0700 Subject: [PATCH 573/797] Equious updated courses/vyper-101/1-favorites/6-pragma-version/+page.md. --- .../1-favorites/6-pragma-version/+page.md | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/6-pragma-version/+page.md b/courses/vyper-101/1-favorites/6-pragma-version/+page.md index 5ebef9151..5054cdb86 100644 --- a/courses/vyper-101/1-favorites/6-pragma-version/+page.md +++ b/courses/vyper-101/1-favorites/6-pragma-version/+page.md @@ -1,3 +1,25 @@ ---- - title: Pragma Version - --- \ No newline at end of file +## Pragma Version + +We will start by setting a version for our Vyper smart contract. This is an important step to ensure that our code is compatible with the appropriate compiler version. + +The version is set using the `#pragma version` directive. + +We will use `0.4.0`, a stable and widely supported version. + +```python +#pragma version 0.4.0 +``` + +We can also use other versions, such as 0.4.1 and above, by using the `^` symbol to indicate a minimum version. + +```python +#pragma version ^0.4.0 +``` + +We will stick with `0.4.0` in this lesson. + +Using this version is recommended because it's widely supported and allows for greater compatibility across different compilers. + +For production code, it's best to use a specific version for the reasons mentioned above. + +Let's move on to the next step in creating our smart contract. From 42877d1cf3569f6bf5bfd0bc97a73c9f03ca3ef0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:15:50 -0700 Subject: [PATCH 574/797] Equious updated courses/vyper-101/1-favorites/7-comments/+page.md. --- .../vyper-101/1-favorites/7-comments/+page.md | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/7-comments/+page.md b/courses/vyper-101/1-favorites/7-comments/+page.md index d42c6c4b2..955769634 100644 --- a/courses/vyper-101/1-favorites/7-comments/+page.md +++ b/courses/vyper-101/1-favorites/7-comments/+page.md @@ -1,3 +1,27 @@ ---- - title: Comments - --- \ No newline at end of file +## Comments in Vyper + +We're going to talk about comments in Vyper. + +This little hashtag here is, or pound symbol, makes this whole line here, what's known as a comment. + +```python +# pragma version 0.4.0 +``` + +And typically, a comment is a line in your code where you can write pretty much whatever you want, and the compiler will ignore it. The compiler doesn't ignore these lines if it sees a comment. + +```python +# asdfagolsa asdfasrtafdsdf +``` + +We can also use comments to leave ourselves notes, like this: + +```python +# This is how we tell the Vyper compiler +# what version to use +# pragma version 0.4.0 +``` + +We can also copy and paste these comments into a text editor or a notes app so that we can refer to them later. + +It is important to save our work frequently, because if we lose our tab, we'll lose all of our text. From 28ccd5bb0e66c731fa931de469e4bb6509568d75 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:16:15 -0700 Subject: [PATCH 575/797] Equious updated courses/vyper-101/1-favorites/8-license/+page.md. --- .../vyper-101/1-favorites/8-license/+page.md | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/8-license/+page.md b/courses/vyper-101/1-favorites/8-license/+page.md index 6f900f5b0..e1d01d36c 100644 --- a/courses/vyper-101/1-favorites/8-license/+page.md +++ b/courses/vyper-101/1-favorites/8-license/+page.md @@ -1,3 +1,27 @@ ---- - title: License - --- \ No newline at end of file +We are building a simple smart contract for a favorites list. + +The first line of code we will write in our Solidity smart contract file should be: + +```python +pragma version 0.4.0 +``` + +This line tells the compiler what version of Solidity we will be using. In this case, we will be using Solidity version 0.4.0. + +Next, we will add another line that defines the license of our code: + +```python +@license MIT +``` + +This line tells the world that this code is licensed under the MIT license. + +Let's break down why we use a license: + +- There are many types of code licenses out there. +- Most of the code in the blockchain world is open source. +- This line tells the compiler what license our code is under. + +The MIT license is one of the most permissive licenses. This means that anyone can use, redistribute, or modify our code as they see fit. + +We've now established a basic code structure and license. From 0236c45f91155a21a736b05a0b3afff94204b59a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:16:40 -0700 Subject: [PATCH 576/797] Equious updated courses/vyper-101/1-favorites/9-compiling/+page.md. --- .../1-favorites/9-compiling/+page.md | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/1-favorites/9-compiling/+page.md b/courses/vyper-101/1-favorites/9-compiling/+page.md index 4c9310136..a71396dc8 100644 --- a/courses/vyper-101/1-favorites/9-compiling/+page.md +++ b/courses/vyper-101/1-favorites/9-compiling/+page.md @@ -1,3 +1,35 @@ ---- - title: Compiling - --- \ No newline at end of file +## Compiling + +We're going to look at the compilation process for a smart contract written using Vyper. + +Even with just this small contract, we have no code. All we have is a version and a license. Let's go ahead and compile this contract. + +We'll go to the Vyper compiler and click the Compile button. + +Clicking the "Compile favorites.vy" button gives us a compilation details box. + +We'll click the "Compilation Details" button and see bytecode, runtime bytecode, and ABI. + +The bytecode and runtime bytecode are sent to the blockchain because the blockchain only understands raw bytecode. The blockchain only understands zeros and ones and doesn't understand what "pragma version" means. So when we compile our code we're essentially transforming our human-readable code into machine readable code. + +If our compilation fails, it means we have a mistake in our code somewhere. + +Let's go back to our "favorites.vy" file and try adding a line with gibberish code: + +```python +asdfhasjh a:dhfpuiowht92y92 +``` + +Trying to compile this gives us an error: + +```bash +favorites.vy +SyntaxException:Semi-colon statements not allowed +line 4:11 +``` + +We'll remove the line and compile again. This time the compiler will successfully compile our code, which is indicated by a green checkmark. + +While we're not actually deploying a contract here, this is still important to help us understand the compilation process. + +As you get used to coding, you'll get used to hitting Cmd+S or Ctrl+S. From cb6175a1660f79f6c03bd62f9d70a67fe4aa17d6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:17:18 -0700 Subject: [PATCH 577/797] Equious updated courses/vyper-101/2-remix-coffee/1-introduction/+page.md. --- .../2-remix-coffee/1-introduction/+page.md | 87 ++++++++++++++++++- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/1-introduction/+page.md b/courses/vyper-101/2-remix-coffee/1-introduction/+page.md index c21ef2ce7..96c8cbb27 100644 --- a/courses/vyper-101/2-remix-coffee/1-introduction/+page.md +++ b/courses/vyper-101/2-remix-coffee/1-introduction/+page.md @@ -1,3 +1,84 @@ ---- - title: Introduction - --- \ No newline at end of file +## Introduction to Remix Buy Me A Coffee Smart Contract + +This lesson is part of the Cyfrin Updraft Vyper course. We will be exploring the Buy Me a Coffee smart contract. + +The code for this lesson is available on the following GitHub repo: + +```bash +https://github.com/Cyfrin/remix-buy-me-a-coffee-cu +``` + +We will be building a simple smart contract that allows people to send you money based on a price that we set. In this case, we'll be using a price of $50. We will also explore a withdrawal function that allows the owner of the contract to withdraw the funds. We will be using Remix and the Tenderly virtual network for this lesson. + +We will explore the following code: + +```python +pragma version 0.4.0 +pragma enable-decimals + +license: MIT +title: A sample buy-me-a-coffee contract + +@author You! +@notice This contract is for creating a sample funding contract + +# We'll learn a new way to do interfaces later... +interface AggregatorV3Interface: + def decimals() -> uint8: view + def description() -> String[1000]: view + def version() -> uint256: view + def getRoundData(roundId: uint80) -> (uint80, int256, uint256, uint256, uint80): view + def latestRoundData() -> (uint80, int256, uint256, uint256, uint80): view + +# minimum USD decimals: public(constant(decimal)) = 50.0 +MINIMUM_USD: public(constant(uint256)) = 50 * (10**18) +PRECISION: constant(uint256) = 1 * (10**18) +OWNER: public(immutable(address)) +funders: public(DynArray[address], 100) +address_to_amount_funded: public(HashMap[address, uint256]) +price_feed: public(AggregatorV3Interface) + +@deploy +def __init__(price_feed: address): + self.price_feed = AggregatorV3Interface(price_feed) + OWNER = msg.sender + +@internal +def _only_owner(): + assert msg.sender == OWNER, "Not the contract owner!" + +@external +@payable +def fund(): + usd_value_of_eth: uint256 = self.get_eth_to_usd_rate(self.price_feed, msg.value) + assert usd_value_of_eth >= MINIMUM_USD, "You need to spend more ETH!!" + self.address_to_amount_funded[msg.sender] += msg.value + self.funders.append(msg.sender) + +@external +def withdraw(): + self._only_owner() + for funder: address in self.funders: + self.address_to_amount_funded[funder] = 0 + self.funders = [] + send(OWNER, self.balance) + +@internal +@view +def get_eth_to_usd_rate(price_feed: AggregatorV3Interface, eth_amount: uint256) -> uint256: + # Check the conversion rate + a: uint80 = 0 + b: int256 = 0 + c: uint256 = 0 + d: uint256 = 0 + e: uint80 = 0 + (a, b, c, d, e) = staticcall(price_feed.latestRoundData()) + # We know the price has 8 decimals, so we need to add 1 + eth_amount: uint256 = convert(int256, (10**18) * (b * (10**-8))) + # return eth_amount: uint256 = convert(int256, price * eth_amount) + price: int256 = 0 + return price: int256 +``` + +We can compile and deploy this smart contract in Remix. Remix allows us to interact with our smart contract to fund it with our test ETH and then withdraw those funds as well. + +We can use Tenderly to see the balance of our deployed smart contract. From 339f304120f88902276ab88d7bfd01b4faebb7f3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:18:09 -0700 Subject: [PATCH 578/797] Equious updated courses/vyper-101/2-remix-coffee/10-chainlink-in-vyper/+page.md. --- .../10-chainlink-in-vyper/+page.md | 81 ++++++++++++++++++- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/10-chainlink-in-vyper/+page.md b/courses/vyper-101/2-remix-coffee/10-chainlink-in-vyper/+page.md index 54423f9d5..b00141c8c 100644 --- a/courses/vyper-101/2-remix-coffee/10-chainlink-in-vyper/+page.md +++ b/courses/vyper-101/2-remix-coffee/10-chainlink-in-vyper/+page.md @@ -1,3 +1,78 @@ ---- - title: Chainlink In Vyper - --- \ No newline at end of file +We are going to create a simple smart contract to teach you how to use Chainlink price feeds. + +We are going to use Remix to create this smart contract, with the following code. We will explain this code in detail later. + +```python +# @license: MIT +# @author: You! + +minimum_usd: uint256 + +@deploy +def __init__(): + self.minimum_usd = 5 + +@external +@payable +def fund(): + """Allows users to send $ to this contract. + Have a minimum $ amount send + """ + # How do we convert the ETH amount to dollars amount? + assert msg.value >= self.minimum_usd, "You must spend more ETH!" + +@external +def withdraw(): + pass +``` + +We want users to send us the minimum USD value. In this example, we have set this value to 5. So how do we convert this ETH amount to dollars? + +First, let's create a new function for this conversion. + +```python +@internal +def get_eth_to_usd_rate(): + # Address: 0x9aA77716935D5E4AC08b1f17f309aC232d236858 + # ABI + pass +``` + +We will need to obtain the price of ETH in dollars. + +Chainlink provides price feeds, which we can use for this conversion. We will need to get the Chainlink price feed address for the network we are working with. We can find this information in the Chainlink documentation. We are going to be working with the Sepolia testnet, and we can find the address for the ETH / USD price feed there. + +We have the address for the Chainlink price feed. Now, we need the ABI or the Application Binary Interface. This interface defines the functions of the Chainlink price feed contract. + +The ABI is also available in the Chainlink documentation. + +```python +@internal +def get_eth_to_usd_rate(): + # Address: 0x9aA77716935D5E4AC08b1f17f309aC232d236858 + # ABI + eth_usd_price_feed = Contract("0x9aA77716935D5E4AC08b1f17f309aC232d236858", + get_eth_to_usd_rate_abi) + # Now, we can call the latestRoundData function + # of the price feed and store it as a tuple. + # latestRoundData is a function that returns the latest round data for the price feed. + # It returns a tuple of four values: + # - current round + # - latest answer + # - latest timestamp + # - latest updated timestamp + # The second element of this tuple, + # latest answer, is the latest price + # of ETH in dollars. + ( + # current round + , + # latest answer + latest_answer + # latest timestamp + , + # latest updated timestamp + , + ) = eth_usd_price_feed.latestRoundData() + return latest_answer +``` From e5e0367e907ff16a183631aa7b3a222376e1c432 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:23:35 -0700 Subject: [PATCH 579/797] Equious updated courses/vyper-101/2-remix-coffee/11-abi/+page.md. --- .../vyper-101/2-remix-coffee/11-abi/+page.md | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/11-abi/+page.md b/courses/vyper-101/2-remix-coffee/11-abi/+page.md index 25fb9c94d..3520b15ae 100644 --- a/courses/vyper-101/2-remix-coffee/11-abi/+page.md +++ b/courses/vyper-101/2-remix-coffee/11-abi/+page.md @@ -1,3 +1,48 @@ ---- - title: Abi - --- \ No newline at end of file +## ABI + +The ABI (Application Binary Interface) is an important part of interacting with smart contracts. It defines the functions that a contract exposes and how different applications can interact with them. + +We'll look at a simple Vyper contract in Remix and explore the ABI generated by the compiler. + +### Generating the ABI + +Let's start by compiling our contract. + +```bash +Compile buy_me_a_coffee.vy +``` + +Once compiled, we can see the compilation details, including the ABI. The ABI is a JSON-formatted document that specifies the contract's functions, inputs, outputs, and other metadata. + +### Understanding the ABI + +The ABI is a list of different types of functions that the smart contract can accept. For example, we can see a `fund` function and a `withdraw` function in our contract. + +```python +"root": { + "0": { + "type": "string \"function\"", + "name": "string \"fund\"", + "stateMutability": "string \"payable\"", + "inputs": [], + "outputs": [] + } +}, +"1": { + "type": "string \"function\"", + "name": "string \"withdraw\"", + "stateMutability": "string \"nonpayable\"", + "inputs": [], + "outputs": [] +} +``` + +The ABI also includes information about the contract's version, EVM version, and other metadata. + +### Using the ABI + +The ABI is used by applications to interact with the smart contract. By providing the ABI to a library or tool, the application can understand the contract's functions and interact with them accordingly. + +The ABI doesn't include the contract's logic. It only defines the interface for interacting with the contract. + +We will see how to integrate the ABI into our smart contract in the next lesson. From 2b5e0edc94c632e6293e3cdaae23bf5284d5a526 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:24:06 -0700 Subject: [PATCH 580/797] Equious updated courses/vyper-101/2-remix-coffee/12-in-line-inter/+page.md. --- .../2-remix-coffee/12-in-line-inter/+page.md | 74 ++++++++++++++++++- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/12-in-line-inter/+page.md b/courses/vyper-101/2-remix-coffee/12-in-line-inter/+page.md index 60e5ba549..9801f2031 100644 --- a/courses/vyper-101/2-remix-coffee/12-in-line-inter/+page.md +++ b/courses/vyper-101/2-remix-coffee/12-in-line-inter/+page.md @@ -1,3 +1,71 @@ ---- - title: In Line Inter - --- \ No newline at end of file +## In-Line Vyper Interfaces + +In this lesson, we'll learn about in-line interfaces in Vyper. + +In-line interfaces are a way to define the functions and return types of a contract without needing to know the logic inside the contract itself. This is useful for interacting with contracts that have been deployed to a blockchain. + +We can define an in-line interface by using the `interface` keyword followed by the name of the interface and a colon. Inside the interface, we can define functions using the `def` keyword, followed by the function name and a colon. Then, we use a right arrow (`->`) to specify the return type for the function. An example of defining an interface is as follows: + +```vyper +interface AggregatorV3Interface: + def decimals(self) -> uint256: view + def description(self) -> String[1000]: view + def version(self) -> uint256: view + def latestAnswer(self) -> int256: view +``` + +We can use this interface to call the functions of the contract without needing to know the logic inside of the contract itself. For example, we could call the `latestAnswer` function using the following code: + +```vyper +price_feed: AggregatorV3Interface = AggregatorV3Interface(0x694A4A17699357215D6F4C081f1f309dDC325306) +return price_feed.latestAnswer() +``` + +This code snippet creates a variable called `price_feed` that holds an interface to the AggregatorV3Interface contract at the address `0x694A4A17699357215D6F4C081f1f309dDC325306`. Then, we can call the `latestAnswer()` function on this variable to obtain the price feed. + +Now we'll deploy a custom function, just to get and see this price feed here. + +```vyper +@external +def get_price() -> int256: + price_feed: AggregatorV3Interface = AggregatorV3Interface(0x694A4A17699357215D6F4C081f1f309dDC325306) + return price_feed.latestAnswer() +``` + +Now, we'll go ahead and deploy this. This custom function gets the latest answer from the price feed. It's an integer, but the price feed is using 8 decimals. We'll want to adjust that. + +```vyper +@external +def get_price() -> int256: + price_feed: AggregatorV3Interface = AggregatorV3Interface(0x694A4A17699357215D6F4C081f1f309dDC325306) + return price_feed.latestAnswer() / 10 ** 8 +``` + +This is what's going to return that price feed. We'll go ahead and deploy this to our blockchain. + +## Deploying to Blockchain + +To deploy this function to the blockchain, we can use Remix. Remix is an online IDE that allows us to write and deploy Solidity code to the blockchain. We'll also want to adjust the `decimals` value in the `AggregatorV3Interface` contract to 8 for this function to work properly. + +```vyper +interface AggregatorV3Interface: + def decimals(self) -> uint256: view + def description(self) -> String[1000]: view + def version(self) -> uint256: view + def latestAnswer(self) -> int256: view +``` + +This code snippet is defining the interface for the `AggregatorV3Interface` contract. The `decimals` function specifies that the returned value for this function is an `int256` (integer with 256 bits). We need to change this so it reflects the 8 decimals used by the price feed. + +Now, we'll paste this code into the `AggregatorV3Interface` contract, just so the `decimals` function now returns the correct value. + +```vyper +interface AggregatorV3Interface: + def decimals(self) -> uint256: view + def description(self) -> String[1000]: view + def version(self) -> uint256: view + def latestAnswer(self) -> int256: view + def latestRoundData(self) -> (int256,int256,int256,uint256,uint256): view +``` + +We can see that the `decimals` function is now correctly reflecting the 8 decimals that are being used in the price feed. We can deploy our `get_price()` function and test it. When we deploy, the `get_price()` function can be tested and it will return a price feed that is represented by 8 decimals. From dab6beeeaa46b826c3c6e6c7a7f1a6e29d471aef Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:25:24 -0700 Subject: [PATCH 581/797] Equious updated courses/vyper-101/2-remix-coffee/13-staticcall/+page.md. --- .../2-remix-coffee/13-staticcall/+page.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/13-staticcall/+page.md b/courses/vyper-101/2-remix-coffee/13-staticcall/+page.md index c3c2f772c..a9bf3ba9d 100644 --- a/courses/vyper-101/2-remix-coffee/13-staticcall/+page.md +++ b/courses/vyper-101/2-remix-coffee/13-staticcall/+page.md @@ -1,3 +1,12 @@ ---- - title: Staticcall - --- \ No newline at end of file +## Calling External Contracts in Vyper + +We are going to make sure that we use the proper keyword when we call external contracts. In Solidity, it�s pretty straightforward. We just call an external contract. However, iVyperer, we need to use a specific keyword. If we are calling a view function or don�t want to change any state, we use `staticcall`. Otherwise, we use `extcall`, which stands for external call. + +We will use the following code block to demonstrate how to call an external contract using `staticcall` in Vyper. + +```python +price_feed: AggregatorV3Interface = AggregatorV3Interface(0x6944AA1769357215DE4FAC081bf1f309aDC325306) +return staticcall price_feed.latestAnswer() +``` + +So, in this code block, we're first defining a variable called `price_feed` and setting it to an object of type `AggregatorV3Interface`. Next, we are saying that we want to return the value returned by the `latestAnswer` function, which is a view function in this case. We use `staticcall` since we are calling a view function. This means that we are not going to change any state in our contract. From fbbd0edeb31ab7ce2cc25c00450c5191bae7982f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:25:50 -0700 Subject: [PATCH 582/797] Equious updated courses/vyper-101/2-remix-coffee/14-tenderly/+page.md. --- .../2-remix-coffee/14-tenderly/+page.md | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/14-tenderly/+page.md b/courses/vyper-101/2-remix-coffee/14-tenderly/+page.md index ea1b9ce91..86c28316c 100644 --- a/courses/vyper-101/2-remix-coffee/14-tenderly/+page.md +++ b/courses/vyper-101/2-remix-coffee/14-tenderly/+page.md @@ -1,3 +1,29 @@ ---- - title: Tenderly - --- \ No newline at end of file +## Deploying to Tenderly Virtual Network + +We're going to deploy our contract to our fake Tenderly chain. Remember, if we have your Tenderly application setup, it will fetch data for a second. + +We'll switch to injected Metamask in our Remix IDE and select our fake chain. We'll then deploy the contract. Before deploying, we need to ensure the Solidity contract is compiled. This is a requirement of the Remix IDE as of this recording. + +After we deploy our contract, we'll switch back to Remix VM. Our fake chain is based on the Sepolia network, which is a test network. We've turned off state sync for this chain. That means we won't update the chain to the latest Sepolia block. This will keep costs down. + +We can then call the `get_price` function, which will return the ETH price on Sepolia when we first created this chain. + +Let's go over the major concepts we just used: + +1. **ABI** +2. **Address** +3. **Static Call** + +We need to understand what an ABI and address is when we interact with contracts. We got the address for our chainlink price feed from the chainlink documentation. We also got the ABI for the contract from the `AggregatorV3Interface` interface. This interface essentially defines the ABI and tells us which functions are available. + +When we interact with a contract, we have to specify whether it is a `static call` or `ext call`. A `static call` does not modify the state of a contract. In this case, we were performing a `static call` to our `get_price` function because we were simply calling the view function of the contract. + +If you're still getting up to speed on this, don't worry. We'll go over these concepts in more detail throughout Updraft. + +```python +def get_price() -> int256: + price_feed: AggregatorV3Interface = AggregatorV3Interface(0x6944A41769357215DE4FAC081bf1f309aDb) + return staticcall(price_feed.latestAnswer()) +``` + +This code shows how we are getting the latest ETH price from the chainlink price feed. We call the `latestAnswer` function of the price feed, which returns an integer. From 7e56b26231988ae8ea63c6e6432c5231730eac91 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:26:48 -0700 Subject: [PATCH 583/797] Equious updated courses/vyper-101/2-remix-coffee/15-ai/+page.md. --- .../vyper-101/2-remix-coffee/15-ai/+page.md | 77 ++++++++++++++++++- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/15-ai/+page.md b/courses/vyper-101/2-remix-coffee/15-ai/+page.md index b9e433f65..8211f1c30 100644 --- a/courses/vyper-101/2-remix-coffee/15-ai/+page.md +++ b/courses/vyper-101/2-remix-coffee/15-ai/+page.md @@ -1,3 +1,74 @@ ---- - title: Ai - --- \ No newline at end of file +## AI Prompting for Smart Contracts + +AI can be extremely helpful when dealing with smart contract code, and we'll be looking at how it can be used in this lesson. + +The first thing we can do is use an AI to help explain what we are looking at, particularly if we're confused. Let's look at an example: + +```python +@external +@view +def get_price() -> int256: + price_feed: AggregatorV3Interface = AggregatorV3Interface(0x69444A1769357215DEA6AC081bf1f130939a0dC25306) + # ABI + # Address + return staticcall(price_feed.latestAnswer(), []) +``` + +If we're unsure about what the `staticcall` keyword is doing, we can copy that line of code and paste it into the AI of our choice. For this example we'll be using Claude. We'll add some context around the code and ask our AI to explain it to us. + +Here's an example of what we might ask Claude: + +```` +Hi, I have this function: + +```python +@external +@view +def get_price() -> int256: + price_feed: AggregatorV3Interface = AggregatorV3Interface(0x69444A1769357215DEA6AC081bf1f130939a0dC25306) + # ABI + # Address + return staticcall(price_feed.latestAnswer(), []) +```` + +This is in my Vyper smart contract. I don't understand what the `staticcall` keyword is doing. Can you help explain it to me? + +```` + +Claude will then give us an explanation of what the keyword does, which can help us to better understand this part of our smart contract. + +We can also ask Claude to write some code for us, so we can avoid having to type it all ourselves, and this can be especially helpful when we are working with more complex code. If we have a smart contract that is already written and we're looking at how it's currently being used, we can ask Claude to write a new function that takes that code, restructures it, and makes it safe for our use. + +For example, if we have the following function: + +```python +@external +def set_price(price: int256): + price_feed: AggregatorV3Interface = AggregatorV3Interface(0x69444A1769357215DEA6AC081bf1f130939a0dC25306) + # ABI + # Address + price_feed.setLatestAnswer(price) +```` + +We can copy this function, paste it into Claude and ask: + +```` +Hi Claude, this function: + +```python +@external +def set_price(price: int256): + price_feed: AggregatorV3Interface = AggregatorV3Interface(0x69444A1769357215DEA6AC081bf1f130939a0dC25306) + # ABI + # Address + price_feed.setLatestAnswer(price) +```` + +This is in my Vyper smart contract. I would like to make it so that this function can be called by a `staticcall`. Can you help me write a new function that does that? + +``` + +Claude will then write a new function that takes the existing code, restructures it, and uses the `staticcall` keyword so that it is safe for our use. + +As we progress through this course, we will be learning a lot about smart contracts, but often the hardest part is knowing when to ask for help. We'll be doing everything in our power to avoid that! +``` From 9eacf67f8acbd8d4a06c908b67fcd75b793d1a8a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:27:40 -0700 Subject: [PATCH 584/797] Equious updated courses/vyper-101/2-remix-coffee/16-deploy-parameter/+page.md. --- .../16-deploy-parameter/+page.md | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/16-deploy-parameter/+page.md b/courses/vyper-101/2-remix-coffee/16-deploy-parameter/+page.md index 26d4517bd..1b995a7c9 100644 --- a/courses/vyper-101/2-remix-coffee/16-deploy-parameter/+page.md +++ b/courses/vyper-101/2-remix-coffee/16-deploy-parameter/+page.md @@ -1,3 +1,40 @@ ---- - title: Deploy Parameter - --- \ No newline at end of file +## Deployment Parameterization + +We're back to our code base. We now have this `get_price` function which we are actually going to comment out. Again, I'm using command forward slash as a keyboard shortcut for this because we are not actually going to use this. + +But what we are going to do is we're going to create this `get_eth_to_usd_rate` function. + +We just learned how to get the price from a chain price feed. This is really exciting. We're only going to use this one price feed in this entire contract. + +We are going to make the price feed a state variable, up at the top. + +Since our structs are the same as in the last lesson, the `AggregatorV3Interface` is a new type. We can create a variable, a state variable, or a storage variable, called `price_feed` of type `AggregatorV3Interface`. + +In our deploy function we can say `self.price_feed = AggregatorV3Interface()` at address. We are hardcoding this address into the contract. + +We can add a comment saying that we are using the Sepolia testnet: + +```python +# Sepolia +``` + +We should instead add the address as a parameter. We can do this with the following code: + +```python +@external +def deploy(price_feed_address: address): + self.minimum_usd = 5 + self.price_feed = AggregatorV3Interface(price_feed_address) +``` + +The deploy function now has an input for the price feed address. + +Now that we have our `price_feed` object, we can scroll down to our `get_eth_to_usd_rate` function. We will make the price variable equal to `staticcall self.price_feed.latestAnswer()`. + +```python +@internal +def get_eth_to_usd_rate(): + price: int256 = staticcall(self.price_feed.latestAnswer()) +``` + +This way, right when we deploy our contract, we can parameterize the address that we want to use. This is a much cleverer way than hard coding it in. From 5fd72633db244eb35bc9faf6d783913c347d8253 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:28:04 -0700 Subject: [PATCH 585/797] Equious updated courses/vyper-101/2-remix-coffee/17-integer-precision/+page.md. --- .../17-integer-precision/+page.md | 110 +++++++++++++++++- 1 file changed, 107 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/17-integer-precision/+page.md b/courses/vyper-101/2-remix-coffee/17-integer-precision/+page.md index 9e85fbc71..4b9129ca8 100644 --- a/courses/vyper-101/2-remix-coffee/17-integer-precision/+page.md +++ b/courses/vyper-101/2-remix-coffee/17-integer-precision/+page.md @@ -1,3 +1,107 @@ ---- - title: Integer Precision - --- \ No newline at end of file +## Integer Precision + +We're going to work on integer precision. We'll be getting the price of Ethereum using a Chainlink price feed, which returns a price with eight decimals. + +Here we're creating a function called `get_eth_to_usd_rate` which returns the price. + +```python +def get_eth_to_usd_rate(): + price: int256 = staticcall(self.price_feed.latestAnswer(), []) +``` + +We'll use the `decimals` function to get the number of decimal places in the price. + +```python + # 8 decimals +``` + +This function returns a price in USD, which is 3,021. + +```python + # $3,021 +``` + +We need to calculate the ETH amount in USD. + +```python + eth_amount_in_usd +``` + +The price that we're going to get from Chainlink is going to be a number like this: + +```python + price: int256 = staticcall(self.price_feed.latestAnswer(), []) # 33655100000 +``` + +We need to convert this to the ETH amount in USD. + +```python + eth_amount_in_usd +``` + +The function that we'll use is called `get_eth_to_usd_rate`, and we'll pass in the ETH amount. + +```python +def get_eth_to_usd_rate(eth_amount: uint256): +``` + +Let's say Chris sent us 0.01 ETH to buy a coffee. + +```python + Chris sent us 0.01 ETH for us to buy a coffee. +``` + +Is that more or less than $5? + +```python + Chris sent us 0.01 ETH for us to buy a coffee. + Is that more or less than $5? +``` + +Our minimum USD is $5. + +```python +minimum_usd: uint256 +``` + +So how do we convert this 0.01 to its dollar amount? + +```python + price: int256 = staticcall(self.price_feed.latestAnswer(), []) # 33655100000 +``` + +We get the price, which will be something like this. + +```python + price: int256 = staticcall(self.price_feed.latestAnswer(), []) # 33655100000 +``` + +Now, our ETH amount is going to have how many decimal places? + +```python + price: int256 = staticcall(self.price_feed.latestAnswer(), []) # 33655100000 +``` + +This is where the math in the blockchain gets a little bit tricky. + +Remember before, in Ethereum, there's ether, there's Gwei, and there's Wei. One ether has this many Wei. + +So it's got 18 zeros, or 18 decimal places. However, we found from looking at this, and then actually there's also a decimals function, which has eight here. This answer only has eight decimal places. It has eight additional zeros, although some of the zeros are actual numbers. So it has eight decimal places. + +So we first going to need to update this price from having eight decimals to 18. That's actually really easy. All we have to do is say ETH price, + +```python + eth_price: uint256 = +``` + +of type uint256 equals price times 10 raised to the 10th. + +```python + eth_price: uint256 = price * 10**10 +``` + +This is how we add those decimal places. + +```python + eth_price: uint256 = price * 10**10 +``` From a60c20b23dc0263073314dc020dd34f1e7189e66 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:28:30 -0700 Subject: [PATCH 586/797] Equious updated courses/vyper-101/2-remix-coffee/18-converting-types/+page.md. --- .../18-converting-types/+page.md | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/18-converting-types/+page.md b/courses/vyper-101/2-remix-coffee/18-converting-types/+page.md index 7e8858a8c..0536f7b88 100644 --- a/courses/vyper-101/2-remix-coffee/18-converting-types/+page.md +++ b/courses/vyper-101/2-remix-coffee/18-converting-types/+page.md @@ -1,3 +1,30 @@ ---- - title: Converting Types - --- \ No newline at end of file +## Converting Types in Vyper + +We will learn about type conversions in Vyper. We'll start with an example of a scenario where we might need to perform a type conversion: + +```python +@external +def get_eth_to_usd_rate(eth_amount: uint256): + # Chris sent us 0.01 ETH for us to buy a coffee. + # Is that more or less than $5? + price: int256 = staticcall(self.price_feed, "latestAnswer()", [336551000000]) + # 8 decimals + # $3,021 + eth_amount_in_usd = price * (10 ** 10) +``` + +This code shows an error: + +```bash +TypeError: TypeMismatchGiven reference has type int256, expected uint256 +``` + +This error indicates that the variable `eth_amount` has a type `int256`, but the variable `price` is expecting `uint256`. + +We can address this by performing a type conversion on the `price` variable. Vyper provides a built-in function called `convert`, which we can use to convert a variable or literal from one type to another. + +```python +eth_amount_in_usd = convert(price, uint256) * (10 ** 10) +``` + +This line converts the `price` variable, which is `int256`, to `uint256`, and then multiplies by `10**10`. We can compile this code and it should execute as expected. From 56bb0ce03ee2b3de2c0a6d7922d5c8e10d8dd620 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:28:56 -0700 Subject: [PATCH 587/797] Equious updated courses/vyper-101/2-remix-coffee/19-integer-division/+page.md. --- .../19-integer-division/+page.md | 103 +++++++++++++++++- 1 file changed, 100 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/19-integer-division/+page.md b/courses/vyper-101/2-remix-coffee/19-integer-division/+page.md index 8bc547921..7f0505d68 100644 --- a/courses/vyper-101/2-remix-coffee/19-integer-division/+page.md +++ b/courses/vyper-101/2-remix-coffee/19-integer-division/+page.md @@ -1,3 +1,100 @@ ---- - title: Integer Division - --- \ No newline at end of file +## Integer Division in Vyper + +We're going to make a smart contract to buy us a coffee. Our price is going to be a uint256. + +```python +price: int256 = staticcall self.price_feed.latestAnswer() +``` + +Let's say the price is $3.021. + +```python +# 8 decimals +# $3,021 +``` + +We can then multiply this price times 10 ^ 10 to get it into units of ETH. + +```python +eth_price: uint256 = convert(price, uint256) * (10 ** 10) +``` + +Now we've multiplied this price by 10 ^ 10, so we need to add zeros. + +```python +# ETH : 110000000000000000000 +``` + +We can then get a USD value of ETH. + +```python +eth_amount_in_usd: uint256 = (eth_amount * eth_price) // 1 * (10 ** 18) +``` + +Let's break down this equation to understand what's going on. First, we have the eth_amount, which is the amount of ETH. This is multiplied by eth_price, which is in dollars per ETH. We are going to add zeros to this. + +```python +# $ / ETH : 336551000000000000000 +``` + +To do this, we divide by 10 ^ 18. + +```python +// 1 * (10 ** 18) +``` + +We're going to create a new function called divide_me which will take a uint256 number as input and return a uint256. + +```python +def divide_me(number: uint256) -> uint256: +``` + +We'll return this value. + +```python +return number // 3 +``` + +We can see that this works by trying a few examples. + +```python +# 4 / 2 = 2 +# 6 / 3 = 2 +# 7 / 3 +``` + +Let's compile this and deploy it. + +```bash +Compile buy_me_a_cofee.vy +``` + +We'll grab any address, like our price feed address. We'll scroll down and put in one for divide_me. What do you think we'll get if we do 1 / 3? + +```bash +Deploy +``` + +We get 0. What about 2? Still 0. How about 3? We get 1. Four? One. Five? One. Six? Two. So, integer division is basically cutting off any decimal places. Let's try 7 / 3. + +```bash +Transact +``` + +It's still 2. What if we do 7 / 3 on our calculator? It's 2.33333333. This is because we can't have decimals in our smart contracts. We need to be very precise when working with smart contracts. That's a crucial piece of knowledge to keep in mind when designing mathematically complex applications. We're also going to comment out the math examples we used, but we'll leave them in the Git repo associated with this course. We also have a function called get_eth_to_usd_rate. + +```python +def get_eth_to_usd_rate(eth_amount: uint256) -> uint256: +``` + +We can now go back up and convert msg.value, the amount of ETH that they sent, to its dollar equivalent. + +```python +usd_value_of_eth: uint256 = self.get_eth_to_usd_rate(msg.value) +``` + +So, instead of saying that msg.value must be greater than 1 ether, which would mean coffee cost $3,000, we'll say that the USD value of ETH must be greater than or equal to self.minimum_usd. + +```python +assert usd_value_of_eth >= self.minimum_usd, "You must spend more ETH!" +``` From 9a69458279be08e7f74337a2a54ca0e242272998 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:30:33 -0700 Subject: [PATCH 588/797] Equious updated courses/vyper-101/2-remix-coffee/2-setup/+page.md. --- .../vyper-101/2-remix-coffee/2-setup/+page.md | 103 +++++++++++++++++- 1 file changed, 100 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/2-setup/+page.md b/courses/vyper-101/2-remix-coffee/2-setup/+page.md index fcc7a149d..53044a9ad 100644 --- a/courses/vyper-101/2-remix-coffee/2-setup/+page.md +++ b/courses/vyper-101/2-remix-coffee/2-setup/+page.md @@ -1,3 +1,100 @@ ---- - title: Setup - --- \ No newline at end of file +We're going to start by deleting everything in our Remix here. You're probably a little bit familiar with Remix at this point, which is great. So, we're going to go ahead and delete everything in my Remix here. And, I'm going to create again this hi.sol contract here. Oh, it came back. Sorry about that. And, I'm going to create this hi.sol contract because, again, Remix assumes you're going to be working with Solidity and is always looking for Solidity. So, we have to at least make a Solidity file. + +```python +pragma solidity ^0.8.18; + +contract hi { + +} +``` + +So, we're going to go ahead and we'll go to the Solidity compiler. We'll compile hi.sol so that we don't have to worry about this in the future. And then, we'll also do SPDX license identifier MIT. + +```python +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +contract hi { + +} +``` + +Again, don't need to worry about the Solidity stuff for now, just know that as of recording, Remix has this bug where it needs to see a Solidity file in order for it to deploy anything. But, so let's go back to our File Explorer here. And let's create a new file called buy me a coffee. + +Now, right on the naming convention here, you see we're using underscores for spaces between the names here. This is known as snake case. And, there's a bit of a disagreement in the Vyper community as of recording, if this is better, or something called camel case is better, which looks like this. Where it's like every start of a new word just has a capitalized letter at the beginning. Python by nature is typically what's called snake case with these underscores like this. But, I want to point out that for the names of files, you might see it both ways. In the Python, in the Vyper code itself, we'll definitely be using snake case with the underscores. But, for the names of file it might go either way. Now, before we actually begin coding anything, let's write down what we want to do here. It's usually a good idea to write down what you want your code base to do before you even get started coding so that you have a design spec of what it should be doing. And, this is a really good step for anybody who is building smart contracts or building any type of code. So, what do we want this to do? Well, we want this application to do three things: allow us to get funds from users so that people can buy us coffee. We want to be able to withdraw those funds so that we can actually go off and buy the coffee. And then finally, set a minimum funding value in USD. + +Now, originally, I said $50, we might make it five. We might make it two because now that I'm thinking about it, $50 coffee is ridiculous. But, you know, you can set your coffee price to whatever you want it to be. So, let's go ahead and let's get started here, of course, with pragma version 0.4.0. And, we'll say @license MIT. + +```python +# Get funds from users +# Withdraw funds +# Set a minimum funding value in USD + +pragma version 0.4.0 +@license: MIT +``` + +And then if you want, you can also do @author and put your name here. + +```python +# Get funds from users +# Withdraw funds +# Set a minimum funding value in USD + +pragma version 0.4.0 +@license: MIT +@author: You! +``` + +There's a couple other different types of tags that you'll see people use pretty often. And, pretty soon we'll actually learn a nicer way to format this than with these hashtags here, but we'll get to that in a bit. + +Now, let's actually build a little bit of a skeleton for our smart contract here. Let's just build the names of the functions that we want this to have. So, we probably want a def fund some type of fund function here. + +```python +# Get funds from users +# Withdraw funds +# Set a minimum funding value in USD + +pragma version 0.4.0 +@license: MIT +@author: You! + +def fund(): +``` + +And what you can do that's quite nice in Vyper is that if you want to just name a function but not have it do anything quite yet, you can just type this pass in the function definition. + +```python +# Get funds from users +# Withdraw funds +# Set a minimum funding value in USD + +pragma version 0.4.0 +@license: MIT +@author: You! + +def fund(): + pass +``` + +So, this contract right here, even though it doesn't really do anything, is actually valid Vyper. So, I can even go ahead and compile this. And, you'll see that it compiles successfully. + +So, this pass keyword is valid Vyper here. So, we want def fund. What else? We probably want def withdraw. We want to be able to withdraw the money that is funded to us. And, that's pretty much it. Now, these two functions are going to be the main functionality of the contract. However, we are obviously going to be adding other functions in here as well because, well, in order to fund and withdraw, we probably need some other functionality, including getting price and etc. So, this fund function, we want anybody outside of this contract to be able to call. So, let's give it a visibility of @external. So now, anybody can call this. Same thing, we want humans to actually be able to call withdraw. So, we'll do @external. We probably only want us to call this, but we'll fix that in a bit. + +```python +# Get funds from users +# Withdraw funds +# Set a minimum funding value in USD + +pragma version 0.4.0 +@license: MIT +@author: You! + +@external +def fund(): + pass + +@external +def withdraw(): + pass +``` From ed3e5acb2304cd101b42cf6c0db30bd90bbd9592 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:30:59 -0700 Subject: [PATCH 589/797] Equious updated courses/vyper-101/2-remix-coffee/20-as-wei-value/+page.md. --- .../2-remix-coffee/20-as-wei-value/+page.md | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/20-as-wei-value/+page.md b/courses/vyper-101/2-remix-coffee/20-as-wei-value/+page.md index f08ba5668..3455a8ef8 100644 --- a/courses/vyper-101/2-remix-coffee/20-as-wei-value/+page.md +++ b/courses/vyper-101/2-remix-coffee/20-as-wei-value/+page.md @@ -1,3 +1,43 @@ ---- - title: As Wei Value - --- \ No newline at end of file +## As Wei Value + +In this lesson, we're going to look at the `as_wei_value()` function within solidity. + +Let's say we have a smart contract that requires a minimum USD value to be sent to it. In this case, that minimum amount is 5 USD. + +```python +self.minimum_usd = 5 +``` + +However, this can be an issue because we're working in Ethereum, and the units of value are in Ether. + +```python +usd_value_of_eth: uint256 = self.get_eth_to_usd_rate(msg.value) +assert usd_value_of_eth >= self.minimum_usd, "You must spend more ETH!" +``` + +Remember, ETH has 18 decimal places. So, a value of 5 USD will not be represented as 5 in this context. Instead, we'll need to convert the value of 5 USD into Ether (WEI). + +```python +self.minimum_usd = 5 * (10 ** 18) +``` + +We can also do this: + +```python +self.minimum_usd = 5000000000000000000 +``` + +However, this is not a readable way to present the code. Instead, we can use the function `as_wei_value()` to make the code much more legible. + +```python +self.minimum_usd = as_wei_value(5, "ether") +``` + +We can now use this new minimum USD value (in WEI) for our assertions: + +```python +assert usd_value_of_eth >= self.minimum_usd, "You must spend more ETH!" +``` + +This `as_wei_value()` function is a great shortcut for adding those 18 decimal places. +courses\vyper-101\2-remix-coffee\20-as-wei-value\+page.md From 9bf5900246c189eb73a24b0bb65bda058e4f1a2b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:31:24 -0700 Subject: [PATCH 590/797] Equious updated courses/vyper-101/2-remix-coffee/21-send-eth-in-tx/+page.md. --- .../2-remix-coffee/21-send-eth-in-tx/+page.md | 57 ++++++++++++++++++- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/21-send-eth-in-tx/+page.md b/courses/vyper-101/2-remix-coffee/21-send-eth-in-tx/+page.md index 979795eac..061899398 100644 --- a/courses/vyper-101/2-remix-coffee/21-send-eth-in-tx/+page.md +++ b/courses/vyper-101/2-remix-coffee/21-send-eth-in-tx/+page.md @@ -1,3 +1,54 @@ ---- - title: Send Eth In Tx - --- \ No newline at end of file +In this lesson, we'll learn how to send a transaction using ETH. We can then use a deployed contract to show how to call another function. + +Let's begin by going over how to compile, deploy and run transactions. + +We'll need to compile our contract. We can then deploy it to our fake chain. + +```python +# Get funds from users +# Withdraw funds +# Set a minimum funding value in USD +# pragma version 0.4.8 +# license: MIT +# author: You! +# We'll learn a new way to do interfaces later... +interface AggregatorV3Interface: + def decimals() -> uint8: view + def description() -> String: view + def version() -> uint256: view + def latestAnswer() -> int256: view +minimum_usd: uint256 +price_feed: AggregatorV3Interface = AggregatorV3Interface(0x69444179935776935DE41F4AC081f1FD3C909Dc256) # sepolia +# ... +def __init__(price_feed: address): + self.minimum_usd = as_wei_value(5, "ether") + self.price_feed = AggregatorV3Interface(price_feed) +# ... +# Allows users to send $ to this contract +def fund(): + # Have a minimum $ amount to send + # How do we convert the ETH amount to get dollars amount? + usd_value_of_eth: uint256 = self.get_eth_to_usd_rate(msg.value) + assert usd_value_of_eth >= self.minimum_usd, "You must spend more ETH!" +# ... +def get_eth_to_usd_rate(amount: uint256) -> uint256: + # ... + eth_price: uint256 = staticcall(self.price_feed, latestAnswer()) + # ... + eth_amount_in_usd: uint256 = (eth_price * eth_amount / 10 ** 18 + 18 ** 18 * 1) / 10 ** 18 + return eth_amount_in_usd # in $ 's, 18 decimal places +# ... +# remove all decimals +def divide_number(me: uint256) -> uint256: + # ... +``` + +After deploying our contract we can use a calculator to determine the amount of ETH that should be sent to the `fund` function. The `fund` function requires at least 5 dollars worth of ETH. + +We will need to use a website like `eth-converter.com` to calculate the amount of ETH required. + +We'll then paste this amount in Remix and send the transaction to our contract. + +We can now call the `fund` function from Remix to test our logic. This will send our calculated amount of ETH to the contract and trigger the `fund` function. + +The contract balance will then be updated to show the new balance after the transaction has been processed. From 9396b6098580e64508d482d0f1cb433fcedce51b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:32:14 -0700 Subject: [PATCH 591/797] Equious updated courses/vyper-101/2-remix-coffee/22-contract-to-contract/+page.md. --- .../22-contract-to-contract/+page.md | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/22-contract-to-contract/+page.md b/courses/vyper-101/2-remix-coffee/22-contract-to-contract/+page.md index f6e4e2888..cdfca2c8f 100644 --- a/courses/vyper-101/2-remix-coffee/22-contract-to-contract/+page.md +++ b/courses/vyper-101/2-remix-coffee/22-contract-to-contract/+page.md @@ -1,3 +1,34 @@ ---- - title: Contract To Contract - --- \ No newline at end of file +## Making a function call another function + +In this lesson, we'll learn about making a function call another function in Vyper. + +We'll use an example of a function that takes an amount of ETH in Wei and converts it to USD. + +First, we create a function to do the calculation. + +```python +def get_eth_to_usd_rate(eth_amount: uint256) -> uint256: + """ + Chris sent us 0.01 ETH for us to buy a coffee: + Is that more or less than $5? + """ + eth_price: uint256 = staticcall(self.price_feed, latestAnswer()) * (10 ** 10) + price_in_usd: uint256 = (convert(uint256, price) * eth_amount) // (1 * 10 ** 18) + eth_amount_in_usd_uint256: uint256 = price_in_usd * eth_amount // (1 * 10 ** 18) + return eth_amount_in_usd_uint256 # 18 0's, 18 decimal places +``` + +We can create an external function that runs our internal function. + +```python +@external +@view +def get_eth_to_usd_rate(eth_amount: uint256) -> uint256: + return self._get_eth_to_usd_rate(eth_amount) +``` + +We'll say ETH amount uint256 returns a uint256. All we got to do is say return self.\_get_eth_to_usd_rate(eth_amount). + +This creates an external function `get_eth_to_usd_rate` that calls the internal function `_get_eth_to_usd_rate` passing the `eth_amount` as an argument. + +This is a useful technique when you need to expose an internal function. It allows you to keep internal functions private while still providing an external interface to access their functionality. From c6b95eaa7dc97599c1a106a075e67856269c72ee Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:32:44 -0700 Subject: [PATCH 592/797] Equious updated courses/vyper-101/2-remix-coffee/23-getting-revert/+page.md. --- .../2-remix-coffee/23-getting-revert/+page.md | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/23-getting-revert/+page.md b/courses/vyper-101/2-remix-coffee/23-getting-revert/+page.md index 8dc8d171f..eb63086a1 100644 --- a/courses/vyper-101/2-remix-coffee/23-getting-revert/+page.md +++ b/courses/vyper-101/2-remix-coffee/23-getting-revert/+page.md @@ -1,3 +1,35 @@ ---- - title: Getting Revert - --- \ No newline at end of file +## Getting a Revert + +In this lesson, we are going to learn how to get a revert. We'll test out this revert to ensure that our code is working as intended. We'll use a fake blockchain network, Remix, and a smart contract for this example. + +### Testing our Revert + +We are going to use the smart contract we created in previous lessons to test our revert. We'll first deploy the contract to our fake blockchain network. + +Let's test our smart contract! We need to check if the revert function is working correctly. We need to see what happens when people don't send enough money to the contract. + +#### Making a Transaction + +We can use a website like eth-converter.com to determine how much Wei we need to send to the contract in order to meet the required minimum value. Let's use 2000000000000000 Wei, which is $6.53. + +Now let's copy this Wei value and paste it into the `get_eth_to_usd_rate` function in Remix. + +We'll now go ahead and click on the `fund` button on the Remix interface. + +#### The Revert + +You will notice that we are getting an error: `Gas estimation failed`, `Transaction execution will likely fail`. Let's go ahead and click on the `Send Transaction` button. + +Now that the transaction has been sent, we can go ahead and use the drop-down menu to view the transaction details. We can see that the transaction has been `mined` but that the `execution failed`. + +This error happens because we are not sending at least 5 USD to the contract. The `assert` function was designed to stop the execution of the transaction if the user is not meeting the minimum value. This is called a `revert`. + +Our `assert` function is working exactly as it should! + +```python +assert usd_value_of_eth >= self.minimum_usd, "You must spend more ETH!" +``` + +As we can see in the code, the `assert` function is used to ensure that the user is sending at least 5 USD. If the user doesn't meet this requirement, then the `revert` message is triggered. + +We've now demonstrated what a `revert` looks like in practice. We'll learn more about reverts and how to handle them in future lessons. From ef9109abb001103affbb0f5d267061fd69e3c1c6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:33:32 -0700 Subject: [PATCH 593/797] Equious updated courses/vyper-101/2-remix-coffee/24-msg-sender/+page.md. --- .../2-remix-coffee/24-msg-sender/+page.md | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/24-msg-sender/+page.md b/courses/vyper-101/2-remix-coffee/24-msg-sender/+page.md index d00f579be..2323a0727 100644 --- a/courses/vyper-101/2-remix-coffee/24-msg-sender/+page.md +++ b/courses/vyper-101/2-remix-coffee/24-msg-sender/+page.md @@ -1,3 +1,51 @@ ---- - title: Msg Sender - --- \ No newline at end of file +## msg.sender, owner and access control + +We're building a smart contract where we want to make sure only we can pull the money out of the contract. We do this by using the msg.sender, which is the account that's sending the message. We can use this to make sure that only the owner of the contract can withdraw the money. + +We first set the owner in the deploy function: + +```python +owner: address +``` + +```python +def __init__(price_feed: address): + self.minimum_usd = as_wei_value(5, "ether") + self.price_feed = AggregatorV3Interface(price_feed) + self.owner = msg.sender +``` + +We use the `msg.sender` built-in variable to set the owner of the contract to the account that's deploying it. + +Then, in the withdraw function, we use the `assert` statement to make sure that the msg.sender is equal to the owner. + +```python +external +def withdraw(): + """Take the money out of the contract, that people sent via the fund function. + How do we make sure only we can pull the money out? + """ + assert msg.sender == self.owner, "Not the contract owner!" +``` + +If the msg.sender is not the owner, the transaction will revert. This makes sure that only the owner of the contract can withdraw the money. + +To make sure the owner is public we add `public` in front of the declaration. + +```python +owner: public(address) +``` + +We can see this in action if we redeploy the contract and call the withdraw function. + +If we call the withdraw function from the owner account, it will be successful. However, if we call the withdraw function from a different account, it will revert with the error message "Not the contract owner!". + +This is an example of how we can use the msg.sender to control access to our smart contract functions. It's a simple but powerful technique that can be used to secure our code. + +```bash +truffle compile +``` + +```bash +truffle migrate +``` From 114501023584b5c4752c4a7700ae723f67f500d2 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:34:01 -0700 Subject: [PATCH 594/797] Equious updated courses/vyper-101/2-remix-coffee/25-withdraw-eth/+page.md. --- .../2-remix-coffee/25-withdraw-eth/+page.md | 75 ++++++++++++++++++- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/25-withdraw-eth/+page.md b/courses/vyper-101/2-remix-coffee/25-withdraw-eth/+page.md index adffc9a9e..175e1b1bb 100644 --- a/courses/vyper-101/2-remix-coffee/25-withdraw-eth/+page.md +++ b/courses/vyper-101/2-remix-coffee/25-withdraw-eth/+page.md @@ -1,3 +1,72 @@ ---- - title: Withdraw Eth - --- \ No newline at end of file +## Sending ETH From a Contract + +In this lesson, we'll learn how to send ETH from a smart contract to a designated address, using the `send` function. Later, we'll look at another built-in function called `raw_call` and how to implement that function. + +We'll start by creating a `withdraw` function that will send the ETH to the owner of the smart contract. + +```python +@external +def withdraw(): + """Take the money out of the contract, that people sent via the fund function. + How do we make sure only we can pull the money out? + """ + assert msg.sender == self.owner, "Not the contract owner!" + + send(self.owner, self.balance) +``` + +In our function, we can see that we are using the `send` function and giving it two arguments: the recipient's address (`self.owner`) and the value that we want to send (`self.balance`). + +Our smart contract has a balance of ETH that we'll use to send to the owner. We'll start by funding our contract, using the `fund` function. + +```python +@external +@payable +def fund(): + """Allows users to send $ to this contract + Have a minimum $ amount to send + """ + usd_value_of_eth: uint256 = self.get_eth_to_usd_rate(msg.value) + assert usd_value_of_eth >= self.minimum_usd, "You must spend more ETH!" +``` + +We can see that our `fund` function takes an amount in ETH and converts it to USD for comparison. + +Now, we'll deploy the contract. We'll use the injected provider and set the value in wei. Then, we'll confirm the deployment. + +```bash +vyper --version +vyper --optimize-for-size --optimize-for-speed --deploy +``` + +Now, we can call the `fund` function and provide a value in wei to fund our contract. + +```bash +fund(1000000000000000) +``` + +We'll confirm the transaction. It will take a few seconds for the balance to update, but we'll confirm that it worked. + +Now, let's go ahead and call the `withdraw` function. We'll confirm the transaction, and then we'll check our balance to make sure that the ETH was successfully transferred. + +```bash +withdraw() +``` + +Now, we'll check that the balance has gone back to zero in our deployed contract. + +We can see that our balance has gone back to zero. + +Now, if we want to fund with more than just wei, we can use the `ether` option in the value field and fund our contract with one ETH. + +```bash +fund(1 ether) +``` + +We'll confirm the transaction, and we'll check that the balance has gone up to 998. + +Let's go back to our contract and call the `withdraw` function. Confirm the transaction, and then check the balance in Metamask to make sure it went up to 998. + +We can see that we successfully funded our contract with 1 ETH. + +That's how we can send ETH from a contract! In the next lesson, we'll learn how to use the `raw_call` function. \ No newline at end of file From 811c7e4dfcdeccf904b6cffcf73b616fa58fee1d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:34:46 -0700 Subject: [PATCH 595/797] Equious updated courses/vyper-101/2-remix-coffee/26-dynamic-vs-fixed-array/+page.md. --- .../26-dynamic-vs-fixed-array/+page.md | 122 +++++++++++++++++- 1 file changed, 119 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/26-dynamic-vs-fixed-array/+page.md b/courses/vyper-101/2-remix-coffee/26-dynamic-vs-fixed-array/+page.md index 88419ab64..f3e3153ea 100644 --- a/courses/vyper-101/2-remix-coffee/26-dynamic-vs-fixed-array/+page.md +++ b/courses/vyper-101/2-remix-coffee/26-dynamic-vs-fixed-array/+page.md @@ -1,3 +1,119 @@ ---- - title: Dynamic Vs Fixed Array - --- \ No newline at end of file +## Dynamic vs. Fixed Arrays in Vyper + +We're going to create a new Vyper contract to demonstrate the differences between a **dynamic array** and a **fixed-size array.** + +### Dynamic Array + +First, let's declare a dynamic array: + +```vyper +dynamic_array: public DynArray[uint256, 100] +``` + +The array type is `DynArray` and has a maximum size of 100. We set this array to be `public` so that it's viewable from outside the contract. + +### Fixed-Size Array + +Now, let's create a fixed-size array: + +```vyper +fixed_sized_array: public uint256[100] +``` + +The fixed-size array is simply a list of 100 `uint256` values. Note that we can't set the size of the array to be dynamic like we did with the `DynArray.` + +### `len` Keyword + +We can use the `len` keyword to determine the length of a dynamic array. Let's create a function called `dyn_array_size` that returns the length of our dynamic array: + +```vyper +@external +@view +def dyn_array_size() -> uint256: + return len(self.dynamic_array) +``` + +### Adding Elements to Arrays + +We can add elements to our arrays with the `append` function. Let's create a function called `add_to_array` that adds an element to both arrays: + +```vyper +@external +def add_to_array(): + self.fixed_sized_array[self.index] = 1 + self.dynamic_array.append(1) + self.index = self.index + 1 +``` + +We also need to declare an index variable: + +```vyper +index: uint256 +``` + +### Dynamic Array Length + +We can see that the dynamic array length is initially 0 because it's initialized as an empty array: + +```vyper +#[ ] +``` + +However, after we append an element, the length increases to 1: + +```vyper +#[1] +``` + +We can append as many elements to the dynamic array as long as the maximum size of 100 is not exceeded. + +### Fixed Array Length + +Now, let's try to append an element to our fixed array. We'll create a function called `fixed_array_size` that returns the size of the fixed array: + +```vyper +@external +@view +def fixed_array_size() -> uint256: + return len(self.fixed_sized_array) +``` + +We can compile this code: + +```bash +vyper arrays_compared.vy +``` + +We can now deploy the contract. Let's run the `add_to_array` function to add an element to our dynamic array: + +The dynamic array length now reflects the change to 1. + +```vyper +#[1] +``` + +Now, let's try to run the `add_to_array` function again. + +We can see that the dynamic array length is now 2. + +```vyper +#[1,1] +``` + +However, the fixed array length is still 1. + +### Fixed Array Limitations + +We can try to append to the fixed array: + +```vyper +self.fixed_sized_array.append(1) +``` + +But we'll get an error! + +We cannot append to fixed-size arrays because the length is determined at the time the array is declared. However, we can modify existing elements. + +### Conclusion + +The difference between dynamic and fixed-size arrays is whether they can change in size during runtime. Fixed-size arrays are more efficient than dynamic arrays, but we lose flexibility. Dynamic arrays allow for flexibility but can be less efficient. From 9ff9a4f1050fc7f5d419d2626159e0249a8419da Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:35:31 -0700 Subject: [PATCH 596/797] Equious updated courses/vyper-101/2-remix-coffee/27-resetting-array/+page.md. --- .../27-resetting-array/+page.md | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/27-resetting-array/+page.md b/courses/vyper-101/2-remix-coffee/27-resetting-array/+page.md index e7f9f5fbf..72dc92cda 100644 --- a/courses/vyper-101/2-remix-coffee/27-resetting-array/+page.md +++ b/courses/vyper-101/2-remix-coffee/27-resetting-array/+page.md @@ -1,3 +1,21 @@ ---- - title: Resetting Array - --- \ No newline at end of file +## Resetting a Dynamic Array + +We are looking to keep track of all the funders in our contract. We can set this up as a fixed-size array, but it is probably going to be better for us to use a dynamic array. Let's make this a public dynamic array of addresses with a max size of, let's say, 1,000. This means there will be a maximum of 1,000 addresses we can have as funders. If we have more funders, our contract will kind of break, but let's just hope that we don't get too many people who want to buy us coffee. + +We'll scroll down to our fund function and we'll keep track of this funder here, whoever funds us. We'll say: + +```python +self.funders.append(msg.sender) +``` + +So, we're going to say, hey, in our funders dynamic array, we'll just append, we'll just add to the list, the message.sender, whoever calls this fund function. + +Great, and then when we call withdraw, we probably want to reset the funders, maybe we don't, but I want to reset the funders every time I call withdraw. We can do this really easily with dynamic arrays which is part of the reason why I'm using a dynamic array. We can just say: + +```python +self.funders = [] +``` + +Boom! That's it. + +This is how you identify an empty array. So self.funders equals this, means it's an empty array, and it is essentially reset. From 114ea3cc73637f07ed50d53f3940e2e3c366484d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:35:57 -0700 Subject: [PATCH 597/797] Equious updated courses/vyper-101/2-remix-coffee/28-plus-equals/+page.md. --- .../2-remix-coffee/28-plus-equals/+page.md | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/28-plus-equals/+page.md b/courses/vyper-101/2-remix-coffee/28-plus-equals/+page.md index 762f63235..acdec5825 100644 --- a/courses/vyper-101/2-remix-coffee/28-plus-equals/+page.md +++ b/courses/vyper-101/2-remix-coffee/28-plus-equals/+page.md @@ -1,3 +1,49 @@ ---- - title: Plus Equals - --- \ No newline at end of file +## Mappings to track funders + +In this lesson, we'll learn how to keep track of who sent funds to our contract, and how much they sent. + +We'll use a mapping. Mappings are a fundamental concept in smart contracts. Think of them as dictionaries in Python or JavaScript. They pair a key with a value. We can make mappings public to allow anyone to read them. + +We'll create a new mapping to keep track of funders and how much they sent. + +```python +# # Keep track of who sent us +# # How much they sent us +``` + +We'll call this new mapping `_funders_to_amount_funded`. + +```python +# funder -> how much they funded +_funders_to_amount_funded: public(HashMap[address, uint256]) +``` + +This mapping will store the address of the funder as a key and the amount they sent as a value. + +In our `fund` function, we'll track the amount each person sent us. + +```python +@payable +def fund(): + """ + Allows users to send $ to this contract + Have a minimum $ amount to send + """ + # ... previous code + self._funders_to_amount_funded[msg.sender] += msg.value + # ... +``` + +Here, we access the hash map with the `msg.sender` address as the key and add the amount sent by the `msg.sender` (`msg.value`) to the value associated with the `msg.sender` in the hash map. We can also use the `+=` operator as a shorthand for adding to a value in a mapping. + +```python +self._funders_to_amount_funded[msg.sender] = self._funders_to_amount_funded[msg.sender] + msg.value +``` + +We can also use the `+=` operator as a shorthand for adding to a value in a mapping. + +```python +self._funders_to_amount_funded[msg.sender] += msg.value +``` + +This is the same as writing the line above. From 5726054a624daa9e963969c6a15dac192f379623 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:36:23 -0700 Subject: [PATCH 598/797] Equious updated courses/vyper-101/2-remix-coffee/29-for-loops/+page.md. --- .../2-remix-coffee/29-for-loops/+page.md | 97 ++++++++++++++++++- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/29-for-loops/+page.md b/courses/vyper-101/2-remix-coffee/29-for-loops/+page.md index 186c15878..c481f628d 100644 --- a/courses/vyper-101/2-remix-coffee/29-for-loops/+page.md +++ b/courses/vyper-101/2-remix-coffee/29-for-loops/+page.md @@ -1,3 +1,94 @@ ---- - title: For Loops - --- \ No newline at end of file +## For Loops + +In this lesson we will explore the `for` loop in Vyper. + +We will first use a for loop to iterate over a range of integers. We can use the `range` function to specify the starting and ending index of the loop. + +```python +@external +@pure +def for_loop() -> DynArray[uint256]: + arr: DynArray[uint256, 10] = [] + + for i: uint256 in range(5): + arr.append(i) + + return arr +``` + +In the above code, we are using a for loop to iterate over the first 5 integers. For each iteration, we append the current integer to the `arr`. Finally, we return the `arr`. + +We can also iterate over a fixed-size list. + +```python +@external +@pure +def for_loop_list() -> DynArray[uint256]: + arr: DynArray[uint256, 10] = [] + nums: uint256[4] = [11, 22, 33, 44] + + for i: uint256 in nums: + arr.append(i) + + return arr +``` + +In this code, we are iterating over the fixed-size list `nums` and appending each element to the `arr`. + +You can also skip iterations using the `continue` keyword. For example: + +```python +@external +@pure +def for_loop_skip() -> DynArray[uint256]: + arr: DynArray[uint256, 10] = [] + nums: uint256[4] = [11, 22, 33, 44] + + for i: uint256 in nums: + if i == 2: + continue + arr.append(i) + + return arr +``` + +In the code above, we are iterating over the list `nums`. If the current element is equal to 2, the `continue` keyword will skip the rest of the code for that iteration and move on to the next iteration. + +You can also break out of a for loop early using the `break` keyword. + +```python +@external +@pure +def for_loop_break() -> DynArray[uint256]: + arr: DynArray[uint256, 10] = [] + nums: uint256[4] = [11, 22, 33, 44] + + for i: uint256 in nums: + if i == 2: + continue + if i == 4: + break + arr.append(i) + + return arr +``` + +In this code, we are iterating over the list `nums`. If the current element is equal to 2, the `continue` keyword will skip the rest of the code for that iteration and move on to the next iteration. If the current element is equal to 4, the `break` keyword will exit the for loop. + +To reset the elements of a hashmap to zero, we can use a for loop. + +```python +for funder: address in self.funders: + self.funder_to_amount_funded[funder] = 0 +``` + +The code above iterates through each address in the `self.funders` list and sets the corresponding value in the `self.funder_to_amount_funded` hashmap to 0. + +We can also iterate through the `self.funders` list using a for each loop. + +```python +for funder: address in self.funders: + self.funder_to_amount_funded[funder] = 0 +``` + +Using a for loop to reset the values in a hashmap will use a lot of gas. You should carefully consider the gas costs and trade-offs of different data structures when designing your smart contracts. From 658838959b0a2305c4eeabdb4a0dd4b84fe489b7 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:37:33 -0700 Subject: [PATCH 599/797] Equious updated courses/vyper-101/2-remix-coffee/3-doc-strings/+page.md. --- .../2-remix-coffee/3-doc-strings/+page.md | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/3-doc-strings/+page.md b/courses/vyper-101/2-remix-coffee/3-doc-strings/+page.md index 328343a0d..eb414ef73 100644 --- a/courses/vyper-101/2-remix-coffee/3-doc-strings/+page.md +++ b/courses/vyper-101/2-remix-coffee/3-doc-strings/+page.md @@ -1,3 +1,31 @@ ---- - title: Doc Strings - --- \ No newline at end of file +We're going to look at what's called a docstring in Vyper. It's a method of adding comments to our code. + +```python +@external +def fund(): + pass +``` + +To create a docstring, we use triple quotes. + +```python +@external +def fund(): + """ + """ + pass +``` + +Similar to how the hashtag works in a regular comment, we can use triple quotes for multi-line comments. The docstring is then ignored by the compiler. + +```python +@external +def fund(): + """ + Allows users to send $ to this contract. + Have a minimum $ amount sent + """ + pass +``` + +Docstrings are a commonly used method of documenting functions in Vyper. From fae311fe5cf8032449ecc6c8fc3c9a9711cea265 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:37:58 -0700 Subject: [PATCH 600/797] Equious updated courses/vyper-101/2-remix-coffee/30-tenderly_/+page.md. --- .../2-remix-coffee/30-tenderly_/+page.md | 108 +++++++++++++++++- 1 file changed, 105 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/30-tenderly_/+page.md b/courses/vyper-101/2-remix-coffee/30-tenderly_/+page.md index 92d2c2d94..b8c69ab05 100644 --- a/courses/vyper-101/2-remix-coffee/30-tenderly_/+page.md +++ b/courses/vyper-101/2-remix-coffee/30-tenderly_/+page.md @@ -1,3 +1,105 @@ ---- - title: Tenderly_ - --- \ No newline at end of file +We are learning to build a smart contract that will allow users to send funds, with the goal of buying a coffee. We will also explore the concept of interfaces, how we can use interfaces to retrieve data and perform actions from our contract, and how to use a price feed. + +We will be building our contract in the Remix IDE. Remix IDE is a great tool for developing smart contracts and interacting with them on the blockchain. It provides a user-friendly interface for writing, compiling, deploying, and testing smart contracts. + +First, we will create a new Remix project and write the following code: + +```python +# Get funds from users +# Withdraw funds +# Set a minimum funding value in USD +pragma version ^0.4.0 +@license: MIT +@author: You! + +# We'll learn a new way to do interfaces later... +interface AggregatorV3Interface: + def decimals() -> uint8: view + def description() -> String[1000]: view + def version() -> uint256: view + def latestAnswer() -> int256: view + +minimum_usd: public uint256 +price_feed: public AggregatorV3Interface # 0x6944A41769357215DE4F4C0881f1f309a0DC325306 sepolia +owner: public address +funders: public DynArray[address, 1000] + +# funder -> how much they funded +funder_to_amount_funded: public HashMap[address, uint256] + +# Keep track of who sent us +# How much they sent us + +@deploy +def __init__(price_feed: address): + self.minimum_usd = as_wei_value(5, "ether") + self.price_feed = AggregatorV3Interface(price_feed) + self.owner = msg.sender + +@external +@payable +def fund(): + """Allows users to send $ to this contract + Have a minimum $ amount to send + How do we convert the ETH amount to dollars amount? + """ + + usd_value_of_eth: uint256 = self.get_eth_to_usd_rate(msg.value) + assert usd_value_of_eth >= self.minimum_usd, "You must spend more ETH!" + self.funders.append(msg.sender) + self.funder_to_amount_funded[msg.sender] += msg.value + +@external +def withdraw(): + """Take the money out of the contract, that people sent via the fund function. + How do we make sure only we can pull the money out? + """ + + assert msg.sender == self.owner, "Not the contract owner!" + send(self.owner, self.balance) + + # resetting + for funder: address in self.funders: + self.funder_to_amount_funded[funder] = 0 + self.funders = [] + +@internal +@view +def get_eth_to_usd_rate(eth_amount: uint256) -> uint256: + """Chris sent us 0.01 ETH for us to buy a coffee + Is that more or less than $5? + """ + + price: int256 = staticcall(self.price_feed, latestAnswer()) + eth_price: uint256 = (convert(price, uint256) * 10**18) / (10**10) + eth_amount_in_usd: uint256 = (eth_price * eth_amount) / (1 * 10**18) + return eth_amount_in_usd * 10**18 # 0's, 18 decimal places + +# 5 000000000000000000 +``` + +After we have written our code, we are ready to compile it. We can do so in Remix by clicking the "Compile" button and selecting the desired compiler version. + +Once we have compiled our code successfully, we can deploy it to the blockchain. We will first need to connect to the blockchain network. In this case, we are connecting to a fake virtual testnet that we have created on Tenderly. You can create a virtual testnet on Tenderly for free. We will be deploying our contract to this virtual testnet. Once you are connected to the network, you can deploy the contract by clicking the "Deploy" button in Remix. You will also need to provide the price feed address. The price feed address is the address of the Chainlink price feed. + +Once you have provided the price feed address and deployed your contract, you can now start testing. + +Let's switch to our account 2 and fund it with 1,000 ETH using the Tenderly faucet. + +```bash +1000 +``` + +Next, we will confirm the fund function, and we should see that account 2 has been funded. + +Now, let's switch back to our owner account (account 1). We can see that account 1 is connected. We can now call withdraw on the contract. + +Now we'll verify that only the contract owner can withdraw the funds. To do this, we will switch back to account 2 and try to withdraw the funds. We will confirm this action in MetaMask, and we expect it to fail. + +And it does! We can now switch back to account 1, the owner, and attempt to withdraw our funds. + +We will confirm this action in MetaMask, and we expect it to succeed. + +As we can see, it succeeds! So, our smart contract is doing everything that we wanted it to do. We now have a way to deploy our contract and update some starter variables in our contract constructor (aka the init function). We can fund the contract and make sure there is a minimum dollar amount that must be hit in order to even fund this contract. We're keeping track of how much and who is sending us money for us to go buy a coffee, and then only we can withdraw the money out, that is withdrawn with this send function from the contract. Then, we're going to reset those data structures that are keeping track of the funders. We have a way to actually get the price of this data, and we have a little external function as well, so that we can make sure everything is working. This is fantastic! Great job. + +Now, if you want to go the extra mile and actually test this on a true testnet, like Sepolia, you can, but again, like I said, getting testnet Sepolia can be very tricky, very difficult. So, we're going to, So, I don't recommend you do this, because you're going to run into a lot of issues. However, So I highly recommend we just stick with the Tenderly virtual testnet here, which again, shows us all these transactions very similar to what an explorer would do anyways. From e3aba2eb81b69725e244480656baad776e400199 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:38:39 -0700 Subject: [PATCH 601/797] Equious updated courses/vyper-101/2-remix-coffee/31-idk/+page.md. --- .../vyper-101/2-remix-coffee/31-idk/+page.md | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/31-idk/+page.md b/courses/vyper-101/2-remix-coffee/31-idk/+page.md index d226208fe..32769983b 100644 --- a/courses/vyper-101/2-remix-coffee/31-idk/+page.md +++ b/courses/vyper-101/2-remix-coffee/31-idk/+page.md @@ -1,3 +1,27 @@ ---- - title: Idk - --- \ No newline at end of file +## Immutables & Constants + +We'll learn about immutables and constants. Immutables are a way to declare values that we know won't change once a contract is deployed. They help improve the readability and gas efficiency of our code. + +Let's look at an example. Imagine we have an owner for our contract, and we know this owner will never change within the contract. We can use a constant to represent this value. + +First, let's declare the `owner` variable as a public address: + +```python +owner: public(address); +``` + +Now, we want to set this value in the constructor of the contract. Using the keyword `constant`, we need to initialize it with a value: + +```python +owner: public(constant(address)) = msg.sender +``` + +Notice that we can't assign a value to a constant within the constructor. Instead, we need to assign it at compile time. So, we can change the code to: + +```python +OWNER: public(constant(address)) = msg.sender +``` + +Here, we are assigning a value to a constant, which is the `msg.sender` address at compile time. + +We will cover constants in more detail in the following lessons. From 47ab286efe1de9fccc194d46c971e61d47641da3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:39:08 -0700 Subject: [PATCH 602/797] Equious updated courses/vyper-101/2-remix-coffee/32-natspec/+page.md. --- .../2-remix-coffee/32-natspec/+page.md | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/32-natspec/+page.md b/courses/vyper-101/2-remix-coffee/32-natspec/+page.md index 092dcef15..48f6baf7e 100644 --- a/courses/vyper-101/2-remix-coffee/32-natspec/+page.md +++ b/courses/vyper-101/2-remix-coffee/32-natspec/+page.md @@ -1,3 +1,44 @@ ---- - title: Natspec - --- \ No newline at end of file +## Natspec docstring + +Now that we've learned more about immutables and constants, we can improve our code to be more professional and gas-efficient. + +Before we even get to immutables and constants, we can improve our code by adding documentation at the top of the contract. + +This is a special type of comment called a docstring. We can do this by adding three quotes: + +```python +""" +""" +``` + +This is the same as adding a hashtag (#) to every single line, but this means that we don't have to do that. Everything within these three quotes will be a comment. + +We can use a special docstring format called NatSpec Metadata to add documentation to our code. It's a way to provide rich documentation for functions, return values, and more. + +To use NatSpec, we add an "at" symbol (@) followed by a tag. We'll add the following NatSpec tags at the top of our contract: + +```python +pragma version 0.4.0 +@license MIT +@title Buy Me A Coffee! +@author You! +@notice This contract is for creating a sample funding contract. +``` + +- **`pragma version`**: specifies the version of Vyper we are using. It isn't part of NatSpec, but it is convention to put it at the top of our contract. +- **`@license`**: describes the license for our code (in this case, MIT). +- **`@title`**: provides a short title for our contract. +- **`@author`**: identifies the author of the code. +- **`@notice`**: explains to an end user what the contract does. + +The compiler doesn't parse docstrings for internal functions. While we can add NatSpec tags in comments for internal functions, the compiler won't process or include them. + +We can add other NatSpec tags to document different parts of our contract, like functions and parameters. For example: + +```python +@dev Explains to a developer any extra details. +@param Documents a single parameter. +@return Documents one or all return value(s). +``` + +Let's add these NatSpec tags to our code so it looks a little more professional. From ec61d599d42d4b0c3ed76a0d3f56afc00e148fad Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:39:42 -0700 Subject: [PATCH 603/797] Equious updated courses/vyper-101/2-remix-coffee/33-update-immute/+page.md. --- .../2-remix-coffee/33-update-immute/+page.md | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/33-update-immute/+page.md b/courses/vyper-101/2-remix-coffee/33-update-immute/+page.md index d1e653aa9..efd279d26 100644 --- a/courses/vyper-101/2-remix-coffee/33-update-immute/+page.md +++ b/courses/vyper-101/2-remix-coffee/33-update-immute/+page.md @@ -1,3 +1,43 @@ ---- - title: Update Immute - --- \ No newline at end of file +## Updating our Immutables and Constants + +We'll finally now move on to the immutables and the constant variables here. So, down here we have these different values: minimum USD, price feed, owner, funders, etc. Now, as of today, these are all what's known as storage variables. + +Storage variables can be very gas-intensive to work with. Every time we read or write to a storage variable, it costs a lot of gas. We're going to learn about storage much later in the course. So, for now, just think of any time a variable isn't ever going to change, and you want to think about how making it a constant or immutable. + +Constant and immutable variables mean that they can never be changed. However, they are way more gas efficient for a whole bunch of reasons. And, we can even test this out. So, let's take this minimum USD. Now, minimum USD, we set to $5, and then we never change. So, what we could do is we could set this minimum USD to be a constant. So, we could say: + +```python +public constant uint256 +``` + +And, the convention for constant variables is to have constant variables be all upper case. So, we would do MINIMUM_USD, and then since it's constant, we don't set it in the constructor down here anymore. We would have to set it right up here. So, we would say MINIMUM_USD, public constant uint256 equals as wei value (5, "ether"), and then we would delete this line here. + +Now, constant variables are not considered storage variables, which is another reason why we have them all updated. Both constants and immutables are not storage variables. Again, we'll learn about storage much later. And, since it's not a storage variable, we scroll down. We no longer have to reference it with self.minimum USD. This self when we do this self.minimum USD, we're usually referring to storage variables or functions. Since MINIMUM_USD is a constant, we can actually just refer to it like this in all caps here. + +Is there any other place where we have minimum USD? Nope, that's it. Okay, great, we can just leave it like that. Okay, the next, the price feed. So, price feed we set one time, and we never update it again. + +So, can we set the price feed to be constant? Well, we could if we were always using the same price feed. So, I could do: + +```python +constant aggregator V interface +``` + +equals aggregator V interface, wrapped around this address here. However, this would assume that we're always going to use this address. Now, the price feed for the Ethereum USD price is going to be different on different chains. So, we don't actually want this to be constant. What we want it to be is immutable. So, let me undo everything I just did with command Z or control Z. So, instead of constant here, we could make this immutable. So, to set this as immutable, we would go: + +```python +immutable aggregator V interface +``` + +And then, now, same thing, price feed, we would do from lower case to all upper case. PRICE_FEED. + +Because, this is also not stored in storage. Now, what we can do though is right in our constructor, we can set price feed equals aggregator V interface, the price feed that we pass in. This way, whenever we deploy this, we will update the price feed with whatever address that gets passed in here. This way, when we deploy this contract on different chains, we can use different price feed addresses on those different chains and leave the contract as such. So, now I can scroll down. Let me look for any spots that we refer to the price feed. Same thing here, static call self.price feed . latest answer. We would just do the immutable PRICE_FEED instead. + +Let me remove these comments as well. Okay, great. So okay, so this one's a constant because it's always going to be five, no matter what. This one's immutable because it's going to be different depending on the chain that we're on. But, once we figure out what it's going to be, it's always going to be the same. + +The owner, hm, what should the owner be? Well, if we change accounts, the owner is probably going to be different depending on when we change it. So, the owner we probably want to be immutable as well. So, we say immutable, and then same thing. We're going to make this upper case, OWNER. We scroll down here. Now instead of self.owner we're just going to say OWNER. + +Now we can scroll down some more, let's look for any spot we refer to OWNER. Okay, great, right here. OWNER, self.owner is now just OWNER. Let's look for some more. Nope, looks pretty good. Okay, great. + +Do a little clean up here, these comments. Okay, so these are going to be constants and immutables. Okay, great. What about the funders dynamic array? Is this ever going to change? Well, yes. Every single time a funder funds, this is going to get updated. So, this we have to keep as a storage variable. Storage. + +What about funder to amount funded? Is this ever going to change? Yes. Same thing. Every single time a funder funds or we withdraw money, this is going to change. So, we're going to leave these as not constants and not immutables. From 55cf1322854cf3e4c1f237e9985d1ba17b561d1d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:40:11 -0700 Subject: [PATCH 604/797] Equious updated courses/vyper-101/2-remix-coffee/34-magic/+page.md. --- .../2-remix-coffee/34-magic/+page.md | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/34-magic/+page.md b/courses/vyper-101/2-remix-coffee/34-magic/+page.md index 5bc4b4213..100bba111 100644 --- a/courses/vyper-101/2-remix-coffee/34-magic/+page.md +++ b/courses/vyper-101/2-remix-coffee/34-magic/+page.md @@ -1,3 +1,23 @@ ---- - title: Magic - --- \ No newline at end of file +## Antipattern: Magic Numbers + +We're going to learn about a programming antipattern called "magic numbers." An antipattern is essentially a "bad coding habit" or an unrecommended way to write code. + +We can see a magic number in the following code block: + +```python +eth_amount_in_usd: uint256 = (eth_price * eth_amount) // (10 ** 18) +``` + +The magic number here is 18. + +We'll improve readability by using a variable to represent this value: + +```python +PRECISION: constant(uint256) = 1 * (10 ** 18) +``` + +Now, we can replace the magic number with the `PRECISION` variable, which makes the code clearer: + +```python +eth_amount_in_usd: uint256 = (eth_price * eth_amount) // PRECISION +``` From f1c48aefe42a4668ebc928c6bf36abe9788f0cfd Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:40:35 -0700 Subject: [PATCH 605/797] Equious updated courses/vyper-101/2-remix-coffee/35-gas/+page.md. --- .../vyper-101/2-remix-coffee/35-gas/+page.md | 77 ++++++++++++++++++- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/35-gas/+page.md b/courses/vyper-101/2-remix-coffee/35-gas/+page.md index ef4aef09d..79394875a 100644 --- a/courses/vyper-101/2-remix-coffee/35-gas/+page.md +++ b/courses/vyper-101/2-remix-coffee/35-gas/+page.md @@ -1,3 +1,74 @@ ---- - title: Gas - --- \ No newline at end of file +## Gas Comparison: Constants and Immutables vs Storage + +We are going to explore how expensive it is to deploy a contract, and call a fund function with constants and immutables. + +Let's make sure that our contract has compiled and is ready to be deployed. + +Next, we will navigate to the deploy tab in Remix. We are going to be using our injected Metamask. However, we're going to go back to our fake chain. + +Now, we're going to use this price feed address. We'll copy this, paste it in, and deploy our contract. + +After a few moments, we'll see that our contract has deployed and is available to interact with. + +Let's take a look at how much gas it cost to deploy our contract. In the transaction details, scroll down and you'll find the transaction cost. This is the entire cost of the whole transaction. Let's copy this number. + +Now we'll return to our contract code, and above our deploy function, we'll add this line: + +```python +# With constants: 262853 +``` + +We'll add a second line: + +```python +# With constants: 105332 +``` + +Next, we'll make some changes to our contract code to remove the `constant` keyword. This will require us to change our deploy function to the following code: + +```python +@deploy +def __init__(price_feed: address): + self.minimum_usd = as_wei_value(5, "ether") + PRICE_FEED = AggregatorV3Interface(price_feed) + OWNER = msg.sender +``` + +We've also changed our fund function to the following: + +```python +@external +@payable +def fund(): + """Allows users to send $ to this contract + Have a minimum $ amount to send + How do we convert the ETH amount to dollars amount?""" + + usd_value_of_eth: uint256 = self.get_eth_to_usd_rate(msg.value) + assert usd_value_of_eth >= self.minimum_usd, "You must spend more ETH!" + self.funders.append(msg.sender) + self.funder_to_amount_funded[msg.sender] += msg.value + +``` + +We'll compile these changes and deploy our contract again. + +Now, let's take a look at the gas costs and compare them. + +With constants, deploying our contract cost 262,853 gas. Let's put those numbers side by side to really see the difference. + +Without constants, it cost 282,553 gas to deploy our contract. + +That's 20,000 gas difference, or in real world money, it's 7 cents cheaper. + +Let's do the same for the fund function. We'll copy 0.002, and call the fund function. + +After confirmation, let's take a look at the gas cost. + +With constants, the transaction cost was 105,332 gas. We'll go back to our contract and put these costs side by side. + +Without constants, the transaction cost is 107,432 gas. + +Again, by making the minimum a constant we saved 2,000 gas. + +So we've seen that making small changes to our code can lead to significantly lower gas usage, which will save money for anyone interacting with your contracts. From eebae75bb2fbc730a197b13a7694c98fb4dc1ca4 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:41:07 -0700 Subject: [PATCH 606/797] Equious updated courses/vyper-101/2-remix-coffee/36-fallback/+page.md. --- .../2-remix-coffee/36-fallback/+page.md | 67 ++++++++++++++++++- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/36-fallback/+page.md b/courses/vyper-101/2-remix-coffee/36-fallback/+page.md index ea13f6a83..b8b226158 100644 --- a/courses/vyper-101/2-remix-coffee/36-fallback/+page.md +++ b/courses/vyper-101/2-remix-coffee/36-fallback/+page.md @@ -1,3 +1,64 @@ ---- - title: Fallback - --- \ No newline at end of file +We're learning about the default function in Vyper. + +Vyper is a smart contract language similar to Solidity, but it has some key differences. + +We're building a smart contract that allows people to send money to this contract, which we'll call "Buy Me A Coffee". + +We'll use Vyper to make sure that when somebody sends money to this contract, we can keep track of them as a funder. We're going to do this through a function called "fund". + +The fund function is a key part of our "Buy Me A Coffee" smart contract. It helps us keep track of who's donated to our cause. + +The fund function allows people to send us money in the form of Ether. This contract uses a price feed to convert the Ether amount into US dollars. + +We've already made this contract work, and we've even added functionality so we can withdraw money from this contract. + +However, right now, this contract is dependent on the fund function to keep track of the funders. + +We can make our smart contract more robust by allowing somebody to send us money without even calling the fund function. We can do this using the default function. + +Here is an example of the code we've written so far. + +```python +@external +@payable +def fund(): + """Allows users to send $ to this contract + Have a minimum $ amount to send + """ + usd_value_of_eth: uint256 = self.get_eth_to_usd_rate(msg.value) + assert usd_value_of_eth >= MINIMUM_USD, "You must spend more ETH!!" + self.funders.append(msg.sender) + self.funder_to_amount_funded[msg.sender] += msg.value +``` + +We're going to add a new function above this one called "def _default_". The default function is executed when somebody sends money to our contract without calling a specific function. + +Here is the code: + +```python +@external +@payable +def _default_(): + pass +``` + +The default function should accept no parameters. We use the "pass" keyword to tell Vyper to do nothing. We then recompile the code and deploy this contract again. + +In our Remix VM, we'll now try to send 1 Ether to this contract, without calling the fund function, but the transaction will revert. Our "funders" array still shows zero funders. + +Now, we'll try to call the fund function from our default function. + +Here is the updated code: + +```python +@external +@payable +def _default_(): + self.fund() +``` + +We'll recompile the code and deploy this contract. + +Now when we send 1 Ether to our "Buy Me A Coffee" contract, it should still update the balance of the contract, but this time, it should also add the funder to the "funders" array. + +This default function is a very powerful tool that can be used to add a layer of functionality to our Vyper smart contracts. From 44585aaf34c1e953868d89e5ecbfaecd29dd8bb1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:45:02 -0700 Subject: [PATCH 607/797] Equious updated courses/vyper-101/2-remix-coffee/37-better-way-to-send/+page.md. --- .../37-better-way-to-send/+page.md | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/37-better-way-to-send/+page.md b/courses/vyper-101/2-remix-coffee/37-better-way-to-send/+page.md index 63fa80df2..23535b887 100644 --- a/courses/vyper-101/2-remix-coffee/37-better-way-to-send/+page.md +++ b/courses/vyper-101/2-remix-coffee/37-better-way-to-send/+page.md @@ -1,3 +1,37 @@ ---- - title: Better Way To Send - --- \ No newline at end of file +## Better way to send ETH + +We've learned how to send ETH to another account using the `send` function. However, there's a better way to do it that's considered more secure. + +The `send` function is a lower-level function that can be unreliable. There are potential issues with how much gas the EVM uses for different opcodes (for example, logging), and this could cause transactions to fail. + +Instead, we're going to use the `raw_call` function. This is a built-in function in Vyper that allows us to call any function in the world, even if the target contract doesn't have that function. + +Let's look at how to use `raw_call` to send ETH. We'll use the `withdraw` function as an example. + +```vyper +@external +def withdraw(): + """Take the money out of the contract, that people sent via the fund function. + + How do we make sure we can pull the money out? + ..... + """ + assert msg.sender == OWNER, "Not the contract owner!" + #send(OWNER, self.balance) + raw_call(OWNER, b"", value=self.balance) + revert_on_failure=True + #resetting + for funder, address in self.funders: + self.funder_to_amount_funded[funder] = 0 + self.funders = [] +``` + +**Explanation:** + +- `raw_call(OWNER, b"", value=self.balance)` calls the raw call function. +- The first argument `OWNER` is the address we're sending ETH to. +- The second argument `b""` is an empty byte string that represents the data we're sending. +- The third argument `value=self.balance` is the amount of ETH we're sending, which is the contract's current balance. +- `revert_on_failure=True` tells Vyper to revert the transaction if `raw_call` fails. + +We can learn more about `raw_call` and its advanced features in later lessons. For now, understand that `raw_call` is considered a safer way to send ETH than using the `send` function. From 51fbd604bfea827b42e521b6888aa975b351b482 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:45:54 -0700 Subject: [PATCH 608/797] Equious updated courses/vyper-101/2-remix-coffee/38-recap/+page.md. --- .../2-remix-coffee/38-recap/+page.md | 73 ++++++++++++++++++- 1 file changed, 70 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/38-recap/+page.md b/courses/vyper-101/2-remix-coffee/38-recap/+page.md index 385e6edfe..3980dc237 100644 --- a/courses/vyper-101/2-remix-coffee/38-recap/+page.md +++ b/courses/vyper-101/2-remix-coffee/38-recap/+page.md @@ -1,3 +1,70 @@ ---- - title: Recap - --- \ No newline at end of file +In this lesson we will continue working with our _buy-me-a-coffee_ smart contract. We will introduce a few more key fundamentals to help us understand the basics of smart contract development in Vyper. We'll then move on to more complex aspects later in the course. + +Here is the code we are working with so far: + +```python +#pragma version 0.4.0 +@license MIT +@title Buy Me A Coffee! +@author You! +@notice This contract is for creating a sample funding contract + +# We'll learn a new way to do interfaces later... +interface AggregatorV3Interface: + def decimals() -> uint8: view + def description() -> String[1000]: view + def version() -> uint256: view + def latestAnswer() -> int256: view + +# Constants & Immutables +MINIMUM_USD: public(constant(uint256)) = as_wei(value=5, "ether") +PRICE_FEED: public(immutable(AggregatorV3Interface)) = 0x6944AA1769357215DE4FAC081f113094dC325306 sep0lia # ABI Address +OWNER: public(immutable(address)) +PRECISION: constant(uint256) = 1 * (10 ** 18) + +# Storage +funders: public(DynArray[address, 1000]) +funder_to_amount_funded: public(HashMap[address, uint256]) + +# With constants: 262, 853 +@deploy +def __init__(price_feed: address): + PRICE_FEED = AggregatorV3Interface(price_feed) + OWNER = msg.sender + +@external +@payable +def fund(): + """Allows users to send $ to this contract + Have a minimum $ amount to send + """ + usd_value_of_eth: uint256 = self.get_eth_to_usd_rate(msg.value) + assert usd_value_of_eth >= MINIMUM_USD, "You must spend more ETH!!" + self.funders.append(msg.sender) + self.funder_to_amount_funded[msg.sender] += msg.value +``` + +In this code, we have: + +- A _decimals_ function which returns a uint8 value. +- A _description_ function which returns a String value. +- A _version_ function which returns a uint256 value. +- A _latestAnswer_ function which returns an int256 value. +- We have declared the constants _MINIMUM_USD_, _PRICE_FEED_, _OWNER_, and _PRECISION_. +- We have declared the storage variables _funders_ and _funder_to_amount_funded_. +- We have declared the initializer function **_init_**. +- We have declared the _fund_ function which is payable and allows users to send ETH to the contract. + +The topics we've covered so far are: + +- Interfaces +- Constants +- Immutables +- Storage +- Initializers +- Payable Decorators +- Function Documentation + +We have also seen how to use `msg.sender`, `msg.value`, and `self` in our code. + +We will cover more advanced topics later in the course. From 908e39307fdc1c7cfce362623710026b472a5f9e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:51:09 -0700 Subject: [PATCH 609/797] Equious updated courses/vyper-101/2-remix-coffee/4-sending-eth/+page.md. --- .../vyper-101/2-remix-coffee/4-sending-eth/+page.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/4-sending-eth/+page.md b/courses/vyper-101/2-remix-coffee/4-sending-eth/+page.md index 2a8f120b6..2bc1a107d 100644 --- a/courses/vyper-101/2-remix-coffee/4-sending-eth/+page.md +++ b/courses/vyper-101/2-remix-coffee/4-sending-eth/+page.md @@ -1,3 +1,9 @@ ---- - title: Sending Eth - --- \ No newline at end of file +The first question that will come up is how do we send ETH to this contract? The answer to this is that in every transaction you send, there's a value field that allows you to send a certain amount of ETH. You can even see this in Metamask, where you can send a specific amount of ETH to an address. This populates the value field in the transactions. + +Not all functions can read from this value field. To tell a function that it can read from the value field, we use the `@payable` keyword. This tells Vyper that the function can work with the `msg.value` variable. Similar to wallets, smart contracts can hold funds. To ensure someone calling the `fund` function sends at least one ETH, we can use the `assert` function and say: + +```python +assert msg.value == 1000000000000000000 +``` + +We'll understand what `wei` is later on. We also have a variable called `msg.sender`, which is the sender of the current message. We will be using this variable in our code. From b7ee2e63cd5117be9cec58d7fffc29b4ae3fec8b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:51:38 -0700 Subject: [PATCH 610/797] Equious updated courses/vyper-101/2-remix-coffee/5-gwei-wei-eth/+page.md. --- .../2-remix-coffee/5-gwei-wei-eth/+page.md | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/5-gwei-wei-eth/+page.md b/courses/vyper-101/2-remix-coffee/5-gwei-wei-eth/+page.md index 9baa35504..064b9caec 100644 --- a/courses/vyper-101/2-remix-coffee/5-gwei-wei-eth/+page.md +++ b/courses/vyper-101/2-remix-coffee/5-gwei-wei-eth/+page.md @@ -1,3 +1,69 @@ ---- - title: Gwei Wei Eth - --- \ No newline at end of file +## Wei, Gwei, and ETH in Vyper + +We're going to learn about how to convert between Wei and ETH. + +Here's a code snippet: + +```python +# pragma version 0.4.0 +# @license: MIT +# @author: You! + +@external +@payable +def fund(): + """Allows users to send $ to this contract. + Have a minimum $ amount send + + 1. How do we send ETH to this contract? + """ + assert msg.value == 1000000000000000000 +``` + +This is a pretty confusing concept, but it will make more sense as we explore it. + +First, if you go to the site eth-converter.com, you can see there are some different units for Ethereum. + +If you type in one ETH, you'll see how much one ETH is in Wei. Wei is the smallest divisible unit of account in the Ethereum ecosystem. So, one ETH, as of recording, is worth approximately $3241.63, and has 18 zeros in its Wei equivalent. + +Let's look at how we can make our code more readable. + +Instead of typing in that long Wei number every time, we can use a built-in Vyper function called as_wei_value. Here's an example: + +```python +assert msg.value == as_wei_value(1, "ether") +``` + +We're saying, hey, let's get the wei value of one ETH and return it as Wei. + +Another way to see this is with a calculation: + +```python +assert msg.value == (1 * 10 ** 18) +``` + +This double times, or power of 18, is the same as the Wei value of one ETH. + +We can add a message in our code in case someone doesn't send enough ETH, like this: + +```python +assert msg.value == as_wei_value(1, "ether"), "You must spend more ETH!" +``` + +This helpful message will let users know if they don't send enough ETH. Without this message, if someone sends less than one ETH, the transaction will break. + +Let's talk about the different ways we can use the 'equals' sign in Vyper. The `==` symbol is what we use to check if two things are equivalent. + +Here's an example: + +```python +my_num: uint256 = 7 +``` + +This is setting the value of `my_num` to 7. It's not checking if the value of `my_num` is equal to 7. So, this line is not equivalent to: + +```python +assert msg.value == as_wei_value(1, "ether"), "You must spend more ETH!" +``` + +This is a subtle but important distinction for new Vyper developers. Don't worry too much about this right now, as you practice more it'll start to make more sense. From 1185cb6923c6df6e22ca35d1048587b0ef77f235 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:52:33 -0700 Subject: [PATCH 611/797] Equious updated courses/vyper-101/2-remix-coffee/6-send-tx/+page.md. --- .../2-remix-coffee/6-send-tx/+page.md | 66 ++++++++++++++++++- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/6-send-tx/+page.md b/courses/vyper-101/2-remix-coffee/6-send-tx/+page.md index 5b4867baa..6ac1dc604 100644 --- a/courses/vyper-101/2-remix-coffee/6-send-tx/+page.md +++ b/courses/vyper-101/2-remix-coffee/6-send-tx/+page.md @@ -1,3 +1,63 @@ ---- - title: Send Tx - --- \ No newline at end of file +## Sending a Transaction with ETH in Remix + +We're going to compile and deploy a contract. We will then call a function on this contract which requires the transaction to pay ETH. We're going to do this using the Remix VM. + +First, we'll compile our contract. + +```python +pragma version 0.4.0 +# @license: MIT +# @author: You! + +external +@payable +def fund(): + """Allows users to send $ to this contract. + Have a minimum $ amount send + + 1. How do we send ETH to this contract? + """ + assert msg.value == as_wei(1, "ether") "You must spend more ETH!" +external +def withdraw(): + pass +``` + +Now, we'll deploy this contract. + +```python +pragma version 0.4.0 +# @license: MIT +# @author: You! + +external +@payable +def fund(): + """Allows users to send $ to this contract. + Have a minimum $ amount send + + 1. How do we send ETH to this contract? + """ + assert msg.value == as_wei(1, "ether") "You must spend more ETH!" +external +def withdraw(): + pass +``` + +We'll see a red button and an orange button. + +The orange button `withdraw` is not payable and doesn't do anything. But `fund` is red and is payable because it has the `@payable` keyword in the code. + +We can send a transaction to `fund` and the Remix VM will know to include some ETH. The default account in Remix has 99.9999999999999999 ETH in it. + +We can send a transaction to `fund` by placing a value in the `VALUE` section and calling the function. + +If we call the function with a value of zero, the transaction will be reverted, because our contract requires a value of at least one ETH. We'll see a message: "You must spend more ETH!". + +Transactions can be reverted because the contract has specific requirements that were not met, such as the requirement to send at least one ETH in this case. + +If we call the function with a value of one ETH, the transaction will go through. + +We can set the value to two ETH and try to call the function again, but the transaction will be reverted, showing the same error message: "You must spend more ETH!". + +We'll go into reverts in more depth in a later lesson. From e4ef5559c2f3b63d4365ef171284e056dabdcb9e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:52:59 -0700 Subject: [PATCH 612/797] Equious updated courses/vyper-101/2-remix-coffee/7-reverts/+page.md. --- .../2-remix-coffee/7-reverts/+page.md | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/7-reverts/+page.md b/courses/vyper-101/2-remix-coffee/7-reverts/+page.md index b1dc9fd85..695c83be9 100644 --- a/courses/vyper-101/2-remix-coffee/7-reverts/+page.md +++ b/courses/vyper-101/2-remix-coffee/7-reverts/+page.md @@ -1,3 +1,50 @@ ---- - title: Reverts - --- \ No newline at end of file +## Reverts in Solidity + +Reverts are an incredibly important part of the Solidity language. They allow us to undo any actions that have been done and send the remaining gas back. Let's explore how they work! + +We can see a revert in action with this code: + +```python +// SPDX-License-Identifier: MIT +pragma version 0.4.0 + +contract buy_me_a_coffee { + + my_num: public uint256; + + @external + @payable + def fund(): + """ + Allows users to send $ to this contract. + Have a minimum $ amount send + 1. How do we send ETH to this contract? + """ + self.my_num = self.my_num + 2; + assert msg.value == as_wei_value(1, "ether"), "You must spend more ETH!" + + @external + def withdraw(): + pass +} +``` + +Let's set our state variable to `2` and then call our `fund` function. We'll deploy the contract and then call `my_num`. We'll see that our `my_num` has been set to `2` as expected. This is because the `assert` condition was met. + +Now, let's change the `value` to `0` and then call `fund`. Our terminal output will show us that the transaction failed and has been reverted. When we call `my_num` again, we'll see that it is still set to `2` and the value has not changed. + +This is because the `assert` condition was not met. The transaction was reversed and the state was rolled back to how it was before. + +Reverts are a great way to ensure that transactions are only executed when certain conditions are met. They are particularly useful when working with real networks, where transactions can be expensive. + +We will also want to check that our transaction did not revert. We can do this by running the following terminal command: + +```bash +truffle test +``` + +If the transaction reverted, the terminal output will tell us why. This can be useful for debugging and understanding why our transaction is failing. + +In the blockchain world, if you send a transaction and it reverts, you've updated nothing. You will have spent money but the transaction will not have updated the state. We want to do everything in our power to not send transactions that are going to revert. + +Metamask will also give us a popup saying that the transaction will likely revert. If this happens, we should confirm that we want to send the transaction. From 647c7fcc643f610031df9390d308ba6ee6ebd8c9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:53:43 -0700 Subject: [PATCH 613/797] Equious updated courses/vyper-101/2-remix-coffee/8-chainlink/+page.md. --- .../2-remix-coffee/8-chainlink/+page.md | 129 +++++++++++++++++- 1 file changed, 126 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/8-chainlink/+page.md b/courses/vyper-101/2-remix-coffee/8-chainlink/+page.md index 6dd518502..6d0c4d95f 100644 --- a/courses/vyper-101/2-remix-coffee/8-chainlink/+page.md +++ b/courses/vyper-101/2-remix-coffee/8-chainlink/+page.md @@ -1,3 +1,126 @@ ---- - title: Chainlink - --- \ No newline at end of file +## Oracles and Chainlink + +We are going to learn about oracles and Chainlink and how to bring real-world data into our smart contracts. + +Blockchains are deterministic systems, meaning they can't interact with real-world data and events on their own. They can't know what the value of ETH is, they can't know if it's sunny outside, or what the temperature is. They also can't do any external computation. + +This is known as the smart contract connectivity problem or the oracle problem. This is bad news because we want our smart contracts to replace traditional agreements. And traditional agreements need data, and they need to interact with the real world. + +This is where Chainlink and blockchain oracles come into play. A blockchain oracle is any device that interacts with the off-chain world to provide external data or computation to smart contracts. + +However, the whole story doesn't end there. If we use a centralized oracle, we are reintroducing a point of failure. We've done all this work to make our logic layer decentralized, but if we get our data through a centralized node or through a centralized API, or we decide we want to make the API call ourselves, we are reintroducing these trust assumptions that we've worked so hard to get rid of. We're essentially ruining the entire purpose of building a smart contract. So we don't want to get our data, or do external computation, through centralized nodes. Those are bad news. + +Chainlink is the solution here. Chainlink is a decentralized oracle network for bringing data and external computation into our smart contracts. + +As we mentioned before, this gives rise to these hybrid smart contracts, which combine on-chain and off-chain to make incredibly feature-rich, powerful applications. + +Chainlink is a modular decentralized oracle network that can be customized to deliver any data or do any external computation that you like. + +So, for example, a lot of people might just say, "Oh, well I can just make an API call to, you know, a data provider to get the pricing information on my smart contract." However, blockchain nodes can't actually make these API calls. You can't make like an HTTP GET, if you're familiar with that, HTTP GET. You can't make an HTTP GET call because the different Ethereum nodes, the different blockchain nodes, would not be able to reach consensus about what the result of that API call even is. Additionally, this is a huge centralization vector and kind of defeats the purpose of smart contracts in the first place. + +So instead, we need a decentralized network of nodes to get us this data for us. + +Now, Chainlink networks can be completely customized to bring any data or any external computation that you want. However, doing the customization can be a little bit extra work. There are a ton of Chainlink features that come out of the box, completely decentralized, ready to plug-and-play into your smart contract applications. + +What are those features? The first one is going to be Chainlink Data Feeds. And, that's the one we're actually going to be using for our application here. Chainlink Data Feeds currently, at the time of recording, are powering over $50 billion in the DeFi world. + +The way they work is a network of Chainlink nodes gets data from different exchanges and data providers and brings that data through a network of decentralized Chainlink nodes. The Chainlink nodes use a median to figure out what the actual price of the asset is, and then deliver that in a single transaction to what's called a reference contract, a price feed contract, or a data contract, on-chain, that other smart contracts can use. And then, those smart contracts use that pricing information to power their DeFi application. + +You can see an example at data.chain.link. And you can change networks, you can change price feeds, you can change a whole bunch of information to see some of those popular price feeds. + +Let's look at ETHUSD, for example. + +On ETHUSD, we can see this whole network of independent Chainlink node operators that are each getting different answers for the price of ETHUSD. They're getting aggregated by the network and then delivered on-chain. We can see how often they're updated. These ones are updated for a 0.5 deviation threshold, or a few hour heartbeat, whichever one hits first. We can see when the last update was. We can see the number of oracle responses, etc. + +We can see the contract address directly on-chain. + +We can even look at the contract on Etherscan. + +We can see some of the history. We can see all the responses of the different oracles. + +And then, at the bottom, we can see the different users and sponsors keeping this network up. + +Similar to transaction gas, whenever a node operator delivers data to a smart contract, the Chainlink node operators are paid a little bit of oracle gas in the Chainlink token. Right now, these users of the protocol are sponsoring keeping these feeds up, and are paying the oracle gas associated with delivering this data on-chain. + +We can take a look at an example over at docs.chain.link. The solidity docs have the solidity example directly in them, but if you scroll down you can also see some Vyper examples or, if you click this little README, it will bring you to the Vyper edition of the Chainlink starter kit, which will show you how to make a price feeds using Vyper. + +We are going to walk you through a little demo. This is in solidity, so you can ignore the exact code, but the process will be essentially the same. + +Now, the docs are probably going to look very different by the time you actually start looking at them because they change the docs pretty frequently. So an easy way to get started here is maybe go to docs.chain.link, and then over either on developer hub, or overview, go to data feeds. And this is where you can see most of what you need in the getting started section of the documentation. + +We can see an example of an art contract that uses and reads from one of these Chainlink price feeds. + +**Code:** + +```python +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.7; + +import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; + +contract PriceConsumerV3 { + + AggregatorV3Interface internal priceFeed; + + /** + * Network: Kovan + * Aggregator: ETH/USD + * Address: 0x9326BFA02AD2366d30baCb125266AF641031331 + */ + constructor() { + priceFeed = AggregatorV3Interface(0x9326BFA02AD2366d30baCb125266AF641031331); + } + + /** + * Returns the latest price + */ + function getLatestPrice() public view returns (int) { + ( + uint80 roundID, + int price, + uint startedAt, + uint timeStamp, + uint80 answeredInRound + ) = priceFeed.latestRoundData(); + return price; + } +} +``` + +We can even open up this up in Remix and work with it in Remix. It looks like this example is running from a price feed on Kovan. The reason we are actually going to use a testnet to see this work is that there's a set of Chainlink nodes monitoring the testnet to show you exactly how this works out. + +Once we get deeper into the course, we'll show you how to actually run tests and work with Chainlink nodes without actually being on a testnet, which will make your development much faster. But I highly recommend walking through this section along with me so that you can see first-hand how this actually works. + +So let's go ahead to faucets.chain.link /kovan We're going to switch to the Kovan network. + +We're going to get some Kovan ETH, but remember, look at the network flag, and use whatever network is in the documentation. + +**Terminal:** + +```bash +faucet.chain.link/kovan +``` + +We're going to turn off test LINK; we'll just stay with ETH. I'm not a robot. + +And then send request. Once our Kovan ETH has reached our wallet, we can go ahead and close. And, we can take a look in our wallet and see that we do indeed have 0.1 ETH on Kovan. + +Now, let's go back to our Remix. We'll compile this contract. + +We'll go and deploy this on injected Web3. + +And again, the reason we are going to use injected Web3, instead of Javascript VM, is that there's no network of Chainlink nodes watching our little fake Javascript VM. There are a network of Chainlink nodes watching the testnet. + +So we'll scroll down. We'll switch contract to the PriceConsumerV3. + +We'll hit deploy. MetaMask will pop up, and after a brief delay, we can see our PriceFeedConsumer down here, and we can hit get the latest price, which shows us the latest price of Ethereum in terms of USD. You may be wondering why the number looks so weird. That seems like a really large number for the price of Ethereum in terms of USD, and this is because decimals don't actually work so well in Solidity. And we'll get to that in a little bit. + +There's a decimals flag associated with this PriceFeed address that tells us how many decimals to include with this price. It's also in the documentation. However, I know that this one has eight decimals. So, this is saying the value of Ethereum right now is 3,262. + +It may, of course, be different when you go ahead and try this. + +Now there's a number of things that happen in this contract that I'll explain in our fund me example. But if you want to take a look now and see if you can figure out what's going on, I recommend you do so. Price feeds are one of the most powerful out-of-the-box decentralized features you can use in your smart contract to level them up, especially for decentralized finance. + +If you're looking for different addresses of different price feeds, you can check the contract addresses section of the documentation, choose the network that you want, and then scroll down and then look some of the different addresses of the different price feeds. For example, this address will give you the price of 1inch token in terms of ETH. + +This address will give you the price of the Apple stock in terms of USD, and so on and so forth. You can see a lot of the different Chainlink functionalities and tools, and services in the DevHub, or, aka, the docs of Chainlink. One of the newest and coolest ones that we have a section on in this little course is Chainlink CCIP or cross-chain interoperability protocol, which is a way to do token transfers across different blockchains, which, as of today, is a big issue, but you'll learn about that much later. From a10bf0d2dc21682997bfcd04584ac370ec35f13d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:59:45 -0700 Subject: [PATCH 614/797] Equious updated courses/vyper-101/2-remix-coffee/9-mid-recap/+page.md. --- .../2-remix-coffee/9-mid-recap/+page.md | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/2-remix-coffee/9-mid-recap/+page.md b/courses/vyper-101/2-remix-coffee/9-mid-recap/+page.md index 074b2dd9f..69fdf462c 100644 --- a/courses/vyper-101/2-remix-coffee/9-mid-recap/+page.md +++ b/courses/vyper-101/2-remix-coffee/9-mid-recap/+page.md @@ -1,3 +1,20 @@ ---- - title: Mid Recap - --- \ No newline at end of file +## Recap + +We haven't written much code yet, but we've covered some important topics. + +The `payable` decorator is used to mark a function that can receive Ethereum. We've seen this in the `fund()` function: + +```python +@payable +def fund(): +``` + +We've also looked at the `assert` keyword. This allows us to check conditions and if the condition is false, the transaction will revert. In our code, we've checked that the `msg.value` sent to the contract is at least 1 ether. + +```python +assert msg.value >= wei_value(1, "ether"), "You must spend more ETH!" +``` + +If the transaction reverts, all changes made during the transaction are undone, and the user receives a refund of gas. + +The next topic we'll discuss is how to get data from the real world into the blockchain. We learned that this is not as simple as making an API call, because we need to avoid relying on centralized entities. We'll explore decentralized oracle networks like Chainlink Price Feeds to address this challenge. From c66c8f8084e8e25ad99f07b09fa1fdc173d66c63 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 14:00:11 -0700 Subject: [PATCH 615/797] Equious updated courses/vyper-101/3-ai/1-intro/+page.md. --- courses/vyper-101/3-ai/1-intro/+page.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/3-ai/1-intro/+page.md b/courses/vyper-101/3-ai/1-intro/+page.md index b7e64e913..2383ac530 100644 --- a/courses/vyper-101/3-ai/1-intro/+page.md +++ b/courses/vyper-101/3-ai/1-intro/+page.md @@ -1,3 +1,5 @@ ---- - title: Intro - --- \ No newline at end of file +## AI Prompting + +Why learn this when there is AI? + +Now a lot of people get discouraged by AI thinking ah, like why bother learning anything if AI already knows a lot of the stuff. Well, in order to think critically about problems and how to solve them, you always need the prerequisite knowledge before you can even start coming up with solutions to fix a problem. So yes, AI knows a lot of things. But, in order for you to solve problems effectively, you need that knowledge as well. So, you need to take the knowledge from AI. Thank you AI for giving us all this knowledge as well. So that you can think critically and come up with better solutions than AI could ever do. Because as of today, that's where humans shine. We are phenomenally better at coming up with solutions. And AI is a tool to help us have even better solutions. But in order for us to come up with the best solutions, we need the knowledge first. \ No newline at end of file From f9536ef242d6ed82a57d039fe00d88e95b248c38 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 14:00:47 -0700 Subject: [PATCH 616/797] Equious updated courses/vyper-101/3-ai/2-vid/+page.md. --- courses/vyper-101/3-ai/2-vid/+page.md | 36 ++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/3-ai/2-vid/+page.md b/courses/vyper-101/3-ai/2-vid/+page.md index cd52348ae..13eefe9c3 100644 --- a/courses/vyper-101/3-ai/2-vid/+page.md +++ b/courses/vyper-101/3-ai/2-vid/+page.md @@ -1,3 +1,33 @@ ---- - title: Vid - --- \ No newline at end of file +## AI Prompting Introduction + +In the age of AI, debugging and getting into software engineering has never been easier. Here are the exact six steps we need to take to unblock ourselves from any software engineering error we'll ever get: + +1. **Tinker** - Try to pinpoint your error. We can usually use an AI buddy to help us out here. Pinpointing your error will potentially solve your problem before we even go into an AI and allow us to craft a better question to an AI. + * **Example:** Try adding a debug print to see where the issue is. + * **Example:** Comment out sections of code to see if it fixes the issue. + +2. **Ask your AI** - We can use ChatGPT, Phind, Bing's AI, or if we want to get wrong answers, Google's Bard. There are six principles to prompt engineering so that we can get the best out of our AI. + * **Example:** Ask "I'm getting this error [Error message]: [Code]. What's the issue?" + * **Principle 1: Write clear and specific instructions** - Give as much context as possible. + * **Principle 2: Give as much context as possible** - Use delimiters to clearly indicate distinct parts of the input. + * **Principle 3: Use delimiters to clearly indicate distinct parts of the input** - Especially look out for something called hallucinations. + * **Principle 4: Look out for hallucinations** - Hallucinations are when your AI gives you an output that it thinks is right, but it's completely wrong. For example, if we write about writing Solidity invariant tests in Foundry, ChatGPT disgraces us by saying we have to npm install it from OpenZeppelin. These can be tough to spot, but once we try it out we'll see it doesn't work. + * **Principle 5: Understand limitations** - Finally, we want to understand the limitations of the AI we're working with. + * **Principle 6: Iterate constantly** - Large language models are trained on human conversations, so we can interact with them as if we're having a conversation, but it's important to know the limitations of these AIs. As most AIs have a limit on how many tokens or words they can keep in context at one time. AI is trained off of human language, so if we're good at asking other humans questions, we'll probably be good at asking robots questions too. Asking questions is a skill, so keep practicing. I've got a link in the description to learn.deeplearning.ai, which is a free course to help software engineers be better prompt engineers. + +3. **Read docs** - When the AIs can't help us, we'll have to go back to the old standbys, actually doing work ourselves. And one of the first pieces of work is reading the documentation. We should have done this already. However, we can still use ChatGPT because a strategy that we constantly use is, I'll copy paste sections of the documentation, add to ChatGPT's context and say, "Something like the above are the docs for tool X, based on those docs, how do I do Y?" + * **Example:** "This is a section of Solidity docs: [Copy and paste relevant docs here] This is my solidity code: [Copy and paste solidity code here] Based on the docs, how do I do [Specific goal in code]?" + +4. **Web Search** - Google might be crying because ChatGPT is eating its lunch, but Google still has what AI doesn't have - the entire internet. Previously, anytime I ran into an issue, I prayed someone else had run into it before I made a post on it so I could Google search that exact issue. There's a new tool called Phind that combines web search with AI as it does a web search and it crawls through all the data of the sites, reads them all, and then gives us an answer based off of what it reads. + * **Example:** "How do I debug Solidity code?" + +5. **Ask in a forum** - Sometimes, the information just isn't out there and we need to ask human beings. We always want to ask our questions on a web-indexed forum like Stack Exchange, Stack Overflow, Quora, or Reddit. This way web crawlers and more likely AIs can scrape the data from these sites and learn from us. That way the next time we have this question, we can get our answers quickly. Asking on Discord and Twitter is a shit because your knowledge will get lost to the unsearchable hole conversations that Discord is and web crawlers don't index them. + * **Example:** "I'm getting this error in Solidity: [Code]. How do I fix it?" + * **Example:** "I'm trying to deploy my smart contract, but I'm getting this error: [Code]. How do I fix it?" + * **Example:** "I'm trying to compile my Solidity code, but I'm getting this error: [Code]. How do I fix it?" + +6. **Ask support or GitHub** - The super secret alpha is to ask a question on Stack Exchange, and then post your Stack Exchange link to Discord. We should 100% always ask our questions and format them with markdown. And if we're not sure how to do markdown, we can ask ChatGPT to help us format our questions in markdown. + * **Example:** "I'm getting this error in Solidity: [Code]. How do I fix it?" + +7. **Iterate** - Do all these same steps over again. And, as always, keep hopping through the code and until next time, stay ribbeting, my fellow blockchainers. + From 5776f18aa79a31f870b791d8fc077cdf2c780667 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 14:03:29 -0700 Subject: [PATCH 617/797] Equious updated courses/vyper-101/3-ai/3-triage/+page.md. --- courses/vyper-101/3-ai/3-triage/+page.md | 42 ++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/3-ai/3-triage/+page.md b/courses/vyper-101/3-ai/3-triage/+page.md index 8ea84026c..0395f3aa6 100644 --- a/courses/vyper-101/3-ai/3-triage/+page.md +++ b/courses/vyper-101/3-ai/3-triage/+page.md @@ -1,3 +1,39 @@ ---- - title: Triage - --- \ No newline at end of file +## 7 Triage Steps for This Course (and Real Life!) + +We're going to learn a bit more about different tools and techniques we can use when we get stuck. We'll cover tools like ChatGPT and forums to ask questions, as well as Google Search for finding information, and Stack Exchange or Peeranha for posting questions. + +### 7 Triage Steps + +1. **Limit self-triage to 15-20 minutes.** For instance, if we're trying to compile our `PriceConverter.sol` file and we've forgotten to add an address, we'll go ahead and compile, but then we'll get this error: + +```python +TypeError: Exactly one argument expected for explicit type conversion. + --> PriceConverter.sol:15:43: +15 | AggregatorV3Interface priceFeed = AggregatorV3Interface( + | ^ (Relevant source part starts here and spans across multiple lines.) +``` + +This error should be pretty obvious: "exactly one argument expected", and we just need to remove that argument. But maybe you're having a really hard time and can't seem to figure it out. Limit yourself to 15-20 minutes, so you don't get stuck for so long that you can't figure anything out. Something like this would be very easy for us to compile, copy the error, go to ChatGPT, and say something like, "Hey, I'm getting an error compiling my solidity. Here is the error: + +```python +TypeError: Exactly one argument expected for explicit type conversion. + --> PriceConverter.sol:15:43: +15 | AggregatorV3Interface priceFeed = AggregatorV3Interface( + | ^ (Relevant source part starts here and spans across multiple lines.) +``` + +" and then it'll probably give us the answer. And, sure enough, the error message suggests that you need to provide an address when using explicit type conversion to create an `AggregatorV3Interface` instance. You're missing the address of the deployed Chainlink Price Feed contract. To fix the error, provide the contract address as an argument when creating the instance. + +2. **Don't be afraid to ask AI, but don't skip learning.** The purpose of this course is for you to be able to learn everything here. AI is going to get things wrong, and it's only the people who actually have learned what's going on under the hood who are going to be able to call out when AI gets something wrong. When AI gets something wrong, it does something called "hallucinate", and we talked a bit about that in that AI video we just watched. So, hallucinations are when the AI makes something up that it thinks is right, but it's completely wrong, and that's something we absolutely need to watch out for when we're coding and when we're learning. + +3. **Use the forums!** Web3Education.dev will have a place for you to ask questions, but in the meantime, definitely be sure to use the Foundry full course discussions. Use this to your advantage. And, use this to help other people out who have questions. This is a community project, we're all going to be helping each other out learning. + +4. **Google the exact error.** If AI doesn't know, and the forums aren't know, Google the exact error. Maybe somebody else has come across this error previously, asked a question online, and you can just Google it. + +5. **Post in Stack Exchange or Peeranha.** And, like we said in that AI video, you want to use Markdown and format your questions as best as possible. So, if you're unfamiliar with how to use Markdown, if you're unfamiliar with how to format your questions, again, please be sure to ask ChatGPT or some other AI how to best format your questions. You can even simply say, "Ask ChatGPT, could you give me an example of a well-formatted Stack Overflow question with code?" And it'll actually give us a really good formatted question. So it gives us the question, it formats the code for us, it's using this with the three backticks that I showed you in order to get this code block here. It's using three backticks and it's being very verbose in giving all the details of the question. + +6. **Posting an issue on github/git.** Obviously when you're out in the wild, and you're actually building things yourself, obviously the education site and the discussions channel of the GitHub repo, the people in these aren't going to have context for the new creative thing that you're working on. So I want you to get used to doing that methodology that we're teaching here. Right? After asking your AI buddy, if your AI buddy doesn't know, Googling, asking questions on Stack Exchange, Ethereum, asking questions on Peeranha, Peeranha is arguably better because you're asking your questions in a decentralized location as opposed to a centralized server. But I definitely want you to practice asking questions, and go to Peeranha, go to Stack Exchange. Make accounts for these so that when you do run into an issue, because you will, you'll know where to post them. I highly encourage you to pause and post a question on one of these forums right now, just so that you get used to it. Just so that you get out of your shell, and you're going to suck at asking questions in the beginning, and that's okay. You will get better at asking questions as you continue with this course. Asking good questions is a skill in itself, and if you learn how to ask very good questions, that's the secret sauce to being amazing at AI prompting as well. + +7. **Post in stack exchange or github/git.** Now, the final step in all of this is actually going to be posting an issue on GitHub/git. A surprisingly incredibly important part of being a software engineer and being a developer in Web3 is interacting with the community. The vast majority of these tools that we're working with are going to be something called open source, meaning that the code associated with them is actually available for anybody to view. This tool, Foundry that we're going to be working with is one such example. And, if you see, it has this issues tab where there's just a ton of issues people are posting while using this tool. This is how code is able to be improved and move forward. All this code is public for people to use and work with. And, if there's a question that isn't answered, you can post here and tell the developers of this tool, "Hey, I'm running into an issue, maybe we should make a project improvement." I would say be very respectful with the way that you make issues. You definitely want to do some searching on issues to make sure that nobody else has asked the question that you're working with, and be sure to use these other resources first, like Peeranha, like Stack Exchange. But in the future, once you leave this course, it's going to be incredibly important for you to participate in the ecosystem by making issues, by making pull requests, and actually improving some of the tools that we're going to be working with yourself. Even Ethereum has a GitHub, and, if there's any improvements that you want to make, you can add an EIP to actually improve Ethereum. We'll talk about EIPs some more later. You can improve some of the clients that Ethereum runs, so interacting with each other is incredibly important. And, in fact, if you don't have a GitHub, we are going to get you set up with GitHub right now, because GitHub is a platform that most developers use to share code and write code and interact with code in between each other. So, if you don't have a GitHub, let's sign up right now. And, we're going to use the GitHub to create our own portfolios of all the different cool coding products that we've created. This way, when you go to apply for a job, you can say, "Hey, go look at my GitHub, I've got all these really cool projects." + +We're going to walk through formatting a question on GitHub, as well. I know I'm belaboring the point here, but I really really want to stress the importance of formatting these questions really well. So, we're actually going to show a clip from my past video, so we're going to be using the full blockchain facility course JS. But, again, for this video, just be sure to use the GitHub repo associated with this course, and not that other old GitHub repo. From 3a40a85fba09f8b9097f72be7cf5cc0139c0207a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 14:05:45 -0700 Subject: [PATCH 618/797] Equious updated courses/vyper-101/3-ai/4-formatting-qs/+page.md. --- .../vyper-101/3-ai/4-formatting-qs/+page.md | 57 ++++++++++++++++++- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/3-ai/4-formatting-qs/+page.md b/courses/vyper-101/3-ai/4-formatting-qs/+page.md index 5d1732912..486d5ae9e 100644 --- a/courses/vyper-101/3-ai/4-formatting-qs/+page.md +++ b/courses/vyper-101/3-ai/4-formatting-qs/+page.md @@ -1,3 +1,54 @@ ---- - title: Formatting Qs - --- \ No newline at end of file +## Formatting a Question + +In this lesson, we'll learn how to properly format a question on a forum or when using an AI. + +We'll start by creating a new discussion on GitHub. + +Click the "Discussions" tab, then click the "New discussion" button. Choose "General" as the category, and you'll be presented with a form. + +For the discussion title, let's use "Test discussion". + +For the body, we can type something simple, like: "Feel free to say hello here!". After typing, click "Start discussion". + +We can then add a comment, which will be our poorly-formatted question. This comment will read: + +``` +Hey why my code not be good? AggregatorV3Interface priceFeed = AggregatorV3Interface { } +``` + +We'll then use a different tool, Remix, to copy the actual error message. We'll be copying the error: + +``` +TypeError: Exactly one argument expected for explicit type conversion, +-- > PriceConverter.sol:21:43: +AggregatorV3Interface priceFeed = AggregatorV3Interface +(Relevant source part starts here and spans across multiple lines). +``` + +Copy the entire error message and then navigate back to our GitHub discussion. + +Let's add a new comment and write: + +``` +I am receiving this error while compiling: ``` +TypeError: Exactly one argument expected for explicit type conversion, +-- > PriceConverter.sol:21:43: +AggregatorV3Interface priceFeed = AggregatorV3Interface +(Relevant source part starts here and spans across multiple lines). +``` +Here is my code: ```solidity +AggregatorV3Interface priceFeed = AggregatorV3Interface {} +``` +Can someone help me figure out what the issue is? + +``` + +You'll notice that our question is now much better formatted and more readable. It also includes the exact error we are receiving and only the relevant code to the error. + +We can then copy the entire question and paste it into a new chat in ChatGPT. The AI will be able to read and comprehend the code blocks, which will then provide a good, helpful response. + +The AI's response will be something like: "You're receiving the error because you're trying to create an instance of 'AggregatorV3Interface' without providing the necessary address argument for explicit type conversion. You need to supply the address of the deployed ChainLink Price Feed contract when creating the instance. To resolve this error, provide the contract address as an argument when creating the 'AggregatorV3Interface' instance." + +By following these steps, you can see how much better your questions will be received both by humans and AIs. This lesson will help you grow and move through your learning journey much faster. Make sure to spend time answering other people's questions in the forum. Think of it as question and answer debt. Every time you answer a question, make a little mental note to yourself: in the future, I need to at least try to answer one of somebody else's questions. This is how we grow and move so much faster. + +We also learned a key formatting technique: code blocks. Code blocks make your code more readable, and they help AIs to understand the content more easily. We'll cover more formatting techniques in future lessons. From 8c271de1b1016b23e9b09fff8fe2d5d8b219c7ea Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Fri, 22 Nov 2024 14:06:34 -0700 Subject: [PATCH 619/797] Equious updated courses/vyper-101/3-ai/5-workshop/+page.md. --- courses/vyper-101/3-ai/5-workshop/+page.md | 64 +++++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/courses/vyper-101/3-ai/5-workshop/+page.md b/courses/vyper-101/3-ai/5-workshop/+page.md index 789149836..a3621938d 100644 --- a/courses/vyper-101/3-ai/5-workshop/+page.md +++ b/courses/vyper-101/3-ai/5-workshop/+page.md @@ -1,3 +1,61 @@ ---- - title: Workshop - --- \ No newline at end of file +## Section 3: Prompting, Asking Questions, and Researching + +We've learned a lot about Vyper in the previous sections and now we are ready to put that knowledge to the test. We are going to do some work with AI. While AI can be a powerful tool, it is important to understand its limitations and use it wisely. It's crucial to be aware of situations where AI might be mistaken or give us incorrect information. + +For this workshop, we'll be testing out a few different AI tools and comparing their abilities. We'll be asking them some softball questions to gauge their understanding of smart contract development. + +**Our First Test:** + +Our first test will be to ask the AI to make a minimal Vyper contract. + +**Next, we'll ask the AI to explain the difference between a dynamic array and a fixed-sized array in Vyper.** + +**We can also test the AI's ability to understand Vyper code by asking it to explain a code snippet.** + +For example, we can ask: + +```python +@external +def add_person(name: String[100], favorite_number: uint256): + new_person = Person(self.list_of_people_index, favorite_number, name=name) + self.list_of_people[self.list_of_people_index] = new_person + self.list_of_numbers[self.list_of_people_index] = favorite_number + self.list_of_people_index += 1 + self.name_to_favorite_number[name] = favorite_number +``` + +**What does this code do?** + +**Finally, we'll test the AI's knowledge of Vyper security by asking it to analyze a code snippet and identify any potential vulnerabilities.** + +For example, we can ask: + +```python +send(OWNER, self.balance) +``` + +**Is this Vyper code safe?** + +We've learned that we need to use **raw call** in Vyper instead of **send** for security reasons. Let's ask the AI to tell us if our code is safe and suggest a better way to send funds: + +```python +send(OWNER, self.balance) +``` + +**What's a better way?** + +**Let's test the AI's understanding of how to use the `raw_call` method.** + +We can ask: + +```python +success = raw_call(self.owner, amount, gas=3000, value=amount) +``` + +**How can we use the `raw_call` method for sending Ether to prevent reentrancy issues?** + +**In the previous sections, we learned about the `raw_call` method.** It is a powerful tool in Vyper that allows us to interact with other contracts directly. But it is important to use the `raw_call` method cautiously and to be aware of the risks associated with it, specifically the risk of reentrancy. + +We are also going to test the AI to make sure it can provide secure solutions. + +**By testing these AI tools, we can gain a better understanding of how they work and how they can be used to help us write better Vyper contracts.** From 3decfbddc2c203d46eca8073fb572db6265dbf30 Mon Sep 17 00:00:00 2001 From: hunter <104146303+solhosty@users.noreply.github.com> Date: Sat, 23 Nov 2024 22:01:48 -0500 Subject: [PATCH 620/797] changes to mc101 --- .../1-python-in-updraft/{38-recap => 38-recap-pt-2}/+page.md | 0 courses/moccasin-101/2-web3py/{14-tx => 14-tx-pt-2}/+page.md | 0 courses/moccasin-101/2-web3py/{15-tx => 15-tx-pt-3}/+page.md | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename courses/moccasin-101/1-python-in-updraft/{38-recap => 38-recap-pt-2}/+page.md (100%) rename courses/moccasin-101/2-web3py/{14-tx => 14-tx-pt-2}/+page.md (100%) rename courses/moccasin-101/2-web3py/{15-tx => 15-tx-pt-3}/+page.md (100%) diff --git a/courses/moccasin-101/1-python-in-updraft/38-recap/+page.md b/courses/moccasin-101/1-python-in-updraft/38-recap-pt-2/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/38-recap/+page.md rename to courses/moccasin-101/1-python-in-updraft/38-recap-pt-2/+page.md diff --git a/courses/moccasin-101/2-web3py/14-tx/+page.md b/courses/moccasin-101/2-web3py/14-tx-pt-2/+page.md similarity index 100% rename from courses/moccasin-101/2-web3py/14-tx/+page.md rename to courses/moccasin-101/2-web3py/14-tx-pt-2/+page.md diff --git a/courses/moccasin-101/2-web3py/15-tx/+page.md b/courses/moccasin-101/2-web3py/15-tx-pt-3/+page.md similarity index 100% rename from courses/moccasin-101/2-web3py/15-tx/+page.md rename to courses/moccasin-101/2-web3py/15-tx-pt-3/+page.md From 413e6c000af92f60892b474328d9b167f3a08a85 Mon Sep 17 00:00:00 2001 From: hunter <104146303+solhosty@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:09:40 -0500 Subject: [PATCH 621/797] new: changes --- .../{9-types => 10-types}/+page.md | 0 .../{10-math => 11-math}/+page.md | 0 .../{11-more-math => 12-more-math}/+page.md | 0 .../{12-funcs => 13-funcs}/+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../{15-loops-2 => 16-loops-2}/+page.md | 0 .../{16-loops-3 => 17-loops-3}/+page.md | 0 .../{17-workshop => 18-workshop}/+page.md | 0 .../{18-recap => 19-recap}/+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../{29-local-py => 30-local-py}/+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../{38-recap-pt-2 => 39-recap-pt-2}/+page.md | 0 .../{6-type-hints => 7-type-hints}/+page.md | 0 .../{7-arrays => 8-arrays}/+page.md | 0 .../{8-inputs => 9-inputs}/+page.md | 0 .../{9-using-key => 10-using-key}/+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../4-mox-favs/{13-aaa => 14-aaa}/+page.md | 0 .../{14-fixtures => 15-fixtures}/+page.md | 0 .../{15-conftest => 16-conftest}/+page.md | 0 .../{16-type-hints => 17-type-hints}/+page.md | 0 .../+page.md | 0 .../{18-verify => 19-verify}/+page.md | 0 .../+page.md | 0 .../{20-eravm => 21-eravm}/+page.md | 0 .../+page.md | 0 .../{22-bridging => 23-bridging}/+page.md | 0 .../+page.md | 0 .../+page.md | 0 .../{25-tx-types => 26-tx-types}/+page.md | 0 .../{26-workshop => 27-workshop}/+page.md | 0 .../{27-recap => 28-recap}/+page.md | 0 .../4-mox-favs/{8-shell => 9-shell}/+page.md | 0 script.js | 62 +++++++++++++++++++ 54 files changed, 62 insertions(+) rename courses/moccasin-101/1-python-in-updraft/{9-types => 10-types}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{10-math => 11-math}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{11-more-math => 12-more-math}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{12-funcs => 13-funcs}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{13-conditionals => 14-conditionals}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{14-while-loops => 15-while-loops}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{15-loops-2 => 16-loops-2}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{16-loops-3 => 17-loops-3}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{17-workshop => 18-workshop}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{18-recap => 19-recap}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{19-dev-env-setup => 20-dev-env-setup}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{20-install-vscode-macos-linux => 21-install-vscode-macos-linux}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{21-install-wsl => 22-install-wsl}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{22-vscode-windows-install => 23-vscode-windows-install}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{23-vscode-windows-wsl-extension => 24-vscode-windows-wsl-extension}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{24-vscode-quickstart => 25-vscode-quickstart}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{25-install-python-macos => 26-install-python-macos}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{26-install-python-wsl-linux => 27-install-python-wsl-linux}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{27-vscode-quickstart-2 => 28-vscode-quickstart-2}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{28-mental-prep => 29-mental-prep}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{29-local-py => 30-local-py}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{30-python-shell => 31-python-shell}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{31-python-extensions-vscode => 32-python-extensions-vscode}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{32-our-first-python => 33-our-first-python}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{33-python-imports => 34-python-imports}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{34-installing-uv => 35-installing-uv}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{35-uv-python-version => 36-uv-python-version}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{36-adding-packages-uv => 37-adding-packages-uv}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{37-virtual-envs => 38-virtual-envs}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{38-recap-pt-2 => 39-recap-pt-2}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{6-type-hints => 7-type-hints}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{7-arrays => 8-arrays}/+page.md (100%) rename courses/moccasin-101/1-python-in-updraft/{8-inputs => 9-inputs}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{9-using-key => 10-using-key}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{10-account-cli => 11-account-cli}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{11-mox-testing => 12-mox-testing}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{12-testing-deploy-script => 13-testing-deploy-script}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{13-aaa => 14-aaa}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{14-fixtures => 15-fixtures}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{15-conftest => 16-conftest}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{16-type-hints => 17-type-hints}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{17-sepolia-deploy => 18-sepolia-deploy}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{18-verify => 19-verify}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{19-zksync-setup => 20-zksync-setup}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{20-eravm => 21-eravm}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{21-setting-up-zksync => 22-setting-up-zksync}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{22-bridging => 23-bridging}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{23-zksync-deploy => 24-zksync-deploy}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{24-zksync-contract-deployment => 25-zksync-contract-deployment}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{25-tx-types => 26-tx-types}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{26-workshop => 27-workshop}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{27-recap => 28-recap}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{8-shell => 9-shell}/+page.md (100%) create mode 100644 script.js diff --git a/courses/moccasin-101/1-python-in-updraft/9-types/+page.md b/courses/moccasin-101/1-python-in-updraft/10-types/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/9-types/+page.md rename to courses/moccasin-101/1-python-in-updraft/10-types/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/10-math/+page.md b/courses/moccasin-101/1-python-in-updraft/11-math/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/10-math/+page.md rename to courses/moccasin-101/1-python-in-updraft/11-math/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/11-more-math/+page.md b/courses/moccasin-101/1-python-in-updraft/12-more-math/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/11-more-math/+page.md rename to courses/moccasin-101/1-python-in-updraft/12-more-math/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/12-funcs/+page.md b/courses/moccasin-101/1-python-in-updraft/13-funcs/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/12-funcs/+page.md rename to courses/moccasin-101/1-python-in-updraft/13-funcs/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/13-conditionals/+page.md b/courses/moccasin-101/1-python-in-updraft/14-conditionals/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/13-conditionals/+page.md rename to courses/moccasin-101/1-python-in-updraft/14-conditionals/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/14-while-loops/+page.md b/courses/moccasin-101/1-python-in-updraft/15-while-loops/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/14-while-loops/+page.md rename to courses/moccasin-101/1-python-in-updraft/15-while-loops/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/15-loops-2/+page.md b/courses/moccasin-101/1-python-in-updraft/16-loops-2/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/15-loops-2/+page.md rename to courses/moccasin-101/1-python-in-updraft/16-loops-2/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/16-loops-3/+page.md b/courses/moccasin-101/1-python-in-updraft/17-loops-3/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/16-loops-3/+page.md rename to courses/moccasin-101/1-python-in-updraft/17-loops-3/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/17-workshop/+page.md b/courses/moccasin-101/1-python-in-updraft/18-workshop/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/17-workshop/+page.md rename to courses/moccasin-101/1-python-in-updraft/18-workshop/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/18-recap/+page.md b/courses/moccasin-101/1-python-in-updraft/19-recap/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/18-recap/+page.md rename to courses/moccasin-101/1-python-in-updraft/19-recap/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/19-dev-env-setup/+page.md b/courses/moccasin-101/1-python-in-updraft/20-dev-env-setup/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/19-dev-env-setup/+page.md rename to courses/moccasin-101/1-python-in-updraft/20-dev-env-setup/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/20-install-vscode-macos-linux/+page.md b/courses/moccasin-101/1-python-in-updraft/21-install-vscode-macos-linux/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/20-install-vscode-macos-linux/+page.md rename to courses/moccasin-101/1-python-in-updraft/21-install-vscode-macos-linux/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/21-install-wsl/+page.md b/courses/moccasin-101/1-python-in-updraft/22-install-wsl/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/21-install-wsl/+page.md rename to courses/moccasin-101/1-python-in-updraft/22-install-wsl/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/22-vscode-windows-install/+page.md b/courses/moccasin-101/1-python-in-updraft/23-vscode-windows-install/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/22-vscode-windows-install/+page.md rename to courses/moccasin-101/1-python-in-updraft/23-vscode-windows-install/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/23-vscode-windows-wsl-extension/+page.md b/courses/moccasin-101/1-python-in-updraft/24-vscode-windows-wsl-extension/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/23-vscode-windows-wsl-extension/+page.md rename to courses/moccasin-101/1-python-in-updraft/24-vscode-windows-wsl-extension/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/24-vscode-quickstart/+page.md b/courses/moccasin-101/1-python-in-updraft/25-vscode-quickstart/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/24-vscode-quickstart/+page.md rename to courses/moccasin-101/1-python-in-updraft/25-vscode-quickstart/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/25-install-python-macos/+page.md b/courses/moccasin-101/1-python-in-updraft/26-install-python-macos/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/25-install-python-macos/+page.md rename to courses/moccasin-101/1-python-in-updraft/26-install-python-macos/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/26-install-python-wsl-linux/+page.md b/courses/moccasin-101/1-python-in-updraft/27-install-python-wsl-linux/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/26-install-python-wsl-linux/+page.md rename to courses/moccasin-101/1-python-in-updraft/27-install-python-wsl-linux/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/27-vscode-quickstart-2/+page.md b/courses/moccasin-101/1-python-in-updraft/28-vscode-quickstart-2/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/27-vscode-quickstart-2/+page.md rename to courses/moccasin-101/1-python-in-updraft/28-vscode-quickstart-2/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/28-mental-prep/+page.md b/courses/moccasin-101/1-python-in-updraft/29-mental-prep/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/28-mental-prep/+page.md rename to courses/moccasin-101/1-python-in-updraft/29-mental-prep/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/29-local-py/+page.md b/courses/moccasin-101/1-python-in-updraft/30-local-py/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/29-local-py/+page.md rename to courses/moccasin-101/1-python-in-updraft/30-local-py/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/30-python-shell/+page.md b/courses/moccasin-101/1-python-in-updraft/31-python-shell/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/30-python-shell/+page.md rename to courses/moccasin-101/1-python-in-updraft/31-python-shell/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/31-python-extensions-vscode/+page.md b/courses/moccasin-101/1-python-in-updraft/32-python-extensions-vscode/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/31-python-extensions-vscode/+page.md rename to courses/moccasin-101/1-python-in-updraft/32-python-extensions-vscode/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/32-our-first-python/+page.md b/courses/moccasin-101/1-python-in-updraft/33-our-first-python/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/32-our-first-python/+page.md rename to courses/moccasin-101/1-python-in-updraft/33-our-first-python/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/33-python-imports/+page.md b/courses/moccasin-101/1-python-in-updraft/34-python-imports/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/33-python-imports/+page.md rename to courses/moccasin-101/1-python-in-updraft/34-python-imports/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/34-installing-uv/+page.md b/courses/moccasin-101/1-python-in-updraft/35-installing-uv/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/34-installing-uv/+page.md rename to courses/moccasin-101/1-python-in-updraft/35-installing-uv/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/35-uv-python-version/+page.md b/courses/moccasin-101/1-python-in-updraft/36-uv-python-version/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/35-uv-python-version/+page.md rename to courses/moccasin-101/1-python-in-updraft/36-uv-python-version/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/36-adding-packages-uv/+page.md b/courses/moccasin-101/1-python-in-updraft/37-adding-packages-uv/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/36-adding-packages-uv/+page.md rename to courses/moccasin-101/1-python-in-updraft/37-adding-packages-uv/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/37-virtual-envs/+page.md b/courses/moccasin-101/1-python-in-updraft/38-virtual-envs/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/37-virtual-envs/+page.md rename to courses/moccasin-101/1-python-in-updraft/38-virtual-envs/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/38-recap-pt-2/+page.md b/courses/moccasin-101/1-python-in-updraft/39-recap-pt-2/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/38-recap-pt-2/+page.md rename to courses/moccasin-101/1-python-in-updraft/39-recap-pt-2/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/6-type-hints/+page.md b/courses/moccasin-101/1-python-in-updraft/7-type-hints/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/6-type-hints/+page.md rename to courses/moccasin-101/1-python-in-updraft/7-type-hints/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/7-arrays/+page.md b/courses/moccasin-101/1-python-in-updraft/8-arrays/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/7-arrays/+page.md rename to courses/moccasin-101/1-python-in-updraft/8-arrays/+page.md diff --git a/courses/moccasin-101/1-python-in-updraft/8-inputs/+page.md b/courses/moccasin-101/1-python-in-updraft/9-inputs/+page.md similarity index 100% rename from courses/moccasin-101/1-python-in-updraft/8-inputs/+page.md rename to courses/moccasin-101/1-python-in-updraft/9-inputs/+page.md diff --git a/courses/moccasin-101/4-mox-favs/9-using-key/+page.md b/courses/moccasin-101/4-mox-favs/10-using-key/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/9-using-key/+page.md rename to courses/moccasin-101/4-mox-favs/10-using-key/+page.md diff --git a/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md b/courses/moccasin-101/4-mox-favs/11-account-cli/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/10-account-cli/+page.md rename to courses/moccasin-101/4-mox-favs/11-account-cli/+page.md diff --git a/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md b/courses/moccasin-101/4-mox-favs/12-mox-testing/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md rename to courses/moccasin-101/4-mox-favs/12-mox-testing/+page.md diff --git a/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md b/courses/moccasin-101/4-mox-favs/13-testing-deploy-script/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md rename to courses/moccasin-101/4-mox-favs/13-testing-deploy-script/+page.md diff --git a/courses/moccasin-101/4-mox-favs/13-aaa/+page.md b/courses/moccasin-101/4-mox-favs/14-aaa/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/13-aaa/+page.md rename to courses/moccasin-101/4-mox-favs/14-aaa/+page.md diff --git a/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md b/courses/moccasin-101/4-mox-favs/15-fixtures/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/14-fixtures/+page.md rename to courses/moccasin-101/4-mox-favs/15-fixtures/+page.md diff --git a/courses/moccasin-101/4-mox-favs/15-conftest/+page.md b/courses/moccasin-101/4-mox-favs/16-conftest/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/15-conftest/+page.md rename to courses/moccasin-101/4-mox-favs/16-conftest/+page.md diff --git a/courses/moccasin-101/4-mox-favs/16-type-hints/+page.md b/courses/moccasin-101/4-mox-favs/17-type-hints/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/16-type-hints/+page.md rename to courses/moccasin-101/4-mox-favs/17-type-hints/+page.md diff --git a/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md b/courses/moccasin-101/4-mox-favs/18-sepolia-deploy/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md rename to courses/moccasin-101/4-mox-favs/18-sepolia-deploy/+page.md diff --git a/courses/moccasin-101/4-mox-favs/18-verify/+page.md b/courses/moccasin-101/4-mox-favs/19-verify/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/18-verify/+page.md rename to courses/moccasin-101/4-mox-favs/19-verify/+page.md diff --git a/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md b/courses/moccasin-101/4-mox-favs/20-zksync-setup/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md rename to courses/moccasin-101/4-mox-favs/20-zksync-setup/+page.md diff --git a/courses/moccasin-101/4-mox-favs/20-eravm/+page.md b/courses/moccasin-101/4-mox-favs/21-eravm/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/20-eravm/+page.md rename to courses/moccasin-101/4-mox-favs/21-eravm/+page.md diff --git a/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md b/courses/moccasin-101/4-mox-favs/22-setting-up-zksync/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md rename to courses/moccasin-101/4-mox-favs/22-setting-up-zksync/+page.md diff --git a/courses/moccasin-101/4-mox-favs/22-bridging/+page.md b/courses/moccasin-101/4-mox-favs/23-bridging/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/22-bridging/+page.md rename to courses/moccasin-101/4-mox-favs/23-bridging/+page.md diff --git a/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md b/courses/moccasin-101/4-mox-favs/24-zksync-deploy/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md rename to courses/moccasin-101/4-mox-favs/24-zksync-deploy/+page.md diff --git a/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md b/courses/moccasin-101/4-mox-favs/25-zksync-contract-deployment/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md rename to courses/moccasin-101/4-mox-favs/25-zksync-contract-deployment/+page.md diff --git a/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md b/courses/moccasin-101/4-mox-favs/26-tx-types/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/25-tx-types/+page.md rename to courses/moccasin-101/4-mox-favs/26-tx-types/+page.md diff --git a/courses/moccasin-101/4-mox-favs/26-workshop/+page.md b/courses/moccasin-101/4-mox-favs/27-workshop/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/26-workshop/+page.md rename to courses/moccasin-101/4-mox-favs/27-workshop/+page.md diff --git a/courses/moccasin-101/4-mox-favs/27-recap/+page.md b/courses/moccasin-101/4-mox-favs/28-recap/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/27-recap/+page.md rename to courses/moccasin-101/4-mox-favs/28-recap/+page.md diff --git a/courses/moccasin-101/4-mox-favs/8-shell/+page.md b/courses/moccasin-101/4-mox-favs/9-shell/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/8-shell/+page.md rename to courses/moccasin-101/4-mox-favs/9-shell/+page.md diff --git a/script.js b/script.js new file mode 100644 index 000000000..0843784f2 --- /dev/null +++ b/script.js @@ -0,0 +1,62 @@ +const fs = require('fs'); +const path = require('path'); + +function renumberLessonsFromPoint(basePath, section, startNumber) { + const sectionPath = path.join(basePath, section); + + // Get all lesson directories and sort them numerically + const lessons = fs.readdirSync(sectionPath) + .filter(dir => { + const fullPath = path.join(sectionPath, dir); + return fs.statSync(fullPath).isDirectory() && /^\d+/.test(dir); + }) + .sort((a, b) => { + const numA = parseInt(a.split('-')[0]); + const numB = parseInt(b.split('-')[0]); + return numA - numB; + }); + + // Find the index of the second occurrence of startNumber + let startIndex = -1; + let foundFirst = false; + for (let i = 0; i < lessons.length; i++) { + const num = parseInt(lessons[i].split('-')[0]); + if (num === startNumber) { + if (foundFirst) { + startIndex = i; + break; + } + foundFirst = true; + } + } + + if (startIndex === -1) { + console.log(`No second occurrence of lesson ${startNumber} found.`); + return; + } + + // Rename in reverse order starting from the end of the array + for (let i = lessons.length - 1; i >= startIndex; i--) { + const lesson = lessons[i]; + const currentNum = parseInt(lesson.split('-')[0]); + const restOfName = lesson.substring(lesson.indexOf('-')); + const newNum = currentNum + 1; + const newName = `${newNum}${restOfName}`; + + const oldPath = path.join(sectionPath, lesson); + const newPath = path.join(sectionPath, newName); + + fs.renameSync(oldPath, newPath); + console.log(`Renamed: ${lesson} -> ${newName}`); + } +} + +const basePath = 'courses/moccasin-101'; + +// Renumber lessons after the second '6' in section 1 +console.log('\nRenumbering Python section lessons...'); +renumberLessonsFromPoint(basePath, '1-python-in-updraft', 6); + +// Renumber lessons after the first '8' in section 4 +console.log('\nRenumbering Mox Favs section lessons...'); +renumberLessonsFromPoint(basePath, '4-mox-favs', 8); \ No newline at end of file From 5e7c9760fb310e72c1eed1848b2431271a8280ff Mon Sep 17 00:00:00 2001 From: hunter <104146303+solhosty@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:10:21 -0500 Subject: [PATCH 622/797] new: changes --- script.js | 62 ------------------------------------------------------- 1 file changed, 62 deletions(-) delete mode 100644 script.js diff --git a/script.js b/script.js deleted file mode 100644 index 0843784f2..000000000 --- a/script.js +++ /dev/null @@ -1,62 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -function renumberLessonsFromPoint(basePath, section, startNumber) { - const sectionPath = path.join(basePath, section); - - // Get all lesson directories and sort them numerically - const lessons = fs.readdirSync(sectionPath) - .filter(dir => { - const fullPath = path.join(sectionPath, dir); - return fs.statSync(fullPath).isDirectory() && /^\d+/.test(dir); - }) - .sort((a, b) => { - const numA = parseInt(a.split('-')[0]); - const numB = parseInt(b.split('-')[0]); - return numA - numB; - }); - - // Find the index of the second occurrence of startNumber - let startIndex = -1; - let foundFirst = false; - for (let i = 0; i < lessons.length; i++) { - const num = parseInt(lessons[i].split('-')[0]); - if (num === startNumber) { - if (foundFirst) { - startIndex = i; - break; - } - foundFirst = true; - } - } - - if (startIndex === -1) { - console.log(`No second occurrence of lesson ${startNumber} found.`); - return; - } - - // Rename in reverse order starting from the end of the array - for (let i = lessons.length - 1; i >= startIndex; i--) { - const lesson = lessons[i]; - const currentNum = parseInt(lesson.split('-')[0]); - const restOfName = lesson.substring(lesson.indexOf('-')); - const newNum = currentNum + 1; - const newName = `${newNum}${restOfName}`; - - const oldPath = path.join(sectionPath, lesson); - const newPath = path.join(sectionPath, newName); - - fs.renameSync(oldPath, newPath); - console.log(`Renamed: ${lesson} -> ${newName}`); - } -} - -const basePath = 'courses/moccasin-101'; - -// Renumber lessons after the second '6' in section 1 -console.log('\nRenumbering Python section lessons...'); -renumberLessonsFromPoint(basePath, '1-python-in-updraft', 6); - -// Renumber lessons after the first '8' in section 4 -console.log('\nRenumbering Mox Favs section lessons...'); -renumberLessonsFromPoint(basePath, '4-mox-favs', 8); \ No newline at end of file From 38563412a6245971d9f54c3bbd297ade32693a42 Mon Sep 17 00:00:00 2001 From: hunter <104146303+solhosty@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:24:31 -0500 Subject: [PATCH 623/797] new --- .../4-mox-favs/{11-account-cli => 10-account-cli}/+page.md | 0 .../4-mox-favs/{12-mox-testing => 11-mox-testing}/+page.md | 0 .../+page.md | 0 courses/moccasin-101/4-mox-favs/{14-aaa => 13-aaa}/+page.md | 0 .../moccasin-101/4-mox-favs/{15-fixtures => 14-fixtures}/+page.md | 0 .../moccasin-101/4-mox-favs/{16-conftest => 15-conftest}/+page.md | 0 .../4-mox-favs/{17-type-hints => 16-type-hints}/+page.md | 0 .../4-mox-favs/{18-sepolia-deploy => 17-sepolia-deploy}/+page.md | 0 courses/moccasin-101/4-mox-favs/{19-verify => 18-verify}/+page.md | 0 .../4-mox-favs/{20-zksync-setup => 19-zksync-setup}/+page.md | 0 courses/moccasin-101/4-mox-favs/{21-eravm => 20-eravm}/+page.md | 0 .../{22-setting-up-zksync => 21-setting-up-zksync}/+page.md | 0 .../moccasin-101/4-mox-favs/{23-bridging => 22-bridging}/+page.md | 0 .../4-mox-favs/{24-zksync-deploy => 23-zksync-deploy}/+page.md | 0 .../+page.md | 0 .../moccasin-101/4-mox-favs/{26-tx-types => 25-tx-types}/+page.md | 0 .../moccasin-101/4-mox-favs/{27-workshop => 26-workshop}/+page.md | 0 courses/moccasin-101/4-mox-favs/{28-recap => 27-recap}/+page.md | 0 .../4-mox-favs/{8-encrypt-key => 7-encrypt-key}/+page.md | 0 courses/moccasin-101/4-mox-favs/{9-shell => 8-shell}/+page.md | 0 .../4-mox-favs/{10-using-key => 9-using-key}/+page.md | 0 21 files changed, 0 insertions(+), 0 deletions(-) rename courses/moccasin-101/4-mox-favs/{11-account-cli => 10-account-cli}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{12-mox-testing => 11-mox-testing}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{13-testing-deploy-script => 12-testing-deploy-script}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{14-aaa => 13-aaa}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{15-fixtures => 14-fixtures}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{16-conftest => 15-conftest}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{17-type-hints => 16-type-hints}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{18-sepolia-deploy => 17-sepolia-deploy}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{19-verify => 18-verify}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{20-zksync-setup => 19-zksync-setup}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{21-eravm => 20-eravm}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{22-setting-up-zksync => 21-setting-up-zksync}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{23-bridging => 22-bridging}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{24-zksync-deploy => 23-zksync-deploy}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{25-zksync-contract-deployment => 24-zksync-contract-deployment}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{26-tx-types => 25-tx-types}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{27-workshop => 26-workshop}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{28-recap => 27-recap}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{8-encrypt-key => 7-encrypt-key}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{9-shell => 8-shell}/+page.md (100%) rename courses/moccasin-101/4-mox-favs/{10-using-key => 9-using-key}/+page.md (100%) diff --git a/courses/moccasin-101/4-mox-favs/11-account-cli/+page.md b/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/11-account-cli/+page.md rename to courses/moccasin-101/4-mox-favs/10-account-cli/+page.md diff --git a/courses/moccasin-101/4-mox-favs/12-mox-testing/+page.md b/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/12-mox-testing/+page.md rename to courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md diff --git a/courses/moccasin-101/4-mox-favs/13-testing-deploy-script/+page.md b/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/13-testing-deploy-script/+page.md rename to courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md diff --git a/courses/moccasin-101/4-mox-favs/14-aaa/+page.md b/courses/moccasin-101/4-mox-favs/13-aaa/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/14-aaa/+page.md rename to courses/moccasin-101/4-mox-favs/13-aaa/+page.md diff --git a/courses/moccasin-101/4-mox-favs/15-fixtures/+page.md b/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/15-fixtures/+page.md rename to courses/moccasin-101/4-mox-favs/14-fixtures/+page.md diff --git a/courses/moccasin-101/4-mox-favs/16-conftest/+page.md b/courses/moccasin-101/4-mox-favs/15-conftest/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/16-conftest/+page.md rename to courses/moccasin-101/4-mox-favs/15-conftest/+page.md diff --git a/courses/moccasin-101/4-mox-favs/17-type-hints/+page.md b/courses/moccasin-101/4-mox-favs/16-type-hints/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/17-type-hints/+page.md rename to courses/moccasin-101/4-mox-favs/16-type-hints/+page.md diff --git a/courses/moccasin-101/4-mox-favs/18-sepolia-deploy/+page.md b/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/18-sepolia-deploy/+page.md rename to courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md diff --git a/courses/moccasin-101/4-mox-favs/19-verify/+page.md b/courses/moccasin-101/4-mox-favs/18-verify/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/19-verify/+page.md rename to courses/moccasin-101/4-mox-favs/18-verify/+page.md diff --git a/courses/moccasin-101/4-mox-favs/20-zksync-setup/+page.md b/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/20-zksync-setup/+page.md rename to courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md diff --git a/courses/moccasin-101/4-mox-favs/21-eravm/+page.md b/courses/moccasin-101/4-mox-favs/20-eravm/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/21-eravm/+page.md rename to courses/moccasin-101/4-mox-favs/20-eravm/+page.md diff --git a/courses/moccasin-101/4-mox-favs/22-setting-up-zksync/+page.md b/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/22-setting-up-zksync/+page.md rename to courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md diff --git a/courses/moccasin-101/4-mox-favs/23-bridging/+page.md b/courses/moccasin-101/4-mox-favs/22-bridging/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/23-bridging/+page.md rename to courses/moccasin-101/4-mox-favs/22-bridging/+page.md diff --git a/courses/moccasin-101/4-mox-favs/24-zksync-deploy/+page.md b/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/24-zksync-deploy/+page.md rename to courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md diff --git a/courses/moccasin-101/4-mox-favs/25-zksync-contract-deployment/+page.md b/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/25-zksync-contract-deployment/+page.md rename to courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md diff --git a/courses/moccasin-101/4-mox-favs/26-tx-types/+page.md b/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/26-tx-types/+page.md rename to courses/moccasin-101/4-mox-favs/25-tx-types/+page.md diff --git a/courses/moccasin-101/4-mox-favs/27-workshop/+page.md b/courses/moccasin-101/4-mox-favs/26-workshop/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/27-workshop/+page.md rename to courses/moccasin-101/4-mox-favs/26-workshop/+page.md diff --git a/courses/moccasin-101/4-mox-favs/28-recap/+page.md b/courses/moccasin-101/4-mox-favs/27-recap/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/28-recap/+page.md rename to courses/moccasin-101/4-mox-favs/27-recap/+page.md diff --git a/courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md b/courses/moccasin-101/4-mox-favs/7-encrypt-key/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/8-encrypt-key/+page.md rename to courses/moccasin-101/4-mox-favs/7-encrypt-key/+page.md diff --git a/courses/moccasin-101/4-mox-favs/9-shell/+page.md b/courses/moccasin-101/4-mox-favs/8-shell/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/9-shell/+page.md rename to courses/moccasin-101/4-mox-favs/8-shell/+page.md diff --git a/courses/moccasin-101/4-mox-favs/10-using-key/+page.md b/courses/moccasin-101/4-mox-favs/9-using-key/+page.md similarity index 100% rename from courses/moccasin-101/4-mox-favs/10-using-key/+page.md rename to courses/moccasin-101/4-mox-favs/9-using-key/+page.md From daf293d529cff2eb4fd25ef55b2b06b0866ac9f5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 05:58:06 -0700 Subject: [PATCH 624/797] Equious updated courses/moccasin-101/1-python-in-updraft/1-intro/+page.md. --- .../1-python-in-updraft/1-intro/+page.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/1-intro/+page.md b/courses/moccasin-101/1-python-in-updraft/1-intro/+page.md index b7e64e913..4a548e331 100644 --- a/courses/moccasin-101/1-python-in-updraft/1-intro/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/1-intro/+page.md @@ -1,3 +1,13 @@ ---- - title: Intro - --- \ No newline at end of file +## Moccasin Fundamentals + +Welcome back to the Moccasin and Python Fundamental Section, where you're going to learn how to build and deploy even more advanced Vyper smart contracts, using some really powerful Python tools. The main tool that we're going to be working with is this tool called Moccasin, which is a smart contract developer framework. We're going to be teaching you the same tools that the pros use. So, buckle up and let's get froggy! + +Remix is a phenomenal tool, but pretty soon we're going to be moving over to this tool called Moccasin, which is going to give us a more professional setup for deploying and testing and working with our smart contracts. + +However, before we do that, we're actually going to teach you how to do a lot of the basics with raw Python. With no frameworks, no nothing, just Python and Vyper, that's it. And this is incredibly helpful for you as a learner because you will learn what's going on under the hood of Moccasin, and then additionally, if ever you want to do something yourself, do something manually, you can come back and just do it right in Python. + +Additionally, you will also learn a lot of the basics of Python here as well, and how we work with Python in Updraft. I'm going to be teaching you a lot of modern best practices for working with Python that I think are going to help you in the long run, help you really understand what's going on that a lot of other Python tutorials kind of skip over sometimes. And similar to everything that we've been working with so far, all of the code for all of our examples are going to be in the GitHub repo associated with this course. + +Now, you might be asking a pretty astute question here. You might be saying, "Hey, uh Patrick, why are we even going to this other tool? Why are we even going to Moccasin? Remix is working great. Like, I'm able to deploy contracts, what are you talking about?" Here's what the issue is. We had to do a lot of manual work to do anything with Remix. If I wanted to deploy this contract, I would have to go okay, first, I got to go compile it. And, I got to wait for the compile. Okay, cool. And then, I go to the run tab. Well, let's say I didn't have this contract in here. I have to okay I got to switch to the correct network that I want to be at. Okay, cool, I got to Okay, let's grab the price feed. Let's okay, then I deployed it. Um let me look in here, uh hoops, I I made a mistake. Okay, I got to un- delete that. I got to come in here you know make my change whatever it is. I got to come back. I got to re- compile. I got to go back, hit the deploy, and then I got to paste this back in or uh I don't have the write address, paste it in. Okay, maybe I maybe I make a new function or something, okay, I want to see if it actually works. I go re- deploy, I go check it works. After some time, let's say you have a 1,000 different functions and you want to test that they're all still working, when you go back and you make some small change, you don't want to have to press every single button. Press deploy. Press get contract. Make sure all your new functions are working. It's going to take you forever to get anything done in Remix. So, we want a framework that automates all of this for us, and so that we can make sure we test every single part of our code base in a reproducible manner. Smart contracts are fickle. If you have a bug, it can be a disaster. It can ruin your entire smart contract. So, we want a way to interact with test, deploy, script, and all of that stuff in a more programmatic autonomous way, rather than us manually clicking buttons. In Moccasin, we can do all of that in one command, in one click. + +Like I said, we're going to be teaching you Python and Titanaboa first, and then we're going to be moving over to Moccasin. From 45ddd66602073371ecd29115a3f98c1f263cf04f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:01:00 -0700 Subject: [PATCH 625/797] Equious updated courses/moccasin-101/1-python-in-updraft/10-types/+page.md. --- .../1-python-in-updraft/10-types/+page.md | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/10-types/+page.md b/courses/moccasin-101/1-python-in-updraft/10-types/+page.md index c6210ebf1..41683c5ac 100644 --- a/courses/moccasin-101/1-python-in-updraft/10-types/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/10-types/+page.md @@ -1,3 +1,61 @@ ---- - title: Types - --- \ No newline at end of file +## Types + +We can convert types from one to another using something called casting. + +For example, let's say we had this: + +```python +year = "2025" +``` + +This is technically a string because it has quotes around it. If we got rid of the quotes, it would be a number, or an int. + +But, since it has quotes, it's a string. + +What if we tried to add 25 to this year number here? We can try this: + +```python +year + 25 +``` + +This will result in an error: + +```bash +TypeError: can only concatenate str (not "int") to str +``` + +Since 25 is an int, and year is a string, Python can't perform the addition. + +To fix this, we can typecast the year variable to an int: + +```python +year_as_int = int(year) +``` + +Now, we can add 25 to the year variable: + +```python +year_as_int + 25 +``` + +This will result in 2050. + +We can also convert the result back into a string using the `str()` function: + +```python +year_string = str(year_as_int + 25) +``` + +Now, we can print the string: + +```python +print(year_string + " is 25 years after 2025") +``` + +This will print the string: + +```bash +2050 is 25 years after 2025 +``` + +This is how we can convert types in Python using casting. From 37960acc4040d497751fac421f204963c0939a9e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:01:30 -0700 Subject: [PATCH 626/797] Equious updated courses/moccasin-101/1-python-in-updraft/11-math/+page.md. --- .../1-python-in-updraft/11-math/+page.md | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/11-math/+page.md b/courses/moccasin-101/1-python-in-updraft/11-math/+page.md index d246d700c..56e0ad0f0 100644 --- a/courses/moccasin-101/1-python-in-updraft/11-math/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/11-math/+page.md @@ -1,3 +1,37 @@ ---- - title: Math - --- \ No newline at end of file +## Math in Python + +We can perform simple mathematical calculations in Python. Let's look at addition, subtraction, multiplication, and division. + +### Addition + +```python +print("add") +my_number = 5 + 5 +print(my_number) +``` + +### Subtraction + +```python +print("subtract") +my_number = 5 - 5 +print(my_number) +``` + +### Multiplication + +```python +print("multiply") +my_number = 5 * 5 +print(my_number) +``` + +### Division + +```python +print("divide") +my_number = 7 / 2 +print(my_number) +``` + +We can run the script and view the results. From 36b7c457aeda37a93f17215dc20709bbc4197c3f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:01:56 -0700 Subject: [PATCH 627/797] Equious updated courses/moccasin-101/1-python-in-updraft/12-more-math/+page.md. --- .../1-python-in-updraft/12-more-math/+page.md | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/12-more-math/+page.md b/courses/moccasin-101/1-python-in-updraft/12-more-math/+page.md index 52de64c11..b177ce95d 100644 --- a/courses/moccasin-101/1-python-in-updraft/12-more-math/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/12-more-math/+page.md @@ -1,3 +1,30 @@ ---- - title: More Math - --- \ No newline at end of file +## Advanced Math + +In this lesson, we're going to take a look at advanced math operations in Python. + +We can do something called integer division. + +```python +print("integer division") +my_number = 7 // 2 +print(my_number) +``` +Integer division will round down our division to the nearest whole number. + +We can also do something called modulo. This will return the remainder of our division. + +```python +print("modulo") +my_number = 7 % 2 +print(my_number) +``` +For example, 7 divided by 2 is 3 with a remainder of 1. + +Finally, we can perform exponent operations. + +```python +print("exponents") +my_number = 2 ** 3 +print(my_number) +``` +The double multiply symbol means raise to the power of. So, 2 raised to the power of 3 is 8. From 78eb0bae9839894fc84e1cc9c9feced23efa904e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:02:22 -0700 Subject: [PATCH 628/797] Equious updated courses/moccasin-101/1-python-in-updraft/13-funcs/+page.md. --- .../1-python-in-updraft/13-funcs/+page.md | 101 +++++++++++++++++- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/13-funcs/+page.md b/courses/moccasin-101/1-python-in-updraft/13-funcs/+page.md index 125b3fa6b..9aadf6664 100644 --- a/courses/moccasin-101/1-python-in-updraft/13-funcs/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/13-funcs/+page.md @@ -1,3 +1,98 @@ ---- - title: Funcs - --- \ No newline at end of file +## Functions / Methods: The "def" Keyword + +We'll create a new section and talk about functions. Functions can be written by typing out the "def" keyword. A function is a self-contained, reusable chunk of logic. + +Let's create a function that will print "hi" two times. + +```python +def print_hi_two_times(): + print("hi") + print("hi") +``` + +We can create a function by typing the "def" keyword, then give our function a name, for example, "print_hi_two_times". Open and close parentheses, and then a colon. We'll explain what the parentheses are for in a moment. + +```python +def print_hi_two_times(): + print("hi") + print("hi") +``` + +Now, hit enter and Google Colab will indent the function for us. The line doesn't start at the beginning of the line, it's tabbed in. This is because Python is an indentation-based language. We need to indent to type the body of the function. + +```python +def print_hi_two_times(): + print("hi") + print("hi") +``` + +So, the function name is "print_hi_two_times", and anything that's indented is considered part of this function. + +```python +def print_hi_two_times(): + print("hi") + print("hi") +``` + +If we print "hi" and "hi" again, but the second "hi" isn't indented, Python will see that it's not part of the function. Indenting both lines will make them part of the function. We now have two "hi" print statements. + +```python +def print_hi_two_times(): + print("hi") + print("hi") +``` + +If we run the cell, nothing happens. We don't see any "hi"s printed out. To run the function, we can copy and paste it, adding parentheses, and then run the cell. + +```python +print_hi_two_times() +``` + +This will print "hi" twice. The line with "print_hi_two_times()" is considered an invocation, or a calling of the function. The definition of the function is "def print_hi_two_times():", where we tell Python what to do when somebody calls the function. The line with "print_hi_two_times()" is where we call the function. We're essentially saying, "Hey, do this thing." + +We can also create functions that take parameters. + +```python +def print_some_word(my_word): + print(my_word) +``` + +This function takes a "my_word" parameter and prints it out. We can call this function, passing in the word "miss you mom!" + +```python +print_some_word("miss you mom!") +``` + +This will print out "miss you mom!". The "miss you mom!" is passed in as a parameter and assigned to the "my_word" variable, which is then printed. + +We can also do more interesting things with math. + +```python +def add_six(my_number): + print(my_number + 6) +``` + +This function takes a "my_number" parameter, adds six to it, and then prints the result. + +```python +add_six(10) +``` + +We can call the function, passing in 10, which should print out 16. Running the cell confirms this. + +We can also create functions that take multiple parameters. + +```python +def add_together(my_first_number, my_second_number): + print(my_first_number + my_second_number) +``` + +This function takes two parameters, adds them together, and prints the result. + +```python +add_together(10, 20) +``` + +Calling the function with 10 and 20 as parameters should print out 30. Running the cell confirms this. + +This concludes the lesson on functions. From 1c228cc24c0ce5299f079d8fcf56182597f393b8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:02:50 -0700 Subject: [PATCH 629/797] Equious updated courses/moccasin-101/1-python-in-updraft/14-conditionals/+page.md. --- .../14-conditionals/+page.md | 120 +++++++++++++++++- 1 file changed, 117 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/14-conditionals/+page.md b/courses/moccasin-101/1-python-in-updraft/14-conditionals/+page.md index 1d57c9ca3..37ab68d48 100644 --- a/courses/moccasin-101/1-python-in-updraft/14-conditionals/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/14-conditionals/+page.md @@ -1,3 +1,117 @@ ---- - title: Conditionals - --- \ No newline at end of file +## Conditionals (if/else Statements) + +In Python, we can use `if` / `else` statements, also known as conditionals. + +Let�s create a new chunk of code. +```python +if 7 > 5: + print("7 is greater than 5") +``` + +We can run this code as it is. + +```bash +7 is greater than 5 +``` + +Now, let�s try seeing if the numbers are equal: + +```python +if 7 == 5: + print("7 is greater than 5") +``` + +If we run this code, nothing will print because seven is not equal to five. Notice we are using a double equals sign (`==`) here and not a single equals sign (`=`). A single equals sign is used to set a value. + +To check if they are actually equal, we will use a double equals: + +```python +if 7 == 5: + print("7 is greater than 5") +``` + +If we run this, nothing gets printed because seven is not equal to five. + +Just like with functions, we have some indentation here. If we remove the indentation, Python will give us an error. + +```python +if 7 == 5: +print("7 is greater than 5") +``` + +```bash +File "", line 3 + print("7 is greater than 5") + ^ +IndentationError: expected an indented block after 'if' statement on line 2 +``` + +Python is telling us that it expected an indentation block after the if statement. + +So we will go back, indent it and run it: + +```python +if 7 == 5: + print("7 is greater than 5") +``` + +It does not print out. If we change the code to check if seven is greater than five: + +```python +if 7 > 5: + print("7 is greater than 5") +``` + +When we run it, we see this printed to the console: + +```bash +7 is greater than 5 +``` + +We can also use an `else` statement. + +```python +if 7 > 5: + print("7 is greater than 5") +else: + print("5 is greater than 7") +``` + +If we run this line, it will still print out �7 is greater than 5�. This is because what we are saying is if 7 is greater than 5, print out �7 is greater than 5�. Otherwise, print out �5 is greater than 7�. + +If we were to flip the sign around to say if 7 is less than 5: + +```python +if 7 < 5: + print("7 is greater than 5") +else: + print("5 is greater than 7") +``` + +Running this code, we see the following output: + +```bash +5 is greater than 7 +``` + +This is because the `if` condition is false and so the `else` block is executed. + +This is kind of similar to saying if true do this: + +```python +if True: + print("7 is greater than 5") +else: + print("5 is greater than 7") +``` + +And if false, don't do this, do the else. + +```python +if False: + print("7 is greater than 5") +else: + print("5 is greater than 7") +``` + +If that is a little confusing, don�t worry about it for now. It will make sense to you the more you work with conditionals. From f0dab4de9a2a90b02ca0b530ad73f60c7e4d7cd6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:03:16 -0700 Subject: [PATCH 630/797] Equious updated courses/moccasin-101/1-python-in-updraft/15-while-loops/+page.md. --- .../15-while-loops/+page.md | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/15-while-loops/+page.md b/courses/moccasin-101/1-python-in-updraft/15-while-loops/+page.md index 9e54beace..7afd80392 100644 --- a/courses/moccasin-101/1-python-in-updraft/15-while-loops/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/15-while-loops/+page.md @@ -1,3 +1,61 @@ ---- - title: While Loops - --- \ No newline at end of file +## `while` Loops + +We'll learn about `while` loops. + +Let's say we wanted to print out the word "hi" a thousand times. It would be incredibly tedious to write "hi" a thousand times. + +There sure is! In Python, we can do repetitive tasks with something called loops. And, there are many different types of loops that we can use. + +The first one is going to be the `while` loop. + +Let's say we have a variable called `my_number` that starts at 0. So, `my_number` is set to 0. + +We can then do something like: + +```python +my_number = 0 +while my_number < 3: + print("My number is " + str(my_number)) + my_number = my_number + 1 +print("Done!") +``` + +And, as long as `my_number` stays less than 3, Python will just keep looping and running this. + +Now, don't hit the play button yet, because Python would technically run into an infinite loop because `my_number` would always be less than 3, since `my_number` is never incremented. + +So, first we'll say: + +```python +print("My number is " + str(my_number)) +``` + +Then, we'll say: + +```python +my_number = my_number + 1 +``` + +And, this is how every single time we run this loop, we add 1 to the number here. + +We will then print out "Done!". + +Notice again that this `print("Done!")` is outside of the `while` loop because it's not indented. + +So, if we hit play here, and scroll down, you'll see we get "My number is 0", "My number is 1", "My number is 2", and then, "Done!". + +You see it stops because once `my_number` is set to 3, `my_number` is no longer strictly less than 3, and it will execute. + +So, we can even kind of visualize this a little better by saying, okay, `my_number` starts off as 0. Then, we enter the loop. `My_number` is 0, so it says, "while 0 is less than 3", 0 is less than 3, so it goes into the loop. Print out "My number is " Again, it's 0, so we would print out 0. And, then `my_number` equals 0 + 1, so then, `my_number` would be set to 1. + +So, "while 1 is less than 3" Print "My number is 1". And, then `my_number` equals 1 + 1, which is now 2. So, then `my_number` is then set to 2. + +And, we would read it as "while 2 is less than 3" which it is. We would print out "My number is 2". `my_number` equals 2 + 1, so `my_number` now equals 3. + +Then, we would hit "while 3 is less than 3." Now, 3 is not less than 3, 3 is equal to 3, so it will skip executing the loop and just print out the "Done!". + +So, that's how you can think of walking through these `while` loops here. + +And, let's just revert everything back and we'll hit play. + +And, boom. From 40650b98bcfb22e2e02c5e62692f4676c0539152 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:03:44 -0700 Subject: [PATCH 631/797] Equious updated courses/moccasin-101/1-python-in-updraft/16-loops-2/+page.md. --- .../1-python-in-updraft/16-loops-2/+page.md | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/16-loops-2/+page.md b/courses/moccasin-101/1-python-in-updraft/16-loops-2/+page.md index 1633a4fcb..19ffb90df 100644 --- a/courses/moccasin-101/1-python-in-updraft/16-loops-2/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/16-loops-2/+page.md @@ -1,3 +1,33 @@ ---- - title: Loops 2 - --- \ No newline at end of file +## Loops: For-Range + +We've learned about while loops, but there are other ways to loop, too. Let's look at a different kind of loop called a for-range loop. + +We previously used the code: +```python +my_number = 0 +while my_number < 3: + print("My number is " + str(my_number)) + my_number = my_number + 1 +print("Done!") +``` + +We can rewrite this using a for-range loop, which is more concise than the while loop: +```python +for number in range(3): + print("My number is " + str(number)) +print("Done!") +``` + +The `for` keyword lets Python know that we are going to use a for-range loop. The loop will iterate over the numbers in `range(3)` � that is, the numbers 0, 1, and 2. For each number, it will execute the code in the loop block (which prints "My number is" plus the number). Let's run this code and see what happens. + +We can see the output: +``` +My number is 0 +My number is 1 +My number is 2 +Done! +``` + +So, `range(3)` says to loop from 0 to 2. We can see the result in the output: the code prints out "My number is" plus the number 0, then 1, then 2. + +This is a much more concise way to accomplish the same result as the while loop we used before. In the for-range loop, we don't need to worry about incrementing a counter variable because Python does that for us automatically. From 292a8975aea8cca61cf319e60f818d0075cd8e03 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:04:10 -0700 Subject: [PATCH 632/797] Equious updated courses/moccasin-101/1-python-in-updraft/17-loops-3/+page.md. --- .../1-python-in-updraft/17-loops-3/+page.md | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/17-loops-3/+page.md b/courses/moccasin-101/1-python-in-updraft/17-loops-3/+page.md index 3e226d5ca..fb312eb92 100644 --- a/courses/moccasin-101/1-python-in-updraft/17-loops-3/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/17-loops-3/+page.md @@ -1,3 +1,51 @@ ---- - title: Loops 3 - --- \ No newline at end of file +## Loops: For-Each + +We've looked at `while` loops and `for` loops. Let's look at the `for-each` loop. + +Let's say we have a list: + +```python +my_list = [0, 1, 2] +``` + +We could loop through all the elements in this list by saying `for` each element `in` my list: + +```python +for element in my_list: + print("My number is " + str(element)) + print("Done!") +``` + +We can see this is going to loop through each element in the list. So if we hit play we see `My number is 0`, `My number is 1`, and `My number is 2`. + +Let's add some more numbers to our list: + +```python +my_list = [0, 1, 2, 3, 5, 7] +``` + +And then hit play. Now, we see our original numbers 0, 1, 2, and then our new numbers 3, 5, and 7. + +Now, let's look at how to use a loop for repeating a specific task a large number of times. + +Let's say we wanted to print "Hi" 1,000 times. It would be tedious to write: + +```python +print("Hi") +print("Hi") +print("Hi") +``` + +1,000 times. Is there a better way? + +There sure is! In Python, we can do repetitive tasks with something called "loops". + +We could do something as simple as `for` number `in` range 1,000 print: + +```python +for number in range(1000): + print("My number is " + str(number)) + print("Done!") +``` + +I recommend you don't do this, because you're going to get a massive cell that's outputted here. You know what, screw it. Let's try it. `For` number `in` range 1,000. Let's go ahead and hit play. If we scroll down we see just a ton of numbers. Some of this was even truncated and we'd have to scroll for a long time. But you can see it's printing out every single number between 0 and 999. So let's leave this as three so it's a lot more digestible. From 6224f49ec271f0d50cfdd9c29a87576cddc3240c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:04:38 -0700 Subject: [PATCH 633/797] Equious updated courses/moccasin-101/1-python-in-updraft/18-workshop/+page.md. --- .../1-python-in-updraft/18-workshop/+page.md | 55 ++++++++++++++++++- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/18-workshop/+page.md b/courses/moccasin-101/1-python-in-updraft/18-workshop/+page.md index 789149836..d32b555c1 100644 --- a/courses/moccasin-101/1-python-in-updraft/18-workshop/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/18-workshop/+page.md @@ -1,3 +1,52 @@ ---- - title: Workshop - --- \ No newline at end of file +## What Year Function Workshop + +This workshop will walk you through creating a function in Python that will take two inputs: a year and a number of days. The function will then calculate and print the year after the given number of days has passed from the beginning of the year. + +### Defining the Function + +We'll start by defining our function, which we'll name `what_year`. This function will take two input parameters: `start_year` and `days`. + +```python +def what_year(start_year, days): + +``` + +### Calculating the Years Passed + +Now we'll write some code to calculate how many years have passed from the starting year based on the `days` passed. + +```python +def what_year(start_year, days): + years_passed = days // 365 + +``` + +### Calculating the Target Year + +Next we'll write code to calculate the `target_year`. This is the year after the `days` have passed from the `start_year`. + +```python +def what_year(start_year, days): + years_passed = days // 365 + target_year = start_year + years_passed + +``` + +### Printing the Result + +Now we need to write a conditional to determine whether to print the "still" version of the sentence, or to print out the year after the days have passed. + +```python +def what_year(start_year, days): + years_passed = days // 365 + target_year = start_year + years_passed + + if years_passed > 0: + print(f"{days} days after Jan 1st, {start_year}, it will be the year {target_year}") + else: + print(f"{days} days after Jan 1st, {start_year}, it will still be the year {target_year}") +``` + +### Trying Out Our Function + +We've successfully created our What Year function. Go ahead and try it out in the Updraft code editor. From 6c792505042bf06cb811990832ee4b8246e26e61 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:05:06 -0700 Subject: [PATCH 634/797] Equious updated courses/moccasin-101/1-python-in-updraft/19-recap/+page.md. --- .../1-python-in-updraft/19-recap/+page.md | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/19-recap/+page.md b/courses/moccasin-101/1-python-in-updraft/19-recap/+page.md index 385e6edfe..42c4eb442 100644 --- a/courses/moccasin-101/1-python-in-updraft/19-recap/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/19-recap/+page.md @@ -1,3 +1,28 @@ ---- - title: Recap - --- \ No newline at end of file +In this lesson, we learned how to code using Python notebooks on Google Colab. This is a commonly used method for data scientists and portfolio managers, especially those who work at hedge funds or asset managers. + +In a previous lesson, we learned about the basics of Python. We were able to write a function to calculate how many years have passed after January 1st of a given year: + +```python +def what_year(start_year, days): + # Calculate how many years have passed (integer division) + years_passed = days // 365 + target_year = start_year + years_passed + + # Technically we might be off by a day, but we are going to ignore that + if years_passed > 0: + print(f"{days} days after Jan 1st, {start_year}, it will be the year {target_year}") + else: + print(f"{days} days after Jan 1st, {start_year}, it will still be the year {target_year}") + +what_year(1985, 376) +what_year(1985, 200) +what_year(1985, 1098) +``` + +We've learned a lot in this crash course, and if you were able to come up with the solution to our problem, give yourself a round of applause. It took me a long time to learn how to code Python and learning the basics here is absolutely fantastic. There's a lot more for us to learn. + +It's a great time to take a break, go get some coffee, go for a walk, go to the gym, and I'll see you soon. + +What we're going to do next is, in my opinion, the hardest part of any Python tutorial. I feel like this is the part of Python tutorials that most educators gloss over because setting up your Python environment on your local computer can be incredibly challenging. So we're going to spend the time to make sure we get you set up correctly so that you can be successful. + +I do actually want you to take at least a 30 minute break before going to this next section because I want some of the information here to settle in. And, guess what, your brain cannot process too much information in a day, it will do a worse job of learning that information. So, pause for at least a half an hour if you've already been coding for a while today. Pause for the whole day because installing Python and getting your environment set up correctly can take a long time. And if it does take a long time, don't be frustrated. It took me a long time the first time I got it set up. But, if you can get through installing Python and installing your environment the correct way, you can do anything, because it's honestly the hardest part of all of this. So, take a break and I'll see you soon. From 00af4cbe017218014b65598d862dda8920f21e4e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:05:33 -0700 Subject: [PATCH 635/797] Equious updated courses/moccasin-101/1-python-in-updraft/2-google-collab/+page.md. --- .../2-google-collab/+page.md | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/2-google-collab/+page.md b/courses/moccasin-101/1-python-in-updraft/2-google-collab/+page.md index 735bc3c07..7e20340f7 100644 --- a/courses/moccasin-101/1-python-in-updraft/2-google-collab/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/2-google-collab/+page.md @@ -1,3 +1,45 @@ ---- - title: Google Collab - --- \ No newline at end of file +## Google Colab Python Cells + +In this lesson, we will walk through a quick crash course in Python using the Google Colab tool. + +Google Colab is an excellent tool for running Python code online in your browser. You don't have to download or install anything to get started. Colab is similar to the way we were able to run everything online in the browser in previous lessons. + +Let's start with Google Colab: + +We will walk through setting up your development environment on MacOS and Linux, and Windows with WSL. Microsoft recommends installing Python from the Windows store, using PowerShell or using a different method, but we won't be doing that. Instead, we will teach you the Linux-based way, which is how many developers work, maybe even 99% of smart contract developers. + +We will first go over Google Colab and complete a Python crash course. Then, we will learn how to install and set up Python on your computers. + +We are going to skip all the installation and setup sections of the local development environment. If you are already comfortable with Python, feel free to do so as well. + +Let's start with Google Colab: +- We will be going over the completed code for the Google Colab. +- It's located here: [https://colab.research.google.com/drive/1OhOh0TtmJjlMKXwnbD-00ckXP3supNCwf7usps-sharing](https://colab.research.google.com/drive/1OhOh0TtmJjlMKXwnbD-00ckXP3supNCwf7usps-sharing) +- We'll do a brief walkthrough of everything you will see. + +**Python Crash Course:** + +We will walk through a Python crash course in the Google Colab. + +We will be teaching you Python, but we're also teaching you smart contract development. + +**Terminal Commands:** +```bash +code . +``` + +**Python in Updraft** + +We will cover how to install and set up Python locally. We will not be covering the Microsoft way of using PowerShell or the Windows store. We will be teaching you the Linux-based way which is how most developers work. + +In our opinion, setting up Python locally is the hardest part of this whole course. + +**Gitpod or Codespaces** + +If you are comfortable with Python and have a good foundation, you may choose to skip the setup sections. + +We will then go over a Python crash course, and then cover how to install and set up Python locally. Again, we will be skipping the Gitpod or Codespaces sections. Don't skip the Python in Updraft sections, because I promise you, the Python in Updraft section will be different from what you are used to. + +**Recap:** + +We have given you a heads up that these are the steps we will be taking. We will start by walking through a Python crash course with Google Colab. Then, we will learn how to install and set up Python locally. From 2ca1c472efe30b8ff8b1cd987081bf413e7012bf Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:07:13 -0700 Subject: [PATCH 636/797] Equious updated courses/moccasin-101/1-python-in-updraft/20-dev-env-setup/+page.md. --- .../20-dev-env-setup/+page.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/20-dev-env-setup/+page.md b/courses/moccasin-101/1-python-in-updraft/20-dev-env-setup/+page.md index 82dee4ad0..a7b9f99d7 100644 --- a/courses/moccasin-101/1-python-in-updraft/20-dev-env-setup/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/20-dev-env-setup/+page.md @@ -1,3 +1,13 @@ ---- - title: Dev Env Setup - --- \ No newline at end of file +## Development Environment Setup Introduction + +In this lesson, we'll be looking at installing Visual Studio Code. We'll go through three different installation methods, for MacOS/Linux, Windows, and Gitpod/Codespaces. However, we recommend against using Gitpod or Codespaces because you can quickly run out of your free trial on those platforms. + +Visual Studio Code is often referred to as VS Code. It's a great tool for us to use in this course, as it'll make our development experience a lot easier. We'll also discuss the benefits of using Visual Studio Code and how to avoid common pitfalls. We'll be using an AI to help us debug any issues that we run into during this course. + +Let's start with Visual Studio Code. Visual Studio Code is a standalone source code editor that runs on Windows, MacOS, and Linux. The top pick for JavaScript and web developers, it works with extensions to support just about any programming language. + +For MacOS and Linux, we're going to download and install the Visual Studio Code application. The process is very straightforward. We'll use the download link provided on their website, [code.visualstudio.com](code.visualstudio.com). + +For Windows, we'll download and install the Visual Studio Code application using a different method. The process is similar to installing it on MacOS and Linux. We'll again use the download link provided on their website, [code.visualstudio.com](code.visualstudio.com). + +In the next few sections, we'll go through setting up Visual Studio Code the way we like it, but, of course, you can set it up however you like. From 9ac598c87352fdd3c9e82692e3c038fff28c5305 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:08:42 -0700 Subject: [PATCH 637/797] Equious updated courses/moccasin-101/1-python-in-updraft/21-install-vscode-macos-linux/+page.md. --- .../21-install-vscode-macos-linux/+page.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/21-install-vscode-macos-linux/+page.md b/courses/moccasin-101/1-python-in-updraft/21-install-vscode-macos-linux/+page.md index 29e695218..d6e7f0b95 100644 --- a/courses/moccasin-101/1-python-in-updraft/21-install-vscode-macos-linux/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/21-install-vscode-macos-linux/+page.md @@ -1,3 +1,7 @@ ---- - title: Install Vscode Macos Linux - --- \ No newline at end of file +## Installing VS Code for Linux and macOS Users + +We will now be setting up our development environment. This will be one of the hardest parts of the whole course. So, if it takes you a long time, that's okay! If you're able to solve everything quickly, great! Please use the discussions forums, AI, and search engines if you get stuck on any part. + +The first thing we're going to want to do is download VS Code. You can download the Mac installation of VS Code, or, if you're working with Linux, download the Linux installation. + +Once we have it installed, it will look a little something like this. And if it's a fresh installation, it'll even give you some tips and tools to actually get started. If you've never worked with Visual Studio Code before, we highly recommend going through any "Get Started" or "Getting Instructions" tips that come with opening Visual Studio Code. Additionally, we have a Visual Studio Code crash course in the GitHub repo associated with this course. From a276bc39da9c11e500984facf41ce9229d67b390 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:09:10 -0700 Subject: [PATCH 638/797] Equious updated courses/moccasin-101/1-python-in-updraft/22-install-wsl/+page.md. --- .../22-install-wsl/+page.md | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/22-install-wsl/+page.md b/courses/moccasin-101/1-python-in-updraft/22-install-wsl/+page.md index 475d38e9a..feac123c1 100644 --- a/courses/moccasin-101/1-python-in-updraft/22-install-wsl/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/22-install-wsl/+page.md @@ -1,3 +1,33 @@ ---- - title: Install Wsl - --- \ No newline at end of file +## Installing WSL + +This lesson covers how to install WSL (Windows Subsystem for Linux). WSL is a really important tool that helps us run Linux environments and utilities on our Windows machine. This will allow us to run any Linux tools and applications that we might need for our blockchain development. + +### What is WSL? + +Microsoft has significantly improved their support for developers in recent years, but when it comes to smart contract development, WSL is the better choice. It is the Windows Subsystem for Linux, and it is a game changer! WSL allows us to run a Linux distribution on our Windows machine. + +### Introduction + +Let's get started with the installation process! The first thing that we need to do is install WSL, which we can do through the Windows terminal. If we are using Windows 11, we can just hit the Windows key and type **terminal** and hit enter. + +### Installing WSL + +This will open the Windows Terminal for us which defaults to Powershell. However, if we are using Windows 10, we will need to install the Windows Terminal from the Microsoft Store. + +To install WSL, open the Windows Terminal and run the following command: + +```bash +wsl --install +``` + +This will trigger some admin level operations, as we are about to see on the screen now. We just need to select **yes**, hit **enter** and once the installation process is finished, this will require us to restart our computer. + +Once we reboot our computer, this is going to automatically trigger this window to continue the installation. + +The first thing we need to do here is to select our UNIX username. I am going to select **"cromewar"** and hit **enter**. Then we will be required to set up a new password. + +Something interesting about most Linux operating systems/distros is that when we are using the terminal, if we type anything over here, the password is going to remain hidden. That doesn't mean that we are not typing anything, but the terminal is not going to show anything over here, unless we use another Windows distro, for example, Linux Mint. Otherwise, most of the Linux operating systems are going to keep this always hidden. + +I am going to type my password though, and then hit **enter**. As we can see here, the terminal recognizes that password and asks me to type it again for confirmation. + +Once we finish this, that's it. We have WSL installed on our machine. As we can see here, the installation finished properly, and we can continue. I am going to actually close this for now. From cc2aba289e6abdb2a97d6960b167d52554fbdda8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:11:55 -0700 Subject: [PATCH 639/797] Equious updated courses/moccasin-101/1-python-in-updraft/23-vscode-windows-install/+page.md. --- .../23-vscode-windows-install/+page.md | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/23-vscode-windows-install/+page.md b/courses/moccasin-101/1-python-in-updraft/23-vscode-windows-install/+page.md index a09ad1944..50d19cc43 100644 --- a/courses/moccasin-101/1-python-in-updraft/23-vscode-windows-install/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/23-vscode-windows-install/+page.md @@ -1,3 +1,23 @@ ---- - title: Vscode Windows Install - --- \ No newline at end of file +## Windows Users Only: Installing VS Code + +We can install VS Code in a few different ways. + +The easiest is to use the **Windows Terminal**, using a package manager pre-installed on Windows 11 called **winget**. If we want to install VS Code using winget, we type the following command: + +```bash +winget search vscode +``` + +Then we copy the package name and use it in the following command: + +```bash +winget install Microsoft.VisualStudioCode +``` + +This will start the installation process. Once complete, we can access it from our Windows Menu. + +Another way is to use a web browser. We can go to the official website, **code.visualstudio.com**. We click on the "Download for Windows" button to trigger the download and install. + +If you want to ensure no data tracking from Microsoft, we can use a community-driven version of Visual Studio Code called **VsCodium**. It's basically the same code editor but without the Microsoft telemetry, gallery, logo, etc. The license is also changed to the MIT license. The installation process is similar to the previous method: We go to the VsCodium website, which is **vscodium.com**. We click on the "Install" button and download the latest release for Windows. + +We can now use VS Code in three different ways. The one we use for the tutorial, and for the rest of the course, is going to be the official Microsoft Visual Studio Code. From 40c545390840fc9f9c36d6cf23fc866011c3e179 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:15:09 -0700 Subject: [PATCH 640/797] Equious updated courses/moccasin-101/1-python-in-updraft/24-vscode-windows-wsl-extension/+page.md. --- .../24-vscode-windows-wsl-extension/+page.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/24-vscode-windows-wsl-extension/+page.md b/courses/moccasin-101/1-python-in-updraft/24-vscode-windows-wsl-extension/+page.md index 2acc9a55f..ee7b8061c 100644 --- a/courses/moccasin-101/1-python-in-updraft/24-vscode-windows-wsl-extension/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/24-vscode-windows-wsl-extension/+page.md @@ -1,3 +1,15 @@ ---- - title: Vscode Windows Wsl Extension - --- \ No newline at end of file +## Windows Users ONLY: WSL VSCode Extension + +We will be using a terminal built directly into Visual Studio Code. This is a Linux or Ubuntu terminal. We want to install the **WSL** extension for **Visual Studio Code** which is available from Microsoft. + +The WSL extension will pop up a terminal window similar to the PowerShell window, but we will choose Ubuntu to create a Linux terminal. This can be accessed by clicking on the three dots in the Visual Studio Code terminal dropdown and choosing **Ubuntu**. + +We will also be using the **Open a Remote Window** section at the bottom left of Visual Studio Code. We will select **Connect to WSL** in this dropdown to open up our VS Code directly in a WSL Ubuntu setup. + +To open a new terminal, we can either click on the three dots in the terminal dropdown and choosing **New Terminal**, or we can use the shortcut **Ctrl + Shift + `**. + +When we are in the Ubuntu terminal in VS Code, we will use Linux commands. We will not use Windows commands. If a website says, "Here is the Linux command, here is the Windows command", we will use the Linux command if we are in the Ubuntu terminal in VS Code. + +If we close out of Visual Studio Code and reopen it, we will be able to reconnect to the Ubuntu terminal by using the **Open a Remote Window** section at the bottom left of Visual Studio Code and selecting **Connect to WSL**. + +We will be working with Ubuntu or WSL or this Linux-like environment throughout this course. From 00ad7459a58f1b7b547cd5fb971026f4e05180d0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:15:42 -0700 Subject: [PATCH 641/797] Equious updated courses/moccasin-101/1-python-in-updraft/25-vscode-quickstart/+page.md. --- .../25-vscode-quickstart/+page.md | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/25-vscode-quickstart/+page.md b/courses/moccasin-101/1-python-in-updraft/25-vscode-quickstart/+page.md index 3ab104359..f8d96c439 100644 --- a/courses/moccasin-101/1-python-in-updraft/25-vscode-quickstart/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/25-vscode-quickstart/+page.md @@ -1,3 +1,36 @@ ---- - title: Vscode Quickstart - --- \ No newline at end of file +## Visual Studio Code Quickstart 1: Terminals & Git + +Visual Studio Code (VS Code) is a powerful and popular text editor. One of the things that makes it so powerful is its built-in terminal feature. + +### Terminals + +VS Code's terminal lets us run scripts from within the text editor. It's essentially a command-line prompt. + +To open a terminal, we can: + +1. Click the "Terminal" menu and select "New Terminal." +2. Use the keyboard shortcut **ctrl backtick** on Mac or Linux, which will toggle the terminal on and off. + +### Git + +We will be using Git to manage our code projects. Git is a version control system that lets us track changes to our code and collaborate with others. + +We need to install Git before we can use it. To install Git on Linux, use one of these commands: + +```bash +sudo dnf install git-all +``` + +```bash +sudo apt install git-all +``` + +On macOS, we can run the following command in the terminal: + +```bash +git --version +``` + +This will prompt us to install Git if it's not already installed. We can also use a macOS Git installer by clicking the link to a Git installer on the [git-scm.com](https://git-scm.com/) website. + +We will go over how to use Git in detail in future lessons. For now, we can skip the next two sections of this course if we're not planning on using Windows or GitPod. From 0d0aa1a9459a6a29f3354ab40090f783a3d8d313 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:16:08 -0700 Subject: [PATCH 642/797] Equious updated courses/moccasin-101/1-python-in-updraft/26-install-python-macos/+page.md. --- .../26-install-python-macos/+page.md | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/26-install-python-macos/+page.md b/courses/moccasin-101/1-python-in-updraft/26-install-python-macos/+page.md index d2148949d..cc344200e 100644 --- a/courses/moccasin-101/1-python-in-updraft/26-install-python-macos/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/26-install-python-macos/+page.md @@ -1,3 +1,34 @@ ---- - title: Install Python Macos - --- \ No newline at end of file +## Installing Python on a Mac + +If you're on a Linux or a Windows machine, you can skip this lesson! + +To install Python on a macOS system, we'll go to the python.org website and download Python. + +On the python.org website, under Downloads, go to macOS and then scroll down to the latest Python 3.11 release. + +Click the link for the **Python 3.11.x macOS 64-bit universal2 installer**. The installation file will download to your Downloads folder. + +We'll then open the installer file, and then agree to the license agreement. + +We'll click **Continue**, and then **Install**. Python will install automatically. + +Once the installation is complete, a pop-up message will appear confirming that the installation was successful. We'll then close the installer. + +We'll open our VS Code terminal, either by clicking **Terminal > New Terminal** or by pressing **Control, Shift, Tilde**. + +In the VS Code terminal, we can confirm that the correct Python version is installed with: +```bash +python3.11 --version +``` + +We can also try: +```bash +python --version +``` + +Although, as of the recording, I don't have the `python` keyword. + +If you have multiple versions of Python installed, you can use this command to ensure that you're working with the correct version. + +We're going to switch to using tools called UV and Moccasin, which will make it easier to work with different versions of Python. + From 4c137365c11fe98968373d62c2aa7aee6024a717 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:16:34 -0700 Subject: [PATCH 643/797] Equious updated courses/moccasin-101/1-python-in-updraft/27-install-python-wsl-linux/+page.md. --- .../27-install-python-wsl-linux/+page.md | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/27-install-python-wsl-linux/+page.md b/courses/moccasin-101/1-python-in-updraft/27-install-python-wsl-linux/+page.md index d18275288..42fdfd340 100644 --- a/courses/moccasin-101/1-python-in-updraft/27-install-python-wsl-linux/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/27-install-python-wsl-linux/+page.md @@ -1,3 +1,49 @@ ---- - title: Install Python Wsl Linux - --- \ No newline at end of file +## Installing Python (Windows WSL and Linux users) + +We're going to learn how to install Python in this WSL if you're on a Windows machine, or if you're on a Linux machine, just right on your Linux machine. Most sites are going to ask you to go directly to the Python website and select download. The issue with this for those of you on a Windows or a WSL environment is that downloading directly from the website will download this into your Windows operating system. We don't want to do that because we are going to be working in the Linux, the WSL, the Ubuntu operating system. So, we want to download into our Linux operating system. + +The same is actually true for any other software application that you want to run in your WSL environment; you're going to have to download it directly from the command line as opposed to downloading from some website with a click of a button. + +We'll need to make sure we're in a Linux environment. We can do this by typing `echo $SHELL` in the terminal. If we see a path that looks like `/bin/bash` or `/bin/zsh`, that's a good sign that we're in the right place. If we get an error, we can use an AI chatbot like Claude to help us troubleshoot. + +To install a specific version of Python, we'll use a few terminal commands. + +First, we'll run `sudo apt-get update`. This command updates our system's package index. Claude, a chatbot, can explain this in more detail. + +```bash +sudo apt-get update +``` + +Next, we'll install a common Linux package by running `sudo apt-get install software-properties-common`. + +```bash +sudo apt-get install software-properties-common +``` + +We'll then add the "deadsnakes" PPA by running `sudo apt-add-repository ppa:deadsnakes/ppa`. This PPA (Personal Package Archive) allows us to access different versions of Python. + +```bash +sudo apt-add-repository ppa:deadsnakes/ppa +``` + +Now, we need to update again to ensure that the PPA is correctly included. We'll run `sudo apt-get update`. + +```bash +sudo apt-get update +``` + +Finally, we'll install a specific version of Python. In this case, we're installing Python 3.11. We'll run `sudo apt-get install python3.11`. + +```bash +sudo apt-get install python3.11 +``` + +We can check that Python 3.11 is installed by running `python3.11 --version`. + +```bash +python3.11 --version +``` + +We're going to be moving away from using Python 3.11 in the terminal and instead use the "uv" tool. The "uv" tool will make it easier to switch between different versions of Python. + +If you do encounter any issues, remember that Googling, joining the discussions forum, and using AI can be incredibly helpful for troubleshooting. From 30e934e12ce414e0f3818e245662e65943807c44 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:20:19 -0700 Subject: [PATCH 644/797] Equious updated courses/moccasin-101/1-python-in-updraft/28-vscode-quickstart-2/+page.md. --- .../28-vscode-quickstart-2/+page.md | 109 +++++++++++++++++- 1 file changed, 106 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/28-vscode-quickstart-2/+page.md b/courses/moccasin-101/1-python-in-updraft/28-vscode-quickstart-2/+page.md index 7d3ad9c57..b48f29876 100644 --- a/courses/moccasin-101/1-python-in-updraft/28-vscode-quickstart-2/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/28-vscode-quickstart-2/+page.md @@ -1,3 +1,106 @@ ---- - title: Vscode Quickstart 2 - --- \ No newline at end of file +We are ready to get started with VS Code for this course! Let's open up VS Code. If you are on a Mac or Linux, you should see a shortcut to open a "remote window" in the bottom left of the screen. If you are on a Windows machine, it will likely display WSL or Ubuntu or some combination of the two. + +Let's open up a terminal using the command `Command ~` on Mac and `Control ~` on Windows or Linux. + +In our terminal, we can type the command +```bash +echo $SHELL +``` + +This will tell us the shell that we are using. It could be `zsh`, `bash`, or many other types of shells that all work the same way. The shell that we are using doesn't matter because the commands that we will be running work on any shell that you are working with. + +We'll often want to clear the terminal of old commands. We can do that by typing the command `clear`, and then hitting enter. + +We can also clear the terminal by using the keyboard shortcut `Command K` on Mac, or `Control K` on Windows or Linux. + +The trashcan icon on the terminal will delete the current terminal entirely. + +Let's open a new terminal and type a few lines. The X icon in the terminal is to hide the terminal. We can always pull the terminal back up. + +There is a keyboard shortcut for toggling the terminal, which is `Command ` `~` on Mac or `Control` `~` on Windows or Linux. This will hide and show the terminal window. + +We can also toggle the terminal by going to `View` and selecting `Terminal`. + +To delete a terminal window, we can click on the trashcan icon. + +Now, we'll create a new folder to store all of the files and folders that we will need for this curriculum. To create a new folder, we'll type the command: +```bash +mkdir mox-cu +``` +This command stands for `make directory`, and we'll use `mox-cu` as our folder name. We can call it anything we want. + +Now, we'll go into the folder that we just created by using the command: +```bash +cd mox-cu +``` + +The command `cd` stands for `change directory`. + +If we use the command `pwd`, which stands for `present working directory`, it will tell us the current location. + +To open the folder that we created, we can type the command `open .` on Mac. The dot (.) in this command refers to the current directory. + +There is a similar command on Windows to open a folder. For Windows users, we can type the command: +```bash +explorer . +``` +This will open the folder in Windows Explorer. + +For Linux, we can type the command: +```bash +xdg-open . +``` +This will open the current directory in the Linux file explorer. + +If you are a Linux user, you may not have this command installed by default. You may need to install this command. To install this, you can type: +```bash +sudo apt-get install xdg-utils +``` + +Now, we are going to install an AI extension. + +You can go to the extensions section. You'll find a search box where you can search for extensions. + +The AI that we will be using is GitHub Copilot. Feel free to search for other AI extensions, but GitHub Copilot is the one we will be using. + +After you install it, you'll see a little GitHub Copilot icon in the bottom right corner of your screen. This is a little reminder that you have installed it correctly. + +You might also want to install GitHub Copilot Chat. This will open a chat box for GitHub Copilot. + +Once you have installed it, you will see a little GitHub Copilot icon. You can right-click on the icon and select the chat option. This will open a chat box similar to ChatGPT or Cloud. + +We will be working in our `mox-cu` folder, which is the folder that we just created, and can see at the top of our VS Code screen. + +We can also view our file explorer. We'll be able to see all of our files here. + +You can toggle back to your terminal using the `Control ~` shortcut. + +We'll be working with files in this folder. We can create files by right-clicking and selecting `new file`. + +Let's create a file named `hi.txt`. + +You can see that `hi.txt` is listed in the left sidebar. + +Now, let's go to our terminal and type the command `ls`, which stands for `list`. This will list all of the files in our folder. + +We can see that our `hi.txt` file is in our folder. + +If we want to create a new file in VS Code, we can do so by right-clicking and selecting `new file`. Let's create a file named `hi2.txt`. + +We can see that both `hi.txt` and `hi2.txt` are listed. + +To edit a file, we can simply click on it. We can make changes and save the file. + +Let's delete this file. You can do this by right-clicking the file and selecting `delete`. You can also delete the file by using the trash can icon. + +You can also see a little dot next to the file name. This dot means the file is unsaved. To save, click `file`, `save`, and the dot will go away. + +That's a quick introduction to VS Code. + +Let's go ahead and try out GitHub Copilot. It's a little doodad that appears at the bottom of our screen, and helps us code. + +For example, we'll type `SPDX license identifier`, and GitHub Copilot will provide a suggestion. To accept the suggestion, we can hit `tab`. + +You can also click on the little GitHub Copilot icon. You can go to GitHub Copilot Chat to use GitHub Copilot in a chat-like format. + +In this lesson, we have learned the basics of navigating VS Code, creating files, editing files, and using GitHub Copilot. From c16e328626ffced758317f014d8b146e34e37c5e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:21:04 -0700 Subject: [PATCH 645/797] Equious updated courses/moccasin-101/1-python-in-updraft/29-mental-prep/+page.md. --- .../29-mental-prep/+page.md | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/29-mental-prep/+page.md b/courses/moccasin-101/1-python-in-updraft/29-mental-prep/+page.md index cfcec4377..425d1ecb2 100644 --- a/courses/moccasin-101/1-python-in-updraft/29-mental-prep/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/29-mental-prep/+page.md @@ -1,3 +1,38 @@ ---- - title: Mental Prep - --- \ No newline at end of file +## Mental Preparation + +Mental preparation is key when learning a new skill. Before we start coding, let�s think about why we want to learn, what we want to accomplish and what steps we will take to get there. + +The first question we should ask ourselves is: Why am I learning Vyper and Python? + +We should be honest with ourselves. Maybe we want to be part of the blockchain movement and make a lot of money, or maybe we want to learn a new skill and build our own projects. Whatever our rationale is, write it down and be honest with ourselves, don't placate ourselves. + +The next question is: What do I want to do/be when I finish this course? + +If we want to be a software engineer, security researcher, technical CEO or technical BD, write it down. What do we want to do? What do we want to feel like when we're finished with this course? + +Finally, what are the steps we are going to take to get there? + +This is a long course, so we need to figure out a learning cadence that works for us and stick to it. Maybe 30 minutes a day for 4 days a week, 1 hour a day, or 2 hours on Saturday and Sunday. Whatever our schedule is, write it down so that we can come back to it when things get tough. We should keep these goals private and be honest with ourselves. + +We're going to start by making a README.md file in our terminal. This will be our manifesto that we can come back to when things get hard. + +In our terminal, we're going to create a new file named README.md + +```bash +touch README.md +``` + +We can open this file in our VS code, by using a command in our terminal. + +```bash +code README.md +``` + +This should open up our new file in our VS Code. +Now, let's go back to our terminal and make sure we're in the correct directory. + +```bash +pwd +``` + +Now that our setup is complete, we are ready to start coding! From 8a25236553480435229b6e3a80b01a49eb3b82a8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:21:31 -0700 Subject: [PATCH 646/797] Equious updated courses/moccasin-101/1-python-in-updraft/3-setup/+page.md. --- .../1-python-in-updraft/3-setup/+page.md | 156 +++++++++++++++++- 1 file changed, 153 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/3-setup/+page.md b/courses/moccasin-101/1-python-in-updraft/3-setup/+page.md index fcc7a149d..fab7a007c 100644 --- a/courses/moccasin-101/1-python-in-updraft/3-setup/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/3-setup/+page.md @@ -1,3 +1,153 @@ ---- - title: Setup - --- \ No newline at end of file +## Python Crash Course + +This section will be a Python Crash Course. We will be using the tool Google Colab, which is an online, browser-based IDE. It's great for working with Python. + +You can see an example of the final code from the tutorial in the repository, but we will be starting from a brand new notebook to ensure you can practice the code. + +To access Google Colab, you will need a Google account. + +To get started with Google Colab, we will need to go to the Google Colab site and create a new notebook. + +**Creating a New Notebook** + +You will need to select **File** and then **New Notebook in Drive**. This will create a new notebook for us. + +**Naming the Notebook** + +We can name our notebook whatever we want, but I will name my notebook "Updraft Python". + +**Jupyter Notebooks** + +Google Colab uses what are called Jupyter Notebooks. These are essentially a way to combine Markdown text, Python code, and other elements into a single document. + +The way this works is, you have these cells in a Jupyter Notebook. A Jupyter Notebook is made up of different types of cells. + +**Cells** + +You can run Python code in a Jupyter Notebook by creating a code cell, and running that code. You can also add text, or Markdown, to the cells as well. We will be using code cells to run all of our Python code. + +To execute a code cell, you simply click the play button. + +**Terminal Commands** + +We will also be using terminal commands. We will format these terminal commands in a code block, so you can copy and paste them. For example, the command to list the contents of a directory, which is "ls", will be formatted like this: + +```bash +ls +``` + +**Example Code** + +The code we're going to execute is a simple "Hello, World" example. + +```python +print("Hello, World") +``` + +This will print "Hello, World" to the console output. + +**Variables** + +We can also assign variables, like this: + +```python +my_variable = 7 +``` + +This will assign the value 7 to the variable my_variable. + +**Data Types** + +Python comes with many data types, including integers, strings, and booleans. + +```python +my_number = 10 +my_boolean = True +my_string = "hello!" +``` + +**Type Hints** + +We can also use type hints in Python. Type hints are a way to indicate the expected data type of a variable. + +```python +my_typed_number: int = 9 +``` + +This indicates that the variable my_typed_number is expected to be an integer. + +**Updating Variables** + +We can also update variables, like this: + +```python +my_number = 7 +``` + +This will assign the value 7 to the variable my_number. + +**Lists** + +Variables in Python can hold lists of elements. + +```python +my_list: list = [7, "cat", True] +``` + +**Accessing List Elements** + +In Python, lists are "0 indexed." This means that the first element in a list has an index of 0, the second element has an index of 1, and so on. + +For example: + +```python +my_list = [7, "cat", True] +my_list[1] = "dog" +print(my_list) +``` + +The output will be: + +```python +[7, "dog", True] +``` + +**Casting** + +You can convert data types from one to another in Python using casting. + +```python +year = "2025" +int_year = int(year) +added_year = int_year + 25 +print(added_year) +``` + +The output will be: + +```python +2050 +``` + +**Math Operations** + +You can also do math in Python, like this: + +```python +print("Add") +my_number = 5 + 5 +print(my_number) +print("Subtract") +my_number = 5 - 5 +print(my_number) +``` + +**Code Blocks** + +All of the code blocks in this tutorial will have code formatted on new lines, like this: + +```python +print("Hello, World") +``` + +Be sure to practice the code shown in this tutorial to get a good understanding of Python basics. From 63e9e831a19c8adf0f6cd3007b69ffbbd17ea2a3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:21:59 -0700 Subject: [PATCH 647/797] Equious updated courses/moccasin-101/1-python-in-updraft/30-local-py/+page.md. --- .../1-python-in-updraft/30-local-py/+page.md | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/30-local-py/+page.md b/courses/moccasin-101/1-python-in-updraft/30-local-py/+page.md index 8c591a536..ef2c947f9 100644 --- a/courses/moccasin-101/1-python-in-updraft/30-local-py/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/30-local-py/+page.md @@ -1,3 +1,49 @@ ---- - title: Local Py - --- \ No newline at end of file +## Local Python Development: An Introduction + +We are going to create our first Python project and use a more professional environment. + +### Project Creation + +First, we need to create a new directory. + +We can do this using the command: + +```bash +mkdir python-in-updraft-cu +``` + +Or to keep things in order, we can use: + +```bash +mkdir 1-python-in-updraft-cu +``` + +Then hit enter. + +If we run the command `ls`, we can see we now have a folder, `python-in-updraft-cu`, and a file `README.md`. + +### Navigating to Our New Directory + +Next, we will navigate to the newly created folder. We can do this using the command: + +```bash +cd python-in-updraft-cu +``` + +You can also use the Tab key to auto-complete the directory name. This is a helpful tip. + +We can check our current location by using the command: + +```bash +pwd +``` + +### Opening Our Project in Visual Studio Code + +Now we need to open the project in Visual Studio Code. You can do this by typing the command: + +```bash +code . +``` + +Alternatively, you can open Visual Studio Code, go to the "File" menu, click "Open Folder" and then select the `python-in-updraft-cu` folder. From 6a47e69093d748120daf421b29979887cb3eba28 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:22:25 -0700 Subject: [PATCH 648/797] Equious updated courses/moccasin-101/1-python-in-updraft/31-python-shell/+page.md. --- .../31-python-shell/+page.md | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/31-python-shell/+page.md b/courses/moccasin-101/1-python-in-updraft/31-python-shell/+page.md index 9c47c3f3e..f8d710e5f 100644 --- a/courses/moccasin-101/1-python-in-updraft/31-python-shell/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/31-python-shell/+page.md @@ -1,3 +1,61 @@ ---- - title: Python Shell - --- \ No newline at end of file +## Python Shell / Console + +We can try out code in Python using the Python shell or console. To do this, we type: + +```bash +python3.11 +``` + +This will open the Python shell. The shell allows us to write any code we want and have it executed immediately. For example, to print the string "hi", we would type: + +```python +print("hi") +``` + +The shell will immediately respond: + +``` +hi +``` + +We can also assign values to variables. For example, to assign the value 7 to the variable my_var, we would type: + +```python +my_var = 7 +``` + +The shell will not respond to this, since we have only assigned the value. We can then print the variable value by typing: + +```python +print(my_var) +``` + +The shell will respond with the value: + +``` +7 +``` + +If we type quit and hit enter, we will exit the shell and return to the terminal. To reenter the Python shell, we would have to type: + +```bash +python3.11 +``` + +again. + +If we try to print the variable my_var without assigning it a value, we will get an error: + +```python +print(my_var) +``` + +The shell will respond with: + +``` +Traceback (most recent call last): + File "", line 1, in +NameError: name 'my_var' is not defined +``` + +This error occurs because variables assigned in the shell are not saved when we exit the shell. From a70f0588e56f021b2e7bc539f2b95171cb535647 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:22:51 -0700 Subject: [PATCH 649/797] Equious updated courses/moccasin-101/1-python-in-updraft/32-python-extensions-vscode/+page.md. --- .../32-python-extensions-vscode/+page.md | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/32-python-extensions-vscode/+page.md b/courses/moccasin-101/1-python-in-updraft/32-python-extensions-vscode/+page.md index 85f6eb88c..25abaa5ec 100644 --- a/courses/moccasin-101/1-python-in-updraft/32-python-extensions-vscode/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/32-python-extensions-vscode/+page.md @@ -1,3 +1,34 @@ ---- - title: Python Extensions Vscode - --- \ No newline at end of file +## Jupyter and Python VS Code Extensions + +We can create an environment very similar to a Google Colab environment by creating a file in VS Code called `cells.ipynb`. + +To run the cells in this notebook, we need to install two extensions: + +1. **Jupyter Notebook**: This extension provides support for Jupyter notebooks. + ```bash + jupyter + ``` +2. **Python**: This extension provides language support for Python and helpful tools, including syntax highlighting and formatting. + ```bash + python + ``` + +After we install these extensions, we need to select a kernel. We can do this by clicking the three dots in the top right corner of the VS Code window and selecting "Extensions". Alternatively, we can click the "Extensions" button on the left side of the window. + +We can then select the desired Python environment. We'll choose `Python 3.11.9` in this example. + +Now we can run the cells in our Jupyter notebook by typing `shift enter`. We'll see that the output of the cells will appear below the cell itself. + +We can also run basic Python commands in a Jupyter notebook in VS Code. For example, we can create a variable called `my_var` and set it equal to 8. We can then run the cell to assign the value to the variable. + +```python +my_var = 8 +``` + +Then, we can print the value of the variable `my_var`. + +```python +print(my_var) +``` + +We can see that the output of this cell will be the number 8. From 1da364042b24a2f495238084c234c20df829b79a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:23:20 -0700 Subject: [PATCH 650/797] Equious updated courses/moccasin-101/1-python-in-updraft/33-our-first-python/+page.md. --- .../33-our-first-python/+page.md | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/33-our-first-python/+page.md b/courses/moccasin-101/1-python-in-updraft/33-our-first-python/+page.md index f790b0411..55b35e978 100644 --- a/courses/moccasin-101/1-python-in-updraft/33-our-first-python/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/33-our-first-python/+page.md @@ -1,3 +1,35 @@ ---- - title: Our First Python - --- \ No newline at end of file +## Our first Python file + +We've been working with `cells.ipynb` files. Let's create our first basic Python file. This is how professional software engineers work with Python. + +Google Colab and these Jupyter Notebooks are great for testing, tinkering, learning, and working with stuff and the like, but they aren't great for professional environments. This is because, similar to Remix, if we wanted to test something and had to do shift-enter or execute all these cells at the same time, it could be very annoying. This isn't how professional projects work. + +What they do instead is they create Python files to run and execute. For example, we are going to create a new file called `basic_python.py`. + +The `.py` file extension is how VS Code and other Python tools know that this is a Python file. + +In here, we can type and run kind of the basic Python stuff. We can do + +```python +print("hi") +``` + +in here. Remember, this little white dot means it's not saved. Hit `command s` to save it. And then we can hit this little plus button that comes with this, and it will run my Python file with this `hi`. + +Now there is a whole bunch of other stuff that it will do, and so this is kind of like a cheat sheet shortcut. This is something that you can use to run your Python files. However, we are going to discourage that use for a lot of reasons. + +Instead, in your terminal, if you do + +```bash +ls +``` + +you can see we have this `basic_python.py`. We are going to write + +```bash +python3.11 basic_python.py +``` + +Hit enter and we will see it prints out `hi`. + +This is how we can execute an entire file of Python, like so. From 9d69130a301a90e9e7f758b87074c8020f102a56 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:23:44 -0700 Subject: [PATCH 651/797] Equious updated courses/moccasin-101/1-python-in-updraft/34-python-imports/+page.md. --- .../34-python-imports/+page.md | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/34-python-imports/+page.md b/courses/moccasin-101/1-python-in-updraft/34-python-imports/+page.md index fae7a0f96..fa83c14a0 100644 --- a/courses/moccasin-101/1-python-in-updraft/34-python-imports/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/34-python-imports/+page.md @@ -1,3 +1,40 @@ ---- - title: Python Imports - --- \ No newline at end of file +## Installing Libraries and using imports + +One of the things we can do in Python is install packages and libraries. + +To install the Python package called "Titanoboa" (a Python tool for interacting with Vyper), we can visit the Titanoboa Github repository: + +```bash +github.com/vyperlang/titanoboa +``` + +On the repository page, if we scroll down to the Installation section, we can see how to install the Python package directly into our environment. + +The command we will use is: + +```bash +pip install titanoboa +``` + +We can then run a command using the package in our Python. + +To install the Titanoboa package into our global Python environment, we will type: + +```bash +python3.11 -m pip install titanoboa +``` + +After installing Titanoboa, we can view a list of all the different packages that we have installed in our Python environment. + +To view this list, we can type: + +```bash +python3.11 -m pip freeze +``` + +We can use the Titanoboa package to evaluate Vyper. To evaluate some Vyper code, we can type "import boa". For example, if we want to evaluate the Vyper code to create an empty uint256 object (AKA 0), we can type: + +```python +import boa +print(boa.eval('"empty(uint256)"')) +``` From 7e4273958acec22af9f5a0b8dc8e5723c9bb9445 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:25:24 -0700 Subject: [PATCH 652/797] Equious updated courses/moccasin-101/1-python-in-updraft/35-installing-uv/+page.md. --- .../35-installing-uv/+page.md | 75 ++++++++++++++++++- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/35-installing-uv/+page.md b/courses/moccasin-101/1-python-in-updraft/35-installing-uv/+page.md index ef00c9919..875cfb285 100644 --- a/courses/moccasin-101/1-python-in-updraft/35-installing-uv/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/35-installing-uv/+page.md @@ -1,3 +1,72 @@ ---- - title: Installing Uv - --- \ No newline at end of file +## UV Installation + +We are going to introduce you to the `uv` tool. + +`uv` is a very fast Python package and project manager. It was written in Rust. This tool is very fast and very modern. Let's install it so we can see what all the fuss is about. + +The `uv` tool can help us with the following: + +* Installing and managing Python versions +* Creating professional Python projects +* Maintaining Python versions + +First, we're going to go to the `uv` documentation website: + +```bash +docs.astral.sh/uv +``` + +Then, we're going to scroll down to the "Getting started" section. This is where we will find the instructions for installing the `uv` tool. + +We'll copy the command below and paste it into our terminal. + + +```bash +curl -Lssf https://astral.sh/uv/install.sh | sh +``` + +This will install both the `uv` and the `uvx` commands. + +Once we have it installed, we can go ahead and delete our terminal and type: + +```bash +which uv +``` +This will show us the location of our installed `uv` command. + +We can also type: + +```bash +uv --version +``` +This will display the current version of `uv` that we are using. + +Now that we have installed `uv`, we can use it to create a new Python project. + +```bash +uv init python-in-updraft-cu +``` + +This will create a new project folder called `python-in-updraft-cu`. + +We can now see a whole bunch of new files on the left side of the screen: + +* `.gitignore` +* `.python-version` +* `basic_python.py` +* `cells.ipynb` +* `hello.py` +* `pyproject.toml` +* `README.md` + +Let's go over what some of these files do: + +The `.gitignore` file is specifically for working with Git and GitHub. + +The `.python-version` file tells other developers and tools what Python version is recommended for this project. + +The `pyproject.toml` file tells the world and other Python projects how to interact with our Python project here. + +The `README.md` file is a file that every single one of your projects should come with. + +We'll explain these other files later. See you next time! From 66dfff6371ebd053d946807f66c2ace11f04b625 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:25:49 -0700 Subject: [PATCH 653/797] Equious updated courses/moccasin-101/1-python-in-updraft/36-uv-python-version/+page.md. --- .../36-uv-python-version/+page.md | 118 +++++++++++++++++- 1 file changed, 115 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/36-uv-python-version/+page.md b/courses/moccasin-101/1-python-in-updraft/36-uv-python-version/+page.md index 84d31ea64..f6e7c1d72 100644 --- a/courses/moccasin-101/1-python-in-updraft/36-uv-python-version/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/36-uv-python-version/+page.md @@ -1,3 +1,115 @@ ---- - title: Uv Python Version - --- \ No newline at end of file +## Using uv to Automatically Change Python Versions + +We can use `uv` to automatically switch between different Python versions. This is useful when we need to run scripts that require a specific Python version. + +We start off looking at a `basic_python.py` file with the following code: +```python +import boa +print(boa.eval('"empty(uint256)"')) +print("Hello!") +``` + +If we run this script with Python 3.11: +```bash +python3.11 basic_python.py +``` + +We will get the following output: +```bash +0 +Hello! +``` + +Let's look at a different scenario. If we try to run this script with `uv` and Python 3.11: +```bash +uv run python3.11 basic_python.py +``` + +We will get the following error: +```bash +Traceback (most recent call last): + File "Users/patrick/mox-cu/python-in-updraft-cu/basic_python.py", line 1, in + import boa +ModuleNotFoundError: No module named 'boa' +``` + +The error occurs because the Boa package is installed into our global Python environment, not our `uv` environment. + +We can see our Python versions using `uv`. If we type: +```bash +uv run python --version +``` + +We will get the version we are currently working with. If we type: +```bash +python3.11 --version +``` + +We will get the version of our global Python environment. + +We are going to update this to use a specific Python version. We can add the following lines to our `basic_python.py` file: +```python +import sys +if sys.version_info < (3, 12): + raise RuntimeError("This script requires Python 3.12 or higher") +``` + +If we run this script with Python 3.11: +```bash +python3.11 basic_python.py +``` + +We will get the following error: +```bash +Traceback (most recent call last): + File "/Users/patrick/mox-cu/python-in-updraft-cu/basic_python.py", line 5, in + raise RuntimeError("This script requires Python 3.12 or higher") +RuntimeError: This script requires Python 3.12 or higher +``` + +So this is a way to specify that a script requires a certain Python version. + +We can go back to our terminal and type: +```bash +uv python install 3.12 +``` + +This will install Python 3.12 into our `uv` environment. + +If we clear our terminal and run our script: +```bash +uv run basic_python.py +``` + +We will now get an error about the `boa` module because we commented it out: +```bash +Traceback (most recent call last): + File "/Users/patrick/mox-cu/python-in-updraft-cu/basic_python.py", line 6, in + print(boa.eval('"empty(uint256)"')) +NameError: name 'boa' is not defined +``` + +We can use `uv` to see a list of the Python versions that we have installed. If we type: +```bash +uv python list +``` + +We will see a list of all the Python versions installed on our computer. + +We can also directly specify a version of Python to use: +```bash +uv run --python 3.12 python basic_python.py +``` + +This will run our `basic_python.py` script with Python 3.12.7. + +We can also pin the Python version for a project using a file named `.python-version` and store it in the project's root directory. Inside this file, we can specify the Python version that we want to use. We can then update the Python version in the `.python-version` file. + +This will update the Python version of the project and automatically download the new version and update the virtual environment. + +To see this in action, we can update our `.python-version` file to Python 3.13: +``` +3.13 +``` + +We can then use `uv run basic_python.py` to run our script and it will automatically download Python 3.13, update our virtual environment, and then run the script. From 5b6f7920af997b3898f4af4aceeb1aa9d9a4af55 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:26:17 -0700 Subject: [PATCH 654/797] Equious updated courses/moccasin-101/1-python-in-updraft/37-adding-packages-uv/+page.md. --- .../37-adding-packages-uv/+page.md | 77 ++++++++++++++++++- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/37-adding-packages-uv/+page.md b/courses/moccasin-101/1-python-in-updraft/37-adding-packages-uv/+page.md index d2268f193..b82fac182 100644 --- a/courses/moccasin-101/1-python-in-updraft/37-adding-packages-uv/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/37-adding-packages-uv/+page.md @@ -1,3 +1,74 @@ ---- - title: Adding Packages Uv - --- \ No newline at end of file +## Adding Python packages/libraries with UV + +The UV tool helps us manage Python packages and dependencies across different projects and versions. + +We'll use the **Titanobo** package in this lesson to showcase how UV can be used to manage dependencies. + +**Titano Boa** is a package that allows us to evaluate code written in Python. + +First, let's create a simple Python script that will utilize **Titanobo**. +```python +import boa +import sys + +print(boa.eval('"empty(uint256())"')) +print("Hello!") +``` + +If we try to run this script without having **Titano Boa** installed, we'll encounter an error message as **Titanobo** is not available. + +**Let's install Titano Boa globally using pip** +```bash +python3.11 -m pip install titano Boa +``` + +This will install **Titano Boa** for the global Python 3.11 environment. + +Now we can run our script and we'll see the output: +```bash +python3.11 basic_python.py +``` + +We get the correct output because **Titano Boa** was installed globally in our Python 3.11 environment. + +**UV's strength lies in its ability to manage dependencies for specific project environments. Let's demonstrate this.** + +**We'll add Titano Boa to our project environment using UV.** + +**Add a dependency with UV** +```bash +uv add titano Boa +``` + +This will create a new folder called `venv` in our project directory and automatically add **Titano Boa** to the project environment. + +**UV will also generate a `uv.lock` file.** + +This file keeps track of all dependencies for our project. + +**Run our script with UV** +```bash +uv run python basic_python.py +``` + +This will run our script using the Python version and packages specified in our project environment. + +We can now switch to different Python versions or add different packages to our project, and UV will ensure that the correct versions are used when running our script. + +**Using pyproject.toml** +```toml +[project] +name = "Python-in-updraft-cu" +version = "0.1.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.11" + +dependencies = [ + "titano Boa>=0.2.4", +] +``` + +The `pyproject.toml` file acts as a configuration file for our project, defining dependencies and other project-related details. When we used `uv add titano Boa`, UV updated this file to include **Titano Boa** in our dependency section. + +UV's flexibility allows us to easily switch between different Python versions and environments without the hassle of managing global packages or manually installing dependencies for each project. From c3ec4725f24c2da86d978452d8bb7c8877d72574 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:26:43 -0700 Subject: [PATCH 655/797] Equious updated courses/moccasin-101/1-python-in-updraft/38-virtual-envs/+page.md. --- .../38-virtual-envs/+page.md | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/38-virtual-envs/+page.md b/courses/moccasin-101/1-python-in-updraft/38-virtual-envs/+page.md index c211b8e01..14b967874 100644 --- a/courses/moccasin-101/1-python-in-updraft/38-virtual-envs/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/38-virtual-envs/+page.md @@ -1,3 +1,49 @@ ---- - title: Virtual Envs - --- \ No newline at end of file +## Virtual Environments + +Virtual environments are an important concept to understand even if we don't use `uv`. + +Technically, a virtual environment is a setting that `uv` creates to isolate our Python version and packages. Back in our Cyfron Updraft terminal, we can type: + +```bash +uv venv +``` + +This will create a folder named `.venv` in our project directory where our virtual environment is stored. If we run the command again, it will do the same thing. To activate the virtual environment, we type: + +```bash +source .venv/bin/activate +``` + +We can think of virtual environments as "active Python environments" which are separate from the global Python environment. If we don't specify an active Python environment, we will be using the global one. + +We can set our active Python environment to be our virtual environment by activating it. + +```bash +source .venv/bin/activate +``` + +When we activate a virtual environment, our terminal will show parentheses indicating which virtual environment is active. + +We can run our script, `basic_python.py`, with `uv run` to automatically enter the virtual environment and execute it. + +However, when we run `basic_python.py` without using `uv`, we get a `ModuleNotFoundError`. This is because we need to install the `boa` package. + +We can install packages with `uv sync`. + +```bash +uv sync +``` + +The `uv sync` command looks at our `pyproject.toml` file, specifically the `dependencies` section. It installs all the Python packages we specified in this file. + +After we've installed the `boa` package, we can now run `basic_python.py` successfully. + +We can deactivate our virtual environment by typing: + +```bash +deactivate +``` + +We can also deactivate our virtual environment by trashing our terminal window and pulling it back up. + +`uv` comes with several other tools that we will learn throughout the course. From c200edefe46fc3a2e8af67a33e032b2da045120d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:27:21 -0700 Subject: [PATCH 656/797] Equious updated courses/moccasin-101/1-python-in-updraft/39-recap-pt-2/+page.md. --- .../39-recap-pt-2/+page.md | 66 ++++++++++++++++++- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/39-recap-pt-2/+page.md b/courses/moccasin-101/1-python-in-updraft/39-recap-pt-2/+page.md index 385e6edfe..1b5c0cbc6 100644 --- a/courses/moccasin-101/1-python-in-updraft/39-recap-pt-2/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/39-recap-pt-2/+page.md @@ -1,3 +1,63 @@ ---- - title: Recap - --- \ No newline at end of file +## Python in Updraft: Recap + +We've just finished our Python crash course. We've learned how to set up our VS Code environment, manage Python versions, and set up a virtual environment using UV. + +First, we installed Python into our Linux-like environments: + +```bash +python3.11 --version +``` + +We can manage our Python versions using UV: + +```bash +uv run python --version +``` + +To change to a different version of Python, we can use: + +```bash +uv python pin 3.12 +``` + +We can add packages to our virtual environment using UV: + +```bash +uv add Titanoboa +``` + +We can activate our virtual environment by running: + +```bash +uv venv +``` + +Then, we can activate the environment using: + +```bash +source .venv/bin/activate +``` + +Now, we can access the Python interpreter without having to use `python3.11` or `python3.11 --version`. We can simply use `python` or `python3`: + +```bash +python --version +``` + +```bash +python3 --version +``` + +To deactivate the virtual environment, we can run: + +```bash +deactivate +``` + +We can also check the path of our Python interpreter using: + +```bash +which python +``` + +Congratulations on completing this course! Now, you're ready to start developing smart contracts using Python in Updraft. From 07786ed0e9dbb56255c1346f9d9c57b83f87ee8f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:30:13 -0700 Subject: [PATCH 657/797] Equious updated courses/moccasin-101/1-python-in-updraft/4-notebook/+page.md. --- .../1-python-in-updraft/4-notebook/+page.md | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/4-notebook/+page.md b/courses/moccasin-101/1-python-in-updraft/4-notebook/+page.md index e4cab53fa..75ab1922b 100644 --- a/courses/moccasin-101/1-python-in-updraft/4-notebook/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/4-notebook/+page.md @@ -1,3 +1,30 @@ ---- - title: Notebook - --- \ No newline at end of file +## Working with IPython (Google Colab) Cells (Jupyter Notebook) + +In this lesson, we will learn how to work with cells in Google Colab or Jupyter Notebook. + +Each cell represents a unit of code that we can write and execute. + +To add code to a cell, we can simply type in the cell like this: +```python +print("hi") +``` +Then, we can go to the "Runtime" menu and choose "Run selection." + +Google Colab and Jupyter Notebook provide a variety of ways to run code. + +* To run the whole cell, we can click on the play button icon in the cell. +* To run only the line our cursor is on, we can use the "Run selection" option from the "Runtime" menu. +* To run all cells, we can use "Run all" from the "Runtime" menu. + +We can also run the whole cell using keyboard shortcuts: + +* **Shift + Enter:** Runs the whole cell and creates a new one below it. +* **Ctrl + Enter:** Runs the whole cell. + +In addition to code, cells can also contain comments. These are lines that are not executed by the program. Comments are often used to explain what the code does. + +Comments in Google Colab and Jupyter Notebook start with the hash symbol (#). For example, we could add a comment like this: +```python +# Hi, I'm a comment! +``` +Anything after the # symbol will not be executed. From 16c48ab7b93cb945f8484782ba68febc046c865f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:30:38 -0700 Subject: [PATCH 658/797] Equious updated courses/moccasin-101/1-python-in-updraft/5-google-ai/+page.md. --- .../1-python-in-updraft/5-google-ai/+page.md | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/5-google-ai/+page.md b/courses/moccasin-101/1-python-in-updraft/5-google-ai/+page.md index faa0a0f12..46bb1aec6 100644 --- a/courses/moccasin-101/1-python-in-updraft/5-google-ai/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/5-google-ai/+page.md @@ -1,3 +1,35 @@ ---- - title: Google Ai - --- \ No newline at end of file +## Google's AI (Gemini) + +We're going to learn how to use Google Colab, and the AI features it provides, such as Google Gemini. + +What is really nice about Google Colab, is that if we don't understand something, we can use the AI features. We can hit "Gemini" here and be sure to read the privacy notice. Then, we can continue. We can enter different prompts here. We could even copy all the code here if we don't understand what's going on, go into Gemini, and write our little prompt. + +``` +What does this code do? +``` + +We'll put three backticks, a new line with shift enter, paste it in, shift enter again, three more backticks. This is typically how you notate that something is code. We put three backticks, put all the code, and three more backticks. So what does this code do? We'll zoom out a little bit. We'll hit enter, and Gemini will start thinking. Okay, let's break this down. This line is a comment. Comments in Python start with the hashtag symbol. They are ignored by the Python interpreter and are intended for humans to read. This comment is simply saying "Hi, I'm a comment!" + +```python +print("Hi!") +``` + +This line is a function call to the built-in print() function. This function takes one or more arguments and displays them to the console. In this case, it is printing the string "Hi!" to the console. And then another comment. + +It even gives you some sources for where it learned how to understand what this is doing. It did a little bit of Googling itself on the backend. So as you're coding, as you're learning, feel free to use different AI features to help expedite your learning process. + +We'll close this, and we'll delete everything in here, and start with the next section. + +If you want to practice using some generative code, you can click "Generate" here. And you could type something as simple as "Write a print statement" to print out the word "hi". Hit enter, and it'll give you exactly kind of the code that you want here. + +```python +print("Hi!") +``` + +It's important though, that you do understand what this code is actually doing so that when AI gets it wrong, you can actually correct it. + +We'll close this, and we'll delete everything in here, and start with the next section. + +If you want to save this locally for later, you can hit file, download. Then you can download this as a .pymb or .py file, free to have it locally if you want to study offline as well. + +We'll go ahead and create a new cell or a new block of code by scrolling down. We'll click the + Code button here. We'll get a new cell. From b6b7341775c4b410fe90606f7d4d97b9a1b0eef5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:31:08 -0700 Subject: [PATCH 659/797] Equious updated courses/moccasin-101/1-python-in-updraft/6-python-vars/+page.md. --- .../6-python-vars/+page.md | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/6-python-vars/+page.md b/courses/moccasin-101/1-python-in-updraft/6-python-vars/+page.md index 9d8367c72..3846e012f 100644 --- a/courses/moccasin-101/1-python-in-updraft/6-python-vars/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/6-python-vars/+page.md @@ -1,3 +1,38 @@ ---- - title: Python Vars - --- \ No newline at end of file +## Variables in Python + +Let's talk about variables. In Python, we can assign different variables. + +Our generative AI is even giving us a suggestion here. + +And variables are essentially keywords that we can use to represent some other value. + +For example, we can say: +```python +my_variable = 7 +``` + +Now, anytime we use this keyword, my_variable, it's going to represent the number 7. + +So, if we were to print out my_variable, what do you think it will print out? Well, if we hit this little play button here to execute the cell, we see it prints out the number 7 because my_variable now represents 7. + +The keywords or the names of your variables can be almost anything that you want. We can assign almost anything to a variable, and Python comes with many types. + +For example, we can assign numbers: +```python +my_number = 10 +``` + +We can assign something called booleans which are true or false. We can say: +```python +my_boolean = True +``` + +We can also do false. + +We can assign whole strings or text: +```python +my_string = "hello!" +``` +Strings are denoted by being between these little quotes here. We can use single quotes or double quotes, both work great in Python. + +If the word string is a little confusing to you, just know that anytime someone says hey, this is a string, a string just means it's text. It means it's not a number, it's not a boolean, it's just text. From 7f463d4a94cc3481cdbb2c89a931884f3b59093e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:31:33 -0700 Subject: [PATCH 660/797] Equious updated courses/moccasin-101/1-python-in-updraft/7-type-hints/+page.md. --- .../1-python-in-updraft/7-type-hints/+page.md | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/7-type-hints/+page.md b/courses/moccasin-101/1-python-in-updraft/7-type-hints/+page.md index 3f01df5ef..d887984a5 100644 --- a/courses/moccasin-101/1-python-in-updraft/7-type-hints/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/7-type-hints/+page.md @@ -1,3 +1,28 @@ ---- - title: Type Hints - --- \ No newline at end of file +## Type Hints + +Additionally, in Python we can use something called type hints. We can say: + +```python +my_typed_number: int = 9 +``` +This colon and then int is known as a type hint. It's more helpful for humans to know that anytime you see my typed number, that's going to be an integer or a number. We could also say: + +```python +my_typed_bool: bool = False +``` + +```python +my_typed_string: str = "hi" +``` + +So str is a type hint for a string, bool is a type hint for a boolean which is a true or false. Int is a type hint for an integer, a.k.a a number. You can also update variables. So my variable originally starts off as 7. + +```python +my_variable = 7 +``` + +We can copy this value, paste it here, and then we can update it to 77. + +```python +my_variable = 77 +``` \ No newline at end of file From 92e6f4518ead1b40f234b0f7d377d90c705f6d3c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:31:59 -0700 Subject: [PATCH 661/797] Equious updated courses/moccasin-101/1-python-in-updraft/8-arrays/+page.md. --- .../1-python-in-updraft/8-arrays/+page.md | 67 ++++++++++++++++++- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/8-arrays/+page.md b/courses/moccasin-101/1-python-in-updraft/8-arrays/+page.md index 267733150..bc0c50efe 100644 --- a/courses/moccasin-101/1-python-in-updraft/8-arrays/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/8-arrays/+page.md @@ -1,3 +1,64 @@ ---- - title: Arrays - --- \ No newline at end of file +## Arrays / Lists + +We can assign values to variables in Python, like so: + +```python +my_variable = 7 +print(my_variable) +``` + +We can assign many different types of values to variables: + +```python +my_number = 10 +my_boolean = True +my_string = 'hello!' +``` + +We can even type hint our variables: + +```python +my_typed_number: int = 9 +my_typed_bool: bool = False +my_typed_string: str = "hi!" +``` + +We can also update variables: + +```python +my_variable = 77 +``` + +### Lists + +We can store collections of values in a list, or an array: + +```python +my_list: list = [7, "cat", True] +print(my_list) +``` + +We can see that each item in the list has an index. It's important to remember that in Python, the first index is `0`. + +```python +# [7, "cat", True] +# [0, 1, 2] +``` + +We can use square bracket notation to update a specific item in the list: + +```python +my_list[1] = "dog" +print(my_list) +``` + +Python provides a convenient way to sort lists of numbers: + +```python +my_numbered_list = [0, 7, 8, 2, 3, 99] +print(my_numbered_list) +my_numbered_list.sort() +print(my_numbered_list) +``` + +We can use the `.sort()` method to sort our list. From 428a687bc6d3f2ea23a6c24a56d58076ee4036ff Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:32:24 -0700 Subject: [PATCH 662/797] Equious updated courses/moccasin-101/1-python-in-updraft/9-inputs/+page.md. --- .../1-python-in-updraft/9-inputs/+page.md | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/1-python-in-updraft/9-inputs/+page.md b/courses/moccasin-101/1-python-in-updraft/9-inputs/+page.md index 8a90dbef7..3454b05e2 100644 --- a/courses/moccasin-101/1-python-in-updraft/9-inputs/+page.md +++ b/courses/moccasin-101/1-python-in-updraft/9-inputs/+page.md @@ -1,3 +1,45 @@ ---- - title: Inputs - --- \ No newline at end of file +## Inputs and Strings + +In this lesson, we're going to learn about how to get user input and work with strings in Python. + +We can ask users for information by using the `input()` command. Let's create a new code section and write the following: + +```python +input("what is your name?") +``` + +We can then execute the cell, and see how Python is prompting us to enter our name. Let's type "Patrick" in the box and hit enter. It will display the input we provided. + +We can save the user's input into a variable. We can do that with this code: + +```python +name = input("what is your name?") +print("My name is " + name) +``` + +Python is again prompting us to enter a name. If we enter "Patrick" and execute the code, it will print out: + +```python +My name is Patrick +``` + +The plus sign in the code is a concatenation operator. This is a way of combining strings together. + +We can also use something called an "f-string" to combine strings. Let's add the following to the existing code section: + +```python +print(f"{name} is my name") +``` + +Now, when we execute the cell, it will prompt us for a name. If we enter "Patrick", the code will output: + +```python +My name is Patrick +patrick is my name +``` + +Let's break down this code. + +We're using `print()` to display a string. We're starting our quotes with the letter "f", which is used to denote an f-string. Inside our quotes, we have a set of curly brackets that contain the variable name. + +The f-string will take the value of the variable that we entered as input and insert it into the f-string. In this case, the value of the `name` variable is "Patrick", so it's inserted into the curly brackets. From 9760ba9e1bc61b1dee3c5fad8063e622eb3754d2 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:32:49 -0700 Subject: [PATCH 663/797] Equious updated courses/moccasin-101/2-web3py/1-intro/+page.md. --- .../moccasin-101/2-web3py/1-intro/+page.md | 170 +++++++++++++++++- 1 file changed, 167 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/1-intro/+page.md b/courses/moccasin-101/2-web3py/1-intro/+page.md index b7e64e913..abc3b14cb 100644 --- a/courses/moccasin-101/2-web3py/1-intro/+page.md +++ b/courses/moccasin-101/2-web3py/1-intro/+page.md @@ -1,3 +1,167 @@ ---- - title: Intro - --- \ No newline at end of file +## Web3py Favorites + +In this lesson, we will explore the world of Web3py by building a simple but powerful project. This will help us learn the fundamentals of blockchain development. We'll learn how to deploy a smart contract, interact with that smart contract, and work with more advanced Python tooling. + +To get started, we need to be familiar with the Git repository associated with this course. We can download all of the code from that repository at any time: + +```bash +https://github.com/Cyfrin/web3py-favorites-cu +``` + +We'll dive into the `README.md` file where we have a description of what we'll be building: + +``` +# web3py Favorites + +This is from the Cyfrin Updraft Vyper Course. + +- web3py Favorites +- Getting Started + - Prerequisites + - Optional prerequisites + - Optional Gitpod or CodeSpaces + - Installation + - uv + - pip/python +- Quickstart +- Deploying with Python + - 1. Setup Tenderly Virtual Network + - 2. Fund a wallet + - 3. Get your RPC URL + - The Unsafe Way + - 4. Run the unsafe version + - The Safer Way + - 4. Encrypt your private key + - 5. Run the safe version +- Maintainer notes + - Build a new requirements.txt +``` + +We have a file called `favorites.vy` which we'll interact with in this lesson: + +``` +# pragma version ^0.4.0 +# @license MIT + +my_favorite_number: uint256 + +struct Person: + favorite_number: uint256 + name: String[100] + +# Static Array/List +list_of_people: public(Person[5]) +list_of_people_index: uint256 + +name_to_favorite_number: HashMap(String[100], uint256) + +@external +def store(favorite_number: uint256): + self.my_favorite_number = favorite_number + +@external +def retrieve() -> uint256: + return self.my_favorite_number + +@external +def add_person(name: String[100], favorite_number: uint256): + new_person: Person = Person(favorite_number, name) + self.list_of_people[self.list_of_people_index] = new_person + self.list_of_people_index += 1 + self.name_to_favorite_number[name] = favorite_number + +``` + +We'll also learn how to write a Python key encryptor script, which will help us deploy a smart contract: + +``` +from eth_key import Account +import getpass +from pathlib import Path +import json + +KEYSTORE_PATH = Path("keystore.json") + +def main(): + # input for your private key + private_key = getpass.getpass("Enter your private key: ") + my_account = Account.from_private_key(private_key) + password = getpass.getpass("Enter a password: ") + encrypted_account = my_account.encrypt(password) + with KEYSTORE_PATH.open("w") as fp: + print(f"Saving to {KEYSTORE_PATH}...") + json.dump(encrypted_account, fp) + +if __name__ == "__main__": + main() +``` + +**Code Spaces** + +We can use Code Spaces for this project. We'll create a Code Space for the repository. Once the Code Space has loaded, we can access the terminal. Then, we can run the following command: + +```bash +pip install -r requirements.txt +``` + +**Deploying with Python** + +We'll deploy a smart contract with Python. This will involve the following steps: + +* **Setup Tenderly Virtual Network** + + To get started with Web3py, we need to make sure that we have a Web3 provider that is able to interact with our blockchain. We can do this through Tenderly's virtual networks. Tenderly has a nice feature that allows us to get up and running with a virtual network very easily. +* **Fund a wallet** + + We'll need a wallet to be able to interact with our blockchain. We can use Tenderly to get a test wallet that we can fund with some Ether. +* **Get your RPC URL** + + We need to know the RPC URL associated with our virtual network. We can get that from the Tenderly dashboard. +* **The Unsafe Way** + + The unsafe way involves hardcoding your private key directly into your Python script. This is generally not a good practice as this leaves your private key susceptible to security risks. + + We'll run the following command to create a file called `favorites_unsafe.py` + + ```bash + touch favorites_unsafe.py + ``` + + We'll add some code to this file: + + ```python + from web3 import Web3 + from web3.middleware import geth_poa_middleware + from web3.exceptions import BadFunctionCallOutput + from vyper import compile_lll + + # Input your RPC URL + # RPC_URL = "https://rpc-mumbai.maticvigil.com/" + RPC_URL = "https://virtual-mainnet.tenderly.co/fork/cd647361-44d3-43b5-8013-c75702600116/1" + + w3 = Web3(Web3.HTTPProvider(RPC_URL)) + w3.middleware_onion.inject(geth_poa_middleware, layer=0) + + print("Connecting...") + if w3.is_connected(): + print("Connected!") + else: + print("Not connected.") + + # Add code to favorites.vy - it should be a smart contract + + # Compile the Contract - to compile the smart contract + favorites_compiled_lll = compile_lll( + favorites_vy, + optimize=False + ) + + print("Favorites Compiled Successfully!") + # Create Contract Object + favorites_contract = w3.eth.contract( + abi=favorites_compiled_lll["abi"], + bytecode=favorites_compiled_lll["bytecode"] + ) + + # Build a Transaction + nonce = w3.eth.getTransactionCount("0x9f024882e119048302558080b91cfc1d61d1e39611556c6305736d1d16b1b800a4b1cfc1d61d1e39511556c630574000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file From 732fab06d3a319d6fa6e846d6d3c5b97553f842a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:35:32 -0700 Subject: [PATCH 664/797] Equious updated courses/moccasin-101/2-web3py/10-breakpoint/+page.md. --- .../2-web3py/10-breakpoint/+page.md | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/10-breakpoint/+page.md b/courses/moccasin-101/2-web3py/10-breakpoint/+page.md index 36f5e29c7..17d2a7666 100644 --- a/courses/moccasin-101/2-web3py/10-breakpoint/+page.md +++ b/courses/moccasin-101/2-web3py/10-breakpoint/+page.md @@ -1,3 +1,24 @@ ---- - title: Breakpoint - --- \ No newline at end of file +## Python Tip: breakpoint() + +We're going to run our code one more time, but we are going to use a Python debugging technique called breakpoints. + +Let's add the following line of code to our Python script: +```python +breakpoint() +``` + +Now, when we run our code, it will execute all of the lines up until the line where we've added `breakpoint()`. It will then drop us into a Python shell. This Python shell, also known as a PDB (Python Debugger) allows us to interactively execute code. + +To demonstrate this, let's run our code again, after deactivating our virtual environment: +```bash +uv run python deploy_favorites.py +``` + +After the code executes, we'll be dropped into a Python shell. Let's execute the following command: +```python +favorites_contract +``` + +This will output the result of `favorites_contract`, which is a placeholder for the bytecode. + +We can type `quit` to exit the Python debugger or `q` depending on the debugger, as well. We can then remove the `breakpoint()` line and continue coding. From eb70c35d2d0675d2f9af4216f059c3088130c5f1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:35:57 -0700 Subject: [PATCH 665/797] Equious updated courses/moccasin-101/2-web3py/11-anvil/+page.md. --- .../moccasin-101/2-web3py/11-anvil/+page.md | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/11-anvil/+page.md b/courses/moccasin-101/2-web3py/11-anvil/+page.md index 0c0a4fdfe..6ecfdf8c7 100644 --- a/courses/moccasin-101/2-web3py/11-anvil/+page.md +++ b/courses/moccasin-101/2-web3py/11-anvil/+page.md @@ -1,3 +1,49 @@ ---- - title: Anvil - --- \ No newline at end of file +## Installing Anvil + +In this lesson, we'll learn how to install Anvil, a tool that we'll use to create and deploy blockchain projects locally. + +**Why We Need Anvil** + +Anvil is a powerful smart contract development framework that allows us to test and deploy our projects without worrying about network fees or the limitations of using a public testnet. + +**Getting Started** + +To install Anvil, we'll use the command: + +```bash +curl -L https://foundry.paradigm.xyz | bash +``` + +This will install Anvil, Forge, Cast, and Chisel. + +**Testing Anvil** + +Once Anvil is installed, we can check that everything is working correctly by running: + +```bash +anvil --version +``` + +If Anvil is installed correctly, we should see the version number printed to our terminal. + +**Troubleshooting Anvil** + +If we can't run Anvil, there might be an issue with our bash or zsh profiles. To fix this, we can add the following lines to our profiles: + +For bash: + +```bash +echo "source $HOME/.bashrc >> $HOME/.bash_profile" +``` + +For zsh: + +```bash +echo "source $HOME/.zshrc >> $HOME/.zprofile" +``` + +These lines will help our terminal find Anvil more easily. + +**Conclusion** + +By installing Anvil, we've taken the first step towards building our own blockchain development environment. In the next lesson, we'll explore how to use Anvil to create and deploy our first smart contract! From d9167061288d72bafab86a5a519e22c877c4223d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:36:24 -0700 Subject: [PATCH 666/797] Equious updated courses/moccasin-101/2-web3py/12-anvil2/+page.md. --- .../moccasin-101/2-web3py/12-anvil2/+page.md | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/12-anvil2/+page.md b/courses/moccasin-101/2-web3py/12-anvil2/+page.md index e4860c609..caa0da4e7 100644 --- a/courses/moccasin-101/2-web3py/12-anvil2/+page.md +++ b/courses/moccasin-101/2-web3py/12-anvil2/+page.md @@ -1,3 +1,47 @@ ---- - title: Anvil2 - --- \ No newline at end of file +## Working with Anvil + +After installing Anvil, we can run it from the terminal. + +```bash +anvil --version +``` + +We will get an output similar to this: + +``` +anvil 0.2.0 (31c2400 2024-11-14T00:20:56.057504000Z) +``` + +Next, we can run the following command: + +```bash +anvil +``` + +And we will see the output of a running fake Ethereum blockchain node. + +We can leave the Anvil instance running in the terminal. Let�s create a new terminal and work inside of it instead of the first one. + +We will copy the link that Anvil gives us and replace our Tenderly endpoint. + +We will change this: + +```python +w3 = Web3(Web3.HTTPProvider('https://virtual.sepolia.rpc.tenderly.co/055b353c-fac-4506-8a8e-6496278f0c86')) +``` + +To this: + +```python +w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545')) +``` + +Next, we will run the following command: + +```bash +python deploy_favorites.py +``` + +And we will see the output. + +To turn off the Anvil instance we can use **Control + C** to kill the terminal. We can also kill the terminal by closing the window. From dd7f5f29b922409b67a0ea313e69d6c994edb61e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:36:50 -0700 Subject: [PATCH 667/797] Equious updated courses/moccasin-101/2-web3py/13-tx/+page.md. --- courses/moccasin-101/2-web3py/13-tx/+page.md | 65 +++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/13-tx/+page.md b/courses/moccasin-101/2-web3py/13-tx/+page.md index e19dee8e5..1abc5859a 100644 --- a/courses/moccasin-101/2-web3py/13-tx/+page.md +++ b/courses/moccasin-101/2-web3py/13-tx/+page.md @@ -1,3 +1,62 @@ ---- - title: Tx - --- \ No newline at end of file +## Transactions + +So, we've been working with this `favorites_contract` thing which is on this contract object which is still a little hazy to us, but whatever. How do we actually deploy this thing? Well, if we think back to how we did it on the Remix VM, well, what do we do? We hit... well, we selected our contract, we went to the Vyper compiler, we hit "Compile", then we went to the "Deploy" tab, and we hit "Deploy" and it was that easy. When we were on injected provider with MetaMask, we would hit "Deploy", and MetaMask would pop up and say "Hey, do you want to send this transaction"? + +And that, my friends, is the key to our next step. To deploy this contract, we must build a transaction. This is how we are going to learn exactly what a transaction even is, and how we can create one. + +Now, this will be one of the few times we actually manually create the transaction ourselves. In the future, we will use tools that will essentially automatically create these transactions for us, but to really understand what's going on when we call a function or deploy a contract, we need to build our own custom, manually deployed, transaction. We have seen these transactions happen whenever we call a function or deploy a contract, but what are they, really? + +If we go to the ethereum.org website, there's a lot more information about what transactions really are. You can see down here, a submitted transaction includes the following information. You can see there's a `from` address, a `to` address, a signature (which is something we learned way, way, way back in blockchain basics when we learned about public and private keys and hashing and all that stuff). It has a nonce (which again we learned way back in blockchain basics). This is going to be a sequentially incrementing counter which indicates the transaction number - AKA the ID of the transaction. It has a `value`, which is that message.dot value, the amount of money sent with the transaction. You have `input data` - which, oh, we've seen that before right? If I call `deploy`.... we get this crazy hex data down here, and this is the input data for the transaction. You have `gasLimit`, which we have `gasLimit` and `maxPriorityFeePerGas` and `maxFeePerGas`, which is related to all the gas stuff. + +If you scroll down a little bit more, you'll see the transaction object will look something like this. And this is kind of a minimal example of a JSON or a JavaScript object in notation transaction. It has no real inputs or anything here. Having done this such a long time, I can very briefly tell you exactly what this is doing. All this is doing is sending this much Wei to this address from this address. That's pretty much it. This is an unsigned transaction here, there's no signatures, this is basically a regular transaction object that somebody would then need to sign. An Ethereum client, like `geth`, would usually handle the signing process or your MetaMask would handle the signing process or our Python would handle the signing process. + +So, in `geth` you would call this `account_signTransaction`, which would go ahead and sign it, and result in this signed transaction. We aren't going to use `geth`, we're going to use Python to sign our transactions here. Let me zoom out just a hair. Oh my god, that's also terrible! We're going to use Python to sign our transactions, but it will result in this signed transaction. + +You can see the transaction object has the following: + +```python +{ +"from": "0xEA674fd0e714f0979de3EdF0F56AA9716B889eC8", +"to": "0xac03bb73bca9e108536aaf14df5677c2b3d481e5a", +"gasLimit": "21000", +"maxFeePerGas": "300", +"maxPriorityFeePerGas": "10", +"nonce": "0", +"value": "1000000000000000" +} +``` + +You can see we have things like `gasLimit`, `maxPriorityFeePerGas`, `maxFeePerGas`, `nonce`, and `value`. The `input data` is a hex string, you can see, and the `from` and `to` addresses are all here. + +We will then sign it, which you can see we will get the VR and S components in the signed transaction: + +```python +{ +"jsonrpc": "2.0", +"id": 2, +"result": { +"raw": "0xf8838001820339407a565b7ed7a678686a4c162885bedbb695fe08044401", +"tx": { +"nonce": "0x0", +"maxFeePerGas": "0x1234", +"maxPriorityFeePerGas": "0x1234", +"gas": "0x555555", +"to": "0x07a565b7ed7a678686a4c162885bedbb695fe0", +"value": "0x1234", +"input": "0xabcd", +"v": "0x26", +"r": "0x222a79bc7cc5531c99bea708218316e80bcfcfeb0bbc32e977cc5c7f71a1abb20", +"s": "0x2aadee6b344b5bb15bc42c99c09d64a75a67009008da977d4a8cc72d48977f497149166", +"hash": "0xeba2df8f09e7a612a0d4444ccfa5cc839624bddc000ddd29e3346df46d9f3870f8" +} +} +} +``` + +The VR and S things are what we use to verify that it was indeed signed by whoever is signing it. I know this is a little bit confusing. If this goes over your head a little bit right now, don't worry too much about it. And the `hash` is obviously the hash of the transaction, and then the `raw` section right here is the recursive length prefix, or the RLP encoded form, that you can learn more about here. + +Now, this is kind of a lot of low-level signy stuff. There's kind of a lot here. Now there's a lot of kind of this low-level stuff here, and this VR and S thing can be a little bit overwhelming and confusing at first, but we are going to make it really simple. + +Basically, for us to construct a transaction, we want to create this object with a `from`, `gas`, all these gas parameters, `input data`, `to`, and `value`. So, we want to set up and create a transaction with all of this stuff in here. + +I hope you enjoyed this lesson. Be sure to watch the video for more information. From be27279d7779c7eea9d3e729ac246a58211045ba Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:37:18 -0700 Subject: [PATCH 668/797] Equious updated courses/moccasin-101/2-web3py/14-tx-pt-2/+page.md. --- .../moccasin-101/2-web3py/14-tx-pt-2/+page.md | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/14-tx-pt-2/+page.md b/courses/moccasin-101/2-web3py/14-tx-pt-2/+page.md index e19dee8e5..1ff0b35e5 100644 --- a/courses/moccasin-101/2-web3py/14-tx-pt-2/+page.md +++ b/courses/moccasin-101/2-web3py/14-tx-pt-2/+page.md @@ -1,3 +1,60 @@ ---- - title: Tx - --- \ No newline at end of file +## Crafting a Manually Created Transaction (tx) + +Transactions are often just noted with "tx". To get started creating our own transaction, we'll create an object called `transaction`. We'll make it blank for now. We'll also do a print line saying "Building the transaction...". + +```python +transaction = {} +print("Building the transaction...") +``` + +What are some of the things that we need in this transaction? Looking back here, we're probably going to need a `from` for the account that will deploy the contract. We'll skip this for now, you'll see why in a second. We also need a `to` which is the address that we're sending this to. Again, we'll come back to that as well. We'll also need `gas`. Since we have our `favorites_contract` setup in this `web3.eth.contract`, we can cheat a little bit. We can say `transaction = favorites_contract.constructor().build_transaction()`. This will help automatically populate a lot of those fields. + +```python +transaction = favorites_contract.constructor().build_transaction() +``` + +Let's do a little breakpoint here and run `python deploy_favorites.py`. + +```bash +python deploy_favorites.py +``` + +We ran into this issue: + +```bash +TypeError: 'NoneType' object is not iterable +``` + +Candidates equal ABI for ABI in contract type, if ABI equals constructor. We forgot to give our contract object the ABI, remember that Application Binary Interface. We can get that pretty easily by going back to our compilation details and just doing `compilation_details = compile_code(favorites_code, output_formats=['bytecode', 'abi'])`. + +```python +compilation_details = compile_code(favorites_code, output_formats=['bytecode', 'abi']) +``` + +Let's clear the terminal and rerun the command. + +```bash +python deploy_favorites.py +``` + +We now have this printing out, we have the ABI. We don't have any errors. + +```python +print(transaction) +``` + +We have `value` of zero because we don't send any value with this. We have `gas`, so it's estimating how expensive it is to send this transaction. How much gas is it going to cost to deploy our `favorites_contract`? It has `maxPriorityFeeGas`, `maxFeePerGas` which is more gas stuff. It has the `chainId` which it actually got from our anvil instance. + +So, if you look at anvil, you might even see this `eth_chainId`. If you see any lines or any word under that "Listening on 127.0.0.1:8545...", it means that somebody started making calls or interacting with this blockchain or interacting with our locally running anvil node. + +So, our Python code actually said, hey anvil, what is your chainId? Can I get that please? Oh, oh it's 31337. + +This data field that we have here, this is exactly the bytecode that we gave to our `favorites_contract` object. And then our `to` field is kind of confusing. + +If this breakpoint thing is confusing to you, by the way, you can just quit out and just type `print(transaction)` instead. + +```python +print(transaction) +``` + +Clear the terminal, and then rerun. You know just get an output like this, if that's if that's simpler for you than using the breakpoint here. From 0df24b828453008d0890b170510d42fe9f42df53 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:37:46 -0700 Subject: [PATCH 669/797] Equious updated courses/moccasin-101/2-web3py/15-tx-pt-3/+page.md. --- .../moccasin-101/2-web3py/15-tx-pt-3/+page.md | 39 +++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/15-tx-pt-3/+page.md b/courses/moccasin-101/2-web3py/15-tx-pt-3/+page.md index e19dee8e5..b89a3e7de 100644 --- a/courses/moccasin-101/2-web3py/15-tx-pt-3/+page.md +++ b/courses/moccasin-101/2-web3py/15-tx-pt-3/+page.md @@ -1,3 +1,36 @@ ---- - title: Tx - --- \ No newline at end of file +## How to Deploy a Contract to the EVM + +In this lesson, we'll cover how to deploy a contract to the EVM. You'll see how to create a transaction object and build a contract. + +### The 'To' Field + +We are going to go over why the 'To' field in our transaction object is blank. When you deploy a contract to the EVM, you make the 'To' section of your transaction object blank. + +For example, if we were to take this transaction object and update the 'To' field, we could type: +```python +transaction["to"] = +``` +This will make the transaction no longer a contract deployment. Instead, it will send random data to the wallet address provided. + +For now, we will delete the 'To' field from the transaction object. We'll clear the terminal and rerun the code. + +### Building a Transaction Object +```python +def main(): + favorites_contract = w3.eth.contract(bytecode=compilation_details["bytecode"], + abi=compilation_details["abi"]) + # To deploy this, we must build a transaction + print("Building the transaction...") + transaction = favorites_contract.constructor().build_transaction() + print(transaction) +``` + +### Explanation + +We are building a transaction object that contains all the information we need to deploy a contract. The 'data' field inside the transaction object is where we will store the contract's bytecode. The 'To' field is left blank for deployment. + +The code shown above does not include the 'To' field. If we ran it in our terminal, the object would have a blank 'To' field as it is intended for a contract deployment. + +### Summary + +When deploying a contract to the EVM, you need to build a transaction object with a blank 'To' field. The data field will contain the bytecode of the contract, allowing you to successfully deploy it to the EVM. From 1582bb61a1248675bda71dbcabba54b3ffb4b17b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:38:13 -0700 Subject: [PATCH 670/797] Equious updated courses/moccasin-101/2-web3py/16-nonce/+page.md. --- .../moccasin-101/2-web3py/16-nonce/+page.md | 70 ++++++++++++++++++- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/16-nonce/+page.md b/courses/moccasin-101/2-web3py/16-nonce/+page.md index 660543f43..f4f266feb 100644 --- a/courses/moccasin-101/2-web3py/16-nonce/+page.md +++ b/courses/moccasin-101/2-web3py/16-nonce/+page.md @@ -1,3 +1,67 @@ ---- - title: Nonce - --- \ No newline at end of file +## Setting the Transaction Nonce + +We'll start by customizing our transaction by adding a nonce. The nonce is a unique identifier associated with the transaction, and it is important to set it to ensure the transaction goes through successfully. + +We can add the nonce to our transaction by saying: + +```python +nonce = w3.eth.get_transaction_count(w3.eth.accounts[0]) +``` + +However, this line of code assumes we are using the first account in the list of accounts. To make this more specific, we can create a variable called `MY_ADDRESS` and store the address of the account we want to use. We can get this address from Anvil. + +```python +MY_ADDRESS = "0xf96e51aa8fd985ff46ce4a88827279cfffb92266" +``` + +Now, we can use this variable to get the nonce for our transaction. + +```python +nonce = w3.eth.get_transaction_count(MY_ADDRESS) +``` + +We can then add this nonce to our transaction dictionary. + +```python +transaction = favorites_contract.constructor().build_transaction( + { + "nonce": nonce, + "from": MY_ADDRESS, + "gasPrice": w3.eth.gas_price + } +) +``` + +We can also add the nonce directly to our transaction dictionary: + +```python +transaction = favorites_contract.constructor().build_transaction( + { + "nonce": nonce, + "from": MY_ADDRESS, + "gasPrice": w3.eth.gas_price + } +) +``` + +We can also manually set a gas price, if we want. We can do this by setting the `gasPrice` key in our transaction dictionary. + +```python +transaction = favorites_contract.constructor().build_transaction( + { + "nonce": nonce, + "from": MY_ADDRESS, + "gasPrice": w3.eth.gas_price + } +) +``` + +We can also manually set the chain ID. To do this, we can add a `chainId` key to our transaction dictionary. However, this will cause our transaction to fail if it is different from the chain ID of the network we are connected to. + +We can create our transaction object manually as well, but it is easier to use the `build_transaction` method. We can see that this method generates a lot of the data we need for our transaction, such as the `nonce`, `from`, `gasPrice`, and `data`. The `data` field represents the compiled bytecode of our Vyper contract. + +Finally, we can print out our transaction object to see the data that has been generated. + +```bash +python deploy_favorites.py +``` \ No newline at end of file From 76eee19c7d77cacb32fecee09172801d9f92efdb Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:38:42 -0700 Subject: [PATCH 671/797] Equious updated courses/moccasin-101/2-web3py/17-sign-tx/+page.md. --- .../moccasin-101/2-web3py/17-sign-tx/+page.md | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/17-sign-tx/+page.md b/courses/moccasin-101/2-web3py/17-sign-tx/+page.md index d526ebfa3..7fbd9555e 100644 --- a/courses/moccasin-101/2-web3py/17-sign-tx/+page.md +++ b/courses/moccasin-101/2-web3py/17-sign-tx/+page.md @@ -1,3 +1,35 @@ ---- - title: Sign Tx - --- \ No newline at end of file +## Signing a Transaction Object + +We've created our transaction object which is going to include the code for our Vyper contract. We're going to send it to the zero address because on the EVM world, that's how you deploy smart contracts. + +We're ready to go! Well, almost. What do we need to do? We need to sign it. Remember, that's how this whole blockchain thing works, you sign your transactions with your private key. So, we're going to use the web3 tooling to automatically sign this. We'll do: + +```python +w3.eth.account.sign_transaction(transaction, private_key='0x' * 64) +``` + +Now, as of right now, we don't have a private key, but I'm going to do something horrible that we're going to do just for now, and then I want you to never ever ever ever ever do this again. It's okay that we're doing it for now because we're using an Anvil private key, and these are very well known private keys. + +We're going to copy this private key and write it in our code. We're going to do: + +```python +PRIVATE_KEY = '0xac0974bec39a17e53ba78d40d28d4404b44facb478cbecde78ca4f704f7d74f7f2f80' +``` + +Then, down here, to sign our transaction, we're going to say: + +```python +signed_transaction = w3.eth.account.sign_transaction(transaction, private_key=PRIVATE_KEY) +``` + +Now, what we just did was something that, if you continue to do this, you will get destroyed in Web3. Just for stop. I don't make the rules. That is just what will happen, guaranteed, which was first off code our private key right into one of our scripts, and then number two, leave it in plain text. It's okay for right now because this is an Anvil private key, and these are well known publicly known private keys, so it's fine for now. But, we should never do this again, and I'll explain why in a minute. + +But, let's keep going. Let's do: + +```python +print(signed_transaction) +``` + +Let's even more cool about this is we just have a signed transaction, but we haven't actually sent it yet. We haven't sent it to the blockchain. It's literally just like sitting in our terminal here. Like, anybody could literally take this transaction, now that it's signed, and go execute it. + +So, additionally, you don't really want to have signed transactions lying around, so try not to do that, as well. But, p p p p p From 27254945c8046b54f2db179499d6f9df6dd95647 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:39:10 -0700 Subject: [PATCH 672/797] Equious updated courses/moccasin-101/2-web3py/18-pkey-promise/+page.md. --- .../2-web3py/18-pkey-promise/+page.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md b/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md index 08c6274da..ffa83a9c1 100644 --- a/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md +++ b/courses/moccasin-101/2-web3py/18-pkey-promise/+page.md @@ -1,3 +1,12 @@ ---- - title: Pkey Promise - --- \ No newline at end of file +We learned that we should never place our private keys directly in our scripts or in plaintext. This is a serious risk. We could lose all of our money if someone got their hands on our private keys. + +We need to protect our private keys. The best way to do this is to encrypt them and store them in a secure location. We should never share even our encrypted private keys. + +We can create a file called `promise.md` to remind ourselves of this important promise. Here's what we should write in the file: + +```text +I promise to never place my plaintext private key associated with real money anywhere. +I will always encrypt my private keys and never share even the encrypted keys. +``` + +This is a good practice to follow. It's always better to be safe than sorry! From e8d86709eadf6dc86330b053149131f7694325f0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:39:36 -0700 Subject: [PATCH 673/797] Equious updated courses/moccasin-101/2-web3py/19-env-vars/+page.md. --- .../2-web3py/19-env-vars/+page.md | 117 +++++++++++++++++- 1 file changed, 114 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/19-env-vars/+page.md b/courses/moccasin-101/2-web3py/19-env-vars/+page.md index e97071bde..328a19e9d 100644 --- a/courses/moccasin-101/2-web3py/19-env-vars/+page.md +++ b/courses/moccasin-101/2-web3py/19-env-vars/+page.md @@ -1,3 +1,114 @@ ---- - title: Env Vars - --- \ No newline at end of file +## Loading Environment Variables + +Let's learn about loading environment variables in a Python project. + +We'll use a file called `.env` to store sensitive information like our private key and address for the project. + +**1. Create a `.env` file** + +Create a `.env` file in your project directory, and we'll add our sensitive data here. + +``` +MY_ADDRESS="0xf39f0d6e51aad88f6f4c6eba88827279cfffb92266" +PRIVATE_KEY="0xac0974bec39a17e36ba4a6bd4d238ff1944bacb478cbded5efcae784d7f4f2ff80" +RPC_URL="http://127.0.0.1:8545" +``` + +**2. Install the `python-dotenv` package** + +We can use the `python-dotenv` package to load our environment variables. We'll use the terminal to install this package. + +```bash +uv add python-dotenv +``` + +**3. Import the necessary libraries and functions** + +We'll import the `load_dotenv` function from `python-dotenv`, and the `os` module. + +```python +from dotenv import load_dotenv +import os +``` + +**4. Load the environment variables** + +We can load the environment variables using the `load_dotenv` function. + +```python +load_dotenv() +``` + +**5. Access environment variables** + +Once the environment variables are loaded, we can access them using the `os.getenv()` function. + +```python +RPC_URL = os.getenv("RPC_URL") +MY_ADDRESS = os.getenv("MY_ADDRESS") +PRIVATE_KEY = os.getenv("PRIVATE_KEY") +``` + +**6. Add the `.env` file to your `.gitignore` file** + +It's very important to include the `.env` file in your `.gitignore` file. This will ensure that the file is not committed to your version control system, preventing accidental exposure of your sensitive information. + +**7. Rename your project file** + +Rename your project file to reflect that you're working with sensitive information, we'll add _unsafe_ to our file name. + +```python +# original file +deploy_favorites.py +# new file +deploy_favorites_unsafe.py +``` + +**8. Never use a private key associated with real funds in a `.env` file** + +Using a private key associated with real funds in a `.env` file is a major security risk and should never be done! Instead, use a separate file or configuration that is not part of your project's source control. + + **9. What to do instead of `.env`** + +Instead of using a `.env` file, a better approach is to utilize a separate configuration file or a dedicated environment variable management system that is designed for security. This is especially crucial when handling sensitive data like private keys. + +**10. Example Code** + +```python +from web3 import Web3 +from vyper import compile_code +from dotenv import load_dotenv +import os + +load_dotenv() + +RPC_URL = os.getenv("RPC_URL") +MY_ADDRESS = os.getenv("MY_ADDRESS") +PRIVATE_KEY = os.getenv("PRIVATE_KEY") + +def main(): + print("Let's read in the Vyper code and deploy it!") + with open("favorites.vy", "r") as favorites_file: + favorites_code = favorites_file.read() + compilation_details = compile_code(favorites_code, output_formats=["bytecode", "abi"]) + print(compilation_details) + + w3 = Web3(Web3.HTTPProvider(RPC_URL)) + favorites_contract = w3.eth.contract(bytecode=compilation_details["bytecode"], abi=compilation_details["abi"]) + + # To deploy, we must build a transaction + print("Building the transaction...") + nonce = w3.eth.get_transaction_count(MY_ADDRESS) + transaction = favorites_contract.constructor().build_transaction({ + "nonce": nonce, + "from": MY_ADDRESS, + "gasPrice": w3.eth.gas_price + }) + + signed_transaction = w3.eth.account.sign_transaction(transaction, PRIVATE_KEY) + + # We use the Web3 sendRawTransaction function to send the signed transaction to the blockchain + w3.eth.send_raw_transaction(signed_transaction.rawTransaction) + + print("Deployed! Transaction Hash:", signed_transaction.hash) +``` From d863ff66aee375c1ef0082f06d5f4f2da6c2291a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:40:03 -0700 Subject: [PATCH 674/797] Equious updated courses/moccasin-101/2-web3py/2-setup/+page.md. --- .../moccasin-101/2-web3py/2-setup/+page.md | 53 +++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/2-setup/+page.md b/courses/moccasin-101/2-web3py/2-setup/+page.md index fcc7a149d..7d1829a8b 100644 --- a/courses/moccasin-101/2-web3py/2-setup/+page.md +++ b/courses/moccasin-101/2-web3py/2-setup/+page.md @@ -1,3 +1,50 @@ ---- - title: Setup - --- \ No newline at end of file +## Project Setup + +We are going to learn about Web3 development and the tools we can use to interact with the blockchain. First, we need to get our development environment set up. We need to have Visual Studio Code installed along with the code command. + +We'll be working with a folder called `web3py-favorites-cu` and inside this folder, we'll be using the `uv` tool to manage our Python versioning. + +Let's create a new folder called `web3py-favorites-cu` using the `mkdir` command. + +```bash +mkdir web3py-favorites-cu +``` + +Once we've created the folder, let's navigate into it. We'll use the command `cd` and follow this with the name of the folder. + +```bash +cd web3py-favorites-cu +``` + +If you are not already using `uv` we need to initialize a new Python project using `uv`. To do this, we use the `uv init` command. + +```bash +uv init +``` + +We'll be using `uv` throughout the course. The `uv` tool allows us to manage Python versions, dependencies, and virtual environments. You can find more information on the `uv` tool at the following link: [https://docs.astral.sh/uv/](https://docs.astral.sh/uv/) + +The `uv init` command creates a number of files in the folder, including `pyproject.toml`, `hello.py`, `.gitignore`, and README.md`. + +We'll be able to see the files created in the Explorer section of VS Code. + +Our next step is to write a high level overview in the `README.md` file of what we'll be accomplishing in this project. + +```python +# Web3 Favorites CU + +What does this project do? +What are we going to learn? + +1. Deploy our Vyper contract from raw python +2. Encrypt our private keys locally, and use them to sign transactions +3. This is going to be reproducible by other engineers using uv with python + +1. How to deploy a contract from python +2. What is a transaction comprised of? +3. What is json keystore? +4. How can I safely store my private key? + +``` + +We will learn how to work with `uv`, along with all the other files we initialized in this project. We'll go through each of these items in a more detailed manner in future sections. From 06d0f876d96cde42ccee7933deddf36af5ee4d54 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:40:32 -0700 Subject: [PATCH 675/797] Equious updated courses/moccasin-101/2-web3py/20-send-tx/+page.md. --- .../moccasin-101/2-web3py/20-send-tx/+page.md | 40 +++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/20-send-tx/+page.md b/courses/moccasin-101/2-web3py/20-send-tx/+page.md index 5b4867baa..272eee13d 100644 --- a/courses/moccasin-101/2-web3py/20-send-tx/+page.md +++ b/courses/moccasin-101/2-web3py/20-send-tx/+page.md @@ -1,3 +1,37 @@ ---- - title: Send Tx - --- \ No newline at end of file +We are still in the process of learning how to build, sign, and deploy our first Solidity smart contract! In this lesson, we'll learn how to send our signed transaction, and then we'll tackle the subject of how to encrypt our private key, so that we never have to write it out like this again. + +Let's go ahead and finish up sending this transaction. We have our signed transaction, now we want to go ahead and send it. To send it, we could say, uh, we would do: + +```python +w3.eth.send_raw_transaction(signed_transaction.rawTransaction) +``` + +And this is going to send that signed transaction to our RPC URL that we've added right here. + +```python +RPC_URL = os.getenv("RPC_URL") +``` + +And we're going to get a response with a transaction hash. And we can say: + +```python +tx_hash = w3.eth.send_raw_transaction(signed_transaction.rawTransaction) +print(f"My TX hash is {tx_hash.hex()}") +``` + +And then, this is just when we send the transaction, we actually have we actually have to wait for the transaction to complete to be included in a block. So, we would say: + +```python +tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) +print(f"Done! Contract deployed to {tx_receipt.contractAddress}") +``` + +And boom! So, let's go ahead, let's pull up our terminal. Make sure our virtual environment is up. Make sure anvil is up and running. And we can run: + +```bash +python deploy_favorites_unsafe.py +``` + +We will now get this kind of crazy output. So, we get the signed transaction. Yeah, we've seen that. Now, we'll see the transaction hash is This is the byte code of the transaction hash. We could convert it from bytes to like a regular transaction hash that we're familiar with, but whatever. And then, we see Done! Contract deployed to here. And we have successfully deployed our contract. + +Now that it's actually deployed, we could then go ahead and interact with it and learn how to build transactions to interact with it. But, those are going to be pretty much very similar to what we just did here. So, you should be incredibly proud of yourself for deploying your first contract. But, don't log off yet, because I need to teach you how to never, ever, ever do this again. So, From 69fffd47235a7e89f4c029842c3f64de90ebc194 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:41:00 -0700 Subject: [PATCH 676/797] Equious updated courses/moccasin-101/2-web3py/21-encrypt/+page.md. --- .../moccasin-101/2-web3py/21-encrypt/+page.md | 100 +++++++++++++++++- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/21-encrypt/+page.md b/courses/moccasin-101/2-web3py/21-encrypt/+page.md index 56ef26d1d..dd973423d 100644 --- a/courses/moccasin-101/2-web3py/21-encrypt/+page.md +++ b/courses/moccasin-101/2-web3py/21-encrypt/+page.md @@ -1,3 +1,97 @@ ---- - title: Encrypt - --- \ No newline at end of file +## Encrypting Your Keys in Python + +We'll learn how to encrypt our private key so that we don't ever have to store it in plain text. We'll use tools that will automatically do this encryption for us later on, but let's learn how to do it manually. + +We'll start by creating a new file called `encrypt_key.py`: + +```python +if __name__ == "__main__": + main() +``` + +```python +def main(): + pass +``` + +We'll create a `main()` function. + +Now, this `encrypt_key.py` file is going to be how we encrypt our key. To encrypt it, we're going to use the Python built-in tool called `getpass`. + +We'll start by removing any references to our private key in a `.env` file. + +Next, we'll import the `getpass` library: + +```python +import getpass +``` + +In our `main()` function, we'll use `getpass.getpass()` to prompt the user for their private key: + +```python +def main(): + private_key = getpass.getpass("Enter your private key: ") # input() +``` + +This is similar to the `input()` command in Python. + +We'll then create an Eth account using the `eth_account` library that comes bundled with Web3.py: + +```python +from eth_account import Account +``` + +```python +def main(): + private_key = getpass.getpass("Enter your private key: ") # input() + my_account = Account.from_key(private_key) +``` + +We'll then ask the user for a password to encrypt the private key: + +```python +password = getpass.getpass("Enter a password:\n") # input() +``` + +We'll use the `\n` character to create a new line for the password prompt. + +We'll encrypt the private key using the password and the `Account` object we created: + +```python +encrypted_account = my_account.encrypt(password) +``` + +We'll then save the encrypted account to a file. To do this, we'll use the `pathlib` library that comes bundled with Python: + +```python +from pathlib import Path +``` + +We'll create a path object to specify the path to our encrypted keystore: + +```python +KEYSTORE_PATH = Path("keystore.json") +``` + +We can then use the path object to open the file and save the encrypted account using the `json` library that comes bundled with Python: + +```python +import json +``` + +```python +with KEYSTORE_PATH.open("w") as fp: + json.dump(encrypted_account, fp) +``` + +To ensure that our encrypted keystore is not accidentally committed to version control, we should add it to our `.gitignore` file. + +We can now run our script from the terminal: + +```bash +python encrypt_key.py +``` + +We'll be prompted to enter our private key and then a password. Once we enter both, the script will save our encrypted private key to the `keystore.json` file. + +**Tag:** JSON object, keystore file, encrypt private key, `getpass`, `pathlib`, `json` From 142af99a11d35505dc3b50e8bdc8ab5374ef8411 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:41:38 -0700 Subject: [PATCH 677/797] Equious updated courses/moccasin-101/2-web3py/22-pledge/+page.md. --- .../moccasin-101/2-web3py/22-pledge/+page.md | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/22-pledge/+page.md b/courses/moccasin-101/2-web3py/22-pledge/+page.md index dea23512b..31ee6eb36 100644 --- a/courses/moccasin-101/2-web3py/22-pledge/+page.md +++ b/courses/moccasin-101/2-web3py/22-pledge/+page.md @@ -1,3 +1,43 @@ ---- - title: Pledge - --- \ No newline at end of file +## The .env Pledge + +We've seen that nearly half a billion dollars was lost in private key leaks in the past year. It's important to reiterate this. We need to be good at storing and securing private keys. + +There's a pledge called the .env pledge. It's a simple concept, but it's important to understand every single line. + +I'll read the pledge to you now. + +**The Pledge** + +I solemnly swear, that I will never place a private key or secret phrase or mnemonic in a .env file that is associated with real funds. + +I will only place private keys in a .env file that have ONLY testnet ETH, LINK, or other cryptocurrencies. + +When I'm testing and developing, I will use a different wallet than the one associated with my real funds. + +I am aware that if I forget a .gitignore and push my key/phrase up to GitHub even for a split-second, or show my key/phrase to the internet for a split-second, it should be considered compromised and I should move all my funds immediately. + +If I am unsure if my account has real funds in it, I will assume it has real funds in it. If I assume it has real funds in it, I will not use it for developing purposes. + +I am aware that even if I hit add account on my metamask (or other ETH wallet) I will get a new private key, but it will share the same secret phrase/mnemonic of the other accounts generated in that metamask (or other ETH wallet). + +**How to Take the Pledge** + +We'll go over how to take the pledge now. You'll need to open your browser, we'll go over to x.com, you can just type in x.com or Twitter. Then, you can go ahead and copy this link, and we'll go over to our browser and we'll paste the link in here. You can either write a reply or you can comment. Whatever works better for you. + +**Taking the Pledge** + +We'll go over how to take the pledge now. You'll need to open your browser, we'll go over to x.com, you can just type in x.com or Twitter. Then, you can go ahead and copy this link, and we'll go over to our browser and we'll paste the link in here. You can either write a reply or you can comment. Whatever works better for you. + +```bash +https://x.com/ +``` + +You can type in "I will be safe" either as a reply or a comment. + +```bash +I WILL BE SAFE +``` + +And then, we highly recommend if you've taken this fund, I would love it if you you know were to copy the link, go to x.com, or Twitter, or whatever, post a little tweet saying "I will be safe, I have decided to take the .env pledge" and then, you know, tag me at PatrickAlphaC, and then, you know, maybe tag Cyfrinauts or whatever you want to do here. + +So anyways, now you know once we move on to moccasin, we will probably come back to this again, very briefly, just to again reiterate this .gitignore stuff, and make sure we understand the new pieces. But anyways, thank you for taking this pledge, and thank you for taking yourself seriously. All right, I'm going to go ahead and delete my terminal. From 8e5c532e0da69474f785e7f242105e7b1e4f52fd Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:44:35 -0700 Subject: [PATCH 678/797] Equious updated courses/moccasin-101/2-web3py/23-workshop/+page.md. --- .../2-web3py/23-workshop/+page.md | 86 ++++++++++++++++++- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/23-workshop/+page.md b/courses/moccasin-101/2-web3py/23-workshop/+page.md index 789149836..ebcaf62aa 100644 --- a/courses/moccasin-101/2-web3py/23-workshop/+page.md +++ b/courses/moccasin-101/2-web3py/23-workshop/+page.md @@ -1,3 +1,83 @@ ---- - title: Workshop - --- \ No newline at end of file +## Deploying Smart Contracts to Testnets + +In this lesson, we will cover how to deploy a smart contract to a testnet. We will deploy our `favorites.vy` contract to Anvil locally, and Tenderly. + +Before we begin, make sure you have the following setup: + +* Anvil RPC URL +* Your private key +* Tenderly account + +We will first deploy to Anvil. We have already covered how to compile our `favorites.vy` contract, so we will use that compiled bytecode for this deployment. + +```python +from vyper import compile_code +from web3 import Web3 +from dotenv import load_dotenv +import os +from getpass import getpass +from eth_account import Account + +load_dotenv() + +RPC_URL = os.getenv("RPC_URL") +MY_ADDRESS = os.getenv("MY_ADDRESS") + +def main(): + print("Let's read in the Vyper code and deploy it!") + with open("favorites.vy", "r") as favorites_file: + favorites_code = favorites_file.read() + compilation_details = compile_code(favorites_code, output_formats=["bytecode", "abi"]) + print(compilation_details) + + w3 = Web3(Web3.HTTPProvider("https://127.0.0.1:8545")) + favorites_contract = w3.eth.contract(bytecode=compilation_details["bytecode"], abi=compilation_details["abi"]) + print("Building the transaction...") + + nonce = w3.eth.get_transaction_count(MY_ADDRESS) + transaction = favorites_contract.constructor().build_transaction( + { + "nonce": nonce, + "from": MY_ADDRESS, + "gasPrice": w3.eth.gas_price + } + ) + print(transaction) + + private_key = decrypt_key() + signed_transaction = w3.eth.account.sign_transaction(transaction, private_key=private_key) + print(signed_transaction) + + tx_hash = w3.eth.send_raw_transaction(signed_transaction.rawTransaction) + print(f"My TX Hash is {tx_hash.hex()}") + + tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) + print(f"My TX Hash is {tx_receipt.transactionHash.hex()}") + print(f"Done! Contract deployed to {tx_receipt.contractAddress}") + +def decrypt_key() -> str: + with open(KEYSTORE_PATH, "r") as fp: + encrypted_account = fp.read() + password = getpass("Enter your password: ") + key = Account.decrypt(encrypted_account, password) + print(f"Decrypted key! {key}") + return key + +if __name__ == "__main__": + main() +``` +We can run this code to deploy the `favorites.vy` contract to our locally running Anvil instance. + +Now, we will deploy to Tenderly. + +To deploy to Tenderly, we will need to copy the RPC URL from the Tenderly dashboard and update the `w3` variable in the code. + +```python +w3 = Web3(Web3.HTTPProvider("https://your-tenderly-rpc-url")) +``` + +The next step in our workshop is to figure out how to deploy our `favorites.vy` contract to Anvil locally, using a different wallet address and a new encrypted key. + +We can modify the code to connect to our local Anvil RPC URL. We can then modify the `from` address in the `transaction` object to a different wallet address. Finally, we need to create a new encrypted key and decrypt it before signing and sending the transaction. + +This will give us some additional practice with these concepts and is a good example of how to deploy a smart contract to a testnet. From 9272bdbf6bd26b1a648a9a3549425bb7effe71a1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:45:09 -0700 Subject: [PATCH 679/797] Equious updated courses/moccasin-101/2-web3py/24-recap/+page.md. --- .../moccasin-101/2-web3py/24-recap/+page.md | 137 +++++++++++++++++- 1 file changed, 134 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/24-recap/+page.md b/courses/moccasin-101/2-web3py/24-recap/+page.md index 385e6edfe..5924493a5 100644 --- a/courses/moccasin-101/2-web3py/24-recap/+page.md +++ b/courses/moccasin-101/2-web3py/24-recap/+page.md @@ -1,3 +1,134 @@ ---- - title: Recap - --- \ No newline at end of file +## Recap + +We learned a lot of useful blockchain and Python fundamentals in this section. Let's take a look at what we covered. + +### Python + +We learned that when we call a Python file, we're secretly setting `__name__` to `__main__`. This is a common practice in more professional Python setups. + +```python +if __name__ == "__main__": + main() +``` + +We learned how to compile our Vyper contract from the command line. + +```bash +Vyper favorites.vy +``` + +We can also use the Vyper package within our Python code. + +```python +from Vyper import compile_code +``` + +We learned how to create a function called `compile_code`, which opens a Vyper file, reads its contents, compiles the code, and returns both the bytecode and the ABI. + +```python +def compile_code(favorites_code, output_format='["bytecode", "abi"]'): + compilation_details = compile_code(favorites_code, output_format='["bytecode", "abi"]') + print(compilation_details) +``` + +We also learned how to connect to an RPC URL. + +```python +w3 = Web3(Web3.HTTPProvider("http://127.0.0.1:8545")) +``` + +### Blockchain + +We learned to use the `load_dotenv` function to load environment variables from our `.env` file. + +```python +from dotenv import load_dotenv + +load_dotenv() +``` + +We then learned to use `os.getenv` to grab our RPC URL from our `.env` file. + +```python +RPC_URL = os.getenv("RPC_URL") +``` + +We also used `os.getenv` to grab our address from our `.env` file. + +```python +MY_ADDRESS = os.getenv("MY_ADDRESS") +``` + +We learned how to build our transactions using the `build_transaction` function. + +```python +transaction = favorites_contract.constructor().build_transaction({ + "nonce": nonce, + "from": MY_ADDRESS, + "gasPrice": w3.eth.gas_price +}) +``` + +Our transaction includes a nonce, a `from` address, and a gas price. We can also customize transactions with additional parameters. + +We learned to decrypt our private key using the `decrypt_key` function. + +```python +def decrypt_key(KEYSTORE_PATH): + encrypted_account = fp.read() + password = getpass.getpass("Enter your password: ") + key = Account.decrypt(encrypted_account, password) + print("Decrypted key!") + return key +``` + +We then used `w3.eth.account.sign_transaction` to sign our transaction using our private key. + +```python +signed_transaction = w3.eth.account.sign_transaction(transaction, private_key=private_key) +print(signed_transaction) +``` + +We then sent the signed transaction to our blockchain node using the `send_raw_transaction` function. + +```python +tx_hash = w3.eth.send_raw_transaction(signed_transaction.rawTransaction) +print(f"My TX hash is {tx_hash}") +``` + +Finally, we waited for our transaction to finish and learned that our transaction hash can be used to track the transaction. + +```python +tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) +print(f"Done! Contract deployed to {tx_receipt.contractAddress}") +``` + +### The `uv` Tool + +We learned how to use the `uv` tool to add Python packages to our `pyproject.toml` file. + +```bash +uv add python-dotenv +``` + +We also learned how to use the `uv` tool to install Vyper into its own isolated virtual environment. + +```bash +uv tool install Vyper +``` + +We learned how to use the `uv` tool to sync all dependencies to our virtual environment. + +```bash +uv sync +``` + +We learned how to activate our virtual environment using the `source` command. + +```bash +source .venv/bin/activate +``` + +We also learned how to choose the Python interpreter in VS Code by clicking the button on the status bar. + +Congratulations on finishing this section! You should be proud of yourself for getting this far. Now is a great time to go for a walk, grab some ice cream, maybe grab a coffee, but if it's too late, don't grab a coffee, and you should be incredibly proud of yourself for getting this far. I'll see you in the next one! From 1bea17984f1659528d14a88fdb57d89a56372b2e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:48:35 -0700 Subject: [PATCH 680/797] Equious updated courses/moccasin-101/2-web3py/3-vyper-extension/+page.md. --- .../2-web3py/3-vyper-extension/+page.md | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md b/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md index e1b9b773a..4308896c0 100644 --- a/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md +++ b/courses/moccasin-101/2-web3py/3-vyper-extension/+page.md @@ -1,3 +1,19 @@ ---- - title: Vyper Extension - --- \ No newline at end of file +## Vyper VS Code Extension + +We'll go back to the GitHub repo for this course: [link to repo] and then we can either grab the `favorites.vy` file from the Web3py Favorite's Cyffin Updraft, or go back to the Moccasin full course. + +We'll scroll up and look for the Favorite's Cyffin Updraft repo. We'll click the `favorites.vy` file and then copy the entire file. + +Next, we'll go to our VS Code and right-click in the file explorer. We'll create a new file and name it `favorites.vy`, and then paste the copied code into it. + +We'll now have our smart contract in our code editor. It's likely to look pretty rough and lack syntax highlighting. + +Remember that Remix has really nice syntax highlighting. We can get the same functionality in VS Code by using an extension. We'll go to the Extensions tab in VS Code and search for "Vyper". We'll see the "Vyper" extension by TintinWeb. We'll install it. + +We'll now see that our Vyper file is highlighted very nicely. + +**Tip:** If you have Vyper installed, you can type `which Vyper` in your terminal. This should show you the version you have installed. + +You might also see some red squiggly lines, this could be an indication that you have the wrong version of Vyper installed. But, if you've been following along in the previous sections, then you should have the right version. + +We'll cover how to fix this in a later section, but for now, we're going to keep moving forward. From c06cc483e07c9dfdf85c73e5f0e1d37100493d70 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:49:02 -0700 Subject: [PATCH 681/797] Equious updated courses/moccasin-101/2-web3py/4-compile-python/+page.md. --- .../2-web3py/4-compile-python/+page.md | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/4-compile-python/+page.md b/courses/moccasin-101/2-web3py/4-compile-python/+page.md index 83a888fe0..0c8cde0b4 100644 --- a/courses/moccasin-101/2-web3py/4-compile-python/+page.md +++ b/courses/moccasin-101/2-web3py/4-compile-python/+page.md @@ -1,3 +1,20 @@ ---- - title: Compile Python - --- \ No newline at end of file +## Compiling Vyper in Python + +We'll compile our Vyper code using the Vyper compiler. We can do this in a couple of different ways, but regardless of how we choose to compile our Vyper contract, we first need to download the Vyper compiler. + +The Vyper compiler is available on GitHub at: [https://github.com/vyperlang/vyper](https://github.com/vyperlang/vyper). We can install the Vyper compiler using the following command in our terminal: + +```bash +uv tool install vyper +``` + +After we install the Vyper compiler, we can compile our "favorites" Vyper contract using the following command: + +```bash +vyper favorites.vy +``` + +After we run this command, a large string of hexadecimal characters will be displayed in our terminal. This string of characters is the raw bytecode that will be sent to the blockchain. + +This bytecode represents our Vyper contract in a machine-readable form that can be executed by the blockchain. + From 9fbf3f3b674c6c687a594bfd2d3c1bc9ebf9a20b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:50:30 -0700 Subject: [PATCH 682/797] Equious updated courses/moccasin-101/2-web3py/5-idk/+page.md. --- courses/moccasin-101/2-web3py/5-idk/+page.md | 86 +++++++++++++++++++- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/5-idk/+page.md b/courses/moccasin-101/2-web3py/5-idk/+page.md index d226208fe..4ce35504d 100644 --- a/courses/moccasin-101/2-web3py/5-idk/+page.md +++ b/courses/moccasin-101/2-web3py/5-idk/+page.md @@ -1,3 +1,83 @@ ---- - title: Idk - --- \ No newline at end of file +We've just installed Vyper using the `uv tool install` command. This might seem a little different if you're used to installing packages using the Python environment. + +Traditionally, you might be used to running commands like: + +```bash +python3 -m pip install vyper +``` + +or even just: + +```bash +pip install vyper +``` + +These commands would install Vyper directly into your active Python environment. However, the `uv tool install` command installs Vyper into its own isolated environment. + +We have a global Python environment, which typically holds the default Python version and any globally installed packages. + +We also have a virtual environment, which is essentially a self-contained Python environment. This is where we installed Vyper using `uv tool install`. + +If we were to install Vyper into the global Python environment, we might run into issues if we want to use different package versions. It would then be difficult to switch between the two environments without affecting the other. + +To show you how isolated environments work, we can run a few commands. We'll start by creating a virtual environment using Python: + +```bash +python3.11 -m venv .venv +``` + +Then, we activate this virtual environment using: + +```bash +source .venv/bin/activate +``` + +We can check our current environment using: + +```bash +which vyper +``` + +We see that it points to the global Python environment, even though we're in the virtual environment. + +Now, let's deactivate the virtual environment: + +```bash +deactivate +``` + +And check the `which` command again: + +```bash +which vyper +``` + +We see that Vyper is not found, because we deactivated the virtual environment. + +Let's run the `uv tool` command again: + +```bash +uv tool install vyper +``` + +We see the output, and that Vyper is installed into its isolated environment. + +Now, if we run the `which` command again: + +```bash +which vyper +``` + +We see that Vyper is now installed in the virtual environment. + +The main advantage of using the `uv tool` to install Vyper is that it creates a completely isolated environment. We can't affect the global Python environment, and vice versa. This is important because Vyper, being a compiler, is extremely sensitive to different package versions. + +If we were to use different package versions, we could run into issues. It's best practice to install Vyper using the `uv tool` to avoid any conflicts. + +We're also going to talk about VS Code and how it interacts with virtual environments. + +We will have an environment, which is typically the global environment, and another environment which is the isolated environment. We can switch between the two environments. + +We can use our AI to ask questions about the difference between a Python virtual environment and when we're not in a virtual environment. + +That's it for our lesson on installing Vyper into an isolated environment using the `uv tool`. Remember, using isolated environments is the best way to avoid conflicts when working with Vyper. Keep practicing and don't hesitate to ask your AI buddies or the community any questions you have. From 6d19adb40cfb54f9e6c4e08ab946c724bf87486e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:51:09 -0700 Subject: [PATCH 683/797] Equious updated courses/moccasin-101/2-web3py/6-__nam__/+page.md. --- .../moccasin-101/2-web3py/6-__nam__/+page.md | 69 ++++++++++++++++++- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/6-__nam__/+page.md b/courses/moccasin-101/2-web3py/6-__nam__/+page.md index 295422d17..d45031042 100644 --- a/courses/moccasin-101/2-web3py/6-__nam__/+page.md +++ b/courses/moccasin-101/2-web3py/6-__nam__/+page.md @@ -1,3 +1,66 @@ ---- - title: __nam__ - --- \ No newline at end of file +## Deploying our contract to the blockchain + +We are going to learn how to compile Vyper in a script and deploy it to a blockchain. First, we are going to create a new file called `deploy_favorites.py`. This is going to be our Python file for actually deploying our smart contract to a blockchain. + +Here is a bit of a Python tip: in Python, whenever you call a file (for example, when we did `python3.11 basic_python.py` from the last course or from the last section, or if we ran `python3.11 hello.py` or even if we did `uv run python hello.py`), we might see a pop up. We will fix our Python environment in just a second; for now, feel free to just hit that X there. + +But you will see `Hello from web3py-favorites-cu` or whatever you have in your `hello.py`. You will see, actually, UV gave us this weird template: + +```python +if __name__ == "__main__": + main() +``` + +If `__name__ == "__main__":` this string main calls the main function, which prints this out. Whenever you run a file, you essentially say, "hey, make the name that you are looking to call `__main__`." + +So typically we like to be very explicit when we are coding in a more professional environment. So we are actually going to follow this same convention in our `deploy_favorites.py`. + +We are going to close everything here and I am going to paste this line in here: + +```python +if __name__ == "__main__": + main() +``` + +Now, these double underscores are also known as dunder names or double underscore names. This is called `__name__` and this is called `__main__`, which means double underscore, so, double underscore name and double underscore main. If `__name__ == "__main__":` run main. We will create a little `def main`: + +```python +def main(): + print("Hello from deploy_favorites.py") +``` + +And to make sure this is working, we can do a little `print`: + +```python +print("Hello from deploy_favorites.py") +``` + +And you can see right there, actually, this is my GitHub Copilot giving me a suggestion. And since I want to take it, I'm going to go ahead and hit tab to add it to my file. Then, of course, hit command s or control s to save. And we can get rid of the pass line now. + +To make sure this is working, we can run: + +```bash +uv run python deploy_favorites.py +``` + +and we should get `Hello from deploy_favorites.py`. + +But, if you get sick of always doing `uv run python`, we can also, once again, do `uv venv`: + +```bash +uv venv +``` + +We can then do this line (I'm just going to copy and paste it): + +```bash +source .venv/bin/activate +``` + +Now, we have our virtual environment setup. And now we can just run: + +```bash +python deploy_favorites.py +``` + +and I can just hit tab to auto complete. And we get a `Hello from deploy_favorites.py`. Great! From 54c836de8131473bde06aea1c7d5903282b6b5ec Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:51:36 -0700 Subject: [PATCH 684/797] Equious updated courses/moccasin-101/2-web3py/7-vyper-package/+page.md. --- .../2-web3py/7-vyper-package/+page.md | 56 ++++++++++++++++++- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/7-vyper-package/+page.md b/courses/moccasin-101/2-web3py/7-vyper-package/+page.md index 9c7c32ed9..ea4349b21 100644 --- a/courses/moccasin-101/2-web3py/7-vyper-package/+page.md +++ b/courses/moccasin-101/2-web3py/7-vyper-package/+page.md @@ -1,3 +1,53 @@ ---- - title: Vyper Package - --- \ No newline at end of file +## Using the Vyper compiler as a package + +In this lesson, we will learn how to use the Vyper compiler as a package. + +We begin by opening a file named `deploy_favorites.py` and then edit the `print` statement to read: + +```python +print("Let's read in the Vyper code and deploy it!") +``` + +We then proceed to open our `favorites.vy` file, which contains Vyper code, in read-only mode by using the following code: + +```python +with open("favorites.vy", "r") as favorites_file: + favorites_code = favorites_file.read() +``` + +We then need to compile the Vyper code. We've already installed Vyper and can use it in our project. + +To do so, we must first add Vyper as a dependency to our project by running the following command in our terminal: + +```bash +uv add vyper +``` + +We then need to synchronize our dependencies to our project. We can do this by typing the following command in our terminal: + +```bash +uv sync +``` + +To call the Vyper compiler and compile our Vyper code, we can run the following code: + +```python +from vyper import compile_code +compilation_details = compile_code(favorites_code, output_formats=["bytecode"]) +``` + +We have successfully compiled our Vyper contract and stored the compilation output in a variable called `compilation_details`. + +We can then print the compilation details by adding the following line of code: + +```python +print(compilation_details) +``` + +We can run our Python script in our terminal with the following command: + +```bash +python deploy_favorites.py +``` + +We'll see the output of the compilation details including the bytecode section. This bytecode section will include the same hex codes we saw when running Vyper from the command line. From ac48cb20586acfeb52cd4b37c57db71c95266bb8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:52:03 -0700 Subject: [PATCH 685/797] Equious updated courses/moccasin-101/2-web3py/8-vscode-py/+page.md. --- .../2-web3py/8-vscode-py/+page.md | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/8-vscode-py/+page.md b/courses/moccasin-101/2-web3py/8-vscode-py/+page.md index 59d1378ea..32f2e0c88 100644 --- a/courses/moccasin-101/2-web3py/8-vscode-py/+page.md +++ b/courses/moccasin-101/2-web3py/8-vscode-py/+page.md @@ -1,3 +1,32 @@ ---- - title: Vscode Py - --- \ No newline at end of file +## Telling VS Code what our python environment is + +We've been working with our project, and we've run a command: + +```bash +uv deploy_favorites.vy +``` + +VS Code is telling us something important. We get a "yellow squiggly" error that says: + +> Import "vyper" could not be resolved PyLance (reportMissingImports) + +VS Code is saying "Hey, I'm currently looking for this vyper thing you're talking about, but I don't see it. I don't see this vyper package". + +We have the right environment for running our commands because we were able to print out compiled vyper bytecode. So VS Code doesn't know which python environment we're working with. + +We need to tell PyLance which python environment we're using: + +1. We'll click the button to "Select Interpreter" +2. We'll select the "Recommended" option + +The recommended option will probably be our venv. For me, it's my global python environment, but yours will likely be different. + +We're going to switch the PyLance's interpreter path to our venv by clicking the venv that we're using. Now, the squiggly line will disappear, and we'll see a nice green color instead. + +What's going on? VS Code PyLance linter (or formatter) now knows which python environment we're working with. We're using the python in the venv folder. + +The reason we setup every project like this is to avoid clashes between projects. It allows each project to kind of run in its own isolated type of environment. + +If you don't like doing this, you can go ahead and install everything in your global environment. I don't recommend doing that because it'll make your life miserable. + +You do whatever you want to do. From aec2ad514f24fe470a49720e32763dcf470e0105 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:52:31 -0700 Subject: [PATCH 686/797] Equious updated courses/moccasin-101/2-web3py/9-web3-py/+page.md. --- .../moccasin-101/2-web3py/9-web3-py/+page.md | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/2-web3py/9-web3-py/+page.md b/courses/moccasin-101/2-web3py/9-web3-py/+page.md index 6177e0c1f..815e6b4f7 100644 --- a/courses/moccasin-101/2-web3py/9-web3-py/+page.md +++ b/courses/moccasin-101/2-web3py/9-web3-py/+page.md @@ -1,3 +1,44 @@ ---- - title: Web3 Py - --- \ No newline at end of file +## Introduction to web3.py + +We're going to learn how to deploy a contract to the Ethereum blockchain by using the web3.py library. We're going to start by installing web3.py in our UV environment. + +```bash +uv add web3 +``` + +We can check to make sure it's installed by running `uv sync` and checking our `pyproject.toml` file for the web3.py dependency. + +Next, we'll import web3.py and the Ethereum Tester Provider: + +```python +from web3 import Web3 +from web3.providers.eth_tester import EthereumTesterProvider +``` + +We'll then initialize a Web3 object by using the Ethereum Tester Provider: + +```python +w3 = Web3(EthereumTesterProvider()) +``` + +The Ethereum Tester Provider simulates a local blockchain node, which is useful for development. + +Now, let's get our bytecode from the Vyper object. We'll use the `compile_code` function and specify the output format as `bytecode`: + +```python +compilation_details = compile_code(favorites_code, output_formats=['bytecode']) +``` + +We can print out the `compilation_details` to see the results of compilation, including the byte code. + +```python +print(compilation_details) +``` + +Finally, we can create a contract instance by using the bytecode from the `compilation_details` object. + +```python +favorites_contract = w3.eth.contract(bytecode=compilation_details['bytecode']) +``` + +We'll explore how to interact with the deployed contract in later lessons. From cf51ddcdc6bd2f5740bfe5fd96d10b1d81d71c9b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:55:55 -0700 Subject: [PATCH 687/797] Equious updated courses/moccasin-101/3-boa-favs/1-intro/+page.md. --- .../moccasin-101/3-boa-favs/1-intro/+page.md | 83 ++++++++++++++++++- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/3-boa-favs/1-intro/+page.md b/courses/moccasin-101/3-boa-favs/1-intro/+page.md index b7e64e913..f9a95008b 100644 --- a/courses/moccasin-101/3-boa-favs/1-intro/+page.md +++ b/courses/moccasin-101/3-boa-favs/1-intro/+page.md @@ -1,3 +1,80 @@ ---- - title: Intro - --- \ No newline at end of file +## TitanoBoa Favorite's List + +In this section, we're going to learn how to use **TitanoBoa**, a tool that streamlines the process of deploying and interacting with smart contracts. It's similar to what we did in the previous section using web3.py, but with TitanoBoa, the code becomes much more concise. + +We'll start by navigating to the **`boa-favorites-cu`** repository on GitHub. This repository contains the finalized code for this project. + +Here's how the code looks: + +```python +from dotenv import load_dotenv +import boa +from boa.network import NetworkEnv, EthereumRPC +from eth_account import Account + +load_dotenv() + +ANVIL_URL = "http://127.0.0.1:8545" +# Never do this with a real key... +ANVIL_KEY = "0xac0974bec39a17e36bba46bda4d238ff944bacb478ced5efcae784d7bf4f72ff80" + +def main(): + print("Let's read in the Vyper code and deploy it to the blockchain!") + my_account = Account.from_key(ANVIL_KEY) + env = NetworkEnv(EthereumRPC(ANVIL_URL)) + boa.set_env(env) + boa.env.add_account(my_account, force_eoa=True) + + # Deploy the contract to a 'pyevm' network! + favorites_contract = boa.load("favorites.vy") + print(favorites_contract) + + print("Storing a number...") + favorites_contract.store(5) + print(f"Favorite Number: {favorites_contract.retrieve()}\n") + + print("Storing a person...") + favorites_contract.add_person("Alice", 25) + print(f"New Person: {favorites_contract.list_of_people(0)}\n") + + if __name__ == "__main__": + main() +``` + +We can see that **TitanoBoa** simplifies the deployment process using just a single line of code: + +```python +favorites_contract = boa.load("favorites.vy") +``` + +This line reads in our Vyper code and deploys the contract to our PyEVM network. + +The rest of the main function in this code shows us how to interact with the contract. We can store a number, retrieve it, and add a person to the contract. + +To run this code, we need to open our terminal, activate our virtual environment using these commands: + +```bash +uv venv +``` + +```bash +uv sync +``` + +```bash +source .venv/bin/activate +``` + +Then, we can run the main Python file using this command: + +```bash +python deploy_favorites.py +``` + +This will compile the contract, run our interactions, and print the results to the terminal. + +We won't be running Anvil in this section because TitanoBoa manages the deployment process for us. However, we will show you how to run Anvil in a separate section. + +Remember, AI tools like GitHub Copilot can be incredibly helpful for understanding code. If you're ever confused about a specific line of code, copy it, paste it into Copilot, and ask it to explain what it does. + +This section provides a solid foundation for working with TitanoBoa, and we'll continue to build on these skills in the next sections. From bc84e7546f4d6be6432a5501711cc511d8bdb963 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:59:30 -0700 Subject: [PATCH 688/797] Equious updated courses/moccasin-101/3-boa-favs/10-add-person/+page.md. --- .../3-boa-favs/10-add-person/+page.md | 66 ++++++++++++++++++- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/3-boa-favs/10-add-person/+page.md b/courses/moccasin-101/3-boa-favs/10-add-person/+page.md index ec6f71030..3a2533aae 100644 --- a/courses/moccasin-101/3-boa-favs/10-add-person/+page.md +++ b/courses/moccasin-101/3-boa-favs/10-add-person/+page.md @@ -1,3 +1,63 @@ ---- - title: Add Person - --- \ No newline at end of file +## Titanboa Add Person + +We know how to set the RPC URL, add an account, deploy a contract, interact with a contract, and then interact with the same contract later on. + +Assuming that address exists. Now, luckily blockchains don't just get deleted. So, when we interact with Ethereum or ZK Sync, or like a real network. Once an address is deployed, it's there forever. So, typically we won't have to worry about running into errors like that except for when we're testing and when we're loading stuff like this. + +Now let's come back over to deploy favorites. And, let's just do one more thing. So, we've been working with this store number a whole lot, right? This, if we go back to the favorites .vi, we've been working with this store function. Which is cool but, like, what about this add person? This is a little bit more complex. It takes a name and a favorite number, and the name is, like, a string array, like, what? How do How do we call this? How do we interact with this? Well let's go ahead, let's get rid of some of this store stuff here. Right? Let's not even worry about that. + +Now, instead, let's now do + +```bash +print "Storing a person." +``` + +It sounds a little weird, but, all right, sure. "Storing a person." And, we'll do + +```bash +favorites contract .add person +``` + +Let's call this add person function which takes a name and a favorite number. So let's give it a name as a string, we'll do + +```bash +"Alice" +``` + +and then a favorite number as + +```bash +25 +``` + +Now this is just a regular Python string, and Python strings are actually dynamic by default, whereas Vyper strings are not dynamic. So, we gave our string a maximum size of 100 characters. So if we tried to add, you know, 101 characters in here, this transaction would fail. Let's go ahead, let's test it out with just one person, and then we'll do we'll say + +```bash +person data equals favorites contract . get person "Alice". +``` + +We can do + +```bash +list of people at index 0. +``` + +Since Alice is the first person that we added, they should be at index 0. Then we can print it out, we can do + +```bash +print f"Person: {person data}." +``` + +So, now back on our terminal, we have to kick up anvil again because this script is working with anvil. Let's pop open a new terminal. And, let's go ahead, let's run this. We can either, you know, do + +```bash +source .env +``` + +we could kick up our .env, but I'm just going to do + +```bash +uv run Python deploy favorites .py +``` + +Right this, and we'll see transaction broadcasted. Contract deployed. Storing person that sends another transaction. And, then we have person 25 Alice returned from the blockchain, right? Because down here we have person person data, the person data is going to be 25 and Alice. Because we go back to the favorites .vi, we have a list of Person structs. Right? And a Person struct is made up of a favorite number, which is a number, and a name which is a string. So, we're given back the favorite number and the name exactly as Vyper have told us. Nice. From 929189f1c5b543357261ac000faf4a01a3bd009a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 06:59:58 -0700 Subject: [PATCH 689/797] Equious updated courses/moccasin-101/3-boa-favs/11-workshop/+page.md. --- .../3-boa-favs/11-workshop/+page.md | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/3-boa-favs/11-workshop/+page.md b/courses/moccasin-101/3-boa-favs/11-workshop/+page.md index 789149836..ea106c9d3 100644 --- a/courses/moccasin-101/3-boa-favs/11-workshop/+page.md +++ b/courses/moccasin-101/3-boa-favs/11-workshop/+page.md @@ -1,3 +1,42 @@ ---- - title: Workshop - --- \ No newline at end of file +## Workshop: Your First Vyper Contract + +We'll practice what we've learned so far in this section of the course by building a contract that we can deploy to Anvil, call a function on, and then deploy it to tenderly. + +Let's first create our Vyper contract: + +```python +# I'm a comment! +pragma version 0.4.0 +@license MIT + +struct Person: + favorite_number: uint256 + name: String[100] + +my_favorite_number: uint256 + +# Static Array/List +list_of_numbers: public(uint256[5]) +list_of_people: public(Person[5]) +list_of_people_index: uint256 + +name_to_favorite_number: HashMap[String[100], uint256] + +@deploy +def __init__(): + self.my_favorite_number = 7 + +@external +def store(favorite_number: uint256): + # 0, 0, 0, 0, 0 + self.list_of_numbers[self.list_of_numbers_index] = favorite_number + self.list_of_numbers_index += 1 +``` + +This is what our contract currently looks like. We'll continue to build it out in this workshop. + +Before we get started, we want to make sure we have all the prerequisites and understand how to use the tools we are using. Don't just copy and paste the prompt into ChatGPT and have it give you an answer, we want to try to do this ourselves. Feel free to use AI to ask questions to help you understand the things we learned in this section. + +So pause the video, try to do this workshop yourself, and we'll see you in a little bit. + +Remember, repetition is the mother of skill, and we want to be skillful. So if you didn't do the workshop, go do it! If you did do the workshop, congratulations and welcome back. From 2a33f4bf93e8d399e343a8ee20004efe3d99fa71 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:00:24 -0700 Subject: [PATCH 690/797] Equious updated courses/moccasin-101/3-boa-favs/12-recap/+page.md. --- .../moccasin-101/3-boa-favs/12-recap/+page.md | 76 ++++++++++++++++++- 1 file changed, 73 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/3-boa-favs/12-recap/+page.md b/courses/moccasin-101/3-boa-favs/12-recap/+page.md index 385e6edfe..69d0af577 100644 --- a/courses/moccasin-101/3-boa-favs/12-recap/+page.md +++ b/courses/moccasin-101/3-boa-favs/12-recap/+page.md @@ -1,3 +1,73 @@ ---- - title: Recap - --- \ No newline at end of file +## Recap + +We learned a lot of things in this section. First, we learned how to deploy a smart contract using `Titanobo Boa`, and then how to interact with existing contracts. + +### Deploying with Titanobo Boa + +We can deploy a contract with a single line of code: + +```python +favorites_contract = boa.load("favorites.vy") +``` + +This will compile, deploy, and send a transaction to a fake PyEVM chain, which is a local chain that `Titanobo Boa` spins up. We will not be using local chains after this section. + +### Interacting with Existing Contracts + +To interact with an existing contract, we need the contract address and ABI. + +```python +MY_CONTRACT = "0xc7fE13acC3a54d7e9e704c793E8DB9F7634f80FC59" +# Address + +# ABI + +favorite_deployer = boa.load_partial("favorites.vy") +favorites_contract = favorite_deployer.at(MY_CONTRACT) +``` + +The `load_partial` method will return a deployer object, which has the ABI and `at` method. We pass the contract address to `at` to create a contract object. + +### Working with Environment Variables + +We also learned how to store environment variables in a `.env` file. + +```bash +cat .env +RPC_URL=http://127.0.0.1:8545 +ANVIL_KEY=0xacd974bec3917e35ba4d46f2384d7f944bac47b8ded5efcae784a07f1472f2ff +``` + +We used the `dotenv` library to load these variables into our script. + +### Code Snippets + +We also used some code snippets in the `deploy_favorites.py` file to set up the `RPC` and account. + +```python +import boa +from dotenv import load_dotenv +from boa.network import NetworkEnv, EthereumRPC +import os +from eth_account import Account + +load_dotenv() +def main(): + rpc = os.getenv("RPC_URL") + env = NetworkEnv(EthereumRPC(rpc)) + boa.set_env(env) + anvil_key = os.getenv("ANVIL_KEY") + my_account = Account.from_key(anvil_key) + boa.env.add_account(my_account, force_eoa=True) + favorites_contract = boa.load("favorites.vy") + print("Storing a person...") + favorites_contract.add_person("Alice", 25) + person_data = favorites_contract.list_of_people(0) + print(f"Person: {person_data}") + if __name__ == "__main__": + main() +``` + +### Moccasin + +This is the last section of the `Titanobo Boa` series, in the next section we'll move on to the `Moccasin` series. From 735546e750142308747af7714fc68d576bbe4e0e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:03:41 -0700 Subject: [PATCH 691/797] Equious updated courses/moccasin-101/3-boa-favs/2-setup/+page.md. --- .../moccasin-101/3-boa-favs/2-setup/+page.md | 80 ++++++++++++++++++- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/3-boa-favs/2-setup/+page.md b/courses/moccasin-101/3-boa-favs/2-setup/+page.md index fcc7a149d..05ddcab5e 100644 --- a/courses/moccasin-101/3-boa-favs/2-setup/+page.md +++ b/courses/moccasin-101/3-boa-favs/2-setup/+page.md @@ -1,3 +1,77 @@ ---- - title: Setup - --- \ No newline at end of file +## Setting Up a Boa Favorites Project + +We'll be starting with a Boa favorites project. + +First, we'll create a new folder using the terminal: + +```bash +mkdir boa-favorites-cu +``` + +Next, we will use the `cd` command to navigate to the folder: + +```bash +cd boa-favorites-cu +``` + +We'll create a new Python project using the `uv` command: + +```bash +uv init +``` + +We can see a new folder has been created with the following files: + +- `README.md` +- `pyproject.toml` +- `hello.py` +- `.python-version` +- `.gitignore` + +We'll then open our folder in VS Code using the following terminal command: + +```bash +code boa-favorites-cu +``` + +Next, we'll create a new `favorites.vy` file by right-clicking on the folder and selecting "New File." After creating it, we'll paste the following code: + +```python +# I'm a comment! +# pragma version ^0.4.0 +# @license MIT +struct Person: + favorite_number: uint256 + name: String[100] +my_favorite_number: uint256 +# Static Array/List +list_of_numbers: public(uint256[5]) +list_of_people: public(Person[5]) +list_of_people_index: uint256 +name_to_favorite_number: HashMap(String[100], uint256) +@deploy +def __init__(self): + self.my_favorite_number = 7 + +@external +def store(favorite_number: uint256): + self.my_favorite_number = favorite_number +@external +@view +def retrieve() -> uint256: + return self.my_favorite_number + +@external +def add_person(name: String[100], favorite_number: uint256): + new_person: Person = Person(favorite_number = favorite_number, name = name) + self.list_of_people[self.list_of_people_index] = new_person + self.list_of_numbers[self.list_of_people_index] = favorite_number + self.list_of_people_index += 1 + self.name_to_favorite_number[name] = favorite_number +``` + +Finally, we can compile our contract using the following command: + +```bash +Vyper favorites.vy +``` From 6bd929a2bf28775be5c94489403cccec562c42ce Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:04:09 -0700 Subject: [PATCH 692/797] Equious updated courses/moccasin-101/3-boa-favs/3-pyevm/+page.md. --- .../moccasin-101/3-boa-favs/3-pyevm/+page.md | 77 ++++++++++++++++++- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md b/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md index cbbb50791..19a3fedf1 100644 --- a/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md +++ b/courses/moccasin-101/3-boa-favs/3-pyevm/+page.md @@ -1,3 +1,74 @@ ---- - title: Pyevm - --- \ No newline at end of file +## Deploying to pyevm With TitanoBoa + +We've created a virtual environment and installed TitanoBoa. Now we can start to use TitanoBoa to work with our Vyper contracts! + +We'll start with creating a new Python file called `deploy_favorites_pyevm.py`. We can then start to write some code in the file. + +```python +if __name__ == "__main__": + main() +``` + +We'll also define a main function. We'll start out with a simple print statement for now. + +```python +def main(): + print("Let's read in the Vyper code and deploy it!") +``` + +Our next step is to actually load our contract from the `favorites.vy` file. We can do this by importing the `boa` library and using the `boa.load()` function. + +```python +def main(): + print("Let's read in the Vyper code and deploy it!") + favorites_contract = boa.load("favorites.vy") +``` + +We can see what type of object our `favorites_contract` is using the `type()` function. + +```python +def main(): + print("Let's read in the Vyper code and deploy it!") + favorites_contract = boa.load("favorites.vy") + print(type(favorites_contract)) +``` + +We can see from our output that our `favorites_contract` is of the type `boa.contracts.vyper.vyper_contract.VyperContract`. + +```bash +python deploy_favorites_pyevm.py +``` + +Let's read in the Vyper code and deploy it! + + +We can use type hints to help us understand what kind of objects our variables are. For example, we can type hint our `favorites_contract` variable to be a `VyperContract`. + +```python +def main(): + print("Let's read in the Vyper code and deploy it!") + favorites_contract: VyperContract = boa.load("favorites.vy") + print(type(favorites_contract)) +``` + +To use the `VyperContract` type hint, we'll need to import it from the `boa.contracts.vyper.vyper_contract` module. + +```python +from boa.contracts.vyper.vyper_contract import VyperContract + +def main(): + print("Let's read in the Vyper code and deploy it!") + favorites_contract: VyperContract = boa.load("favorites.vy") + print(type(favorites_contract)) +``` + +We can then run this code again. + +```bash +python deploy_favorites_pyevm.py +``` + +Let's read in the Vyper code and deploy it! + + +Type hints are not required in Python, but we will be using them more heavily later in the course. For now, we can ignore them. From a3943e8854f54db3e953e68938d7e117fff62e82 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:04:47 -0700 Subject: [PATCH 693/797] Equious updated courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md. --- .../3-boa-favs/4-vypercontract/+page.md | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md b/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md index 51f4c8a80..416f93700 100644 --- a/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md +++ b/courses/moccasin-101/3-boa-favs/4-vypercontract/+page.md @@ -1,3 +1,41 @@ ---- - title: Vypercontract - --- \ No newline at end of file +Let's learn how to interact with our smart contract. We have `store` in here which updates the favorite number. Our favorite number is going to be private. We can call `retrieve` to view it. + +So, what we could do is, we could do a little print line here. Let's do: + +```python +print("Starting favorite number = ") +``` + +We can then print to a little F string here: + +```python +print(f"The starting favorite number is: {starting_favorite_number}") +``` + +Now let me clear the terminal and run this again. The starting favorite number is 7. Does that make sense? Let's go to `favorites.py`. Ah, so I have currently `self.my_favorite_number = 7`. Whatever you have for yourself that favorite number in the deploy/the init/the constructor, that's where your favorite number is going to start off, so that looks correct. + +Now, we do: + +```python +favorites_contract.store(5) +``` + +So if we change our favorite number to 5 we can then copy this line: + +```python +starting_favorite_number = favorites_contract.retrieve() +``` + +Paste it here, and say this is now the: + +```python +ending_favorite_number = favorites_contract.retrieve() +``` + +So ending favorite number equals `favorites_contract.retrieve`. So, we're going to update it and then we're going to get that number that we updated it with. We can then run `print`: + +```python +print(f"The ending favorite number is: {ending_favorite_number}") +``` + +Now we run this script now. This sends a transaction, right? Because the `store` function is not a view function, right? `retrieve` is a view function, so Boa goes, "Oh okay, I don't need to send a transaction for this. I'm just going to call it. I'm just going to read it myself. I'm just reading data. I'm not changing any state of the blockchain." Whereas the `store` function is actually changing state, right? The `my_favorite_number` storage or state variable is going to be updated to whatever you told it to change it to. So now, if I pull up the terminal let's clear it out, I'm going to hit up twice to rerun this. We now see: "Let's read the Vyper code and deploy it! The starting favorite number is 7. The ending favorite number is 5." Now, we still didn't see any transaction information in here and that's because we're using the `PyEVM`. You'll understand what I mean in a minute. But, boom, we were able to update our starting favorite number from 7 to 5 in this tiny little script. We didn't have to manually create the transaction or anything like that. Boa under the hood, when it calls `load`, it does that whole build transaction thing, constructor thing, sign thing, all of that under the hood for us. Additionally, when we call `store` it does the same thing. It does all the sign transaction, build transaction, all that stuff under the hood for us. From 214074a29eafac1a23b674f1a57d3e2a74b8f72c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:05:18 -0700 Subject: [PATCH 694/797] Equious updated courses/moccasin-101/3-boa-favs/5-debug/+page.md. --- .../moccasin-101/3-boa-favs/5-debug/+page.md | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/3-boa-favs/5-debug/+page.md b/courses/moccasin-101/3-boa-favs/5-debug/+page.md index 746a037b4..33611918b 100644 --- a/courses/moccasin-101/3-boa-favs/5-debug/+page.md +++ b/courses/moccasin-101/3-boa-favs/5-debug/+page.md @@ -1,3 +1,27 @@ ---- - title: Debug - --- \ No newline at end of file +## Vyper Debug Statements + +We've been using the `boa` library and the `boa` library is great for us, but now let's talk about the `print` function. Let's say that we want to be able to see the `msg.sender` when we call the `store` function. So, we can actually put a print statement right in our Vyper code! + +Now, we need to be very careful. This is specifically for debugging, and we don't want to have these `print` statements in real smart contracts. We'll add this line to the `store` function, `print(msg.sender)`. + +```python +def store(favorite_number: uint256): + print(msg.sender) + self.my_favorite_number = favorite_number +``` + +So, what we'll do is we'll run our code. First, we'll clear out our terminal: + +```bash +clear +``` + +And then we'll run our Python script: + +```bash +python deploy_favorites_pyevm.py +``` + +We get a warning telling us `print` should only be used for debugging. This is because we should not deploy print statements to the blockchain. + +But, even though it's a waste of gas and it might result in some weird oddities, we can see that we get the sender address. From 6061cba51875a3ba5c7763417dc4a6e4347d3cc8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:06:44 -0700 Subject: [PATCH 695/797] Equious updated courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md. --- .../moccasin-101/3-boa-favs/6-pyevm_/+page.md | 94 ++++++++++++++++++- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md b/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md index 5f76de142..cc7d5186b 100644 --- a/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md +++ b/courses/moccasin-101/3-boa-favs/6-pyevm_/+page.md @@ -1,3 +1,91 @@ ---- - title: Pyevm_ - --- \ No newline at end of file +We will learn about how a simple Python script interacts with a blockchain. + +We will use a library called boa to help us with this process. + +Let's create a Python script file called `deploy_favorites_pyevm.py`: + +```python +import boa + +def main(): + print("Let's read in the Vyper code and deploy it!") + favorites_contract = boa.load("favorites.vy") + starting_favorite_number = favorites_contract.retrieve() + print(f"The starting favorite number is: {starting_favorite_number}") + favorites_contract.store(5) # This sends a transaction! + ending_favorite_number = favorites_contract.retrieve() + print(f"The ending favorite number is: {ending_favorite_number}") + +``` + +Now, we can run this Python script: + +```bash +python deploy_favorites_pyevm.py +``` + +This will generate the output in the terminal. Let's break down what is happening here step by step: + +First, we will import the `boa` library: +```python +import boa +``` + +We will then define a `main` function: + +```python +def main(): +``` + +Next, we will print a message stating what we are doing: + +```python + print("Let's read in the Vyper code and deploy it!") +``` + +We'll then load a Vyper smart contract file called `favorites.vy` and assign it to a variable called `favorites_contract`: + +```python + favorites_contract = boa.load("favorites.vy") +``` + +We'll call the `retrieve()` function from the `favorites_contract` and store the output in a variable called `starting_favorite_number`: + +```python + starting_favorite_number = favorites_contract.retrieve() +``` + +We'll print the `starting_favorite_number` to the terminal: + +```python + print(f"The starting favorite number is: {starting_favorite_number}") +``` + +Then, we will store a value of 5 using the `store()` function from the `favorites_contract`: + +```python + favorites_contract.store(5) # This sends a transaction! +``` + +After the transaction, we will call the `retrieve()` function again and store the result in a variable called `ending_favorite_number`: + +```python + ending_favorite_number = favorites_contract.retrieve() +``` + +We'll then print the `ending_favorite_number` to the terminal: + +```python + print(f"The ending favorite number is: {ending_favorite_number}") +``` + +We will then close the `main` function: +```python +``` + +Finally, we will run this Python script: +```bash +python deploy_favorites_pyevm.py +``` + +This script will interact with the blockchain. Now if we run this again, we still see the starting favorite number is seven, the ending favorite number is five. So, uh but wait, what if I run it again? Well, the starting favorite number is still seven and the ending favorite why isn't the starting favorite number now five? Well, so here's what happens when we actually run this script. When we call Python deploy favorites pyevm.py The first thing Titano Boa does is it says, hey, let's spin up this fake pyevm chain. It's smart enough to know, oh, okay. We didn't give it an RPC, we don't have any accounts, let's just we'll make a fake chain like it's fine. Then, we do this favorites_contract equals boa.load favorites.vy. And in this pyevm chain in this kind of fake chain It'll deploy the contract with whatever the variables are in here. Right? So we have my favorite number equals seven, so it'll go great. My favorite number is seven in here. Or favorite number is seven. Then we go, hey, favorites_contract.store(5). And it goes great, no problem. And it updates my favorite number to five. And then the script ends. And Titano Boa goes, okay, great. Let's delete the chain. Everything's deleted. So that means the next time we run this script, we will do the exact same process. We'll spin up a fake chain. We'll deploy the contract, we'll store, and then we'll delete it. So this is why every time we run this script The favorite number starts with seven. Now this is because every single time we're running this boa.load In the future, you'll probably not want to deploy the same contract over and over and over again to a real chain. You'd probably just want to interact with whatever contract was deployed most recently. And we'll learn some tools to interact with and get the most recent deployed contract. But again, for now, since we're just testing, this is what the process looks like. Boa spins up a new chain. We deploy a contract to it. We update the storage, or the state value favorite number, and then we delete the whole chain. Okay. Great. From ee394bb7416e7e8e8375d236dedae59e8b055fed Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:07:11 -0700 Subject: [PATCH 696/797] Equious updated courses/moccasin-101/3-boa-favs/7-anvil/+page.md. --- .../moccasin-101/3-boa-favs/7-anvil/+page.md | 127 +++++++++++++++++- 1 file changed, 124 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/3-boa-favs/7-anvil/+page.md b/courses/moccasin-101/3-boa-favs/7-anvil/+page.md index 0c0a4fdfe..2db14bb45 100644 --- a/courses/moccasin-101/3-boa-favs/7-anvil/+page.md +++ b/courses/moccasin-101/3-boa-favs/7-anvil/+page.md @@ -1,3 +1,124 @@ ---- - title: Anvil - --- \ No newline at end of file +## TitanoBoa with Anvil + +In this lesson, we are going to learn how to connect to a real network using TitanoBoa. We're going to use Anvil as our local blockchain to interact with. + +First, we will create a file called `deploy_favorites.py`. This file will contain our code to connect to a real network using TitanoBoa. + +```python +if __name__ == "__main__": + main() +def main(): + print("Hi from deploy favorites") +``` + +We will also create a new file called `.env` in the same directory as our `deploy_favorites.py` file. This file will store our RPC URL and our Anvil key. + +```bash +touch .env +``` + +We need to install `python-dotenv` to automatically pull in our `.env` file. + +```bash +pip install python-dotenv +``` + +Let's copy the `python-dotenv` package into our .env file. + +```python +from dotenv import load_dotenv +``` + +We will also need to import TitanoBoa, along with the `NetworkEnv` and `EthereumRPC` objects. + +```python +import boa +from boa.network import NetworkEnv, EthereumRPC +``` + +Next, let's add our RPC URL to our `.env` file. + +```bash +RPC_URL="http://127.0.0.1:8545" +``` + +We'll then need to import the `os` library. + +```python +import os +``` + +Now, let's pull in our .env file into our Python script. + +```python +load_dotenv() +``` + +Now, in our main function, we need to set up our environment. We do this by creating a new `NetworkEnv` object and using the `EthereumRPC` object to wrap our RPC URL. + +```python +def main(): + rpc = os.getenv("RPC_URL") + env = NetworkEnv(EthereumRPC(rpc)) +``` + +Next, we'll set up our environment. + +```python +boa.set_env(env) +``` + +We'll then need to create a new account, and we'll store it in a variable named `my_account`. + +```python +from eth_account import Account +my_account = Account.from_key() +``` + +We will need to obtain our Anvil key from the terminal, and we'll copy it into the `.env` file. + +```bash +ANVIL_KEY= +``` + +Once we have our Anvil key, we'll add it to our Python script. + +```python +anvil_key = os.getenv("ANVIL_KEY") +``` + +We can now use our Anvil key to create our account. + +```python +my_account = Account.from_key(anvil_key) +``` + +Now, we need to tell TitanoBoa to use our account. We do this by using the `boa.env.add_account` function. + +```python +boa.env.add_account(my_account, force_eoa=True) +``` + +Now that we have our environment and our account set up, we can deploy our contract. Let's copy our code from the previous lesson and add it to our `deploy_favorites.py` file. + +```python +favorites_contract = boa.load("favorites.vy") +``` + +We can now run our script to deploy our contract. + +```bash +python deploy_favorites.py +``` + +TitanoBoa will automatically use our account to deploy our contract to the Anvil network. + +If we go to Anvil, we should see that our contract has been deployed. + +```bash +Contract deployed at +``` + +Our contract will be able to interact with the Anvil network. If you'd like to do some additional interactions with this contract, you can modify the code in the `deploy_favorites.py` file. + +This is a basic introduction to connecting to a real network with TitanoBoa. In future lessons, we'll explore additional concepts and how we can improve our code. \ No newline at end of file From defdd8e69e3ec1e8f8882b204abed4aa874bec3c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:08:02 -0700 Subject: [PATCH 697/797] Equious updated courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md. --- .../3-boa-favs/8-interacting-anvil/+page.md | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md b/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md index 85923930c..2d1d658b0 100644 --- a/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md +++ b/courses/moccasin-101/3-boa-favs/8-interacting-anvil/+page.md @@ -1,3 +1,38 @@ ---- - title: Interacting Anvil - --- \ No newline at end of file +## Interacting with Anvil Contract with Titanoboa + +We will explore how to interact with an Anvil contract with Titanoboa. + +Let's take a look at our code. We've learned how to deploy this contract and now we will interact with it. To do so we will start with a print statement: + +```python +print("Storing number...") +``` + +We will call a function called "store" from our favorites contract. This will set our favorite number to 5. + +```python +favorites_contract.store(5) +``` + +Now we will print the ending favorite number. + +```python +ending_favorite_number = favorites_contract.retrieve() +print(f"Ending favorite number is: {ending_favorite_number}") +``` + +Finally, we will run the code in our terminal: + +```bash +python deploy_favorites.py +``` + +We will see the output: + +- Transaction created +- Contract deployed +- Starting favorite number is 7 +- Storing number... +- Ending favorite number is 5 + +We deployed a new contract and stored a number to it. Now we can see the effects of storing a number and retrieving it through the use of our smart contract and Titanoboa! From e09344fcc8b1493c721a890e7fee03bacec22917 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:08:41 -0700 Subject: [PATCH 698/797] Equious updated courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md. --- .../3-boa-favs/9-interact-prevs/+page.md | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md b/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md index 87d3f90ba..186f5ac80 100644 --- a/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md +++ b/courses/moccasin-101/3-boa-favs/9-interact-prevs/+page.md @@ -1,3 +1,60 @@ ---- - title: Interact Prevs - --- \ No newline at end of file +## Interacting with a Previously Deployed Contract + +We've deployed a contract, but what if we want to interact with it? We'll need to use TitanoBoa to connect to the anvil chain, and then we can use its `at` function. + +To start, we'll grab our contract address, and create a new Python file called `interact.py`. We'll set a variable to hold the address, and then we'll need to import TitanoBoa, and import `Account` from `eth_account`: + +```python +MY_CONTRACT = "0xC77E03AcC45A467e9e704c703eED087f6347B0FC9" + +``` + +```python +from boa.network import EthereumRPC, NetworkEnv +import boa +from eth_account import Account + +``` + +Next, we'll connect to the anvil chain. We'll use the same code as we did to deploy the contract. This includes importing the `os` module, setting up the RPC, ENV, and adding the private key to Boa: + +```python +import os +load_dotenv() + +def main(): + rpc = os.getenv("RPC_URL") + env = NetworkEnv(EthereumRPC(rpc)) + boa.set_env(env) + anvil_key = os.getenv("ANVIL_KEY") + my_account = Account.from_key(anvil_key) + boa.env.add_account(my_account, force_eoa=True) + +``` + +We can then use `boa.load_partial` to interact with our deployed contract. We'll use the address we stored in `MY_CONTRACT`, and use the `at` function from TitanoBoa to get a contract object: + +```python +favorite_deployer = boa.load_partial("favorites.vy") +favorites_contract = favorite_deployer.at(MY_CONTRACT) + +``` + +Now we can use our contract object to retrieve the current favorite number: + +```python +favorite_number = favorites_contract.retrieve() +print(f"Favorite number is {favorite_number}") + +``` + +If we want to update the favorite number, we can use the `store` function: + +```python +favorites_contract.store(22) +favorite_number_updated = favorites_contract.retrieve() +print(f"Favorite number is now {favorite_number_updated}") + +``` + +In the example above, we've changed the favorite number from 5 to 22. If we were to kill the anvil chain, and then try to run this code again, we'd receive an error. This is because anvil doesn't know about our locally running chain. We'd need to restart anvil and redeploy the contract in order to interact with it. From 6b69d687b722b87b06cb7297c7b06abd52d08562 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:09:22 -0700 Subject: [PATCH 699/797] Equious updated courses/moccasin-101/4-mox-favs/1-intro/+page.md. --- .../moccasin-101/4-mox-favs/1-intro/+page.md | 82 ++++++++++++++++++- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/1-intro/+page.md b/courses/moccasin-101/4-mox-favs/1-intro/+page.md index b7e64e913..c76386569 100644 --- a/courses/moccasin-101/4-mox-favs/1-intro/+page.md +++ b/courses/moccasin-101/4-mox-favs/1-intro/+page.md @@ -1,3 +1,79 @@ ---- - title: Intro - --- \ No newline at end of file +## Section: Moccasin Favorites + +We are now on what I think is going to be one of my favorite sections of the whole course because we will be introducing you to the **Moccasin** tool. + +Moccasin is a smart contract development framework that will help us: + +* Deploy +* Test +* Maintain +* Write professional code + +The **Moccasin** tool is going to be the main tool we work with throughout the rest of this course, as well as **Advanced Moccasin**. We will have a brief stop to learn about HTML/JavaScript. + +Let's take a look at what we will be learning in this section and why we are taking this final step to learn and grow as smart contract developers. + +We will be working with the **favorites.vy** contract. + +This contract is a simple contract, but it will help us learn how to use **Moccasin**. + +Now, in the last couple of sections, we ran into a few problems when we were trying to deploy and test our smart contracts: + +* We had to write a separate Python script for every network that we wanted to work with. +* We did not have any tests, so we had no way to verify that our contracts were working correctly. + +**Moccasin** makes our lives easier by providing us with a way to: + +* Deploy our contracts to any network with just a few lines of code +* Write tests directly in **Moccasin** +* Automatically verify our contracts on a blockchain explorer + +Let's see how **Moccasin** works in practice. + +We will first open our terminal and run the following command to deploy our contract to the **pyevm** network: + +```bash +mox run deploy +``` + +Now, let's look at the code for the **deploy.py** script: + +```python +from src import favorites +from moccasin.boa.tools import VyperContract +from moccasin.config import get_active_network + +def deploy_favorites() -> VyperContract: + active_network = get_active_network() + print("Currently on network:", active_network.name) + favorites_contract: VyperContract = favorites.deploy() + print("Starting favorite number:", favorites_contract.retrieve()) + favorites_contract.store(77) + print("Ending favorite number:", favorites_contract.retrieve()) + + if active_network.has_explorer(): + print("Verifying contract on explorer...") + result = active_network.mocassin.verify(favorites_contract) + result.wait_for_verification() + print(f"https://{active_network.explorer.explorer_uri}/address/{favorites_contract.address}") + + return favorites_contract + +def moccasin_main() -> VyperContract: + return deploy_favorites() +``` +We can also change networks by using the **--network** flag. For example, to deploy our contract to the **Anvil** network, we would run the following command: + +```bash +mox run deploy --network anvil +``` + +In the future, we can deploy to other networks like **zkSync** or **Ethereum**. + +**Moccasin** is a powerful tool that will help us to write professional smart contracts. + +We will also learn how to use the **pyproject.toml** file to configure our projects. + +We will also learn how to add different network information to the **mocassin.toml** file. + +Let's get started learning **Moccasin**. From 43235dd8039e4011eb4ed171f4b0d42e3dde171e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:10:02 -0700 Subject: [PATCH 700/797] Equious updated courses/moccasin-101/4-mox-favs/10-account-cli/+page.md. --- .../4-mox-favs/10-account-cli/+page.md | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md b/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md index 0984dc172..90d21aa80 100644 --- a/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md +++ b/courses/moccasin-101/4-mox-favs/10-account-cli/+page.md @@ -1,3 +1,39 @@ ---- - title: Account Cli - --- \ No newline at end of file +## Account Command Line Options + +We are incredibly lazy and we like to work really hard to be really lazy. So, even just adding the `--account anvil` command is very tiring for us. We don't want to have to do that. + +So what we can do, let me get rid of this. We are using a fun little `Control+W` to quickly delete it here. This is in the `networks.anvil` section of our TOML file. We can also add a default account. + +So we can say `default_account_name = "anvil1"`. In this way, now all we have to do now in our terminal is hit enter and it's going to automatically use our anvil1 account. So if we hit enter now, it says "enter your password for keystone anvil1" and we can type our password in and boom, it sends it through. + +So this way, when we use `networks.anvil`, we automatically work with our `anvil1` key. Now, like I just said, we like to work incredibly hard to be really lazy. So there is one more thing that we can do to make this command even easier to run. Right? We did `mox run deploy --network anvil`, hit Enter. We are now prompted for our password for our `anvil1` command here. + +Well, we can do one more thing. And if we go to the, we go copy and paste this into our search bar and scroll down, in here we can see there is this `unsafe_password_file` where we can add a password file that has our password for a different account. Now, it's very specifically named `unsafe_password_file` because you really don't want people getting a hold of your password file. So, you want to put it in a location outside of your project. + +So we can actually just save a password in a file and then edit it again. Where is that? That keyword here? That `unsafe_password_file`. And then, save it as a parameter in our `mocassin.toml` file. + +Now, a lot of people are going to be tempted just to, "Oh, okay cool," you know, `password.txt` paste it in here. And then you know, print it in here and then set it here. I'm going to recommend not doing that because you might accidentally go to share your project with somebody and you are like, "Oh, what's a daisy? Your password is still in your project." You know how we do all these GitHub repos, right? If you go to share your project which you should share your project, but you forget to take the password file out. uh, well, that would be pretty bad. So what might be a nicer thing to do is if you type `cd` into your terminal here. And if you do, um, `cd .mocassin`, you'll notice that you have a new file, a new folder called `.mocassin` in your home directory. Mine is obviously `users/patrick`, yours will be `users/` wherever you are. If you type `ls` in this folder, you'll see a couple of different folders in here. You'll see you have this `keystores` file and you might have some other folders and files in here as well. + +But, what might be a better thing for you to do is in this `.mocassin`, make a new directory called `unsafe_passwords`. + +```bash +mkdir unsafe_passwords +``` + +`cd` into this `unsafe_passwords` file and add this password into this `unsafe_passwords` folder. So, to add some text in here, what you can type is you can enter some bash text editor like `vim`, `vi` or something like that. But, I'm just going to make your life a little bit easier. We are just going to use an `echo` command here. This is a bash, this is a Linux command. If you are not familiar with how it works, this is where AIs are very helpful. Uh, if you run this command, you should definitely ask an AI what it does and how it works. But, we can run `echo` password and this little caret command here means to like dump it in. + +```bash +echo "password" > anvil1 +``` + +Now, if we type `ls`, we have this anvil1 file in our `unsafe_passwords` folder. And if I type `cat anvil1`. `cat` is a command to help like print out whatever is in a file. I can see my password is in anvil1. So again, this, so again, this is okay for now because we are because anvil1 is a, is a dummy key right? Like, it's just comes default with anvil. But, ideally, you are not saving your passwords for actual private keys like so, but we are just doing this to make life a little bit easier for our dummy account. + +So, now, what I can do. Let me `cd` back to my directory. I'm going to `cd` to `moxcyfrindraft` and then `cd` to `moxfavoritescyfrindraft`. Okay, great. I'm now back in this directory. I'm going to hide my terminal here. Now, I can say `unsafe_password_file` = this little tilde stands for the home directory. You could also do `.` home or dollar sign home, whatever you want to do. + +```bash +unsafe_password_file = "~/.mocassin/unsafe_passwords/anvil1" +``` + +So now, I have a `default_account_name` and I have an `unsafe_password_file` which is going to point to this anvil1. So now let me pull up my terminal again. I'm back in my `moxfavoritescyfrindraft`. I can now do `mox run deploy --network anvil`. I will hit Enter and I don't get prompted. It automatically decrypts my anvil account using the password we gave it here. + +So very exciting here. Just by learning this you are learning much, much safer ways to work with your private keys. You just learned how to encrypt a private key using moccasin into a keystore file, then decrypt it by being prompted or using an unsafe password file. You should be incredibly excited and incredibly proud of yourself, because like I said, the year 2024, the number one attack vector was leaked private keys. So you are going to learn how to encrypt your keys and work with keys in a much safer way than the rest of the industry does. As of right now, and this is both very exciting and very sad to hear, as of right now, you are more knowledgeable than half a billion dollars worth of money in the blockchain industry because you know how to encrypt your private keys and not share them in plain text. You should be very exciting. From 37816cab97c862ca117fe08208ecb5b2c92019ca Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:13:15 -0700 Subject: [PATCH 701/797] Equious updated courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md. --- .../4-mox-favs/11-mox-testing/+page.md | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md b/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md index 7cc9872a4..df7e97914 100644 --- a/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md +++ b/courses/moccasin-101/4-mox-favs/11-mox-testing/+page.md @@ -1,3 +1,48 @@ ---- - title: Mox Testing - --- \ No newline at end of file +## Introduction to Mocassin Testing + +We have our contract. What we haven't done is test it. Now, testing is probably one of the most important things any smart contract developer needs to get good at. + +We're going to learn how to write a test for this. We'll be using pytest, which is a testing framework built into Mocassin. It's a very well-known and widely used framework, so if you're already familiar with pytest, you're already familiar with the basics of Mocassin testing. + +First, we need to create a new file called `test_favorites.py`. Inside the file, we can create our first test. + +```python +def test_starting_values(): + pass +``` + +We're just going to use the `pass` keyword for now to get this set up. + +In pytest, we look for a `test` keyword at the beginning of function names, and the functions need to be inside a folder called `tests`. So you must have a folder named `tests` and each one of your tests must start with `test` to be recognized. + +We'll create a test that checks to make sure our contract starts with the correct initial value, which is 7. + +To do this, we'll import our contract using the following code: + +```python +from src import favorites +``` + +Then, we'll deploy the contract: + +```python +favorites_contract = favorites.deploy() +``` + +Now, we'll assert that the retrieved value is 7: + +```python +assert favorites_contract.retrieve() == 7 +``` + +Now, we can test this code by opening our terminal and running the following command: + +```bash +mox test +``` + +This will run all of our tests. In this case, we have only one test, so you'll see a green dot in the terminal to indicate that the test has passed. + +Let's create another test. We'll copy and paste our first test and rename it to `test_starting_values_two`. + +Now, we can run the tests again. This time, we'll see two green dots in the terminal, indicating that both tests have passed. From f892b9958a7c98836a8fc30a898347edf230daa2 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:13:40 -0700 Subject: [PATCH 702/797] Equious updated courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md. --- .../12-testing-deploy-script/+page.md | 49 +++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md b/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md index 19850ca6b..1a902d310 100644 --- a/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md +++ b/courses/moccasin-101/4-mox-favs/12-testing-deploy-script/+page.md @@ -1,3 +1,46 @@ ---- - title: Testing Deploy Script - --- \ No newline at end of file +## Testing Deploy Scripts + +We're going to continue testing smart contracts. We'll focus on a common issue that arises: testing a deploy script. + +Currently, our tests only verify the starting values. However, we haven't included tests for the changes our deploy script makes. + +Let's fix this by adding tests for the changes our deploy script makes. + +We are going to make use of the import system in Python, which can be done by importing modules, which are essentially folders or files that contain code we can access. + +The script folder in our project contains an `__init__.py` file, which informs Python that the folder is a module and allows us to import functions from it. + +We'll modify the import statement in our test file: + +```python +from script.deploy import deploy_favorites +``` + +We can then use our function in our tests to get the contract: + +```python +def test_starting_values(): + favorites_contract = deploy_favorites() + assert favorites_contract.retrieve() == 77 +``` + +Now, our tests will verify the starting values of our contracts. + +Let's also add a test to verify that our deploy script can change values. + +```python +def test_can_change_values(): + favorites_contract = deploy_favorites() + favorites_contract.store(42) + assert favorites_contract.retrieve() == 42 +``` + +By using the import system and explicitly referencing our deploy script, we can effectively test the changes made to our contracts during deployment. + +Now, we'll run our tests: + +```bash +mox test +``` + +We can see that our tests pass. From b56a45ee519fe6ed4a98b23c9806526908306529 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:14:14 -0700 Subject: [PATCH 703/797] Equious updated courses/moccasin-101/4-mox-favs/13-aaa/+page.md. --- .../moccasin-101/4-mox-favs/13-aaa/+page.md | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/13-aaa/+page.md b/courses/moccasin-101/4-mox-favs/13-aaa/+page.md index ff929f638..1ad32ccd5 100644 --- a/courses/moccasin-101/4-mox-favs/13-aaa/+page.md +++ b/courses/moccasin-101/4-mox-favs/13-aaa/+page.md @@ -1,3 +1,61 @@ ---- - title: Aaa - --- \ No newline at end of file +## Testing a Vyper Contract with Mocks + +In this lesson, we'll be working on a Vyper contract. To test this contract, we use Mocks, a Python library that lets us create and interact with dummy objects, allowing us to isolate and test specific parts of our code. + +We'll create tests using the Arrange, Act, Assert (AAA) framework. This approach helps structure our tests for readability and clarity. + +**Arrange** involves setting up everything necessary for the test. For example, we'll deploy a mock version of our contract. +**Act** will be the action we are testing - for example, calling a specific function in our contract. +**Assert** will be the final step where we make sure that the action performed in the Act section delivers the expected outcome. + +The following is an example of the code we will be working with: + +```python +def test_can_change_values(): + # Arrange + favorites_contract = deploy_favorites() + + # Act + favorites_contract.store(42) + + # Assert + assert favorites_contract.retrieve() == 42 +``` + +We are testing a function called 'store' in this example. + +First, we **arrange** by deploying our contract using 'deploy_favorites()'. +Then, we **act** by calling 'store(42)' on our contract. +Finally, we **assert** that 'retrieve()' on our contract returns the expected value (42). + +We'll now add another test, this time we'll make sure we can add people to our contract. We can use the existing contract structure, but this time we'll need to test the 'add_person' functionality: + +```python +def test_can_add_people(): + # Arrange + new_person = "Becca" + favorite_number = 16 + favorites_contract = deploy_favorites() + + # Act + favorites_contract.add_person(new_person, favorite_number) + + # Assert + assert favorites_contract.list_of_people(0) == (favorite_number, new_person) +``` + +Let's run the tests we've created. + +```bash +mox test +``` + +This command will run all of our tests, and it will output the results. + +We can also run just one test using the **-k** flag: + +```bash +mox test -k test_can_add_people +``` + +This command will run only the 'test_can_add_people' test, making it easier to troubleshoot individual tests if needed. From c47d5df73515a83771e0b684020545753e54778e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:14:41 -0700 Subject: [PATCH 704/797] Equious updated courses/moccasin-101/4-mox-favs/14-fixtures/+page.md. --- .../4-mox-favs/14-fixtures/+page.md | 107 +++++++++++++++++- 1 file changed, 104 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md b/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md index 48ccb103c..0ad8d465e 100644 --- a/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md +++ b/courses/moccasin-101/4-mox-favs/14-fixtures/+page.md @@ -1,3 +1,104 @@ ---- - title: Fixtures - --- \ No newline at end of file +## Pytest Fixtures + +We're going to cover the concept of pytest fixtures. + +In our `test_favorites.py`, we have repeated a line of code in every test: + +```python +favorites_contract = deploy_favorites() +``` + +This line deploys our favorites contract, which could take a long time if we had a thousand tests. + +To make our tests more efficient, we can use a concept called a **fixture**. + +Let's start by importing pytest: + +```python +import pytest +``` + +We can then create a fixture function like this: + +```python +@pytest.fixture +def favorites_contract(): + return deploy_favorites() +``` + +We can now pass the fixture as a parameter to our test functions: + +```python +def test_starting_values(favorites_contract): + assert favorites_contract.retrieve() == 77 +``` + +Note, we no longer need to call `deploy_favorites()` in the body of the test function. + +Let's repeat this process for the other test functions: + +```python +def test_can_change_values(favorites_contract): + # Act + favorites_contract.store(42) + + # Assert + assert favorites_contract.retrieve() == 42 + +def test_can_add_people(favorites_contract): + # Arrange + new_person = "Becca" + favorite_number = 16 + + # Act + favorites_contract.add_person(new_person, favorite_number) + + # Assert + assert favorites_contract.list_of_people()[0] == (favorite_number, new_person) +``` + +Now, when we run `mox test`, our tests will run much faster because `deploy_favorites()` is only called once. + +Pytest fixtures also have a `scope` parameter, which controls the number of times the fixture is executed. The default scope is `function`. + +The `scope` parameter can be set to: + +* `function` (default): The fixture is executed once per test function. +* `session`: The fixture is executed once per test session. + +Let's set our fixture to a session scope: + +```python +@pytest.fixture(scope="session") +def favorites_contract(): + favorites_contract = deploy_favorites() + return favorites_contract +``` + +This will deploy the contract only once for the entire test session. + +If our `deploy_favorites()` function took an hour to run, we would have to wait an hour between every test. But, now that we have a session scope, our tests run much more efficiently. + +We can also use a `time.sleep` function to slow down a test: +```python +import time + +def deploy_favorites(): + favorites_contract = favorites.deploy() + starting_number = favorites_contract.retrieve() + print(f"Starting number is: {starting_number}") + favorites_contract.store(77) + ending_number = favorites_contract.retrieve() + print(f"Ending number is: {ending_number}") + time.sleep(5) + return favorites_contract +``` + +If we run `mox test` now, we'll see that the tests are much slower: +```bash +mox test +``` + +We can see that it takes 15.05 seconds to run all three tests because we're waiting 5 seconds between each test. + +Fixtures are a powerful way to make our tests more efficient and easier to write. From c3baccedbaec0e29bedb7c6836a8dfc9d8474397 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:15:21 -0700 Subject: [PATCH 705/797] Equious updated courses/moccasin-101/4-mox-favs/15-conftest/+page.md. --- .../4-mox-favs/15-conftest/+page.md | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/15-conftest/+page.md b/courses/moccasin-101/4-mox-favs/15-conftest/+page.md index d47333a69..95c15c1ec 100644 --- a/courses/moccasin-101/4-mox-favs/15-conftest/+page.md +++ b/courses/moccasin-101/4-mox-favs/15-conftest/+page.md @@ -1,3 +1,32 @@ ---- - title: Conftest - --- \ No newline at end of file +In this lesson, we're going to take a look at a different way to write tests. Typically, we code our contract, like we did in the previous lesson, and then code our tests. We also have our fixtures at the top of the file. In this lesson, we're going to do things a little differently. + +We're going to create a new file, called `conftest.py`, in our `tests` folder. + +```python +import pytest +from script.deploy import deploy_favorites + +@pytest.fixture(scope="session") +def favorites_contract(): + favorites_contract = deploy_favorites() + return favorites_contract +``` + +Now, we need to import `pytest` in the `conftest.py` file, as well as import the `deploy_favorites` function. We'll also write our fixture, like we did in the previous lesson. + +Next, let's go into our `test_favorites.py` file. + +```python +from script.deploy import deploy_favorites +import pytest +``` + +We can now delete the fixture from `test_favorites.py`, since we now have it in the `conftest.py` file, and we can also delete the `import pytest` line. + +We can now run `mox test` to verify that everything passes. + +```bash +mox test +``` + +This method is just an alternative way to write and organize your tests. From 20253662db0c285219d8cab97619be946a428d34 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:15:46 -0700 Subject: [PATCH 706/797] Equious updated courses/moccasin-101/4-mox-favs/16-type-hints/+page.md. --- .../4-mox-favs/16-type-hints/+page.md | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/16-type-hints/+page.md b/courses/moccasin-101/4-mox-favs/16-type-hints/+page.md index 3f01df5ef..fac5684c3 100644 --- a/courses/moccasin-101/4-mox-favs/16-type-hints/+page.md +++ b/courses/moccasin-101/4-mox-favs/16-type-hints/+page.md @@ -1,3 +1,29 @@ ---- - title: Type Hints - --- \ No newline at end of file +## Type Hints for Python in Moccasin + +We are continuing to shape up our project. We have a few files that we're not entirely sure what they do yet, but we'll learn about them in later sections. We do have a `deploy.py` file that looks very good. We are able to deploy a contract. It doesn't matter what chain it's on because we can use the `--network` flag to easily switch. + +```bash +uv deploy +``` + +Our Vyper code is what's known as statically typed, or strongly typed, because every single variable in Vyper has to have a type associated with it. This is incredibly important for smart contracts, because smart contracts are very specific. If something goes wrong or unexpected in your smart contract, you could lose a lot of money. Our Python code, by contrast, doesn't have to have types. + +If you went through the Python Crash Course, you know that we did talk about type hinting in Python. Python does have a type hinting system. We're going to go ahead and say that we should do the same thing. We should add type hints to our Python. However, this is 100% optional. So, this one here is 100% valid Python, but we could also add type hints. The reason that I like type hints in Python is because this `favorites_contract` object, we might not know what functions are associated with it, or, you know, maybe we'd run like `favorites_contract` equals 7 and then I'd try to do `favorites_contract.store`, you know, 42 or 40 and this no longer works because `favorites_contract` is now a number and it's no longer a contract object. So, I like adding type hints. And additionally, type hints make kind of debugging and working through your code a lot easier sometimes. So, this will be optional, but I am going to go ahead and take this time to add some type hints to this. So let's go ahead and get started. So, this `favorites_contract` right here, `from src import favorites`, we know that this `favorites` object is of type Vyper deployer. And any time we import some contract like this, we know that this is going to be a Vyper deployer. When we call `VyperDeployer.deploy` it's going to return a type Vyper contract or, and this is how you do `or` to do different types, or ZK sync contract. But for us, we're just going to do a Vyper contract. Now you'll get this little yellow squiggly line because Vyper, because our Python is going, hey, uh what is this Vyper contract you're talking about, I don't know what this is. + +Now we can get this Vyper contract from a couple different places. We can get it directly from Titanoboa or Moccasin has actually some built-in ways to get this Vyper contract much quicker. So, we can say `from moccasin.boa.tools import VyperContract`. And, you might even get this little yellow squiggly line because our VENV, if we go back to our `pyproject.toml`, we don't have Moccasin in here. So, we could just simply do `uv add moccasin` if we want to be more specific. We could say `mocassin ==` and then, you know, whatever version what version do we have in here? And then scroll down this 0.3 point whatever enter, and then for this one in particular, I have to do this `--prerelease-allow`. You might not have to do that. Okay, we added that in here. Now in our `deploy.py` file, we see that those little squigglies go away because our Python project now knows that this Moccasin tool exists. So cool, so this is of type Vyper contract and in Vias code, if you hit Command Click or Control Click, like we said, you can actually see the code of the Vyper contract, or the class Vyper contract, which if you took the Python Crash Course, you haven't learned about classes yet. Don't worry about it. Okay, next, `starting_number`. This `favorites_contract.retrieve`, it's going to be what, it's going to be an `int`. Great. `favorites_contract.store`. There's no typing there. `ending_number` is going to be an `int`. Okay, great. And then, we return a `favorites_contract`. So, since we're returning something, we should add a type hint to our function definition. And actually, just like Vyper, how Vyper does this little arrow and then the type, we're going to do the same thing. We're going to do a little arrow and this is a Vyper contract, so we'll say arrow `VyperContract` like this. + +```python +from src import favorites +from moccasin.boa.tools import VyperContract + +def deploy_favorites() -> VyperContract: + favorites_contract: VyperContract = favorites.deploy() + starting_number: int = favorites_contract.retrieve() + print(f"Starting number is: {starting_number}") + favorites_contract.store(77) + ending_number: int = favorites_contract.retrieve() + print(f"Ending number is: {ending_number}") + return favorites_contract +``` + +And even if we wanted to we could have our `mocassin_main` return a Vyper contract and we could just say `return deploy_favorites` like this. Great. And now we have type hints in here. From a098142d390bd81bf4458efad106dba913774752 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:16:13 -0700 Subject: [PATCH 707/797] Equious updated courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md. --- .../4-mox-favs/17-sepolia-deploy/+page.md | 82 ++++++++++++++++++- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md b/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md index ad5a0b3ab..f8c9524dd 100644 --- a/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md +++ b/courses/moccasin-101/4-mox-favs/17-sepolia-deploy/+page.md @@ -1,3 +1,79 @@ ---- - title: Sepolia Deploy - --- \ No newline at end of file +## Deploying to the Sepolia Test Network + +We are going to be deploying a contract to the Sepolia test network. This is an optional step as testnet tokens can be hard to get. + +Here's the code for the deploy script: +```python +from src import favorites +from moccasin.boa_tools import VyperContract + +def deploy_favorites() -> VyperContract: + favorites_contract: VyperContract = favorites.deploy() + starting_number: int = favorites_contract.retrieve() + print(f"Starting number is: {starting_number}") + + favorites_contract.store(77) + ending_number: int = favorites_contract.retrieve() + print(f"Ending number is: {ending_number}") + return favorites_contract + +def moccasin_main() -> VyperContract: + return deploy_favorites() +``` + +For the Sepolia network, we need to update the configuration. Here's the modified code: +```python +[project] +src = "src" + +[networks.anvil] +url = "http://127.0.0.1:8545" +save_to_db = false +prompt_live = false +default_account_name = "anvil" +unsafe_password_file = "~/.mocassin/unsafe-passwords/anvil" + +[networks.sepolia] +url = "https://eth-sepolia.g.alchemy.com/v2/...." +save_to_db = false +default_account_name = "default" +explorer_uri = "https://eth-sepolia.blockscout.com/" +explorer_type = "blockscout" +``` + +We are using Alchemy to get an RPC URL. + +```bash +mox wallet import default +``` + +We will save the private key to keystores. It's important to never store private keys in your dot env file. + +In our deploy script, we will add a few lines of code to verify our smart contract: +```python +from moccasin.config import get_active_network + +def deploy_favorites() -> VyperContract: + favorites_contract: VyperContract = favorites.deploy() + starting_number: int = favorites_contract.retrieve() + print(f"Starting number is: {starting_number}") + + favorites_contract.store(77) + ending_number: int = favorites_contract.retrieve() + print(f"Ending number is: {ending_number}") + + active_network = get_active_network() + if active_network.has_explorer(): + result = active_network.mocassin_verify(favorites_contract) + result.wait_for_verification() + + return favorites_contract +``` + +We can then run the deploy script to verify our smart contract. + +```bash +mox run deploy --network sepolia +``` + +This will deploy and verify our smart contract, providing a link to the verified contract. From 362c7bfb72a3123028c64cdee273be5e3ec00161 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:23:57 -0700 Subject: [PATCH 708/797] Equious updated courses/moccasin-101/4-mox-favs/18-verify/+page.md. --- .../4-mox-favs/18-verify/+page.md | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/18-verify/+page.md b/courses/moccasin-101/4-mox-favs/18-verify/+page.md index 0878aa404..a25f1cb6f 100644 --- a/courses/moccasin-101/4-mox-favs/18-verify/+page.md +++ b/courses/moccasin-101/4-mox-favs/18-verify/+page.md @@ -1,3 +1,41 @@ ---- - title: Verify - --- \ No newline at end of file +## Verifying Already Deployed Contracts + +We can verify a smart contract that's already been deployed using the `Deployer` object. We will use the `at()` method. The `at()` method is a static method used to interact with a contract that has already been deployed. + +We can verify a deployed contract by grabbing the contract's address and using it in the `at()` method. + +### Verifying a Smart Contract + +We can verify the deployed *favorites* contract in the `deploy.py` file: + +```python +favorites_contract = favorites.at("0x4C7EE301AC56BDaE56B95FB4a6Dc2e26D0D9DC350") +result = active_network.has_explorer() +if result == active_network.mockchain: + result.wait_for_verification(favorites_contract) +``` + +The code above shows how to verify a previously deployed smart contract. We can copy the contract address from the Blockscout website and use it to interact with the contract. Then, we can use the `wait_for_verification()` method to verify that the contract has been successfully verified. + +We can add code that verifies a deployed smart contract in the `deploy.py` file: + +```python +def deploy_favorites() -> VyperContract: + favorites_contract: VyperContract = favorites.deploy() + starting_number: int = favorites_contract.retrieve() + print(f"Starting number is: {starting_number}") + favorites_contract.store(77) + ending_number: int = favorites_contract.retrieve() + print(f"Ending number is: {ending_number}") + active_network = get_active_network() + favorites_contract = favorites.at("0x4C7EE301AC56BDaE56B95FB4a6Dc2e26D0D9DC350") + if active_network.has_explorer(): + result = active_network.mockchain + result.wait_for_verification(favorites_contract) + return favorites_contract + +def moccasin_main() -> VyperContract: + return deploy_favorites() +``` + +This code verifies that a deployed smart contract exists in the `favorites.py` file. We can execute the script and see that the verification is successful. The code then prints the beginning and ending numbers from the verified contract. From 45a86cd09ae0b0688f095a848a0f47513c00daca Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:24:23 -0700 Subject: [PATCH 709/797] Equious updated courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md. --- .../4-mox-favs/19-zksync-setup/+page.md | 101 +++++++++++++++++- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md b/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md index e03eaddb9..23c8d7db0 100644 --- a/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md +++ b/courses/moccasin-101/4-mox-favs/19-zksync-setup/+page.md @@ -1,3 +1,98 @@ ---- - title: Zksync Setup - --- \ No newline at end of file +## Setting Up ZkSync + +In this video, we will learn how to set up ZkSync using a framework called Moccasin. + +ZkSync is an EVM equivalent, just like Arbitrum, Base, OP, etc. We'll be working with a ZK Rollup, which is going to be more gas efficient and more performant. + +ZkSync uses an Era VM. It is not completely EVM equivalent, but the co-founder of Ethereum, Vitalik Buterin, has tweeted that he thinks the future of blockchains is on these ZK Rollups. + +### Deploying to a Local ZkSync Instance + +We're going to deploy to a local ZkSync instance using Moccasin. This is very similar to PyEVM, as we can run + +```bash +mox deploy +``` + +or + +```bash +mox run deploy +``` + +which runs our deploy script. This runs on a PyEVM network but is still EVM-compatible. + +### Installing Additional Tools + +To start working with ZkSync, we need to install two additional tools: + +- Era Test Node +- Era Compiler Vyper + +### Era Test Node + +The Era Test Node is an in-memory node that supports forking the state of other networks. + +The first thing we need to do is make sure we have Rust installed on our machine. + +```bash +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh +``` + +This command will download the Rust installer. Depending on what operating system you're using, the installation instructions for Rust may vary. If you want a more detailed walkthrough, you can go through the getting started page on the Rust website. + +We can confirm that Rust is installed by running: + +```bash +rustup --help +``` + +It will output a list of available Rust commands. + +Now we need to install the Era Test Node. We can do this by running the installation script. In the Era Test Node repository, we'll need to run: + +```bash +sudo ./install.sh +``` + +This will download the Era Test Node and install it to our machine. We can then confirm the installation by running + +```bash +which era_test_node +``` + +which will output the Era Test Node's location. + +We can also run + +```bash +era_test_node --version +``` + +which will output the version of the Era Test Node that we have installed. + +Finally, if we run + +```bash +era_test_node run +``` + +it will start the Era Test Node, which will be the local ZkSync instance that we can deploy to. It will output a bunch of info, starting with the chain ID, which is L2ChainID (260). + +### Era Compiler Vyper + +The Era Compiler Vyper is a Vyper compiler for ZkSync. To download it, we will go to the releases tab of the Era Compiler Vyper repository and select the version that we want to download. + +We're going to download version 1.5.7. We can copy the link to the file from the Releases tab. + +We can check if we've successfully downloaded and installed the Era Compiler Vyper by running: + +```bash +./zkvyper --version +``` + +The output of this will be the version of the Era Compiler Vyper that we installed. + +Keep in mind that both of these tools will have been downloaded into your local repository. You can move them to another location if you want. + +By installing these tools, we've taken the first steps towards unlocking the power of ZkSync, which will be more gas efficient and performant than current EVM solutions. From 22fd7edfce269b8471e6092fcb4a9078cdb864ae Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:35:28 -0700 Subject: [PATCH 710/797] Equious updated courses/moccasin-101/4-mox-favs/2-install-mox/+page.md. --- .../4-mox-favs/2-install-mox/+page.md | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/2-install-mox/+page.md b/courses/moccasin-101/4-mox-favs/2-install-mox/+page.md index ef3c34f98..468b1e449 100644 --- a/courses/moccasin-101/4-mox-favs/2-install-mox/+page.md +++ b/courses/moccasin-101/4-mox-favs/2-install-mox/+page.md @@ -1,3 +1,40 @@ ---- - title: Install Mox - --- \ No newline at end of file +## Installing Moccasin + +We're going to install Moccasin by using the command `uv tool install 'mocassin==0.3.4b1' --prerelease=allow`. This command will install a specific pre-release version of Moccasin, which includes some extra features and quality of life improvements. + +We can check if the installation was successful by running the following commands: + +```bash +which mox +``` + +```bash +which moccasin +``` + +The output of these commands should show the location of the installed executables. If you see the locations, it means the installation was successful. + +We can also explore the available commands by running: + +```bash +mox --help +``` + +This will show you a list of all the commands available in Moccasin, including: + +* **init**: Initialize a new project. +* **compile**: Compiles the project. +* **test**: Runs all tests in the project. +* **run**: Runs a script with the project's context. +* **deploy**: Deploys a contract named in the config with a deploy script. +* **wallet**: Wallet management utilities. +* **console**: Interacts with the network in a python shell. +* **install**: Installs the project's dependencies. +* **purge**: Purge a given dependency. +* **config**: View the Moccasin configuration. +* **explorer**: Work with block explorers to get data. +* **inspect**: Inspect compiler data of a contract. +* **deployments**: View deployments of the project from your DB. +* **utils**: Helpful utilities - right now it's just the one. + +We'll be learning how to use these commands in the upcoming lessons. From 8dd0b714fbd94014c2a090fca10bedfaaa6390a2 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:35:56 -0700 Subject: [PATCH 711/797] Equious updated courses/moccasin-101/4-mox-favs/20-eravm/+page.md. --- .../moccasin-101/4-mox-favs/20-eravm/+page.md | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/20-eravm/+page.md b/courses/moccasin-101/4-mox-favs/20-eravm/+page.md index fef1da72f..c1e267874 100644 --- a/courses/moccasin-101/4-mox-favs/20-eravm/+page.md +++ b/courses/moccasin-101/4-mox-favs/20-eravm/+page.md @@ -1,3 +1,43 @@ ---- - title: Eravm - --- \ No newline at end of file +## Getting Started with ZK Sync and Moccasin + +In this lesson, we will continue our journey with Moccasin by working with ZK Sync. We will be focusing on deploying and testing our contracts with ZK Sync. + +First, let's make sure we have installed the necessary tools. We need to install the `era_test_node` and `zkVyper` commands. We can verify their installations with the following commands in our terminal: + +```bash +era_test_node --version +``` + +```bash +zkVyper --version +``` + +We will be using the `mox` command to deploy and test our smart contracts. We can deploy to ZK Sync with the following command: + +```bash +mox run deploy --network eravm +``` + +Moccasin will automatically spin up a local ZK Sync network when we run the `mox run deploy` command. We can then run our tests using the following command: + +```bash +mox test --network eravm +``` + +We will see a lot of warnings during the testing phase. These warnings are due to ZK Sync VM being different from the EVM. However, we can ignore these warnings as our tests will still pass. + +We also saw how to compile our contracts with both the EVM and ZK Sync: + +```bash +mox compile +``` + +```bash +mox compile --network eravm +``` + +Moccasin uses different bytecode for both the EVM and ZK Sync. We can check the bytecode by looking at the `favorites.json` file in our `out` folder. We will see that the VM has changed from EVM to `eravm` and the bytecode has changed. However, the ABI (Application Binary Interface) will remain the same for both the EVM and ZK Sync. + +We have now learned how to deploy and test our contracts with ZK Sync using Moccasin. This allows us to take advantage of the power of ZK Rollups, making our applications faster and more efficient. + +We are now ready to deploy and test our smart contracts in a ZK Sync environment, and we can do so with the confidence that our code is working as expected. From f3e1944d4b2327e019115c2fbbaeb4bfa36204b8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:39:04 -0700 Subject: [PATCH 712/797] Equious updated courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md. --- .../4-mox-favs/21-setting-up-zksync/+page.md | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md b/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md index a515e5e34..dc65fdcd2 100644 --- a/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md +++ b/courses/moccasin-101/4-mox-favs/21-setting-up-zksync/+page.md @@ -1,3 +1,47 @@ ---- - title: Setting Up Zksync - --- \ No newline at end of file +## Setting up ZkSync network configuration + +In this lesson, we will learn how to set up the configuration necessary to deploy a smart contract to the ZkSync Sepolia Testnet. This can be confusing, but we'll walk through this together. + +We can start with the `mocassin.toml` file. We need to create a new network configuration below the existing network entries. The new network configuration should be named `sepolia-zkync`. + +Here is the basic structure of our network configuration: + +```toml +[networks.sepolia-zkync] +url = "$ZKSYNC_SEPOLIA_RPC_URL" +chain_id = 300 +save_to_db = false +default_account_name = "default" +explorer_uri = "https://explorer.sepolia.era.zkync.dev" +explorer_type = "zkyncxplorer" +is_zkync = true +``` + +We've already configured our RPC URL and chain ID, but we still need to add the `explorer_uri` and `explorer_type`. + +We can use the `mox explorer list` command to list all available explorers, but there are a lot of them. The one we are using is `sepolia-zkync-era`. + +```bash +mox explorer list +``` + +Here is our complete `mocassin.toml` file: + +```toml +[networks.sepolia-zkync] +url = "$ZKSYNC_SEPOLIA_RPC_URL" +chain_id = 300 +save_to_db = false +default_account_name = "default" +explorer_uri = "https://explorer.sepolia.era.zkync.dev" +explorer_type = "zkyncxplorer" +is_zkync = true +``` + +Now, we need to add our new network to MetaMask. We will do this by going to the network settings and hitting "Add a custom network". + +Give the network a name like `ZkSync Era - Sepolia` and then add the RPC URL, chain ID, and currency symbol. We will use the same block explorer URL as our `explorer_uri` in the `mocassin.toml` file. + +Finally, hit "save" in MetaMask and our new network is ready! + +We've now set up our ZkSync Sepolia Testnet and are ready to deploy. From 8deffe8af5ef47c8b5c517f659194208744f8e2c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:39:35 -0700 Subject: [PATCH 713/797] Equious updated courses/moccasin-101/4-mox-favs/22-bridging/+page.md. --- .../4-mox-favs/22-bridging/+page.md | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/22-bridging/+page.md b/courses/moccasin-101/4-mox-favs/22-bridging/+page.md index 1b24a95e4..40bed46a9 100644 --- a/courses/moccasin-101/4-mox-favs/22-bridging/+page.md +++ b/courses/moccasin-101/4-mox-favs/22-bridging/+page.md @@ -1,3 +1,69 @@ ---- - title: Bridging - --- \ No newline at end of file +## Bridging to ZkSync + +In this lesson, we are going to learn how to bridge funds from the Sepolia Testnet to the ZkSync Sepolia Testnet. + +First, we need to connect our wallet. We will connect via Metamask. + +Then, in Metamask, go to "Edit Networks" and ensure the following are selected: + +* ZkSync Sepolia Testnet +* Sepolia + +Then, hit the "Update" button, and then "Connect". + +Now, we will see an error message. This is due to the fact that we are on the wrong chain in our wallet. If we open the "Menu" tab, we will see an option to change the network. + +We will select "ZkSync Sepolia Testnet" from the menu. + +Our interface now looks like a standard bridging app, and we will type in the amount we want to bridge. + +Then, we will hit "Continue", and we are asked to confirm our transaction. After confirming, we will have to wait approximately 15 minutes for our funds to appear on the ZkSync network. + +Let's look at our configuration file and see what we've added: + +```toml +[networks.sepolia-zkSync] +url = "$ZKSYNC_SEPOLIA_RPC_URL" +chain_id = 300 +save_to_db = false +default_account_name = "default" +explorer_uri = "https://explorer.sepolia.era.zkSync.dev" +explorer_type = "zkSyncExplorer" +is_zkSync = true +``` + +We've also added the explorer type, which is "zkSyncExplorer". + +Next, we'll go to our deploy script, and make sure the following are correct: + +```python +from src import favorites +from moccasin.boa.tools import VyperContract +from moccasin.config import get_active_network + +def deploy_favorites() -> VyperContract: + favorites_contract: VyperContract = favorites.deploy() + starting_number: int = favorites_contract.retrieve() + print(f"Starting number is: {starting_number}") + favorites_contract.store(77) + ending_number: int = favorites_contract.retrieve() + print(f"Ending number is: {ending_number}") + active_network = get_active_network() + if active_network.has_explorer(): + result = active_network.mocassin.verify(favorites_contract) + result.wait_for_verification() + return favorites_contract + +def moccasin_main() -> VyperContract: + return deploy_favorites() +``` + +Now, we are going to deploy our smart contract to the ZkSync Sepolia Testnet. We will run the following in the terminal: + +```bash +python deploy.py +``` + +This will deploy our contract, and then verify it on the ZkSync Sepolia Testnet. + +We will then see a new transaction in our Metamask wallet, and our funds will be available to us on ZkSync! \ No newline at end of file From a83b45f636a420206edab5591bc02ec25b8b084e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:40:06 -0700 Subject: [PATCH 714/797] Equious updated courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md. --- .../4-mox-favs/23-zksync-deploy/+page.md | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md b/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md index ef6567697..6e5ffb2c8 100644 --- a/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md +++ b/courses/moccasin-101/4-mox-favs/23-zksync-deploy/+page.md @@ -1,3 +1,44 @@ ---- - title: Zksync Deploy - --- \ No newline at end of file +## Deploying to ZKSync + +In this lesson, we'll deploy our smart contract to the ZKSync network. We'll cover the following: + +- Deploying to ZKSync Testnet +- Verifying Our Smart Contract +- Sharing Your Achievement +- Cleaning Up + +### Deploying to ZKSync Testnet + +We can deploy to ZKSync using this command: + +```bash +mox run deploy --network sepolia-zksync +``` + +We'll be prompted to confirm that we want to continue. Type "y" and hit enter. + +We'll then be asked to enter our password. + +Now we'll see our transactions being broadcasted and we can see our contract address has been printed in the terminal. + +### Verifying Our Smart Contract + +Let's verify our smart contract by copying the contract address from our terminal and going to the ZKSync explorer. + +We can find the ZKSync explorer by searching "zksync sepolia testnet explorer" on Google. + +Once we've pasted the contract address in the explorer search, we'll be able to see our contract information, including the source code and deployed bytecode. + +### Sharing Your Achievement + +If we successfully deployed our contract to ZKSync, we can go to the Github repo associated with this course and click on the "Tweet Me (add your contract in)!" link. + +We recommend sending a tweet at ZKSync letting them know we just deployed a smart contract using Mocassin. + +Sharing our success with the community is an important part of our developer journey. + +### Cleaning Up + +If we have an "install.sh" file in our project directory, we can delete it. + +We may also have a "era_test_node.log" file. We can delete this file as well. From b64b79a046e99d100237e0ef27c1488f6333a1f6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:42:07 -0700 Subject: [PATCH 715/797] Equious updated courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md. --- .../24-zksync-contract-deployment/+page.md | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md b/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md index 7676d99dc..26eacf8c0 100644 --- a/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md +++ b/courses/moccasin-101/4-mox-favs/24-zksync-contract-deployment/+page.md @@ -1,3 +1,18 @@ ---- - title: Zksync Contract Deployment - --- \ No newline at end of file +## ZK Sync Contract Deployment + +ZK Sync contract deployment is a little different than Ethereum deployments. Instead of having a blank to address, ZK Sync has a to address that's actually another contract, the Contract Deployer contract. This is the contract we used to send our contract to. + +We can find the Contract Deployer's address under the "to" field on the Block Explorer, which we can verify by searching for the address in our MetaMask Wallet. + +The address we found in our MetaMask Wallet is `0x0000000000000000000000000000000000000006`. + +The Contract Deployer contract is actually written in Solidity, and we can find the code using the block explorer. + +Here's an example of how to write the code to call the `ContractDeployer` contract: + +```python +contract_deployer_contract = ContractDeployer.at("0x0000000000000000000000000000000000000006") +contract_deployer_contract.create(bytes_salt, bytes_bytecodeHash, bytes_input) +``` + +The code above shows the necessary parameters to call the `ContractDeployer` contract's `create` function, and the `bytes_salt`, `bytes_bytecodeHash` and `bytes_input` parameters are ones that we would have to convert our Vyper code to. The `ContractDeployer` contract will handle this conversion for us, under the hood. From 6446d7135d71022b28905c8cec7b8cd332fc48b0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:42:35 -0700 Subject: [PATCH 716/797] Equious updated courses/moccasin-101/4-mox-favs/25-tx-types/+page.md. --- .../4-mox-favs/25-tx-types/+page.md | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md b/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md index e465b90e1..6a4c55f1c 100644 --- a/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md +++ b/courses/moccasin-101/4-mox-favs/25-tx-types/+page.md @@ -1,3 +1,39 @@ ---- - title: Tx Types - --- \ No newline at end of file +## Transaction Types + +We are going to talk about transaction types. We won't do a deep dive explainer, but we will provide a link to an article in the GitHub repo associated with this course. + +Let's dive into this. + +If we run the command: + +```bash +mox run deploy --network eravm +``` +we get a warning that keeps popping up: + +```bash +No EIP-1559 transaction available, falling back to legacy +``` +What's going on here? + +Well, in the blockchain world, there are several different types of transactions. And I kind of glossed over it when we went over the transaction object. + +We said: "Okay, here's what a transaction looks like. It has its from, to, gas limit, fee, blah, blah, blah." + +But, there's also a typed transaction envelope. We can also pass a transaction type in that RLP encoding. + +Now what makes it kind of confusing is that it's not actually in this little JSON blob here, right? It's actually outside of the JSON blob, but again, we're getting kind of a low-level; doesn't really matter where it is. All you need to know is that there are actually multiple different types of transactions. + +The Ethereum website does a decent job of kind of walking you through some of the different types of transactions, but we can also look at them in the Cyfrin Updraft. + +So what's happening is when we get this warning: "Hey, uh no EIP 1559 or 1559 transaction available, falling back to legacy," is that ZK Sync works with a few different types of transactions, like legacy transactions, and they have a couple of their own custom transactions themselves. The main transactions or the new, normal type of transactions on Ethereum are known as these Type 2 or EIP-1559 transactions. Again, if this is going over your head a little bit, don't worry about it too much, but this type of transaction doesn't exist on ZK Sync, right? This is essentially like an advanced gas type of transaction, and ZK Sync has them in by default. + +So, what happens here is that our tools try to send a Type 2 transaction. This super gas, this EIP 1559 transaction onto ZK Sync, and ZK Sync says, "Hey, we don't have those. We're already like pretty darn gas efficient. So, Mocassin and Titania will always try to send an EIP 1559 transaction first, but then, it'll revert back to a legacy transaction for ZK Sync. + +Now, when we're sending on Ethereum, it will work with a Type 2 transaction. It will work with a Type 2 transaction. You can also send Type 0 transactions on Ethereum, but you shouldn't, because they're kind of worse for gas and like gas is money, so you don't want to spend more money. So, pretty much nowadays, everyone sends Type 2 transactions on Ethereum on ZK Sync, they send legacy transactions because the gas on ZK Sync is just better. + +I'm kind of glossing over the details, and this is kind of it from a high level. That's why you're seeing this error here is because there's multiple different types of transactions. + +One of the coolest types of transactions is this EIP 712 or an OX 71 or a 113 transaction, which is known as a native account abstraction transaction. We won't be learning about that in this curriculum. + +**[VIDEO TAG]** **show Solidity examples of transaction types in Cyfrin Updraft** From 96fa645e517205b5ef466c28b4af6c288c71bdc9 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:45:07 -0700 Subject: [PATCH 717/797] Equious updated courses/moccasin-101/4-mox-favs/26-workshop/+page.md. --- .../4-mox-favs/26-workshop/+page.md | 72 ++++++++++++++++++- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/26-workshop/+page.md b/courses/moccasin-101/4-mox-favs/26-workshop/+page.md index 789149836..8668ded0f 100644 --- a/courses/moccasin-101/4-mox-favs/26-workshop/+page.md +++ b/courses/moccasin-101/4-mox-favs/26-workshop/+page.md @@ -1,3 +1,69 @@ ---- - title: Workshop - --- \ No newline at end of file +## Workshop + +We have a few workshops for you. + +The first is to deploy your contract to your Tenderly virtual network. We'll be using a `mocassin.toml` file for this. To add a new network, you'll need to create a new array within the networks key. For example, to deploy to Tenderly you can create a new network named `our-fake-chain` and then add the necessary keys and values. + +```toml +networks.our-fake-chain +``` + +Next, we'll write our own deploy script and deploy to the PyVM network. To do this, we can create a new file called `my_deploy.py` within the `script` folder. Here's some boilerplate code to get started: + +```python +def deploy_me(): + print("Hello!") + +def moccasin_main(): + return deploy_me() +``` + +We can test this with the following command: + +```bash +mox run my_deploy +``` + +The output should be: + +```bash +Hello! +``` + +We can also write a deploy script and deploy to the EraVM network. To do this, we'll use a `--network EraVM` flag. + +```bash +mox run my_deploy --network EraVM +``` + +The final workshop is to write a new test in your test file and run it. You can do this in the `test_favorites.py` file. + +For our final example, we'll be using the `buy_me_a_coffee.vy` contract. The first thing you need to do is get the price of a different asset using Chainlink price feeds on your fake chain. We have a function called `get_eth_to_usd_rate` that we can repurpose for this. + +We can rename the function to `get_rate`. + +```vyper +def get_rate(eth_amount: uint256) -> uint256: + return self.get_eth_to_usd_rate(eth_amount) +``` + +The second workshop is to write a function to get the total amount of funds in the contract. We can use a loop and the `funders` array to accomplish this. + +```vyper +def get_total() -> uint256: + return self.balance +``` + +Finally, we'll write a function that allows you to change the owner of the contract. Remember, our owner at the top is immutable, so we'll need to remove this to create our function. + +```vyper +OWNER: public(immutable(address)) +``` + +We need to make the `OWNER` variable mutable. We can do that by removing the `immutable` keyword. + +```vyper +OWNER: public(address) +``` + +You should spend no more than 30 minutes working on these workshops. If you get stuck, you can use an AI assistant to help you. If you still can't figure it out after 30 minutes, take a break and come back to it later. From 94c51cd39019e2e821ee5420457ea4f450b9d78e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:48:22 -0700 Subject: [PATCH 718/797] Equious updated courses/moccasin-101/4-mox-favs/27-recap/+page.md. --- .../moccasin-101/4-mox-favs/27-recap/+page.md | 97 ++++++++++++++++++- 1 file changed, 94 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/27-recap/+page.md b/courses/moccasin-101/4-mox-favs/27-recap/+page.md index 385e6edfe..39489661d 100644 --- a/courses/moccasin-101/4-mox-favs/27-recap/+page.md +++ b/courses/moccasin-101/4-mox-favs/27-recap/+page.md @@ -1,3 +1,94 @@ ---- - title: Recap - --- \ No newline at end of file +## Mocassin Favorites Recap + +And with that, we have crammed so much information into your brain that you should be bursting at the seams with information. And we are going to take some time to wrap up so that you can go on an ice cream break or a gym break or a coffee break or whatever kind of break that you would like to go on. We've learned a ton in this section. So let's do a quick recap of all the things that you've learned so you can take a break. + +First off, we were introduced to this tool called Mocassin, which is this TitanoBoa based smart contract development framework, which allows us to test deploy and work with our smart contracts in a much simpler way. We spun up a brand-new Mocassin project and we learned a ton of stuff. First off, we learned how to even test our contracts, which is a crucial piece of our journey, and we know that no one's going to take our code seriously unless we have tests. Tests are absolutely crucial to your smart contract development journey. We learned how to write tests using Mocassin's pie test framework. + +```python +def test_add_favorite(): + favorites = Favorites.deploy() + favorites.add_favorite(1, "Ethereum") + assert favorites.favorites(1) == "Ethereum" +``` + +Additionally, we learned about how fixtures can help write our tests to be faster and even more proficient. + +```python +@pytest.fixture +def favorites(): + return Favorites.deploy() + +def test_add_favorite(favorites): + favorites.add_favorite(1, "Ethereum") + assert favorites.favorites(1) == "Ethereum" +``` + +We learned how to write a deploy script in Mocassin using this native import syntax like from SRC import favorites where we can actually just deploy our contract with the deploy keyword. + +```python +from src import favorites + +def main(): + favorites.deploy() +``` + +And then additionally, right inside Mocassin, we can verify our smart contracts with just one or two, or I guess three here, three lines of code. + +```bash +mox verify --network sepolia +``` + +We learned how to switch between networks in Mocassin. If we want to work with a different network, all we have to do is add the information about that network to our moccasin.toml under the networks area. And we can deploy to different networks just by running mox run deploy with --network, and then the name of the other network that we want to deploy to. + +```toml +[networks] +default = "pie-evm" +anvil = { + url = "http://127.0.0.1:8545" +} +sepolia = { + url = "https://sepolia.infura.io/v3/YOUR_INFURA_PROJECT_ID" +} +``` + +```bash +mox run deploy --network anvil +``` + +If we don't specify a network, it will use the default network. And Mocassin defaults to the pie EVM, which is this fake, locally running network. We also learned that Mocassin comes built in with the EraVM. + +```bash +mox run deploy --network EraVM +``` + +We can test and deploy to ZK Sync. + +We learned about encrypting and decrypting our wallets. So, if I do mox wallet list, I can see a list of accounts that I've encrypted locally so that I don't have to expose my private key. Oh my gosh, that feels good. That feels good. And I know that if I were to, you know, for example, let's spin up let's spin up anvil on another terminal. If I were to do mox run deploy --network anvil, and I were to get rid Where is it? And I were to get rid of the unsafe password file, it would prompt me for my password, meaning my keys can stay secure. I will not be sharing my private keys with you. Although, this one, the password is just "password" which is a terrible password. But you get the picture. We learned how to do that. We learned how to deploy to Sepolia and to ZK Sync Sepolia. And if you didn't actually deploy there, no worries, you got to see the process. You got to watch us automatically verify these contracts on different explorers, like BlockScout and ZK Sync Explorer. + +We learned we could compile our contracts. And we learned we could compile them both with EVM or with ZK Sync EVM. + +```bash +mox compile --network sepolia +``` + +We learned a little bit more Python, we added type hinting into our scripts here. We learned about environment variables and how our .env file can have environment variables. We know that it's not a great place to store private keys. It's It's more okay to store RPC URLs cuz they're not that sensitive. Private keys are very sensitive. + +```bash +mox run deploy --network sepolia +``` + +We learned a little bit more about Python here, where we added some dependencies for our project so that our linter, our little syntax highlighter, worked correctly. + +```toml +[project] +name = "mocassin" +version = "^0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.11" +[dependencies] +mocassin-0 = "0.3.4b2", +pytest-8 = "8.3.3", +``` + +You have learned an absolute ton in this section. And you should be incredibly proud of yourself. Now, if you haven't shared on Twitter or on some social media, I'm going to just tell you one more time, you absolutely should. Joining the developer community is going to a increase your chances of getting a job if that's what you're looking for. b you're going to get to meet a ton of really cool phenomenal people. And c give you a chance to Yeah, join like-minded individuals. You can join here or if you're on Cyffin Updraft, you can of course join the Discord and meet a ton of other like-minded developers as well. That being said, huge congratulations for getting this far. And huge congratulations for finishing Mocassin Favorites. From a09c0dd3d992cd8ada5ae5079ad52340277caba3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:51:16 -0700 Subject: [PATCH 719/797] Equious updated courses/moccasin-101/4-mox-favs/3-create-mox/+page.md. --- .../4-mox-favs/3-create-mox/+page.md | 74 ++++++++++++++++++- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md b/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md index 0f542f929..313af66c5 100644 --- a/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md +++ b/courses/moccasin-101/4-mox-favs/3-create-mox/+page.md @@ -1,3 +1,71 @@ ---- - title: Create Mox - --- \ No newline at end of file +## Creating a Moccasin project + +Now that we have Moccasin installed, we can start creating our project. We'll be working in our `mox-cu` folder. + +Let's start by creating a new folder called `mox-favorites-cu` with the following command: + +```bash +mkdir mox-favorites-cu +``` + +Next, we'll open this new folder in VS Code. + +```bash +code mox-favorites-cu/ +``` + +If you don't have the `code` command, you can also do `File > Open Folder`. + +Moccasin comes with a built-in tool to help us create new projects. We can use the `mox init` command to do so. + +```bash +mox init +``` + +Before running this command, we can use the `--help` flag to see what it will do. + +```bash +mox init --help +``` + +This will print out a list of options and the directory structure that the project will have. We'll be using VS Code and want to include a `pyproject.toml` file, so we can run the following command to initialize the project: + +```bash +mox init --vscode --pyproject +``` + +The terminal will output a message confirming the project was initialized. + +Let's take a look at the files and folders that have been created: + +- `.vscode` : This folder contains settings for VS Code, which we'll explore later. +- `lib` : This is where we'll install any packages or dependencies our project requires. +- `script` : This folder is where we'll store any deploy scripts. In this case, we have a script called `deploy.py` which deploys the `Counter` contract. +- `src` : This is where we'll store our Vyper contracts. Moccasin has included a simple `Counter.vy` contract for us to start with. +- `tests` : This folder will house any tests related to our contracts. Currently, it has a few simple dummy tests. +- `pytest_cache` : This folder stores information from the pytest testing framework to improve test run times. +- `coveragerc` : This file is used for code coverage reporting and we'll discuss it in detail later. +- `.gitattributes` and `.gitignore` : These files are used to configure Git behavior and specify files or folders that shouldn't be tracked by Git. +- `mocassin.toml` : This file configures Moccasin settings. It has information like network URLs and chain IDs. +- `pyproject.toml` : This file contains information about our Python project, including dependencies and project metadata. +- `README.md` : This file provides a brief overview of the project, including instructions for getting started. + +We can start by creating a new file called `favorites.vy` in the `src` folder. We can do this by right-clicking within the `src` folder, selecting `New File`, and entering the name `favorites.vy`. + +We'll then copy and paste the code for the `favorites.vy` contract from the GitHub repository for this course. + +Let's go through the folders and files in detail: + +- `.vscode` : This folder contains the `settings.json` file, which is only relevant to users of VS Code. It helps with syntax highlighting and other editor features. +- `lib` : We'll use this folder to install dependencies. +- `script` : This folder contains the deploy script `deploy.py` which deploys the `Counter` contract. It uses the `deploy` keyword to deploy the contract, followed by calling the `increment` function to check the starting and ending count. +- `src` : This folder will contain all our Vyper contracts. Currently, we have a `Counter.vy` contract and we've just added the `favorites.vy` contract, which we'll use throughout this course. +- `tests` : This folder is used to store tests. We can run the tests with the `mox test` command. +- `pytest_cache` : This folder is used by pytest to store information that makes tests run faster. +- `coveragerc` : This file is used to configure coverage reporting. +- `.gitattributes` and `.gitignore` : These files are used to manage Git behavior. +- `mocassin.toml` : This file stores Moccasin settings. +- `pyproject.toml` : This file contains project information. +- `README.md` : This file provides a brief overview of the project and instructions for getting started. + + From 5718fee1d32be39af2248be6057cb5cc2430e782 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:51:47 -0700 Subject: [PATCH 720/797] Equious updated courses/moccasin-101/4-mox-favs/4-mox-something/+page.md. --- .../4-mox-favs/4-mox-something/+page.md | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md b/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md index e56710475..b96a73fcd 100644 --- a/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md +++ b/courses/moccasin-101/4-mox-favs/4-mox-something/+page.md @@ -1,3 +1,26 @@ ---- - title: Mox Something - --- \ No newline at end of file +## Compiling a project + +We have our `favorites.vy` file here with a pragma version 0.4.0. We also see a comment indicating the license is MIT. + +```python +# pragma version 0.4.0 +# @license MIT +``` + +We have the contract code in here, which is typical. Usually we would compile this with Vyper SRC, but in this case, we will do it with the MoccaSin command. We will run the Vyper compiler to actually compile the project. + +```bash +vyper src/favorites.vy +``` + +We can compile every file in our SRC folder by running the MoccaSin command. This will compile one project into an out directory. + +```bash +mox compile +``` + +We can see that this successfully creates a `favorites.json` file in the out directory. + +This has a ton of compilation details about the favorites contract. It has the bytecode that we're used to seeing now. It has the ABI. If I scroll over to the left here, I can even click this little drop-down to see what else we have and then we have VM which is the EVM or the Ethereum virtual machine. So that's great. And if we were to have Let me just copy-paste this in here a whole bunch If we were to have a ton of contracts in here Same thing, we could just run `mox compile` compile every single project to the out folder and be good. So, I'm going to go ahead and delete all of these now. + +Now what's cool about MoccaSin is that you don't even have to compile. When you run your scripts, if they don't compile, well the scripts will just break. So compiling is actually optional. It's just that if you do want to compile so that you have these different so that you can actually see, you can inspect the bytecode and the ABI, etc, you can see that in the out folder there. From 7c099df599819dbe81bda5f724a71e8da4a92c3f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:52:15 -0700 Subject: [PATCH 721/797] Equious updated courses/moccasin-101/4-mox-favs/5-mox-script/+page.md. --- .../4-mox-favs/5-mox-script/+page.md | 78 ++++++++++++++++++- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md b/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md index 9b8bba199..5b625d62f 100644 --- a/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md +++ b/courses/moccasin-101/4-mox-favs/5-mox-script/+page.md @@ -1,3 +1,75 @@ ---- - title: Mox Script - --- \ No newline at end of file +## Moccasin Scripting + +In this section, we will learn how to deploy our smart contract using a deploy script. + +We will start with the typical way we would deploy a contract using Boa, as we did in the previous section. We would use code similar to this: + +```python +import boa +boa.load("favorites.vy") +``` + +However, in Moccasin, we can directly import the contract we want to deploy using the Python import system. For example: + +```python +from src import favorites +``` + +Moccasin is smart enough to know that it is dealing with a Vyper contract and will automatically import the necessary libraries and dependencies. + +To deploy the contract using a deploy script, we will need to write a Python script that utilizes the `deploy` command. In this script, we can also interact with the deployed contract to verify its state. + +Let's create a new file called `deploy.py` and add the following code: + +```python +from src import favorites + +def deploy(): + favorites_contract = favorites.deploy() + starting_number = favorites_contract.retrieve() + print(f"Starting number is: {starting_number}") + +def moccasin_main(): + deploy() +``` + +To run this script in Moccasin, we can use the `mox run` command. + +This command will execute the `mocassin_main()` function, which in turn will call the `deploy()` function. The `deploy()` function will deploy the `favorites` contract and then retrieve the starting number. We can then print the starting number to the terminal to verify that the contract has been deployed correctly. + +We can also use the `breakpoint()` function to step through the script and inspect the state of the variables. + +To use `breakpoint()`, we can add the following code to our `deploy.py` script: + +```python +from src import favorites + +def deploy(): + breakpoint() + favorites_contract = favorites.deploy() + starting_number = favorites_contract.retrieve() + print(f"Starting number is: {starting_number}") + +def moccasin_main(): + deploy() +``` + +When we run this script with `mox run deploy`, the script will pause at the `breakpoint()` function. We can then use the debugger to inspect the state of the variables and step through the code. + +```bash +mox run deploy +``` + +We can then use commands such as `type(favorites)` to view the type of the `favorites` object: + +```bash +type(favorites) +``` + +Finally, we can run `quit()` to exit the debugger and continue the execution of the script. + +```bash +quit() +``` + +This is a basic example of deploying a contract using a deploy script in Moccasin. There are many other ways to interact with the deployed contract, such as calling functions and viewing events. In the following sections, we will explore some of these advanced techniques in more detail. From 56840f605b7c65b3acf24a0a3390b3622cc11ac0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:52:53 -0700 Subject: [PATCH 722/797] Equious updated courses/moccasin-101/4-mox-favs/6-other-net/+page.md. --- .../4-mox-favs/6-other-net/+page.md | 86 ++++++++++++++++++- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/6-other-net/+page.md b/courses/moccasin-101/4-mox-favs/6-other-net/+page.md index 19588553c..f48e84e4b 100644 --- a/courses/moccasin-101/4-mox-favs/6-other-net/+page.md +++ b/courses/moccasin-101/4-mox-favs/6-other-net/+page.md @@ -1,3 +1,83 @@ ---- - title: Other Net - --- \ No newline at end of file +We've learned how to deploy a simple script to our local PiVM. Now, let's learn how to deploy it to a different network. + +We can deploy this script to our anvil network. You know, our locally running anvil network. + +First, open a new terminal, clear it out, and run anvil: + +```bash +anvil +``` + +We can then run our script like this: + +```bash +mox run deploy +``` + +Our script will run, but nothing will happen on Anvil. This is because we're deploying to Anvil, and our current setup is running on PiVM. + +We're going to use a flag to tell our script which network we're deploying to. If we run: + +```bash +mox run --help +``` + +We'll see a number of commands to help us interact with our Anvil chain. There's a flag called `--network` which lets us define the network we want to deploy to, taken from our `mocassin.toml` file. + +To see what's in our `mocassin.toml` file, let's look at it! + +This `mocassin.toml` file is used to configure all of our networks and contains any kind of setting for Moccasin. + +You can see all the possible settings in the TOML documentation here: https://cyfrin.github.io/mocassin/all_mocassin_toml_parameters.html + +In our case, we can create a new network object named anvil. + +To do this, we'll make a new section in our `mocassin.toml` file: + +```toml +[networks.anvil] +``` + +We need to give our network a URL. We can find the Anvil URL running in the terminal: + +```toml +url = "http://127.0.0.1:8545" +``` + +We'll also add this flag: + +```toml +save_to_db = false +``` + +We've added our new network section to our `mocassin.toml` file. + +Let's try to deploy our contract again! + +```bash +mox run deploy --network anvil +``` + +Our script will run, but it'll ask us to hit yes. + +We'll see a value error here. + +```bash +ValueError: eoa not defined! +``` + +This is a common error. You can find more information about this in the Moccasin documentation: https://cyfrin.github.io/mocassin/common_errors.html + +It means that we're trying to deploy to Anvil, but we haven't added an account to our `mocassin.toml` file! + +We can do this by following the wallet guide in the documentation: https://cyfrin.github.io/mocassin/core/concepts/wallet.html + +Our Anvil network is running, so we can go there and grab a private key to deploy our contract. + +We can then run our deploy script like this: + +```bash +mox run deploy --network anvil --private-key 0x9740....2f764180aa3 +``` + +That was an example of how to deploy a script to a different network. In the next section, we'll learn how to use Moccasin's wallet commands! From f6d0c76bfa7ddb1139338f10554e19e3c3defa2e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:55:17 -0700 Subject: [PATCH 723/797] Equious updated courses/moccasin-101/4-mox-favs/7-encrypt-key/+page.md. --- .../4-mox-favs/7-encrypt-key/+page.md | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/7-encrypt-key/+page.md b/courses/moccasin-101/4-mox-favs/7-encrypt-key/+page.md index 7ab4c1ff8..5eff336f3 100644 --- a/courses/moccasin-101/4-mox-favs/7-encrypt-key/+page.md +++ b/courses/moccasin-101/4-mox-favs/7-encrypt-key/+page.md @@ -1,3 +1,62 @@ ---- - title: Encrypt Key - --- \ No newline at end of file +## Encrypting a Private Key + +We've learned how to encrypt our keys back when we were using Python, but Mocassin has its own way to handle encryption. + +We can find it in the documentation under the **Wallet** section. + +We'll use the `wallet import ACCOUNT_NAME` command to create a keystore file in the default keystore directory. + +The command will then prompt us to enter our private key and password. + +The example command is as follows: + +```bash +mox wallet import my_account +``` + +Let's look at the different commands available to us in the `wallet` section: + +```bash +mox wallet --help +``` + +This shows a list of commands, including: + +* `list (ls)`: This will list all of our accounts. +* `generate (g, new)`: This will create a new account with a random private key. +* `import (i, add)`: This will import a private key into an encrypted keystore. +* `view (v)`: This will view the JSON of a keystore file. +* `decrypt (dk)`: This will decrypt a keystore file to get the private key. +* `delete (d)`: This will delete a keystore file. + +We'll use the `import` command to encrypt our key. To do this, we'll copy the private key for the Anvil account and run this command in our terminal: + +```bash +mox wallet import anvil1 +``` + +The terminal will then ask us to enter our private key. We'll paste the copied key into the terminal and press Enter. + +The terminal will then ask us to enter a password to encrypt our key. We'll enter a password and confirm it. The terminal will then show: + +```bash +Saved account anvil1 to keystores! +``` + +This will save the encrypted account to our keystore. + +Now, if we want to view the accounts we have, we can run: + +```bash +mox wallet list +``` + +The terminal will show us all accounts we have saved in our keystore. + +We can also use the `view` command to see the JSON of a specific keystore. For example: + +```bash +mox wallet view anvil1 +``` + +This will show the JSON for the `anvil1` keystore. We'll see the address of the account and the encrypted key. From 495c9762e78de071426db697c6b8d99526787f3c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:56:26 -0700 Subject: [PATCH 724/797] Equious updated courses/moccasin-101/4-mox-favs/9-using-key/+page.md. --- .../4-mox-favs/9-using-key/+page.md | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/4-mox-favs/9-using-key/+page.md b/courses/moccasin-101/4-mox-favs/9-using-key/+page.md index dd0adc820..4c59eed74 100644 --- a/courses/moccasin-101/4-mox-favs/9-using-key/+page.md +++ b/courses/moccasin-101/4-mox-favs/9-using-key/+page.md @@ -1,3 +1,27 @@ ---- - title: Using Key - --- \ No newline at end of file +## Using an encrypted key in your moccasain script + +We've already encrypted a private key in our Mocaasain project and have the following in our `mocassin.toml` file. + +```toml +[project] +src = "src" + +[networks.anvil] +url = "http://127.0.0.1:8545" +save_to_db = false +prompt_live = false +``` + +Now we can run this script. We can do + +```bash +mox run deploy --network anvil +``` + +We can also add the following to our command: + +```bash +mox run deploy --network anvil --account anvil1 +``` + +Moccasin knows that `anvil1` is one of the accounts that we have encrypted. When we hit enter we are prompted to enter our password for the keystore. We'll enter our password and you'll notice that it doesn't show our password. When we hit enter, it decrypts our key and sends the transactions. We can see that we have some transaction activity on the Anvil chain. This is very exciting! From 616f78b8e30f485fb46cb8ca49bead3b57643752 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:56:51 -0700 Subject: [PATCH 725/797] Equious updated courses/moccasin-101/5-mox-five/1-intro/+page.md. --- courses/moccasin-101/5-mox-five/1-intro/+page.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/1-intro/+page.md b/courses/moccasin-101/5-mox-five/1-intro/+page.md index b7e64e913..a5ee45916 100644 --- a/courses/moccasin-101/5-mox-five/1-intro/+page.md +++ b/courses/moccasin-101/5-mox-five/1-intro/+page.md @@ -1,3 +1,13 @@ ---- - title: Intro - --- \ No newline at end of file +## Moccasin Five More + +We're going to keep moving right along in this course. We're going to be learning about modules today. The repo's coming along very well. We're going to keep moving on along here, and we're going to go into be the next section, the Moccasin Five More. This is going to be the final time we work with our favorites contract. We will see you no more. However, we're not just working with the favorites contract. We're going to be working with a few other contracts here. + +Let me show you what we're going to be learning in this section. We have a couple of new contracts, along with a `favorites_factory` contract, that we will interact with. We will also use the `ext call` to interact with our contracts and also learn about `static call`. + +We also have an interface, which is a new thing we've not encountered before. Our main Vyper code will be in our `five_more.vy` file. We'll use it to import favorites. + +We're going to use the `initialize` and `favorites.init` functions. + +We also have the `export` function at the bottom of our file. + +This section is all about modules. We will be playing a whole bunch with this contract. This should be a quick pit stop here, just to learn about modules, and then we're going to go on to the more advanced Buy Me a Coffee. \ No newline at end of file From b904abfd33ba27da8640fc86ee2e8bdc1146ee11 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:58:21 -0700 Subject: [PATCH 726/797] Equious updated courses/moccasin-101/5-mox-five/10-vyper-modules/+page.md. --- .../5-mox-five/10-vyper-modules/+page.md | 59 ++++++++++++++++++- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/10-vyper-modules/+page.md b/courses/moccasin-101/5-mox-five/10-vyper-modules/+page.md index 92ee2de81..0d10a4fb4 100644 --- a/courses/moccasin-101/5-mox-five/10-vyper-modules/+page.md +++ b/courses/moccasin-101/5-mox-five/10-vyper-modules/+page.md @@ -1,3 +1,56 @@ ---- - title: Vyper Modules - --- \ No newline at end of file +## Introduction to Vyper Modules + +We're going to be learning about Vyper modules. + +We'll create a new file called `five_more.vy`. It's going to be very similar to the `favorites.vy` contract, but we'll modify the `store()` function to add five to the number stored. + +```python +self.my_favorite_number = new_number + 5 +``` + +We want to reuse as much code as possible without copy-pasting everything, so we'll use Vyper's module system. + +A module is a way to encapsulate reusable code. + +Vyper favors **composition over inheritance** - we compose modules to create new contracts. + +Our `favorites_factory.vy` contract imports the `I_favorites` module: + +```python +from interfaces import I_favorites +``` + +The `I_favorites` module helps us type our list of `favorites` contracts. + +```python +list_of_favorite_contracts: public(DynArray[I_favorites, 100]) +``` + +When we import a module, it doesn't automatically become part of our contract. We need to explicitly tell Vyper how to use it. + +We can import the `favorites` contract into our `five_more.vy` file: + +```python +import favorites +``` + +Now, if we comment out the variables and functions that we imported, the contract still compiles because we only imported it, not copied it. + +```python +# my_favorite_number: uint256 +# @external +# def store(new_number: uint256): +# self.my_favorite_number = new_number +``` + +We can verify this by running the following commands: + +```bash +mox compile +``` + +The ABI of our `five_more.vy` contract will be empty since we're just importing it. + +```bash +# mox run deploy +``` From 6abb7b2920537a31425106f2ecbee20f8dc91381 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:58:49 -0700 Subject: [PATCH 727/797] Equious updated courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md. --- .../11-initializes-module-state/+page.md | 78 ++++++++++++++++++- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md b/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md index 7096200f7..fd5dd0314 100644 --- a/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md +++ b/courses/moccasin-101/5-mox-five/11-initializes-module-state/+page.md @@ -1,3 +1,75 @@ ---- - title: Initializes Module State - --- \ No newline at end of file +## Initializing Module State + +We can initialize a module's state using the `initializes` keyword in Vyper. The `initializes` keyword declares where a module's storage is located in the contract's storage layout. If the module has an `_init()` function, the `initializes` keyword will create a requirement that the module's `_init()` function is invoked. We can use this keyword to make sure the module's state is set up before interacting with it. + +We can also reference a module's state using the `uses` keyword. This approach is more advanced and commonly used by library designers. The `uses` statement allows us to utilize another module's state without directly initializing it. This is a good approach when we are using libraries that have pre-defined states that we don't want to modify. + +Let's look at an example of initializing a module using the `initializes` keyword. + +We have a module called `favorites` that has a few state variables: + +```python +struct Person: + favorite_number: uint256 + name: String[100] + +my_name: public(String[100]) +my_favorite_number: public(uint256) # 7 +list_of_numbers: public(uint256[5]) # 0, 0, 0, 0, 0 +list_of_people: public(Person[5]) +index: public(uint256) +name_to_favorite_number: public(HashMap[String[100], uint256]) +``` + +The `favorites` module also has an `_init()` function: + +```python +@deploy +def _init_(): + self.my_favorite_number = 7 + self.index = 0 + self.my_name = "YOUR NAME!" +``` + +We can initialize the `favorites` module from our contract using the `initializes` keyword: + +```python +initializes: favorites +``` + +To access the state variables, we can use the following code: + +```python +@deploy +def _init_(): + favorites._init_() + print(favorites.my_favorite_number) +``` + +When we compile the code, the `favorites` module's state variables will be initialized, and we will be able to access them. We'll get a warning message: + +```bash + "print should only be used for debugging!", node) +``` + +Since the `favorites` module has no view functions, we cannot directly call any of them. However, if we wrap a variable with the `public` keyword, it will implicitly create an external view function. + +We also have a module called `five_more` that has no `_init()` function and we can access its state variables in the same way: + +```python +@deploy +def _init_(): + favorites._init_() + print(favorites.my_favorite_number) + print("HI FROM FIVE MORE!") +``` + +We can access a module's state variables by referencing them using the module name and the variable name: + +```python +print(favorites.my_favorite_number) +``` + +The `uses` statement provides an alternative approach to initializing a module, but we will not cover that here. + +Let's review the major topics discussed in this lesson. We learned how to initialize a module's state using the `initializes` keyword. We also reviewed how to access the module's state variables. Finally, we learned that we can use the `public` keyword to implicitly create an external view function. This approach provides a more secure way of accessing a module's state. From 78055affd3efff0dcbebf84749ad6c9d28dc30eb Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:01:46 -0700 Subject: [PATCH 728/797] Equious updated courses/moccasin-101/5-mox-five/12-exports/+page.md. --- .../5-mox-five/12-exports/+page.md | 174 +++++++++++++++++- 1 file changed, 171 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/12-exports/+page.md b/courses/moccasin-101/5-mox-five/12-exports/+page.md index cd5b9a644..b669c9d57 100644 --- a/courses/moccasin-101/5-mox-five/12-exports/+page.md +++ b/courses/moccasin-101/5-mox-five/12-exports/+page.md @@ -1,3 +1,171 @@ ---- - title: Exports - --- \ No newline at end of file +## Exports + +The next question we'll address is how to access functions from another Vyper contract. We'll demonstrate this with our `five_more` contract. + +First we'll have a look at the `five_more.json` file, specifically the `abi` portion: + +```json +{ + "contract_name": "five_more", + "bytecode": "346180615761000c61001e565b100286100e565b396100266100f358600760055", + "abi": [ + { + "stateMutability": "nonpayable", + "type": "constructor", + "inputs": [], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "retrieve", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + }, + { + "stateMutability": "nonpayable", + "type": "function", + "name": "store", + "inputs": [ + { + "name": "new_number", + "type": "uint256" + } + ], + "outputs": [] + }, + { + "stateMutability": "view", + "type": "function", + "name": "my_name", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "my_favorite_number", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "list_of_numbers", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256[]" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "list_of_people", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "tuple[]" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "index", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256" + } + ] + }, + { + "stateMutability": "view", + "type": "function", + "name": "name_to_favorite_number", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "map(string,uint256)" + } + ] + } + ], + "vmf": "evm" +} +``` + +We can select which functions we want to expose in our contract. + +We'll use the `exports` keyword to achieve this: + +```vyper +exports: ( + favorites.retrieve, + favorites.store +) +``` + +We can access these functions from our `five_more` contract by using the following format: + +```vyper +favorites.retrieve() +``` + +```vyper +favorites.store(new_number) +``` + +Let's add another external function called `store` that adds a new number to the `my_favorite_number` variable: + +```vyper +@external +def store(new_number: uint256): + favorites.my_favorite_number = new_number + 5 +``` + +Let's compile our updated `five_more` contract: + +```bash +mox compile +``` + +We can now use the `store` function in our `deploy.py` script to store a new value in the `my_favorite_number` variable: + +```python +five_more_contract.store(90) +print(five_more_contract.retrieve()) +``` + +And now we'll run our deploy script: + +```bash +mox run deploy +``` + +We should see that `retrieve` gives us a new value of 95! + +We can think of the `exports` keyword like this, if we have a contract `favorites.vy` inside of `five_more.vy`. + +Using the `exports` keyword allows us to define which of the functions or public variables from `favorites.vy` we want to expose publicly in our `five_more.vy` contract. From 0519ccb2159a8cfd27c0bf055b50620708afb530 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:02:20 -0700 Subject: [PATCH 729/797] Equious updated courses/moccasin-101/5-mox-five/13-workshop/+page.md. --- .../5-mox-five/13-workshop/+page.md | 60 ++++++++++++++++++- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/13-workshop/+page.md b/courses/moccasin-101/5-mox-five/13-workshop/+page.md index 789149836..04db1277b 100644 --- a/courses/moccasin-101/5-mox-five/13-workshop/+page.md +++ b/courses/moccasin-101/5-mox-five/13-workshop/+page.md @@ -1,3 +1,57 @@ ---- - title: Workshop - --- \ No newline at end of file +## Modules and Uses Statement + +Let's talk about modules and the uses statement in Vyper. + +We've already gone over how to create a module. There's just one more thing to talk about. + +### Initializing a Module With Dependencies + +Sometimes, you'll encounter a module that uses other modules. + +Vyper's module system allows this. However, it requires us to explicitly declare access to the imported module's state. + +We will use the special "walrus" syntax to initialize the module that we're going to use. + +We'll import `ownable_2step` and then we'll say `initializes: ownable`. This is the walrus syntax. + +```python +import ownable_2step + +initializes: ownable +``` + +Next, we'll initialize the `ownable_2step` module, and we'll have to use the walrus operator for this. Remember that this syntax might seem weird. + +```python +initializes: ownable_2step[ownable] := ownable +``` + +This is just saying that the `ownable_2step` module is initialized by this module. This might be a little confusing, but it'll make sense once you see it in practice. + +### Workshop + +Here's a workshop for you: + +1. Add a second module to `five_more`. We've already imported `favorites`, and we've initialized `favorites`. + +```python +import favorites + +initializes: favorites +``` + +2. Try to export functions from two different modules. + +### The Uses Statement + +This is one area we'll use an AI. You can go ahead and ask AI questions to solve this problem. + +Remember, there is a `uses` statement in Vyper. You can read through the docs and understand how to use it to make a contract with a `uses` statement. + +```python +import ownable + +uses: ownable +``` + +We'll go over this more later in the course! From e3c39671ef0596894ace60cd5e47c433753e376a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:04:02 -0700 Subject: [PATCH 730/797] Equious updated courses/moccasin-101/5-mox-five/14-recap/+page.md. --- .../moccasin-101/5-mox-five/14-recap/+page.md | 71 ++++++++++++++++++- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/14-recap/+page.md b/courses/moccasin-101/5-mox-five/14-recap/+page.md index 385e6edfe..3ea28052b 100644 --- a/courses/moccasin-101/5-mox-five/14-recap/+page.md +++ b/courses/moccasin-101/5-mox-five/14-recap/+page.md @@ -1,3 +1,68 @@ ---- - title: Recap - --- \ No newline at end of file +## Recap + +We've learned a lot in this section, so let's do a quick recap. + +### Creating Contracts from Other Contracts + +We've learned about creating contracts from other contracts, and we've learned about two keywords that Vyper has built in. + +One of these keywords is `create_copy_of`. This takes the address of another contract and literally copies the bytecode of it. + +```python +create_copy_of(self.original_favorite_contract) +``` + +### Creating Interfaces + +We've also learned about interfaces. We can have a .vyi file where we just have the function definitions, and we don't have any of the function body. + +```python +@external +def store(new_number: uint256): + ... +``` + +### Interacting with Other Contracts + +We've learned that our contracts can interact with other contracts using `staticcall` and `extcall`. + +`staticcall` is something we learned about earlier, but now we've finally learned about `extcall`, which is an external call where we're going to call a contract outside of our contract. + +```python +extcall favorites_contract.store(new_number) +``` + +### Initializing Variables + +We've learned that we can initialize state and storage variables with the `initializes` keyword. + +```python +initializes: favorites +``` + +### Importing Functions + +We've learned about the `exports` keyword, which we can use to import specific functions from any modules that we've initialized or imported. + +```python +exports: (favorites.retrieve, favorites.add_person) +``` + +### Function Name Collision + +We've learned that we can't have a function with the same name as one of the functions that we export. Otherwise, we'll get a collision. You can't have two functions of the same name. + +### Chaining Commands + +We've learned a bit more about chaining commands, which is something we've done a few times now, but we made it more explicit in this section. + +```python +favorites.init() +``` + +## Moccasin Buy Me A Coffee (GET HERE!) + +Now is a great time to take a break. Go get some coffee, go for a walk, or go to the gym because the next section is probably one of the most important sections you'll do in your entire coding curriculum. +We will be putting this on your GitHub. This will be the start of your Syphon profile, doing projects like this, showing other people how badass you are and how much of a badass coder you are, is how you're going to be able to get hired. + +And, if you don't care about getting hired, it's drilling these skills in that're going to make you very skillful. Repetition is the mother of skill. We want you to be skillful, so be sure to take that break before tackling this project. I'll see you very soon. From 67ec395f4a7646231289cdeb41397fc134959cf7 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:05:57 -0700 Subject: [PATCH 731/797] Equious updated courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md. --- .../5-mox-five/3-create-copy-of/+page.md | 49 +++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md b/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md index a391afc59..44b1543b6 100644 --- a/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md +++ b/courses/moccasin-101/5-mox-five/3-create-copy-of/+page.md @@ -1,3 +1,46 @@ ---- - title: Create Copy Of - --- \ No newline at end of file +## Creating Copies of Existing Contracts in Vyper + +We are going to implement the `create_copy_of` function in Vyper. This function will create an identical copy of an existing contract, with a new unique address. + +First, we need to save the address of our `favorites.vy` contract. We will store it as a state variable called `original_favorite_contract`. + +```python +original_favorite_contract: address +``` + +Next, we need to define an `_init` function. This function will be called when we deploy the `favorites_factory.vy` contract. We will pass in the address of the `favorites.vy` contract as an argument, and then store it as a state variable. + +```python +@deploy +def _init(original_contract: address): + self.original_favorite_contract = original_contract +``` + +We will now create a new function called `create_favorites_contract`. This function will be responsible for creating a copy of the `favorites.vy` contract. It will call the `create_copy_of` function, which will create a byte-for-byte copy of the runtime code stored at the `original_favorite_contract` address. The function will then return the address of the new contract. + +```python +@external +def create_favorites_contract(): + new_favorites_contract: address = create_copy_of(self.original_favorite_contract) + return new_favorites_contract +``` + +Let's also save the addresses of our new contracts to a list, so we can keep track of them. + +```python +list_of_favorite_contracts: public(DynArray[address], 100) +``` + +We are creating a dynamic array with a maximum size of 100. This is where we will store the address of every new contract. + +Now, we will update our `create_favorites_contract` function to append the address of our new contract to the `list_of_favorite_contracts` array. + +```python +@external +def create_favorites_contract(): + new_favorites_contract: address = create_copy_of(self.original_favorite_contract) + self.list_of_favorite_contracts.append(new_favorites_contract) + return new_favorites_contract +``` + +This is all we need to do to create copies of existing contracts. We have successfully implemented the `create_copy_of` function in Vyper. From fd2399dd2c7805dfb25b2be5b2ae197726fad2ea Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:09:02 -0700 Subject: [PATCH 732/797] Equious updated courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md. --- .../5-mox-five/4-static-ext-call/+page.md | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md b/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md index e5dcc0071..f30fda8d2 100644 --- a/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md +++ b/courses/moccasin-101/5-mox-five/4-static-ext-call/+page.md @@ -1,3 +1,28 @@ ---- - title: Static Ext Call - --- \ No newline at end of file +## Staticcall and Extcall + +In this lesson, we'll be expanding on our previous work with the `chainlink` price feed and our `favorites` contract by creating a `favorites_factory` contract that can interact with deployed `favorites` contracts. We'll specifically be looking at the `staticcall` and `extcall` function calls, and how to use them to read and write data, respectively. + +First, let's create a new external function called `store_from_factory`. This function will take two inputs: `favorites_index` of type `uint256` and `new_number` of type `uint256`. These inputs represent the index of a deployed `favorites` contract and the new value that we want to store within it. We can then use the `extcall` method to execute the `store` function on the desired `favorites` contract. + +```python +def store_from_factory(favorites_index: uint256, new_number: uint256): + favorites_contract: address = self.list_of_favorite_contracts[favorites_index] + favorites_contract.store(new_number) +``` + +Let's break down the code above: + +- First, we access the address of the `favorites` contract corresponding to the provided `favorites_index` using the `list_of_favorite_contracts` array. +- Then, we call the `store` function on the `favorites_contract`, passing in the `new_number` value. + +Using the `extcall` method allows us to modify the state of the `favorites` contract. This differs from using `staticcall`, which only reads data and doesn't change the state of the contract. + +```python +favorites_contract.staticcall(store(new_number)) +``` + +The code above demonstrates how we can use `staticcall` to read the current value of `my_favorite_number` on our deployed `favorites` contract. + +We can then use `extcall` to call the `store` function on this contract, setting a new value for `my_favorite_number`. + +By using `extcall` and `staticcall`, we have greater control over how our `favorites_factory` contract interacts with deployed `favorites` contracts, enabling both reading and writing of data. From 41e6b52cd77f3a560391e1bb3e4382fb1035cff4 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:09:30 -0700 Subject: [PATCH 733/797] Equious updated courses/moccasin-101/5-mox-five/5-vyi/+page.md. --- .../moccasin-101/5-mox-five/5-vyi/+page.md | 58 ++++++++++++++++++- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/5-vyi/+page.md b/courses/moccasin-101/5-mox-five/5-vyi/+page.md index 62bd446ed..ab0cdd272 100644 --- a/courses/moccasin-101/5-mox-five/5-vyi/+page.md +++ b/courses/moccasin-101/5-mox-five/5-vyi/+page.md @@ -1,3 +1,55 @@ ---- - title: Vyi - --- \ No newline at end of file +## File Interfaces + +We will learn about file interfaces in Vyper, which are a more efficient way of dealing with interfaces. You may be asking "What's wrong with the inline interfaces?" And that's a fair question. The inline interfaces are perfectly valid and there is nothing wrong with using them. However, there are some reasons why using a file interface can be a better approach. + +One reason to use a file interface is that if we have a contract with a lot of functions, for example an interface with 50 functions, the inline interface would be very long and visually clunky. + +We can create a file interface in a separate file and import it into our main contract file. For example, we will make a file interface for our *favorites* contract. + +We can start by creating a new folder and then a new file in that folder. + +```bash +mkdir interfaces +touch interfaces/i_favorites.vyi +``` + +We like to use an 'i_' prefix for our interface files, but this is not a requirement of Vyper. + +Now, the interface that we wrote earlier was an inline interface. An inline interface is written directly within our contract file, for example: + +```vyper +interface i_favorites: + def store(new_number: uint256): nonpayable + def retrieve() -> uint256: view +``` + +And the file interface that we just created is written in a separate file. + +Now, in our factory file, we can go ahead and import our *i_favorites* file interface. We can do this by using a similar syntax to Python. + +```vyper +from interfaces import i_favorites +``` + +We don't need to include the '.vyi' extension after the *i_favorites* import, as Vyper knows that it is a file interface. + +So, this one line of code is equivalent to writing the interface directly inline. + +Now, we can actually call our interface in our factory file. Let's go ahead and do that. + +```vyper +favorites_contract: i_favorites = i_favorites(self.list_of_favorite_contracts[favorites_index]) +favorites_contract.store(new_number) +``` + +We can test our code by running: + +```bash +mox compile +``` + +It should compile successfully. + +We have now created our first file interface in Vyper. We are going to go ahead and tweak one more piece of our factory contract. + + courses\moccasin-101\5-mox-five\5-vyi\+page.md From ad7360a3c277c355b79f0c01a05784aa063e9a8b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:10:10 -0700 Subject: [PATCH 734/797] Equious updated courses/moccasin-101/5-mox-five/6-idk/+page.md. --- .../moccasin-101/5-mox-five/6-idk/+page.md | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/6-idk/+page.md b/courses/moccasin-101/5-mox-five/6-idk/+page.md index d226208fe..089750b9e 100644 --- a/courses/moccasin-101/5-mox-five/6-idk/+page.md +++ b/courses/moccasin-101/5-mox-five/6-idk/+page.md @@ -1,3 +1,51 @@ ---- - title: Idk - --- \ No newline at end of file +## Deploy Script + +We're going to write a deploy script and test this out. + +First, we'll create a new file in our `script` directory named `deploy.py`. + +We'll create a function called `deploy_favorites()`. This function will deploy our `favorites` contract. We can grab our contract with `from src import favorites`. Next, we'll import `VyperContract` so we can assign a type to our deployed contract: + +```python +from src import favorites +from moccasin.boa_tools import VyperContract +``` + +Let's finish the function: + +```python +def deploy_favorites() -> VyperContract: + favorites_contract: VyperContract = favorites.deploy() + return favorites_contract +``` + +Next, we'll create a function called `deploy_factory()` that will take a `favorites_contract` and deploy our `favorites_factory`: + +```python +def deploy_factory(favorites_contract: VyperContract): + favorites_factory = favorites_factory.deploy(favorites_contract.address) + favorites_factory.create_favorites_contract() +``` + +To make sure our `favorites_factory` is deployed with the address of our initial `favorites` contract, we'll use the `@` function in our deploy script to grab the address: + +```python +new_favorites_address: str = favorites_factory.list_of_favorite_contracts[0] +new_favorites_contract: VyperContract = favorites.at(new_favorites_address) +print(f"Stored value is: {new_favorites_contract.retrieve()}") +``` + +We can now create our `mocassin_main()` function and run it in our terminal: + +```python +def moccasin_main(): + favorites_contract = deploy_favorites() + deploy_factory(favorites_contract) + +``` + +```bash +mox run deploy +``` + +This will deploy our contracts, and we can see the results in the terminal. From eb471a5bcb603466688476e5fce0f7d23c90fbb7 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:10:51 -0700 Subject: [PATCH 735/797] Equious updated courses/moccasin-101/5-mox-five/7-extcall/+page.md. --- .../5-mox-five/7-extcall/+page.md | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/7-extcall/+page.md b/courses/moccasin-101/5-mox-five/7-extcall/+page.md index 36c841a81..730264597 100644 --- a/courses/moccasin-101/5-mox-five/7-extcall/+page.md +++ b/courses/moccasin-101/5-mox-five/7-extcall/+page.md @@ -1,3 +1,43 @@ ---- - title: Extcall - --- \ No newline at end of file +## Cross-Contract Interactions (Extcall) + +In this lesson, we are going to learn about interacting with other contracts. + +We begin with a Python script. + +```python +from src import favorites, favorites_factory +from moccasin.boa.tools import VyperContract + +def deploy_favorites() -> VyperContract: + favorites_contract: VyperContract = favorites.deploy() + return favorites_contract + +def deploy_factory(favorites_contract: VyperContract): + factory_contract: VyperContract = favorites_factory.deploy(favorites_contract_address) + factory_contract.create_favorites(1) + new_favorites_address: str = factory_contract.list_of_favorite_contracts(0) + new_favorites_contract: VyperContract = favorites.at(new_favorites_address) + print(f"Stored value is: {new_favorites_contract.retrieve()}") + factory_contract.store_from_factory(0, 88) + print(f"New contract stored value is: {new_favorites_contract.retrieve()}") + print(f"Factory stored value is: {factory_contract.retrieve()}") + +def moccasin_main(): + favorites_contract = deploy_favorites() + deploy_factory(favorites_contract) + +moccasin_main() +``` + +We will run the code in a terminal. + +```bash +patrick@cu:mox-five-more-cu $ & mox run deploy +Running run command... +Stored value is: 77 +New contract stored value is 88 +Original contract stored value is 7 +patrick@cu:mox-five-more-cu $ +``` + +We can use this to show how calling a function from a factory contract can affect the state of another contract. We can update the value of `favorites.vy` by calling the `store()` function from the `favorites_factory.vy` contract. We can also call `retrieve()` on the `favorites.vy` contract to see the stored value. From 79993ef51e26443dbb0c736cd5565dda9ef0840b Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:11:20 -0700 Subject: [PATCH 736/797] Equious updated courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md. --- .../8-store-contract-by-interface/+page.md | 43 +++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md b/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md index d79d0e7af..fad37f067 100644 --- a/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md +++ b/courses/moccasin-101/5-mox-five/8-store-contract-by-interface/+page.md @@ -1,3 +1,40 @@ ---- - title: Store Contract By Interface - --- \ No newline at end of file +## Storing Contracts By Interface Type + +We're going to do a little bit of refactoring here, just to show you something cool that you can do. + +This `i_favorites` interface, we can also store contracts not just by address, but we could store them as type `i_favorites`. + +So, what we can do is instead of storing this as an address, we can store these as this `i_favorites` type. + +If we do that, we're actually going to get to save an extra line of code. + +Down here, when we call `self.list_of_favorite_contracts` at the favorites index, it's not going to give me an address anymore, it's going to give me an `i_favorites`. + +So, what we can do is we can say, instead of `favorites_address`, we can do `favorites_contract` of type `i_favorites` and then just delete that next line. + +Additionally, when we do `self.list_of_favorite_contracts.append`, we would have to wrap our `new_favorites_contract` as type `i_favorites`. + +We don't have to do this. If what we just showed you is actually very confusing, feel free to just move it back to what it was. Which is this one right here. Feel free to just move it back to what it was, and go with that. Whatever is easier for you, this is your learning journey, and you can come back to this later and go, "Okay, what did Patrick mean by that? Let me ask some AIs, etc., etc." + +This is another way that we can actually store and work with these variables. + +```python +from interfaces import i_favorites + +list_of_favorite_contracts: publicDynArray[i_favorites, 100] +original_favorite_contract: address + +@deploy +def __init__(original_favorite_contract: address): + self.original_favorite_contract = original_favorite_contract + +@external +def create_favorites_contract(): + new_favorites_contract: address = create_copy_of(self.original_favorite_contract) + self.list_of_favorite_contracts.append(new_favorites_contract) + +@external +def store_from_factory(favorites_index: uint256, new_number: uint256): + favorites_contract: i_favorites = self.list_of_favorite_contracts[favorites_index] + favorites_contract.store(new_number) +``` \ No newline at end of file From cb31191827b1b3457a328b86e869e3c387494078 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:11:49 -0700 Subject: [PATCH 737/797] Equious updated courses/moccasin-101/5-mox-five/9-method-chaining/+page.md. --- .../5-mox-five/9-method-chaining/+page.md | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md b/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md index 2aa8fbe12..cd9b72c02 100644 --- a/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md +++ b/courses/moccasin-101/5-mox-five/9-method-chaining/+page.md @@ -1,3 +1,38 @@ ---- - title: Method Chaining - --- \ No newline at end of file +In this lesson, we will continue working with the `favorites` contract. + +We will introduce a `view` function and we'll look at some more advanced concepts, like chaining several lines of code together to perform a single action. + +First, let's add a `view` function. + +```python +@view +def view_from_factory(favorites_index: uint256) -> uint256: + favorites_contract: IFavorites = self.list_of_favorite_contracts[favorites_index] + return extcall(favorites_contract.retrieve()) +``` + +We can call this function using `extcall` but, because it's a `view` function, we'll use `staticcall`. + +```python +values: uint256 = staticcall(favorites_contract.retrieve()) +``` + +This line of code is equivalent to the following three lines: + +```python +favorites_contract: IFavorites = self.list_of_favorite_contracts[favorites_index] +values: uint256 = extcall(favorites_contract.retrieve()) +return values +``` + +Whether you prefer to use the single line or the three separate lines is up to you, but both achieve the same result. + +This is an example of method chaining. We're chaining several lines of code together to perform a single action. We can also chain the calls to `staticcall` and `retrieve`. + +```python +values: uint256 = staticcall(self.list_of_favorite_contracts[favorites_index].retrieve()) +``` + +This line of code will first access the `favorites_contract` from the list, then call the `retrieve` function on it, and finally return the value. + +The use of method chaining can help to make your code more concise and readable. It's a powerful technique that you can use in your own Vyper contracts. From 84ba0e5b837afbad29e8a05a4cd8bdec7d168e52 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:12:18 -0700 Subject: [PATCH 738/797] Equious updated courses/moccasin-101/6-mox-coffee/1-intro/+page.md. --- .../6-mox-coffee/1-intro/+page.md | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/1-intro/+page.md b/courses/moccasin-101/6-mox-coffee/1-intro/+page.md index b7e64e913..b7c5ed6de 100644 --- a/courses/moccasin-101/6-mox-coffee/1-intro/+page.md +++ b/courses/moccasin-101/6-mox-coffee/1-intro/+page.md @@ -1,3 +1,45 @@ ---- - title: Intro - --- \ No newline at end of file +## Section: Moccasin: Buy Me A Coffee + +In this section, we are going to make our Buy Me A Coffee project very professional. + +We are going to use the GitHub repo associated with the project to find all the code. + +We are going to make some changes to the code, including refactoring, modules and imports. The biggest thing that we are going to improve on is our deployment process and our tests. + +We will write unit tests, staging tests and integration tests. + +We are going to learn what deployments.db does and what storage does. + +We are going to learn about a powerful moccasin feature called manifest named, and how it makes testing easier. + +Finally, we are going to push our code up to GitHub, which will be the start of your portfolio. + +Now let's look at the tests. + +We can run our tests with the following command: + +```bash +mox test +``` + +We can also run coverage tests with: + +```bash +mox test --coverage +``` + +We can also run tests on a fork of the Sepolia testnet with: + +```bash +mox test --network sepolia --fork +``` + +We can also run staging tests. + +We are going to learn how to write very defensible code. One mistake can mean the end of millions of dollars. + +In the smart contract world, you need to be able to write very defensible code. + +We are going to learn about all the cool features of moccasin, and you are going to become a better Python and Vyper developer. + +We are going to push this code up to GitHub so you can start building your portfolio. From 55c92df02daaed80525a1e29872679c96936f7c7 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:14:51 -0700 Subject: [PATCH 739/797] Equious updated courses/moccasin-101/6-mox-coffee/10-kinds/+page.md. --- .../6-mox-coffee/10-kinds/+page.md | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md b/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md index 3a20eb491..6dc6f028b 100644 --- a/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md +++ b/courses/moccasin-101/6-mox-coffee/10-kinds/+page.md @@ -1,3 +1,17 @@ ---- - title: Kinds - --- \ No newline at end of file +## Kinds of Tests + +We're back in the GitHub repo associated with this course in section with Moccasin Buy Me A Coffee. + +We have several, several, different types of tests. + +The test that we've gone over so far are something called unit tests. And these basically test a single function or part of your code. + +The next step up from that is usually integration tests. And this is testing different systems together or different contracts together or basically the definition can be a little bit loose depending on how you define it. + +Then, the step up from that would be a staging test. And these are testing your code in a production-like environment. + +Now, one of the tests kind of unique to blockchain is going to be this type of forked test. Although, you could probably categorize these as staging tests as well. And this is essentially where you deploy your contracts to a fake virtual network or a forked network and call the different functions on it. We've kind of done something like this with tenderly's virtual network, but we're also going to do it with alchemy here as well. And these fake networks will simulate what it's like to actually work with the real blockchain. + +Then, there's fuzz and formal verification. Now, fuzzing is incredibly important, and you should 100% learn how to fuzz. And then, formal verification is when you mathematically prove different functions. + +So, for us, we are going to do all of these types of tests for this project. And then, pretty soon once you get to the stablecoin portion, we are going to add fuzz testing as well. From bfac70622de2ed6e3df5aadd4c95a7359bb270ea Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:16:20 -0700 Subject: [PATCH 740/797] Equious updated courses/moccasin-101/6-mox-coffee/11-unit/+page.md. --- .../6-mox-coffee/11-unit/+page.md | 74 ++++++++++++++++++- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/11-unit/+page.md b/courses/moccasin-101/6-mox-coffee/11-unit/+page.md index ef3d00c8c..7d61be4cb 100644 --- a/courses/moccasin-101/6-mox-coffee/11-unit/+page.md +++ b/courses/moccasin-101/6-mox-coffee/11-unit/+page.md @@ -1,3 +1,71 @@ ---- - title: Unit - --- \ No newline at end of file +## Unit Tests + +We'll start with the simplest kind of test, unit tests. We'll test a function and see if it works. We can create a new folder called **unit** to hold these tests. + +We'll need to create a file called **conftest.py** (make sure this is in your **tests** folder, not in your **unit** folder) to hold our fixtures. + +```python +import pytest + +@pytest.fixture +def coffee(): + return deploy_coffee() +``` + +Here, we import the `pytest` library and create a function called `coffee` that returns the result of calling our deploy script. + +Next, we need to create a file called **test_unit_coffee.py** in our **unit** folder to write our actual tests. + +```python +from eth_utils import to_wei + +def test_price_feed_is_correct(coffee, eth_usd): + assert coffee.PRICE_FEED() == eth_usd.address + +def test_starting_values(coffee, account): + assert coffee.MINIMUM_USD() == to_wei(5, "ether") + assert coffee.OWNER() == account.address +``` + +Here, we import the `to_wei` function from `eth_utils`, then we create two tests. The first checks if the price feed address is correct. The second tests the starting values of the coffee contract. + +We'll run our tests using the command: + +```bash +mox test +``` + +We'll need to make sure to import the `get_active_network` function in **conftest.py**, as well as create a fixture for our account. + +```python +from moccasin.config import get_active_network + +@pytest.fixture(scope="session") +def account(): + return get_active_network().get_default_account() +``` + +Now, we've created a `get_active_network` fixture that will always return the same default account for each test, ensuring consistency. + +We've also added a `to_wei` function to test the minimum USD value in Wei. + +If we run our tests again using the command: + +```bash +mox test +``` + +We'll see that our tests are all passing. + +## TAG: add a code block to show the deployment script + +We've covered how to write unit tests for our coffee contract, ensuring the price feed and starting values are correct. Now, let's test the owner of the contract. + +Let's create a new test: + +```python +def test_owner_is_account(coffee, account): + assert coffee.OWNER() == account.address +``` + +We use the `account` fixture we created in our **conftest.py** to make sure the owner of the contract is the same as the account that deployed it. From 1bc26a136473a799ddee3a96b24ebefb2f76bd5d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:17:06 -0700 Subject: [PATCH 741/797] Equious updated courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md. --- .../6-mox-coffee/12-test-revert/+page.md | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md b/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md index 66d5d3331..e8bd88d54 100644 --- a/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md +++ b/courses/moccasin-101/6-mox-coffee/12-test-revert/+page.md @@ -1,3 +1,35 @@ ---- - title: Test Revert - --- \ No newline at end of file +## Testing for Reverts + +We will learn how to test for reverts in our smart contracts. + +When we test our smart contracts, we also want to test that they revert correctly. + +For example, if somebody calls our fund function without enough money, we should expect this to actually revert. So, how do we test when a function reverts? + +We can use the `boa.reverts` method. We can add this code to our test file: + +```python +def test_fund_fails_without_enough_eth(coffee): + with boa.reverts(): + coffee.fund() +``` + +This will test that the `fund` function reverts when called without enough ETH. + +We can even check the exact revert message. We can add this code to our test file: + +```python +def test_fund_fails_without_enough_eth(coffee): + with boa.reverts("You must spend more ETH!"): + coffee.fund() +``` + +This will test that the `fund` function reverts with the message "You must spend more ETH!". + +To run a specific test, we can use the following command: + +```bash +mox test -k test_fund_fails_without_enough_eth +``` + +This will only run the test called `test_fund_fails_without_enough_eth`. From b552413dbac7a6d4337b4ad7518809db94b806f8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:17:31 -0700 Subject: [PATCH 742/797] Equious updated courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md. --- .../6-mox-coffee/13-set-balance/+page.md | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md b/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md index b44c55fda..bb4758fe5 100644 --- a/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md +++ b/courses/moccasin-101/6-mox-coffee/13-set-balance/+page.md @@ -1,3 +1,34 @@ ---- - title: Set Balance - --- \ No newline at end of file +## Set balance in MochaSin and TitanoBoa + +We are going to discuss some cheat codes in MochaSin and TitanoBoa. These codes will allow us to set the balance of a user and also pretend or prank a user. This is important if we want to test how other users with different amounts of money interact with our contract. + +We are going to call our `fund` function and actually send some money, but we need to make sure that whoever calls this `fund` function actually has money to do so. This is where we can start getting into the concept of cheat codes or functions that work with the PyEVM or local forked network in order to set up our tests better. + +For example, if we want to call `fund`, we'll need some money to actually have money. So, we can add this test: + +```python +def test_fund_with_money(coffee, account): + account.transfer(coffee.address, to_wei(5, "ether")) + assert coffee.balance() == to_wei(5, "ether") + boa.env.set_balance(account.address, SEND_VALUE) + coffee.fund(value=SEND_VALUE) + # Assert + amount_funded = coffee.funders(0) + assert amount_funded == SEND_VALUE +``` + +We are going to call the `fund` function with money. In order to do this, we'll need to send some money to the account we want to interact with. Then, we can set the balance of the account with the `SEND_VALUE` amount. We can then go ahead and run this test: + +```bash +mox test +``` + +Or, we can run a specific test with: + +```bash +mox test -k test_fund_with_money +``` + +We are testing some basic functionality here, and I'm going to leave a lot of time for you to actually write a whole bunch of tests because you should get incredibly good at writing tests. AI's are very helpful at writing tests, and you should use AI's to help you write your tests. But, sometimes, AI's screw it up, and what's worse is if you write a test or AI writes a test, and it doesn't test what you want it to test, and it breaks. That will be very bad. + +So, let's keep going, and I'll leave you some time to write tests afterwards. From 2d88070c3541c3d3564b71959df3aae50b183166 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:18:01 -0700 Subject: [PATCH 743/797] Equious updated courses/moccasin-101/6-mox-coffee/14-prank/+page.md. --- .../6-mox-coffee/14-prank/+page.md | 66 ++++++++++++++++++- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/14-prank/+page.md b/courses/moccasin-101/6-mox-coffee/14-prank/+page.md index 024a80546..f8175b517 100644 --- a/courses/moccasin-101/6-mox-coffee/14-prank/+page.md +++ b/courses/moccasin-101/6-mox-coffee/14-prank/+page.md @@ -1,3 +1,63 @@ ---- - title: Prank - --- \ No newline at end of file +## Pranking and Impersonating in Solidity Tests + +Sometimes when we're writing tests, we want to pretend to be somebody else, or we want to prank. Our account, the default account, is going to be who deployed this address. But we should probably check that the non-owner cannot withdraw. + +We will need to get some other random user. We can assign a value to `RANDOM_USER`: + +```python +RANDOM_USER = boa.env.generate_address('non-owner') +``` + +Now we can write a test called `test_non_owner_cannot_withdraw`: + +```python +def test_non_owner_cannot_withdraw(coffee, account): + # Arrange + boa.env.set_balance(account.address, SEND_VALUE) + coffee.fund(value=SEND_VALUE) + # Act + with boa.prank(RANDOM_USER): + boa.reverts('You are not the owner!', + coffee.withdraw()) +``` + +We are arranging by funding the account. Then, we are pranking a random user, and we are reverting. Let's test it out with a terminal command: + +```bash +mox test +``` + +This is how you pretend to be some other user. This is how you set the current user to somebody else random. And this is how you revert. Let's keep going. + +We will check to see if it doesn't work. Let's also check to see how it does work. We can do a test called `test_owner_can_withdraw`. + +```python +def test_owner_can_withdraw(coffee, account): + # Arrange + boa.env.set_balance(account.address, SEND_VALUE) + coffee.fund(value=SEND_VALUE) + # Act + with boa.env.prank(coffee.OWNER): + coffee.withdraw() + # Assert + assert coffee.funders() == boa.env.get_balance(coffee.OWNER) == 0 +``` + +Usually, just to make sure, I like to also prank that I am actually the owner here. So, I might do something like `boa.env.set_balance` and then `coffee.OWNER`. + +We then do `coffee.fund(value=SEND_VALUE)`. Finally, we assert that `boa.env.get_balance(coffee.address)` is equal to zero. + +Let's test this out. + +```bash +mox test +``` + +We ran into an error "unsupported type". Let's scroll up and see what line it's mad at me about. It looks like it's on the `assert` line about getting the balance of `coffee.address`. + +Let's change the `assert` line, to instead be: +```python +assert coffee.funders() == 0 +``` + +Let's run `mox test` again and see if it passes. From 54c49851760209a41f9591e2f169ead4bf131da2 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:18:28 -0700 Subject: [PATCH 744/797] Equious updated courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md. --- .../6-mox-coffee/15-mid-sec-work/+page.md | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md b/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md index 510c15538..45a17f13f 100644 --- a/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md +++ b/courses/moccasin-101/6-mox-coffee/15-mid-sec-work/+page.md @@ -1,3 +1,42 @@ ---- - title: Mid Sec Work - --- \ No newline at end of file +## Mid-Section Workshop + +We've done a little bit of refactoring to make our code more efficient. We're also starting to do some interesting things with our tests, and we want you to write one of the last tests we'll need before we move on to some more advanced topics. + +We're going to do Workshop 1. We want you to write a test that: + +* funds the contract with 10 different funders +* withdraws the funds using the owner +* asserts that: + * the ending balance of `buy_me_a_coffee` is 0 + * the ending balance of the owner is the addition of all the amounts the funders added + +This might sound simple, but there are some tricky parts to it. We've seen how to use `boa.env.generate_address()` to make a random address to use as a funder, so try making 10 of them. For bonus points, see if you can write some code that makes it a bit easier to make a bunch of these addresses at once, rather than just copy-pasting the code 10 times. + +To withdraw the funds, we'll have to use the `prank` function to pretend we are the owner. We've done this in earlier lessons, so this should be a review. + +Finally, we'll want to use the `boa.env.get_balance()` function to check the ending balance of both the contract and the owner. We've also seen this function in earlier lessons, so this part should be familiar. + +As always, spend at most 25 minutes on this workshop. If you're stuck, take a break and ask for help or look at the solution on GitHub. + +```python +RANDOM_USER = boa.env.generate_address("non-owner") +``` + +```python +def test_fund_with_money(coffee, account): + # Arrange + boa.env.set_balance(account.address, SEND_VALUE) + # Act + coffee.fund(value=SEND_VALUE) + # Asset + funder = coffee.funders(0) + assert funder == account.address + assert coffee.funder_to_amount(funder) == SEND_VALUE +``` + +```python +def test_owner_can_withdraw(coffee, funded): + with boa.env.prank(coffee.OWNER()): + coffee_funded.withdraw() + assert boa.env.get_balance(coffee_funded.address) == 0 +``` \ No newline at end of file From 2ba7ba1e7ad8406a980a7152d0f0587aed21e4ed Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:18:54 -0700 Subject: [PATCH 745/797] Equious updated courses/moccasin-101/6-mox-coffee/16-more-fixtures/+page.md. --- .../6-mox-coffee/16-more-fixtures/+page.md | 90 ++++++++++++++++++- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/16-more-fixtures/+page.md b/courses/moccasin-101/6-mox-coffee/16-more-fixtures/+page.md index e5d0bc24e..726722802 100644 --- a/courses/moccasin-101/6-mox-coffee/16-more-fixtures/+page.md +++ b/courses/moccasin-101/6-mox-coffee/16-more-fixtures/+page.md @@ -1,3 +1,87 @@ ---- - title: More Fixtures - --- \ No newline at end of file +## More Fixtures + +We can create a fixture to reduce the code duplication in our tests. + +We can use a `pytest.fixture` with a `scope="function"` to create a fixture that runs once per test function. Here's how we can write a new fixture called `coffee_funded`: + +```python +@pytest.fixture(scope="function") +def coffee_funded(coffee, account): + boa.env.set_balance(account.address, SEND_VALUE) + coffee.fund(value=SEND_VALUE) + return coffee +``` + +We can then use this fixture in our tests. For example, in the `test_non_owner_cannot_withdraw` test, instead of setting the balance of the account and funding the contract, we can now use the `coffee_funded` fixture: + +```python +def test_non_owner_cannot_withdraw(coffee_funded, account): + # Arrange + with boa.env.prank(RANDOM_USER): + with boa.reverts("Not the contract owner!"): + coffee_funded.withdraw() +``` + +We can also update the `test_owner_can_withdraw` test: + +```python +def test_owner_can_withdraw(coffee_funded, account): + with boa.env.prank(coffee_funded.OWNER): + coffee_funded.withdraw() + assert boa.env.get_balance(coffee_funded.address) == 0 +``` + +We'll also add a new test to make sure we can withdraw from the contract: + +```python +def test_fund_with_money(coffee_funded, account): + # Arrange + boa.env.set_balance(account.address, SEND_VALUE) + + # Act + coffee_funded.fund(value=SEND_VALUE) + + # Assert + funder = coffee_funded.funders(0) + assert funder == account.address + assert coffee_funded.to_amount_funded(funder) == SEND_VALUE +``` + +And lastly, we can update the `test_fund_with_money` test as well: + +```python +def test_fund_with_money(coffee_funded, account): + # Arrange + boa.env.set_balance(account.address, SEND_VALUE) + + # Act + coffee_funded.fund(value=SEND_VALUE) + + # Assert + funder = coffee_funded.funders(0) + assert funder == account.address + assert coffee_funded.to_amount_funded(funder) == SEND_VALUE +``` + +We'll make sure to import `boa` and `SEND_VALUE` in our test file. +```python +from eth_utils import to_wei +import boa +from tests.conftest import SEND_VALUE +``` + +Now we can run our tests: + +```bash +mox test +``` + +We'll have to update our `conftest.py` file to add our new `SEND_VALUE` variable: + +```python +SEND_VALUE = to_wei(1, "ether") +``` + +Running our tests again will pass. + +Our tests now reuse code by using the `coffee_funded` fixture, which helps us avoid duplicating code in our tests and makes them more readable. From 2f0b210c99031e4a8f4a8d5ec043ae2a0749cfa3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:20:21 -0700 Subject: [PATCH 746/797] Equious updated courses/moccasin-101/6-mox-coffee/17-test-coverage/+page.md. --- .../6-mox-coffee/17-test-coverage/+page.md | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/17-test-coverage/+page.md b/courses/moccasin-101/6-mox-coffee/17-test-coverage/+page.md index 25317a24e..bd64019be 100644 --- a/courses/moccasin-101/6-mox-coffee/17-test-coverage/+page.md +++ b/courses/moccasin-101/6-mox-coffee/17-test-coverage/+page.md @@ -1,3 +1,34 @@ ---- - title: Test Coverage - --- \ No newline at end of file +## Test Coverage + +We've been writing tests for our smart contracts. You might be thinking, "Hey, I've done a pretty good job testing all of my contracts. I'm content with the amount I've tested." This is where the concept of **coverage** comes into play. + +Moccasin comes with support for a tool called **pytest-cov**. It's a way to test how much of our code has actually been tested. We can install **pytest-cov** using this command: + +```bash +pip install pytest-cov +``` + +Let's say we want to test how much of our current smart contract has been tested. We can run the following command: + +```bash +mox test --coverage +``` + +This command will run all of our tests and compare it to how much of our contracts we've actually tested. + +The output of the command will show us exactly which lines of code haven't been tested. For example, we might see that lines 64-69 of our smart contract have not been tested. + +To see the exact lines of code that we've missed, we can run this command: + +```bash +mox test --coverage --cov-report term-missing +``` + +Now, we can go into the lines of code that haven't been tested and add some test cases for those. For example, if lines 64-69 are our `get_eth_to_usd_rate` function, we might add a test case for that like so: + +```python +def test_get_rate(coffee): + assert coffee.get_eth_to_usd_rate(SEND_VALUE) > 0 +``` + +We should get a value that is greater than zero, because we are sending one whole ETH. Now if we run our test coverage command again, we should see that the lines 64-69 are now covered. From d7e6d0117bafd24904906e409c9cd5ebc3815cc3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:21:03 -0700 Subject: [PATCH 747/797] Equious updated courses/moccasin-101/6-mox-coffee/18-gas-profile/+page.md. --- .../6-mox-coffee/18-gas-profile/+page.md | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/18-gas-profile/+page.md b/courses/moccasin-101/6-mox-coffee/18-gas-profile/+page.md index 88ca818ae..dac0b48dd 100644 --- a/courses/moccasin-101/6-mox-coffee/18-gas-profile/+page.md +++ b/courses/moccasin-101/6-mox-coffee/18-gas-profile/+page.md @@ -1,3 +1,41 @@ ---- - title: Gas Profile - --- \ No newline at end of file +## Gas Profiling + +Let's talk about gas profiling. We'll start by looking at the differences in gas cost between storage variables and constant variables. + +So, to do some testing, let's go ahead and run a command in our terminal: + +```bash +mox test --help +``` + +We can see in the help output there is a `gas-profile` command here where we can get an output on gas use for all of our test functions. So, if I just run: + +```bash +mox test --gas-profile +``` + +This will give us a large output showing how much gas these functions cost. + +This output is kind of borderline impossible to read. So what we might do is run this again with a little zoom way the heck out. Now, I'm going to run this command, and zoom way back in. We can see things a little bit better now. + +So, we have count, mean, median, standard deviation, min, and max. If we scroll down into this section here and scroll over, we can see how much calling each one of these functions costs, including the functions up here, the different lines, and, of course, our different functions. + +Down here, we can see, first off the count, which is how many times in the test, or the test suite, it was called. Then, we have the average gas cost, the median gas cost, standard deviation, the minimum, and the maximum. And, it's literally for like every line of computation here, which is kind of crazy. + +Okay, raw call owner. Let's look at this one. This one was 19 gas on average. Okay, cool. + +So, now let's go back here. Let's do a little refactoring. You don't have to do this, by the way. + +Let's get rid of it being immutable. So, the owner is no longer immutable. So, we'll do `self.owner` here. Any place we see owner, where else is owner? Owner, `self.owner`, we'll do `self.owner` here. + +Okay, great. Remember, this was 19 gas when it was a constant or, excuse me, 19 gas when it was immutable. + +Let's rerun this again to `gas.txt`: + +```bash +mox test --gas-profile > gas.txt +``` + +Now, we're using `self.owner`. Oh, I got to Sorry, I got to zoom way out and run this. Zoom zoom zoom up up. Run it. Zoom way back in. Now, let's see. Now it costs more. Now it's 21 here. + +So, we can see that we actually ended up spending more gas by having it be a storage variable. So I'm actually going to move it back to immutable. So, if you want to check how much more or less gas your contract uses, you can use that `gas-profile` command. From d8fd60eec3748d0aadc4d1fec78b3c70d886067f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:22:45 -0700 Subject: [PATCH 748/797] Equious updated courses/moccasin-101/6-mox-coffee/19-fork-tests/+page.md. --- .../6-mox-coffee/19-fork-tests/+page.md | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/19-fork-tests/+page.md b/courses/moccasin-101/6-mox-coffee/19-fork-tests/+page.md index 2c00fcac4..e8f72aa72 100644 --- a/courses/moccasin-101/6-mox-coffee/19-fork-tests/+page.md +++ b/courses/moccasin-101/6-mox-coffee/19-fork-tests/+page.md @@ -1,3 +1,29 @@ ---- - title: Fork Tests - --- \ No newline at end of file +## Fork Tests + +We've written some unit tests and learned a little more about gas. We could write an integration test, but we've been kind of doing that with our unit tests here, so I'm going to skip it for now. But, we haven't done the staging tests and we also haven't done the forked tests. So, let's go ahead and create the staging folder, but let's do the fork tests, because technically the fork tests are a type of staging tests. + +Now, what are fork tests? Now, fork tests are going to be very similar to us just working with the tenderly virtual network. So, our tenderly virtual network is an example of a forked network. So, what really is a forked chain, cuz I've kind of been dancing around it a little bit? Well, so, imagine there's a real blockchain, right? A real blockchain is happening and blocks are being added, and people are sending transactions, and everything. Well, imagine we, on the side, what we do is we spin up our little fake anvil chain. We spin up a fake much tinier little chain. Now, the idea behind a forked blockchain is that it will resemble everything that's on a real blockchain, but in an easier way. So, if in my python code, I'm connected to this forked blockchain, but I call `price_feed.latestAnswer`... Well, our forked blockchain is empty, it doesn't have this price feed on it. Well, the real blockchain does have the price feed, right? It does have this price feed contract. So, since we're connected to kind of this forked empty little thing, what happens is we say hey, we want the latest answer or fake chain. What it does is it makes an API call to the real chain. Says hey, I need this price feed. I need this contract. And what it does is kind of at request time, it'll grab that price feed and give it to itself. Give it to itself and it'll like, oh yeah, I had this the whole time. They'll go, oh, I had this the whole time. And then, we will be able to call it and interact with it as if we were interacting with the real blockchain. This allows us to quote-unquote have the whole blockchain, but only really when we request something about the real blockchain. This is also incredibly helpful for us to have this forked blockchain because then, we can do something like `buy_me_a_coffee.deploy` and we'll deploy it to this forked faked blockchain, which kind of has all the real contracts that are on the actual real blockchain. Because any time any of these contracts need the data from a real contract, our forked blockchain will just go ahead and grab it and copy it to itself essentially. So, forked blockchains are incredibly helpful because they allow us to simulate a real blockchain without actually having the whole blockchain, but for our from our perspectives, we have the whole blockchain at our disposal, which is really really nice. And forked tests and running forked tests therefore are one of the most important steps whenever you're going to try to deploy a smart contract because you want to see hey, what does my test look like compared up against a real blockchain with the real contracts, because my mocks could have been wrong. I could have screwed these up, right? So, we always want to run what's called forked tests. + +Now, these are actually really easy for us to run in Moccasin. All we have to do is in our `Moccasin.toml` we have that real network set up and then what we can do is we can just do: +```bash +mox test --network sepolia --fork +``` + +Let's say we wanted to test our smart contracts against the real sepolia test net. But, then all we have to do is `--fork`. This tells our test suite to use the sepolia testnet but run it as a fork. Don't run it, don't actually deploy any contracts, don't actually do anything. And, if we hit enter, we do have to enter our password for the default key, because we did set the default account name to default. So, we do have to do this. You could have, we could have not done that and it would have worked a little bit easier, but anyways, let's enter the password. You'll notice it didn't prompt us to say hey you're sending a real transaction cuz it's smart enough to know that we're not. + +Now, this will take a little bit longer to run these tests because we're actually making API calls to our sepolia RPC URL. And, I just realized that our active network does indeed have an explorer, but we need to do: +```python +if active_network.has_explorer() and active_network.is_local_or_forked_network() is False: +``` + +So, if we don't have this line, when we go to run our fork tests, this is going to try to kick off and we don't want to verify to nowhereville. So yeah. So, now that we've updated this, if `active_network.has_explorer()`, and `active_network.is_local_or_forked_network()` is false: +```python +result = active_network.moccasin_verify(coffee) +``` + +Now, we can run: +```bash +mox test --network sepolia --fork +``` + +And we see that everything passes. So, this is additionally why it's so important to do these conf tests as well. From 3f3686a862a42d1b9d95e109bbd18cf9e844662e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:23:12 -0700 Subject: [PATCH 749/797] Equious updated courses/moccasin-101/6-mox-coffee/2-setup/+page.md. --- .../6-mox-coffee/2-setup/+page.md | 127 +++++++++++++++++- 1 file changed, 124 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/2-setup/+page.md b/courses/moccasin-101/6-mox-coffee/2-setup/+page.md index fcc7a149d..101d663d0 100644 --- a/courses/moccasin-101/6-mox-coffee/2-setup/+page.md +++ b/courses/moccasin-101/6-mox-coffee/2-setup/+page.md @@ -1,3 +1,124 @@ ---- - title: Setup - --- \ No newline at end of file +## Project Setup + +We're back in our `mox-cu` folder. Let's do a little `ls` to see what we've built so far: + +```bash +ls +``` + +We're building up a nice little folder here filled with demo projects that we're using to level up our career. Let's go ahead and make the next folder. We'll do `mkdir` and name this new folder `mox-buy-me-a-coffee-cu`. + +```bash +mkdir mox-buy-me-a-coffee-cu +``` + +Then, we'll `cd` into that folder. + +```bash +cd mox-buy-me-a-coffee-cu +``` + +Now, we can open this folder in our code editor. We'll do `code .`. + +```bash +code . +``` + +We already know that we have `mox --help` and `mox` installed. We're going to initialize our new project using `mox init`. We want to use VS Code, so we'll pass in the flag `--vscode`, and we'll use a `pyproject` file, so we'll pass in the `--pyproject` flag as well: + +```bash +mox init --vscode --pyproject +``` + +Now, we'll delete the files that were created in this directory so we can start from a blank project. We can just right-click, then click "delete" and "move to trash". + +To get our starting code for this project, we'll use the code from the "Buy Me A Coffee" section in the Remix Fundamentals video. We'll go over to our GitHub repository, open `remix-buy-me-a-coffee-cu` and then open the `buy-me-a-coffee.vy` file. We're going to bring this code into our `mox-buy-me-a-coffee-cu` directory. We can copy it and paste it into a new file. We can right-click, select "New File", and name it `buy-me-a-coffee.vy`: + +```python +# pragma version ^0.4.0 +""" +@license MIT +@title Buy Me A Coffee! +@author You! +@notice This contract is for creating a sample funding contract + +We'll learn a new way to do interfaces later... +""" +interface AggregatorV3Interface: + def decimals() -> uint256: view + def description() -> String[1000]: view + def version() -> uint256: view + def latestAnswer() -> int256: view + +# Constants & Immutables +MINIMUM_USD: public(constant(uint256)) = wei_value(5, "ether") +PRICE_FEED: public(immutable(AggregatorV3Interface)) = # 0x694AA1769357215DE4FAC081bf1f309c33Dc4536 sepolia +OWNER: public(immutable(address)) = +PRECISION: constant(uint256) = 1 * (10 ** 18) + +# Storage +funders: public(DynArray[address, 1000]) +funder_to_amount_funded: public(HashMap[address, uint256]) + +with constants: 262, 853 + +@deploy +def init(price_feed: address): + PRICE_FEED = AggregatorV3Interface(price_feed) + OWNER = msg.sender + +@external +@payable +def fund(): + """Allows users to send $ to this contract + Have a minimum amount to send + How do we convert the ETH amount to dollars amount? + """ + usd_value_of_eth: uint256 = self.get_eth_to_usd_rate(msg.value) + assert usd_value_of_eth >= MINIMUM_USD, "You must spend more ETH!" + self.funders.append(msg.sender) + self.funder_to_amount_funded[msg.sender] += msg.value + +@external +def withdraw(): + """Take the money out of the contract, that people sent via the fund function. + How do we make sure only we can pull the money out? + """ + assert msg.sender == OWNER, "Not the contract owner!" + raw_call(OWNER, b"", value = self.balance) + # send(OWNER, self.balance) + # resetting + for funder: address in self.funders: + self.funder_to_amount_funded[funder] = 0 + self.funders = [] + +@internal +@view +def _get_eth_to_usd_rate(eth_amount: uint256) -> uint256: + """Chris sent us 0.01 ETH for us to buy a coffee + Is that more or less than $5? + """ + price: int256 = staticcall(PRICE_FEED.latestAnswer()) + eth_price: uint256 = convert(price, price * eth_amount) * (10 ** 10) + eth_amount_in_usd: uint256 = (eth_price * eth_amount) // PRECISION + return eth_amount_in_usd # 18 '0's, 18 decimal places + +@external +@view +def get_eth_to_usd_rate(eth_amount: uint256) -> uint256: + return self._get_eth_to_usd_rate(eth_amount) + +@external +@payable +def default(): + self.fund() + +``` + +Now, we'll compile the code. We'll use `mox compile` to do that. + +```bash +mox compile +``` + +We have successfully compiled the contract. From 8a34c4d4c462272584326b39f14204a6afff6c94 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:23:40 -0700 Subject: [PATCH 750/797] Equious updated courses/moccasin-101/6-mox-coffee/20-staging/+page.md. --- .../6-mox-coffee/20-staging/+page.md | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/20-staging/+page.md b/courses/moccasin-101/6-mox-coffee/20-staging/+page.md index f2de04c12..c16615268 100644 --- a/courses/moccasin-101/6-mox-coffee/20-staging/+page.md +++ b/courses/moccasin-101/6-mox-coffee/20-staging/+page.md @@ -1,3 +1,51 @@ ---- - title: Staging - --- \ No newline at end of file +## Staging Tests + +We're going to be working with staging tests. Fork tests are technically a type of staging test. But we're going to be working with a type of test where we can actually deploy the smart contracts to a testnet or even to a mainnet. + +A set of tests you may want to run on an actual network is to make sure that the network does what you want it to do. + +We can also signify staging tests to run on real networks. To learn more about this, we can scroll down to staging markers in the Moccasin documentation. + +A lot of developers should run some sanity checks on a live network. For example, if you're working with oracles or any setup tricks. But, a lot of people don't. + +In order to run a test on an actual testnet, we have to mark it with a staging `pytest` marker. + +We can tell Moccasin that it can run the test, deploy the code, and send transactions. If we don't have a staging test, the tests should skip it. + +By default, all tests are marked as `local`. We can make a test that's both a staging and a local test by using the following: + +```python +@pytest.mark.staging +@pytest.mark.local +``` + +Let's write a staging test. We will create a new file called `test_staging_coffee.py`. + +```python +def test_can_fund_and_withdraw_live(): + active_network = get_active_network() + price_feed = active_network.manifest_named("price_feed") + coffee = deploy_coffee(price_feed) + coffee.fund(value=SEND_VALUE) + amount_funded = coffee.address_to_amount_funded(boa.env.eoa) + assert amount_funded == SEND_VALUE + coffee.withdraw() + assert boa.env.get_balance(coffee.address) == 0 +``` + +We will then run the test in our terminal using the following command: + +```bash +mox test --network sepolia +``` + +This will take a lot longer because we're sending real transactions. We can modify our `deploy` file to only run verification in the main function. + +**Tag:** We can add a code block here for the updated deploy file. + +This test might take a long time to run, and we can expect our tests to fail because we don't have any ETH on our testnet. + +We can also see that the tests are trying to verify the contract. + +This is how we write a staging test and run it on a live network. + From ba7074e098892e5d2f62cfe6f93c7ab12ddbe780 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:24:10 -0700 Subject: [PATCH 751/797] Equious updated courses/moccasin-101/6-mox-coffee/21-deployments-db/+page.md. --- .../6-mox-coffee/21-deployments-db/+page.md | 121 +++++++++++++++++- 1 file changed, 118 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/21-deployments-db/+page.md b/courses/moccasin-101/6-mox-coffee/21-deployments-db/+page.md index d1459d73d..9e1e3e129 100644 --- a/courses/moccasin-101/6-mox-coffee/21-deployments-db/+page.md +++ b/courses/moccasin-101/6-mox-coffee/21-deployments-db/+page.md @@ -1,3 +1,118 @@ ---- - title: Deployments Db - --- \ No newline at end of file +## Deployments Database + +We are working with a Python project that interacts with smart contracts, including a `buy_me_a_coffee` contract. + +We've set up a few test files, and if we run them, we can see that they all pass. + +```bash +mox test +``` + +We can also see that we have a `mocassin.toml` file with the following code: + +```python +[networks.tenderly-sepolia] +url = "$TENDERLY_RPC_URL" +save_to_db = false +default_account_name = "default" +``` + +This file is key to working with a database. The important feature to note here is the `save_to_db` option. We want to set this to `true`, which means Mocassin will save information about deployments to a database. + +Let's add a new network to the `mocassin.toml` file for interacting with the Anvil blockchain. + +```python +[networks.anvil] +url = "http://127.0.0.1:8545" +default_account_name = "anvil1" +save_to_db = true +``` + +We also want to create a file to write our withdrawal function: + +```python +from src import buy_me_a_coffee +from moccasin.config import get_active_network + +def withdraw(): + active_network = get_active_network() + coffee = active_network.manifest_named("buy_me_a_coffee") + print(f"On network {active_network.name}, withdrawing from {coffee.address}") + coffee.withdraw() + +def moccasin_main(): + return withdraw() +``` + +If we run this, the function will use the `get_active_network` to get the latest deployment, and it'll print the network and address of the contract we're withdrawing from. We can also add more details to this script using the `get_latest_contract_checked` option. + +```python +from src import buy_me_a_coffee +from moccasin.config import get_active_network + +def withdraw(): + active_network = get_active_network() + coffee = active_network.manifest_named("buy_me_a_coffee") + coffee = active_network.get_latest_contract_unchecked("buy_me_a_coffee") + print(f"On network {active_network.name}, withdrawing from {coffee.address}") + coffee.withdraw() + +def moccasin_main(): + return withdraw() +``` + +This allows us to specifically target a contract based on a name that we've given it. + +We can also see that this is creating a database file called `deployments.db`. + +Let's go back to the terminal and run the Anvil blockchain locally: + +```bash +anvil +``` + +Now we can deploy to the Anvil chain. + +```bash +mox run deploy --network anvil +``` + +If we open our `deployments.db` file, we can see that the database is storing information about our deployments. The database will store many different pieces of information such as: +- session ID +- contract address +- contract name +- RPC deployer +- TX hash +- TX broadcast +- receipt dict +- source code +- ABI + +If we scroll over the database, we can see the contract address that was just deployed for the contract named "buy_me_a_coffee". + +Now that we have this, let's go back to our `withdraw.py` file and create a new function where we interact specifically with that address. + +```python +from src import buy_me_a_coffee +from moccasin.config import get_active_network + +def withdraw(): + active_network = get_active_network() + coffee = active_network.manifest_named("buy_me_a_coffee") + coffee = active_network.get_latest_contract_unchecked("buy_me_a_coffee") + print(f"On network {active_network.name}, withdrawing from {coffee.address}") + coffee.withdraw() + +def moccasin_main(): + return withdraw() +``` + +It's best practice to use the `manifest_named` function when dealing with smart contracts because it ensures you are working with the specific contract you intended. + +Let's clear the terminal and run the `withdraw.py` file. + +```bash +mox run withdraw --network anvil +``` + +We can now see the transaction being broadcasted and the withdrawal function being executed. This is how we can have even more powerful scripting and keep track of our deployments. Mocassin keeps track of all of that for us, which is incredibly exciting. From a9ef93a7174e0e8a5b26c4f6764f5b0025acaa38 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:24:49 -0700 Subject: [PATCH 752/797] Equious updated courses/moccasin-101/6-mox-coffee/22-zksync-testing/+page.md. --- .../6-mox-coffee/22-zksync-testing/+page.md | 44 +++++++++++++++++-- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/22-zksync-testing/+page.md b/courses/moccasin-101/6-mox-coffee/22-zksync-testing/+page.md index 4f5922387..df4c98714 100644 --- a/courses/moccasin-101/6-mox-coffee/22-zksync-testing/+page.md +++ b/courses/moccasin-101/6-mox-coffee/22-zksync-testing/+page.md @@ -1,3 +1,41 @@ ---- - title: Zksync Testing - --- \ No newline at end of file +## zkSync Testing + +We have learned about using a mock network to test our code. This is useful because it allows us to test our code without having to deploy it to a live network. + +We can also test our code against zkSync if we have the zkSync prerequisites installed. + +First, we need to check the version of the zkSync node and zkVyper: + +```bash +era test node --version +``` + +```bash +zkVyper --version +``` + +Once we have those installed, we can run the following command to test our code against the zkSync network: + +```bash +mox test --network eravm +``` + +This will spin up a fake zkSync network, allowing us to test our code against zkSync without deploying it to a live network. + +To further test our code, we also need to ensure we are correctly handling the `not enough balance` error. We can fix this by adding some code to our tests. For example, in the `conftest.py` file, we can add a line of code to set the balance of an account to 10 times the `SEND_VALUE`: + +```python +boa.env.set_balance(account.address, SEND_VALUE * 10) +``` + +Then, in the `test_unit_coffee.py` file, we can add a line of code to set the balance of an account to 3 times the `SEND_VALUE`: + +```python +boa.env.set_balance(account.address, SEND_VALUE * 3) +``` + +Running our tests again, we can see that all our tests pass. We have now tested our code against the zkSync network and ensured that it handles the `not enough balance` error correctly. + +We can also see that our tests run on zkSync as they now display the expected information in the terminal. + +We are now confident that our code is working correctly on zkSync! From 1c082f1dead0b7f450d4c8b7dcd3c64374c818bf Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:25:19 -0700 Subject: [PATCH 753/797] Equious updated courses/moccasin-101/6-mox-coffee/23-github/+page.md. --- .../6-mox-coffee/23-github/+page.md | 31 +++++++++++++++++-- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/23-github/+page.md b/courses/moccasin-101/6-mox-coffee/23-github/+page.md index 759cfde0e..f20f647a0 100644 --- a/courses/moccasin-101/6-mox-coffee/23-github/+page.md +++ b/courses/moccasin-101/6-mox-coffee/23-github/+page.md @@ -1,3 +1,28 @@ ---- - title: Github - --- \ No newline at end of file +## Push to GitHub + +We have one thing left to do here, it's finally time for your GitHub repos, for your GitHub profiles to start to develop. And also your Cyfrn profiles as well. People always ask me, Patrick, how do I get hired? What do I do after I take your curriculum? And the answer is you do a lot of stuff, and you gotta show off all the cool stuff that you're doing. So pushing your projects to GitHub and then also signing up for Cyfrn profiles is going to be how you start showing off. + +So, I'm going to have a link to Cyfrn profiles, of course, in the GitHub repo associated with this course. But now we're going to do what I think is arguably one of the most important things for us to do in this entire course. And this is push our codebase up to GitHub. I've mentioned this a couple of times, but GitHub is how a lot of the entire blockchain industry works. For example, if I look up geth GitHub. That's, that's for the go implementation of Ethereum. It's got 20,000 forks. Almost 50,000 stars. 2000 people watching it. This is one of the most popular repositories in all of the EVM and the blockchain ecosystem. The go Ethereum is the code that runs one of the most popular ways to run an Ethereum node. If you were to look up Mocassin Cyfrn Mocassin, that we've shown you before. This is the GitHub repo of the tool we're working with. If we look up Vyper, we look up Vyper in here. Vyper lang/Vyper. 5000 stars. Almost 1000 forks. This is the language that we're learning in here. And if you go into issues, you can see countless issues. You can see countless pull requests. This is how developers interact with each other. This is how developers in the open source community contribute and work with each other. And, guess what I do sometimes? I might go to repo, I might go hmm, okay, who is working on this? Who are the cool people here? I might click someone's profile and go Whoa, this person is working on some really cool stuff. And especially, if you're a hiring manager, this is often how you're going to do a lot of your hiring is looking at people's profiles and saying what is this person about? What does this person do? What have they done? What have they shown success in? And the Cyfrn profiles, as well, they do the same thing, especially when it comes to competitive audits and security, which is something that you can get in much, much later after finishing the Updraft curriculum. And, the profiles are growing more and more with more and more interesting features coming out to show off to potential hiring managers. + +So, the first step, though, is for us to push our code up to GitHub and sign up for Cyfrn profiles. So, let's go ahead. Let's get started pushing up to GitHub. You have done a ton in this project, and this is the final step. This is a bad-ass project that you're going to push up. Now, the first thing that you should check finally is that in the .gitignore, the .env is in here. So way, way back when I was like, hey, the pledge, the .env pledge blah, blah, blah. If we go back to the GitHub repo associated with this course. Let's scroll way up to the top. Let's go to discussions here. The .env pledge. In here, we said, "I am aware". If I forget a .gitignore and push my key/phrase up to GitHub even for a split-second, or show my key/phrase to the internet for a split-second, it should be considered compromised and I should move all my funds immediately. If I am unsure if my account has real funds in it, I will assume it has real funds in it. I will assume it has real funds in it, I will not use it for developing purposes. I am aware that even if I hit add account on my Metamask (or other ETH wallet), I will get a new private key, but it will share the same secret phrase/mnemonic of the other accounts generated in that Metamask (or other ETH wallet). Pledge Additions. For this course, I will only use funds associated with a brand new never-before-used Metamask (or other ETH wallet). I am aware that my account associated with my private key is the same on testnets that it is on mainnets. If I must use a private key associated with real funds in the future, until I am 100% sure what I am doing, I will always either: 1. Encrypt the private key MYSELF in such a way as Patrick taught me. 2. Use the built-in functionality of Mocassin to encrypt my private keys. 3. Use the command line way to pass private keys, and delete my command line history right after ONLY AS A LAST OPTION. If I never actually deploy anything to mainnet myself or work with a private key with real funds, I do not need to be concerned. This .gitignore is a file that says hey, when we're pushing stuff up to GitHub ignore these files. So, we do not want to push these up to GitHub. If there's anything else sensitive that you don't want to push up to GitHub it's a good idea to put it in this file. We will, we will still be able to check what we're about to push up to GitHub before we push it up. That's how, that's why this line in the pledge is so important. And then, additionally down here, now this sentence makes sense, use the built-in functionality of Mocassin to encrypt my private keys. Now, you understand how that works. Now, you understand you never, ever, ever need to really deal with your private keys ever again. So, now this is the GitHub repo that I'm going to be deploying to and it's a newer GitHub repo because I wanted to show you what a blank GitHub repo looks like. It's got this sick neon sign as the avatar. So to get started here, we first need to make sure we have git installed. git --version per usual. This is one of the things we installed way, way, way at the beginning of this whole course. So, you should have git installed. If you don't have git installed there's a ton there are links in the GitHub repo associated with this course. As well as AIs are very helpful at this. Google is very helpful at this. There's a lot of places where you can install git. Now, GitHub is a centralized company and there are decentralized versions of GitHub being worked on but, as of today, GitHub is what we have. As of today, GitHub is still the dominant player to the point where we kind of have to use it. So with that being said, if we go to the GitHub docs, we should go to the get started. And, in here, it says get started with GitHub documentation. We'll go to the quickstart, as well. And, you should have already created an account on GitHub, right? So, you should already have an account here. So, you don't have to do that one. You don't have to set up your profile, downloading files. Now, we could follow along with this uploading a project to GitHub, but this is going to show you kind of the manual way to upload everything. And, that's cool, but like, I don't want to have to go onto a website every single time I want to upload my code. I want to work incredibly hard to be incredibly lazy. So, what I'm going to do instead is I am going to first come to repositories. I'm going to select new, and I am going to create a new repository, but I'm going to upload all the stuff from it from the command line. So, we're going to call this our Mox Buy Me a Coffee Cyfrn Updraft. And we are going to make sure this is public so other people can see how cool we are for finishing this project. We're going to go ahead and click Create repository. And, boom. Now, this is created. There are some notes down here. It says quick setup if you've done this kind of thing before or create a new repository on the command line. And, this will show you how to get set up here as well, but this assumes you're already signed in. We are not signed in. We want to do this the hardcore way, so we're going to look up load locally hosted files, adding locally hosted code to GitHub and this is what we're going to follow. And, since Windows users are using WSL you should be following the Mac or the Linux stuff here. I'm going to follow along with the Linux pieces. This link will be in the GitHub repo associated with this course. So, the first thing that we're going to need to do here is do git init. And, this will say Initialized an empty Git repository in. At this location, right? At your pwd wherever you're working with. You might even see some colors light up in your VS code as well. And, that's actually our first step in the docs as well. Initialize a Git repository. It says git init -b main. You can do that, as well. Or, just git init like what we did. Don't do this one. Then, what we want to do is we want to decide which one of these files we want to put into what's called version control or source control. You also might see something like this pop up. This tells us what branch we're on. You can learn about branches another day. But, we want to say which files we want to push up to GitHub. Which files do we want to share with the world? Now, if we do a little git status what we can see is a list of all the different potential files that we could push up to GitHub. All the different files that we've recently made changes on that we need to update. And, all these look pretty good. So, this is a coverage file for coverage, git attributes, gitignore. These all look fine. I don't see any I don't see the .env in here. This is great. If you want to test it. If you go into your .gitignore delete the line that says .env. Then run, you know clear, git status again. Now, in here, oh, looks like we still don't see it. Oh, it's cuz there's more .envs, there's a whole bunch of .envs. If we delete all the .envs and then we do git status we now see .env is in our list of untracked files. That's very bad. So, I'm going to undo all of that that we just did. I'm going to do git status again. And, now, it's no longer in there. Now, we can override the .gitignore, but having the .env and any sensitive stuff in the .gitignore is going to be helpful to not push it up to GitHub. So, this is the list of stuff that we're going to push up to GitHub. You might notice on the left hand side, if you're using VS code, depending on how your formatting is, some of these are green, and some of these are grayed out. So, Mocassin comes default with this .gitignore, and it automatically grays out a bunch of stuff, like build out, lib, DS store, etc. So, some of these are great out because you don't really need to push a lot of these to GitHub. You definitely don't need to push the deployments database. You don't need to push your .env, the era test node, the compiled out folder, lib, there's a bunch of stuff that's not really important that you share with the world. So, we don't push it up. So, once we have it initialized, we can choose which files we want to add by we can do git add uh SRC like this. Now, if we do git status. We see oh, everything in the SRC folder is in this other section called changes to be committed. And then down here is untracked files. So, this is like a staging ground for, it's like hey it's almost committed, it's almost pushed up to GitHub. These are the and these are the files that we've changed, but we haven't like we haven't staged them to be committed. So just stage everything, we can do git add . This period stands for everything in this current directory. Do clear, I do a git status again. Now, we see README.md is once again untracked, and these ones are staged. I want to add it back, so I'll just do get add . like this. Run another git status, and now I see once again, everything is in here. Now, to commit this to our local Git history, we do git commit -m which stands for message, and then some message like "our first commit!" little exclamation mark there. Enter. Oops, uh sorry, it's uh single quotes, not double quotes. Oh what a new mistake by me. Now, you'll see this create mode for all this stuff, and it's entering all these files into our git history. Now, if we do a little git log, we can actually see a log of all the commits that have ever been done and we can see we just have one, our first commit. Now, if I do git status it'll look like it's blank. There's nothing to commit. This has been committed to our locally running commit history. But, if we go back to GitHub, we do a little refresh on our repo here. It's still blank. Uh, what the heck? Patrick, your GitHub repos have like so much code. What's going on? Well, we we need to push our git changes to GitHub. So, this is, this git commit is only on our machine. We gotta push it over to GitHub. Then, we have to do what I think is arguably the hardest part. Importing a Git repository with the command line. After you've initialized a Git repository, you can push the repository to GitHub using either GitHub's CLI or git. You can download the GitHub application, as well, if that's going to make your life easier. You can 100% download the GitHub CLI and, to be honest, that'll probably make your life a little bit easier if you're struggling. But, I want to do it raw with the git command because it's going to allow you to use more than just GitHub as your remote provider. And if that doesn't make sense, don't worry, the more you do this, eventually that will make sense. So we're going to follow this adding a local repository to GitHub using git. It's important to note that GitHub and git are different, right? When I type git --version this is a tool for doing version control management, and git hub is a place to push code. It's like like a cloud provider or like a Google Drive for code if you will. So git is a tool. GitHub is a company, they are different. So, for us to do this we're going to need to create a new repository on GitHub. We've actually already done this. Well done, us. To avoid errors, do not initialize the new repository with README, license, or gitignore files. You can add these files after your project has been pushed to GitHub. For more information, see "Creating a new repository." At the top of your repository on GitHub's Quick Setup page, click the copy button to copy the remote repository URL. Okay? So that's going to be this button, right here. Okay, clicked it. And then what we're going to do is we're going to open our terminal and run a couple of commands here. So, we're going to run this command here. We're going to run git remote add origin. And then paste that in there. And, what this is going to do is it's going to when we type git remote -v, it's going to say whenever we push or pull code from a remote Git repository, it's This one that we just set up. It's the one that we're going to use. And then, finally you can just run get push -u origin, origin, main like this. And, I'm getting an error because I'm logged in as a different user. Oops. So to make my life easier, I'm just going to give access to Patrick. All right. So, I've gone and added my other account to this one. I'm just going to rerun that command and what's going to happen now, Now, if I do a little refresh here. Now I see all the code that we just created in here. Now, we have a terrible readme, and if you've been following along with the GitHub repo associated with this course, Of course, you know that in most of our readmes, you know, let's look at uh yeah, let's look at this one, for example. If you go to the code base associated with this one it has a really nice readme, where it says here's how you get started, here's how you can install, here's how you can work with all the code in this code base. But now, I will tell you right now there's a good chance that you'll run into an error here and working with AIs, AIs are phenomenal at triaging GitHub issues. So, if you run into an issue please work with an AI, be sure to Google around because getting this up here getting this project up here, like I said, is incredibly important for your career, because guess what, if you go build a bunch of amazing awesome, really cool projects, and really cool things, people want to see that. So, you kind of have to show it off. You have to have a place to show it off. + +```bash +git config --global user.name "Your Name" +``` + +```bash +git config --global user.email "youremail@example.com" +``` + +To verify your settings: + +```bash +git config --list +``` + +If you need to update credentials for authentication: + +- For HTTPS: Use a Personal Access Token (PAT) as your password when prompted. +- For SSH: You'll need to create and add an SSH key to your Git account. + +Would you like me to explain more about any of these methods? From de89b8fca509cad4a0aaad620f2dfec5244f8ad6 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:34:23 -0700 Subject: [PATCH 754/797] Equious updated courses/moccasin-101/6-mox-coffee/24-clone/+page.md. --- .../6-mox-coffee/24-clone/+page.md | 134 +++++++++++++++++- 1 file changed, 131 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/24-clone/+page.md b/courses/moccasin-101/6-mox-coffee/24-clone/+page.md index bdc0c631b..b6ed80f53 100644 --- a/courses/moccasin-101/6-mox-coffee/24-clone/+page.md +++ b/courses/moccasin-101/6-mox-coffee/24-clone/+page.md @@ -1,3 +1,131 @@ ---- - title: Clone - --- \ No newline at end of file +## Cloning a Repo + +We are going to learn how to clone a repo. + +On every GitHub repo we create, we usually include an "Installation" section. This section typically includes commands like: + +```bash +git clone +``` + +and + +```bash +cd +``` + +Let's see what this looks like. + +We will run a command in our terminal. + +Here we are in our `mox-cu` folder. + +We can run the following command: + +```bash +git clone https://github.com/cyfrin/mox-buy-me-a-coffee-cu cyfrin-buy-me-a-coffee-mox +``` + +This command will clone a repo, and we can name it something like `cyfrin-buy-me-a-coffee-mox`. + +The terminal will then output a list of files that have been cloned. + +We can then run the following command: + +```bash +cd cyfrin-buy-me-a-coffee-mox +``` + +to change into the folder we just created. + +We can then run the following command: + +```bash +code +``` + +to open VS Code. + +This gives us access to all of the code that is in the repo. + +We can see all of the files in our explorer pane. + +Now, let's go back to our terminal. We will run a few more commands here. + +```bash +cd +``` + +This changes us back to the parent folder. + +We can now change directories into the `mox-buy-me-a-coffee-cu` folder that we cloned from GitHub. + +```bash +cd mox-buy-me-a-coffee-cu +``` + +Another command we can run in the terminal is: + +```bash +git log +``` + +This command will display a log of all the commits to the repo. + +We can see the first commit made in the terminal. + +We can then make a small change in the README file. + +Let's add the following line: + +``` +Hello! This is a test. +``` + +We then save the file. + +Now, if we run the following command: + +```bash +git status +``` + +we can see that the README file has been changed. + +We can then run the following commands: + +```bash +git add . +``` + +```bash +git status +``` + +This will stage the file for commit. + +Next, we can commit the changes with the following command: + +```bash +git commit -m 'update!' +``` + +We can then push the changes to the GitHub repository. + +```bash +git push +``` + +Now, when we go back to our GitHub repo, we can see there are two commits: our first commit and the update commit. + +Sometimes, you might encounter errors when following these steps. We encourage you to work with your AI to help you solve these errors so that you can continue working with your GitHub repo. + +Let's also see what this looks like on the GitHub repo. + +If we go to the repo and refresh the page, we can see the two commits we made. + +If we click on the update commit, we can see the small change we made to the README file. + +A great way to engage with the developer community is by tweeting about your work on GitHub. + +You can do this by clicking on the "Tweet Me" button, which will then send a tweet about your project to your Twitter account. From d181a411a3293205873e4c0a041857a739386d35 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:36:14 -0700 Subject: [PATCH 755/797] Equious updated courses/moccasin-101/6-mox-coffee/25-workshop/+page.md. --- .../6-mox-coffee/25-workshop/+page.md | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/25-workshop/+page.md b/courses/moccasin-101/6-mox-coffee/25-workshop/+page.md index 789149836..e35133e52 100644 --- a/courses/moccasin-101/6-mox-coffee/25-workshop/+page.md +++ b/courses/moccasin-101/6-mox-coffee/25-workshop/+page.md @@ -1,3 +1,31 @@ ---- - title: Workshop - --- \ No newline at end of file +## Introduction to Testing in Solidity + +In this lesson, we will cover some best practices for testing your Solidity code, in this case, we will focus on our `buy_me_a_coffee` contract. + +We've already learned a lot, now we will get hands-on with our testing methods. We'll begin by writing enough tests to get our code to 100% coverage. + +Here is how we'll do it: + +1. Write enough tests to get your code to 100% code coverage for `buy_me_a_coffee.vy`. + + We'll be using our testing framework: + + ```bash + mox test --coverage + ``` + + We'll use this command to run our tests, which will output the coverage we have achieved. + +2. Sign up for [Cyfrn Profiles](https://profiles.cyfrn.io/). + + This is very important for building your web3 career. Cyfrn Profiles provides a platform for you to showcase your skills, find opportunities, and build a network of fellow developers. + +3. Push your code to GitHub + + By pushing your code to GitHub, you'll be able to share your progress with others, document your work, and track changes. + +4. Add a new commit to your GitHub repo + + Adding a commit helps to keep your project organized and track the changes you make. + +We encourage you to spend at most 25 minutes on this workshop, without the aid of AI. If you're unable to solve it, take a break, and then work with AI or look to the discussions for help. Good luck! From ec0c8f5e80a7bf0e064b9cbc9494421805546419 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:40:49 -0700 Subject: [PATCH 756/797] Equious updated courses/moccasin-101/6-mox-coffee/26-recap/+page.md. --- .../6-mox-coffee/26-recap/+page.md | 222 +++++++++++++++++- 1 file changed, 219 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/26-recap/+page.md b/courses/moccasin-101/6-mox-coffee/26-recap/+page.md index 385e6edfe..bb1221949 100644 --- a/courses/moccasin-101/6-mox-coffee/26-recap/+page.md +++ b/courses/moccasin-101/6-mox-coffee/26-recap/+page.md @@ -1,3 +1,219 @@ ---- - title: Recap - --- \ No newline at end of file +## Moccasin: A Smart Contract Development Course + +This course will walk you through building a foundational understanding of smart contract development. We will be using Moccasin, a free and open source development framework, to learn how to write, test, and deploy smart contracts. + +The course is designed to be interactive, with quizzes, code samples, and workshops to help you learn. We'll go through a real-world example: a "Buy Me a Coffee" smart contract, to help solidify the concepts learned. + +**This section will be covering:** + +* Formatting code +* Using Constants and Immutables +* Understanding storage vs constants vs immutables +* Writing unit tests +* Using mocks to test our contracts +* Using mox's manifest named +* Keeping track of deployments in a database +* Running fork tests + +### Formatting Code + +We will start by learning how to format our codebase in a more readable and maintainable way. We will split our codebase into separate files. + +For our example, we'll have three files: + +* buy_me_a_coffee.vy +* get_price_module.vy +* AggregatorV3Interface.vyi + +#### buy_me_a_coffee.vy + +```python +#pragma version 0.4.0 + +@license MIT +@title Buy Me A Coffee! +@author You! + +#notice This contract is for creating a sample funding contract +#....... + +from interfaces import AggregatorV3Interface +import get_price_module + +# Constants & Immutables +MINIMUM_USD: public(constant(uint256)) = wei_value(5, "ether") +PRICE_FEED: public(immutable(AggregatorV3Interface)) = 0x694AA1769357215DE4FAC081b1f +OWNER: public(immutable(address)) = + +# Storage +funders: public(DynArray(address, 1000)) +funder_to_amount_funded: public(HashMap(address, uint256)) + +# With constants: 262,853 +@deploy +def __init__(price_feed: AggregatorV3Interface, address: address): + self.price_feed = price_feed + self.address = address +``` + +#### get_price_module.vy + +```python +from interfaces import AggregatorV3Interface + +PRECISION: constant(uint256) = 1 * (10 ** 18) + +@internal +@view +def get_eth_to_usd_rate(price_feed: AggregatorV3Interface, eth_amount: uint256) -> uint256: + # Chris sent us 0.01 ETH for us to buy a coffee + # Is that more or less than $5? + + price: int256 = staticcall(price_feed.latestAnswer()) + eth_price: uint256 = convert(price, uint256) * (10 ** 10) / (10 ** 18) + eth_amount_in_usd: uint256 = (eth_price * eth_amount) // (10 ** 18) + + return eth_amount_in_usd # 18 '0's, decimal places +``` + +#### AggregatorV3Interface.vyi + +```python +@external +@view +def decimals() -> uint8: + #....... + +@external +@view +def description() -> String[100]: + #....... + +@external +@view +def version() -> uint256: + #....... + +@external +@view +def latestAnswer() -> int256: + #....... +``` + +### Understanding Constants and Immutables + +We'll then go over the concepts of constants and immutables, key elements in smart contract development. + +**Constants:** +* Values defined during contract deployment. +* Cannot be changed once deployed. +* Their values are inlined at compile time. + +**Immutables:** +* Values defined during contract deployment, like constants. +* Their values are stored in a specific location in storage, not inlined. +* Can be read by anyone. + +### Testing Smart Contracts + +We will then learn how to test our smart contracts using the Python testing framework PyTest. + +**Types of Tests:** + +* Unit Tests: Test a single function or part of your code. +* Integration Tests: Test how different parts of your code work together. +* Fork Tests (Staging): Test your code in a production-like environment, but with a forked version of the blockchain. + +We will be primarily writing unit tests in this section. To run our tests, we will use the following terminal command: + +```bash +mox test +``` + +This will run all of our unit tests. We can also run a specific test file: + +```bash +mox test tests/unit/test_unit_coffee.py +``` + +#### Writing Unit Tests + +We will write unit tests to verify the following: + +* The `PRICE_FEED` is correctly set. +* The initial values of `MINIMUM_USD` and `OWNER` are correct. +* The `fund` function fails if the sender doesn't provide enough ETH. +* The `fund` function correctly sets the `funders` array and `funder_to_amount_funded` mapping. +* The `withdraw` function can only be called by the `OWNER`. +* The `withdraw` function correctly updates the balance of the contract and the `OWNER`. + +**test_unit_coffee.py** + +```python +from eth_utils import to_wei +import boa +from tests.conftest import SEND_VALUE + +RANDOM_USER = boa.env.generate_address("non-owner") + +def test_price_feed_is_correct(coffee, eth_usd): + assert coffee.PRICE_FEED() == eth_usd.address + +def test_starting_values(coffee, account): + assert coffee.MINIMUM_USD() == to_wei(5, "ether") + assert coffee.OWNER() == account.address + +def test_fund_fails_without_enough_eth(coffee): + with boa.reverts("You must spend more ETH!"): + coffee.fund() + +def test_fund_with_money(coffee, account): + # Arrange + boa.env.set_balance(account.address, SEND_VALUE * 3) + + # Act + coffee.fund(value=SEND_VALUE) + + # Asset + funder = coffee.funders(8) + assert funder == account.address + assert coffee.funder_to_amount_funded(funder) == SEND_VALUE + +def test_non_owner_cannot_withdraw(coffee_funded, account): + with boa.env.prank(RANDOM_USER): + with boa.reverts("Not the contract owner!"): + coffee_funded.withdraw() + +def test_owner_can_withdraw(coffee_funded): + with boa.env.prank(coffee_funded.OWNER()): + coffee_funded.withdraw() + + assert boa.env.get_balance(coffee_funded.address) == 0 + +def test_get_rate(coffee): + assert coffee.get_eth_to_usd_rate(SEND_VALUE) > 0 +``` + +### Fork Tests + +Fork tests allow us to test our smart contracts in a production-like environment, but without sending any real money. This is useful for testing complex scenarios or for verifying that our contracts work as expected. + +To run a fork test, we use the following terminal command: + +```bash +mox test --network sepolia --fork +``` + +This will run our tests on a forked version of the Sepolia testnet. + +### Working with the Database + +Moccasin provides a database where we can store information about our deployments. This database is used to keep track of the addresses of our contracts, the RPCs used to deploy them, and the transactions that were sent. + +### Wrapping Up + +Congratulations on completing this section! You have learned how to format code, understand constants and immutables, write unit tests, and run fork tests. You've also learned how to use mox's manifest named and how to use a database to keep track of your deployments. + +Now is a great time to take a break, go for a walk, or lift some iron at the gym! You have earned it! We've covered a lot in this section, so make sure to review the material and reach out if you have any questions. + +Get ready for the next section, where we will learn about deploying our smart contracts to the Ethereum blockchain! From 0d898fde5de6b2db8d1557ac909f86cdd073d90c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:43:48 -0700 Subject: [PATCH 757/797] Equious updated courses/moccasin-101/6-mox-coffee/3-refactor/+page.md. --- .../6-mox-coffee/3-refactor/+page.md | 337 +++++++++++++++++- 1 file changed, 334 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/3-refactor/+page.md b/courses/moccasin-101/6-mox-coffee/3-refactor/+page.md index fc4ec237d..5646ad853 100644 --- a/courses/moccasin-101/6-mox-coffee/3-refactor/+page.md +++ b/courses/moccasin-101/6-mox-coffee/3-refactor/+page.md @@ -1,3 +1,334 @@ ---- - title: Refactor - --- \ No newline at end of file +## Refactoring + +We've learned a couple of things since we originally wrote this code. We first learned about interfaces and how they can actually be in their own file. So, to make this code a little bit nicer, we're going to go ahead create a new folder called "interfaces". And we're going to create an interface called AggregatorV3interface. + +```python +interface AggregatorV3Interface: + def decimals() -> uint8: view + def description() -> String[1000]: view + def version() -> uint256: view + def latestAnswer() -> int256: view +``` + +Now, the reason I'm using camel case here instead of snake case, right? I'm having these capital letters and no underscores, is because this is the name of the interface in its Solidity edition, and I'm looking to keep the same name of the interface to match what Chainlink Labs wrote for the Solidity edition of this. + +But if this is confusing, you can obviously do that, I underscore, or the I methodology that we did previously. What we can't do is we can't just copy-paste this in here. We have to actually convert it to its interface edition. But, oh, man, that's quite annoying, uh, that's quite a lot of work, and I am incredibly lazy. + +So let's see what our friend ChatGPT has to say. Let's give this a little prompt. I'll say, here is my inline Vyper interface: + +```python +interface AggregatorV3Interface: + def decimals() -> uint8: view + def description() -> String[1000]: view + def version() -> uint256: view + def latestAnswer() -> int256: view +``` + +Can you convert it to a Vyper file interface? Here is an example. + +```python +@external +@view +def retrieve() -> uint256: + ... +``` + +You actually already know how to convert this from its edition here to its file edition, right? You you know how to do that transition. You could 100% do it manually yourself, if you want to, too. But, it's just kind of busy work, right? We're not, it's not super important, so it'd be great if AI could just do it. + +So we're going to say, hey here is my inline Vyper interface: + +```python +interface AggregatorV3Interface: + def decimals() -> uint8: view + def description() -> String[1000]: view + def version() -> uint256: view + def latestAnswer() -> int256: view +``` + +Can you convert it to a Vyper file interface? Here is an example: + +```python +@external +def store(favorites_number: uint256): + ... +@external +@view +def retrieve() -> uint256: + ... +``` + +Let's see what ChatGPT gives us. To convert your inline Vyper interface into a standard Vyper file interface, you need to define the functions with the appropriate decorators for visibility (@external, @view) and specify the function signatures clearly. Here's how you can structure the AggregatorV3Interface in a Vyper file: + +```python +# AggregatorV3Interface.vy +interface AggregatorV3Interface: + @view + @constant + def decimals() -> uint8: + ... + @view + @constant + def description() -> String[1000]: + ... + @view + @constant + def version() -> uint256: + ... + @view + @constant + def latestAnswer() -> int256: + ... +``` + +Okay. Clearly it's a little bit less up-to-date. + +Oh, ChatGPT, though, is a little confused. It's come up with a new fake decorator called "constant" and it did this at the top for some reason. + +Okay. Well, uh, I guess this one's closer. Let's let's use this one. + +Okay, so maybe, uh AI didn't do such a great job here. But, that's okay. We're going to copy this, we're going to grab this um, and we're just going to do a find and replace. + +So, I did, I gr I got this find and replace by doing command F or control F, depending on if you're Mac or Windows or Linux. And I'm going to say "pass", and we're just going to replace everything with three dots. Hit enter, save it. And that looks pretty good to me. + +```python +@external +@view +def description() -> String[1000]: + ... +``` + +Decimals, description, version, latest answer. + +Decimals, description, latest version, answer, version, latest answer. + +Okay. That looks pretty good to me. Okay, great. So let's go ahead delete this now. And now we can do, from interfaces import I'll hit tab here. + +```python +from interfaces import AggregatorV3Interface +``` + +Yeah, I got this one, right? AggregatorV3Interface. + +And, let's just make sure this works. We'll do a little "mox compile". + +```bash +patrick@cu mox-buy-me-a-coffee-cu % mox compile +``` + +Nice. Okay, so that works. + +Thanks AI. Now, let's actually get a little bit more practice working with these modules. Let's take out, let's look at this eth to USD rate. Let's take this out as an internal function. + +```python +@external +@view +def get_eth_to_usd_rate(eth_amount: uint256) -> uint256: + ... + return self._get_eth_to_usd_rate(eth_amount) +``` + +And let's turn this into a module. So, let's get some practice working with this. So, I'm actually going to delete this from the buy me a coffee. Going to go back to the SRC, new file. + +We're going to do, get price module.vy. And we're going to paste this in here: + +```python +@internal +@view +def _get_eth_to_usd_rate(eth_amount: uint256) -> uint256: + """ + Chris sent us 0.01 ETH for us to buy a coffee + Is that more or less than $5? + """ + + price: int256 = staticcall PRICE_FEED.latestAnswer() + eth_price: uint256 = (convert(price, price * uint256)) * (10 ** 18) + eth_amount_in_usd: uint256 = (eth_price * eth_amount) // PRECISION + return eth_amount_in_usd # $ 8.0's, 18 decimal places +``` + +What are the variables we need? We need a price feed in here. So, let's actually just pass it in as a variable. The price feed is of type AggregatorV3Interface. So we need that, so we'll do from interfaces import AggregatorV3Interface like this. + +```python +from interfaces import AggregatorV3Interface +``` + +We'll pass this in as a variable. We'll say, price feed of type AggregatorV3Interface. + +```python +@internal +@view +def _get_eth_to_usd_rate(price_feed: AggregatorV3Interface, eth_amount: uint256) -> uint256: + """ + Chris sent us 0.01 ETH for us to buy a coffee + Is that more or less than $5? + """ + + price: int256 = staticcall price_feed.latestAnswer() + eth_price: uint256 = (convert(price, price * uint256)) * (10 ** 18) + eth_amount_in_usd: uint256 = (eth_price * eth_amount) // PRECISION + return eth_amount_in_usd # $ 8.0's, 18 decimal places +``` + +And then we'll do staticcall price feed.latest answer. + +```python +@internal +@view +def _get_eth_to_usd_rate(price_feed: AggregatorV3Interface, eth_amount: uint256) -> uint256: + """ + Chris sent us 0.01 ETH for us to buy a coffee + Is that more or less than $5? + """ + + price: int256 = staticcall price_feed.latestAnswer() + eth_price: uint256 = (convert(price, price * uint256)) * (10 ** 18) + eth_amount_in_usd: uint256 = (eth_price * eth_amount) // PRECISION + return eth_amount_in_usd # $ 8.0's, 18 decimal places +``` + +Buy me a coffee. We also have this precision variable. Let me look for this in any other place. It looks like this is the only line. It looks like it was only used in the function, so we're going to take that out. + +```python +PRECISION: constant(uint256) = 1 * (10 ** 18) +``` + +We're going to paste that in here as well. + +```python +PRECISION: constant(uint256) = 1 * (10 ** 18) +``` + +And this is looking pretty good. Now, what we can do back in here is, we can import this now. We can say, from, or excuse me, we can just say import get price module. + +```python +from interfaces import AggregatorV3Interface +import get_price_module +``` + +Right? Because these are in the same folder. Right. So we're just going to say go ahead, just import get price module. + +```python +from interfaces import AggregatorV3Interface +import get_price_module +``` + +And then down here, we're going to have this error because we're saying self.get eth, but instead, we want to do get price module.get eth to USD rate. + +```python +@external +@view +def get_eth_to_usd_rate(eth_amount: uint256) -> uint256: + ... + return get_price_module.get_eth_to_usd_rate(PRICE_FEED, eth_amount) +``` + +Now we know that this function also takes two parameters now. So we're also going to want to pass in the price feed, like this. + +```python +@external +@view +def get_eth_to_usd_rate(price_feed: AggregatorV3Interface, eth_amount: uint256) -> uint256: + ... + return get_price_module.get_eth_to_usd_rate(PRICE_FEED, eth_amount) +``` + +And, oh, we're going to want to do the same thing up here. Price feed, pass it in. + +```python +@internal +@view +def _get_eth_to_usd_rate(eth_amount: uint256) -> uint256: + """ + How do we convert the ETH amount to dollars amount? + """ + + usd_value_of_eth: uint256 = get_price_module.get_eth_to_usd_rate(PRICE_FEED, msg.value) + assert usd_value_of_eth >= MINIMUM_USD, "You must spend more ETH!" + self.funders.append(msg.sender) + self.funder_to_amount_funded[msg.sender] = msg.value + +``` + +And now we're looking pretty good here. So let's do a little mox compile. + +```bash +patrick@cu mox-buy-me-a-coffee-cu % mox compile +``` + +And it compiles successfully. + +Awesome. + +**Code Block** + +```python +@external +@payable +def fund(): + """ + Allows users to send $ to this contract + Have a minimum amount to send + """ + _get_eth_to_usd_rate(msg.value) + +``` + +**Code Block** + +```python +from interfaces import AggregatorV3Interface +import get_price_module + +PRECISION: constant(uint256) = 1 * (10 ** 18) + +@external +@view +def get_eth_to_usd_rate(eth_amount: uint256) -> uint256: + """ + Chris sent us 0.01 ETH for us to buy a coffee + Is that more or less than $5? + """ + + price: int256 = staticcall PRICE_FEED.latestAnswer() + eth_price: uint256 = (convert(price, price * uint256)) * (10 ** 18) + eth_amount_in_usd: uint256 = (eth_price * eth_amount) // PRECISION + return eth_amount_in_usd # $ 8.0's, 18 decimal places + +``` + +**Code Block** + +```python +@internal +@view +def _get_eth_to_usd_rate(eth_amount: uint256) -> uint256: + """ + How do we convert the ETH amount to dollars amount? + """ + + usd_value_of_eth: uint256 = get_price_module.get_eth_to_usd_rate(PRICE_FEED, msg.value) + assert usd_value_of_eth >= MINIMUM_USD, "You must spend more ETH!" + self.funders.append(msg.sender) + self.funder_to_amount_funded[msg.sender] = msg.value + +``` + +**Code Block** + +```python +@external +@payable +def fund(): + """ + Allows users to send $ to this contract + Have a minimum amount to send + """ + _get_eth_to_usd_rate(msg.value) + +``` + +**Code Block** + +```bash +patrick@cu mox-buy-me-a-coffee-cu % mox compile +``` From 5d15d23ec0e31c9ac6af73f898e0f03a405f28c2 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:44:43 -0700 Subject: [PATCH 758/797] Equious updated courses/moccasin-101/6-mox-coffee/4-storage/+page.md. --- .../6-mox-coffee/4-storage/+page.md | 132 +++++++++++++++++- 1 file changed, 129 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/4-storage/+page.md b/courses/moccasin-101/6-mox-coffee/4-storage/+page.md index 841e6f34e..47ba4ea62 100644 --- a/courses/moccasin-101/6-mox-coffee/4-storage/+page.md +++ b/courses/moccasin-101/6-mox-coffee/4-storage/+page.md @@ -1,3 +1,129 @@ ---- - title: Storage - --- \ No newline at end of file +## Storage in Smart Contracts + +In our last lesson, we learned about state variables, which are variables that exist on the blockchain and can be accessed by other smart contracts. These variables are stored in a location called _storage_, but we didn't go into detail about how storage works. + +We'll be doing that in this lesson. In this lesson, we'll learn the differences between _constants_, _immutables_, and _storage_. We'll also cover how variables are stored in the EVM and look at a script that allows us to read storage directly. + +### Storage Layout + +The EVM has a giant list of storage locations where we can store variables. This is how we can update values and retrieve them later. + +Let's start by looking at a minimal smart contract that has one state variable. + +```python +favorite_number: uint256; +``` + +This variable is of type _uint256_. When this contract is deployed, the EVM needs to store the value of this variable. + +Our contract will also have a state variable of type _bool_. + +```python +some_bool: bool; +``` + +The EVM handles booleans by representing them as a hex value. A _true_ boolean will have a hex value of 0x00000001, while a _false_ boolean will have a hex value of 0x00000000. + +The EVM assigns storage slots to variables in order. + +- If we have a variable called _favorite_number_, it's going to be stored in slot zero. +- _some_bool_, being the second variable, will be stored in slot one. + +### Fixed-Sized Arrays + +Let's say we have an array of 1000 slots. + +```python +my_fixed_array: uint256[1000]; +``` + +Fixed-sized arrays take up all the storage slots associated with their size. The EVM will start with slot two for the array and allocate a slot for each element. + +### Dynamic Arrays + +Dynamic arrays differ from fixed-sized arrays by having a special "holder" slot to keep track of the array's length. + +```python +my_dyn_array: DynArray(uint256, 100] +``` + +- This dynamic array can hold up to 100 elements. +- The array starts at slot 1002. +- The length is stored at slot 1003. + +### Mappings + +Mappings use a hashing function to determine the storage location for elements. + +```python +my_map: HashMap[(uint256, bool)]; +``` + +- The mapping will have a blank placeholder slot. +- Each element is stored at a slot based on its key. + +### Constants and Immutables + +Constants and immutables are not stored in storage. They are part of the contract's bytecode. + +```python +NOT_IN_STORAGE: constant(uint256) = 123 +IMMUTABLE_NOT_IN_STORAGE: immutable(uint256) +``` + +This is why we don't need to initialize them like the other state variables. + +### Accessing Storage with a Script + +We can use a script to read values directly from storage. Let's have a look at the storage script from the course repository. + +```python +from src.example_contracts import fun_with_storage +from moccasin.config import get_active_network +import boa + +def deploy_storage(): + fws = fun_with_storage.deploy() + active_network = get_active_network() + if active_network.has_explorer(): + print("Verifying contract on explorer...") + result = active_network.moccasin.verify(fws) + result.wait_for_verification() + print(f"favorite_number is {fws.storage.favorite_number.get()}") + print(f"Immutables: {fws.immutables.IMMUTABLE_NOT_IN_STORAGE}") + print("You can call directly from storage slots!") + print(f"Value at storage slot 0: {boa.env.get_storage(fws.address, 0)}") + print(f"First element of the fixed array: {boa.env.get_storage(fws.address, 2)}") + print(f"Length of the dyn array: {boa.env.get_storage(fws.address, 1002)}") + print(f"First element in dyn array: {boa.env.get_storage(fws.address, 1003)}") + print("Mapping placeholder") + print(f"First element of the mapping: {boa.env.get_storage(fws.address, 1103)}") + slot = 1103 + k = 0 + location = boa.eval(f"convert(keccak256(concat(convert({slot}, bytes32), convert({k}, bytes32))), uint256)") + print(f"Storage of element: {boa.env.get_storage(fws.address, location)}") + +def moccasin_main(): + deploy_storage() +``` + +We can run this script to see the values stored in storage. For example: + +```bash +mox run storage.py +``` + +You can see that we can read the values stored in different slots using `boa.env.get_storage()`. + +We can use `mox inspect` to see the storage layout. This is a useful tool that can be used to debug and understand how storage is being used. + +```bash +mox inspect fun_with_storage storage-layout +``` + +This command will output a dictionary with the following information for each variable: + +- _slot:_ The storage slot where the variable is stored +- _type:_ The type of the variable + +We hope this lesson has helped you understand how storage works in Solidity smart contracts. As we progress through the course, we'll be exploring more about storage and how to use it effectively. From 1059ac0a97aea9e1056dd0559cd538bf8ccf2aba Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:52:57 -0700 Subject: [PATCH 759/797] Equious updated courses/moccasin-101/6-mox-coffee/5-refactor-2/+page.md. --- .../6-mox-coffee/5-refactor-2/+page.md | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/5-refactor-2/+page.md b/courses/moccasin-101/6-mox-coffee/5-refactor-2/+page.md index b558ca50c..f113c60d3 100644 --- a/courses/moccasin-101/6-mox-coffee/5-refactor-2/+page.md +++ b/courses/moccasin-101/6-mox-coffee/5-refactor-2/+page.md @@ -1,3 +1,21 @@ ---- - title: Refactor 2 - --- \ No newline at end of file +We now have a decent understanding of storage. We also understand why we don't need to initialize the `get_price_module`. All we want from this module is the `get_eth_to_usd_rate` function. We also get this `PRECISION` variable, but we get it by default because this is a constant variable and it's going to be embedded directly into the bytecode of this contract. We don't have to initialize storage at all. + +So with that, that's pretty much all the refactoring we're going to do. Now, I'm going to show you later how we can do a little bit of gas profiling to see how much more expensive this would be if these were storage variables instead of constants and immutables. But for the most part, this is looking pretty good. + +```python +from interfaces import AggregatorV3Interface +import get_price_module + +PRECISION = constant(int256(1 * (10 ** 18))) + +@internal +def get_eth_to_usd_rate(price_feed: AggregatorV3Interface, eth_amount: uint256) -> uint256: + """ + Chris sent us 0.01 ETH for us to buy a coffee + Is that more or less than $5? + """ + price: int256 = staticcall(price_feed.latestAnswer(), []) + eth_price: uint256 = convert(price, int256) + (10**18) + eth_amount_in_usd: uint256 = (eth_price * eth_amount) // PRECISION + return eth_amount_in_usd # $ 3 & 0's decimal places +``` From c0291dd7e89114cbb59ff19b77d0648bc2d2328a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:53:24 -0700 Subject: [PATCH 760/797] Equious updated courses/moccasin-101/6-mox-coffee/6-script/+page.md. --- .../6-mox-coffee/6-script/+page.md | 93 ++++++++++++++++++- 1 file changed, 90 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/6-script/+page.md b/courses/moccasin-101/6-mox-coffee/6-script/+page.md index dfe2f7e16..2e859f839 100644 --- a/courses/moccasin-101/6-mox-coffee/6-script/+page.md +++ b/courses/moccasin-101/6-mox-coffee/6-script/+page.md @@ -1,3 +1,90 @@ ---- - title: Script - --- \ No newline at end of file +## Deploying our Smart Contract + +We have now written our smart contract code. Now, we need to give it some scaffolding. We will write some scripts so that we can deploy this and some tests so that we can make sure our code is working correctly. + +First, we will write our deploy script. + +**Code:** + +```python +def moccasin_main(): + deploy_coffee() + +``` + +To ensure that everything is working, we will run our deploy script. First, we will run this command in the terminal. +```bash +& mox run deploy +``` + +Now, we need to figure out what our script needs to deploy the contract. In this example, we are working with a contract called `buy_me_a_coffee`. + +First, we need to figure out which network we are working with. We can import the `get_active_network` function from the `mocassin.config` module. +**Code:** +```python +from moccasin.config import get_active_network + +def deploy_coffee(): + print("Hi from deploy") + +def moccasin_main(): + active_network = get_active_network() + deploy_coffee() +``` + +We can use the `get_active_network` function to get information about our network. + +**Code:** +```python +from moccasin.config import get_active_network +from src import buy_me_a_coffee + +def deploy_coffee(price_feed: str): + buy_me_a_coffee.deploy(price_feed) + +def moccasin_main(): + active_network = get_active_network() + deploy_coffee() + +``` + +Next, we need to get our price feed. In our case, the price feed needs to change based on the network. We will use conditional statements to decide which address to use. + +**Code:** + +```python +from moccasin.config import get_active_network +from src import buy_me_a_coffee + +def deploy_coffee(price_feed: str): + buy_me_a_coffee.deploy(price_feed) + +def moccasin_main(): + active_network = get_active_network() + price_feed = "" + if active_network.name == "sepolia": + price_feed = "0x69444A1769357215DE4FAC081bf1f1309aDc325306" + # if active_network.name == "mainnet": + # price_feed = "" + deploy_coffee(price_feed) + +``` + +In the code above, we have set up the `price_feed` address based on the network. This is the code we would have to write for every network. We could also just set it up like this: +**Code:** + +```python +from moccasin.config import get_active_network +from src import buy_me_a_coffee + +def deploy_coffee(price_feed: str): + buy_me_a_coffee.deploy(price_feed) + +def moccasin_main(): + active_network = get_active_network() + price_feed = "" + if active_network.name == "sepolia": + price_feed = "0x69444A1769357215DE4FAC081bf1f1309aDc325306" + deploy_coffee(price_feed) +``` +This is a pretty inefficient way to manage the price feed address. This is where we will learn about forking and other techniques for testing our code. From 161005a063eccdba1e50ca856c13445af5f87e8a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:54:49 -0700 Subject: [PATCH 761/797] Equious updated courses/moccasin-101/6-mox-coffee/7-mocks/+page.md. --- .../6-mox-coffee/7-mocks/+page.md | 205 +++++++++++++++++- 1 file changed, 202 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/7-mocks/+page.md b/courses/moccasin-101/6-mox-coffee/7-mocks/+page.md index 672e8594e..e6347fb19 100644 --- a/courses/moccasin-101/6-mox-coffee/7-mocks/+page.md +++ b/courses/moccasin-101/6-mox-coffee/7-mocks/+page.md @@ -1,3 +1,202 @@ ---- - title: Mocks - --- \ No newline at end of file +## Mock Contracts + +To test our smart contracts, we are going to deploy mock versions of them to our own local PyEVM network. + +First, we need to make a script to deploy our own fake price feed contract. To deploy our own fake price feed contract, we will need to grab the code from the Chainlink GitHub repo. + +We can find the code in the `src/mocks/mock_v3_aggregator.vy` file. + +We will copy and paste the code into our project, and will need to convert it from Solidity to Vyper. + +We have a minimal Chainlink price feed contract here in Vyper. We are going to use this for mocking, not for actually deploying price feeds. + +We have created a new script called `deploy_mocks.py`. This script will deploy our mock price feed contract. + +```python +from src.mocks import mock_v3_aggregator +from moccasin.boa.tools import VyperContract + +STARTING_DECIMALS = 8 +STARTING_PRICE = int(2000e8) + +def deploy_feed() -> VyperContract: + return mock_v3_aggregator.deploy(STARTING_DECIMALS, STARTING_PRICE) + +def moccasin_main(): + active_network = get_active_network() + price_feed: VyperContract = deploy_feed() + coffee = buy_me_a_coffee.deploy(price_feed.address) + print(f"Coffee deployed at: {coffee.address}") + print(coffee.get_eth_to_usd_rate(1000)) + +``` + +We also have a `deploy.py` script to run these contracts. + +```python +from moccasin.config import get_active_network +from script.deploy_mocks import deploy_feed +from moccasin.boa.tools import VyperContract +from src import buy_me_a_coffee + +def deploy_coffee(price_feed: str): + buy_me_a_coffee.deploy(price_feed) + +def moccasin_main(): + active_network = get_active_network() + price_feed: VyperContract = deploy_feed() + coffee = buy_me_a_coffee.deploy(price_feed.address) + print(f"Coffee deployed at: {coffee.address}") + coffee.get_eth_to_usd_rate(1000) + +``` + +This method of mocking is common in testing. We might need to rewrite a contract to make it easier to work with. + +**Code Block for `mock_v3_aggregator.vy`:** + +```python +# pragma version 0.4.0 +#license MIT + +DECIMALS: immutable(uint8) + +latestAnswer: public(int256) +latestTimestamp: public(uint256) +latestRound: public(uint256) + +getAnswer: public(HashMap[uint256, int256]) +getTimestamp: public(HashMap[uint256, uint256]) +getStartedAt: public(HashMap[uint256, uint256]) + +supply: uint256 +decimals: uint256 +version: public(constant(uint256)) = 4 + +@deploy +def __init__(decimals: uint8, initialAnswer: int256): + DECIMALS = decimals + self.updateAnswer(initialAnswer) + print(f"HELLO FROM MOCK AGGREGATOR") + +@internal +def updateAnswer(answer: int256): + self.latestAnswer = answer + self.latestTimestamp = block.timestamp + self.latestRound = self.latestRound + 1 + self.getAnswer[self.latestRound] = answer + self.getTimestamp[self.latestRound] = block.timestamp + self.getStartedAt[self.latestRound] = block.timestamp + +@external +def updateRoundData( + _roundId: uint256, answer: int256, timestamp: uint256, startedAt: uint256 +): + self.latestRound = _roundId + self.latestAnswer = answer + self.latestTimestamp = timestamp + self.getAnswer[self.latestRound] = answer + self.getTimestamp[self.latestRound] = timestamp + self.getStartedAt[self.latestRound] = startedAt + +@external +@view +def getRoundData(roundId: uint256) -> (uint256, int256, uint256, uint256, uint256): + return ( + roundId, + self.getAnswer[roundId], + self.getStartedAt[roundId], + self.getTimestamp[roundId], + roundId, + ) + +@external +@view +def latestRoundData() -> (uint256, int256, uint256, uint256, uint256): + return ( + self.latestRound, + self.getAnswer[self.latestRound], + self.getStartedAt[self.latestRound], + self.getTimestamp[self.latestRound], + self.latestRound, + ) + +``` + +**Terminal Command to run the script** + +```bash +mox run deploy +``` + +**Code block for `buy_me_a_coffee.vy`** + +```python +# Storage +funders: public(DynArray[address, 1000]) +funder_to_amount_funded: public(HashMap[address, uint256]) + +# With constants: 262,853 +@deploy +def __init__(price_feed: address): + PRICE_FEED = AggregatorV3Interface(price_feed) + OWNER = msg.sender + +@external +@payable +def fund(): + self._fund() + +@internal +@payable +def _fund(): + """ Allows users to send $ to this contract + Have a minimum $ amount to send + How do we convert the ETH amount to dollars amount? + ... + """ + usd_value_of_eth: uint256 = get_price_module.get_eth_to_usd_rate(PRICE_FEED, msg.value) + assert usd_value_of_eth >= MINIMUM_USD, "You must spend more ETH!" + self.funders.append(msg.sender) + self.funder_to_amount_funded[msg.sender] += msg.value + +@external +def withdraw(): + """Take the money out of the contract, that people sent via the fund function. + How do we make sure only we can pull the money out? + ... + """ + assert msg.sender == OWNER, "Not the contract owner!" + raw_call(OWNER, b"", value=self.balance) + +@external +@view +def get_eth_to_usd_rate(eth_amount: uint256) -> uint256: + return get_price_module.get_eth_to_usd_rate(PRICE_FEED, eth_amount) + +@external +@payable +def default(): + self._fund() +``` + +**Code Block for `get_price_module.vy`:** + +```python +from interfaces import AggregatorV3Interface + +PRECISION: constant(uint256) = 1 * (10 ** 18) + +@internal +@view +def _get_eth_to_usd_rate(price_feed: AggregatorV3Interface, eth_amount: uint256) -> uint256: + """Chris sent us 0.01 ETH for us to buy a coffee + Is that more or less than $5? + ... + """ + price: int256 = staticcall(price_feed.latestAnswer()) + eth_price_in_usd: uint256 = convert(price, uint256) * (10 ** 10) // (10 ** 18) + eth_amount_in_usd: uint256 = (eth_price * eth_amount) // PRECISION + return eth_amount_in_usd # 18 '0's, 18 decimal places + +``` From 4adffc00c7dc29095fcc10bd7bc241d41d221cb8 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:55:33 -0700 Subject: [PATCH 762/797] Equious updated courses/moccasin-101/6-mox-coffee/8-manifest/+page.md. --- .../6-mox-coffee/8-manifest/+page.md | 100 +++++++++++++++++- 1 file changed, 97 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/8-manifest/+page.md b/courses/moccasin-101/6-mox-coffee/8-manifest/+page.md index 94d3524f0..87fa527da 100644 --- a/courses/moccasin-101/6-mox-coffee/8-manifest/+page.md +++ b/courses/moccasin-101/6-mox-coffee/8-manifest/+page.md @@ -1,3 +1,97 @@ ---- - title: Manifest - --- \ No newline at end of file +## Manifest Named + +This lesson expands on our understanding of deploying contracts to real networks. We will use a feature called "Named Contracts" from the Mocassin framework. + +This feature will allow us to streamline the process of deploying our price feed contract to different networks. + +In the previous lesson, we were able to deploy our price feed contract to the PyVM. However, this was not very helpful for deploying to real networks. + +Let's explore the example from the Mocassin documentation: + +``` +[project] +src = "contracts" + +[networks.mainnet-fork] +url = "https://ethereum-rpc.publicnode.com" +chain_id = 1 +fork = true + +# Look here! We have a named contract named "usdc" +[networks.mainnet-fork.contracts] +usdc = { address = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"} + +``` + +This code introduces a new section called "contracts" within each network. This section defines a named contract, "usdc" in this case, and provides a specific address associated with that contract on the mainnet fork. + +Mocassin's named contracts allow us to define a variety of parameters. We saw the following: + +* **address:** The address of the contract on the network. +* **abi:** The ABI source of the contract. This can be a JSON file, a Vyper contract file, a Vyper interface file, or a raw ABI string. +* **abi_from_explorer:** This flag is set to true if you want to get the ABI from a public source. You may need to set an `explorer_api_key` in your `mocassin.toml` file or environment variable. +* **deployment_script:** This is the path to the deployment script for the contract. +* **force_deploy:** Set this to true if you want to force deploy the contract even when a contract exists at that address. + +In the previous lesson, we deployed our price feed contract to the PyVM using the `deploy_mocks.py` script. + +Let's revisit this script and incorporate named contracts: + +``` +from src.mocks import mock_v3_aggregator_v2 +from moccasin.boa_tools import VyperContract + +STARTING_DECIMALS = 8 +STARTING_PRICE = int(200e8) + +def deploy_feed() -> VyperContract: + return mock_v3_aggregator_v2.deploy(STARTING_DECIMALS, STARTING_PRICE) + +def moccasin_main() -> VyperContract: + return deploy_feed() +``` + +Now, we can update the `deploy.py` script to use named contracts: + +``` +from moccasin.config import get_active_network +from script.deploy_mocks import deploy_feed +from moccasin.boa_tools import VyperContract +from src import buy_me_a_coffee + +def moccasin_main(): + active_network = get_active_network() + price_feed = active_network.manifest_named("price_feed") + print(f"On network {active_network.name}, using price feed at {price_feed.address}") +``` + +Let's now open our `mocassin.toml` file to configure our deployment. + +First, we'll add a section for the Sepolia network: + +``` +[networks.sepolia] +url = "$SEPOLIA_RPC_URL" +save_to_db = false +default_account_name = "default" +explorer_uri = "https://eth-sepolia.blockscout.com/" +explorer_type = "blockscout" +``` + +We will create an `.env` file and set the `SEPOLIA_RPC_URL` environment variable to the Sepolia RPC URL from our Alchemy dashboard. + +We'll also add the price feed address and deploy script for Sepolia: + +``` +[networks.sepolia.contracts.price_feed] +address = "0x6944A41769357215DE4FAC081bf1f309aDC325306" +deployer_script = "script/deploy_mocks.py" +``` + +We're ready to test our deployment by running the command: + +```bash +mox run deploy --network sepolia +``` + +Mocassin will now be smart enough to know that there isn't a price feed contract on the PyVM. Therefore, it will use the address and deploy script we defined in our `mocassin.toml` file. This will ensure our deployment is efficient across various networks. From 91ea8341cea7e15ef3efc730f796c8818c62988d Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:02:16 -0700 Subject: [PATCH 763/797] Equious updated courses/moccasin-101/6-mox-coffee/9-top-level/+page.md. --- .../6-mox-coffee/9-top-level/+page.md | 71 ++++++++++++++++++- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/6-mox-coffee/9-top-level/+page.md b/courses/moccasin-101/6-mox-coffee/9-top-level/+page.md index 1006fc842..db971419f 100644 --- a/courses/moccasin-101/6-mox-coffee/9-top-level/+page.md +++ b/courses/moccasin-101/6-mox-coffee/9-top-level/+page.md @@ -1,3 +1,68 @@ ---- - title: Top Level - --- \ No newline at end of file +## Top-level Named Contracts + +In this lesson, we're going to be learning about a new concept called "top-level named networks". So far, we've been deploying our contracts using separate configurations for different networks. But, what if we could write one configuration for each of our networks and then have a top-level file to act as the main configuration file? This way, we can avoid repeating ourselves when deploying to different networks. We can use a technique called "top-level named networks" to do this. + +Here's how we can implement this technique: + +1. First, let's create a new section for each network: + +```toml +[networks.contracts] +deployer_script = "script/deploy_mocks.py" +abi = "Mock/v3_aggregator.json" + +[networks.contracts.price_feed] +address = "0x6944A41769357215DE4FAC4081f1f1309aDc323586" +deployer_script = "script/deploy_mocks.py" + +[networks.pyevm.contracts.price_feed] +deployer_script = "script/deploy_mocks.py" +``` + +2. Next, create a section for a "top-level named contract": + +```toml +[networks.contracts.coffee] +deployer_script = "script/deploy.py" +``` + +Now, for every network that doesn't have an address, it will automatically deploy a mock for us. This makes our life a little easier, but we can also specify an address for the network if we want. + +We can see that we do not need a deployer script for the `sepolia` network because we already have a default deployer script that can be used for all networks. + +Let's go ahead and run the following command to deploy to our network: + +```bash +mox run deploy --network sepolia +``` + +We are warned that our contract won't be compiled, but we are able to deploy. + +Now, we're going to refactor our code to include the power of top-level named networks. Let's add a line of code to our `deploy_coffee` function: + +```python +def deploy_coffee(price_feed: VyperContract) -> VyperContract: + coffee: VyperContract = buy_me_a_coffee.deploy(price_feed) + print(f"Coffee deployed at {coffee.address}") +``` + +We're going to go ahead and pass in the price feed to the `deploy_coffee` function. We can access our price feed using a `manifest named` function. The `manifest named` function will allow us to access any named contract that has been specified in our `mocassin.toml` configuration file. We can use this function in our `mocassin_main` function like so: + +```python +def moccasin_main() -> VyperContract: + active_network = get_active_network() + price_feed: VyperContract = active_network.manifest_named('price_feed') + print(f"On network {active_network.name}, using price feed at {price_feed.address}") + return deploy_coffee(price_feed) +``` + +Here's the breakdown of the code: + +1. We're first going to get the active network using the `get_active_network` function. +2. Next, we're going to use the `manifest_named` function to get the price feed. +3. We're going to print a message about the network and the price feed. +4. Finally, we're going to return the deployed `coffee` contract. + +This allows us to deploy our contract in a way that is easy to maintain and test. + +We can now deploy to our local network, an actual network, or a fork network. From 89111b027052b659cdd01280ace01f25a8c1e629 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:05:08 -0700 Subject: [PATCH 764/797] Equious updated courses/moccasin-101/7-mox-html/1-mox-intro/+page.md. --- .../7-mox-html/1-mox-intro/+page.md | 119 +++++++++++++++++- 1 file changed, 116 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/7-mox-html/1-mox-intro/+page.md b/courses/moccasin-101/7-mox-html/1-mox-intro/+page.md index f82ad97f5..c45b3c1ba 100644 --- a/courses/moccasin-101/7-mox-html/1-mox-intro/+page.md +++ b/courses/moccasin-101/7-mox-html/1-mox-intro/+page.md @@ -1,3 +1,116 @@ ---- - title: Mox Intro - --- \ No newline at end of file +## HTML/JS Introduction + +This lesson is a little bit different, because we are going to be teaching you how your wallets and how your Metamask interacts with websites. + +If you scroll down in this repo, the front-end code we have written here is actually going to work great for both Foundry and for Moccasin running anvil in the background. + +So, if you want to go ahead and follow along with me here, you can Whenever I say, hey, run this with Foundry, to deploy this with Foundry, just know that I mean with Moccasin. + +And we have some instructions in here on how to get started here with Moccasin instead of Foundry. + +Now, you do not have to follow along with me here. You can just watch and learn because it is really important that you understand what is actually happening when your Metamask pops up and says, hey, confirm this transaction. + +Because, if you confirm the wrong transaction, that's actually really scary. + +So, we want to learn how interacting with websites work, what it looks like. And if you have no intention of ever being a front-end developer, which is totally fine if you're like, hey, screw this I just want to be a Python dev, then great. You don't need to follow along here at all. + +But, if you would like to, the instructions in here for Moccasin are here as well. + +Additionally, the Foundry version of this project is just called fund me for the Moccasin edition. I thought it would be way nicer and more advanced if we called it buy me a coffee. + +So, whenever whenever I refer to fund me, just know that I am referring to the same buy me a coffee contract. Okay? + +So, we are going to go ahead We are going to go through the We are going to go through with this section I'm going to, you know, this is a slightly older video I'm going to be showing you how to do a lot of stuff using Foundry, but again, you can just as easily use Moccasin for this as well. + +So, let's go ahead, let's learn how websites actually work and how our wallets interact with these websites. So, here we go. + +**[Insert Metamask image here]** + +We are going to clone this repository: + +```bash +git clone https://github.com/Cyfrin/html-fund-me-cu +``` + +```bash +cd html-fund-me-cu +``` + +We are going to run the following commands to deploy to Moccasin: + +```bash +git clone https://github.com/Cyfrin/buy-me-a-coffee-cu +cd buy-me-a-coffee-cu +anvil +``` + +We are going to open up another terminal and run the following commands: + +```bash +mox run deploy --network anvil +``` + +**[Insert connect button image here]** + +When we click the **connect** button in the HTML code, Metamask will pop up and ask us to confirm a transaction. + +**[Insert Metamask transaction confirmation image here]** + +This transaction is actually just a call to the blockchain that is running in the background and will allow the connected wallet to interact with our website. + +**[Insert constants.js image here]** + +Here in our **constants.js** file we can see the address of our deployed contract. + +**[Insert Metamask add network image here]** + +We are going to add this network to Metamask. + +```bash +mox run deploy --network anvil +``` + +Let's take a look at the HTML code: + +```python + + + + + + Fund Me + + +

Fund Me

+ + + + + +``` + +This is the simple front-end for our project that we are going to connect with our contract. + +We will connect to our contract with the **index.js** file. + +```python +const connectButton = document.getElementById("connect"); + +connectButton.addEventListener('click', async () => { + if(typeof window.ethereum !== 'undefined'){ + const accounts = await window.ethereum.request({ + method: "eth_requestAccounts", + }); + console.log("Connected", accounts); + } else { + alert("Please install Metamask!"); + } +}) + +``` + +Here in this code, we are selecting the button and assigning it to a variable. We are then adding an event listener, which will fire when the button is clicked. + +The function fires when the button is clicked. It is then going to check if the user has Metamask installed, which we will check with the command `window.ethereum`. If it does, it will request the accounts from the user. And if it doesn't, it will alert the user. + +Hopefully this gives you a good overview of how to interact with your contracts from a web application! From 15485db6234d1a583e136d894900e7ae34d6e528 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:05:35 -0700 Subject: [PATCH 765/797] Equious updated courses/moccasin-101/7-mox-html/2-introduction/+page.md. --- .../7-mox-html/2-introduction/+page.md | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/7-mox-html/2-introduction/+page.md b/courses/moccasin-101/7-mox-html/2-introduction/+page.md index c21ef2ce7..d3234817e 100644 --- a/courses/moccasin-101/7-mox-html/2-introduction/+page.md +++ b/courses/moccasin-101/7-mox-html/2-introduction/+page.md @@ -1,3 +1,19 @@ ---- - title: Introduction - --- \ No newline at end of file +## HTML/JS Fund Me (Quick Fullstack/Front End Tutorial) + +In this lesson, we will take a look at HTML/JS Fund Me (Quick Fullstack/Front End Tutorial). + +We can find the code for this lesson on our GitHub repo: + +```python +Cyfriin/foundry-full-course-f23 +``` + +In this lesson we will be learning the basics of how our MetaMask or wallet interacts with a website. This is important knowledge. We will also be teaching you how to verify that your wallet is sending the transaction that you intended to send. + +We will not be teaching you how to build a full-stack application in this lesson. However, we are planning to launch a full-stack course on Cyfriin Updraft in the future. + +This HTML/JS Fund Me is a very basic, raw JavaScript full-website application. If you want to try to replicate it, you are free to do so. However, it is important that you understand what is going on under the hood when you interact with these websites. The knowledge that we are going to teach you here will work for every single website you interact with. This will allow you to know exactly what's going on when you interact with a website and send a transaction to the blockchain. + +Normally, we walk you through what we're going to do, but in this lesson we will jump right in. + +Assuming that you have downloaded Git, and have been working with Git and GitHub, we can actually start working with this codebase as if we had just come across it. From 428639f4ce11d7cd637fe595f26a49b147a99d16 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:06:22 -0700 Subject: [PATCH 766/797] Equious updated courses/moccasin-101/7-mox-html/3-setup/+page.md. --- .../moccasin-101/7-mox-html/3-setup/+page.md | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/7-mox-html/3-setup/+page.md b/courses/moccasin-101/7-mox-html/3-setup/+page.md index fcc7a149d..cd9372e83 100644 --- a/courses/moccasin-101/7-mox-html/3-setup/+page.md +++ b/courses/moccasin-101/7-mox-html/3-setup/+page.md @@ -1,3 +1,18 @@ ---- - title: Setup - --- \ No newline at end of file +## HTML Fund Me: Setup + +In this lesson, we'll learn how to set up a basic application to demonstrate how MetaMask interacts with a website. + +First, we need to clone the repository from Github. We can do this by opening our terminal and using the following commands: + +```bash +git clone https://github.com/CyfrinAccel0/html-fund-me-f23 +cd html-fund-me-f23 +``` + +Once we've cloned the repository, we can open the `index.html` file in our browser. This will display the basic webpage that we'll be working with. + +We'll be using the Live Server extension to run the website right from VS Code. This extension allows us to quickly preview changes and test our code. + +**[Image of a basic website with buttons and an input field]** + +This website is the foundation for our HTML Fund Me application. As we progress, we'll add functionality to allow users to interact with a smart contract through their MetaMask wallets. From 31323a18679338ae48aad25cfc39c92332976504 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:06:48 -0700 Subject: [PATCH 767/797] Equious updated courses/moccasin-101/7-mox-html/4-metamask/+page.md. --- .../7-mox-html/4-metamask/+page.md | 68 ++++++++++++++++++- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/7-mox-html/4-metamask/+page.md b/courses/moccasin-101/7-mox-html/4-metamask/+page.md index e823921f3..83857b083 100644 --- a/courses/moccasin-101/7-mox-html/4-metamask/+page.md +++ b/courses/moccasin-101/7-mox-html/4-metamask/+page.md @@ -1,3 +1,65 @@ ---- - title: Metamask - --- \ No newline at end of file +## HTML Fund Me: How MetaMask Works with your Browser + +The first thing to understand when working with a website is this MetaMask bit. + +We can inspect the website by right-clicking and hitting "inspect". This opens a window that includes a console, which is a live JavaScript shell. This shell contains information about the browser. + +If we type `window` into the console, we get a list of functions that we can call on this window object. One of the objects included in the window is the `window.ethereum` object. MetaMask injects this object into the browser. This is how websites interact with MetaMask to send transactions. + +If we open the same website in a browser that doesn't have MetaMask installed, the `window.ethereum` object will be undefined. This is because the browser doesn't have an API to connect to MetaMask. + +The MetaMask documentation includes information on how to send and work with the `window.ethereum` object. + +Now in our HTML Fund Me F23 project, we can scroll over to the `index.js` file, where we can see the code the website uses to interact with a wallet. One of the first things most websites do is check to see if MetaMask exists. This is done with the following line: + +```python +if (typeof window.ethereum !== "undefined") +``` + +If MetaMask does exist, they'll call the following function: + +```python +await ethereum.request({ method: "eth_requestAccounts" }) +``` + +This function allows the website to see which accounts the user has available to send transactions from. It doesn't expose the private key, but it lets the website send transactions for the user to sign. + +In the HTML code for this project, there is a button called `connectButton`. In the JavaScript code, the following line finds the `connectButton` in the HTML: + +```python +const connectButton = document.getElementById("connectButton") +``` + +The `connectButton`'s `onclick` event calls the `connect` function. This function checks if MetaMask is present, then attempts to connect to an account using the following line: + +```python +await ethereum.request({ method: "eth_requestAccounts" }) +``` + +If we go to the MetaMask extension, we can see that we're not connected to the site. However, if we click the `connectButton` in the website, a MetaMask popup appears. This popup asks which account we want to connect. We can then select an account to connect. + +We can then call other functions, like `getBalance`, `withdraw`, or `fund`. These functions interact with the Foundry Fund Me contract that we deployed. + +We've hard-coded the contract address and ABI into a `constants.js` file: + +```python +export const contractAddress = "0xe7f1725e7734ce288f8367e1bb043e90db35f0512" +``` + +The contract address and ABI are needed to interact with the deployed contract. + +To connect to a local anvil chain that we deployed the contract to, we open a terminal and run the following command: + +```bash +make anvil +``` + +This will start a local anvil chain. We can then run the following command to deploy the contract to this chain: + +```bash +make deploy +``` + +Now, we can go back to our website and hit the "connect" button. We can then interact with the contract using the "getBalance", "withdraw", and "fund" functions. When we hit the "fund" button, a MetaMask popup appears. This popup lets us sign the transaction that the website sends to the MetaMask. + +The website never accesses the private key. The private key remains secure in the MetaMask extension. From cc5e8a1c4ddf34450305b987dae7e9230b676b49 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:07:28 -0700 Subject: [PATCH 768/797] Equious updated courses/moccasin-101/7-mox-html/5-function-selectors/+page.md. --- .../7-mox-html/5-function-selectors/+page.md | 62 ++++++++++++++++++- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/7-mox-html/5-function-selectors/+page.md b/courses/moccasin-101/7-mox-html/5-function-selectors/+page.md index 73abb7ab1..f698adbc9 100644 --- a/courses/moccasin-101/7-mox-html/5-function-selectors/+page.md +++ b/courses/moccasin-101/7-mox-html/5-function-selectors/+page.md @@ -1,3 +1,59 @@ ---- - title: Function Selectors - --- \ No newline at end of file +## HTML Fund Me: Introduction to Function Selectors + +We'll look at function selectors and how they work within a smart contract. We can confirm or reject a transaction, and there is a lot of data visible within the MetaMask transaction window. + +If we go to the **DATA** tab, we see the function type is **Fund**. + +We can also see the raw transaction data in the **HEX** section of the transaction. We see the value, which is 0.1 GO or etherium. + +We are going to explore function selectors in greater detail in a later lesson, but for now, we can see how they operate. + +We have a **Fund** function within our Solidity code. + +```python +function fund() public payable { + require(msg.value.getConversionRate(priceFeed) >= MINIMUM_USD, + "You need to spend more ETH!!" + ); + // addressToAmountFunded[msg.sender] += msg.value; + s_funders.push(msg.sender); + s_addressToAmountFunded[msg.sender] += msg.value; +} +``` + +This function needs to be converted into a low-level byte code for ethereum to understand. This is where function selectors come in. + +We can see that the MetaMask transaction window shows us the function type is **Fund**. + +We can find the function selector ourselves by using a cast command. We run a cast command with a signature such as: + +```bash +cast sig "fund()" +``` + +The output for this command would be a function selector in Hex format, which is 0xb6e0d4288. + +The function signature **fund** returns the function selector. + +If we were to change the name of the function within our smart contract from **fund** to **stealMoney**, we can see that the function selector would be different. + +```python +function stealMoney() public payable { + require(msg.value.getConversionRate(priceFeed) >= MINIMUM_USD, + "You need to spend more ETH!!" + ); + // addressToAmountFunded[msg.sender] += msg.value; + s_funders.push(msg.sender); + s_addressToAmountFunded[msg.sender] += msg.value; +} +``` + +We can check this in the terminal with the command: + +```bash +cast sig "stealMoney()" +``` + +The function selector for stealMoney() is 0xa7ea5e4e, different from the fund() selector. + +We'll explore function selectors and this methodology in greater depth later. From 5ae58961e2294535da1a63618d980274a9558fdc Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:07:55 -0700 Subject: [PATCH 769/797] Equious updated courses/moccasin-101/7-mox-html/6-summary/+page.md. --- .../7-mox-html/6-summary/+page.md | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/7-mox-html/6-summary/+page.md b/courses/moccasin-101/7-mox-html/6-summary/+page.md index f68223117..452555444 100644 --- a/courses/moccasin-101/7-mox-html/6-summary/+page.md +++ b/courses/moccasin-101/7-mox-html/6-summary/+page.md @@ -1,3 +1,29 @@ ---- - title: Summary - --- \ No newline at end of file +## HTML Fund Me Completed! + +We've just finished a quick lesson on how websites interact with wallets. While it's short, this lesson is important for understanding how websites work when interacting with smart contracts. + +We learned a very basic way of checking something called the "function selector" or "function signature" to make sure that a website isn't malicious and doesn't send a bad transaction. + +We can connect to a wallet by injecting a browser extension into the browser. This can be achieved by checking the existence of `window.ethereum` in the browser. + +If we hit the "connect" button, we can see in the wallet that we've successfully connected. + +When a website sends a transaction, it first needs to obtain the provider or the RPC URL from MetaMask. This is often achieved by using the following code: + +```python +const provider = new ethers.providers.Web3Provider(window.ethereum) +``` + +The above code essentially tells MetaMask that the website needs access to the network's RPC URL. + +After connecting, a website can send transactions to our wallet. The code for a simple transaction might look like this: + +```python +const transactionResponse = await contract.fund({ + value: ethers.utils.parseEther(ethAmount), +}) +``` + +The above code sends a transaction to the wallet, which will then prompt us to sign the transaction by confirming. + +This lesson was a brief overview of the basics of front-end and wallet interactions. As we go further in the course, we'll learn more about function selectors and function signatures and how we can ensure that we protect ourselves against malicious transactions. From 01243aff04b15766079fc855f4cb89b34c2a14c7 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:08:28 -0700 Subject: [PATCH 770/797] Equious updated courses/moccasin-101/8-mox-erc20/1-intro/+page.md. --- .../moccasin-101/8-mox-erc20/1-intro/+page.md | 181 +++++++++++++++++- 1 file changed, 178 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/8-mox-erc20/1-intro/+page.md b/courses/moccasin-101/8-mox-erc20/1-intro/+page.md index b7e64e913..094de6a65 100644 --- a/courses/moccasin-101/8-mox-erc20/1-intro/+page.md +++ b/courses/moccasin-101/8-mox-erc20/1-intro/+page.md @@ -1,3 +1,178 @@ ---- - title: Intro - --- \ No newline at end of file +## Moccasin ERC20 Introduction + +We are about to learn a ton about ERC20 tokens, and how to deploy them. We'll also see a bug that we'll intentionally create in our smart contract. + +### Project Walkthrough + +Let's first take a look at the project. We're working with a GitHub repo that has an ERC20 project. We'll see that this project has a few things, including a contracts folder, a tests folder, and a script folder. + +We will also be creating our own custom token. + +We'll start with a base ERC20 token and then customize it to our liking. + +### Snekmate + +We're going to use a library called Snekmate to help us build our custom token. Snekmate is a Vyper library that provides a ton of boilerplate code for common smart contract functionality. + +### Custom ERC20 + +We will create a custom token that includes: + +- `name` +- `symbol` +- `decimals` +- `eip712 version` + +### Deploying the Token + +To deploy our token, we will use the `moxc` tool. + +```bash +moxc run deploy +``` + +### Events + +We will also learn about events. Events are a way for smart contracts to communicate with the outside world. + +### Testing + +We will use a combination of unit tests and fuzz tests to ensure our ERC20 token is secure and functional. + +- **Fuzz Testing** - Fuzz tests are a type of testing that involves generating random inputs and then running them against your smart contract. Fuzz testing is particularly useful for finding security vulnerabilities. +- **Stateless and Stateful Fuzzing** - We will learn how to create both stateless and stateful fuzzers. + +### Formatting + +We will also learn how to format our smart contract code in a way that automatically ensures our code is consistent and professional. + +### Code Blocks + +```python +pragma version ^0.4.0 +``` + +```python +license MIT +``` + +```python +title snek_token +``` + +```python +author You! +``` + +```python +notice This is my ERC20 token! +``` + +```python +from ethereum.ercs import ERC20 +``` + +```python +implements: ERC20 +``` + +```python +from ethereum.ercs import ERC20Detailed +``` + +```python +implements: ERC20Detailed +``` + +```python +from snekmate.auth import ownable as ow +``` + +```python +initializes: ow +``` + +```python +from snekmate.tokens import erc20 +``` + +```python +initializes: erc20(ownable = ow) +``` + +```python +exports: erc20._interface_ +``` + +```python +NAME: constant(String[25]) = "snek token" +``` + +```python +SYMBOL: constant(String[5]) = "SNEK" +``` + +```python +DECIMALS: constant(uint8) = 18 +``` + +```python +EIP712_VERSION: constant(String[20]) = "1" +``` + +```python +initialSupply: uint256 +``` + +```python +@deploy +def __init__(initial_supply: uint256): + ow.__init__() + erc20.__init__(NAME, SYMBOL, DECIMALS, NAME, EIP712_VERSION) + erc20.mint(msg.sender, initial_supply) + self.initialSupply = erc20.totalSupply +``` + +```python +@external +def super_mint(): + # We forget to update the total supply! + amount: uint256 = as_wei_value(100, "ether") + self.totalSupply += amount + erc20.balanceOf(msg.sender) = erc20.balanceOf(msg.sender) + amount + log ERC20.Transfer(empty_address, msg.sender, amount) +``` + +```python +from script.deploy import deploy +``` + +```python +from eth_utils import to_wei +``` + +```python +from moccasine.boa_tools import VyperContract +``` + +```python +from contracts import snek_token +``` + +```python +INITIAL_SUPPLY = to_wei(1000, "ether") +``` + +```python +def deploy() -> VyperContract: + snek_contract = snek_token.deploy(INITIAL_SUPPLY) + print(f"Deployed SnekToken at {snek_contract.address}") + return snek_contract +``` + +```python +def moccasine_main() -> VyperContract: + return deploy() +``` + +This is just a brief introduction to ERC20 tokens and how to deploy them. This lesson will help you get started with this kind of smart contract. From 05057e189cc84d28c4de7a48abd8274a47fea1ee Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:11:11 -0700 Subject: [PATCH 771/797] Equious updated courses/moccasin-101/8-mox-erc20/10-built-in-interfaces/+page.md. --- .../10-built-in-interfaces/+page.md | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/8-mox-erc20/10-built-in-interfaces/+page.md b/courses/moccasin-101/8-mox-erc20/10-built-in-interfaces/+page.md index 8aa752e0f..1811bc13c 100644 --- a/courses/moccasin-101/8-mox-erc20/10-built-in-interfaces/+page.md +++ b/courses/moccasin-101/8-mox-erc20/10-built-in-interfaces/+page.md @@ -1,3 +1,33 @@ ---- - title: Built In Interfaces - --- \ No newline at end of file +## Vyper Built-in Interfaces + +This lesson will explore the built-in interfaces provided by the Vyper compiler. + +The first interface we will look at is the `IERC20` interface. This interface comes built-in with the Vyper compiler. We can import and implement this interface in our contract. + +```python +from ethereum.erc20 import IERC20 + +implements: IERC20 +``` + +In the code above, we import the `IERC20` interface from the `ethereum.erc20` library and then implement the interface. + +The `implements` keyword in Vyper makes sure our contract will not compile unless it adds all the functions of the `IERC20` interface. The interface ensures our contract will be compatible with the ERC20 standard. + +Vyper comes with a large number of interfaces that are commonly used on the Ethereum blockchain. We will be exploring these in more detail as the course progresses. + +We can also make our own interfaces and implement them in our contracts. This can be beneficial when we want to make our own standards. + +For example, we could make an interface called `my_interface.vyi`. + +```python +# my_interface.vyi +``` + +We can then import and implement this interface in our smart contract to ensure our contract follows our custom standard. + +We are going to create a deployment script so that we can deploy our first token. We will come back to this code later and look at the interfaces in more detail. + +```python +# deploy.py +``` \ No newline at end of file From be657109c09ac02f299b5e26a810d4a1bd008ab1 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:12:17 -0700 Subject: [PATCH 772/797] Equious updated courses/moccasin-101/8-mox-erc20/11-deploy-scripts/+page.md. --- .../8-mox-erc20/11-deploy-scripts/+page.md | 74 ++++++++++++++++++- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/8-mox-erc20/11-deploy-scripts/+page.md b/courses/moccasin-101/8-mox-erc20/11-deploy-scripts/+page.md index 5d5d180f8..d7579eaa1 100644 --- a/courses/moccasin-101/8-mox-erc20/11-deploy-scripts/+page.md +++ b/courses/moccasin-101/8-mox-erc20/11-deploy-scripts/+page.md @@ -1,3 +1,71 @@ ---- - title: Deploy Scripts - --- \ No newline at end of file +## Deploy Scripts + +Let's write a deployment script. We can create a function called: + +```python +def moccasin_main(): +``` + +We can then call another function within this one: + +```python +return deploy() +``` + +Let's create that function: + +```python +def deploy(): +``` + +We'll add a pass statement to the function for now. + +```python +pass +``` + +We'll also add an import statement at the top of the script. + +```python +from contracts import snek_token +``` + +We will import the *to_wei* function from *eth_utils* as well. + +```python +from eth_utils import to_wei +``` + +Let's assign an initial supply to our token in a variable called *INITIAL_SUPPLY* + +```python +INITIAL_SUPPLY = to_wei(1000, 'ether') +``` + +Now, let's get our contract: + +```python +snek_contract = snek_token.deploy(INITIAL_SUPPLY) +``` + +Lastly, let's add a print statement to see the address of our deployed contract. + +```python +print(f"Deployed SnekToken at: {snek_contract.address}") +``` + +Now, if we run our script, we should see our deployed contract address printed in the terminal. + +We can run our script from the terminal. + +```bash +mox run deploy +``` + +We can also run the script using the file path. + +```bash +mox run ./script/deploy.py +``` + +Both of these will output our contract address. From 2f30dbdb5a39a0e1c4e8bdd76c63182a17ae8ed0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:12:45 -0700 Subject: [PATCH 773/797] Equious updated courses/moccasin-101/8-mox-erc20/12-tests/+page.md. --- .../8-mox-erc20/12-tests/+page.md | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/8-mox-erc20/12-tests/+page.md b/courses/moccasin-101/8-mox-erc20/12-tests/+page.md index 564ea6dda..484d23d6c 100644 --- a/courses/moccasin-101/8-mox-erc20/12-tests/+page.md +++ b/courses/moccasin-101/8-mox-erc20/12-tests/+page.md @@ -1,3 +1,31 @@ ---- - title: Tests - --- \ No newline at end of file +## Tests + +We've deployed our contract, and now we're ready to write some tests. We're not going to go in-depth with writing tests in this video, but we'll show a simple test case to get you started. + +In our project, we've created a `tests` folder. We can create a new file here called `test_token.py` and start to write our test. + +First, we'll import the `deploy` function from our `deploy.py` file: + +```python +from script.deploy import deploy, INITIAL_SUPPLY +``` + +Next, we'll create a test function: + +```python +def test_token_supply(): + snek_token = deploy() + assert snek_token.total_supply() == INITIAL_SUPPLY +``` + +The `test_token_supply` function will test the total supply of our token. We first deploy our token using the `deploy` function and store the contract in the `snek_token` variable. Then, we assert that the total supply is equal to `INITIAL_SUPPLY`, which we also imported from our `deploy.py` file. + +To run our test, we can open a terminal and run the following command: + +```bash +mox test +``` + +The test will run and pass, since we've deployed our token with an initial supply of 1000. We can write many more tests to test different functionality of our token. We can also create separate tests for our other functions like `mint`, `transfer`, and `burn`. + +The most important takeaway from this video is that we should be writing tests for our smart contracts to ensure that they function correctly. From 23e1f547e0efffd886b739936a9db7755e71b407 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:13:18 -0700 Subject: [PATCH 774/797] Equious updated courses/moccasin-101/8-mox-erc20/13-events/+page.md. --- .../8-mox-erc20/13-events/+page.md | 155 +++++++++++++++++- 1 file changed, 152 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/8-mox-erc20/13-events/+page.md b/courses/moccasin-101/8-mox-erc20/13-events/+page.md index 9e8e1b107..9486c2a99 100644 --- a/courses/moccasin-101/8-mox-erc20/13-events/+page.md +++ b/courses/moccasin-101/8-mox-erc20/13-events/+page.md @@ -1,3 +1,152 @@ ---- - title: Events - --- \ No newline at end of file +## Lesson 9: Events in our Raffle.sol + +In this lesson, we learn about events. You might think you're familiar with events, but you're really not. Let's dive into that. + +First, we've got our `Raffle.sol` contract. It's going to be a pretty simple raffle contract. It will have a `winner` variable and a `raffleEntries` variable. + +```python +pragma solidity ^0.8.0; + +contract Raffle { + + uint256 public raffleEntries; + address public winner; + + constructor() public { + raffleEntries = 0; + winner = address(0); + } + +``` + +Then we will add an event called `Entered`, it takes a single parameter, which is an address, and it will be used to record everyone who enters the raffle. + +```python + event Entered(address entrant); + +``` + +We'll also add an event called `WinnerSelected` with a single parameter which is an address. This is going to record who has won the raffle. + +```python + event WinnerSelected(address winner); + +``` + +Now let's add a function called `enter`. This function is going to be called by a user when they want to enter the raffle. It's going to use the `msg.sender` which is the address of the current user. + +```python + function enter() public payable { + require(msg.value >= entryFees, "You need to pay at least the entry fee to enter the raffle."); + raffleEntries++; + winner = msg.sender; + emit Entered(msg.sender); + } + +``` + +Let's add another function called `selectWinner`. This function is going to be called to randomly select the winner. + +```python + function selectWinner() public { + require(raffleEntries > 0, "There needs to be at least one entry in the raffle."); + uint256 randomIndex = uint256(keccak256(abi.encodePacked(lastBlockHash, msg.sender, raffleEntries))) % raffleEntries; + emit WinnerSelected(randomIndex); + } +} +``` + +We need to be careful, we can't just use the `block.timestamp` or `block.difficulty` for random numbers, because this is not a true random number. For now, let's assume this is a secure way to generate a random number. Of course, it's not truly random, because we're using the block, but it's fine for this example. + +So, we are now ready to test this. + +Now this is what it looks like, if we now go to Remix and copy this code in and compile it, and we can open up the console here and we can type in `raffleEntries` and we can see that it's currently zero, because we haven't had anyone enter the raffle yet. + +```bash +raffleEntries +``` + +We can type in `enter` and then `raffleEntries` again, so we can see that now there is at least one person in the raffle. + +```bash +enter +raffleEntries +``` + +If we now go to the `WinnerSelected` event, we are going to try to call it, and we can try to see the result of it. If we try to run this as it is, it's going to give us a pretty generic error here, because there is no `keccak256` and the `msg.sender` is not really allowed to be used inside an event. If we copy over the whole code, I'll show you what happens when we call it. Let me compile this. + +```bash +selectWinner +``` + +So, it says error, revert. `Invalid opcode`. This is because you can't run `keccak256` inside an event, it's not allowed. Now, how do we solve this issue? It's going to cost some gas, but we're going to need to generate the random number outside of the event. Now, the safest way to do this is to use the `blockhash`. + +Let's add another variable `lastBlockHash`. + +```python + uint256 public lastBlockHash; + +``` + +Now, we're going to make this variable `lastBlockHash` be `blockhash(block.number - 1)`. What does this mean? + +```python + constructor() public { + raffleEntries = 0; + winner = address(0); + lastBlockHash = blockhash(block.number - 1); + } + +``` + +What does this mean? This means that we are storing the hash of the block before this one. For example, let's say we're now on block number 200, so the `lastBlockHash` will be the hash of block number 199. + +Now let's modify the `selectWinner` function to use this `lastBlockHash`: + +```python + function selectWinner() public { + require(raffleEntries > 0, "There needs to be at least one entry in the raffle."); + uint256 randomIndex = uint256(keccak256(abi.encodePacked(lastBlockHash, msg.sender, raffleEntries))) % raffleEntries; + emit WinnerSelected(randomIndex); + } +} +``` + +We are now ready to test this! + +Now this is what it looks like, if we now go to Remix and copy this code in and compile it, and we can open up the console here and we can type in `raffleEntries` and we can see that it's currently zero, because we haven't had anyone enter the raffle yet. + +```bash +raffleEntries +``` + +We can type in `enter` and then `raffleEntries` again, so we can see that now there is at least one person in the raffle. + +```bash +enter +raffleEntries +``` + +If we now go to the `WinnerSelected` event, we are going to try to call it, and we can try to see the result of it. + +```bash +selectWinner +``` + +And you'll see that it successfully executes, it does not give us a revert error. Now it's going to emit an event in the `Logs` tab in Remix. + +So, this is how we've used events to record what's happening in our raffle contract. We can read and log data for our contracts. + +**Now we can write some code to read the events.** Let's go back to Solidity. We can add another function `getWinner`, and let's make this function a view function. + +```python + function getWinner() public view returns(address){ + return winner; + } + +} +``` + +This function is going to simply return the `winner`. + +Now if we go back to Remix and we compile this, we can call `getWinner` and we can see that it's returning the address `0x...` We can go back to the `Events` tab and we can see that this event is now being emitted. So this is how we can emit events and then read events in our raffle contract. If you have any questions about this, please ask! /home/equious/Nevermore/courses/moccasin-101/8-mox-erc20\13-events\+page.md From 0145a7a1a9ea9f0ea04ab9196f68012d46722e15 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:18:27 -0700 Subject: [PATCH 775/797] Equious updated courses/moccasin-101/8-mox-erc20/14-testing-events/+page.md. --- .../8-mox-erc20/14-testing-events/+page.md | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/8-mox-erc20/14-testing-events/+page.md b/courses/moccasin-101/8-mox-erc20/14-testing-events/+page.md index 61a1a8118..7cb678d98 100644 --- a/courses/moccasin-101/8-mox-erc20/14-testing-events/+page.md +++ b/courses/moccasin-101/8-mox-erc20/14-testing-events/+page.md @@ -1,3 +1,51 @@ ---- - title: Testing Events - --- \ No newline at end of file +## Testing for Events + +We've learned what events are and what they're used for. Let's look at our `snek_token` and see if we need to add it anywhere. Okay, maybe for this mint function. Okay, maybe for our initial deploy, but actually, does this mint function already emit logs? Let's take a look. And, yep, it sure does. Okay, so we don't need to do any logging on our `snek_token`. Our `snek_token` is good. + +Let's go to our test token though and let's learn how to read these logs to make sure that we're actually using them. + +So we'll do a little test or a def test `token_emits_event` like this. + +```python +def test_token_emits_event(): + snek_token = deploy() + with boa.env.prank(snek_token.owner): + snek_token.transfer(RANDOM_USER, INITIAL_SUPPLY) + logs = snek_token.get_logs() + log_owner = logs[0].topics[0] + assert log_owner == snek_token.owner() +``` + +We'll run this line again, which again is not good. We should be using this as a fixture. But then, we'll do `with boa.env.prank(snek_token.owner):` Let's just be the `snek_token.owner`. + +We need to import boa. + +```python +import boa +``` + +Let's do `snek_token.transfer(boa.accounts[1], 100)` to some random users. So I'm going to say `RANDOM_USER = boa.env.generate_address('random_user')` like this. + +```python +RANDOM_USER = boa.env.generate_address('random_user') +``` + +We'll do `snek_token.transfer(RANDOM_USER, INITIAL_SUPPLY)`. So this transfer function, if we go to def `transfer`, this is on the `erc20.vy` and it calls this `self.transfer`. This internal transfer function, which is a whole bunch of code here, but basically, this is what updates the balance, right? So the balance of a certain address is really just a mapping. So when people are like, "Oh, I have X number of tokens," what they're really saying is "Oh, I have seven in my mapping on that contract," or however many tokens they have, right? That's really all having tokens is, is having an entry in this mapping in this smart contract. Kind of crazy, right? Well, when we do `snek_token.transfer`, this transfer emits this `IERC20.Transfer(owner, to, amount)`. So this transfer event is actually specified in the `IERC20` interface. + +And events, by the way, they look just like structs. To make an event or a log, you just have event, the name of the event, and any of the parameters in it. And then, you emit it like this or you log it like this. So in the `IERC20` interface, it has those event objects. Specified, one such is the transfer event, but it takes the owner, the to, and the amount and it emits them. + +So we can actually get this log back in our test here after we do the transfer function, but still inside of this this with context, we'll say we can say logs equals `snek_token.get_logs` like this. And this will return a little array of logs. So I can even do a little breakpoint in here and let's run this test. So we'll do `mox test -k` paste that in. We'll pop us into this little terminal here. So, let's see what the the logs variable looks like. So the logs has a single event in it. So this is an array of different logs or events that have happened. And there's a single transfer event in it with a sender, receiver, and a value. So we have We see sender, receiver, value. We'll go back to the `erc20`. We go down to this. We have sender, receiver, and value exactly as the transfer log is doing. + +So to do a little assertion here we could say, let's even look at the `snek_token.owner`. `snek_token.owner` is this address here. We can see that it is also the sender. So what we could do is we could say the log owner is going to be equal to the logs, zero. So the first log or the first event.topics, which we learned about from the video we just watched, zero, which is going to be this sender. And we could do `assert log_owner == snek_token.owner`. We can even run this. We can even run this in our little terminal down here. Let's paste that line in here. + +```bash +mox test -k test_token_emits_event +``` + +We get a little error cuz we're editing our test in a breakpoint, which is annoying. And then, we can run this. + +```bash +mox test -k test_token_emits_event +``` + +And we get true. So, I'm going to type `q`. We're going to quit that. Got rid of the breakpoint. We could also add another assert in here if we want it. We can say assert `snek_token.balanceOf(RANDOM_USER) == INITIAL_SUPPLY`. From e744fea20cb2f98f2ab033e1ed65a585e56d2062 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:20:11 -0700 Subject: [PATCH 776/797] Equious updated courses/moccasin-101/8-mox-erc20/15-formatting/+page.md. --- .../8-mox-erc20/15-formatting/+page.md | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/8-mox-erc20/15-formatting/+page.md b/courses/moccasin-101/8-mox-erc20/15-formatting/+page.md index 33a74c43a..0083f04e4 100644 --- a/courses/moccasin-101/8-mox-erc20/15-formatting/+page.md +++ b/courses/moccasin-101/8-mox-erc20/15-formatting/+page.md @@ -1,3 +1,45 @@ ---- - title: Formatting - --- \ No newline at end of file +## Formatting: Vyper & Python + +We're going to go into fuzz testing in just a minute, but first we'll take a look at some ways to format our Vyper and Python code. + +Our code looks like this: + +```python +script +from moccasin.boa.tools import VyperContract +from eth_utils import to_wei +INITIAL_SUPPLY = to_wei(1000, "ether") +from contracts import snek_token +def deploy() -> VyperContract: + snek_contract = snek_token.deploy(INITIAL_SUPPLY) + print(f"Deployed to {snek_contract.address}") + return snek_contract +def moccasin_main() -> VyperContract: + return deploy() +``` + +This code is not formatted well, with imports in a strange order. We can either manually change this code, or we can use a tool. + +Let's go ahead and install the **ruff** formatter. We can do this through UV's command palette by typing "format document" and hitting enter. + +We can also format our code in the terminal using the following command: + +```bash +uv run ruff check --select I--fix +``` + +This will automatically fix a lot of our imports. + +What about Vyper? We can also format our Vyper code using a tool called **mamushi**. This tool can be installed using the following command: + +```bash +uv add mamushi +``` + +After installing mamushi, we can run the following command to format our contracts folder: + +```bash +uv run mamushi contracts/ +``` + +This will reformat our entire `snek_token.vy` file to be much nicer looking. From f785ee2f14c3f94e526fde925bcfd0cdbbaf4149 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:21:23 -0700 Subject: [PATCH 777/797] Equious updated courses/moccasin-101/8-mox-erc20/16-justfile/+page.md. --- .../8-mox-erc20/16-justfile/+page.md | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/8-mox-erc20/16-justfile/+page.md b/courses/moccasin-101/8-mox-erc20/16-justfile/+page.md index 1c66d6614..e0547d1da 100644 --- a/courses/moccasin-101/8-mox-erc20/16-justfile/+page.md +++ b/courses/moccasin-101/8-mox-erc20/16-justfile/+page.md @@ -1,3 +1,29 @@ ---- - title: Justfile - --- \ No newline at end of file +## Optional: Justfile + +We can use something called a Justfile to run a bunch of commands easily. This is 100% optional but, it's a handy way to save and run project-specific commands. If we're very specific about how we like to have formatters, we can create a Justfile. + +We can create a command that's a combination of a bunch of commands, but are really easy for us to run. For example, if we want to run the formatter, we can add the following to our Justfile: + +```python +# Run the formatter +format: + @just fmt +``` + +We can also add a command to run our formatter: + +```python +# Run the formatter +format: + uv run ruff check --select I --fix +``` + +We're going to use the VS Code Just extension. We can install this from the VS Code marketplace. We can change the language mode of our Justfile from Python to Just. + +Now, we can run the Just format command: + +```bash +just format +``` + +This will run both of the formatter commands for us. We can add a lot of commands to our Justfile and use this as a way to run multiple commands quickly. From 048cf4f3cc04501774f81131ad71f0b9a0f7d9b3 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:21:57 -0700 Subject: [PATCH 778/797] Equious updated courses/moccasin-101/8-mox-erc20/17-vheaders/+page.md. --- .../8-mox-erc20/17-vheaders/+page.md | 77 ++++++++++++++++++- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/8-mox-erc20/17-vheaders/+page.md b/courses/moccasin-101/8-mox-erc20/17-vheaders/+page.md index f03fb7dd5..4bf83d5f0 100644 --- a/courses/moccasin-101/8-mox-erc20/17-vheaders/+page.md +++ b/courses/moccasin-101/8-mox-erc20/17-vheaders/+page.md @@ -1,3 +1,74 @@ ---- - title: Vheaders - --- \ No newline at end of file +## Section Headers in Vyper + +We've learned about how to format our Vyper code with tools such as `black` and `ruff`. However, when our code grows, it can become difficult to navigate and understand. Section headers help with this. + +Section headers help us organize our code and separate it into different sections. For instance, we can separate the **Imports**, **State Variables**, and **Functions** sections to make our code easier to read and understand. + +There are two main ways to create section headers: + +- Using `vheader` Python package +- Using `headers-vy` Rust package + +## `vheader` Python Package + +We can use the `vheader` Python package to generate section headers in our Vyper code. Let's look at how to install this package. + +First, we go to the repository's `README` file. + +Then, we copy the following command to install `vheader`: + +```bash +uv tool install vheader +``` + +Once installed, we can run the following command in our terminal: + +```bash +vheader imports +``` + +This command will generate a section header for the **Imports** section in our Vyper code. + +We can do the same for other sections: + +```bash +vheader state variables +``` + +```bash +vheader functions +``` + +This will add section headers to the **State Variables** and **Functions** sections. + +## `headers-vy` Rust Package + +There is also the `headers-vy` Rust package that we can install. + +To install `headers-vy`, we need to make sure Rust and Cargo are installed on our machine. The `README` file has instructions for installing those if needed. + +Once we have Rust and Cargo installed, we can clone the `headers-vy` repository and run the following command in our terminal to install the package: + +```bash +cargo install --path . +``` + +Once the package is installed, we can run the following command in our terminal: + +```bash +./headers-vy "testing 123" +``` + +This command will generate the following header: + +```bash +# ################################################## +# # +# TESTING 123 # +# # +# ################################################## +``` + +## Conclusion + +Adding section headers to our Vyper code can significantly improve readability and organization. By separating our code into distinct sections, we can make it easier to navigate and understand, ultimately leading to more maintainable and efficient code. From c634a3e3fe35e5bc36803ea3a36d0798e7a70722 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:22:22 -0700 Subject: [PATCH 779/797] Equious updated courses/moccasin-101/8-mox-erc20/18-fuzzing/+page.md. --- .../8-mox-erc20/18-fuzzing/+page.md | 133 +++++++++++++++++- 1 file changed, 130 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/8-mox-erc20/18-fuzzing/+page.md b/courses/moccasin-101/8-mox-erc20/18-fuzzing/+page.md index a52eae390..ee6871015 100644 --- a/courses/moccasin-101/8-mox-erc20/18-fuzzing/+page.md +++ b/courses/moccasin-101/8-mox-erc20/18-fuzzing/+page.md @@ -1,3 +1,130 @@ ---- - title: Fuzzing - --- \ No newline at end of file +## Fuzz Testing: Introduction + +Fuzz Testing is a technique for finding vulnerabilities in software by feeding it random data. We can use this technique to find bugs and vulnerabilities in smart contracts. + +Let's start by looking at a simple example: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract MyContract { + uint256 public shouldAlwaysBeZero = 0; + uint256 private hiddenValue = 0; + function doStuff(uint256 data) public { + if (data == 2) { + shouldAlwaysBeZero = 1; + } + if (hiddenValue == 7) { + shouldAlwaysBeZero = 1; + } + hiddenValue = data; + } +} +``` + +We have a function called `doStuff` which takes an integer as an input parameter. We know that the variable `shouldAlwaysBeZero` should always be zero. This is known as an invariant. + +The invariant is a property of the system that must always hold. + +Let's look at a unit test for this code: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {MyContract} from "./MyContract.sol"; + +contract MyContractTest { + MyContract exampleContract; + + function testAlwaysGetZeroUnit() public { + uint256 data = 0; + exampleContract.doStuff(data); + assert(exampleContract.shouldAlwaysBeZero() == 0); + } +} +``` + +We pass in a single data point, call the function, and then check if our invariant is still true. We might think that our code is covered, but if we look closer at the `doStuff` function we see that if our data input is 2, `shouldAlwaysBeZero` will be set to 1. This will break our invariant, since `shouldAlwaysBeZero` will no longer be zero. + +In order to find this bug, we can write a fuzz test in Foundry. This will allow us to automatically generate random input data and run it through our code to try to find edge cases. + +Let's write a fuzz test for this example: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {MyContract} from "./MyContract.sol"; +import {Test} from "forge-std/Test.sol"; + +contract MyContractTest is Test { + MyContract exampleContract; + + function testAlwaysGetZeroFuzz(uint256 data) public { + // uint256 data = 0; + exampleContract.doStuff(data); + assert(exampleContract.shouldAlwaysBeZero() == 0); + } +} +``` + +In the fuzz test, we will remove the manually selected data and let Foundry automatically randomize the data. + +We can run this fuzz test from the terminal using this command: + +```bash +forge test -m testAlwaysGetZeroFuzz +``` + +Foundry will then automatically run through our code with a ton of different random inputs to try to find a scenario where the invariant is broken. + +We can see that the fuzz test has successfully identified a counter-example. This allows us to go back to our code and fix the bug. + +Foundry fuzz tests are known as stateless fuzz tests, which means that the state of the previous run is discarded for the next run. + +There's another type of fuzz test that we can write in Foundry called a stateful fuzz test. This is where we use the ending state of our previous fuzz run as the starting state of the next fuzz run. + +To write a stateful fuzz test, we use the `invariant` keyword. + +Let's write a stateful fuzz test for our example: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {MyContract} from "./MyContract.sol"; +import {Test} from "forge-std/Test.sol"; +import {StdInvariant} from "forge-std/StdInvariant.sol"; + +contract MyContractTest is StdInvariant, Test { + MyContract exampleContract; + + function setUp() public { + exampleContract = new MyContract(); + targetContract(address(exampleContract)); + } + + function invariant_testAlwaysReturnsZero() public { + assert(exampleContract.shouldAlwaysBeZero() == 0); + } +} +``` + +We first need to import the `StdInvariant` contract and inherit it in our test contract. + +We then need to tell Foundry which contract to run the fuzz test on. Since we only have one contract, we'll tell Foundry that `exampleContract` should be used as the target contract. + +Lastly, we will write a function called `invariant_testAlwaysReturnsZero` that asserts that `shouldAlwaysBeZero` is equal to zero. + +Now when we run this test, Foundry will randomly run through our code, calling our functions in a random order with random data. + +Since we only have one function `doStuff`, it will call `doStuff` with random data, then call `doStuff` again with random data, then call `doStuff` again with random data, and so on. If it happens to call `doStuff` with an input of 7, it will set `hiddenValue` to 7. The next time it calls `doStuff`, it will set `shouldAlwaysBeZero` to 1. When it runs our invariant test, it will find that our invariant is broken. + +We can see in the terminal that the invariant test found a failing test with this sequence: + +```bash +[FAIL. Reason: Assertion violated] +[Sequence] +sender=0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \ No newline at end of file From c72face500065ee8a2ba54109538aed0a4a19010 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:30:53 -0700 Subject: [PATCH 780/797] Equious updated courses/moccasin-101/8-mox-erc20/19-stateless-fuzz/+page.md. --- .../8-mox-erc20/19-stateless-fuzz/+page.md | 90 ++++++++++++++++++- 1 file changed, 87 insertions(+), 3 deletions(-) diff --git a/courses/moccasin-101/8-mox-erc20/19-stateless-fuzz/+page.md b/courses/moccasin-101/8-mox-erc20/19-stateless-fuzz/+page.md index 0b6bd8f45..5ef3d096d 100644 --- a/courses/moccasin-101/8-mox-erc20/19-stateless-fuzz/+page.md +++ b/courses/moccasin-101/8-mox-erc20/19-stateless-fuzz/+page.md @@ -1,3 +1,87 @@ ---- - title: Stateless Fuzz - --- \ No newline at end of file +## Stateless Fuzzing in Python + +We're going to start this lesson by learning how to write stateless fuzz tests. First, we need to understand what fuzz tests are and the difference between stateful and stateless fuzz tests. + +Stateful fuzz tests need to save state information, allowing them to be more complex, and stateless fuzz tests do not need to save state information. This means that stateless fuzz tests are typically simpler and easier to write, so that's what we're going to focus on first. + +Let's get started by creating a new folder called sub lesson. Inside of that folder, let's copy two files from our GitHub repository: + +* `stateful_fuzz_solvable.vy` +* `stateless_fuzz_solvable.vy` + +These files contain code that we will use to write our fuzz tests. If we open the `stateless_fuzz_solvable.vy` file we'll see this code: + +```python +# pragma version 0.4.0 + +# title always_return_input +@license MIT +# notice INVARIANT: always_returns_input_number should always return the input number + +some_number: public(uint256) + +@external +@pure +def always_returns_input_number(input_number: uint256) -> uint256: + @param input_number The input number to check + if input_number == 2: + return 0 + return input_number +``` + +This is a very simple smart contract that has one function called `always_returns_input_number`. This function has an invariant that it should always return the same value that is passed into the function. + +We also see that there is an exception to this invariant, where the function returns 0 if it is passed the value of 2. + +Now, we're going to create a new file called `test_stateless.py`, which will contain our stateless fuzz tests. We need to start by importing the `pytest` and `hypothesis` libraries. Hypothesis comes included with Mocassin, which means that we can just import it directly. Let's also import the `StatelessFuzzSolvable` contract. We do this with these commands: + +```python +import pytest +from contracts.sub_lesson import stateless_fuzz_solvable + +``` + +Now, we need to create a fixture to deploy the smart contract: + +```python +@pytest.fixture(scope="function") +def contract(): + return stateless_fuzz_solvable.deploy() +``` + +This fixture will be used to deploy the contract before running each of our tests. + +To write our actual fuzz test we need to import the `given` function from hypothesis. + +```python +from hypothesis import given +``` + +Now, we can start writing our test! + +```python +@given(input=strategies.uint256) +def test_always_returns_input(contract, input): + print(input) + assert contract.always_returns_input_number(input) == input +``` + +This test uses the `given` function from hypothesis to generate a random `uint256` value. Then we pass that value into the `always_returns_input_number` function and assert that it returns the same value. + +One important thing to note is that Hypothesis doesn't work well with fixtures. We're going to add a setting to our test that will allow it to function properly. + +```python +@settings(suppress_health_check=[HealthCheck.function_scoped_fixture]) +``` + +This setting tells Hypothesis to ignore the warning about using fixtures. + +Now, let's run this test and see the results. We will use this command to run the test: + +```bash +mox test -k test_always_returns_input -s +``` + +The `-s` flag allows us to see the output of the `print` function in the test. We'll see that Hypothesis has generated and tested a bunch of random `uint256` values and has found one example where the invariant is broken. This is because the function returns 0 when given the value of 2. + +This concludes our look at stateless fuzzing. We've successfully written a fuzz test that found a bug in our simple smart contract. From 46cbcd0b441b11cd37e08a6a48a5e74bac07184a Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:53:03 -0700 Subject: [PATCH 781/797] Equious updated courses/moccasin-101/1-python-in-updraft/1-intro/+page.md. From a93434c26465a95fe223b10eebedec31f9e4bdc0 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:55:24 -0700 Subject: [PATCH 782/797] Equious updated courses/moccasin-101/1-python-in-updraft/10-types/+page.md. From 83595c9bb2648e9fd78488a10936e814bb94424f Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:55:38 -0700 Subject: [PATCH 783/797] Equious updated courses/moccasin-101/1-python-in-updraft/11-math/+page.md. From 6ff834add8cfe3010b7c48ca6e2d6f0949e403aa Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:55:51 -0700 Subject: [PATCH 784/797] Equious updated courses/moccasin-101/1-python-in-updraft/12-more-math/+page.md. From a7973151c28523026f92ef2ab3e50cf6fb61e8f4 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:56:23 -0700 Subject: [PATCH 785/797] Equious updated courses/moccasin-101/1-python-in-updraft/13-funcs/+page.md. From b7473cf609724144f374f746de738b9e482f2f36 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:57:09 -0700 Subject: [PATCH 786/797] Equious updated courses/moccasin-101/1-python-in-updraft/14-conditionals/+page.md. From b73bfce3961bc7c1e09c8ec3cb8d5c9f7f93aea5 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:57:28 -0700 Subject: [PATCH 787/797] Equious updated courses/moccasin-101/1-python-in-updraft/15-while-loops/+page.md. From 8e6d301c1e7e8c1ca4bd6473bb8fd0e3a433b6b7 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:58:08 -0700 Subject: [PATCH 788/797] Equious updated courses/moccasin-101/1-python-in-updraft/16-loops-2/+page.md. From 5c7169b55bdb15b92e280ed7a0c60e49eb168f62 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:58:21 -0700 Subject: [PATCH 789/797] Equious updated courses/moccasin-101/1-python-in-updraft/17-loops-3/+page.md. From 29e01b283a9cde05ad3a507adaef0af5a6547127 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:58:37 -0700 Subject: [PATCH 790/797] Equious updated courses/moccasin-101/1-python-in-updraft/18-workshop/+page.md. From 64021729ae9089286b79907d4f4b659bd05db40e Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:58:59 -0700 Subject: [PATCH 791/797] Equious updated courses/moccasin-101/1-python-in-updraft/19-recap/+page.md. From 5f62d029dbf5b4327e0d75bb67dfb41865f478ae Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 10:59:22 -0700 Subject: [PATCH 792/797] Equious updated courses/moccasin-101/1-python-in-updraft/2-google-collab/+page.md. From c4812d95097db69b8f0166b75b52b5881ef87ae7 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:01:56 -0700 Subject: [PATCH 793/797] Equious updated courses/moccasin-101/1-python-in-updraft/20-dev-env-setup/+page.md. From c6c86c91fa059d6f293b5af93c1ede5592978d69 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:03:22 -0700 Subject: [PATCH 794/797] Equious updated courses/moccasin-101/1-python-in-updraft/21-install-vscode-macos-linux/+page.md. From 5a233cf926cf1dc981cc8b8b0b4e08fb9c18e636 Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:03:42 -0700 Subject: [PATCH 795/797] Equious updated courses/moccasin-101/1-python-in-updraft/22-install-wsl/+page.md. From d24f1d3e6e6262b29de6e77e9a384b518b8bf27c Mon Sep 17 00:00:00 2001 From: Equious <76449140+Equious@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:06:35 -0700 Subject: [PATCH 796/797] Equious updated courses/moccasin-101/1-python-in-updraft/23-vscode-windows-install/+page.md. From 267f2da47e0922be4c2286aa8476744d5d374e6b Mon Sep 17 00:00:00 2001 From: hunter <104146303+solhosty@users.noreply.github.com> Date: Wed, 27 Nov 2024 00:36:27 -0500 Subject: [PATCH 797/797] updated paths --- .../10-vscode-solidity-setup/+page.md | 64 ++++++ .../+page.md | 29 +++ .../+page.md | 93 +++++++++ .../+page.md | 24 +++ .../+page.md | 88 +++++++++ .../+page.md | 43 ++++ .../+page.md | 187 ++++++++++++++++++ .../17-what-is-a-transaction/+page.md | 56 ++++++ .../+page.md | 53 +++++ .../19-never-use-a-env-file/+page.md | 44 +++++ .../+page.md | 64 ++++++ .../21-deploying-to-a-testnet/+page.md | 56 ++++++ .../+page.md | 43 ++++ .../23-cleaning-up-the-project/+page.md | 62 ++++++ .../24-foundry-zksync/+page.md | 34 ++++ .../25-compiling-foundry-zksync/+page.md | 11 ++ .../26-zksync-local-node/+page.md | 37 ++++ .../27-zksync-local-deploy/+page.md | 30 +++ .../28-tx-types/+page.md | 36 ++++ .../29-why-l2/+page.md | 30 +++ .../30-alchemy-mempool/+page.md | 82 ++++++++ .../31-summary-congratulations/+page.md | 47 +++++ .../4-develop-in-cloud-using-gitpod/+page.md | 21 ++ .../5-local-setup/+page.md | 9 + .../6-foundry-install/+page.md | 87 ++++++++ .../7-setup-your-vscode/+page.md | 67 +++++++ .../8-create-a-new-foundry-project/+page.md | 86 ++++++++ .../+page.md | 31 +++ 28 files changed, 1514 insertions(+) create mode 100644 courses/foundry/1-foundry-simple-storage/10-vscode-solidity-setup/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/11-compile-a-smart-contract-using-foundry/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/12-deploy-a-smart-contract-locally-using-ganache/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/13-how-to-add-a-new-network-to-metamask/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-forge/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/15-important-private-key-safety-pt-1/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-anvil/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/17-what-is-a-transaction/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/18-important-private-key-safety-pt-2/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/19-never-use-a-env-file/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/20-interact-with-a-smart-contract-using-the-cli/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/21-deploying-to-a-testnet/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/22-verify-a-smart-contract-on-etherscan/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/23-cleaning-up-the-project/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/24-foundry-zksync/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/25-compiling-foundry-zksync/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/26-zksync-local-node/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/27-zksync-local-deploy/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/28-tx-types/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/29-why-l2/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/30-alchemy-mempool/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/31-summary-congratulations/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/4-develop-in-cloud-using-gitpod/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/5-local-setup/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/6-foundry-install/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/7-setup-your-vscode/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/8-create-a-new-foundry-project/+page.md create mode 100644 courses/foundry/1-foundry-simple-storage/9-create-a-new-foundry-project-wsl/+page.md diff --git a/courses/foundry/1-foundry-simple-storage/10-vscode-solidity-setup/+page.md b/courses/foundry/1-foundry-simple-storage/10-vscode-solidity-setup/+page.md new file mode 100644 index 000000000..ae3566759 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/10-vscode-solidity-setup/+page.md @@ -0,0 +1,64 @@ +--- +title: VSCode Solidity setup +--- + +_Follow along with this video:_ + +--- + +### Improving Code Format in Visual Studio Code + +When you first start, your code might just look like a whole bunch of dull, lifeless, white text. + +This can be easily fixed by using one of the `Solidity` extensions. Out of all the Solidity extensions available in the Extensions tab (CTRL/CMD + SHIFT + X) the following are worth mentioning: + +1. [Solidity by Juan Blanco](https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity), the most used Solidity extension out there. +2. [Solidity by Nomic Foundation](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity) is Patrick's favorite Solidity extension. The rest of the course will be displaying this extension. +3. [Solidity Visual Developer](https://marketplace.visualstudio.com/items?itemName=tintinweb.solidity-visual-auditor) is another popular choice. + +**NOTE**: If the code remains unhighlighted despite having installed the extension, there's a quick solution to that. Press `Command + Shift + P`, or `Control + Shift + P` on Windows. This opens up the command bar. In the command bar, type in "Settings" and select "Preferences: Open User Settings (JSON)". + +If you have nothing in there, create a new setting by typing in: + +``` +{ + "editor.defaultFormatter": "NomicFoundation.hardhat" +} +``` + +Use: + +`"editor.defaultFormatter": "tintinweb.solidity-visual-auditor"` for Solidity Visual Developer + +or + +`"editor.defaultFormatter": "JuanBlanco.solidity"` for Solidity by Juan Blanco + +### Other interesting extensions + +In the previous lesson, we mentioned a file called `foundry.toml`. This also has an extension that formats it to make it easier to read. Please install [Even Better TOML](https://marketplace.visualstudio.com/items?itemName=tamasfe.even-better-toml). + +Another indispensable extension is [Inline Bookmarks](https://marketplace.visualstudio.com/items?itemName=tintinweb.vscode-inline-bookmarks). + +The Inline Bookmarks plugin facilitates bookmarking the actual code. The extension can be used for document review, auditing, log analysis, and keeping track of development notes and to-do lists. You may share your notes and bookmarks with others with ease because they are saved with your files. + +The following default trigger words/tags are configured by default: +``` +@todo - (blue) General ToDo remark. +@note - (blue) General remark. +@remind - (blue) General remark. +@follow-up - (blue) General remark. +@audit - (red) General bookmark for potential issues. +@audit-info - (blue) General bookmark for information to be noted for later use. +@audit-ok - (green) Add a note that a specific line is not an issue even though it might look like. +@audit-issue - (purple) Reference a code location an issue was filed for. +``` + +You can fully customize the colors! + +Remember these! They will be very handy in developing and especially in auditing projects. + +More details are available [here](https://github.com/tintinweb/vscode-inline-bookmarks). + +Next comes the fun part! Let's compile our contract using Foundry! + diff --git a/courses/foundry/1-foundry-simple-storage/11-compile-a-smart-contract-using-foundry/+page.md b/courses/foundry/1-foundry-simple-storage/11-compile-a-smart-contract-using-foundry/+page.md new file mode 100644 index 000000000..6b820ad04 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/11-compile-a-smart-contract-using-foundry/+page.md @@ -0,0 +1,29 @@ +--- +title: Compile a smart contract using Foundry +--- + +_Follow along with this video:_ + +--- + +### Compiling Smart Contracts: A Guide to the Foundry Console Compilation Process + +Open a new terminal. Type in `forge build` or `forge compile` to compile the smart contracts in your project. + +Once the compiling is finished, you'll see some new folders in the Explorer tab on the left side. One of them is a folder called `out`. Here you'll be able to find the [ABI](https://docs.soliditylang.org/en/latest/abi-spec.html) of the smart contract together with the [Bytecode](https://www.geeksforgeeks.org/introduction-to-bytecode-and-opcode-in-solidity/) and a lot of useful information. + +The `cache` folder also appears. Generally, this folder is used to store temporary system files facilitating the compilation process. But for this course, you can safely ignore it. + +### More terminal wizardry + +Throughout your solidity development/audit journey you will type a lot of terminal commands, every time to make a change that you want tested you'll probably have to rerun the `forge build` then maybe you test it with `forge test` or run a script with `forge script` and many more. Typing all these over and over again is inefficient and time-consuming. The better way is to use the `up` and `down` arrow keys. Type the following commands: + +``` +echo "I like Foundry" +echo "I love Cyfrin" +echo "Auditing is great" +``` + +Now press the `up` and `down` arrow keys to cycle through the 3 commands. + +Ok, cool! We learned how to compile a contract, but how does one deploy a smart contract? \ No newline at end of file diff --git a/courses/foundry/1-foundry-simple-storage/12-deploy-a-smart-contract-locally-using-ganache/+page.md b/courses/foundry/1-foundry-simple-storage/12-deploy-a-smart-contract-locally-using-ganache/+page.md new file mode 100644 index 000000000..bc9d5ae7c --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/12-deploy-a-smart-contract-locally-using-ganache/+page.md @@ -0,0 +1,93 @@ +--- +title: Deploy a smart contract locally using Ganache +--- + +_Follow along with this video:_ + + +### Deploying a smart contract + +There are multiple ways and multiple places where you could deploy a smart contract. + +While developing using the Foundry framework the easiest and most readily available place for deployment is Anvil. + +Anvil is a local testnet node shipped with Foundry. You can use it for testing your contracts from frontends or for interacting over RPC. + +To run Anvil you simply have to type `anvil` in the terminal. + +::image{src='/foundry-simply-storage/10-deploy-a-smart-contract-locally-using-ganache/Image1.PNG' style='width: 75%; height: auto;'} + +You now have access to 10 test addresses funded with 10_000 ETH each, with their associated private keys. + +This testnet node always listens on `127.0.0.1:8545` this will be our `RPC_URL` parameter when we deploy smart contracts here. More on this later! + +More info about Anvil is available [here](https://book.getfoundry.sh/reference/anvil/). + +Please press `Ctrl/CMD + C` to close Anvil. + +Anvil will be used throughout the course to deploy and test our smart contracts, but before that, let's quickly check an intermediary step. + +### Ganache + +_Ganache is a glaze, icing, sauce, or filling for pastries usually made by heating equal parts weight of cream and chopped chocolate, warming the cream first, then pouring it over the chocolate._ + +Wait, not that ganache! The other ganache: + +Ganache is a personal blockchain for rapid Ethereum and Filecoin distributed application development. You can use Ganache across the entire development cycle; enabling you to develop, deploy, and test your dApps in a safe and deterministic environment. + +Better! + +Please download Ganache from [here](https://archive.trufflesuite.com/ganache/). + +For people using Windows WSL please read [this](https://github.com/Cyfrin/foundry-simple-storage-f23?tab=readme-ov-file#windows-wsl--ganache). Using Ganache in this environment is not the easiest thing to do. We are not going to use this in the future, so don't worry if you can't configure it properly. + +Hit `Quickstart Ethereum`. Voila! A brand new blockchain. We get some addresses, that have balances and private keys. + +### Configuring MetaMask + +To deploy to a custom network (like your localhost), you'll need MetaMask. MetaMask is a popular cryptocurrency wallet and browser extension that allows users to interact with the Ethereum blockchain and its ecosystem. If you don't have it download it from [here](https://metamask.io/download/) + +Follow these steps: + +1. Open MetaMask. + +2. Click the three little dots and select 'Expand View'. + +3. Go to 'Settings', then 'Networks'. + +4. Here, you'll see the list of networks (Ethereum, Mainnet, etc.) with plenty of details about each one. Locate the RPC URL - this is key. + +The RPC URL is essentially the endpoint we make API calls to when sending transactions. For every blockchain transaction you execute, you're making an API to whatever is in here. +To send a transaction to your custom blockchain, you need to add it as a network: + +1. Click on 'Add a Network' + +2. Scroll to the bottom of the list of networks. + +3. Hit 'Add a Network manually'. + +4. Enter the details of your local network + + Network name: `Localhost` + + New RPC URL: Ganache`http://127.0.0.1:7545` or Anvil `http://127.0.0.1:8545` (make sure you always add `http://`) - these two could differ on your machine, please consult the Ganache UI or Anvil terminal for the exact RPC URL. + + Chain ID: Ganache `5777`(sometimes `1337`) or Anvil `31337` - these two could differ on your machine, please consult the Ganache UI or Anvil terminal for the exact Chain ID. + + Currency symbol: ETH + + Block explorer URL: - (we don't have a block explorer for our newly created blockchain, which will most likely disappear when we close the VS Code / Ganache app) + +Great! Now that we configured our local network, the next step is to add one of the accounts available in Ganche or Anvil into our MetaMask. [This is done as follows](https://support.metamask.io/hc/en-us/articles/360015489331-How-to-import-an-account#h_01G01W07NV7Q94M7P1EBD5BYM4): + +1. Click the account selector at the top of your wallet. + +2. Click `Add account or hardware wallet`. + +3. Click `Import account` + +4. You will be directed to the Import page. Paste your Ganache/Anvil private key. Click `Import`. + +**NOTE: Do not use this account for anything else, do not interact with it or send things to it on mainnet or any other real blockchain, use it locally, for testing purposes. Everyone has access to it.** + +Next up we shall talk more about adding a new network to MetaMask. diff --git a/courses/foundry/1-foundry-simple-storage/13-how-to-add-a-new-network-to-metamask/+page.md b/courses/foundry/1-foundry-simple-storage/13-how-to-add-a-new-network-to-metamask/+page.md new file mode 100644 index 000000000..2e69eac1b --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/13-how-to-add-a-new-network-to-metamask/+page.md @@ -0,0 +1,24 @@ +--- +title: How to add a new network to Metamask +--- + +_Follow along with this video:_ + +--- + +### Adding New Networks Using MetaMask + +Conveniently, MetaMask provides an easy way to add EVM-compatible chains. By pre-configuring a host of them, you can add a chain such as the Arbitrum One by simply clicking on the `Networks` button on the top left, then `Add Network` and proceeding to `Add`. The pleasing part is that MetaMask does all the grunt work, filling in all the necessary information for you. A click on Approve Network ensures the successful addition of the network. + +Steps: + +1. Click on the Networks button on the top left +2. Click on Add Network +3. Choose your desired EVM-compatible chain +4. Click on Add +5. After ensuring all necessary information is already filled in, click on Approve Network + +But what can you do if the chain you want to add is not pre-configured? + +Simple! You employ the same process we just used to add our new Ganache local chain in the [previous lesson](https://updraft.cyfrin.io/courses/foundry/foundry-simple-storage/deploy-smart-contract-locally) + diff --git a/courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-forge/+page.md b/courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-forge/+page.md new file mode 100644 index 000000000..ab3a762ce --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/14-deploy-a-smart-contract-locally-using-forge/+page.md @@ -0,0 +1,88 @@ +--- +title: Deploy a smart contract locally using Forge +--- + +_Follow along with this video:_ + +--- + +### Deploying to a local blockchain + +To find out more about forge's capabilities type + +``` +forge --help +``` + +Out of the resulting list, we are going to use the `create` command. + +Type `forge create --help` in the terminal or go [here](https://book.getfoundry.sh/reference/forge/forge-create) to find out more about the available configuration options. + +Try running `forge create SimpleStorage`. It should fail because we haven't specified a couple of required parameters: + +1. `Where do we deploy?` + +2. `Who's paying the gas fees/signing the transaction?` + +Let's tackle both these questions. + +As you've learned in the previous lessons, each blockchain (private or public) has an RPC URL (RPC SERVER) that acts as an endpoint. When we tried to deploy our smart contract, forge tried to use `http://localhost:8545/`, which doesn't host any blockchain. Thus, let's try to deploy our smart contract specifying the place where we want to deploy it. + +Please start Ganache and press `Quickstart Ethereum`. Copy the RPC Server `HTTP://127.0.0.1:7545`. Let's run our forge create again specifying the correct rpc url. + +``` +forge create SimpleStorage --rpc-url http://127.0.0.1:7545 +``` + +This again failed, indicating the following: + +``` +Error accessing local wallet. Did you set a private key, mnemonic or keystore? +``` + +Try the following command: + +``` +forge create SimpleStorage --rpc-url http://127.0.0.1:7545 --interactive +``` + +You will be asked to enter a private key, please paste one of the private keys available in Ganache. When you paste a key you won't see the text or any placeholder symbols, just press CTRL(CMD) + V and then ENTER. + +Voila! + +::image{src='/foundry-simply-storage/12-deploy-a-smart-contract-locally-using-forge/Image1.PNG' style='width: 75%; height: auto;'} + +You can go to Ganache and check the `Blocks` and `Transactions` tabs to see more info about what you just did. + +From now on, everything we deploy shall be done on Anvil. But if you like Ganache more, feel free to use that. + +Do the following: + +1. Run `clear` +2. Run `anvil` +3. Create a new terminal by pressing the `+` button +4. Copy one of the private keys from the anvil terminal +5. Run `forge create SimpleStorage --interactive` + We don't need to specify an `--rpc-url` this time because forge defaults to Anvil's RPC URL. +6. Go to the Anvil terminal and check the deployment details: + +``` + Transaction: 0x40d2ca8f0d680f098c7d5e3c127ef1ce1207ef439ba6e163c2042483e15998a6 + Contract created: 0x5fbdb2315678afecb367f032d93f642f64180aa3 + Gas used: 357076 + + Block Number: 1 + Block Hash: 0x85a56c0b8f166e86d1cce65412615e0d9a72972e04b2488023275131ea27330a + Block Time: "Mon, 15 Apr 2024 11:50:55 +0000" + +``` + +The more explicit way to deploy using `forge create` is as follows: + +``` +forge create SimpleStorage --rpc-url http://127.0.0.1:8545 --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +``` + +We included the `--rpc-url` to not count on the default and the `--private-key` to not use the `--interactive` option anymore. + +Pfew! That was a lot, but we learned a very important thing, how to deploy a smart contract on two local blockchains. But what comes next is one of the most important if not the **_MOST IMPORTANT_** aspects you will learn here: **_Private key safety_** diff --git a/courses/foundry/1-foundry-simple-storage/15-important-private-key-safety-pt-1/+page.md b/courses/foundry/1-foundry-simple-storage/15-important-private-key-safety-pt-1/+page.md new file mode 100644 index 000000000..45cf0530f --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/15-important-private-key-safety-pt-1/+page.md @@ -0,0 +1,43 @@ +--- +title: Important - private key safety pt.1 +--- + +_Follow along with this video:_ + +--- + +### Practicing Private Key Safety + +Having a private key in plain text is extremely bad. The private key(s) we used in the last lesson are well-known keys for local testing, you shouldn't use those on mainnet and keeping them in plain text is ok, but any other private key should be kept hidden, especially your production key or key's associated with accounts that hold crypto. + +Moreover, it's very bad to have private keys in bash history (hit the up arrow and see the key you used to deploy). + +You can delete your history by typing: + +``` +history -c +``` + +We will teach you more about how to secure private keys in one of the next lessons. + +### Your Safety Promise + +It's time now to articulate your promise for maintaining private key safety. Create a file titled `Promise.md`. In this file, make it a point to write down your promise: + +``` +I promise to never use my private key associated with real money in plain text. +``` + +If you feel comfortable doing so, consider tweeting this to affirm and secure your pledge. Make sure to tag [@PatrickAlphaC](https://twitter.com/PatrickAlphaC) and [@CyfrinUpdraft](https://twitter.com/CyfrinUpdraft) or any other professional in this field to hold yourself accountable. + +Hacking private keys is one of the most important reasons people and projects lose absurd amounts. You don't even need to look that deep to find titles like this: + +[The Ronin hack](https://www.halborn.com/blog/post/explained-the-ronin-hack-march-2022) - Social engineering of private keys + +[Early Crypto Investor Bo Shen Says He Lost $42 Million in Wallet Hack](https://www.bnnbloomberg.ca/early-crypto-investor-bo-shen-says-he-lost-42-million-in-wallet-hack-1.1850446) + +[The \$477 million FTX hack](https://www.elliptic.co/blog/the-477-million-ftx-hack-following-the-blockchain-trail) where `The new CEO of FTX revealed that private keys allowing access to the firm’s crypto assets were stored in unencrypted form, and a former employee disclosed that over $150 million was stolen from Alameda Research, due to poor security. ` + +Don't be like that! Maybe you are not holding millions, but what you hold is yours, don't let it become theirs! + +In the following lessons, we'll learn how to access RPC URLs for free using Alchemy for any blockchain. We will also delve into exploring safer methodologies for dealing with private keys. Stay tuned! diff --git a/courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-anvil/+page.md b/courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-anvil/+page.md new file mode 100644 index 000000000..f3106f2ce --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/16-deploy-a-smart-contract-locally-using-anvil/+page.md @@ -0,0 +1,187 @@ +--- +title: Deploy a smart contract locally using Anvil +--- + +_Follow along with this video:_ + +--- + +### Deploy a smart contract locally using Anvil via scripts + +Deploying a smart contract via scripting is particularly handy because it provides a consistent and repeatable way to deploy reliably and its features enhance the testing of both the deployment processes and the code itself. + +There's a strong chance that you like the command-line approach, but scripting enriches the whole deployment process, bringing in more functionality and an ease of use second to none. + +Foundry eases the whole process since it is written in Solidity. This means our deployment scripts will also be written in Solidity. It is essential to distinguish Solidity as a contract language from Solidity as a scripting language. Foundry also incorporates elements that enhance our Solidity experience beyond the smart contracts realm. So, let's get started on creating a script to deploy our simple storage contract. + +In Foundry we keep our scripts in the `script` folder. + +Please create a new file called `DeploySimpleStorage.s.sol`. + +Using `.s.sol` as a suffix is a naming convention for Foundry scripts, in future lessons, when we'll write Foundry tests, these will bear the suffix of `.t.sol`. + +For more best practice info regarding Foundry scripts please click [here](https://book.getfoundry.sh/tutorials/best-practices#scripts). + +Open the newly created file. Here we'll write a solidity script for deploying our SimpleStorage contract. + +Type the following: + +```solidity +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +contract DeploySimpleStorage { + +} +``` + +The first two lines are pretty self-explanatory. + +We declare the new contract, named `DeploySimpleStorage` + +For it to be considered a Foundry script and to be able to access the extended functionality Foundry is bringing to the table we need to import `Script` from `"forge-std/Script.sol"` and make `DeploySimpleStorage` inherit `Script`. + +**NOTE**: `forge-std` also called Forge Standard Library is a collection of pre-written Solidity contracts designed to simplify and enhance scripting and testing within the Foundry development framework. + +Furthermore, to be able to deploy `SimpleStorage` we also need to import it by typing `import {SimpleStorage} from "../src/SimpleStorage.sol";` + +```solidity +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import {Script} from "forge-std/Script.sol"; +import {SimpleStorage} from "../src/SimpleStorage.sol"; + +contract DeploySimpleStorage is Script { + +} +``` + +Every script needs a main function, which, according to the best practice linked above is called `run`. Whenever you run `forge script` this is the function that gets called. + +```solidity +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +import {Script} from "forge-std/Script.sol"; +import {SimpleStorage} from "../src/SimpleStorage.sol"; + +contract DeploySimpleStorage is Script { + function run() external returns (SimpleStorage) { + vm.startBroadcast(); + + SimpleStorage simpleStorage = new SimpleStorage(); + + vm.stopBroadcast(); + return simpleStorage; + } +} +``` +`run` is an external function that will return the `SimpleStorage` contract. + +In the Run function, we are going to use a distinctive keyword: `vm`. Foundry has a distinctive feature known as cheat codes. The `vm` keyword is a cheat code in Foundry, and thereby only works in Foundry. + +`vm.startBroadcast` indicates the starting point for the list of transactions that get to be sent to the `RPC URL`; + +Similarly, `vm.stopBroadcast` indicates the ending point of the list of transactions that get to be sent to the `RPC URL`; + +Between those two we write: + +`SimpleStorage simpleStorage = new SimpleStorage();` + +The `new` keyword is used to create a new smart contract in Solidity. + +We end the function with `return simpleStorage;`. + +Please select the `Anvil` terminal and press `CTRL(CMD) + C` to stop it. Now run the following command: + +```bash +forge script script/DeploySimpleStorage.s.sol +``` + +This should go through without any errors, but if you hit some errors related to `incompatible solidity versions in various files` please ensure that both the `SimpleStorage.sol` and `DeploySimpleStorage.s.sol` use `pragma solidity 0.8.19;` + +If you want to further extend your knowledge about scripting please go [here](https://book.getfoundry.sh/tutorials/solidity-scripting?highlight=scr#solidity-scripting) + +You should get the following output: + +```text +[⠆] Compiling... +[⠔] Compiling 2 files with 0.8.19 +[⠒] Solc 0.8.19 finished in 1.08s +Compiler run successful! +Script ran successfully. +Gas used: 338569 + +== Return == +0: contract SimpleStorage 0x90193C961A926261B756D1E5bb255e67ff9498A1 + +If you wish to simulate on-chain transactions pass a RPC URL. +``` + +**The million-dollar question**: If we didn't pass an RPC URL, where did this deploy to? + +If the RPC URL is not specified, Foundry automatically launches an Anvil instance, runs your script (in our case deployed the contract) and then terminates the Anvil instance. + +Run the `anvil` command in the terminal, open up a new terminal and type the following: + +```bash +forge script script/DeploySimpleStorage.s.sol --rpc-url http://127.0.0.1:8545 +``` + +To get the following output: + +```text +No files changed, compilation skipped +EIP-3855 is not supported in one or more of the RPCs used. +Unsupported Chain IDs: 31337. +Contracts deployed with a Solidity version equal or higher than 0.8.20 might not work properly. +For more information, please see https://eips.ethereum.org/EIPS/eip-3855 +Script ran successfully. + +== Return == +0: contract SimpleStorage 0x34A1D3fff3958843C43aD80F30b94c510645C316 + +## Setting up 1 EVM. + +========================== + +Chain 31337 + +Estimated gas price: 2 gwei + +Estimated total gas used for script: 464097 + +Estimated amount required: 0.000928194 ETH + +========================== + +SIMULATION COMPLETE. To broadcast these transactions, add --broadcast and wallet configuration(s) to the previous command. See forge script --help for more. +``` + +**Another million-dollar question**: Is it deployed now? + +Answer: No, the output indicates this was a simulation. But, we got a new folder out of this, the `broadcast` folder contains information about different script runs in case we forget details. + +Hit the up arrow key and add `--broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80` at the end. + +Our contract is now successfully deployed! Fantastic! + +Switch to the `anvil` terminal where you'll see: + +```text + Transaction: 0x73eb9fb4ef7b159e03c50d669c42e2ec4eeaa9358bea0a710cb07168e5192570 + Contract created: 0x5fbdb2315678afecb367f032d93f642f64180aa3 + Gas used: 357088 + + Block Number: 1 + Block Hash: 0x8ea564f146e04bb36fc27f0b491223a023b5882d2fcfce3ff85e0dd152e611e4 + Block Time: "Tue, 16 Apr 2024 13:39:51 +0000" +``` + +Awesome! + +Through this lesson we kept talking about a thing called `transaction`, but what is a `transaction`? Tune in the next lesson to find out. diff --git a/courses/foundry/1-foundry-simple-storage/17-what-is-a-transaction/+page.md b/courses/foundry/1-foundry-simple-storage/17-what-is-a-transaction/+page.md new file mode 100644 index 000000000..2ae821403 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/17-what-is-a-transaction/+page.md @@ -0,0 +1,56 @@ +--- +title: What is a transaction +--- + +_Follow along with this video:_ + +--- + +### More about blockchain transactions + +In the previous lesson we kept talking about transactions, but we never explained what a transaction is. In simple terms, a transaction captures details of an activity that has taken place on a blockchain. + +On the left side of your screen, in the Explorer tab, you'll find a folder called `broadcast`. Foundry saves all your blockchain interactions here. The `dry-run` folder is used for interactions you made when you didn't have a blockchain running (remember that time when we deployed our contract without specifying an `--rpc-url`). Moreover, the recordings here are separated by `chainId`. + +**Note**: The `chainId` is a unique identifier assigned to a specific blockchain network. It is used to distinguish one blockchain from another and is a crucial parameter for ensuring the security and integrity of transactions and interactions on the blockchain. + +Click on `run-latest.json`. +Here we can find more details about the last deployment script we ran in our previous lesson. It will show things like `transactionType`, `contractName` and `contractAddress`. Moreover, in the `transaction` section, you can see what we actually sent over to the RPC URL: + +```javaScript + "transaction": { + "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "to": null, + "gas": "0x714e1", + "value": "0x0", + "input": "0x608060...c63430008130033", + "nonce": "0x0", + "chainId": "0x7a69", + "accessList": null, + "type": null + } +``` + +Let's go through each of these: + +- `from` is self-explanatory, it's the address we used to sign the transaction; +- `to` is the recipient, in our case is null or address(0), this is the standard destination for when new smart contracts are deployed; +- `gas` is the amount of gas spent. You will see the hex value `0x714e1` (or any other value represented in hex format); + +**Quick tip**: Normal humans can't understand hex values like the one indicated above, but there's a quick way to convert these into usual numbers. Run the following command in your terminal: `cast --to-base 0x714e1 dec`. `cast` is a very versatile tool provided by Foundry, type `cast --help` in your terminal to find out more, or go [here](https://book.getfoundry.sh/reference/cast/cast). + +- `value` is the transaction value, or the amount of ETH we are sending over. Given that this transaction was made to deploy a contract, the value here is `0x0` or `0`, but we could have specified a value and that would have been the initial balance of the newly deployed contract; + +- `data` in this case is the contract deployment code and the contract code. In the excerpt above this was truncated; + +- `nonce` is a unique identifier assigned to each transaction sent from a specific account. The nonce is used to ensure that each transaction is processed only once and to prevent replay attacks. `nonce` is incremented with every single transaction; + +- `accessList` is a feature of Ethereum to optimize the gas cost of transactions. It contains a list of addresses and associated storage keys that the transaction is likely to access, allowing the EVM to more efficiently compute the gas cost of storage access during the transaction's execution; + +- `type` please ignore this for now. + +There are other values that play an important part that weren't presented in that list, namely the `v`, `r`, and `s`. These are components of a transaction's signature, which are used to validate the authenticity and integrity of the transaction. + +Whenever we send a transaction over the blockchain there's a signature happening, that's where we use our `private key`. + +**Important:** Every time you change the state of the blockchain you do it using a transaction. The thing that indicates the change is the `data` field of a transaction. Deployment bytecode, contract bytecode and OPCODEs will be tackled in a future lesson. diff --git a/courses/foundry/1-foundry-simple-storage/18-important-private-key-safety-pt-2/+page.md b/courses/foundry/1-foundry-simple-storage/18-important-private-key-safety-pt-2/+page.md new file mode 100644 index 000000000..251c30c62 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/18-important-private-key-safety-pt-2/+page.md @@ -0,0 +1,53 @@ +--- +title: Important - private key safety pt.2 +--- + +_Follow along with this video:_ + +--- + +### How to not have your private key in the command line + +Some lessons ago we deployed `SimpleStorage` using the following command: + +``` +forge script script/DeploySimpleStorage.s.sol --rpc-url http://127.0.0.1:8545 --broadcast --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +``` + +Having our private key in plain text is very bad, as we've explained in [Lesson 13](https://updraft.cyfrin.io/courses/foundry/foundry-simple-storage/private-key-safety). What can we do to avoid this, except using the `--interactive` parameter, because we don't want to keep copy-pasting our private key? + +**BIG BOLDED DISCLAIMER: What we are about to do is fine for development purposes, do not put a real key here, it very terrible for production purposes.** + +Create a new file in the root of your project called `.env`. Then, go the `.gitignore` file and make sure `.env` is in there. + +The `.env` file will host environment variables. Variables that are of a sensitive nature that we don't want to expose in public. + +Open the file and put the following in it: + +``` +PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 +RPC_URL=http://127.0.0.1:8545 +``` + +Next run `source .env`. This adds the above-mentioned environment variables into our shell. Now run `echo $PRIVATE_KEY` or `echo $RPC_URL` to check if the values are stored in the shell. + +Now we can safely replace the parameters in our `forge script` command: + +``` +forge script script/DeploySimpleStorage.s.sol --rpc-url $RPC_URL --broadcast --private-key $PRIVATE_KEY +``` + +This doesn't only hide your private key from plain sight in the command line but also facilitates faster terminal usage, imagine you'd have to copy-paste the `http://127.0.0.1:8545` RPC URL over and over again. It's cleaner this way. + +But yes, now we have the private key in plain text in the `.env` file, that's not good. + +### How to handle this problem with production code? + +Foundry has a very nice option called `keystore`. To read more about it type `forge script --help` in your terminal. Using `forge script --keystore ` allows you to specify a path to an encrypted store file, encrypted by a password. Thus your private key would never be available in plain text. + +Let's agree to the following: + +1. For testing purposes use a `$PRIVATE_KEY` in an `.env` file as long as you don't expose that `.env` file anywhere. +2. Where real money is involved use the `--interactive` option or a [keystore file protected by a password](https://github.com/Cyfrin/foundry-full-course-f23?tab=readme-ov-file#can-you-encrypt-a-private-key---a-keystore-in-foundry-yet). + +There's one more thing about storing keys in a `.env` file. Please take a look at the ["THE .ENV PLEDGE"](https://github.com/Cyfrin/foundry-full-course-f23/discussions/5). Read it, understand it and comment `I WILL BE SAFE`. Tweet it, Tiktok it, blog about it, make an Insta story about it, print it and put it on your fridge and share some copies with your neighbors. Please stay safe! diff --git a/courses/foundry/1-foundry-simple-storage/19-never-use-a-env-file/+page.md b/courses/foundry/1-foundry-simple-storage/19-never-use-a-env-file/+page.md new file mode 100644 index 000000000..266369548 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/19-never-use-a-env-file/+page.md @@ -0,0 +1,44 @@ +--- +title: Never Use A Env File +--- + +_Follow along with this video:_ + +--- + +### Meanwhile, some things have changed + +In our previous lesson, we showed you how to configure and use a `.env` file to hold your private key and rpc url, some developments have taken place since that lesson was made so ... You should never use a `.env` again. + +### Encrypting your Keys Using ERC2335 + +For now, let's pretend our private key is this: + +`0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80` (key 0 from Anvil) + +Type the following command in your terminal: +``` +cast wallet import nameOfAccountGoesHere --interactive +``` + +Ideally, you don't do this in your VS Code. + +You will be asked for your private key and a password to secure it. You will do this only once, which is amazing! + +If you remember, last lesson we deployed running the following command: +``` +forge script script/DeploySimpleStorage.s.sol --rpc-url $RPC_URL --broadcast --private-key $PRIVATE_KEY +``` + +Now that we configured our wallet we can deploy as following: + +``` +forge script script/DeploySimpleStorage.s.sol --rpc-url http://127.0.0.1:8545 --broadcast --account nameOfAccountGoesHere --sender 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 +``` +You will be asked for your password. You won't be able to deploy without your password. + +To see all the configured wallets you can call the following: `cast wallet list`. + +Clear your history so your private key won't randomly remain there using the following command: `history -c`. + +***Stay safe! Stay froggy! Don't lose your keys. If you are seeing your private key in plain text, you are doing something wrong.*** diff --git a/courses/foundry/1-foundry-simple-storage/20-interact-with-a-smart-contract-using-the-cli/+page.md b/courses/foundry/1-foundry-simple-storage/20-interact-with-a-smart-contract-using-the-cli/+page.md new file mode 100644 index 000000000..308709c7c --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/20-interact-with-a-smart-contract-using-the-cli/+page.md @@ -0,0 +1,64 @@ +--- +title: Interact with a smart contract using the CLI +--- + +_Follow along with this video:_ + +--- + +### Interacting With Contract Addresses via Command Line & Foundry's Cast Tool + +This lesson builds on top of previous lessons where we deployed `SimpleStorage` via `forge script`. We have `Anvil` running and the smart contract is deployed. + +Copy the contract address. + +### Sending information to the blockchain + +Foundry has a built-in tool known as `Cast`. `Cast` comes loaded with numerous commands to interact with. Learn more about them by typing `cast --help`. One such useful command is `send` which is designed to sign and publish a transaction. To view help about `send`, type `cast send --help`. + +To use `send` we need a signature and some arguments. + +Please call the following in your terminal: + +**Note**: Down below use the address you copy-pasted from your terminal, there's a chance it will be different than the one mine was deployed. + +``` +cast send 0x5FbDB2315678afecb367f032d93F642f64180aa3 "store(uint256)" 1337 --rpc-url $RPC_URL --private-key $PRIVATE_KEY +``` + +**What did we just do?** + +Let's break it down: +- `cast send` is the command we used to sign and publish our transaction; +- `0x5FbDB2315678afecb367f032d93F642f64180aa3` or any other address is the target of our `cast send`, the contract we are interacting with; +- `"store(uint256)"` is the [signature of the function](https://ethereum.stackexchange.com/questions/135205/what-is-a-function-signature-and-function-selector-in-solidity-and-evm-language) we are calling. +- `1337` is the number we pass to the `store` function. As we can see in the function signature, we are expected to provide an `uint256` input. You can obviously provide any number you want, as long as it fits `uint256`. +- you already know what `--rpc-url $RPC_URL --private-key $PRIVATE_KEY` are. The place where we send and the private key we use to sign. + +### Reading information from the blockchain + +`cast` conveniently provides a way to read information stored on the blockchain. Type `cast call --help` in your terminal to find out more. It works similarly to `send`, where you have to provide a signature and some arguments. The difference is you are only peering into the storage, not modifying it. + +Call the following command in your terminal: + +``` +cast call 0x5FbDB2315678afecb367f032d93F642f64180aa3 "retrieve()" +``` + +We receive back the following: +``` +0x0000000000000000000000000000000000000000000000000000000000000539 +``` +This represents a hex value. In the previous lessons, we learned how to convert this to a normal number. + +Type the following command in your terminal: +``` +cast --to-base 0x0000000000000000000000000000000000000000000000000000000000000539 dec +``` +And surprise, surprise, `1337` came back. + +I recommend you play around and send multiple transactions with different numbers and then read them from the blockchain. + +Awesome! We've learned something very valuable. You are going to use this more times than you can count. + +**Up next:** Deploying a smart contract on Sepolia diff --git a/courses/foundry/1-foundry-simple-storage/21-deploying-to-a-testnet/+page.md b/courses/foundry/1-foundry-simple-storage/21-deploying-to-a-testnet/+page.md new file mode 100644 index 000000000..ef4e1332d --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/21-deploying-to-a-testnet/+page.md @@ -0,0 +1,56 @@ +--- +title: Deploying to a Testnet +--- + +_Follow along the course with this video._ + + + +--- + +## Deploying our Contract to Testnet or Live Network with Foundry and Alchemy + +Hi, everyone! Are you curious about what your contract would look like on a testnet or a live network? If so, buckle up because this blog post will cover exactly that! We'll walk through the process of updating our Environment Variable (.env) file for an actual testnet. + +Clearly, we need an actual testnet for a real network. But our trusty MetaMask has built-in Infura connections that are incompatible. Why? Because they're tailored specifically for MetaMask. Hence, we need our own Remote Procedure Call (RPC) URL. + +## Creating our Own RPC URL for a Testnet + +_To create one, we could run our own blockchain node, but let's be honest — many folks prefer avoiding that route. Instead, we utilize Node as a Service (NaaS) applications to expedite the process._ + +One promising option is using Alchemy - a free NaaS platform that we can send the transactions to. This procedure resides within the _Deploying to Testnet or Mainnnet_ section in the full course repo of the Foundry. + +::image{src='/foundry/19-testnet-deploy/testnet1.png' style='width: 100%; height: auto;'} + +To access the Alchemy platform, we simply click on the aforementioned function. On the platform, we sign up (I used Google sign-in for this demo). + +Our next step is creating a new app in the Alchemy user interface. I named mine _Sepolia Testing_ and kept the description the same, given that our chain will be an Ethereum one based on Ethiopia. + +We can bypass advanced features for now and finalize our app. Now we have the app details needed for our node, including frequency of calls and other details. We also have a new https endpoint by clicking view key, which functions exactly the same way as our ganache or MetaMask endpoint. + +## Altering our Private Key + +Next, let's do something about our private keys. Our ganache private key will no longer cut it — it has neither real money nor any testnet ETH in it. + +Our solution is to use one of our MetaMask private keys. To do this, we switch back to Sepolia in our MetaMask, choose an account with money in it, click on account details, and export the private key. _Remember, never share your real private key!_ + +Upon confirmation with your password, copy the private key and omit the line in the env file — hashtag or pound sign denoting comments. + +## Executing the Transaction + +With our Sepolia RPC URL and private key from MetaMask, executing a transaction now becomes tremendously easier. + +```bash +source .env +forge script script/deploySimpleStorage.s.sol --rpc-url=$Sepolia_RPC_URL --private-key=$PRIVATE_KEY --broadcast +``` + +This command deploys our contract to the testnet, and we can monitor the transaction on our Alchemy dashboard. + +We soon find that our contract, Simple Storage, has been deployed on the Sepolia chain. We can grab our transaction hash and input it into Sepolia etherscan IO to confirm the successful transaction. + +After we refresh our Alchemy dashboard, we'll verify the requests sent and track the ETH send raw transaction that transmitted our transaction to the blockchain. + +So, this is how we deploy our contract on a real testnet leveraging Foundry and Alchemy! + +Our next step will explore adding real-world components to the mix. Stay tuned! diff --git a/courses/foundry/1-foundry-simple-storage/22-verify-a-smart-contract-on-etherscan/+page.md b/courses/foundry/1-foundry-simple-storage/22-verify-a-smart-contract-on-etherscan/+page.md new file mode 100644 index 000000000..bd2ca42c5 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/22-verify-a-smart-contract-on-etherscan/+page.md @@ -0,0 +1,43 @@ +--- +title: Verify a smart contract on Etherscan +--- + +_Follow along with this video:_ + +--- + +### Manually verify a smart contract on Etherscan + +Soooo ... we just deployed our smart contract on Sepolia, let's check it out! + +We go [here](https://sepolia.etherscan.io/address/0x1093560Fe9029c4fB9044AbF2fC94288970D98Db#code) click on `Contract` and find this: + +::image{src='/foundry-simply-storage/21-verify-a-smart-contract-on-etherscan/Image1.PNG' style='width: 75%; height: auto;'} + +This bytecode looks horrendous. We need to do something to improve the readability (which currently is non-existent). + +Etherscan is prompting us to do something about it via the message: `Are you the contract creator? Verify and Publish your contract source code today!` + +So, let's click on `Verify and Publish`. + +The address of the Contract comes prepopulated, if not please paste it from your terminal. + +Select `Solidity(Single file)` because we are using solidity and we have only one file. + +Select your Compiler Version. My contract used solidity 0.8.19. + +The license type we used is MIT. + +On the next page, paste your Solidity Contract. Select `Yes` in `Optimization`, and leave everything else as is. + +Finish up the `verify` process. If you get this message: + +``` +Successfully generated Bytecode and ABI for Contract Address [0x1093560Fe9029c4fB9044AbF2fC94288970D98Db] +``` + +you did it right! + +Now you have access to the `Read Contract` and `Write Contract`. This lets you interact directly with your contract through etherscan. + +Congratz! You just learned how to verify a smart contract on etherscan, the manual way. This is not the ideal way, in the future, we will teach you how to verify them programmatically. diff --git a/courses/foundry/1-foundry-simple-storage/23-cleaning-up-the-project/+page.md b/courses/foundry/1-foundry-simple-storage/23-cleaning-up-the-project/+page.md new file mode 100644 index 000000000..7a00e1b6a --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/23-cleaning-up-the-project/+page.md @@ -0,0 +1,62 @@ +## Cleaning Up the Project + +We've covered a lot of ground in this project. We learned how to write our first Solidity contract, how to deploy it to a test network, and how to interact with it using Forge. Before we move on to more complex projects, let's take a moment to clean things up and make sure our project is well-organized. + +### Formatting + +One important aspect of any project is consistency in formatting. We've been using VS Code's auto-formatter to help us with this, but it's important to make sure that anyone else working on the project is following the same formatting rules. + +Forge has a built-in format command that we can use to ensure consistent formatting across the project. We can run this command in our terminal with: + +```bash +forge fmt +``` + +This command will automatically format all our Solidity files according to Forge's default style. + +### README.md + +Another important file to include in any project is a `README.md` file. This file serves as a guide for anyone who wants to learn about your project, how to use it, or how to contribute to it. + +The `README.md` file is written in Markdown, which is a lightweight markup language that's easy to read and write. + +Here's an example of what you might include in your `README.md` file: + +````markdown +# SimpleStorage + +This is a simple Solidity contract that stores a single uint256 value. + +## Getting Started + +1. Clone this repository. +2. Install Forge using the instructions found at [https://github.com/foundry-rs/foundry](https://github.com/foundry-rs/foundry). +3. Run the following command to compile the contract: + +```bash +forge build +``` + +4. Run the following command to deploy the contract to a test network: + +```bash +forge create +``` + +5. Interact with the contract using Forge's interactive console. + +```bash +forge console +``` + +## Contributing + +We welcome contributions to this project. If you're interested in contributing, please open an issue or submit a pull request. +``` +We can preview our `README.md` file in VS Code by going to the `View` menu and selecting `Open Preview to the Side`. This will open a new window showing what the `README.md` file will look like when it's rendered on GitHub. + +### Using AI for Markdown Formatting + +If you find that formatting Markdown is a bit tedious, you can use an AI tool like ChatGPT to help you out. Just copy and paste the text you want to format into ChatGPT and ask it to format it in Markdown. It will do a pretty good job of converting your plain text into Markdown, and you can then review and edit it as needed. + +```` diff --git a/courses/foundry/1-foundry-simple-storage/24-foundry-zksync/+page.md b/courses/foundry/1-foundry-simple-storage/24-foundry-zksync/+page.md new file mode 100644 index 000000000..accf8bb0f --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/24-foundry-zksync/+page.md @@ -0,0 +1,34 @@ +--- +title: Foundry ZKsync +--- + +_Follow along with the video_ + +--- + +In this lesson, we'll explore Layer 2 deployment on ZKsync, which involves a different compilation method compared to Ethereum. This difference arises because ZKsync uses unique opcodes. While Solidity code behaves similarly on both platforms, the low-level outputs generated by Foundry in the `/out` folder will not be entirely compatible with the ZKsync VM. + +### Foundry ZKsync + +To get started with ZKsync, we will follow these three steps: + +1. 🛠️ Install `foundry-zksync` +2. 🧑‍💻 Compile the Solidity contract with the `--zksync` flag +3. 🔄🏠 Reinstall the original Vanilla Foundry + +> 👀❗**IMPORTANT**:br +> Installing `foundry-zksync` will override any existing Foundry binaries, such as `forge` and `cast`. + +The GitHub resources for this course contain a link to the [Foundry ZKsync repository](https://github.com/Cyfrin/foundry-full-course-cu?tab=readme-ov-file#compiling-to-zksync-in-foundry-zksync). `foundry-zksync` is a fork of Foundry tailored for the ZKsync environment. The [repository](https://github.com/matter-labs/foundry-zksync) includes quick install instructions to help you set up the tool. + +- First, clone the Foundry ZKsync repository in a different directory from your Foundry project. Use the `git clone` command to clone the repository locally on your computer. + +- Once cloned, navigate to the created Foundry ZKsync directory and run the installation command: + + ``` + ./install-foundry-zksync + ``` + + This command requires a Unix-like environment, such as WSL on Windows, or a Mac or Linux system. After running the command, verify the installation by checking the version with `forge --version`. A different version number will indicate the successful installation of Foundry ZKsync. + +- To keep your environment flexible, you can switch to Foundry ZKsync by running `foundryup-zksync`. After using it, it's recommended to switch back to Vanilla Foundry by running the `foundryup` command. This removes ZKsync-specific flags and settings, allowing you to easily toggle between Foundry ZKsync and Vanilla Foundry as needed. diff --git a/courses/foundry/1-foundry-simple-storage/25-compiling-foundry-zksync/+page.md b/courses/foundry/1-foundry-simple-storage/25-compiling-foundry-zksync/+page.md new file mode 100644 index 000000000..9d06c5c60 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/25-compiling-foundry-zksync/+page.md @@ -0,0 +1,11 @@ +--- +title: Compiling foundry ZKsync +--- + +_Follow along with the video_ + +--- + +> Previously, when we ran the `forge build` command, it generated an `/out` folder in the root project directory. This folder contains all the compilation details related the Ethereum Virtual Machine (EVM) and Vanilla Foundry. To compile for the ZKsync chain instead, we use the command `forge build --zksync`. This command creates a new folder in our project root called `/zkout`, and contains all the compiled code compatible to the ZKsync Era VM. + +If we need to revert to vanilla Foundry for deployment on the EVM, we simply run the command `foundryup` and then use `forge build`, which builds a standard Foundry project. Unless otherwise specified, we should continue using this method. diff --git a/courses/foundry/1-foundry-simple-storage/26-zksync-local-node/+page.md b/courses/foundry/1-foundry-simple-storage/26-zksync-local-node/+page.md new file mode 100644 index 000000000..fbf8cbf1c --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/26-zksync-local-node/+page.md @@ -0,0 +1,37 @@ +--- +title: ZKsync Setting up Local Node +--- + +_Follow along with the video_ + +--- + +### Introduction + +> 👀❗**IMPORTANT**:br +> This lesson is optional. If you encounter difficulties installing or understanding the required tools, feel free to proceed to the next section and continue using Anvil to test your smart contract locally. + +In the previous lessons, we learned about deploying smart contracts with the `forge create` and `forge script` commands on our **local Anvil chain**. In this lesson, we will set up and run a **ZKsync local environment**. + +### Local Node Setup + +To deploy locally on a ZKsync local chain, you'll need additional tools: Docker, Node.js, and zksync-cli. + +1. **Docker**: Start the [Docker](https://www.docker.com/) daemon. On Mac OS, you can start it using the Docker application interface. On Linux, use commands like `sudo systemctl start docker` and `sudo systemctl stop docker` will manage Docker lifecycles. Verify the installation with `docker --version` and `docker ps` commands. + +2. **Node.js and npm**: Install [Node.js](https://nodejs.org/en) and [npm](https://www.npmjs.com/). Follow the Node.js documentation to install the right version for your operating system. Verify the installations with `npm --version` and `node --version` commands. + +3. **zksync-cli**: Once Docker and Node.js are installed, you can install the [zksync-cli](https://www.npmjs.com/package/zksync-cli) to manage your local ZKsync development environment. Run `npx zksync-cli dev config` to set up your configuration. Choose the `in-memory` node option for a quick startup without persistent state and avoid additional options like a portal or block explorer unless you want to explore them independently. + +To start your local ZKsync node, run `npx zksync-cli dev start`. This command spins up a ZKsync node in Docker and runs it in the background. Verify the process is running with `docker ps`. + +> 🗒️ **NOTE**:br +> If Docker isn’t running, the `npx zksync-cli dev start` command will fail. Ensure Docker is running before attempting to start the ZKsync node again. + +### Deployment + +The ZKsync deployment process is similar to previous deployments. We will use the same commands, but this time, we will append the `--zksync` and `--legacy` flags. Note that the `forge script` command is not well supported in ZKsync, so we will use `forge create` instead. + +### Conclusion + +Setting up a local ZKsync node involves a few additional tools, including Docker, Node.js, npm, and zksync-cli: they will help creating a robust ZKsync development environment and allowing test and deployment of smart contracts on a ZKsync local chain. diff --git a/courses/foundry/1-foundry-simple-storage/27-zksync-local-deploy/+page.md b/courses/foundry/1-foundry-simple-storage/27-zksync-local-deploy/+page.md new file mode 100644 index 000000000..2d2ea270a --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/27-zksync-local-deploy/+page.md @@ -0,0 +1,30 @@ +--- +title: ZKsync Local Deployment +--- + +_Follow along with the video_ + +--- + +In this lesson, we are going to deploy the contract `SimpleStorage.sol` on a **ZKsync local chain**. + +We start by verifying that the Forge version we are using is correct. By running the `forge --version` command it confirms that we are on version 0.2: this indicates we are using the right Foundry ZKsync edition. + +Next, we proceed with creating a `SimpleStorage` contract using the command: + +```bash +forge create src/SimpleStorage.sol:SimpleStorage --rpc_url --private_key --legacy --zksync +``` + +Here, `` represents ZKsync node address, such as `http://127.0.0.1:8011`. + +> 👀❗**IMPORTANT**:br +> Including private keys directly in commands is not a safe practice. + +This command instructs Foundry to locate the `SimpleStorage` contract in the `src/SimpleStorage.sol` file and deploy it. Upon execution, the contract compiles and deploys successfully. The output will display details such as the deployer, the deployed contract address, and the transaction hash. + +::image{src='/foundry-simply-storage/27-zksync-local-deploy/deployment-successful.png' style='width: 50%; height: auto;'} + +Using the `--legacy` flag is recommended for deploying simple contracts, while more complex codebases may require different approaches. Attempting to deploy without the `--legacy` flag might result in errors like `failed to serialize transaction, address to address is null`, which will be covered in future lessons. + +Once you are finished, you can close Docker Desktop and revert to the Vanilla Foundry environment using the `foundryup` command. diff --git a/courses/foundry/1-foundry-simple-storage/28-tx-types/+page.md b/courses/foundry/1-foundry-simple-storage/28-tx-types/+page.md new file mode 100644 index 000000000..e1565ff20 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/28-tx-types/+page.md @@ -0,0 +1,36 @@ +--- +title: Transaction Types +--- + +_Follow along with the video_ + +--- + +### Introduction + +In this lesson, we will explore the different transaction types within the ZKsync VM and EVM ecosystems. + +### `/broadcast` Folder + +When deploying to a ZKsync local node, a `/broadcast` folder will be created and it will contain detailed information about the **deployment transactions**. Inside this folder, you will find subfolders named after specific deployment chain IDs, such as **`260`** for ZKsync and **`31337`** for Anvil. These subfolders store the data of the transactions executed during the deployment process. + +By examining both the `run-latest.json` file in these folders, we can observe different **transaction types** for each transaction within a chain. For instance, transactions on the Anvil chain might be labeled as type **`0x2`**, while those on the ZKsync chain will be of type **`0x0`**. Deploying a smart contract on the EVM without the `--legacy` flag results in a default transaction type of `0x2`. Adding the `--legacy` flag changes it to type `0x0`. + +The EVM and ZKsync ecosystems support multiple transaction types to accommodate various Ethereum Improvement Proposals (EIPs). Initially, Ethereum had only one transaction type (`0x0` legacy), but as the ecosystem evolved, multiple types were introduced through various EIPs. Subsequent types include type 1, which introduces an _access list_ of addresses and keys, and type 2, also known as [EIP 1559](https://eips.ethereum.org/EIPS/eip-1559) transactions. + +> 👀❗**IMPORTANT**:br +> This `0x2` type is the current default type for the EVM. + +Additionally, ZKsync introduces its [unique transaction type](https://docs.zksync.io/zk-stack/concepts/transaction-lifecycle#eip-712-0x71), the type `113` (`0x71` in hex), which can enable features like [account abstraction](https://docs.zksync.io/build/developer-reference/account-abstraction/). + +> 💡 **TIP**:br +> The `forge script` command will work in some scenarios, but it’s not entirely clear where it might fail. For the purpose of this course, we will assume scripting does not work while working with ZKsync. + +### Resources + +- [ZKsync documentation](https://docs.zksync.io/zk-stack/concepts/transaction-lifecycle#transaction-types) about transaction types +- [Cyfrin Blog on EIP-4844](https://www.cyfrin.io/blog/what-is-eip-4844-proto-danksharding-and-blob-transactions) + +### Conclusion + +The ZKsync VM and EVM ecosystems support various transaction types to meet different EIP requirements. By examining deployment folders and understanding the use of flags like `--legacy`, we can effectively distinguish between these transaction types. diff --git a/courses/foundry/1-foundry-simple-storage/29-why-l2/+page.md b/courses/foundry/1-foundry-simple-storage/29-why-l2/+page.md new file mode 100644 index 000000000..ceaa6b3fc --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/29-why-l2/+page.md @@ -0,0 +1,30 @@ +--- +title: L2s +--- + +_Follow along with the video_ + +--- + +### Introduction + +In previous lessons, we deployed to the Sepolia testnet and started working with the Layer 2 solution ZKsync. Deploying to Sepolia simulates deployment to the Ethereum mainnet, offering a comprehensive understanding of Layer 1 deployments. However, it's important to note that most projects today prefer deploying to Layer 2 solutions rather than directly to Ethereum due to the high costs associated with deployments. + +### Gas Usage + +When deploying to a ZKsync local node, a `/broadcast` folder is created, containing a lot of detailed deployment transaction information. For instance, in our `run-latest.json` file, we can see the `gasUsed` value and we can convert this hexadecimal number `0x5747A` to its decimal equivalent by typing `cast to base 0x5747A dec`. This conversion allows us to estimate the deployment cost on the Ethereum mainnet. By checking recent gas prices on Etherscan, we can calculate the total cost using the formula: + +``` +Total Cost = Gas Used * Gas Price +``` + +We can see this total cost in the deployment transaction on [Sepolia Etherscan](https://sepolia.etherscan.io/tx/0xc496b9d30df33aa9285ddd384c14ce2a58eef470898b5cda001d0f4a21b017f6), under the `Transaction Fee` section. In this case, `357,498` gas will costs `0.000279288255846978` ETH, which today is equivalent to $7. + +Deploying even a minimal contract like `SimpleStorage` on Ethereum can be expensive. Larger contracts, with thousands of lines of code, can cost thousands of dollars. This is why many developers prefer deploying to Layer 2 solutions like ZKsync, which offer the same security as Ethereum but at a fraction of the cost. + +### Deploying to ZKsync Sepolia + +Deploying to ZKsync Sepolia is similar to deploying to a ZKsync local node. You can retrieve a ZKsync Sepolia RPC URL from [Alchemy](https://www.alchemy.com/) by creating a new app based on the ZKsepolia network. Then, you can proceed to add the `ZKSYNC_RPC_URL` to your `.env` configuration. + +> 🗒️ **NOTE**:br +> To understand the cost benefits of Layer 2 solutions, visit [L2Fees.info](https://l2fees.info) and compare the significant cost differences between sending a transaction on Ethereum and ZKsync Era. diff --git a/courses/foundry/1-foundry-simple-storage/30-alchemy-mempool/+page.md b/courses/foundry/1-foundry-simple-storage/30-alchemy-mempool/+page.md new file mode 100644 index 000000000..03a1dcb3b --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/30-alchemy-mempool/+page.md @@ -0,0 +1,82 @@ +--- +title: Alchemy & The Mempool +--- + +_Follow along the course with this video._ + + + +--- + +## Alchemy: A Game Changer for Decentralized Application Development + +Innovation in the blockchain industry has come a long way, with powerful tools making their way into the ecosystem to support developers and bring efficiency to their workflows. Among these tools is Alchemy, and today we have Vito, the lead developer experience at Alchemy, to walk us through the platform, its features, and how you can leverage it to exponentially increase your productivity. + +## What is Alchemy? + +Alchemy is a platform equipped with APIs, SDKs, and libraries to enhance your developer experience while working on Web3 projects. Think of Alchemy as the AWS of Web3. It functions as a node provider and developer tooling platform predominantly used in thousands of Web3 and Web2 applications, including large Web2 corporations like Adobe, Shopify, and Stripe. + +The need for platforms such as Alchemy arises from the fact that, as a developer, you don't usually have to worry about running the servers your code operates on or developing the deployment and integration pipelines for your application. Instead, you use services such as AWS, Azure, and Google Cloud for that—Alchemy does the same but for Web3. + +## How Does Alchemy Work? + +Alchemy enhances your developer experience through a combination of features. The platform's primary component is the _Supernode_, a proprietary blockchain engine that works as a load balancer on top of your node. + +Like its name suggests, the Supernode ensures data from the blockchain is always up-to-date and readily available. Using the Supernode as a foundation, Alchemy has built the _Enhanced APIs_—a set of APIs that makes pulling data from the blockchain a breeze. + +To put it simply, the Alchemy Supernode sits at the core of its ecosystem, powering up functionalities like Enhanced APIs and monitoring tools while supporting multiple chains. + +What follows is a step-by-step guide on how to create a new account on Alchemy and leverage this platform to its full extent: + +## Creating a New Account on Alchemy + +Creating an account on Alchemy is not only easy but also completely free. You can also freely scale your applications up using the platform's generous premium plans. + +#### Step 1: Navigate to Alchemy.com + +Head over to [Alchemy.com](https://www.alchemy.com/) and create a new account. + +#### Step 2: Create a New Application + +Once you have signed in, create a new application. + +Next, give your application a name and a description. Then, select a chain and network. Alchemy currently supports the majority of EVM-compatible chains, including: + +- Ethereum +- Polygon PoS +- Polygon zkEVM +- Optimism +- Arbitrum +- Solana (non-EVM chain) + +## The Application-Specific Dashboard + +Once your application is up and running, you will have access to the application-specific dashboard. This dashboard provides crucial insights into your application and infrastructure health, such as latency, compute units, and transaction success rate, which can be valuable for debugging and identifying issues. + +If you observe a lower success rate for your transactions, go to the "Recent Invalid Request" tab. This will list all unsuccessful requests along with the reasons for their failure, making it easier for you to debug and fix issues. + +::image{src='/foundry/22-alchemy/alchemy1.png' style='width: 100%; height: auto;'} + +## Mempool Watcher + +Another powerful tool provided by Alchemy is the Mempool watcher. Picture it as Ethereum's mempool, where all pending transactions reside waiting for validation or mining. + +The Mempool watcher provides extensive details about your transactions, such as: + +- Transaction status (mined, pending, dropped, replaced) +- Gas used +- Time taken for validation +- Transaction value +- Sender's and receiver's address + +This detailed transaction tracking allows you to have a better understanding of each transaction and aids immensely in debugging specific issues related to individual transactions. + +## Wrapping Up + +To sum up, Alchemy is a revolutionary platform that brings a plethora of tools to aid your Web3 development experience. From Supernode to Enhanced APIs and crucial troubleshooting tools, Alchemy is undeniably a game changer in the world of decentralized applications. + +"Alchemy can be a powerful asset to any blockchain developer, offering a simplified experience in an inherently complicated Web3 environment." – Vito, Lead Developer Experience at Alchemy. + +Vito suggests that you check out Alchemy's [documentation](https://docs.alchemy.com/) to explore more about the platform, its APIs, SDKs, libraries, and tools. Also, don't forget to follow them on Twitter at [@AlchemyPlatform](https://twitter.com/alchemyplatform) and [@AlchemyLearn](https://twitter.com/alchemyLearn). And if you want to connect directly with Vito, feel free to reach out to him on Twitter at [@VitoStack](https://twitter.com/VittoStack). + +Alchemy is revolutionizing the landscape of blockchain development and making it more accessible and efficient for everyone involved. Happy building with Alchemy! diff --git a/courses/foundry/1-foundry-simple-storage/31-summary-congratulations/+page.md b/courses/foundry/1-foundry-simple-storage/31-summary-congratulations/+page.md new file mode 100644 index 000000000..fdffe8891 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/31-summary-congratulations/+page.md @@ -0,0 +1,47 @@ +--- +title: Summary & Congratulations +--- + +_Follow along the course with this video._ + + + +--- + +## Celebrating Milestones in Foundry: A Complete Walkthrough of Our Recent Project + +You should feel a warm sense of accomplishment envelop you. Completing an entire project in Foundry is no mean feat. A hearty congratulation is in order for such an indomitable effort. This article serves as a quick, yet comprehensive, recap of everything we learnt in our project, proceeding into our next engagement. From the onset, rest assured, we are set to advance our Foundry skills, push upcoming projects on GitHub, and familiarize ourselves with advanced tooling. + +## A Quick Trip Down Memory Lane: Key Takeaways from the Project + +Firstly, we journeyed through the process of creating a new Foundry project using Forge and Knit. These essential tools afforded us a structured, professional environment complete with folders to keep our work organized. + +We not only learnt about Foundry’s basic commands but also their specific functionalities such as: + +- **Cast**: interacts with contracts that have been previously deployed. +- **Forge**: compiles and interacts with our contracts. +- **Anvil**: deploys a local blockchain, similar to another tool we used, Ganache. + +A pivotal part of our learning process was comprehending that sending a transaction via our MetaMask is tantamount to making an HTTP post request to a particular RPC URL. A similar RPC URL can be obtained from a node-as-a-service provider like [Alchemy](https://www.alchemyapi.io/) and used to send transactions directly from our Foundry projects. + +We obtained practical knowledge on how to compile code in Foundry and write a Solidity script for its subsequent deployment. We also find it critical to ensure the security of our private keys. Hence, throughout this course, we will be using an `.env` file. But be warned when dealing with real money, having your private key in plain text is not advisable. + +## Understanding Contract Deployment and Interaction on the Blockchain + +We delved into the automation of contract deployments to a blockchain. Post-deployment, we interacted with them using the `cast` keyword and `send` to make transactions, then `cast call` to read from those contracts. + +Moreover, the knowledge on how to auto format contracts with `Forge format` was acquired. We also learnt the painstaking yet rewarding manual method of verifying our contracts on the blockchain. + +```bash +forge format my_contract.sol +``` + +::image{src='/foundry/23-summary/summary1.png' style='width: 100%; height: auto;'} + +## Looking Ahead + +With these tools in your web development arsenal, you've performed exceptionally well – and yes, you should be incredibly proud. Remember, even something as small as installing tools like `Vs code` and `Foundry` can pose great difficulties, so, you're doing fantastic. + +Take a breather. Remember, breaks enhance productivity. Till next time, continue to strive for greatness in every line of code you write! + +::image{src='/foundry/23-summary/summary2.png' style='width: 100%; height: auto;'} diff --git a/courses/foundry/1-foundry-simple-storage/4-develop-in-cloud-using-gitpod/+page.md b/courses/foundry/1-foundry-simple-storage/4-develop-in-cloud-using-gitpod/+page.md new file mode 100644 index 000000000..11d4b0033 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/4-develop-in-cloud-using-gitpod/+page.md @@ -0,0 +1,21 @@ +--- +title: Develop in the cloud using Gitpod +--- + +_Follow along with this video:_ + +--- + +### Develop in the cloud using Gitpod + +**BIG BOLDED DISCLAIMER: This is not the ideal way to develop smart contracts. While using Gitpod you should never share private information, like a key or a secret phrase. That's if you like to continue being the owner of the associated accounts.** + +Gitpod is an online platform that provides cloud-based, pre-configured development environments specifically designed for working with Git repositories. It's similar to Remix IDE, but it allows you to run VS Code in a browser, on a remote server. + +Go to [Gitpod's website](https://gitpod.io/login/) and click `Continue with Github`. After that, you'll be able to create a new workspace, starting from a Github repository, using a stable version of VS Code. + +You'll be amazed to find out it looks exactly like VS Code. There's also an option to open Gitpod into your VS Code desktop version. + +Everything works like in VS Code and thus you should be able to run anything using the same commands. + +Gitpod has some [fantastic resources](https://www.gitpod.io/docs/introduction/getting-started) to get you started. diff --git a/courses/foundry/1-foundry-simple-storage/5-local-setup/+page.md b/courses/foundry/1-foundry-simple-storage/5-local-setup/+page.md new file mode 100644 index 000000000..217dcbee6 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/5-local-setup/+page.md @@ -0,0 +1,9 @@ +--- +title: Local Setup +--- +_Follow along with the video_ +--- + +To maintain a clean terminal, especially when it becomes cluttered, you can type the command "clear" and press Enter. Alternatively, use the shortcut `command + k` on a Mac or `control + k` on Linux or Windows. + +It's important to understand the difference between the **`trash can`** and the **`x`** icons in your VS code terminal: clicking the **`x`** icon it will _hide/show the terminal_, keeping all previous content visible when reopened. Clicking on the **`trash can`** icon instead, _terminates the current terminal session_. When you reopen it, you’ll see a fresh, empty session. \ No newline at end of file diff --git a/courses/foundry/1-foundry-simple-storage/6-foundry-install/+page.md b/courses/foundry/1-foundry-simple-storage/6-foundry-install/+page.md new file mode 100644 index 000000000..2868dbb5a --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/6-foundry-install/+page.md @@ -0,0 +1,87 @@ +--- +title: Foundry Install +--- + +_Follow along the course with this video._ + + + +--- + +Welcome to this handy guide on installing and operating Foundry, a versatile tool that will add a new level of command-line ease to your developer journey. Whether you're running Windows, Linux or MacOS, we've got you covered with instructions and tips. So sit back, grab a cup of coffee, and let's dive in. + +## Prepping your Terminal + +First things first. Before we dive into installing Foundry, make sure you have your terminal set up correctly. + +If you are using Windows, you should see something like `WSL` or `Ubuntu`. Once you have your terminal environment ready, it’s time for some quick tips to help streamline your workflow. + +### Keeping your Terminal Clutter-free + +When commands pile up in your terminal, things can get a little overwhelming. Clear it up by simply typing `clear` and hitting `Enter`. Alternatively, use `Command K` if you're on a Mac or `Control K` if you're on Linux or Windows. + +**Pro tip:** This is one of my favorite keyboard shortcuts that I use all the time. + +### Understanding the Trash Can and the X + +::image{src='/foundry/5-foundryinstall/foundryinstall1.png' style='width: 100%; height: auto;'} + +The trash can and the X buttons in your terminal perform distinct functions. Hitting `X` simply hides your terminal but retains all the previous lines of code. On the other hand, trashing it essentially deletes whatever is running in it. To open up a clean terminal, hit the trash can and then pull it back using `Toggle` or `Terminal > New Terminal`. + +## Installing Foundry + +With our terminal set and some tips up our sleeve, let's progress to installing Foundry. Navigate to the [Foundry website](https://book.getfoundry.sh/getting-started/installation) and from the installation tab, fetch the command to install Foundry. + +The command would look something like this: + +```bash +curl -L https://foundry.paradigm.xyz | bash +``` + +Hit `Enter` after pasting this in your terminal. + +**Note:** You must have Internet access for this to work as it's downloading Foundry from their official website. + +## Verifying Your Installation + +After running the `curl` command, an output will appear at the bottom of your terminal indicating the detected shell and the fact that Foundry has been added to your `Path`. + +For instance, the output can be something like this: + +```bash +Detected your preferred shell is bashrc and added Foundry to Path run:source /home/user/.bashrcStart +a new terminal session to use Foundry +``` + +Now, simply type `foundryup` and `Enter` to install and update Foundry to the latest version. Whenever you want to install an update for Foundry, simply run `foundryup` again. + +This will install four components: forge, cast, anvil, and chisel. To confirm the successful installation, run `forge --version`. You should get an output indicating the Forge version as shown below. + +```bash +Forge version x.x.x +``` + +Now, here's something to remember: when you hit the trash can in the top right, it literally 'removes' the terminal. The X button, in contrast, simply hides it. + +### Is Foundry Up Not Running? + +Don't panic if this command doesn't run. You might have an issue with your path, and you might need to add Foundry to your path. In case you run into this issue, check lesson 6 of the GitHub repo associated with this course. If no debugging tips are available there, feel free to start a discussion on the course's GitHub repo. Before doing so, make sure to check if a similar discussion already exists. + +Try typing `forge --version` into your terminal. Have you received an unwelcome output saying `Forge command found`? This implies that you have to rerun the `source` command that Foundry offered during installation. + +Note: Most of the time the `bashrc` file gets loaded automatically. However, if this doesn't apply to your setup, the following lines can add the required command to the end of your `Bash profile`. This will ensure that your `bashrc` file loads by default. + +```bash +cd ~ +echo 'source /home/user/.bashrc' >> ~/.bash_profile +``` + +> this depends on your operating system, please check foundry docs to see detailed instructions. + +## Wrapping Up + +And there we have it! Congratulations on installing Foundry and prepping your terminal to work seamlessly with it. Remember, hitting snags during installation is normal, especially if you're new to this. Don't hesitate to engage with the course community via GitHub if you run into issues. + +::image{src='/foundry/5-foundryinstall/foundryinstall2.png' style='width: 100%; height: auto;'} + +Here's to many hassle-free coding sessions with Foundry! diff --git a/courses/foundry/1-foundry-simple-storage/7-setup-your-vscode/+page.md b/courses/foundry/1-foundry-simple-storage/7-setup-your-vscode/+page.md new file mode 100644 index 000000000..48f14854c --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/7-setup-your-vscode/+page.md @@ -0,0 +1,67 @@ +--- +title: Setup your VSCode +--- + +_Follow along with this video:_ + +--- + +## VS Code setup + +### Installing VS Code extensions + +1. Open the Extensions view: + +There are two ways to do this: + +Click the Extensions icon in the Activity Bar on the left side of VS Code. + +Use the shortcut Ctrl+Shift+X (Windows/Linux) or Cmd+Shift+X (Mac). + +2. Browse or search for extensions: + +The Extensions view displays featured extensions by default. + +Use the search bar to find a specific extension by name. + +3. Install the extension: + +Once you've found the extension you want, click the "Install" button. +VS Code will handle the download and installation process. + +**That's it! The extension should be ready to use within VS Code.** + + +### Integrating AI into our work + +One of the best extensions that integrates AI in our development is GitHub Copilot + +Although it's a premium service, its intuitive AI-powered code autocomplete feature could be a game-changer for you. Of course, you can choose to go with other AI extensions based on your preferences. + +You can download GitHub Copilot [here](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot). More details and answers for your GitHub Copilot-related questions are available [here](https://github.com/features/copilot/?editor=vscode#faq). + + +### Other important VS Code Tips + +***Beware the white dot***, if you see it, your work is not saved, which means your project won't behave the way you want it to behave. + +```CTRL(CMD) + ` ```opens/closes your terminal. It's the equivalent of pressing the `X` button on the top right part of your terminal. + +The `trash can` button, on the left side of the `X` button destroys the terminal, make sure you always remember the difference between these two buttons. + +Hooray! This concludes the setup part of this course. Now we get to the fun part, actually developing a project using solidity and foundry. + + +### More setup ... + +Run the following commands in your terminal: + +``` +mkdir foundry-f23 +cd foundry-f23 +``` + +`mkdir` creates a directory or subdirectory. +`cd` changes the directory. + +Moving forward, it's advisable to keep all your repositories in this folder. Thus, you'll always have a place to reference all your code. diff --git a/courses/foundry/1-foundry-simple-storage/8-create-a-new-foundry-project/+page.md b/courses/foundry/1-foundry-simple-storage/8-create-a-new-foundry-project/+page.md new file mode 100644 index 000000000..818e66f52 --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/8-create-a-new-foundry-project/+page.md @@ -0,0 +1,86 @@ +--- +title: Create a new Foundry project +--- + +_Follow along with this video:_ + +--- + +### More setup + +Make sure we are in the folder we created in the previous lesson. + +**Reminder**: We ran the following commands + +``` +mkdir foundry-f23 +cd foundry-f23 +``` + +Now type the following commands: + +``` +mkdir foundry-simple-storage-f23 +cd foundry-simple-storage-f23 +``` + +You can always make the `cd` command faster by pressing the `Tab` key after you type the first couple of letters from the destination name. `Tab` lets you autocomplete a lot of commands/paths. + +If you type `code .` a new instance of VS Code will open, having the `foundry-simple-storage-f23` as the default path. + +You can see the contents of this folder on the left sidebar. Try the following command: + +``` +touch randomFile.txt +``` + +This will create a `randomFile.txt` + +If you want to delete it type: + +``` +rm randomFile.txt +``` + +The terminal is pretty slick when it comes to moving/opening/creating directories/files, changing paths and generally running things. I recommend going through [this tutorial](https://ubuntu.com/tutorials/command-line-for-beginners#1-overview) if you want to learn how to move extra fast. + +### Creating a New Project + +The way you [create a new Foundry project](https://book.getfoundry.sh/projects/creating-a-new-project) is by running the `forge init` command. This will create a new Foundry project in your current working directory. + +If you want Foundry to create the new project in a new folder type `forge init nameOfNewFolder`. + +Keep in mind that by default `forge init` expects an empty folder. If your folder is not empty you must run `forge init --force .` + +Be sure to configure your username and email if you encounter errors related to Git configuration. + +``` +git config --global user.email "yourEmail@provider.com" +git config --global user.name "yourUsername" +``` + +And that's it, your folder should look as follows: + +::image{src='/foundry-simply-storage/7-create-a-new-foundry-project/Image1.PNG' style='width: 75%; height: auto;'} + +**But what does all this mean?** + +`lib` is the folder where all your dependencies are installed, here you'll find things like: + +- `forge-std` (the forge library used for testing and scripting) +- `openzeppelin-contracts` is the most battle-tested library of smart contracts +- and many more, depending on what you need/install + +`scripts` is a folder that houses all your scripts + +`src` is the folder where you put all your smart contracts + +`test` is the folder that houses all your tests + +`foundry.toml` - gives configuration parameters for Foundry + +More on these folders and files later. + +Please right-click `src`, click on `New File` and name it `SimpleStorage.sol`. Copy the code available [here](https://github.com/Cyfrin/foundry-simple-storage-f23/blob/main/src/SimpleStorage.sol). + +One last thing, please delete `Counter.s.sol`, `Counter.sol` and `Counter.t.sol`. These files are a set of basic smart contracts that Foundry provides as a default when you create a new Foundry project. diff --git a/courses/foundry/1-foundry-simple-storage/9-create-a-new-foundry-project-wsl/+page.md b/courses/foundry/1-foundry-simple-storage/9-create-a-new-foundry-project-wsl/+page.md new file mode 100644 index 000000000..8753fcd6c --- /dev/null +++ b/courses/foundry/1-foundry-simple-storage/9-create-a-new-foundry-project-wsl/+page.md @@ -0,0 +1,31 @@ +--- +title: WSL setup +--- + +_Follow along with the video_ + +--- + +### Introduction + +Hallo 👋🏻, I'm Vasily and I'll be your instructor for all Windows development. You'll see me frequently as I guide you through installing, running, and configuring various Windows tools. + +### WSL setup + +Microsoft has significantly improved its development environment support in recent years. However, for _smart contract development_, installing dependencies can sometimes be tricky. To streamline this process, we will use the **Windows Subsystem for Linux (WSL)**: this is a better option because it enables a full-fledged _unix-like console_ on your Windows machine, simplifying the use of tools and utilities commonly found in unix-based environments. This setup ensures compatibility with all the code that runs on unix-based systems like macOS and Linux. + +To install WSL, you can begin by opening the Windows terminal. On Windows 11, press the Windows key, type "terminal," and hit `enter`. On Windows 10, you need to install the Windows terminal from the Microsoft Store (select the official app from Microsoft Corporation). + +Once installed, open the terminal and type `wsl --install`. This command will initiate the installation process. Afterward, restart your computer. Upon reboot, the terminal will appear again, prompting you to select a Unix username and set a password. WSL will be then successfully installed ✅. + +### Visual Studio Code + +After installing WSL, we need to install a code editor. We will use Visual Studio Code (VS Code), and there are three different methods to install it: + +1. **Using the Terminal**: Utilize `winget`, a package manager pre-installed on Windows 11. Open the terminal and type `winget search VS Code` to find the desired package. Then, execute `winget install Microsoft.VisualStudioCode` to install VS Code. + +2. **Via Web Browser**: Search for "Visual Studio Code" in your web browser, select the official Microsoft link and download the installer. Follow the prompts, accept the user agreement and customize all the installation options. + +3. **Using VSCodium**: For those who prefer more independence and privacy, there is an open-source alternative called **VSCodium**. It is similar to VS Code but without Microsoft's telemetry. Download the [VSCodium installer](https://github.com/VSCodium/vscodium/releases) from GitHub and follow its similar installation steps. + +Choose the method that best suits your needs. For this course, I will use the official Visual Studio Code from Microsoft.