Welcome to the repository for the Ultimate Solidity, Blockchain, and Smart Contract - Beginner to Expert Full Course | Python Edition FreeCodeCamp course!
- Table of Contents
- Resources For This Course
- Lesson 0: Welcome To Blockchain
- Lesson 1: Welcome to Remix! Simple Storage
- Lesson 2: Storage Factory
- Lesson 3: Fund Me
- Lesson 4: Web3.py Simple Storage
- Lesson 5: Brownie Simple Storage
- Lesson 6: Brownie Fund Me
- Lesson 7: SmartContract Lottery
- Lesson 8: Chainlink Mix
- Lesson 9: ERC20s, EIPs, and Token Standards
- Lesson 10: Defi & Aave
- Lesson 11: NFTs
- Lesson 12: Upgrades
- Bonus Lesson 13: Full Stack Defi
- Closing and Summary
- Github Discussions
- Ask questions and chat about the course here!
- Stack Exchange Ethereum
- Great place for asking technical questions about Ethereum
- StackOverflow
- Great place for asking technical questions overall
- Bitcoin Whitepaper
- Ethereum Whitepaper
- Hybrid Smart Contracts
- Blockchain Oracles
- What is a blockchain
- Metamask
- Etherscan
- Rinkeby Etherscan
- Kovan Etherscan
- Rinkeby Faucet (Check the link token contracts page)
- NOTE: The Chainlink documentation always has the most up to date faucets on their link token contracts page. If the faucet above is broken, check the chainlink documentation for the most up to date faucet.
- OR, use the Kovan ETH Faucet, just be sure to swap your metamask to kovan!
- Gas and Gas Fees
- Wei, Gwei, and Ether Converter
- ETH Gas Station
- Blockchain Demo
- Public / Private Keys
- Layer 2 and Rollups
- Decentralized Blockchain Oracles
- Block Rewards
- Run Your Own Ethereum Node
Lesson 1: Welcome to Remix! Simple Storage
💻 Code: https://github.com/PatrickAlphaC/simple_storage
Everything in this section can be read about in the Solidity Documentation
- Versioning
- Compiling
- Contract Declaration
- Types & Declaring Variables
uint256
,int256
,bool
,string
,address
,bytes32
- Default Initializations
- Comments
- Functions
- Deploying a Contract
- Calling a public state-changing Function
- Visibility
- Scope
- View & Pure Functions
- Structs
- Intro to Storage
- Arrays - Dynamic & Fixed sized
- Compiler Errors and Warnings
- Memory
- Mappings
- SPDX License
- Recap
- A testnet or mainnet
- Find a faucet here
- Connecting Metamask
- Interacting with Deployed Contracts
- The EVM
Lesson 2: Storage Factory
💻 Code: https://github.com/PatrickAlphaC/storage_factory
- Factory Pattern
- Imports
- Deploy a Contract From a Contract
- Interact With a Deployed Contract
- Recap
Lesson 3: Fund Me
💻 Code: https://github.com/PatrickAlphaC/fund_me
- Payable
- Wei/Gwei/Eth Converter
- msg.sender & msg.value
- Decentralized Oracle Network Chainlink
- Blockchains can't make API calls
- Centralized Nodes are Points of Failure
- data.chain.link
- Getting External Data with Chainlink Oracles
- Decimals/Floating Point Numbers in Solidity
- latestRoundData
- Importing from NPM in Remix
- Interfaces
- Introduction to ABIs
- Getting Price Feed Addresses
- getPrice
- Tuples
- Unused Tuple Variables
- Matching Units (WEI/GWEI/ETH)
- getConversionRate
- Matching Units (Continued)
- SafeMath & Integer Overflow
- using keyword
- Libraries
- SafeMath PSA
- Setting a Threshold
- Require
- Revert
- Withdraw Function
- Transfer
- Balance
- this
- Contract Owners
- Constructor
- ==
- Modifiers
- Resetting
- for loop
- Array Length
- Forcing a Transaction
- Recap
Lesson 4: Web3.py Simple Storage
💻 Code: https://github.com/PatrickAlphaC/web3_py_simple_storage
- Developer Bootcamp Setup Instructions (metamask, vscode, python, nodejs..)
- VSCode
- VSCode Crash Course
- Extensions
- Short Cuts:
- Python
- Install Troubleshooting
- Terminal
- Making a directory/Folder
- Opening the folder up with VSCode
- Creating a new file
- Syntax Highlights
- Remember to save!
- Setting linting compile version
- VSCode Solidity Settings
- Formatting & Format on Save
- Solidity Prettier
- Python Black
- pip
- Reading our solidity file
- Running a Python Script in the Terminal
- MaxOS Shortcuts
- Windows Shortcuts
- Linux Shortcuts
- Compiling in Python
- py-solc-x
- compile_standard
- Colorized Brackets
- JSON ABI
- Saving Compiled Code
- Formatting JSON
- Deploying in Python
- Get Bytecode
- Get ABI
- Choose Blockchain to Deploy To
- Local Ganache Chain
- Web3.py
- HTTP / RPC Provider
- Private Keys MUST start with "0x"
- Contract Object
- Building a Transaction
- Account Nonce
- Calling "Contructor"
- Transaction Parameters
- Signing the Transaction
- NEVER put your private key directly in your code
- Setting Environment Variables (Windows, Linux, MacOS)
- Exported Environment Variables Only Last the Duration of the Shell/Terminal
- Private Key PSA
- .env file
- .gitignore
- Loading .env File in Python
- Viewing our Transaction / Deployment in Ganache
- Waiting for Block Confirmations
- 2 Things you always need
- Contract Address
- Contract ABI
- Getting address from transaction receipt
- Calling a view function with web3.py
- Call vs Transact
- Updating State with Web3.py
- ganache-cli
- Installing Ganache
- Working with ganache-cli
- Open a new terminal in the same window
- Deploying to a testnet
- Infura
- Alchemy
- Using Infura RPC URL / HTTP Provider
- Chain Ids
- Wow this seems like a lot of work... Is there a better way?
Lesson 5: Brownie Simple Storage
💻 Code: https://github.com/PatrickAlphaC/brownie_simple_storage
- Installing Brownie
- Install pipx
- pipx install eth-brownie
- Testing Successful Install
- A new Brownie project with
brownie init
- Project Basic Explanation
- Adding
SimpleStorage.sol
to thecontracts
folder - Compiling with
brownie compile
- Brownie deploy script
def main
is brownie's entry point
- brownie defaults to a
development
ganache
chain that it creates - Placing functions outside of the
main
function - brownie
accounts
- 3 Ways to Add Accounts
accounts[0]
: Brownie's "default" ganache accounts- Only works for local ganache
accounts.load("...")
: Brownie's encrypted command line (MOST SECURE)- Run
brownie accounts new <name>
and enter your private key and a password
- Run
accounts.add(config["wallets"]["from_key"])
: Storing Private Keys as an environment variable, and pulling from ourbrownie-config.yaml
- You'll need to add
dotenv: .env
to yourbrownie-config.yaml
and have a.env
file
- You'll need to add
- 3 Ways to Add Accounts
- Importing a Contract
- Contract.Deploy
- View Function Call in Brownie
- State-Changing Function Call in Brownie / Contract Interaction
transaction.wait(1)
test_simple_storage.py
- Arrange, Act, Assert
assert
brownie test
test_updating_storage
- Pytest / Brownie Test Tips
- Deploy to a Testnet
brownie networks list
- Development vs Ethereum
- Development is temporary
- Ethereum networks persist
- RPC URL / HTTP Provider in Brownie
- The network flag
list index out of range
get_account()
networks.show_active()
- build/deployments
- Accessing previous deployments
- Interacting with contracts deployed in our brownie project
brownie console
Lesson 6: Brownie Fund Me
💻 Code: https://github.com/PatrickAlphaC/brownie_fund_me
- Setup
- Dependencies
- chainlink-brownie-contracts
- remappings
- Deploy Script (V1)
helpful_scripts.py
__init__.py
- Deploy to Rinkeby
- Contract Verification (
publish_source
)- The Manual Way
- "Flattening"
- The Programatic Way
- Getting an Etherscan API Key
ETHERSCAN_TOKEN
- Interacting with Etherscan
- The Manual Way
- Deploying to Local Chains
- Introduction to Mocking
- Constructor Parameters
networks
in ourbrownie-config.yaml
- Copying Mock Contracts from chainlink-mix
- Deploying and using our mock
- Refactoring
- Deploying to a persistent ganache
- brownie attach
- Adding a persistent brownie network
- resetting a network build
- Whoops! Let's fix an issue...
- Fund Script
- Withdraw Script
test_can_fund_and_withdraw
- default networks
- pytest
pip install pytest
- pytest.skip
- brownie exceptions
mainnet-fork
- Custom mainnet fork
- Adding a development brownie network
brownie networks add development mainnet-fork-dev cmd=ganache-cli host=http://127.0.0.1 fork='https://infura.io/v3/$WEB3_INFURA_PROJECT_ID' accounts=10 mnemonic=brownie port=8545
- Alchemy
brownie test --network mainnet-fork
- brownie ganache vs local ganache vs mainnet-fork vs testnet...
- Installing Git
- Creating a repository
- First time with git
- Adding our project to github
- Tweet it out!
Lesson 7: SmartContract Lottery
💻 Code: https://github.com/PatrickAlphaC/smartcontract-lottery
- Add a
README.md
- Defining the project
- Is it decentralized?
- basic setup
- Main Functions
- address payable[]
- getEntranceFee & Setup
- Chainlink Price Feed
- brownie-config
- SPDX
- Matching Units of Measure
- Can't just divide
- Test early and often
- Quick Math Sanity Check
- deleting networks
- Alchemy again
- Enum
startLottery
- Openzeppelin... Is this the first openzeppelin reference?
- Openzeppelin Contracts Github
- Randomness
- Pseudorandomness
block
keywordblock.difficulty
block.timestamp
keccack256
- True Randomness with Chainlink VRF
- Chainlink VRF Remix Version
- Inheriting Constructors
- Oracle Gas & Transaction Gas
- Why didn't we pay gas on the price feeds?
- Chainlink Node Fees
- Request And Receive Introduction
- Kovan Faucets
- Funding Chainlink Contracts
- Request And Receive Explanation
- A Clarification
endLottery
returns (type variableName)
fulfillRandomness
override
- Modulo Operation (Mod Operation %)
- Paying the lottery winner
- Resetting the lottery
deploy_lottery.py
get_account()
refactoredget_contract
contract_to_mock
Contract.from_abi
- Adding the parameters to deploying to lottery
vrfCoordinatorMock
and adding mocksLinkToken
and Mocks- Successful Ganache Deployment!
- Python Lottery Scripts/Functions
start_lottery
- Brownie tip: Remember to
tx.wait(1)
your last transaction enter_lottery
end_lottery
- Funding with LINK
- brownie interfaces
- Waiting for callback
- Integration Tests & Unit Tests
- Test all lines of code
test_get_entrance_fee
pytest.skip
(again)test_cant_enter_unless_started
test_can_start_and_enter_lottery
test_can_pick_winner_correctly
- Events and Logs
callBackWithRandomness
topics
- conftest.py
Lesson 8: Chainlink Mix
💻 Code: https://github.com/smartcontractkit/chainlink-mix
Lesson 9: ERC20s, EIPs, and Token Standards
💻 Code: https://github.com/PatrickAlphaC/erc20-brownie-py
- ERC20/EIP20 Standard
- What is an ERC20?
- Creating an ERC20
- OpenZeppelin ERC20
- Solidity 0.8
- I Challenge you to code this yourself!
deploy_token.py
- Copy paste
helpful_scripts.py
- Viewing our token in metamask
- Adding to an exchange
Lesson 10: Defi & Aave
💻 Code: https://github.com/PatrickAlphaC/aave_brownie_py_freecode
- Defipulse
- Defillama
- Aave Testnet Site
- Paraswap
- Decentralized Exchange
- Kovan ETH
- What is Aave?
- Borrowing and Lending
- Connecting to Aave
- Depositing Tokens / Lending
- Checking your transaction is correct
- WETH Gateway
- Interest Bearing Token (aToken)
- Collateral
- DAI
- Stablecoin
- Wrapped Bitcoin (wBTC)
- Why borrow tokens?
- Blockchain Fintech Tutorial
- DISCLAIMER ABOUT BORROWING
- Borrowing Tokens
- Liquidations
- Your health factor must be above 1
- Solvent
- Stable vs Variable Interest Rate
- Repaying our borrows/loans
- Reward token / governance token
- Governance
- Quant Defi Engineer
- Aave Documentation
- Setup
- Converting ETH -> WETH
get_weth.py
- IWETH
- Kovan WETH Token Address: 0xd0a1e359811322d97991e03f863a0c30c2cf029c
- Mainnet WETH Token Address: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
- Converting WETH -> ETH with
withdraw
aave_borrow.py
- LendingPool
- LendingPoolAddressProvider
- LendingPool and LendingPoolAddressProvider Addresses
- Fixing import dependencies
- Aave Github
- ERC20 Approve Function
- IERC20 from Patrick's repo
deposit
- getUserAccountData
- Liquidation Threshold
- Risk Parameters
- Borrowing DAI
- Getting DAI Conversion Rate
- borrow
- Mainnet DAI Address: 0x6b175474e89094c44da98b954eedeac495271d0f
- Aave Testnet Token Addresses
- Repaying
- Kovan Run
- Viewing the transactions
Lesson 11: NFTs
💻 Code: https://github.com/PatrickAlphaC/nft-demo
- End-to-end article
- What is an NFT?
- ERC721
- Token URI
- Token Metadata Example
- IPFS
- brownie mix
- Initial Setup
SimpleCollectible.sol
- OpenZeppelin ERC721
- Pug Image
- NFT Constructor
- NFT is a type of factory pattern
createCollectible
_safeMint
- TokenURI & Metadata
- Opensea listing example
- Is this decentralized?
- Ethereum Size and dStorage
- You need to have your NFT attributes both on-chain and inside your tokenURI metadata
deploy_and_create.py
- TokenURI used for the demo: https://ipfs.io/ipfs/Qmd9MCGtdVz2miNumBHDbvj8bigSgTwnr4SbyH6DNnpWdt?filename=0-PUG.json
- IPFS Companion
- Rinkeby Deployment
- Opensea Example
- What else with NFTs?
AdvancedCollectible.sol
- Dungeons and Dragons Example
- Double Inherited Constructors
createCollectible
(Advanced)tokenIdToBreed
- Working with in-flight Chainlink VRF requests
- Download the NFT images from the nft-mix
setTokenURI
_isApprovedOrOwner
- Emit events when you update mappings
indexed
event keyword
- Move
OPENSEA_URL
tohelpful_scripts
- Deploying AdvancedCollectible
- Opensea testnet is only compatible with Rinkeby
- Rinkeby Chainlink VRF Contract Addresses
- Speeding through adding functions from previous projects
- Deploy to Rinkeby
create_collectible.py
- A quick unit test
- A quick integration test
create_metadata.py
get_breed
- Metadata Folder
metadata_template
- NFT Metadata Attributes
- Checking if Metadata file already exists
- Uploading to IPFS
upload_to_ipfs
- Download IPFS Command Line
- Download IPFS Desktop
- HTTP IPFS Docs
ipfs daemon
- Pinata
- Pinata Docs
- Refactoring to not re-upload to IPFS
- Setting the TokenURI
- End-To-End Manual Testnet Test
- Viewing on Opensea
Lesson 12: Upgrades
💻 Code: https://github.com/PatrickAlphaC/upgrades-mix
- Original Video
- Smart Contracts can be upgraded!
- Does this mean they are not immutable?
- Trail of Bits on Upgradeable Smart Contracts
- The "Not Really Upgrading" / Parameterization Method
- The Social Yeet / Migration Method
- Contract Migration
- Proxies
- DelegateCall
- Terminology:
- Implementation Contract
- Proxy Contract
- User
- Admin
- Gotchas:
- Storage Clashes
- Function Selector
- Function Selector Clashes
- Proxy Patterns:
- Setup
Box.sol
BoxV2.sol
- Getting the proxy contracts
- Openzeppelin Proxy Github
01_deploy_box.py
- Hooking up a proxy to our implementation contract
- (Optional) Creating a Gnosis Safe
- Initializers
- Encoding Initializer Function
- Assigning ABI to a proxy
- Running the script
- Upgrade Python Function
- Testing our proxy
- Testing our upgrades
Bonus Lesson 13: Full Stack Defi
💻 Code: https://github.com/PatrickAlphaC/defi-stake-yield-brownie-freecode
- FreeCodeCamp React
- What are we building?
- Setup
DappToken.sol
TokenFarm.sol
tokenIsAllowed
addAllowedTokens
- mapping of a mapping
stakeTokens
issueTokens
getUserTotalValue
getUserSingleTokenValue
getTokenValue
setPriceFeedContract
unStakeTokens
- Can this be reentrancy attacked?
deploy.py
- Deploying DappToken
- Deploying TokenFarm
- Adding allowed tokens
- ERC20 Kovan Faucet
- Mocking our ERC20s
test_set_price_feed_contract
test_stake_tokens
- Fixtures
test_issue_tokens
- Now you try on tests!
- Front End Introduction
- Typescript
- React
- useDapp
- npx
- yarn
create-react-app
- Layout
- Testing Front End
- yarn && yarn start
- Connecting our wallets
- Install useDapp
- Header Component
- Connect Button
- Material-UI
- Making our button nicer
Main.tsx
- Sending
brownie-config
&build
folder to our UI - Helper Config
- TypeScript error suppression
- Getting addresses
- Ethers
- Only support kovan
- Sending
YourWallet
supportedTokens
- State Hooks
- Showing tokens
WalletBalance
ethersproject/units
BalanceMsg
- Stake Form
- Calling
approve
useContractFunction
useEffect
- Notifications
- Make it pretty
- Alerts
Shoutout to Matt for the help on the front end!
- Best Practices
- Attacks
- Damn Vulnerable Defi
- Ethernaut
- Some Auditors
- CryptoZombies
- Dapp University
- ChainShot
- Ivan on Tech
- Eat the Blocks
- Patrick Collins
- Austin Griffith
- Nader Dabit
- Ethereum.org
Be sure to check out project grant programs!
And make today an amazing day!