{"id":18794489,"url":"https://github.com/chainstacklabs/learnweb3dao-foundry-workshop","last_synced_at":"2025-04-13T14:32:45.234Z","repository":{"id":113051450,"uuid":"584408434","full_name":"chainstacklabs/learnweb3dao-foundry-workshop","owner":"chainstacklabs","description":"A Foundry workshop with Chainstack and LearnWeb3 DAO","archived":false,"fork":false,"pushed_at":"2023-02-03T04:31:43.000Z","size":65,"stargazers_count":8,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-27T06:12:16.821Z","etag":null,"topics":["ethereum","foundry","smart-contracts","solidity","workshop"],"latest_commit_sha":null,"homepage":"https://www.youtube.com/watch?v=FGl2gk3G71U","language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chainstacklabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-02T13:38:04.000Z","updated_at":"2025-01-08T00:58:43.000Z","dependencies_parsed_at":"2023-05-22T10:15:36.724Z","dependency_job_id":null,"html_url":"https://github.com/chainstacklabs/learnweb3dao-foundry-workshop","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainstacklabs%2Flearnweb3dao-foundry-workshop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainstacklabs%2Flearnweb3dao-foundry-workshop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainstacklabs%2Flearnweb3dao-foundry-workshop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chainstacklabs%2Flearnweb3dao-foundry-workshop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chainstacklabs","download_url":"https://codeload.github.com/chainstacklabs/learnweb3dao-foundry-workshop/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248728225,"owners_count":21152181,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ethereum","foundry","smart-contracts","solidity","workshop"],"created_at":"2024-11-07T21:29:35.581Z","updated_at":"2025-04-13T14:32:45.228Z","avatar_url":"https://github.com/chainstacklabs.png","language":"Solidity","readme":"\u003cimg width=\"1200\" alt=\"Labs\" src=\"https://user-images.githubusercontent.com/99700157/213291931-5a822628-5b8a-4768-980d-65f324985d32.png\"\u003e\n\n\u003cp\u003e\n \u003ch3 align=\"center\"\u003eChainstack is the leading suite of services connecting developers with Web3 infrastructure\u003c/h3\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca target=\"_blank\" href=\"https://chainstack.com/build-better-with-ethereum/\"\u003e\u003cimg src=\"https://github.com/soos3d/blockchain-badges/blob/main/protocols_badges/Ethereum.svg\" /\u003e\u003c/a\u003e\u0026nbsp;  \n  \u003ca target=\"_blank\" href=\"https://chainstack.com/build-better-with-bnb-smart-chain/\"\u003e\u003cimg src=\"https://github.com/soos3d/blockchain-badges/blob/main/protocols_badges/BNB.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\n  \u003ca target=\"_blank\" href=\"https://chainstack.com/build-better-with-polygon/\"\u003e\u003cimg src=\"https://github.com/soos3d/blockchain-badges/blob/main/protocols_badges/Polygon.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\n  \u003ca target=\"_blank\" href=\"https://chainstack.com/build-better-with-avalanche/\"\u003e\u003cimg src=\"https://github.com/soos3d/blockchain-badges/blob/main/protocols_badges/Avalanche.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\n  \u003ca target=\"_blank\" href=\"https://chainstack.com/build-better-with-solana/\"\u003e\u003cimg src=\"https://github.com/soos3d/blockchain-badges/blob/main/protocols_badges/Solana.svg\" /\u003e\u003c/a\u003e\u0026nbsp;\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca target=\"_blank\" href=\"https://chainstack.com/protocols/\"\u003eSupported protocols\u003c/a\u003e •\n  \u003ca target=\"_blank\" href=\"https://chainstack.com/blog/\"\u003eChainstack blog\u003c/a\u003e •\n  \u003ca target=\"_blank\" href=\"https://docs.chainstack.com/quickstart/\"\u003eChainstack docs\u003c/a\u003e •\n  \u003ca target=\"_blank\" href=\"https://docs.chainstack.com/quickstart/\"\u003eBlockchain API reference\u003c/a\u003e •\n  \u003ca target=\"_blank\" href=\"https://console.chainstack.com/user/account/create\"\u003eStart for free\u003c/a\u003e\n\u003c/p\u003e\n\n# Introduction to Foundry Learn Web3 DAO \u0026 Chainstack workshop\n\nThis repository holds the code to be followed along with the Foundry workshop conducted by Chainstack on LWB3.\nFeel free to follow this README at your own pace.\n\n[Workshop video](https://www.youtube.com/watch?v=FGl2gk3G71U).\n\n## Installing Foundry\n\n\u003e This installation method has been tested on Linux and MacOS. Windows users will need to build from Foundry's Github repo. Refer to Foundry docs for [detailed instructions](https://book.getfoundry.sh/getting-started/installation#on-windows-build-from-source \"detailed instructions\").\n\nTo get started open your terminal, and run the following command-\n\n```sh\ncurl --version\n```\n\nThis command will return the version  of the [curl CLI](https://curl.se/ \"curl CLI\") installed in your system. You need it installed before moving on to install Foundry.\n\nInstall Foundry in your system using the curl command-\n\n```sh\ncurl -L https://foundry.paradigm.xyz | bash\n```\n\n\u003e Note that you might need to restart the terminal in case the `foundryup` command is not recognized.\n\nThis will install *foundryup* into your system. Install Foundry by running-\n\n```sh\nfoundryup\n```\n\nAnd that's it. You now have Foundry installed into your system.\nIf you face any errors while installing Foundry, refer to the [docs](https://book.getfoundry.sh/ \"docs\").\n\nThis installs 3 seperate CLI tools to into your system.\n\n1. #### Forge\n   **Forge** is used to initilaize, build, test and deploy a Foundry project.\n\n2. #### Cast\n   **Cast** is the CLI tool that allows us to perfrom RPC calls to the EVM. We can interact with already deployed smart contracts right from our terminals, to both read and sign transactions.\n\n3. #### Anvil\n   **Anvil** is the local testnet node that is shipped with Foundry. You can use Anvil to simulate an EVM enviornment without having to deploy to a live testnet. Truffle and Hardhat also ship similar local testnets.\n\n## Getting Started\n\nTo set up a Foundry project, create a new folder and open the directory in your terminal. In the terminal, run-\n\n```sh\nforge init\n```\n\nThis will set up a basic Foundry project complete with a test and a deployment script. \nYou can compile contracts and generate ABIs for them using-\n\n```sh\nforge build\n```\n\n## Simple ERC20 contract\n\nWe will use Foundry to compile, test and deploy an ERC20 token to the Goerli testnet.\n\n### Installing Opzeppelin contracts library\n\nBy default, Forge manages dependencies as Git Submodules. \nTo install Openzeppelin contracts as a dependency, run this command in your terminal-\n\n```sh\nforge install OpenZeppelin/openzeppelin-contracts\n```\n\nThis will install the [Openzepplin contracts library](https://github.com/OpenZeppelin/openzeppelin-contracts \"Openzepplin contracts library\") directly from the Github repo into oyur 'lib' folder. \nBy default, forge installs the code from the latest version of the master branch from the referenced repository.\n\n### Configuring remappings\n\nInside the src folder, create a file named `ERC20.sol`.  Paste the following code inside the file-\n\n    // SPDX-License-Identifier: MIT\n    pragma solidity ^0.8.17;\n    \n    import \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n    import \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\n    import \"@openzeppelin/contracts/access/Ownable.sol\";\n    contract MyToken is ERC20, ERC20Burnable, Ownable {\n        constructor() ERC20(\"FoundryToken\", \"FTK\") {\n            _mint(msg.sender, 1000 * 10 ** decimals());\n        }\n    \n        function mint(address to, uint256 amount) public onlyOwner {\n            _mint(to, amount);\n        }\n    }\n\nIf you try to compile this code with `forge build`, you will notice that the code doesn't compile because Forge cannot locate the files we are trying to import into our smart contract.\nThis brings us to remappings.\n\nWe need to define the exact path of our dependencies to help forge find them.\nIn your terminal, run-\n\n```sh\nforge remappings\n```\n\nThis will return some remappings that are generated by default. To create a *remappings.txt* from the pre-existing remappings, run-\n\n```sh\nforge remappings \u003e remappings.txt\n```\n\nAdd this line to the remappings file-\n\n```sh\nopenzeppelin/=lib/openzeppelin-contracts/contracts/\n```\n\nThis does two things for us.\n1. We create a new remapping named *openzeppelin* that points forge to our contracts library.\n2. This remapping points directly to the contracts folder inside our library, since all of the required imports are located inside the contracts folder.\n\nEdit all of your imports inside `ERC20.sol` to look like this-\n\n    import \"openzeppelin/token/ERC20/ERC20.sol\";\n    import \"openzeppelin/token/ERC20/extensions/ERC20Burnable.sol\";\n    import \"openzeppelin/access/Ownable.sol\";\n\nThe errors are now resolved. Run `forge build` again to finally compile our ERC20 smart contract.\n\n### foundry.toml\n\nFoundry allows users a high degree of customization.\nA `foundry.toml` file is created at the root of every Foundry project. We can use it to customize almost every Forge configuration.\nWe can also create multiple profiles if all of our smart contracts can't be compiled with a uniform configuration.\nFor now, add this line to foundry.toml-\n\n```sh\nsolc = \"0.8.17\"\n```\n\nThis will ensure our ERC20 contract is compiled with Solidity version 0.8.17. You can see a foundry.toml file with all the configurations set [here](https://github.com/foundry-rs/foundry/blob/master/config/README.md#configuration \"here\"). \nThis [Gist](https://gist.github.com/Genesis3800/bba57037e2b7180f0fda7bc252ddee3b \"Gist\") contains a list of default toml configurations for Foundry.\n\n### Testing in Foundry\n\nFoundry tests are written in Solidity.\n\nThe preffered way of writing Foundry tests is to import the `Test.sol` smart contract provided to us by Forge. The [Test.sol](https://github.com/foundry-rs/forge-std/blob/master/src/Test.sol \"Test.sol\") contract is itself a superset of many different smart contracts that allow us to make assertions and log values to the terminal.\nForge also gives us a variety of utils and cheatcodes designed to make testing easier.\n\nTo test the ERC20 contract-\n1. Create a new file nameds `ERC20.t.sol` inside the test folder. Copy all of the code from the equivalent file in this repo, and paste it inside your project.\n2. Run \n\n```sh\nforge test\n```\n\nFor a simple forge test command, Forge will scan the entire source directory for functions starting with the string \"***test***\". This means a function named \"testTransfer\" will be tested by Foundry, while a function named \"Transfer\" won't be.\nBy convention, all the test contracts are placed under the test folder, and are suffixed with '**.*t.sol***'.\n\nWhat if you only want to run a specific test file?\nTo run only the ERC20.t.sol file, run this command in your terminal-\n\n```sh\nforge test --match-path test/ERC20.t.sol\n```\n\nYou can find a complete reference for the Forge test command in [Foundry's docs](https://book.getfoundry.sh/reference/forge/forge-test \"Foundry's docs\").\n\n### Setting up dotenv file\n\nBefore moving on to deploying and verifying our ERC20 contract, we need to set up a dotenv file. It is not recommended to directly pass sensitive values to Foundry in the command line or foundry.toml, since you may end up pushing them to a remote repository.\n\nCreate a `.env` file at the root of your project.\nFill it like this-\n\n    RPC_URL=\"https://mc-12.p123yippy.com/12ase525c5012\"\n    PRIVATE_KEY=dlhj12342kjh4eslkh1pq4h13sd13vb14kqwrekhwe\n    ETHERSCAN_API_KEY=SDJKASL232ADS7262AS\n\nReplace all the dummy data with real values. You can get an RPC endpoint from [Chainstack](https://chainstack.com/ \"Chainstack\"), and an Etherscan API key from [Etherscan](https://etherscan.io/myapikey \"Etherscan\").\n\nNow save the `.env` file and in your terminal, run-\n\n```sh\nsource .env\n```\n\nThis command will load up the env variables.\n\n### Deploying and verifying using Foundry\n\nCreate a file named `ERC20.s.sol` inside the script folder. Copy all of the code from the equivalent file in this repo, and paste it inside your project.\n\nFoundry allows us to deploy contracts either by using a deploy script (which is what we will be doing), or by using the `forge create` command. You can however only deploy one smart contract at a time using the forge create command.\n\nTo deploy the ERC20 contract using our script, run-\n\n```sh\nforge script script/ERC20.s.sol:ERC20Deploy --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast --verify --etherscan-api-key $ETHERSCAN_API_KEY -vvvv\n```\n\nTo deploy using the forge create command-\n\n    forge create --rpc-url $RPC_URL \\                                                                                  --private-key $PRIVATE_KEY src/ERC20.sol/MyToken \\\n    --etherscan-api-key $ETHERSCAN_API_KEY \\\n    --verify\n\nIdeally Forge should be able to verify your smart contract right after deploying it. But if that doesn't work, we can also verify pre-existing smart contracts by running this command-\n\n    forge verify-contract --chain-id 5 --num-of-optimizations 200 --watch --compiler-version v0.8.17+commit.8df45f5f \u003cYOUR_SMART_CONTRACT_ADDRESS\u003e src/ERC20.sol:MyToken $ETHERSCAN_API_KEY\n \n\n\u003e Note- Foundry allows you to set the number of optimizations in `foundry.toml`. The default value is 200. This value needs to be passed as a parameter to the forge verify command. Also be careful to specify the exact compiler version.\n\n## Cast\n\nCast is shipped with Foundry as a separate CLI. Can be used to make calls, send transactions or retrieve a wide range of data. Can be used to interact with contracts we deployed.\nBasically it is a tool to interact with the blockchain form the terminal.\n\n*cast chain* can be used to fetch blockchain data. Here are two example-\n\n```bash\ncast chain-id --rpc-url $RPC_URL\ncast chain --rpc-url $RPC_URL\n```\n\n*cast rpc* can be used to send any JSON-RPC post request through your blockchain node. \nExample-\n\n```bash\ncast rpc eth_getTransactionByHash \u003cTxn_Hash\u003e --rpc-url $RPC_URL\n```\nYou can read about more about Ethereums's JSON_RPC implementation from [here](https://docs.chainstack.com/api/ethereum/eth_gettransactionbyhash \"here\").\n\nYou can use *cast call* to read data from the blockchain. The following command reads the balance of a particular address from this [contract address](https://goerli.etherscan.io/address/0x806DaB016369A2e74140e34de28ea78e472a1Ab4 \"contract address\").\nThis function takes an address as a parameter, and returns the account balance in the form of a uint256 return value.\n\n```bash\ncast call 0x806DaB016369A2e74140e34de28ea78e472a1Ab4 \"balanceOf(address)(uint256)\" \u003cAccount_Address\u003e --rpc-url $RPC_URL\n```\n\nFinally, you can use *cast send* to sign and send transactions. Please note that you will need a private key to use this command.\nThe following command will invoke the transfer function on our ERC20 contract to transfer tokens from one account to another.\n\n```bash\ncast send --private-key $PRIVATE_KEY 0x806DaB016369A2e74140e34de28ea78e472a1Ab4 \"function transfer(address,uint256)\" \"\u003cRecipient_Address\u003e\" \"\u003cAmount_To_Transfer\u003e\" --rpc-url $RPC_URL\n```\nCast is an incredibly powerful tool, and supports many more functionalities. You can read the detailed reference to Cast from [Foundry docs](https://book.getfoundry.sh/reference/cast/ \"the docs\").\n\n## Anvil\n\nAnvil is the local testnet node that is shipped with Foundry. You can use Anvil to simulate an EVM enviornment without having to deploy to a live testnet. Truffle and Hardhat also ship similar local testnets.\n\nTo start using anvil, open a new terminal, and run:\n\n```bash\nanvil\n```\nBy default, anvil produces a new block only when a new transaction is submitted. You can change configure this behaviour such that it generates a new block after a fixed period of time.\n\n```bash\nanvil --block-time 12\n```\n\nTo deploy a contract on anvil:\n\n```bash\nforge script script/ERC20.s.sol:ERC20Deploy --rpc-url http://localhost:8545 --private-key \u003cAnvil_Private_Key\u003e --broadcast\n```\n\nYou can now use cast to interact with your smart contract as usual.\nYou can check out the detaild reference to anvil [here](https://book.getfoundry.sh/anvil/ \"here\").\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchainstacklabs%2Flearnweb3dao-foundry-workshop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchainstacklabs%2Flearnweb3dao-foundry-workshop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchainstacklabs%2Flearnweb3dao-foundry-workshop/lists"}