
Unlocking Web3 for the Masses: Introduction
Innovators have started building NFT marketplaces, prediction markets, web3 gaming applications, etc. for everyday users, but these applications are held back by the complexity of using web3. Before using a web3 application, users must set up an exchange account, buy crypto, set up a wallet, write down their seed phrase, transfer crypto to their wallet, figure out how to bridge between chains, hold a native token on every chain to pay transaction fees, and more. It's an intimidating and ...
Solana Notes
Notes I put together on Solana in 2022. Lots of the ecosystem stuff is outdated now.Overviewover 60,000 tps$0.00025 transaction fees800 ms blocktimeSets of validators called clusters work together to validate client transactions. Different clusters may coexist and are identified by their genesis block. Two clusters that share the same genesis block will attempt to merge, otherwise they will ignore each other. Differs from traditional blockchains in that actions across nodes can be synchronize...

Unlocking Web3 for the Masses: Private Key Management
To enable the average person to hold cryptoassets, we need solutions to manage private keys that are easier to use and more secure. The current solutions offer easy-to-use key management but make concessions on security and privacy. Fortunately new technology will enable private key management solutions that are still seamless but without the drawbacks of legacy solutions.Legacy SolutionsA handful of private key management solutions have been around for years including Magic Link, Web3Auth, V...

Unlocking Web3 for the Masses: Introduction
Innovators have started building NFT marketplaces, prediction markets, web3 gaming applications, etc. for everyday users, but these applications are held back by the complexity of using web3. Before using a web3 application, users must set up an exchange account, buy crypto, set up a wallet, write down their seed phrase, transfer crypto to their wallet, figure out how to bridge between chains, hold a native token on every chain to pay transaction fees, and more. It's an intimidating and ...
Solana Notes
Notes I put together on Solana in 2022. Lots of the ecosystem stuff is outdated now.Overviewover 60,000 tps$0.00025 transaction fees800 ms blocktimeSets of validators called clusters work together to validate client transactions. Different clusters may coexist and are identified by their genesis block. Two clusters that share the same genesis block will attempt to merge, otherwise they will ignore each other. Differs from traditional blockchains in that actions across nodes can be synchronize...

Unlocking Web3 for the Masses: Private Key Management
To enable the average person to hold cryptoassets, we need solutions to manage private keys that are easier to use and more secure. The current solutions offer easy-to-use key management but make concessions on security and privacy. Fortunately new technology will enable private key management solutions that are still seamless but without the drawbacks of legacy solutions.Legacy SolutionsA handful of private key management solutions have been around for years including Magic Link, Web3Auth, V...

Subscribe to hatem.eth

