From e506b1c440dfbc3a972e6bb2f76708edd1a36a06 Mon Sep 17 00:00:00 2001 From: "escottalexander@gmail.com" Date: Mon, 13 May 2024 16:33:02 -0400 Subject: [PATCH] set up main branch as template --- README.md | 382 +--------------------- packages/foundry/contracts/Challenge.sol | 6 + packages/foundry/contracts/WrappedETH.sol | 143 -------- packages/foundry/foundry.toml | 18 - packages/foundry/script/Deploy.s.sol | 34 ++ packages/foundry/test/Challenge.t.sol | 9 + packages/foundry/test/WrappedETH.t.sol | 116 ------- 7 files changed, 61 insertions(+), 647 deletions(-) create mode 100644 packages/foundry/contracts/Challenge.sol delete mode 100644 packages/foundry/contracts/WrappedETH.sol create mode 100644 packages/foundry/script/Deploy.s.sol create mode 100644 packages/foundry/test/Challenge.t.sol delete mode 100644 packages/foundry/test/WrappedETH.t.sol diff --git a/README.md b/README.md index 69f22c3..666c401 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Wrapped Token Challenge - ETH Tech Tree +# Template For Challenge - ETH Tech Tree ## Contents - [Requirements](#requirements) - [Start Here](#start-here) @@ -21,384 +21,26 @@ foundryup ``` ## Challenge Description -This challenge will require you to write an [ERC20](https://eips.ethereum.org/EIPS/eip-20) compliant token wrapper for ETH. An ERC20 form of ETH is useful because DeFi protocols don't have to worry about integrating special functions for handling native ETH, instead they can just write methods that handle any ERC20 token. +*Edit this section* +Write challenge description here... -Your task starts in `packages/foundry/contracts/WrappedETH.sol`. Use your solidity skills to make this smart contract receive ETH and give the depositor an equal amount of WETH, an ERC20 version of native ETH. The contract already has all the necessary methods to be ERC20 compliant, you will just have to fill in the details on what each method should do. **Don't change any existing method names** as it will break tests but feel free to add additional methods if it helps you complete the task. Here is a helpful reference: -- [Original Ethereum Improvement Proposal for the ERC-20 token standard](https://eips.ethereum.org/EIPS/eip-20) +Here are some helpful references: +- [one](buidlguidl.com) +- [two](buidlguidl.com) +- [three](buidlguidl.com) +*End of challenge specific section* When you think you are done run `yarn foundry:test` to run a set of tests against your code. If all your tests pass then you are good to go! If some are returning errors then you might find it useful to run the command with the extra logging verbosity flag `-vvvv` (`yarn foundry:test -vvvv`) as this will show you very detailed information about where tests are failing. -// TODO: Add front end testing support for a more hands on learning approach - -# 🏗 Scaffold-ETH 2 - Foundry - -🧪 An open-source, up-to-date toolkit for building decentralized applications (dapps) on the Ethereum blockchain. It's designed to make it easier for developers to create and deploy smart contracts and build user interfaces that interact with those contracts. - -⚙️ Built using NextJS, RainbowKit, Hardhat, Wagmi, and Typescript. - -- ✅ **Contract Hot Reload**: Your frontend auto-adapts to your smart contract as you edit it. -- 🔥 **Burner Wallet & Local Faucet**: Quickly test your application with a burner wallet and local faucet. -- 🔐 **Integration with Wallet Providers**: Connect to different wallet providers and interact with the Ethereum network. - -## Contents - -- [Requirements](#requirements) -- [Quickstart](#quickstart) -- [Deploying your Smart Contracts to a Live Network](#deploying-your-smart-contracts-to-a-live-network) -- [Deploying your NextJS App](#deploying-your-nextjs-app) - - [Scaffold App Configuration](#scaffold-app-configuration) -- [Interacting with your Smart Contracts: SE-2 Custom Hooks](#interacting-with-your-smart-contracts-se-2-custom-hooks) -- [Disabling Type & Linting Error Checks](#disabling-type-and-linting-error-checks) - - [Disabling commit checks](#disabling-commit-checks) - - [Deploying to Vercel without any checks](#deploying-to-vercel-without-any-checks) - - [Disabling Github Workflow](#disabling-github-workflow) -- [Contributing to Scaffold-ETH 2](#contributing-to-scaffold-eth-2) - -## Requirements - -Before you begin, you need to install the following tools: - -- [Node (v18 LTS)](https://nodejs.org/en/download/) -- Yarn ([v1](https://classic.yarnpkg.com/en/docs/install/) or [v2+](https://yarnpkg.com/getting-started/install)) -- [Git](https://git-scm.com/downloads) -- [Foundryup](https://book.getfoundry.sh/getting-started/installation) - -## Quickstart - -To get started with Scaffold-ETH 2, follow the steps below: - -1. Clone this repo & install dependencies - -``` -git clone -b foundry https://github.com/scaffold-eth/scaffold-eth-2.git --recurse-submodules -cd scaffold-eth-2 -yarn install -foundryup -``` - -2. Create your `.env` file inside `packages/foundry`: - -``` -(echo "DEPLOYER_PRIVATE_KEY="; echo "ALCHEMY_API_KEY=oKxs-03sij-U_N0iOlrSsZFr29-IqbuF"; echo "ETHERSCAN_API_KEY=DNXJA8RX2Q3VZ4URQIWP7Z68CJXQZSC6AW") >> packages/foundry/.env -``` - -3. Run a local network in the first terminal: - +For a more "hands on" approach you can try testing your contract with the provided front end interface by running the following: ``` yarn chain ``` - -This command starts a local Ethereum network using Anvil in Foundry. The network runs on your local machine and can be used for testing and development. You can customize the network configuration in `foundry.toml` - -4. On a second terminal, deploy the test contract: - +in a second terminal deploy your contract: ``` yarn deploy ``` - -This command deploys a test smart contract to the local network. The contract is located in `packages/foundry/src` and can be modified to suit your needs. The `yarn deploy` command uses the deploy script located in `packages/foundry/script/Deploy.s.sol` to deploy the contract to the network. You can also customize the deploy script. - -5. On a third terminal, start your NextJS app: - +in a third terminal start the NextJS front end: ``` yarn start -``` - -Visit your app on: `http://localhost:3000`. You can interact with your smart contract using the contract component or the example ui in the frontend. You can tweak the app config in `packages/nextjs/scaffold.config.ts`. - -Run smart contract test with `yarn foundry:test` - -- Edit your smart contract `YourContract.sol` in `packages/foundry/src` -- Edit your frontend in `packages/nextjs/pages` -- Edit your deployment scripts in `packages/foundry/script/Deploy.s.sol` - -## Deploying your Smart Contracts to a Live Network - -Once you are ready to deploy your smart contracts, there are a few things you need to adjust. - -1. Select the network - -By default, `yarn deploy` will deploy the contract to the local network. You can change the defaultNetwork in `packages/foundry/foundry.toml`.You could also simply run `yarn deploy --network target_network` to deploy to another network - -Check the `foundry.toml` for the networks that are pre-configured. You can also add other network settings to the `foundry.toml`. Here are the [Alchemy docs](https://docs.alchemy.com/docs/how-to-add-alchemy-rpc-endpoints-to-metamask) for information on specific networks. - -Example: To deploy the contract to the Sepolia network, run the command below: - -``` -yarn deploy --network sepolia -``` - -2. Generate a new account or add one to deploy the contract(s) from. Additionally you will need to add your Alchemy API key. Rename `.env.example` to `.env` and fill the required keys. - -``` -ALCHEMY_API_KEY="", -DEPLOYER_PRIVATE_KEY="" -``` - -The deployer account is the account that will deploy your contracts. Additionally, the deployer account will be used to execute any function calls that are part of your deployment script. - -You can generate a random account / private key with `yarn generate` or add the private key of your crypto wallet. `yarn generate` will create a random account and add the `DEPLOYER_PRIVATE_KEY` to the `.env` file. You can check the generated account with `yarn account`. - -3. Deploy your smart contract(s) - -Run the command below to deploy the smart contract to the target network. Make sure to have some funds in your deployer account to pay for the transaction. - -``` -yarn deploy --network network_name -``` - -4. Deploy and verify your smart contract(s) - -You can deploy & verify your smart contract on Etherscan by running: - -``` -yarn deploy:verify --network network_name -``` - -## Deploying your NextJS App - -**Hint**: We recommend connecting your GitHub repo to Vercel (through the Vercel UI) so it gets automatically deployed when pushing to `main`. - -If you want to deploy directly from the CLI, run `yarn vercel` and follow the steps to deploy to Vercel. Once you log in (email, github, etc), the default options should work. It'll give you a public URL. - -If you want to redeploy to the same production URL you can run `yarn vercel --prod`. If you omit the `--prod` flag it will deploy it to a preview/test URL. - -**Make sure to check the values of your Scaffold Configuration before deploying your NextJS App.** - -### Scaffold App Configuration - -You can configure different settings for your dapp at `packages/nextjs/scaffold.config.ts`. - -```ts -export type ScaffoldConfig = { - targetNetwork: chains.Chain; - pollingInterval: number; - alchemyApiKey: string; - walletConnectProjectId: string; - onlyLocalBurnerWallet: boolean; - walletAutoConnect: boolean; - // your dapp custom config, eg: - // tokenIcon : string; -}; -``` - -The configuration parameters are described below, make sure to update the values according to your needs: - -- **targetNetwork** - Sets the blockchain network where your dapp is deployed. Use values from `wagmi/chains`. - -- **pollingInterval** - The interval in milliseconds at which your front-end application polls the RPC servers for fresh data. _Note that this setting does not affect the local network._ - -- **alchemyApiKey** - Default Alchemy API key from Scaffold ETH 2 for local testing purposes. - It's recommended to obtain your own API key from the [Alchemy Dashboard](https://dashboard.alchemyapi.io/) and store it in an environment variable: `NEXT_PUBLIC_ALCHEMY_API_KEY` at `\packages\nextjs\.env.local` file. - -- **walletConnectProjectId** - WalletConnect's default project ID from Scaffold ETH 2 for local testing purposes. - It's recommended to obtain your own project ID from the [WalletConnect website](https://cloud.walletconnect.com) and store it in an environment variable: `NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID` at `\packages\nextjs\.env.local` file. - -- **onlyLocalBurnerWallet** - Controls the networks where the Burner Wallet feature is available. This feature provides a lightweight wallet for users. - - - `true` => Use Burner Wallet only on hardhat network. - - `false` => Use Burner Wallet on all networks. - -- **walletAutoConnect** - Set it to `true` to activate automatic wallet connection behavior: - - If the user was connected into a wallet before, on page reload it reconnects automatically. - - If user is not connected to any wallet, on reload, it connects to the burner wallet if it is enabled for the current network. See `onlyLocalBurnerWallet` - -You can extend this configuration file, adding new parameters that you need to use across your dapp **(make sure you update the above type `ScaffoldConfig`)**: - -```ts - tokenIcon: "💎", -``` - -To use the values from the `ScaffoldConfig` in any other file of your application, you first need to import it in those files: - -```ts -import scaffoldConfig from "~~/scaffold.config"; -``` - -## Interacting with your Smart Contracts: SE-2 Custom Hooks - -Scaffold-ETH 2 provides a collection of custom React hooks designed to simplify interactions with your deployed smart contracts. These hooks are wrappers around `wagmi`, automatically loading the necessary contract ABI and address. They offer an easy-to-use interface for reading from, writing to, and monitoring events emitted by your smart contracts. - -To help developers get started with smart contract interaction using Scaffold-ETH 2, we've provided the following custom hooks: - -- [useScaffoldContractRead](#usescaffoldcontractread): for reading public variables and getting data from read-only functions of your contract. -- [useScaffoldContractWrite](#usescaffoldcontractwrite): for sending transactions to your contract to write data or perform an action. -- [useScaffoldEventSubscriber](#usescaffoldeventsubscriber): for subscribing to your contract events and receiving real-time updates when events are emitted. -- [useScaffoldEventHistory](#usescaffoldeventhistory): for retrieving historical event logs for your contract, providing past activity data. -- [useDeployedContractInfo](#usedeployedcontractinfo): for fetching details from your contract, including the ABI and address. -- [useScaffoldContract](#usescaffoldcontract): for obtaining a contract instance that lets you interact with the methods of your deployed smart contract. - -These hooks offer a simplified and streamlined interface for interacting with your smart contracts. If you need to interact with external contracts, you can use `wagmi` directly, or add external contract data to your `deployedContracts.ts` file. - -### useScaffoldContractRead: - -Use this hook to read public variables and get data from read-only functions of your smart contract. - -```ts -const { data: totalCounter } = useScaffoldContractRead({ - contractName: "YourContract", - functionName: "getGreeting", - args: ["ARGUMENTS IF THE FUNCTION ACCEPTS ANY"], -}); -``` - -This example retrieves the data returned by the `getGreeting` function of the `YourContract` smart contract. If the function accepts any arguments, they can be passed in the args array. The retrieved data is stored in the `data` property of the returned object. - -### useScaffoldContractWrite: - -Use this hook to send a transaction to your smart contract to write data or perform an action. - -```ts -const { writeAsync, isLoading, isMining } = useScaffoldContractWrite({ - contractName: "YourContract", - functionName: "setGreeting", - args: ["The value to set"], - // For payable functions, expressed in ETH - value: "0.01", - // The number of block confirmations to wait for before considering transaction to be confirmed (default : 1). - blockConfirmations: 1, - // The callback function to execute when the transaction is confirmed. - onBlockConfirmation: (txnReceipt) => { - console.log("Transaction blockHash", txnReceipt.blockHash); - }, -}); -``` - -To send the transaction, you can call the `writeAsync` function returned by the hook. Here's an example usage: - -```ts - -``` - -This example sends a transaction to the `YourContract` smart contract to call the `setGreeting` function with the arguments passed in `args`. The `writeAsync` function sends the transaction to the smart contract, and the `isLoading` and `isMining` properties indicate whether the transaction is currently being processed by the network. - -### useScaffoldEventSubscriber: - -Use this hook to subscribe to events emitted by your smart contract, and receive real-time updates when these events are emitted. - -```ts -useScaffoldEventSubscriber({ - contractName: "YourContract", - eventName: "GreetingChange", - // The listener function is called whenever a GreetingChange event is emitted by the contract. - // It receives the parameters emitted by the event, for this example: GreetingChange(address greetingSetter, string newGreeting, bool premium, uint256 value); - listener: (greetingSetter, newGreeting, premium, value) => { - console.log(greetingSetter, newGreeting, premium, value); - }, -}); -``` - -This example subscribes to the `GreetingChange` event emitted by the `YourContract` smart contract, and logs the parameters emitted by the event to the console whenever it is emitted. The `listener` function accepts the parameters emitted by the event, and can be customized according to your needs. - -### useScaffoldEventHistory: - -Use this hook to retrieve historical event logs for your smart contract, providing past activity data. - -```ts -const { - data: events, - isLoading: isLoadingEvents, - error: errorReadingEvents, - } = useScaffoldEventHistory({ - contractName: "YourContract", - eventName: "GreetingChange", - // Specify the starting block number from which to read events, this is a bigint. - fromBlock: 31231n, - blockData: true, - // Apply filters to the event based on parameter names and values { [parameterName]: value }, - filters: { premium: true } - // If set to true it will return the transaction data for each event (default: false), - transactionData: true, - // If set to true it will return the receipt data for each event (default: false), - receiptData: true -}); -``` - -This example retrieves the historical event logs for the `GreetingChange` event of the `YourContract` smart contract, starting from block number 31231 and filtering events where the premium parameter is true. The data property of the returned object contains an array of event objects, each containing the event parameters and (optionally) the block, transaction, and receipt data. The `isLoading` property indicates whether the event logs are currently being fetched, and the `error` property contains any error that occurred during the fetching process (if applicable). - -### useDeployedContractInfo: - -Use this hook to fetch details about a deployed smart contract, including the ABI and address. - -```ts -// ContractName: name of the deployed contract -const { data: deployedContractData } = useDeployedContractInfo(contractName); -``` - -This example retrieves the details of the deployed contract with the specified name and stores the details in the deployedContractData object. - -### useScaffoldContract: - -Use this hook to get your contract instance by providing the contract name. It enables you interact with your contract methods. -For reading data or sending transactions, it's recommended to use `useScaffoldContractRead` and `useScaffoldContractWrite`. - -```ts -const { data: yourContract } = useScaffoldContract({ - contractName: "YourContract", -}); -// Returns the greeting and can be called in any function, unlike useScaffoldContractRead -await yourContract?.greeting(); - -// Used to write to a contract and can be called in any function -import { useWalletClient } from "wagmi"; - -const { data: walletClient } = useWalletClient(); -const { data: yourContract } = useScaffoldContract({ - contractName: "YourContract", - walletClient, -}); -const setGreeting = async () => { - // Call the method in any function - await yourContract?.setGreeting("the greeting here"); -}; -``` - -This example uses the `useScaffoldContract` hook to obtain a contract instance for the `YourContract` smart contract. The data property of the returned object contains the contract instance that can be used to call any of the smart contract methods. - -## Disabling type and linting error checks - -> **Hint** -> Typescript helps you catch errors at compile time, which can save time and improve code quality, but can be challenging for those who are new to the language or who are used to the more dynamic nature of JavaScript. Below are the steps to disable type & lint check at different levels - -### Disabling commit checks - -We run `pre-commit` [git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) which lints the staged files and don't let you commit if there is an linting error. - -To disable this, go to `.husky/pre-commit` file and comment out `yarn lint-staged --verbose` - -```diff -- yarn lint-staged --verbose -+ # yarn lint-staged --verbose -``` - -### Deploying to Vercel without any checks - -By default, Vercel runs types and lint checks before building your app. The deployment will fail if there are any types or lint errors. - -To ignore these checks while deploying from the CLI, use: - -```shell -yarn vercel:yolo -``` - -If your repo is connected to Vercel, you can set `NEXT_PUBLIC_IGNORE_BUILD_ERROR` to `true` in a [environment variable](https://vercel.com/docs/concepts/projects/environment-variables). - -### Disabling Github Workflow - -We have github workflow setup checkout `.github/workflows/lint.yaml` which runs types and lint error checks every time code is **pushed** to `main` branch or **pull request** is made to `main` branch - -To disable it, **delete `.github` directory** - -## Contributing to Scaffold-ETH 2 - -We welcome contributions to Scaffold-ETH 2! - -Please see [CONTRIBUTING.MD](https://github.com/scaffold-eth/scaffold-eth-2/blob/main/CONTRIBUTING.md) for more information and guidelines for contributing to Scaffold-ETH 2. +``` \ No newline at end of file diff --git a/packages/foundry/contracts/Challenge.sol b/packages/foundry/contracts/Challenge.sol new file mode 100644 index 0000000..c24c6a8 --- /dev/null +++ b/packages/foundry/contracts/Challenge.sol @@ -0,0 +1,6 @@ +//SPDX-License-Identifier: MIT +pragma solidity >=0.8.0 <0.9.0; + +contract Challenge { + // Add the challenges contract here +} diff --git a/packages/foundry/contracts/WrappedETH.sol b/packages/foundry/contracts/WrappedETH.sol deleted file mode 100644 index cb9ca26..0000000 --- a/packages/foundry/contracts/WrappedETH.sol +++ /dev/null @@ -1,143 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity >=0.8.0 <0.9.0; - -contract WrappedETH { - // ERC20 Standard methods for token metadata - string public name = "Wrapped Ether"; - string public symbol = "WETH"; - uint8 public decimals = 18; - - // ERC20 Standard Interface Events - event Approval(address indexed src, address indexed guy, uint wad); - event Transfer(address indexed src, address indexed dst, uint wad); - - // Non-ERC20 Standard Events - specific to the Wrapped Ether contract - event Deposit(address indexed dst, uint wad); - event Withdrawal(address indexed src, uint wad); - - // ERC20 Standard Interface mappings - mapping(address => uint) public balanceOf; - mapping(address => mapping(address => uint)) public allowance; - - /** - * @dev Deposits Ether into the contract. - * @notice This function allows users to deposit Ether into the contract. - * @dev The deposited Ether is added to the balance of the sender. - * Requirements: - * - Adds the amount deposited to the balance of the sender. - * - Emits a `Deposit` event with the caller's address and the amount of Ether deposited. - */ - function deposit() public payable { - balanceOf[msg.sender] += msg.value; - emit Deposit(msg.sender, msg.value); - } - - /** - * @dev Allows the caller to withdraw a specified amount of wrapped Ether (WETH) from their balance. - * @param wad The amount of wrapped Ether to withdraw. - * Requirements: - * - The caller must have a balance of at least `wad` wrapped Ether. - * - The withdrawal must be successful and the Ether must be sent to the caller's address. - * - Emits a `Withdrawal` event with the caller's address and the amount of Ether withdrawn. - */ - function withdraw(uint wad) public { - require(balanceOf[msg.sender] >= wad); - balanceOf[msg.sender] -= wad; - (bool sent, ) = msg.sender.call{value: wad}(""); - require(sent, "Failed to send Ether"); - emit Withdrawal(msg.sender, wad); - } - - /** - * @dev Part of the ERC20 Standard Interface. - * @dev Returns the total supply of the wrapped ETH token. - * @return uint representing the total supply of the wrapped ETH token. - * Requirements: - * - The total supply is equal to the balance of the contract. - */ - function totalSupply() public view returns (uint) { - return address(this).balance; - } - - /** - * @dev Part of the ERC20 Standard Interface. - * @dev Approves the specified address to spend the caller's tokens. - * @param guy The address to be approved. - * @param wad The amount of tokens to be approved. - * @return boolean value indicating whether the approval was successful or not. - * Requirements: - * - The caller sets the allowance of the specified address to the specified amount of tokens. - * - Emits an `Approval` event with the caller's address, the approved address, and the amount of tokens approved. - */ - function approve(address guy, uint wad) public returns (bool) { - allowance[msg.sender][guy] = wad; - emit Approval(msg.sender, guy, wad); - return true; - } - - /** - * @dev Part of the ERC20 Standard Interface. - * @dev Transfers a specified amount of wrapped ETH tokens from the source address to the destination address. - * @param src The address to transfer the tokens from. - * @param dst The address to transfer the tokens to. dst == destination - * @param wad The amount of tokens to transfer. - * @return boolean value indicating whether the transfer was successful or not. - * Requirements: - * - The source address must have a balance of at least `wad` tokens. - * - The source address must have approved the caller to spend at least `wad` tokens. - * - Emits a `Transfer` event with the caller's address, the approved address, and the amount of tokens approved. - */ - function transferFrom( - address src, - address dst, - uint wad - ) public returns (bool) { - require(balanceOf[src] >= wad); - - if ( - src != msg.sender && allowance[src][msg.sender] != type(uint256).max - ) { - require(allowance[src][msg.sender] >= wad); - allowance[src][msg.sender] -= wad; - } - - balanceOf[src] -= wad; - balanceOf[dst] += wad; - - emit Transfer(src, dst, wad); - - return true; - } - - /** - * @dev Part of the ERC20 Standard Interface. - * @dev Transfers a specified amount of wrapped ETH tokens from the caller's address to the destination address. - * @param dst The address to transfer the tokens to. dst == destination - * @param wad The amount of tokens to transfer. - * @return boolean value indicating whether the transfer was successful or not. - * Requirements: - * - The caller must have a balance of at least `wad` tokens. - * - Emits a `Transfer` event with the caller's address, the approved address, and the amount of tokens approved. - */ - function transfer(address dst, uint wad) public returns (bool) { - return transferFrom(msg.sender, dst, wad); - } - - /** - * @dev Default 'fallback' method called when a contract is called with msg.data that doesn't match any other method. - * Requirements: - * - Should call the `deposit` function to handle any received Ether. - */ - fallback() external payable { - deposit(); - } - - /** - * @dev Default method is used when a contract is called with empty msg.data. - * Requirements: - * - Should call the `deposit` function to handle any received Ether. - */ - receive() external payable { - deposit(); - } -} diff --git a/packages/foundry/foundry.toml b/packages/foundry/foundry.toml index 555cbd4..3af6cd6 100644 --- a/packages/foundry/foundry.toml +++ b/packages/foundry/foundry.toml @@ -8,22 +8,4 @@ fs_permissions = [{ access = "read-write", path = "./"}] default_network = "http://127.0.0.1:8545" localhost = "http://127.0.0.1:8545" -mainnet = "https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_API_KEY}" -sepolia = "https://eth-sepolia.g.alchemy.com/v2/${ALCHEMY_API_KEY}" -goerli = "https://eth-goerli.alchemyapi.io/v2/${ALCHEMY_API_KEY}" -arbitrum = "https://arb-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}" -arbitrumGoerli = "https://arb-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}" -optimism = "https://opt-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}" -optimismGoerli = "https://opt-goerli.g.alchemy.com/v2/${ALCHEMY_API_KEY}" -polygon = "https://polygon-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}" -polygonMumbai = "https://polygon-mumbai.g.alchemy.com/v2/${ALCHEMY_API_KEY}" -gnosis = "https://rpc.gnosischain.com" -chiado = "https://rpc.chiadochain.net" -base = "https://mainnet.base.org" -baseGoerli = "https://goerli.base.org" - -[etherscan] -polygonMumbai = { key = "${ETHERSCAN_API_KEY}" } -goerli = { key = "${ETHERSCAN_API_KEY}" } - # See more config options https://github.com/foundry-rs/foundry/tree/master/config diff --git a/packages/foundry/script/Deploy.s.sol b/packages/foundry/script/Deploy.s.sol new file mode 100644 index 0000000..6ba503d --- /dev/null +++ b/packages/foundry/script/Deploy.s.sol @@ -0,0 +1,34 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "../contracts/Challenge.sol"; +import "./DeployHelpers.s.sol"; + +contract DeployScript is ScaffoldETHDeploy { + error InvalidPrivateKey(string); + + function run() external { + uint256 deployerPrivateKey = setupLocalhostEnv(); + if (deployerPrivateKey == 0) { + revert InvalidPrivateKey( + "You don't have a deployer account. Make sure you have set DEPLOYER_PRIVATE_KEY in .env or use `yarn generate` to generate a new random account" + ); + } + vm.startBroadcast(deployerPrivateKey); + Challenge challenge = new Challenge(); + console.logString( + string.concat( + "Challenge deployed at: ", + vm.toString(address(challenge)) + ) + ); + vm.stopBroadcast(); + /** + * This function generates the file containing the contracts Abi definitions. + * These definitions are used to derive the types needed in the custom scaffold-eth hooks, for example. + * This function should be called last. + */ + exportDeployments(); + } + function test() public {} +} \ No newline at end of file diff --git a/packages/foundry/test/Challenge.t.sol b/packages/foundry/test/Challenge.t.sol new file mode 100644 index 0000000..a2340e9 --- /dev/null +++ b/packages/foundry/test/Challenge.t.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Test.sol"; +import "../contracts/Challenge.sol"; + +contract ChallengeTest is Test { + // Put tests here +} diff --git a/packages/foundry/test/WrappedETH.t.sol b/packages/foundry/test/WrappedETH.t.sol deleted file mode 100644 index cb9dee7..0000000 --- a/packages/foundry/test/WrappedETH.t.sol +++ /dev/null @@ -1,116 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "forge-std/Test.sol"; -import "../contracts/WrappedETH.sol"; - -contract WrappedETHTest is Test { - WrappedETH public wrappedETH; - address public userOne = address(0x123); - - function setUp() public { - wrappedETH = new WrappedETH(); - } - - function testDeposit() public { - wrappedETH.deposit{value: 1000}(); - assertEq(wrappedETH.balanceOf(address(this)), 1000); - } - - function testFallback() public { - address(wrappedETH).call{value: 1000}(""); - assertEq(wrappedETH.balanceOf(address(this)), 1000); - } - - function testWithdraw() public { - vm.startPrank(userOne); - vm.deal(userOne, 1000); - wrappedETH.deposit{value: 1000}(); - wrappedETH.withdraw(1000); - assertEq(wrappedETH.balanceOf(userOne), 0); - assertEq(wrappedETH.balanceOf(address(wrappedETH)), 0); - assertEq(userOne.balance, 1000); - } - - function testTotalSupply() public { - wrappedETH.deposit{value: 1000}(); - assertEq(wrappedETH.totalSupply(), 1000); - } - - function testApprove() public { - wrappedETH.approve(vm.addr(2), 1000); - assertEq(wrappedETH.allowance(address(this), vm.addr(2)), 1000); - } - - function testTransfer() public { - wrappedETH.deposit{value: 1000}(); - wrappedETH.transfer(vm.addr(2), 1000); - assertEq(wrappedETH.balanceOf(address(this)), 0); - assertEq(wrappedETH.balanceOf(vm.addr(2)), 1000); - } - - function testTransferWithInsufficientBalance() public { - wrappedETH.deposit{value: 999}(); - vm.expectRevert(); - wrappedETH.transfer(vm.addr(2), 1000); - assertEq(wrappedETH.balanceOf(address(this)), 999); - assertEq(wrappedETH.balanceOf(vm.addr(2)), 0); - } - - function testTransferFrom() public { - wrappedETH.deposit{value: 1000}(); - wrappedETH.approve(vm.addr(2), 1000); - vm.startPrank(vm.addr(2)); - wrappedETH.transferFrom(address(this), vm.addr(2), 1000); - assertEq(wrappedETH.balanceOf(address(this)), 0); - assertEq(wrappedETH.balanceOf(vm.addr(2)), 1000); - } - - function testTransferFromAllowanceIsAdjusted() public { - wrappedETH.deposit{value: 1000}(); - wrappedETH.approve(vm.addr(2), 1000); - vm.startPrank(vm.addr(2)); - wrappedETH.transferFrom(address(this), vm.addr(2), 1000); - assertEq(wrappedETH.balanceOf(address(this)), 0); - assertEq(wrappedETH.balanceOf(vm.addr(2)), 1000); - assertEq(wrappedETH.allowance(address(this), vm.addr(2)), 0); - } - - function testTransferFromWithoutAllowance() public { - wrappedETH.deposit{value: 1000}(); - vm.startPrank(vm.addr(2)); - vm.expectRevert(); - wrappedETH.transferFrom(vm.addr(1), vm.addr(2), 1000); - assertEq(wrappedETH.balanceOf(address(this)), 1000); - assertEq(wrappedETH.balanceOf(vm.addr(2)), 0); - } - - function testTransferFromWithInsufficientAllowance() public { - wrappedETH.deposit{value: 1000}(); - wrappedETH.approve(vm.addr(2), 500); - vm.startPrank(vm.addr(2)); - vm.expectRevert(); - wrappedETH.transferFrom(address(this), vm.addr(2), 1000); - assertEq(wrappedETH.balanceOf(address(this)), 1000); - assertEq(wrappedETH.balanceOf(vm.addr(2)), 0); - } - - function testTransferFromWithInsufficientBalance() public { - wrappedETH.deposit{value: 500}(); - wrappedETH.approve(vm.addr(2), 1000); - vm.startPrank(vm.addr(2)); - vm.expectRevert(); - wrappedETH.transferFrom(address(this), vm.addr(2), 1000); - assertEq(wrappedETH.balanceOf(address(this)), 500); - assertEq(wrappedETH.balanceOf(vm.addr(2)), 0); - } - - function testTransferFromWithMaxAllowance() public { - wrappedETH.deposit{value: 1000}(); - wrappedETH.approve(vm.addr(2), type(uint256).max); - vm.startPrank(vm.addr(2)); - wrappedETH.transferFrom(address(this), vm.addr(2), 1000); - assertEq(wrappedETH.balanceOf(address(this)), 0); - assertEq(wrappedETH.balanceOf(vm.addr(2)), 1000); - } -}