Subscribe to hatem.eth
Share Dialog
Share Dialog
<100 subscribers
<100 subscribers
There’s a large learning curve to learning blockchain development because it’s so different than web2 programming paradigms. Instead of writing code that runs on one computer, you’re writing and interacting with code that runs on a distributed network
To deeply understand blockchain development, we’ll want to look at the virtual machine (VM) that’s used. There’s a couple different virtual machines that different blockchain’s use including Sealevel (Solana), CosmWasm (Cosmos), Wasm (Polkadot), Move VM (created by Facebook for Diem and will be used by Sui and Aptos).
The most popular virtual machine, though, is the Ethereum Virtual Machine or EVM. It has the largest number of applications and support from some of the largest blockchains including Ethereum, Polygon, Avalanche, Near, Optimism, and Arbitrum to name a few.
This guide is designed to get you up to speed on advanced concepts extremely quickly. It should take about 10 hours of deeply focused work to get through but you’ll come out of it with a great knowledge of the EVM.
Some of the basics to understand on Ethereum
For a deeper dive into most of these topics you can go to https://ethereum.org/en/developers/docs/intro-to-ethereum/
Public Key Cryptography: Blockchains rely on public key cryptography to prove ownership of assets and to create transactions. Public key cryptography uses a key pair which consists of a public key and a private key. The private key is kept secret and is used to digital signatures and can derive the public key.
Hash Function: a cryptographic function which creates a unique digital identifier (hash) for a piece of data.
ether (ETH): The native token on Ethereum which is required to pay for transaction fees.
wei: the smallest denomination of ETH. 1 ETH = 10e18 wei
gwei. 1 ETH = 10e9 gwei.
Ethereum Account: An entity that can send transactions. Accounts are either external owned (EOA) and controlled by a private key or they have code associated with them (i.e. it is a smart contract)
Ethereum Address: The public identifier of an ethereum account is it's address. The address is the keccak256 hash of an account
Wallet: a wallet is a piece of software that controls a user's private key. More advance wallets like MetaMask provide an easy way to connect to dapps and send transactions.
Token Decimals: https://docs.openzeppelin.com/contracts/2.x/erc20#a-note-on-decimals
We’re going to use Foundry to create your first smart contract. Foundry is a rust-based smart contract development toolchain created by Georgios Konstantopoulos that’s new but very well liked. There’s other smart contract development environments which I’ll split into 2 categories:
Pure Solidity: Tests are written in Solidity
Foundry
Javascript Based: Tests are written in JS/TS
For your first smart contract, we’re going to create an ERC20 token which is the standard interface for fungible tokens on EVM blockchains. You won’t be expected to understand a lot of what’s happening under the hood, which is fine because we’re just trying to quickly expose you to a bunch of different concepts in EVM development.
Go to the Foundry installation page and follow its directions to install Foundry. If you’re successful you should be able to run the following command.
$ forge --version
# Output should be something like
# -> forge 0.2.0 (60b1919 2022-07-24T00:08:10.658215Z)
forge and cast are the two binaries that foundryup installs and running forge version only returns the version of forge if forge is successfully installed.
Follow the instructions in the Foundry docs to set up your first project.
We’re going to use transmissions11’s Solmate repo as a dependency. Solmate is a collection of common smart contracts that are helpful for using as building blocks. Solmate is gas-optimized (a.k.a. it’s written so people spend as little as possible on transaction fees) and already audited which reduces the surface area for a vulnerability and the cost of an audit for your project.
$ forge install transmissions11/solmate
Rename src/Counter.sol to src/FirstToken.sol. Open up src/FirstToken.sol in your editor and copy in:
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.13;
import { ERC20 } from "solmate/tokens/ERC20.sol";
contract FirstToken is ERC20 {
constructor(uint256 totalSupply) ERC20("First Token", "FT", 18) {
_mint(msg.sender, totalSupply);
}
}
Let’s quickly go over what is happening in the contract.
Line 2: The pragma statement specifies which version of the Solidity compiler we need to use. In this case we’ll only accept the compiler version 0.8.13
Line 4: We import the Solmate ERC20 token contract. This contract is what’s doing all the work under the hood. Refer to that contract if you’re interested in how the token is implemented.
Line 6: We define our contract FirstToken and that it inherits from the Solmate ERC20 contract. Contracts in Solidity are similar to classes in object-oriented languages and can inherit from one another.
Line 7: We define the constructor of the contract and call the constructor of the ERC20 contract.
Solidity is unique in that a contract can extend multiple other contracts, and thus the atypical syntax of calling the ERC20 constructor in the constructor definition, not in a super call.
Our constructor accepts 1 argument totalSupply. The ERC20 constructor accepts 3 arguments: name, symbol and decimals. name and symbol are straightforward. decimals is the number of decimals to use in the numbers representation. Ethereum and all other blockchains I know of have no concept of floating point numbers so for more granular accuracy they just stick a bunch of zeros behind each number and refer to those as decimal points. ETH and most ERC20 tokens have 18 decimals.
Now that we’ve created the smart contract, we need to deploy it.
Before we can deploy the smart contract, we’ll have to create a wallet that we can deploy the contract from.
The simple way to create a wallet with foundry is running:
cast wallet new
But if you want to get creative you can run:
cast wallet vanity --starts-with <prefix>
This command will search for a private key that matches an address that starts with <prefix>. Not that <prefix> must be valid hex (i.e. valid characters include 0-9 and a-f only). Note that the longer the prefix is, the more attempts it will take the script to find a valid address that fulfills your vanity requirements. From my experience, anything under 4 characters will return instantly, 5 characters will take about 20-40s and each successive character will take an order of magnitude longer (it’s 16x harder to be exact). The exact times you’ll see will depend on the specs of the machine you run this on.
💡 Keep your private key safe. Anyone with access to this private key can access any funds in your wallet. It’s recommended to not keep a lot of funds in a hot wallet like this.
We’ll need to fund the wallet before we can send a transaction to it. To accomplish this, we’ll use a “faucet” which see send us testnet tokens. Go to https://faucet.paradigm.xyz/ and claim tokens from the faucet to the wallet you created in the previous step.
Check the wallet is funded
We’re going to deploy the contract on Ethereum’s Goerli testnet so go to https://goerli.etherscan.io/ and search for the wallet address you previously created. After claiming tokens from the faucet you should see that it has an Ether balance.
You should also run:
cast balance --rpc-url https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161 \
<your_address>
You should notice that there are a lot more 0s behind your ETH balance when running this CLI command.
Now let’s deploy the contract. Run the following command:
forge create --rpc-url <your_rpc_url> --private-key <your_private_key> \
src/FirstToken.sol:FirstToken \
--constructor-args 1000000000000000000000000
Replace <your_rpc_url> with https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161 and with the private key you previously created. This will create a token with a total supply of 100,000 (assuming I counted correctly). If you go to the etherscan link for your account that deployed the contract, you’ll notice your balance is shown under the “Erc20 Token Txns” Tabs (e.g. https://goerli.etherscan.io/address/0x8404a542298827022bf4441afef0a96766be7201#tokentxns for account 0x8404A542298827022bf4441Afef0a96766Be7201 on Goerli) Peeking Under the Hood Let’s take a look at what’s happening under the hood. Go back to Goerli etherscan and look up the transaction you just sent. Find the parameter on the transaction called “Input Data” (often just called “data” or “input”). You may have to expand more properties on the transaction to see it. Now open up the out/FirstToken.sol/FirstToken.json file in your repo. The “Input Data” on the transaction should look similar to the bytecode.object field in the file. Next, look up the address of the contract you just created. Click on the “Contract” tab and you should see the deployed bytecode of the contract. This value should look similar to the deployedBytecode.object property within the FirstToken.json file. Interacting with your Contract Now that you’ve deployed your first contract, let’s interact with it. Checking Your Balance First we need to get the calldata to check your balance cast calldata "balanceOf(address)" <your_eoa_address>
If you look closely at the calldata, you’ll notice that there’s 8 digits after the “0x” prefix at the start of it and the last 40 characters are from your address. Now that we have the calldata run: cast call --rpc-url https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161 \
<your_contract_address> <call_data>
The output of the previous command is a bunch of hex jargon so let’s make it a little easier to read: cast --to-dec <hex_output>
You should see the same number you passed into the constructor when creating the contract. Transferring the Token Let’s now transfer some of your token to another address. Run the following command: cast send --rpc-url https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161 \
--private-key <your_private_key> \
<your_contract_address> \
"transfer(address,uint)" 0x6666664c7d32A5577070EB846f7dFa5f962e5e6a 1000000000000000
This will transfer tokens to my address
There’s a large learning curve to learning blockchain development because it’s so different than web2 programming paradigms. Instead of writing code that runs on one computer, you’re writing and interacting with code that runs on a distributed network
To deeply understand blockchain development, we’ll want to look at the virtual machine (VM) that’s used. There’s a couple different virtual machines that different blockchain’s use including Sealevel (Solana), CosmWasm (Cosmos), Wasm (Polkadot), Move VM (created by Facebook for Diem and will be used by Sui and Aptos).
The most popular virtual machine, though, is the Ethereum Virtual Machine or EVM. It has the largest number of applications and support from some of the largest blockchains including Ethereum, Polygon, Avalanche, Near, Optimism, and Arbitrum to name a few.
This guide is designed to get you up to speed on advanced concepts extremely quickly. It should take about 10 hours of deeply focused work to get through but you’ll come out of it with a great knowledge of the EVM.
Some of the basics to understand on Ethereum
For a deeper dive into most of these topics you can go to https://ethereum.org/en/developers/docs/intro-to-ethereum/
Public Key Cryptography: Blockchains rely on public key cryptography to prove ownership of assets and to create transactions. Public key cryptography uses a key pair which consists of a public key and a private key. The private key is kept secret and is used to digital signatures and can derive the public key.
Hash Function: a cryptographic function which creates a unique digital identifier (hash) for a piece of data.
ether (ETH): The native token on Ethereum which is required to pay for transaction fees.
wei: the smallest denomination of ETH. 1 ETH = 10e18 wei
gwei. 1 ETH = 10e9 gwei.
Ethereum Account: An entity that can send transactions. Accounts are either external owned (EOA) and controlled by a private key or they have code associated with them (i.e. it is a smart contract)
Ethereum Address: The public identifier of an ethereum account is it's address. The address is the keccak256 hash of an account
Wallet: a wallet is a piece of software that controls a user's private key. More advance wallets like MetaMask provide an easy way to connect to dapps and send transactions.
Token Decimals: https://docs.openzeppelin.com/contracts/2.x/erc20#a-note-on-decimals
We’re going to use Foundry to create your first smart contract. Foundry is a rust-based smart contract development toolchain created by Georgios Konstantopoulos that’s new but very well liked. There’s other smart contract development environments which I’ll split into 2 categories:
Pure Solidity: Tests are written in Solidity
Foundry
Javascript Based: Tests are written in JS/TS
For your first smart contract, we’re going to create an ERC20 token which is the standard interface for fungible tokens on EVM blockchains. You won’t be expected to understand a lot of what’s happening under the hood, which is fine because we’re just trying to quickly expose you to a bunch of different concepts in EVM development.
Go to the Foundry installation page and follow its directions to install Foundry. If you’re successful you should be able to run the following command.
$ forge --version
# Output should be something like
# -> forge 0.2.0 (60b1919 2022-07-24T00:08:10.658215Z)
forge and cast are the two binaries that foundryup installs and running forge version only returns the version of forge if forge is successfully installed.
Follow the instructions in the Foundry docs to set up your first project.
We’re going to use transmissions11’s Solmate repo as a dependency. Solmate is a collection of common smart contracts that are helpful for using as building blocks. Solmate is gas-optimized (a.k.a. it’s written so people spend as little as possible on transaction fees) and already audited which reduces the surface area for a vulnerability and the cost of an audit for your project.
$ forge install transmissions11/solmate
Rename src/Counter.sol to src/FirstToken.sol. Open up src/FirstToken.sol in your editor and copy in:
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.13;
import { ERC20 } from "solmate/tokens/ERC20.sol";
contract FirstToken is ERC20 {
constructor(uint256 totalSupply) ERC20("First Token", "FT", 18) {
_mint(msg.sender, totalSupply);
}
}
Let’s quickly go over what is happening in the contract.
Line 2: The pragma statement specifies which version of the Solidity compiler we need to use. In this case we’ll only accept the compiler version 0.8.13
Line 4: We import the Solmate ERC20 token contract. This contract is what’s doing all the work under the hood. Refer to that contract if you’re interested in how the token is implemented.
Line 6: We define our contract FirstToken and that it inherits from the Solmate ERC20 contract. Contracts in Solidity are similar to classes in object-oriented languages and can inherit from one another.
Line 7: We define the constructor of the contract and call the constructor of the ERC20 contract.
Solidity is unique in that a contract can extend multiple other contracts, and thus the atypical syntax of calling the ERC20 constructor in the constructor definition, not in a super call.
Our constructor accepts 1 argument totalSupply. The ERC20 constructor accepts 3 arguments: name, symbol and decimals. name and symbol are straightforward. decimals is the number of decimals to use in the numbers representation. Ethereum and all other blockchains I know of have no concept of floating point numbers so for more granular accuracy they just stick a bunch of zeros behind each number and refer to those as decimal points. ETH and most ERC20 tokens have 18 decimals.
Now that we’ve created the smart contract, we need to deploy it.
Before we can deploy the smart contract, we’ll have to create a wallet that we can deploy the contract from.
The simple way to create a wallet with foundry is running:
cast wallet new
But if you want to get creative you can run:
cast wallet vanity --starts-with <prefix>
This command will search for a private key that matches an address that starts with <prefix>. Not that <prefix> must be valid hex (i.e. valid characters include 0-9 and a-f only). Note that the longer the prefix is, the more attempts it will take the script to find a valid address that fulfills your vanity requirements. From my experience, anything under 4 characters will return instantly, 5 characters will take about 20-40s and each successive character will take an order of magnitude longer (it’s 16x harder to be exact). The exact times you’ll see will depend on the specs of the machine you run this on.
💡 Keep your private key safe. Anyone with access to this private key can access any funds in your wallet. It’s recommended to not keep a lot of funds in a hot wallet like this.
We’ll need to fund the wallet before we can send a transaction to it. To accomplish this, we’ll use a “faucet” which see send us testnet tokens. Go to https://faucet.paradigm.xyz/ and claim tokens from the faucet to the wallet you created in the previous step.
Check the wallet is funded
We’re going to deploy the contract on Ethereum’s Goerli testnet so go to https://goerli.etherscan.io/ and search for the wallet address you previously created. After claiming tokens from the faucet you should see that it has an Ether balance.
You should also run:
cast balance --rpc-url https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161 \
<your_address>
You should notice that there are a lot more 0s behind your ETH balance when running this CLI command.
Now let’s deploy the contract. Run the following command:
forge create --rpc-url <your_rpc_url> --private-key <your_private_key> \
src/FirstToken.sol:FirstToken \
--constructor-args 1000000000000000000000000
Replace <your_rpc_url> with https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161 and with the private key you previously created. This will create a token with a total supply of 100,000 (assuming I counted correctly). If you go to the etherscan link for your account that deployed the contract, you’ll notice your balance is shown under the “Erc20 Token Txns” Tabs (e.g. https://goerli.etherscan.io/address/0x8404a542298827022bf4441afef0a96766be7201#tokentxns for account 0x8404A542298827022bf4441Afef0a96766Be7201 on Goerli) Peeking Under the Hood Let’s take a look at what’s happening under the hood. Go back to Goerli etherscan and look up the transaction you just sent. Find the parameter on the transaction called “Input Data” (often just called “data” or “input”). You may have to expand more properties on the transaction to see it. Now open up the out/FirstToken.sol/FirstToken.json file in your repo. The “Input Data” on the transaction should look similar to the bytecode.object field in the file. Next, look up the address of the contract you just created. Click on the “Contract” tab and you should see the deployed bytecode of the contract. This value should look similar to the deployedBytecode.object property within the FirstToken.json file. Interacting with your Contract Now that you’ve deployed your first contract, let’s interact with it. Checking Your Balance First we need to get the calldata to check your balance cast calldata "balanceOf(address)" <your_eoa_address>
If you look closely at the calldata, you’ll notice that there’s 8 digits after the “0x” prefix at the start of it and the last 40 characters are from your address. Now that we have the calldata run: cast call --rpc-url https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161 \
<your_contract_address> <call_data>
The output of the previous command is a bunch of hex jargon so let’s make it a little easier to read: cast --to-dec <hex_output>
You should see the same number you passed into the constructor when creating the contract. Transferring the Token Let’s now transfer some of your token to another address. Run the following command: cast send --rpc-url https://goerli.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161 \
--private-key <your_private_key> \
<your_contract_address> \
"transfer(address,uint)" 0x6666664c7d32A5577070EB846f7dFa5f962e5e6a 1000000000000000
This will transfer tokens to my address
Block: A batch of transactions that includes a hash of the previous block in the chain.
Gas: a unit of measure for how computationally intensive an operation is on Ethereum. The amount of gas a transaction requires is used to calculate the transaction fee a user must pay to execute a transaction.
Gas Price: The amount of ETH a user pays per unit of gas to execute a transaction. Gas Price is typically measured in gwei.
Ethereum Node: a computer running the software for the Ethereum protocol
Json-RPC: A lightweight remote procedure protocol (RPC). Ethereum nodes an expose their json rpc api so that clients can query the state of the blockchain.
Line 8: We mint the totalSupply of tokens to the msg.sender, which is the account that is sending the message to create the contract.
0x6666664c7d32A5577070EB846f7dFa5f962e5e6aBlock: A batch of transactions that includes a hash of the previous block in the chain.
Gas: a unit of measure for how computationally intensive an operation is on Ethereum. The amount of gas a transaction requires is used to calculate the transaction fee a user must pay to execute a transaction.
Gas Price: The amount of ETH a user pays per unit of gas to execute a transaction. Gas Price is typically measured in gwei.
Ethereum Node: a computer running the software for the Ethereum protocol
Json-RPC: A lightweight remote procedure protocol (RPC). Ethereum nodes an expose their json rpc api so that clients can query the state of the blockchain.
Line 8: We mint the totalSupply of tokens to the msg.sender, which is the account that is sending the message to create the contract.
0x6666664c7d32A5577070EB846f7dFa5f962e5e6a
No activity yet