diff --git a/locales/de/Basics/README.md b/locales/de/Basics/README.md new file mode 100644 index 000000000..6b065b830 --- /dev/null +++ b/locales/de/Basics/README.md @@ -0,0 +1,3 @@ +## Loading, Compiling, Deploying + +This beginner level tutorial introduces Remix's interface and concepts used in Ethereum. diff --git a/locales/de/Basics/config.yml b/locales/de/Basics/config.yml new file mode 100644 index 000000000..8c160b545 --- /dev/null +++ b/locales/de/Basics/config.yml @@ -0,0 +1,26 @@ +--- +id: basics +name: Basics of Remix +summary: A typical workflow in Remix +level: 1 +tags: + - Remix +steps: + - + name: Intro to the Interface + path: interface_introduction + - + name: Intro to Workspaces + path: workspaces + - + name: Loading & Compiling + path: load_and_compile + - + name: Deploying to the Remix VM + path: deploy_to_the_remixvm + - + name: Interacting with Functions + path: interacting + - + name: Deploying to Public Networks + path: deploy_injected diff --git a/locales/de/Basics/deploy_injected/README.md b/locales/de/Basics/deploy_injected/README.md new file mode 100644 index 000000000..172396527 --- /dev/null +++ b/locales/de/Basics/deploy_injected/README.md @@ -0,0 +1,21 @@ +1. If you don't have a browser wallet like **MetaMask** download and install one now. + +2. Click the MetaMask icon in your browser. Sign in and choose the Ephemery test network. You might need to update your wallet's settings so that you can see **test networks**. Alternatively, you can go to Remix's Deploy & Run transation module and in the ENVIRONMENT section select Ephemery. + +3. Getting test ETH for public test networks is often annoying. Ephemery is a public network that is refreshed monthly, so getting test ETH should be painless. Here is a link to some Ephemery faucets. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/testnet.png) + +Sepolia is another popular testnet that is not refreshed, so deployments will persist, but Sepolia faucets are more difficult to use. + +In your browser wallet make sure that you have NOT selected mainnet or any network that will cost real ETH. In the Deploy & Run module, below the Environment select box, you'll see a badge with the network's ID and for popular chains, its name. In the case below its Sepolia. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/sepolia.png) + +5. Make sure you see the 2_Owner.sol as a choice in the **CONTRACT** select box, then click the **Deploy** button. + +If the **CONTRACT** select box is empty, you'll need to compile 2_Owner again by making 2_Owner.sol the active file in the **editor** and then go to the **Solidity Compiler** to compile it. + +6. After you hit the `Deploy` button, you'll see the browser wallet popup asking you to pay for the transactions. If you have the appropriate kind of ETH for this chain, approve this transaction. Check the printout in the terminal. Once the block is validated, the **deployed instance** will appear at the bottom of Deploy & Run + +And with that you have finished this tutorial. You now have experience with opening, compiling, deploying and interacting with Smart Contracts in Remix IDE. diff --git a/locales/de/Basics/deploy_to_the_remixvm/README.md b/locales/de/Basics/deploy_to_the_remixvm/README.md new file mode 100644 index 000000000..8035d631b --- /dev/null +++ b/locales/de/Basics/deploy_to_the_remixvm/README.md @@ -0,0 +1,15 @@ +In the previous chapter, we compiled a contract - which is to say the Solidity code has been transformed into little chunks of Ethereum Virtual Machine (EVM) bytecode. + +Now we will put that code on a test blockchain. + +1. Click the Deploy and Run icon ![deploy & run icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_to_the_remixvm/images/run.png "deploy & run icon"). + +2. Select one of the **Remix VM**s from the **Environment** pulldown. + +3. Click the Deploy button (or the transact button in the expanded view). + +4. You have deployed your compiled contract to the Remix VM - a simulated blockchain that is running inside of your browser window. The Remix VM is simple, fast test chain. It is not that realistic because you don't need to approve each transaction. + +5. Check the terminal to see detail of this deployment transaction. + +You can also use Remix to deploy to other public EVM chains. To do this, you'll need to connect to a different **Environment** - like Injected Provider. The Injected Provider connects Remix to browser wallet (like MetaMask or similar). We'll try deploying to a public network at the end of this tutorial. But before we get there, we'll cover how to interact with a deployed contract's functions. diff --git a/locales/de/Basics/interacting/README.md b/locales/de/Basics/interacting/README.md new file mode 100644 index 000000000..59ef44200 --- /dev/null +++ b/locales/de/Basics/interacting/README.md @@ -0,0 +1,19 @@ +## Accessing functions in a deployed contract + +1. When a contract has been successfully deployed, it will appear at the bottom of the Deploy and Run plugin. Open up the contract by clicking the caret - so the caret points down. + ![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/instance.png "deployed contract") + +2. There are 2 functions in this contract. To input the parameters individually, clicking the caret to the right of changeOwner (outlined in red below). In the expanded view, each parameter has its own input box. + +![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/deployed_open2.png "deployed contract") + +If this contract had imported other contracts, then the functions of the imported contracts would also be visible here. At some point, try playing with An ERC20 contract to see all its many functions. + +3. Functions with blue buttons are either **pure** or **view** functions. This means that they are just reading a property or are returning a value. In other words, they aren't saving anything - so they are FREE (they don’t cost gas). Functions with other colors - usually orange (depending on the Remix theme) cost gas because they are saving information. They are creating a **transaction**. + +4. 2_Owner.sol does not have a **payable** function. If it did, the button's color would be red. Payable functions allow you to send Ether to the function. To send ETH with a payable function, you put the amount you want to send in the **value** field towards the top of the Deploy & Run module. + +5. In the Remix VM, you don't need to approve a transaction. When using a more realistic test environment or when using the mainnet - you will need to approve the transactions for them to go through. Approving a transaction costs gas. + +6. Choosing a public network is not done in Remix but in your Browser Wallet. There is a plug icon to the right of the Environment title that links to chainlist.org where you can get the specs of the chain you want to interact with. + ![chainlist](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/chainlist.png "chainlist") diff --git a/locales/de/Basics/interface_introduction/README.md b/locales/de/Basics/interface_introduction/README.md new file mode 100644 index 000000000..76c953fbd --- /dev/null +++ b/locales/de/Basics/interface_introduction/README.md @@ -0,0 +1,15 @@ +## Remix is composed of four panels. + +![Remix layout](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/a-layout1c.png "Remix layout") + +- Most plugins appear in the **Side Panel**. +- Editing code happens in tabs in the **Main Panel**. +- The results of transactions and other actions are visible in the **Terminal**. +- Switching between plugins happens in the **Icons Panel**. +- To make a panel larger, drag its border. + +Try clicking the **Solidity Compiler** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/solidity-icon.png) in the **Icons Panel**. Then click the **Deploy & Run** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/deploy-run.png). Then come back to **LearnEth** by clicking this icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/learneth.png). + +In the **Main Panel** of Remix, make sure you see the **Home** tab. The **Home** tab has lots of useful links. To navigate there, either click the **Home** tab in the **Main Panel** or click the Remix icon ![Remix icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/remix-logo.png "Remix icon") on the top of the icon panel. + +- See all the plugins in the **Plugin Manager**. Click this icon ![plugin manager](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/plugin1.png "Plugin Manager icon") in the lower left corner Remix. diff --git a/locales/de/Basics/load_and_compile/README.md b/locales/de/Basics/load_and_compile/README.md new file mode 100644 index 000000000..a666d5d13 --- /dev/null +++ b/locales/de/Basics/load_and_compile/README.md @@ -0,0 +1,20 @@ +Let's load a file from the File Explorer into the Editor. + +1. In the icon panel, click ![file explorer icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/files1.png "file explorer icon") , the File Explorer's icon. + +2. Make sure you are in the **default_workspace**. + +![default workspace](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/default_workspace_open.png) + +3. Open the contracts folder and click on **2_Owner.sol** in the contracts folder. Click it. The file will appear in a tab in the main panel. + +4. In the icon panel, click the **Solidity Compiler** ![solidity compiler icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/solidity1.png "solidity compiler icon"). The Solidity compiler should now be in the side panel. + +5. Click the compile button. + ![compile 2\_owner](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/compile2owner.png "compile 2_Owner") + +6. Compiling can also be triggered by hitting **CTRL + S**. + +The spinner will turn while the file is compiling. + +**Note:** The spinner also turns when the compiler itself is loading. To choose a **different version of Solidity**, go to the select box at the top of the plugin. diff --git a/locales/de/Basics/workspaces/README.md b/locales/de/Basics/workspaces/README.md new file mode 100644 index 000000000..97a47d283 --- /dev/null +++ b/locales/de/Basics/workspaces/README.md @@ -0,0 +1,23 @@ +## Workspaces help organize your separate projects. + +If this is your first time to Remix, a Workspace named **default_workspace** is loaded in the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/default_workspace.png) + +The **default_workspace** has three Solidity (.sol) files in the contracts folder. Remix has a number of other templates. When you load a template, it goes into a Workspace. To go between Workspaces, use the select box at the top of the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/select-box.png) + +But Workspaces are not only for templates. When cloning a repo into Remix, the files will be put into a Workspace. + +Let's create a new Workspace + +1. At the top of the File Explorer, click the hamburger icon (the 3 horizontal lines). Read through the commands and tools in this menu. + +2. Select **+ Create** (the first choice). + +3. In the modal the comes up, choose one of the templates. + +![hamburger](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/workspaces/images/popup.png) + +Notice that in this popup menu, you can clone a repo. Managing a Git repo happens in the DGit plugin. You can also create Github actions with the three workflow choices in the popup menu. diff --git a/locales/de/CircomHashChecker/README.md b/locales/de/CircomHashChecker/README.md new file mode 100644 index 000000000..20391a668 --- /dev/null +++ b/locales/de/CircomHashChecker/README.md @@ -0,0 +1,14 @@ +Hash Checker Tutorial + +This tutorial guides you through creating and understanding a Hash Checker circuit using Remix-IDE. You'll learn how to generate the circuit using a template, explore the code, perform a trusted setup, generate proofs, and verify them. This tutorial is suitable for beginners familiar with Circom and Zero-Knowledge Proofs. + +Prerequisites + +``` +Basic understanding of Zero-Knowledge Proofs and Circom. +Familiarity with Remix-IDE. +``` + +Estimated Time + +Approximately 1-2 hours. diff --git a/locales/de/CircomHashChecker/config.yml b/locales/de/CircomHashChecker/config.yml new file mode 100644 index 000000000..2c2aae80a --- /dev/null +++ b/locales/de/CircomHashChecker/config.yml @@ -0,0 +1,35 @@ +id: circom-hash-checker +name: Hash Checker Tutorial +summary: A tutorial on creating and understanding a Hash Checker circuit using Remix-IDE templates, including trusted setup and proof generation. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction to the Hash Checker Circuit + path: step-1 + - + name: Generating the Hash Checker Template in Remix-IDE + path: step-2 + - + name: Exploring calculate_hash.circom + path: step-3 + - + name: Compiling the Circuit + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Compute Witness + path: step-6 + - + name: Generate Proof + path: step-7 + - + name: Exploring the Trusted Setup Script (Optional) + path: step-8 + - + name: Exploring the Proof Generation Script (Optional) + path: step-9 diff --git a/locales/de/CircomHashChecker/step-1/README.md b/locales/de/CircomHashChecker/step-1/README.md new file mode 100644 index 000000000..be922e93b --- /dev/null +++ b/locales/de/CircomHashChecker/step-1/README.md @@ -0,0 +1,8 @@ +In this tutorial, we'll explore the **Hash Checker** circuit, a zero-knowledge proof (ZKP) application using Circom and Remix-IDE. The Hash Checker circuit allows you to prove knowledge of certain inputs that hash to a given value without revealing the inputs themselves. + +### What You'll Learn + +- How to generate a Hash Checker circuit using Remix-IDE's workspace templates. +- Understanding the Circom code for hashing and checking hashes. +- Performing a trusted setup using Groth16. +- Generating zero-knowledge proofs. diff --git a/locales/de/CircomHashChecker/step-2/README.md b/locales/de/CircomHashChecker/step-2/README.md new file mode 100644 index 000000000..bc827019e --- /dev/null +++ b/locales/de/CircomHashChecker/step-2/README.md @@ -0,0 +1,37 @@ +Follow these steps to create the Hash Checker workspace in Remix-IDE. + +### Step 1: Access the Workspace Templates + +1. In the **File Explorer** sidebar, click on the **hamburger menu icon** (three horizontal lines). + + hamburger-menu + +2. Select **"Create Using Template"** from the dropdown. + + create-using-template + +### Step 2: Find the Hash Checker Template + +1. In the main panel, scroll down to the **"Circom ZKP"** section. + + create-zkp-section + +2. Locate the **"Hash Checker"** item. + +### Step 3: Create the Workspace + +1. Click on the **"Create"** button on the Hash Checker item. + + create-hash-checker + +2. In the modal pop-up, provide a **workspace name** (e.g., `hash-checker-workspace`). + + workspace-name-modal + +3. Click **"OK"** to create the template. + +### Result + +- The workspace is created with the necessary files and directories. + + workspace-name-modal diff --git a/locales/de/CircomHashChecker/step-3/README.md b/locales/de/CircomHashChecker/step-3/README.md new file mode 100644 index 000000000..b3ac14050 --- /dev/null +++ b/locales/de/CircomHashChecker/step-3/README.md @@ -0,0 +1,32 @@ +## Exploring `calculate_hash.circom` + +Navigate to the `circuits` directory and open `calculate_hash.circom`. This file contains the Circom code for the Hash Checker circuit. + +### Code Breakdown + +#### Pragma and Includes: + +- `pragma circom 2.0.0;` specifies the Circom version. +- `include "circomlib/circuits/poseidon.circom";` fetch and includes the Poseidon hash function from [CircomLib](https://github.com/iden3/circomlib). + +#### `CalculateHash` Template: + +- Defines inputs `value1`, `value2`, `value3`, `value4`. +- Uses the `Poseidon` hash function to compute a hash of these values.\ +- Outputs `out`, which is the hash. + +#### `HashChecker` Template: + +- Inputs are the same values plus a `hash`. +- Instantiates `CalculateHash` as `calculateSecret`. +- Computes `calculatedHash`. +- Uses `assert(hash == calculatedHash);` to ensure the provided hash matches the calculated hash. + +#### Main Component: + +- `component main {public [hash]} = HashChecker();` +- Specifies that `hash` is a `public` input, while the values are `private`. + +### Purpose + +The circuit allows someone to prove they know `value1`, `value2`, `value3`, and `value4` that hash to a specific `hash` without revealing the values themselves. diff --git a/locales/de/CircomHashChecker/step-4/README.md b/locales/de/CircomHashChecker/step-4/README.md new file mode 100644 index 000000000..537c6a241 --- /dev/null +++ b/locales/de/CircomHashChecker/step-4/README.md @@ -0,0 +1,32 @@ +## Compiling the Circuit + +### Selecting the Compiler Version + +1. Go to the **Circuit Compiler** plugin in the sidebar. +2. Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +### Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +### Compiling the Circuit + +1. Click on the **Compile** button. +2. Wait for the compilation to complete. A success badge will appear if compilation is successful. + +compilation-success + +### Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/de/CircomHashChecker/step-5/README.md b/locales/de/CircomHashChecker/step-5/README.md new file mode 100644 index 000000000..c3ea8509b --- /dev/null +++ b/locales/de/CircomHashChecker/step-5/README.md @@ -0,0 +1,25 @@ +## Performing a Trusted Setup + +1. **Access the Setup and Exports Section**: + +- After successful compilation, the **Setup and Exports** section becomes available in the plugin. + +2. **Select Proving Scheme**: + +- Choose **Groth16** from the **Proving Scheme** dropdown. + +3. **Select Power of Tau File**: + +- Choose the appropriate **Power of Tau** file from the dropdown. If unsure, use the default option. + +4. **Export Verification Key and Contract** (optional): + +- Enable **Export Verification Key** to save the verification key to the File Explorer. +- Enable **Export Verifier Contract** to save the Solidity contract for on-chain verification. + +trusted-setup + +5. **Run the Trusted Setup**: + +- Click on the **Run Setup** button. +- Wait for the process to complete. This may take some time depending on the circuit complexity. diff --git a/locales/de/CircomHashChecker/step-6/README.md b/locales/de/CircomHashChecker/step-6/README.md new file mode 100644 index 000000000..03b848f81 --- /dev/null +++ b/locales/de/CircomHashChecker/step-6/README.md @@ -0,0 +1,28 @@ +## Compute Witness + +1. **Access the Compute Witness Section**: + - After the trusted setup, the **Compute Witness** section becomes available. + +2. **Input Values**: + - You'll see input fields for `value1`, `value2`, `value3`, `value4`, and `hash`. + - Enter values for each input. For example: + - `value1`: `1234` + - `value2`: `2` + - `value3`: `3` + - `value4`: `4` + +3. **Calculate the Hash**: + + - Compute the Poseidon hash of the four values using an external tool or library compatible with the Poseidon hash function. + - For the values above, here is the computed Poseidon hash `16382790289988537028417564277589554649233048801038362947503054340165041751802`. + - Enter the calculated `hash` value in the `hash` input field. + + compute-witness + +4. **Compute the Witness**: + + - Click on the **Compute Witness** button. + - Wait for the process to complete. A success badge will appear if the witness is computed successfully. + - If successful, you'll see `calculate_hash.wtn` created in the `.bin` directory in the file explorer. + + witness-computed diff --git a/locales/de/CircomHashChecker/step-7/README.md b/locales/de/CircomHashChecker/step-7/README.md new file mode 100644 index 000000000..e6ae80fea --- /dev/null +++ b/locales/de/CircomHashChecker/step-7/README.md @@ -0,0 +1,21 @@ +## Generate Proof + +1. **Access the Generate Proof Section**: + - After computing the witness, expand the **Generate Proof** section. + +2. **Configure Proof Generation**: + - **Export Verifier Calldata**: Enable this option if you plan to verify the proof on-chain. + +3. **Generate the Proof**: + + - Click on the **Generate Proof** button. + - Wait for the proof generation to complete. + + generate-proof + +4. **View the Proof**: + + - The proof data will be displayed in the File Explorer. + - **Congratulations!** You've successfully compiled the `Hash Checker` circuit, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + + generate-proof diff --git a/locales/de/CircomHashChecker/step-8/README.md b/locales/de/CircomHashChecker/step-8/README.md new file mode 100644 index 000000000..e489a8cab --- /dev/null +++ b/locales/de/CircomHashChecker/step-8/README.md @@ -0,0 +1,34 @@ +## Understanding `groth16_trusted_setup.ts` + +Navigate to `scripts/groth16/groth16_trusted_setup.ts`. This script performs the trusted setup necessary for generating proofs. + +### Code Breakdown + +#### Circuit Compilation: + +- Uses `remix.call('circuit-compiler', 'generateR1cs', ...)` to generate `R1CS` (Rank-1 Constraint System) from the circuit. + +#### Trusted Setup Steps: + +- `snarkjs.zKey.newZKey`: Initializes the proving key (`zkey_0`). +- `snarkjs.zKey.contribute`: Adds contributions to the proving key (`zkey_1`). +- `snarkjs.zKey.beacon`: Finalizes the proving key (`zkey_final`). + +#### Verification: + +- `snarkjs.zKey.verifyFromR1cs`: Verifies the proving key against the `R1CS` and initial parameters. + +#### Exporting Keys: + +- Exports the verification key to `scripts/groth16/zk/keys/verification_key.json`. +- Exports the final proving key (`scripts/groth16/zk/keys/zkey_final.txt`). + +### Purpose + +- Performs the trusted setup required for the `Groth16` proving system. +- Generates the necessary keys for proof generation and verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"setup done."` logged in the terminal. diff --git a/locales/de/CircomHashChecker/step-9/README.md b/locales/de/CircomHashChecker/step-9/README.md new file mode 100644 index 000000000..653d5ced1 --- /dev/null +++ b/locales/de/CircomHashChecker/step-9/README.md @@ -0,0 +1,37 @@ +## Understanding `groth16_zkproof.ts` + +Navigate to `scripts/groth16/groth16_zkproof.ts`. This script generates the zero-knowledge proof and prepares it for verification. + +### Code Overview + +#### Loading Files: + +- Reads the R1CS and WASM files generated from the circuit. +- Loads the final proving key (`zkey_final`) and verification key (`vKey`). + +#### Defining Inputs: + +- Sets the private values (`value1`, `value2`, `value3`, `value4`). +- Computes the `hash` using Poseidon from [CircomLib](https://github.com/iden3/circomlib). + +#### Witness Calculation and Proof Generation: + +- Calculates the witness (`wtns`). +- Checks the witness against the `R1CS`. +- Generates the proof using `Groth16`. +- Verifies the proof. + +#### Exporting Verifier Contract and Inputs: + +- Generates a Solidity verifier contract. +- Exports the proof inputs to `input.json`. + +### Purpose + +- Generates a zero-knowledge proof that the prover knows values hashing to a specific hash. +- Prepares the verifier contract and inputs for on-chain verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"zk proof validity"` logged in the terminal. diff --git a/locales/de/CircomIntro/README.md b/locales/de/CircomIntro/README.md new file mode 100644 index 000000000..c58b2daec --- /dev/null +++ b/locales/de/CircomIntro/README.md @@ -0,0 +1,21 @@ +Intro to Circom + +This is an introduction to Circom. You'll learn how to write, compile, and test arithmetic circuits in Circom. We'll go over how to do this within Remix-IDE. + +Tutorial Overview + +``` +Step 1: Introduction +Step 2: Setting Up Remix-IDE and Installing the Circuit-Compiler Plugin +Step 3: Writing Your First Circom Circuit +Step 4: Compiling the Circuit Using the Plugin +Step 5: Performing a Trusted Setup +Step 6: Computing the Witness +Step 7: Generating the Proof +``` + +Prerequisites: + +``` +Basic understanding of cryptography and zero-knowledge proofs is helpful but not required. +``` diff --git a/locales/de/CircomIntro/config.yml b/locales/de/CircomIntro/config.yml new file mode 100644 index 000000000..d6dfdca46 --- /dev/null +++ b/locales/de/CircomIntro/config.yml @@ -0,0 +1,29 @@ +id: circom-intro +name: Intro to Circom +summary: A intro to using Circom for creating arithmetic circuits. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction + path: step-1 + - + name: Installing the Circuit-Compiler + path: step-2 + - + name: Writing Your First Circom Circuit + path: step-3 + - + name: Compiling the Circuit Using the Plugin + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Computing the Witness + path: step-6 + - + name: Generating the Proof + path: step-7 diff --git a/locales/de/CircomIntro/step-1/README.md b/locales/de/CircomIntro/step-1/README.md new file mode 100644 index 000000000..0766ce6f4 --- /dev/null +++ b/locales/de/CircomIntro/step-1/README.md @@ -0,0 +1,13 @@ +Welcome to this beginner-level tutorial on Circom using Remix. In this tutorial, you'll learn the basics of Circom, a domain-specific language used for creating arithmetic circuits. + +**What is Circom?** + +Circom is a language designed for writing arithmetic circuits that can be used in zero-knowledge proofs, particularly zk-SNARKs. It allows developers to define complex mathematical circuits that can prove knowledge of certain data without revealing it. + +**Why Use Remix-IDE for Circom?** + +- **Ease of Use:** Remix-IDE provides a user-friendly interface that simplifies the development process. +- **Integrated Tools:** With plugins like `circuit-compiler`, you can compile Circom code, perform trusted setups, compute witnesses, and generate proofs all within the same environment. +- **No Installation Required:** As a web-based IDE, you can start coding immediately without setting up a local development environment. + +In the next steps, we'll guide you through setting up Remix-IDE for Circom development and help you write your first circuit. diff --git a/locales/de/CircomIntro/step-2/README.md b/locales/de/CircomIntro/step-2/README.md new file mode 100644 index 000000000..4b228c298 --- /dev/null +++ b/locales/de/CircomIntro/step-2/README.md @@ -0,0 +1,25 @@ +In this step, we'll set up Remix for Circom development by activating the `Circom ZKP compiler` plugin. + +## Activating the Circom ZKP compiler + +1. At the bottom of the icon panel on the left of the screen, click on the **Plugin Manager** (the plug icon). + 2.In the search bar, type **Circom**. +2. Find the **Circuit Compiler** plugin in the list and click on the **Activate** button. +3. The plugin will now appear in your sidebar. + +install-plugin + +## The Circom Compiler Interface + +- **Compiler Version Dropdown:** Select the Circom compiler version you wish to use. +- **Auto Compile Checkbox:** Enable this to automatically compile your circuit whenever you make changes. +- **Hide Warnings Checkbox:** Enable this to suppress compiler warnings. +- **Advanced Configuration:** Click to expand options for selecting the prime field (e.g., BN128, BLS12381). + +compiler-interface + +With the plugin installed, you're now ready to start writing Circom code in Remix-IDE. + +**Note:** Make sure your internet connection is stable, as Remix-IDE is a web-based tool. + +In the next step, we'll write our first Circom circuit. diff --git a/locales/de/CircomIntro/step-3/README.md b/locales/de/CircomIntro/step-3/README.md new file mode 100644 index 000000000..6424668f6 --- /dev/null +++ b/locales/de/CircomIntro/step-3/README.md @@ -0,0 +1,38 @@ +Let's write a simple Circom circuit. + +## Creating a New Circuit File + +1. In the **File Explorer** on the left sidebar, click on the **Create New File** icon. +2. Name your file `multiplier.circom` and press **Enter**. + +create-new-file + +## Writing the Circuit + +Open `multiplier.circom` and add the following code: + +```circom +pragma circom 2.0.0; + +template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; +} + +component main = Multiplier(); +``` + +## Explanation: + +- template `Multiplier()`: Defines a new circuit template called Multiplier. +- `signal input a;` and `signal input b;`: Declare input signals a and b. +- `signal output c;`: Declare an output signal c. +- `c <== a * b;`: Constrain c to be the product of a and b. +- `component main = Multiplier();`: Instantiates the Multiplier circuit as main, which is required for the compiler. + +### NB: + +Signals are values in a cryptographic circuit that are strictly determined by the circuit's equations and constraints. Think of a signal as a value that must follow specific mathematical rules defined by the circuit—once set, it can't be changed arbitrarily. In regular programming, variables are flexible and can be updated or reassigned as needed, whereas, signals can't be altered freely. diff --git a/locales/de/CircomIntro/step-4/README.md b/locales/de/CircomIntro/step-4/README.md new file mode 100644 index 000000000..ad3f2a089 --- /dev/null +++ b/locales/de/CircomIntro/step-4/README.md @@ -0,0 +1,34 @@ +With your `multiplier.circom` circuit ready, let's compile it using the Circuit Compiler plugin. + +## Selecting the Compiler Version + +Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +## Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +## Compiling the Circuit + +1. Click on the **Compile** button. +2. The compiler will process your circuit. +3. If successful, you'll see a compilation success message. + +compilation-success + +**Note:** If there are any errors, they will be displayed in the console. Check your code for typos or syntax errors. + +## Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/de/CircomIntro/step-5/README.md b/locales/de/CircomIntro/step-5/README.md new file mode 100644 index 000000000..8e8496bbd --- /dev/null +++ b/locales/de/CircomIntro/step-5/README.md @@ -0,0 +1,26 @@ +After compiling your circuit, you need to perform a trusted setup to generate proving and verification keys. + +## Understanding Trusted Setup + +- **Trusted Setup:** A process required for zk-SNARKs to generate the necessary parameters for proof generation and verification. +- You can choose between different protocols like **Groth16** and **Plonk**. + +## Performing the Trusted Setup + +1. In the **Setup and Exports** section, select the **Proving Scheme**: + - Choose between **Groth16** or **Plonk**. We'll use **Groth16** for this tutorial. + +2. Choose the appropriate **Power of Tau** file from the dropdown. This file is necessary for the trusted setup. + - If unsure, select the default option. + +3. Click on the **Setup** button to start the trusted setup process. + +4. You can enable **Export Verification Key** to get the verification parameters. + +5. You can enable **Export Verification Contract** if you intend to verify proofs on-chain. + +trusted-setup + +**Note:** The trusted setup may take some time, depending on the complexity of your circuit. + +In the next step, we'll compute the witness for our circuit. diff --git a/locales/de/CircomIntro/step-6/README.md b/locales/de/CircomIntro/step-6/README.md new file mode 100644 index 000000000..e13d33d32 --- /dev/null +++ b/locales/de/CircomIntro/step-6/README.md @@ -0,0 +1,27 @@ +With the trusted setup complete, you can now compute the witness for your circuit based on specific inputs. + +## What is a Witness? + +- A **Witness** is a set of values that satisfy all the constraints of your circuit. It includes all the intermediate numbers and results that satisfy the circuit's rules. The witness is used in zero-knowledge proofs to demonstrate that you know a valid solution to the problem without actually showing the solution itself. This allows others to verify that you did everything correctly while keeping your specific numbers and calculations private. +- It is essential for generating a proof. + +## Inputting Values + +1. In the **Compute Witness** section, you'll see input fields dynamically generated based on your circuit's inputs. +2. Enter values for `a` and `b`. For example: + - `a = 3` + - `b = 4` + +compute-witness + +## Computing the Witness + +1. After entering the inputs, click on the **Compute Witness** button. +2. The plugin will compute the witness based on your inputs. +3. If successful, you'll see `multiplier.wtn` created in the `.bin` directory in the file explorer. + +witness-computed + +**Note:** If there are any errors, ensure that your inputs are valid and satisfy the circuit's constraints. + +In the next step, we'll generate a proof using the computed witness. diff --git a/locales/de/CircomIntro/step-7/README.md b/locales/de/CircomIntro/step-7/README.md new file mode 100644 index 000000000..f5cf332a9 --- /dev/null +++ b/locales/de/CircomIntro/step-7/README.md @@ -0,0 +1,31 @@ +With the witness computed, the final step is to generate a proof that can be verified by others. + +## Generating the Proof + +1. In the **Generate Proof** section, you have the option to **Export Verifier Calldata**. + - Enable the **Export Verifier Calldata** checkbox if you plan to verify the proof on-chain. +2. Click on the **Generate Proof** button. + +generate-proof + +## Understanding the Output + +- After generating the proof, the plugin will display the proof data. +- If you enabled **Export Verifier Calldata**, it will also provide the calldata needed for on-chain verification. + +proof-generated + +## Next Steps + +- **Verification:** You can use the verification key or contract exported earlier to verify the proof. +- **On-Chain Verification:** If you're familiar with smart contracts, you can deploy the verification contract and use the calldata to perform on-chain verification. + +**Congratulations!** You've successfully written a Circom circuit, compiled it, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + +## Additional Resources + +- [Circom Documentation](https://docs.circom.io/) +- [Remix-IDE Documentation](https://remix-ide.readthedocs.io/) +- [Zero-Knowledge Proofs Explained](https://zkproof.org/) + +Feel free to experiment with more complex circuits and explore the capabilities of Circom and Remix-IDE further. diff --git a/locales/de/DeployWithLibraries/1_Writing_a_Library/step1.md b/locales/de/DeployWithLibraries/1_Writing_a_Library/step1.md new file mode 100644 index 000000000..1ad984835 --- /dev/null +++ b/locales/de/DeployWithLibraries/1_Writing_a_Library/step1.md @@ -0,0 +1,17 @@ +A libraries looks like a **contract** but use the keyword `library` + +A library typically is a collection of useful functions sitting out there on the blockchain that any contract can use. Because the library is already deployed, it saves the deployment costs of the many contracts that use it. + +In the following contract: + +- Make a library with the name `LibraryForTest`. + +It is possible to put a library in same file with another contract. So put the library below the contract. + +This library should have a method called `getFromLib` method which returns `3`. + +- Update the `get` method in the `test` contract to use the `LibraryForTest` library. The function `get` should return the value it receives from `getFromLib`. + +--------- + +You can find more info about libraries in this section of the Solidity Docs. diff --git a/locales/de/DeployWithLibraries/2_Generate_Metadata/step2.md b/locales/de/DeployWithLibraries/2_Generate_Metadata/step2.md new file mode 100644 index 000000000..218c86ff9 --- /dev/null +++ b/locales/de/DeployWithLibraries/2_Generate_Metadata/step2.md @@ -0,0 +1,38 @@ +## Deploying Library + +The **library** from the previous chapter was in the same file as the **contract**. However, they won't be deployed together and will have different addresses. + +In order to use a library, the calling contract must have the library's **address**. + +But the library's address is not directly specified in the solidity code. The calling contract's compiled bytecode contains a **placeholder** where library's **addresses** will go. + +At deployment of the **calling contract**, Remix will look in the contract's **metadata** for the library's address and will update the placeholder with the address. + +So before deploying a contract that calls a library, you need to generate the contract's metadata (AKA its **build artifact**) and then you need to input the library's address into the metadata file. + +A contract's metadata is generated at **compile time**. + +Let's setup Remix to generate the **metadata file**. + +- Go to the settings module by clicking on the settings ![settings](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/settings.png "Settings") icon in the icon panel. + +![settings module](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_settings.png "Settings Module") + +- And check the first option `Generate contract metadata`. + +# Compile and generate metadata (JSON) file. + +1. Open the Solidity Compiler ![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +2. Compile `2_contractSimpleLibrary.sol`. + +3. Switch to the File Explorer ![File Explorer](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_file_explorer.png "File Explorer") + +4. Navigate to the newly create JSON files. + - It should be in the folder: + +**browser/.learneth/DeployWithLibraries/2_Generate_Metadata/artifacts/** + +5. Select the newly created JSON file created from the contract. It has the **same name** as the contract `sample` but with the extension **json**: `sample.json` (don't select the library's metadata `contractSimpleLibrary.json`). + +In the next step we'll make some adjustments to the metadata file. diff --git a/locales/de/DeployWithLibraries/3_Edit_Metadata/step3.md b/locales/de/DeployWithLibraries/3_Edit_Metadata/step3.md new file mode 100644 index 000000000..1555d645d --- /dev/null +++ b/locales/de/DeployWithLibraries/3_Edit_Metadata/step3.md @@ -0,0 +1,12 @@ +The `Deploy` property in `sampleContract.json` contains everything you need for telling Remix IDE the address of the library for a specific network. + +- `
` contains the address of the library that is already deployed. You have to specify this address for each network. +- `autoDeployLib` is a boolean and tells Remix IDE if it should autodeploy the library before deploying the contract. + +Basically if `autoDeployLib` is **true**, the `
` will not be used and Remix will automatically deploy the library before deploying the contract. + +For the purpose of this demo - we are mimicking a situation where the library has already been deployed because this is a more common situation. + +So set `autoDeploy` to **false**, for the `VM:-` entry. + +Move to next Step. diff --git a/locales/de/DeployWithLibraries/4_Linking_and_Deploying/step4.md b/locales/de/DeployWithLibraries/4_Linking_and_Deploying/step4.md new file mode 100644 index 000000000..ad5f52e2d --- /dev/null +++ b/locales/de/DeployWithLibraries/4_Linking_and_Deploying/step4.md @@ -0,0 +1,25 @@ +Switch to the `Deploy & Run` module +![Run transaction](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/remix_runtransaction.png "Run Transaction") + +- Select the Remix VM Environment and select the `sampleContract` contract in the list of compiled contracts. + +- Click on `Deploy` + +The terminal should output something like `creation of sample errored:
is not a valid address. Please check the provided address is valid.` +That is expected: **We have set `autoDeployLib` to false, so Remix expects to have an address and not just `
`** + +So we need deploy the library to get its address. + +- Select the library `aLib` in the list of compiled contract and hit `deploy` + + ![Choose aLib](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/contract_alib.png "Choose aLib") + +- Click the clipboard icon to copy the address of the library. + + ![Copy lib1](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/alib_copy.png "Copy") + +- Paste it into the **contract sample's** metadata JSON. + +- Reselect the `sampleContract` contract in the `Run transaction` module and hit deploy. + +- Deploy should now be successful. diff --git a/locales/de/DeployWithLibraries/5_Under_The_Hood/step5.md b/locales/de/DeployWithLibraries/5_Under_The_Hood/step5.md new file mode 100644 index 000000000..860b48b24 --- /dev/null +++ b/locales/de/DeployWithLibraries/5_Under_The_Hood/step5.md @@ -0,0 +1,30 @@ +Switch to the `Solidity compiler` module +![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +- Select the `sampleContract` contract in the list of compiled contracts. +- click on `ByteCode`, it should copy the following to the clipboard: + +``` +{ + "linkReferences": { + "browser/contractSimpleLibrary.sol": { + "lib1": [ + { + "length": 20, + "start": 115 + } + ] + } + }, + "object": "608060405234801561001057600080fd5b5060f68061001f6000396000f3fe6080604052600436106039576000357c0100000000000000000000000000000000000000000000000000000000900480636d4ce63c14603e575b600080fd5b348015604957600080fd5b5060506052565b005b73__$d42d70ba92b626965f4c69b39148e37a33$__63fea24e5f6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801560b157600080fd5b505af415801560c4573d6000803e3d6000fd5b5050505056fea165627a7a7230582068c9a3a9a5cbfd26cfdab2534abfc926912d9b89eaa14e36c8248b7e7eb0ab090029", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xF6 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x39 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x3E JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x50 PUSH1 0x52 JUMP JUMPDEST STOP JUMPDEST PUSH20 0x0 PUSH4 0xFEA24E5F PUSH1 0x40 MLOAD DUP2 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH1 0xB1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS DELEGATECALL ISZERO DUP1 ISZERO PUSH1 0xC4 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 PUSH9 0xC9A3A9A5CBFD26CFDA 0xb2 MSTORE8 0x4a 0xbf 0xc9 0x26 SWAP2 0x2d SWAP12 DUP10 0xea LOG1 0x4e CALLDATASIZE 0xc8 0x24 DUP12 PUSH31 0x7EB0AB09002900000000000000000000000000000000000000000000000000 ", + "sourceMap": "63:85:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63:85:0;;;;;;;" +} +``` + +This is basically what the compiler is returning: + +- `linkReferences` describes what are the libraries used by the contract. +- `object` is the compiled contract (bytecode). This is what gets deployed and saved onto the blockchain. In this example, the value `__$d42d70ba92b626965f4c69b39148e37a33$__` inside the bytecode is just a placeholder for the library address. In your case, the placeholder will be between `__$` and `$__`. + +The metadata JSON from Remix IDE tells Remix to replace the placeholder with the given address. diff --git a/locales/de/DeployWithLibraries/README.md b/locales/de/DeployWithLibraries/README.md new file mode 100644 index 000000000..fb31b1264 --- /dev/null +++ b/locales/de/DeployWithLibraries/README.md @@ -0,0 +1,3 @@ +**Libraries** are deployed contracts that do not store state and are used by other contracts to decrease their size and thus their deployment costs. + +Learn to work with **Libraries** in Remix - you won't need to whisper. diff --git a/locales/de/DeployWithLibraries/config.yml b/locales/de/DeployWithLibraries/config.yml new file mode 100644 index 000000000..0816e2346 --- /dev/null +++ b/locales/de/DeployWithLibraries/config.yml @@ -0,0 +1,8 @@ +--- +id: deploylibraries +name: Deploy with Libraries +summary: Write, Deploy and link a Library to a Contract +level: 3 +tags: + - Remix + - Solidity diff --git a/locales/de/ERC20TokenCourse/README.md b/locales/de/ERC20TokenCourse/README.md new file mode 100644 index 000000000..25a6ccf95 --- /dev/null +++ b/locales/de/ERC20TokenCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Token Course + +Learn to understand and create ERC20 tokens. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/de/ERC20TokenCourse/config.yml b/locales/de/ERC20TokenCourse/config.yml new file mode 100644 index 000000000..8c12a5213 --- /dev/null +++ b/locales/de/ERC20TokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: tokenCourse +name: Solidity ERC20 Token Course +summary: Learn how to create your own ERC20 tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - ERC20 +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc20-interface + - + name: 3. Token Creation + path: erc20-token-creation + - + name: 4. Interaction + path: erc20-interaction + - + name: 5. Testnet Deployment + path: erc20-testnet-deployment + - + name: 6. Extensions + path: erc20-extensions diff --git a/locales/de/ERC20TokenCourse/erc20-extensions/erc20extensions.md b/locales/de/ERC20TokenCourse/erc20-extensions/erc20extensions.md new file mode 100644 index 000000000..b3649fbba --- /dev/null +++ b/locales/de/ERC20TokenCourse/erc20-extensions/erc20extensions.md @@ -0,0 +1,33 @@ +The ERC20 standard only describes the required and optional functionality that your contract needs, but you can add additional functionality. + +In this section, we added the functionality to burn and mint tokens, as well as the ability to pause the contract, by using OpenZeppelin extensions. + +Of course, you can write your own ERC20 token contract implementation or extensions and import them into your contract. But OpenZeppelin contracts have been audited by security experts and are a great way to add desired functionality. + +### Mintable + +The mint function allows the creator of the contract to mint (create) additional tokens after the contract has been deployed (line 22). As input parameters, the function needs the address that the tokens will be minted to, and the amount of tokens that should be minted. + +We don't have to import `mint()` from another contract since the mint function is already part of the ERC20 contract implementation of OpenZeppelin. We import `Ownable` (line 7) which is a contract module that provides a basic access control mechanism that allows an owner to have exclusive access to specific functions. In this contract, we add the inherited `onlyOwner` modifier to the `mint` function (line 22) and restrict access to this function to the "owner". + +The contract will inherit additional functions like owner(), transferOwnership() and renounceOwnership() to manage access, from the Ownable contract. + +### Burnable + +By importing the "ERC20Burnable" (line 5) and inheriting its functions (line 9) our contract allows token holders to destroy their tokens as well as the tokens in their allowance. +For more information, have a look at the ERC20Burnable contract. + +### Pausable + +With the "Pausable" contract module (line 6 and 9) the owner is able to pause (line 14) and unpause (line 18) the contract. In the pause state, tokens can't be transferred, which can be helpful in emergency scenarios. +For more information, have a look at the Pausable contract. + +Have a look at the OpenZeppelins Contract Wizard, which allows you to easily add additional functionality. + +If you successfully completed this course, try the Learneth NFT Course as the next step in your journey. + +## ⭐️ Assignment + +1. Try to mint tokens to an account after deployment. Call `totalSupply()` and `balanceOf()` to confirm the correct execution. +2. Burn tokens and then call `totalSupply()` and `balanceOf()` to confirm the correct execution. +3. Test the pause function by pausing the contract using the owner account and trying to make a transfer with a second account. The transaction should not be able to be executed and will throw the exception: "Pausable: paused". diff --git a/locales/de/ERC20TokenCourse/erc20-interaction/er20interaction.md b/locales/de/ERC20TokenCourse/erc20-interaction/er20interaction.md new file mode 100644 index 000000000..5c082b248 --- /dev/null +++ b/locales/de/ERC20TokenCourse/erc20-interaction/er20interaction.md @@ -0,0 +1,87 @@ +In this section, we will deploy a contract in our browser and test its functionality. + +### 1. Deploy the contract + +**1.1** Compile your EduCoin contract in the "Solidity compiler" module of the Remix IDE. + +**1.2** In the "Deploy & run transactions" module, select your contract "EduCoin" in the contract input field and click on the "Deploy" button. Always make sure to select the correct contract in the contract selector input field. + +**GIF** Compile and deploy: Compile and deploy contract + +### 2. Test the functions + +Expand the token contract functions in the IDE. + +#### 2.1 Decimals + +Click on the "decimals" button to call the decimals() function. +It should return "18". + +#### 2.2 Name + +Click on the "name" button to call the name() function. +It should return "EduCoin". + +#### 2.3 Symbol + +Click on the "symbol" button to call the symbol() function. +It should return "EDC". + +#### 2.4 Total supply + +Click on the "totalSupply" button to call the totalSupply() function. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test decimals, name, symbol, and totalSupply functions: Test transfer function + +#### 2.5 Balance of + +**2.5.1** Go to the "ACCOUNT" section in the sidebar and copy the displayed address by using the copy icon next to it. + +**2.5.2** Paste the address in the input field next to the "balanceOf" function button and click on the button. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test balanceOf function: Test transfer function + +#### 2.6 Transfer + +We will transfer EduCoin from one account to a second account. + +**2.6.1** Go to the "ACCOUNT" section in the sidebar and click on the displayed address. This should open a dropdown. Select the second address displayed and copy its address (account 2). + +**2.6.2** Open the dropdown and select the first account again (account 1), because this is the account that we want to use to make the transfer. + +**2.6.3** Paste the address in the input field next to the "transfer" function button, input the number 500000000000000000000, and click on the button. + +**2.6.4** If you check the balances for account 1 and account 2, they should both return the amount 500000000000000000000. + +**GIF** Test transfer function: Test transfer function + +#### 2.7 Approve + +We will now allow account 1 to spend tokens on behalf of account 2. + +**2.7.1** Go to the "Account" section, copy the address of account 1, then set it to account 2 again. + +**2.7.2** In the approve function, enter the address of account 1 as the input for spender and set the amount to 250000000000000000000. + +**GIF** Test approve function: Test approve function + +#### 2.8 Allowance + +Next to the "allowance" button enter the address of account 2 as the owner and account 1 as the spender; click on the button. +It should return 1000000000000000000000. + +**GIF** Test allowance function: Test allowance function + +#### 2.9 TransferFrom + +Now account 1 will transfer 250000000000000000000 tokens from account 2 to its own account. + +**2.9.1** Select account 1 in the "ACCOUNT" section. + +**2.9.2** Next to the "transferFrom" button enter the address of account 2 as the sender and account 1 as the recipient, enter 250000000000000000000 as the amount and click on the button. + +**2.9.3** Check the balances of accounts 2 and 1, they should return 250000000000000000000 and 750000000000000000000. + +**GIF** Test transferFrom function: Test transferFrom function diff --git a/locales/de/ERC20TokenCourse/erc20-interface/erc20interface.md b/locales/de/ERC20TokenCourse/erc20-interface/erc20interface.md new file mode 100644 index 000000000..5c4e8137c --- /dev/null +++ b/locales/de/ERC20TokenCourse/erc20-interface/erc20interface.md @@ -0,0 +1,76 @@ +ERC20 (Ethereum Request for Comments 20) is a standard for token contracts that manages fungible tokens on the Ethereum blockchain. + +Fungible tokens are all equal to each other and have the same value, behavior, and rights. Fungible tokens are often used as a medium of exchange, like the currencies ETH or BTC. However, they can also have other use cases like voting rights or reputation. + +If you want to know more about the ERC20 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +To get an overview of the required functionality of an ERC20 token contract, we will look at an interface that interacts with an ERC20 contract. +This interface (line 9) is part of the open-source contract library provided by OpenZeppelin. + +## ERC20 Functions + +Contracts compliant with the ERC20 standard must implement the following six functions: + +### totalSupply + +The function `totalSupply` (line 13) returns the total amount of tokens available. + +### balanceOf + +The function `balanceOf` (line 18) returns the amount of tokens owned by the account with the address `account`. + +### transfer + +The function `transfer` (line 27) transfers `amount` of tokens to the address `recipient`. +This function **must** emit (produce) a `Transfer` event (see below) and **should** throw an exception when the sender doesn't have enough tokens to make the transfer. + +### approve + +The function `approve` (line 52) creates an allowance for the address `spender` to transfer `amount` of tokens on behalf of the account calling the function. + +### allowance + +The function `allowance` (line 36) returns the amount of tokens that the address `spender` is allowed to spend on behalf of the account with the address `owner`. + +### transferFrom + +The function `transferFrom` (line 63) transfers `amount` of tokens on behalf of the address `sender` to the address `recipient`. +This function **must** emit a `Transfer` event. + +## ERC20 Events + +ERC20 contracts must also emit two events: + +### Transfer + +The `Transfer` (line 71) event must be emitted when `value` amount of tokens are transferred from the account with the address `indexed from` to `indexed to`. The parameters `from` and `to` are `indexed` allowing us to search for these events using the indexed parameters as filters. + +### Approval + +The `Approval` (line 77) event must be emitted when the account `indexed owner` approves the account `indexed spender` to transfer `value` amount of tokens on its behalf. + +## ERC20 Optional functions + +In addition to the mandatory functions and events, there are also three optional functions specified in the ERC20 standard that are not implemented in this interface: + +### name + +`function name() external view returns (string);` + +Returns the name of the token. + +### symbol + +`function symbol() external view returns (string);` + +Returns the symbol of the token. + +### decimals + +`function decimals() external view returns (uint8);` + +Returns the number of decimal places the token uses. + +You may want to use decimals to make your token divisible into arbitrary amounts like 1.5 ETH when displayed. The EVM (Ethereum virtual machine) only supports integer numbers. That's why the ERC20 standard suggests to implement the decimal functionality that specifies how many decimal places a token has. 18 decimal places is the industry standard. diff --git a/locales/de/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md b/locales/de/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md new file mode 100644 index 000000000..94b513922 --- /dev/null +++ b/locales/de/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md @@ -0,0 +1,41 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to a testnet of the Ethereum blockchain. This testnet behaves very similarly to the real blockchain (mainnet), but does not require real ETH to pay for transactions. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token + +In order to make transactions on the testnet we need Ethereum testnet tokens, which you can receive from something called a _faucet_. + +**2.1** Switch your Metamask network by clicking on the "Ethereum Mainnetwork" drop down and selecting "Ropsten Test Network". If you don’t see any test networks, click on the "Show/hide" link and enable "Show test networks" in the settings. + +**2.2** Go to https://faucet.ropsten.be/, enter the address of your account, and claim testnet ETH. You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Deployment + +Make sure the EduCoin contract is compiled. + +**3.1.** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It will ask you to connect your account which you should confirm. + +**3.2** Deploy the EduCoin contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. Copy the contract address. + +**3.4** In Metamask, click on assets, then click on the "Import tokens" link, and paste the address of your contract in the input field. + +You should now see a balance of 1000 EDC in your wallet. + +### 4. Make a transaction + +**4.1** Click on the identicon (visual representation of your address) in the Metamask wallet and create a second account (Account 2). + +**4.2** Copy the address of Account 2. + +**4.3** Switch to the first account (Account 1) and send 250 EDC to Account 2. Check the balances of Account 1 and Account 2. You might need to add the token address again for Account 2 to import the tokens and you will need testeth if you want to make a transaction with this account. + +You can also see your account balances if you look at the contract in Remix and call the `balanceOf` function using the addresses of Account 1 and Account 2. diff --git a/locales/de/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md b/locales/de/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md new file mode 100644 index 000000000..49b71abdd --- /dev/null +++ b/locales/de/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md @@ -0,0 +1,18 @@ +A token standard tells us what functionality the contract needs to comply with it. How this functionality is implemented is up to the developers. In this contract, we will use an ERC20 token contract implementation from OpenZeppelin (line 4). In this case, we import version 4.4.0 of the OpenZeppelin contracts. + +Have a look at their nicely documented ERC20 contract to have a better understanding of how an implementation might look. Apart from the functionality specified in the ERC20 standard, this contract provides additional functionality. + +We will create our own contract called MyToken (line 6), which inherits the functionality from the OpenZepplin ERC20 token contract implementation that we imported (line 4). + +This contract implements the optional functions `name()` and `symbol()` of the ERC20 Token standard and has a constructor where their values can be set during the deployment of the contract (line 7). +In this case, we are going to use the default values. We will call our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +Next, we make use of the inherited `_mint` function (line 8) that allows us to create tokens upon deployment of the contract. Inside the parameters, we specify the address of the account that receives the tokens and the amount of tokens that are created. +In this case, the account that deploys the contract will receive the tokens and we set the amount to 1000000 to the power of `decimals()`. The optional function `decimals()` of the ERC20 token standard is implemented and set to the default value of 18. This will create 1000000 tokens that will have 18 decimal places. + +## ⭐️ Assignment + +1. Rename your contract to `EduCoin`. +2. Rename your token to `EduCoin`. +3. Change the symbol of your token to `EDC`. +4. Change the amount of tokens that will be minted from 1000000 to 1000. diff --git a/locales/de/ERC20TokenCourse/introduction/introduction.md b/locales/de/ERC20TokenCourse/introduction/introduction.md new file mode 100644 index 000000000..4eaf7583c --- /dev/null +++ b/locales/de/ERC20TokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with the ERC20 token standard in the following sections. + +If you want to learn more about NFTs and the ERC721 token standard, have a look at the Learneth NFT Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/de/ERC721Auction/README.md b/locales/de/ERC721Auction/README.md new file mode 100644 index 000000000..325e4d60e --- /dev/null +++ b/locales/de/ERC721Auction/README.md @@ -0,0 +1,5 @@ +## NFT Auction Contract + +Learn how to write an ERC721 (NFT) auction contract. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/de/ERC721Auction/auction-contract-setup/auctionContractSetup.md b/locales/de/ERC721Auction/auction-contract-setup/auctionContractSetup.md new file mode 100644 index 000000000..945f0f803 --- /dev/null +++ b/locales/de/ERC721Auction/auction-contract-setup/auctionContractSetup.md @@ -0,0 +1,46 @@ +In this contract tutorial, we will learn how to create an ERC721 (NFT) auction contract. +We recommend to you, to do the Learneth "Solidity NFT Course" before starting this tutorial. + +In the following sections, we will create a contract that will enable a seller to auction an NFT to the highest bidder. This contract was created by the Solidity by Example project. In this first section, we will create an interface, the necessary state variables, and the constructor. + +### Interface + +We create the interface (line 5) for the ERC721 token since our contract will need to interact with it. We will need the `safeTransferFrom` (line 5), and` transferFrom` (line 11) methods. + +### EnglishAuction + +We create the four events `Start`, `Bid`, `Withdraw`, `End` (line 19-22) so we can log important interactions. + +Next, we will create the state variables that store all the necessary information about our auction on-chain. + +We create two state variables for the NFT we want to auction. In the variable `nft` (line 24) we store a representation of the NFT contract, that will allow us to call its functions by combining the interface IERC721 and the address of the NFT contract. +In `nftId` (line 25), we store the specific token id in our NFT contract that will be auctioned. + +Next, we need a variable to store the address of the person that is auctioning off the NFT, the `seller` (line 27). +We want our NFT contract to send the seller the proceeds of the auction when it is finished, that’s why use `address payable`. + +We create a state variable `endAt` (line 28) where we will store the end date of the auction. +We also create the two booleans, `started` (line 29) and `ended` (line 30), that keep track of whether the auction has started or ended. + +We create a variable `highestBidder` (line 32) where we will store the address of the highest bidder. We will send the highest bidder the NFT once the auction has ended. + +Finally, we need a uint `highestBid` (line 33) to store the highest bid and a mapping `bids` (line 34), where we can store the total value of bids that an account has made before withdrawing; more on this in the next section. + +### Constructor + +When the auctioneer deploys the contract, they need to provide a few arguments: +the address of the contract of the NFT they want to auction `_nft` (line 37), the token id of the NFT they want to auction `_nftId` (line 38), and a starting price that must be overbid to place the first bid in the auction,`_startingBid` (line 39). + +Once deployed, the state variables `nft` (line 41), `nftId` (line 42), `highestBid` (line 45) will be assigned the values from the arguments. The address of the `seller` that deployed the contract will be automatically read out via msg.sender and stored in the state variable `seller` (line 44). + +In the next section, we will enable the auctioneer to start the auction and bidders to place their bids. + +## ⭐️ Assignment + +We will use the assignment part of the following sections to give you instructions on testing your contract in the Remix VM environment of Remix. + +1. Deploy an NFT contract. You can use the NFT contract that we created in our "3.3 ERC721 - Token Creation" section. + +2. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +3. After deploying your contract, test if contract functions like `nft`, `nftId`, and `started` work as expected. diff --git a/locales/de/ERC721Auction/auction-start-bid/auctionContractStartBid.md b/locales/de/ERC721Auction/auction-start-bid/auctionContractStartBid.md new file mode 100644 index 000000000..c2b944e0c --- /dev/null +++ b/locales/de/ERC721Auction/auction-start-bid/auctionContractStartBid.md @@ -0,0 +1,42 @@ +In this section, we will create a function to start the auction and a function to bid on the NFT. + +### Start + +We use some control structures to check if necessary conditions are met before we let the seller start the auction. + +First, we check if the auction has already started (line 49). If it has started and our state variable `started` returns `true` we exit the function and throw an exception. + +The second condition we check for is whether the seller is executing the function (line 50). We have already created a function to store the seller's address when they deploy the contract in the `seller` state variable and can now check if the account executing the start function is the seller. If not we throw an exception. + +Next, we want to transfer the NFT that is up for auction from the seller to the contract (line 52). +We set the state variable `started` to `true` (line 53), and create an end date for the auction (line 54). In this case, it will be seven days from when the start function has been called. We can use a suffix like `days` after a literal number to specify units of time. If you want to learn more about time units have a look at the solidity documentation. + +Finally, we will emit our `Start()` event (line 56). + +### Bid + +Before the function caller can make a bid, we need to be sure that certain conditions are met. The auction needs to have started (line 60), the auction can not have ended (line 61) and the bid (the value attached to the call) needs to be higher than the current highest bid (line 62). + +Now we want to store the bid of the current highest bidder before we make a new bid. +First, we check if there is a bidder (line 64). If this function call is the first bid then the next line would be irrelevant. +In our mapping `bids` (line 34) we map the key, the `address` of the bidder, to the value, a `uint` that represents the total amount of ETH a bidder has bid in the auction before withdrawing. +If there is a bidder, we add the last bid (`highestBid`) of the `highestBidder` to the total value of the bids they have made (line 65) before withdrawing. +We store the bids because we want to enable the bidder to withdraw the ETH they used to make bids if they are no longer the highest bidder. + +Next, we set the `highestBidder` to the account calling the function (line 68), and the `highestBid` to their bid, the value that was sent with the call (line 69). + +Finally, we emit the `Bid` event (line 71). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we create in our "Solidity NFT Course" Learneth course. + +2. Mint yourself an NFT with the tokenId 0. + +3. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +4. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for `tokenId`. This will allow the contract to transfer the token to be auctioned. + +5. Call the `start` function of your auction contract. If you call the `started` function now, it should return `true`. If you call the `highestBid` function it should return 1. + +6. Set the value that you can attach to transactions to 3 Wei and call the `bid` function of the auction contract. If you call the `highestBid` function it should now return 3. diff --git a/locales/de/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md b/locales/de/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md new file mode 100644 index 000000000..e324a5c6e --- /dev/null +++ b/locales/de/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md @@ -0,0 +1,45 @@ +In this section, we will finish the contract, create a function to withdraw the bids that an account has made, and create a function to end the auction. + +### Withdraw + +We create a local variable `bal` (balance) that stores the total value of bids that the function caller has made (line 75) since their last withdrawal. We can assign this value to `bal` by accessing the bids mapping using the address of the function caller as the key. + +Next, we set the value of the address of the function caller to 0 in the bids mapping because they will withdraw the total value of their bids (line 76). + +Now we transfer that amount of ETH from the contract to the function caller and emit the `Withdraw` event (line 79). + +### End + +Before the function caller can execute this function and end the auction, we need to check if certain conditions are met. The auction needs to have started (line 83), the end date of the auction needs to have been reached (line 84), and the auction must not have ended already (line 85). + +Once the auction has ended, we set the state variable `ended` to `true` (line 87). + +We check if anybody participated in the auction and bid on the NFT (line 88). + +If there was a bid, we transfer the NFT from the contract to the highest bidder (line 89) and transfer the ETH that was sent from the highest bidder to the contract, now to the address of the auctioneer, the seller of the NFT (line 90). + +If nobody bids on the NFT, we send the NFT back to the auctioneer (line 92). + +Finally, we emit the `End` event (line 95). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we created in our Learneth "Solidity NFT Course". + +2. Mint yourself an NFT with the tokenId 0. + +3. For testing purposes, change the value that is assigned to the `endAt` state variable (line 54) from `7 days` to `5 minutes`. + +4. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +5. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for the `tokenId`. + +6. Call the `start` function of your auction contract. + +7. Bid 2 Ether using account 1, and 3 Ether using account 2. If you call the `highestBidder` function, it should now return the address of account 2. + +8. Call the `withdraw` function with account 1. In the balance of account 1, you should see the 2 Ether minus some transaction fees. + +9. After 5 minutes have passed, call the `end` function. Then, call the `ended` function which should return `true`. + +In the NFT contract, if you call the `ownerOf` function with the tokenId 0, it should return the address of account 2. If you look at the balance of account 1 it should have increased by 3 Ether minus some transaction fees. diff --git a/locales/de/ERC721Auction/config.yml b/locales/de/ERC721Auction/config.yml new file mode 100644 index 000000000..0783a37a1 --- /dev/null +++ b/locales/de/ERC721Auction/config.yml @@ -0,0 +1,19 @@ +--- +id: er721Auction +name: NFT Auction Contract +summary: Learn how to write an ERC721 (NFT) auction contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: Contract Setup + path: auction-contract-setup + - + name: Start and Bid Functions + path: auction-start-bid + - + name: Withdraw and End Functions + path: auction-withdraw-end diff --git a/locales/de/Interoperability/1_Intro/intro.md b/locales/de/Interoperability/1_Intro/intro.md new file mode 100644 index 000000000..ab26f4f6d --- /dev/null +++ b/locales/de/Interoperability/1_Intro/intro.md @@ -0,0 +1,5 @@ +As the web3 world grows, there will be more blockchains. Unless the chains can communicate with one another, the ecosystem will become increasingly fragmented. + +The Axelar network enables protocols to have cross-chain functionality between any two blockchains. + +Building a protocol that is interoperable between ecosystems is essential for growth. diff --git a/locales/de/Interoperability/2_Gateway/gateway.md b/locales/de/Interoperability/2_Gateway/gateway.md new file mode 100644 index 000000000..dc752d3eb --- /dev/null +++ b/locales/de/Interoperability/2_Gateway/gateway.md @@ -0,0 +1,25 @@ +The Axelar Gateway is the entrypoint for your smart contract into the Axelar ecosystem. Once you have triggered the appropriate function on the Gateway, your transaction will begin its interchain journey from your source chain across the Axelar network to the destination chain. Each chain that is connected to Axelar has a deployed gateway contract for you to interact with. + +The following are the two more relevant functions you will need to be familiar with. + +## callContract() + +This function triggers an interchain transaction with a message from the source to the destination chain. It takes three relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent + +The first two parameters are quite intuitive. They consist of both the name of the chain you want this transaction to go to and the address on that chain you want to end execute at. The final parameter is the payload. This payload represents a general message that is sent to the destination chain. The message can be used in many different ways on the destination chain. For example, you can send data to be used as a parameter in another function on the destination chain, you can send a function signature as a message that will then get executed on a destination chain, and much more. + +## callContractWithToken() + +This function triggers an interchain with a message and a fungible token from the source to the destination chain. It takes five relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent +4. `symbol`: The symbol of the token being sent +5. `amount`: The amount of that token that is being sent + +The first three parameters here are the same as in `callContract()`. The final two parameters are relevant to the token that is being sent along with the message. These are the symbol of the token and the amount of the token that is being sent. diff --git a/locales/de/Interoperability/3_GasService/GasService.md b/locales/de/Interoperability/3_GasService/GasService.md new file mode 100644 index 000000000..4ed0afbbf --- /dev/null +++ b/locales/de/Interoperability/3_GasService/GasService.md @@ -0,0 +1,29 @@ +The Axelar Gas Service is an extremely useful tool made available to pay gas for an interchain transaction. It allows you to pay for the cost of a transaction in the token of the source chain, making for a much easier end user (and developer) experience. If for example the source chain is Ethereum and the destination chain is Polygon then the gas service will receive the complete payment for the transaction in ETH and no matic is needed from the caller to pay for the execution on the Polygon destination chain. + +The following are the two more relevant functions you will need to be familiar with in regards to the Gas Service. + +## payNativeGasForContractCall() + +This function allows you to pay for the entirety of an interchain transaction in the native token of the source chain. It takes five relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +The parameters overlap with the parameters required by the `callContract()` function in the Gateway contract. The two parameters not discussed in the Gateway section are `sender` and `refundAddress`. The sender is the address paying for the transaction and the refund address is the address that will receive any surplus funds sent to the gas service. + +## payNativeGasForContractCallWithToken() + +This function allows you to pay for the entirety of an interchain transaction (that includes a token transfer) in the native token of the source chain. It takes seven relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `symbol`: The symbol of the token that was sent +6. `amount`: The amount of the token that was sent +7. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +This function is nearly identical to the first top one the main difference being that it is used for message + token transfer transactions as opposed to just interchain message transactions (aka GMP Transactions). As a result the GasService needs to also know the `symbol` and `amount` of the token that is being sent. diff --git a/locales/de/Interoperability/4_Executable/executable.md b/locales/de/Interoperability/4_Executable/executable.md new file mode 100644 index 000000000..1f72c6be4 --- /dev/null +++ b/locales/de/Interoperability/4_Executable/executable.md @@ -0,0 +1,27 @@ +The Axelar executable contains relevant helper functions that will be automatically executed on the destination chain in correspondence to the relevant inbound transaction from the source chain. + +The following are the relevant functions you will need to use from Axelar Executable + +## \_execute() + +This function handles the execution on the destination chain. It takes the following four parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent + +The `sourceChain` and `sourceAddress` are key parameters which you receive out of the box that can be used for verifying authenticity of messages on the destination chain. The payload (as discussed in the gateway section) is the message that was sent from the source chain to be used on your destination chain. The `commandId` will not be used during the rest of this module. + +## \_executeWithToken() + +This function handles the execution on the destination chain for a message being sent with a fungible token. It takes six relevant parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent +5. `tokenSymbol`: The symbol of the token being sent +6. `amount`: The amount of that token that is being sent + +The first four parameters are identical to that of the `_execute()` function. The final two parameters of `tokenSymbol` and `amount` are in reference to the token that is being sent along with the message. It allows you on the destination chain to interact with the token accordingly, for example transferring it to another receiving address. The `commandId` will not be used during the rest of this module. diff --git a/locales/de/Interoperability/5_InterchainMessage/interchainMessage.md b/locales/de/Interoperability/5_InterchainMessage/interchainMessage.md new file mode 100644 index 000000000..029f642ce --- /dev/null +++ b/locales/de/Interoperability/5_InterchainMessage/interchainMessage.md @@ -0,0 +1,53 @@ +In this section we will create a contract that will send a "hello world" message between two blockchains. + +## Constructor + +The first thing you will need to create is the `constructor` for the function. This will allow you to set the `Gateway` and `Gas Service` contracts we discussed in the previous sections. + +When deploying the contract you will pass in the address of the `Gateway` and `GasService` for Ethereum Sepolia those addresses are `0xe432150cce91c13a887f7D836923d5597adD8E31` for the Gateway and `0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6` for the Gas Service. + +For the full list of relevant Axelar addresses see here + +## Send Interchain Message + +Now that the constructor has set the relevant Axelar addresses needed to trigger an interchain transaction you can move on to the `setRemoteValue()`, which will trigger this transaction. + +This function takes three parameters: + +1. `_destinationChain`: The chain which the transaction is going to +2. `_destinationAddress`: The address on the destination chain the transaction will execute at +3. `_message`: The message being passed to the destination chain + +First, you have a `require` statement which ensures that the `msg.value` contains a value. This `msg.value` will be used to pay the `GasService`. If no funds were sent, then the transaction should be reverted as the transaction cannot execute on the Axelar blockchain and destination chain without any gas. + +Next, you encode the `_message` that was passed in. Notice that the `_message` is set as a `string` type. Axelar expects this message to be submitted as a `bytes` type so to convert the `string` to `bytes` you simply pass it through `abi.encode()`. + +Now, with your message encoded you can begin to interact with the `GasService` and the `Gateway` + +To pay for the entire interchain transaction you will trigger the function `payNativeGasForContractCall`, which is defined in the `GasService`. + +This function needs the parameters explained earlier in the GasService section. The `sender` for this transaction will be this contract, which is `address(this)`. The `destinationChain` and `destinationAddress` can simply be passed in from this functions parameters, the `payload` is the encoded \_message we wrote earlier. Finally, you need to specify what the refund address is, this can be the address that triggers this function, which you get by writing `msg.sender`. + +Once you trigger this function you will have successfully sent a transaction from the source chain via Axelar to the destination chain! But there is still one final step that needs to be complete. + +### Receive Message on Destination Chain + +On the destination chain the inbound interchain transaction needs to be picked up and handled by the `AxelarExecutable`'s `_execute()` function. + +The `_execute()` function is defined in the `AxelarExecutable` contract so when defining this function you must remember to include the `override` keyword. + +This function takes three parameters. + +1. `_sourceChain`: The blockchain which the transaction has originated from +2. `_sourceAddress`: The address on the source chain which the transaction has been sent from +3. `_payload`: The message that has been sent from the source chain + +The first thing that needs to be done in this contract is to get access to your `message` that was sent. Recall, before sending the message it was sent through `abi.encode()` to convert the message from type `string` to type `bytes`. To convert your message back from type `bytes` to type `string` simply pass the `_payload` to the function `abi.decode()` and specify that you want the `_payload` decoded to type `string`. This will return the message as a string. + +Now that you have your message as a type string you can set the `sourceChain` and `sourceAddress` storage variables as `_sourceChain` and `_sourceAddress` to have an easy reference to the data that was passed in. You can also emit the `Executed` event with the `sourceAddress` and `message` event that you just decoded. + +Great! At this point you are now handling the interchain transaction on the destination chain. + +To interact with this contract make sure you deploy it on at least two blockchains so that you can call `setRemoteValue()` from the one chain and then have the `_execute()` function automatically triggered on another chain. You will be able to query the `sourceChain` and `sourceAddress` variables on the destination chain to ensure that the interchain execution worked correctly. + +To view the full step by step of the interchain transaction checkout the Axelarscan (testnet) block explorer. diff --git a/locales/de/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md b/locales/de/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md new file mode 100644 index 000000000..11915eb32 --- /dev/null +++ b/locales/de/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md @@ -0,0 +1,39 @@ +At this point we have gone over an example of how to send a general message between one blockchain to another. Now, let's implement a contract that sends a message and a token from one blockchain to another. + +## Overview + +This contract should seem largely familiar. Much like the previous section the `constructor` receives the `Gateway` and `Gas Service` addresses. + +It then has a function that will be called from the source chain called `sendToMany` that takes in parameters similar to the previous section. + +1. `_destinationChain`: The chain the transaction is sending to +2. `_destinationAddress`: The address on the destination chain your transaction is sending to +3. `_destinationAddresses`: The message that you will be sending along with your token transfer. In this example the message is a list of receiving addresses for the token transfer. +4. `_symbol`: The symbol of the token address being sent +5. `_amount`: The amount of the token being sent + +In the function we already have the `require` statement implemented to ensure gas is sent + +We also have the basic ERC20 functionality to send the token from the calling wallet to this smart contract. The contract also calls the `approve` function to allow the Gateway to eventually transfer funds on its behalf. + +Finally, the `_executeWithToken()` function is also implemented out of the box. + +It makes use of the following params: + +1. `_payload`: The incoming message from the source chain +2. `_tokenSymbol`: The symbol of the token that was sent from the source chain +3. `_amount`: The amount of the token that was sent from the source chain + +Now with these params that were passed in, the `_execute()` function can send the tokens that were sent to the appropriate receivers. + +## Challenge + +Your challenge here is to finish off the `sendToMany()` function using the Axelar Gateway and Gas Service to trigger an interchain transaction. + +In the end you should be able to deploy this contract on two testnets, trigger the `sendToMany()` function and see the live transaction on Axelarscan (testnet) block explorer. + +### Testing Notes + +Note 1: The recommended ERC20 to use is `aUSDC` a wrapped version of the USDC token that can be obtained from the discord faucet bot. When triggering the `sendToMany()` function simply pass in the symbol `aUSDC` to the fourth param. + +Note2: When triggering the `sendToMany()` function you must remember to `approve` your contract to spend `aUSDC` tokens on your behalf, otherwise `transferFrom()` on line49 will throw an error. diff --git a/locales/de/Interoperability/7_FurtherReading/furtherReading.md b/locales/de/Interoperability/7_FurtherReading/furtherReading.md new file mode 100644 index 000000000..a601d7ac7 --- /dev/null +++ b/locales/de/Interoperability/7_FurtherReading/furtherReading.md @@ -0,0 +1,11 @@ +Congratulations on making it to the end of the interoperability module! 🎉🎉 + +To continue your learning journey of interoperability with Axelar. There are many useful resources available. + +- For documentation 📚 + +- For more technical examples 💻 + +- For live coding demos 📹 + +- For the developer blog 📝 diff --git a/locales/de/Interoperability/README.md b/locales/de/Interoperability/README.md new file mode 100644 index 000000000..a43fc5dd5 --- /dev/null +++ b/locales/de/Interoperability/README.md @@ -0,0 +1,3 @@ +## Interoperability Between Blockchains + +Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. diff --git a/locales/de/Interoperability/config.yml b/locales/de/Interoperability/config.yml new file mode 100644 index 000000000..39f1be7ed --- /dev/null +++ b/locales/de/Interoperability/config.yml @@ -0,0 +1,31 @@ +--- +id: interopCourse +name: Multichain Protocols with Axelar +summary: Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. +level: 2 +tags: + - Solidity + - Interoperability + - Axelar +steps: + - + name: An Intro to Axelar + path: 1_Intro + - + name: Axelar Gateway + path: 2_Gateway + - + name: Axelar Gas Service + path: 3_GasService + - + name: Axelar Executable + path: 4_Executable + - + name: Interchain Messages + path: 5_InterchainMessage + - + name: Interchain Token Transfers + path: 6_InterchainTokenTransfer + - + name: Further Reading + path: 7_FurtherReading diff --git a/locales/de/Multisig-Tutorial/1-multisig-introduction/introduction.md b/locales/de/Multisig-Tutorial/1-multisig-introduction/introduction.md new file mode 100644 index 000000000..3e9f18938 --- /dev/null +++ b/locales/de/Multisig-Tutorial/1-multisig-introduction/introduction.md @@ -0,0 +1,41 @@ +Welcome to the Multisignature Wallet course! In this section, we'll explore the fundamentals of Multisignature (Multisig) wallets and we'll go through a multisig wallet contract. + +## What is a Multisignature Wallet? + +A multisignature (multisig) wallet is a type of digital wallet that requires multiple keys to authorize a cryptocurrency transaction. + +Imagine a multisig wallet as a secure vault with multiple locks. To open the vault, each keyholder must open their individual lock. This setup ensures that no single person can access the vault's contents without the others' consent. + +## How Does a Multisig Wallet Work? + +In a multisig setup, each transaction must receive a predetermined number of approvals from a set group of individuals. For instance, in a 3-of-5 wallet configuration, there are five authorized addresses, but a transaction only goes through when at least three of them give their approval. When a transaction is initiated, it's presented as a **proposal** to the group. Each member who agrees to the transaction uses their private key to digitally sign it. + +These **digital signatures** are unique and are generated based on the combination of the transaction data and the private key. + +When the required number of signatures is reached, the transaction is broadcasted to the blockchain for execution. + +## Why Use a Multisig Wallet? + +Multisig wallets are crucial for enhanced security in cryptocurrency transactions. They mitigate the risk of theft or loss of a single key. In business, they're used to ensure that funds can't be moved without consensus among stakeholders. For instance, in a company managing cryptocurrency assets, a multisig wallet might require the CFO, CEO, and a board member to all approve significant transactions, protecting against internal fraud or external hacks. + +## Conclusion + +In this section, we learned that a multisig wallet requires multiple keys to authorize a proposed cryptocurrency transaction and that a multisigs mitigates the risk of theft or loss of a single key. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is a Multisignature Wallet? + +1. A digital wallet that requires a single signature for transactions. +2. A digital wallet that requires multiple signatures for transactions. +3. A physical wallet used for storing cryptocurrency. +4. A wallet that can only hold multiple types of cryptocurrencies. + +### 2) How does a Multisignature Wallet enhance security? + +1. By requiring a single private key for transactions. +2. By distributing transaction approval across multiple owners. +3. By storing transaction data on-chain. +4. None of the above. + +Feel free to take your time and answer the questions above. Once you're ready, we'll move on to exploring the Multisig smart contract and understanding its structure. diff --git a/locales/de/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md b/locales/de/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md new file mode 100644 index 000000000..17b0a924f --- /dev/null +++ b/locales/de/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md @@ -0,0 +1,60 @@ +In this section, we'll explore the **initialization process** of the Multisig smart contract. We'll examine the constructor function and review how it sets up the initial state of the contract. + +## Note + +From this section on in this tutorial, we will be building up a multisig contract. In subsequent sections, the contract will become increasingly complete. + +## Overview + +In this section, the contract consists of events, state variables, modifiers, and functions. **Events** provide transparency by logging specified activities on the blockchain, while **modifiers** ensure that only authorized users can execute certain functions. + +## State Variables + +In Line 4, we have the MultisigWallet contract itself. At the beginning of the contract, we have three state variables. + +1. **`owners`:** An array containing the addresses of all owners of the multi-signature wallet (Line 5). +2. **`isOwner`:** A mapping indicating whether an address is an owner (Line 6). +3. **`numConfirmationsRequired`:** The number of confirmations required for a transaction (Line 7). + +The setup of array and mapping allows us to easily retrieve the list of owners and verify whether an address is an owner. + +## Modifiers + +Next, we have a modifier called `onlyOwner` (Line 9). Modifiers in Solidity are special keywords that can be used to amend the behavior of functions. In our case, the `onlyOwner` modifier ensures that only owners can execute a function. It does this by checking whether the address of the **caller** is an owner. + +## Constructor Function + +The `constructor` function (Line 14) is executed only once during the deployment of the contract. It initializes essential parameters, in this case, the list of owners and the required number of confirmations (Line 14). + +On lines 15 and 16, we have two `require` statements to ensure that the inputs are valid. In this case, we require that there must be at least one owner and that the number of required confirmations must be greater than zero and less than or equal to the number of owners. + +The constructor then initializes the contract state by verifying that is not address(0) (Line 25) and that the owner is unique (Line 26). Then it adds a key/ value pair to the isOwner mapping (Line 28), and then it populates the `owners` array with the provided owner addresses (Line 29). + +Finally, it sets the `numConfirmationsRequired` variable with the specified value (Line 32). + +## getOwners Function + +The `getOwners` function (Line 36) allows users to retrieve the list of owners of the multi-signature wallet. It returns the `owners` array (Line 37). + +## getNumConfirmationsRequired Function + +The `getNumConfirmationsRequired` function (Line 41) allows users to retrieve the number of confirmations required for a transaction. It returns the `numConfirmationsRequired` variable (Line 42). + +## Conclusion + +In this section, we explored the initialization process of the Multisig smart contract. We examined the constructor function and understood how it sets up the initial state of the contract. + +## ⭐️ Assignment: Deploy a Multisig Wallet + +Deploy a Multisig contract with three owners and require two confirmations for transaction execution. + +1. Compile contractInitialization.sol +2. Go to Deploy & Run Transactions in Remix. +3. Expand the "Deploy" section. +4. Under "_OWNERS", enter three an array of three addresses. +5. Under "_NUM_CONFIRMATIONS_REQUIRED", enter the number of confirmations required for a transaction. + +**Hints:** + +- You can get addresses from the "ACCOUNTS" dropdown menu. +- The array of addresses should be in the format: ["0x123...", "0x456...", "0x789..."]. diff --git a/locales/de/Multisig-Tutorial/3-multisig-deposits/deposits.md b/locales/de/Multisig-Tutorial/3-multisig-deposits/deposits.md new file mode 100644 index 000000000..a8a14213b --- /dev/null +++ b/locales/de/Multisig-Tutorial/3-multisig-deposits/deposits.md @@ -0,0 +1,34 @@ +In this section, we'll explore the `receive` function and the associated Deposit event. We'll examine how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## Deposit Event + +On line, 9 we have the Deposit event. The Deposit event is emitted whenever Ether is deposited into the multi-signature wallet. It includes three parameters: + +1. `sender`: The address that sent the Ether. +2. `amount`: The amount of Ether deposited. +3. `balance`: The updated balance of the contract after the deposit. + +We can use the Deposit event to track the flow of Ether into the multi-signature wallet and maybe trigger other actions based on the event. + +## receive Function + +On line 43, we have the `receive` function. The `receive` function is a special function that is executed whenever Ether is sent to the contract. + +The `receive` function is marked as `external` and `payable`. The `external` modifier means that the function can only be called from outside the contract. The `payable` modifier means that the function can receive Ether. + +The `receive` function emits the Deposit event (Line 44) with the address of the sender, the amount of Ether sent, and the updated balance of the contract. It doesn't return anything. + +To receive Ether, a contract must have a `receive`, `fallback`, or a function with the `payable` modifier. If none of these are present, the contract will reject any Ether sent to it. + +## Conclusion + +In this section, we explored the `receive` function and the associated Deposit event. We examined how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## ⭐️ Assignment: Deposit Ether + +Deposit 2 Ether into the Multisig contract. + +1. Deploy the Multisig contract as in the previous assignment. +2. Enter a Value of 2 Ether in the Value field and select Ether in the dropdown menu. +3. At the bottom of your deployed contract in the "Low level interactions" section, click on the "Transact" button. +4. On top of your deployed contract, it should now say "Balance: 2 Ether". diff --git a/locales/de/Multisig-Tutorial/4-multisig-transactions/transactions.md b/locales/de/Multisig-Tutorial/4-multisig-transactions/transactions.md new file mode 100644 index 000000000..f62fd48a0 --- /dev/null +++ b/locales/de/Multisig-Tutorial/4-multisig-transactions/transactions.md @@ -0,0 +1,73 @@ +In this section, we'll explore the process of submitting and confirming transactions. + +## Modifiers + +We have new modifiers in this iteration of the contract. Let's examine them one by one. + +1. **`txExists` modifier:** (Line 13) ensures that the transaction exists. It does this by checking whether the transaction index is less than the length of the `transactions` array. We'll go into more about in this modifier later in this section. +2. **`notExecuted` modifier:** (Line 18) ensures that the transaction has not been executed. It does this by checking whether the `executed` variable of the transaction is false. +3. **`notConfirmed` modifier:** (Line 23) ensures that the transaction has not been confirmed by the caller. It does this by checking whether the `isConfirmed` mapping of the transaction index and the caller's address is false. + +## Transaction Struct + +On line 28, we have a struct called `Transaction`. We store the struct members: `to`, `value`, `data`, `executed`, and `numConfirmations` in individual variables. + +## Mapping of Confirmations + +On line 37, we have a mapping called `isConfirmed`. This mapping is used to keep track of the confirmations of each transaction. It maps the transaction's index to a mapping of an owner addresse to a boolean value. The boolean value indicates whether this owner has confirmed the transaction. + +## Transactions Array + +On line 39, we have an array called `transactions`. The array is used to store all the transactions submitted to the multi-signature wallet. + +## Events + +We have four new events in this iteration of the contract: + +1. **`SubmitTransaction` event:** emitted whenever a transaction is submitted to the multi-signature wallet. +2. **`ConfirmTransaction` event:** emitted whenever a transaction is confirmed by an owner. +3. **`RevokeConfirmation` event:** emitted whenever a transaction confirmation is revoked by an owner. +4. **`ExecuteTransaction` event:** emitted whenever a transaction is executed. + +## submitTransaction Function + +The `submitTransaction` function (Line 78) allows users to submit a transaction to the multi-sig wallet. It takes three parameters: `to`, `value`, and `data`. The `to` parameter is the address of the recipient of the transaction. The `value` parameter is the amount of Ether to be sent. The `data` parameter is the data to be sent to the recipient. Only owners can submit transactions. + +On line, 85 we create a new transaction struct and push it to the `transactions` array and emit the `SubmitTransaction` event. The `txIndex` variable is used to keep track of the transaction index. + +## confirmTransaction Function + +The `confirmTransaction` function (Line 98) allows users to confirm a transaction. It takes one parameter: `txIndex`. +It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. The `onlyOwner` modifier ensures that only owners can confirm transactions. The `txExists` modifier ensures that the transaction exists. The `notExecuted` modifier ensures that the transaction has not been executed. + +On line 101, we store the transaction in a local variable called `transaction`. We then increment the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to true. Finally, we emit the `ConfirmTransaction` event. + +## executeTransaction Function + +The `executeTransaction` function (Line 108) allows users to execute a transaction. On line 113, we require that the number of confirmations of the transaction is greater than or equal to the required number of confirmations. We then set the `executed` variable of the transaction to true. Finally, send the funds using the `call` function. This is the `call` of the recipient address with the value and data of the transaction. If the transaction is successful, we emit the `ExecuteTransaction` event. + +## getTransactionCount Function + +The `getTransactionCount` function (Line 132) allows users to retrieve the number of transactions in the multi-signature wallet. It returns the length of the `transactions` array. + +## getTransaction Function + +The `getTransaction` function (Line 136) allows users to retrieve a transaction. It returns the transaction struct members that we explored earlier in this section. + +## Conclusion + +In this section, we explored the process of submitting, confirming, and executing transactions. We examined the `submitTransaction`, `confirmTransaction`, and `executeTransaction` functions and understood how they work together to allow multiple users to submit and confirm transactions. + +## ⭐️ Assignment: Make a Transaction + +Submit, confirm, and execute a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. Deploy the Multisig contract as in the previous assignment. Make sure that the required number of confirmations is 2. +2. Fund the multisig from any address by sending 4 Ether as you did in the previous assignment. +3. Try sending 2 Ether to the first account in the "ACCOUNTS" dropdown menu. Once you have submitted this transaction (with submitTransaction), click on `getTransactionCount` and should see one transaction or you can click on `getTransaction`, insert 0 as the transaction index and see the transaction you just submitted. +4. Now you can click on `confirmTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. +5. Switch to the second owner account and confirm the transaction again. If you click on `getTransaction` again, you should see that the transaction has been confirmed twice. +6. The last step is to execute the transaction. Click on `executeTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been executed. You can also check the balance of the first account in the "ACCOUNTS" dropdown menu. It should now be 2 Ether higher and the balance of the multi-signature wallet should be 2 Ether lower. + +**Hint:** +If you submit a transaction make sure that the value is in Wei and that the _data field is correctly filled in. E.g. it could look like this: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 2000000000000000000, 0x" for 2 Ether. diff --git a/locales/de/Multisig-Tutorial/5-multisig-revoke/revoke.md b/locales/de/Multisig-Tutorial/5-multisig-revoke/revoke.md new file mode 100644 index 000000000..1bf085343 --- /dev/null +++ b/locales/de/Multisig-Tutorial/5-multisig-revoke/revoke.md @@ -0,0 +1,30 @@ +In this section, we'll explore the process of revoking confirmations. This process is necessary when an owner changes their mind about a transaction and wants to stop it from being executed. This section will be pretty straightforward. + +## revokeConfirmation Event + +On line 14, we have added the `RevokeConfirmation` event. This event is emitted whenever a transaction confirmation is revoked by an owner. + +## revokeConfirmation Function + +On line 129, we have added the `revokeConfirmation` function. It allows users to revoke a transaction confirmation. + +`revokeConfirmation` takes one parameter: `txIndex`. It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. + +On line 134, we require that the transaction has been confirmed by the caller. This ensures that an owner who has confirmed the transaction can only revoke their own confirmation. +We then decrement the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to false. Finally, we emit the `RevokeConfirmation` event. + +## Conclusion + +In this section, we explored the process of revoking confirmations. We examined the `revokeConfirmation` function and understood how it works to allow users to revoke confirmations. + +## ⭐️ Assignment: Revoke a Confirmation + +Confirm and revoke a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. As in the previous assignment, deploy the Multisig contract, send the contract some Ether, and then submit a transaction to the first account in the "ACCOUNTS" dropdown menu with a value of 2 Ether. +2. Confirm the transaction twice as in the previous assignment. +3. Revoke the transaction by clicking on `revokeConfirmation` and inserting 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. + +## Final Conclusion + +In this tutorial, we explored the process of creating a multi-signature wallet. We learned how to initialize the contract, deposit Ether, submit, confirm, and revoke transactions. We also learned how to execute transactions and retrieve information about the multi-signature wallet. diff --git a/locales/de/Multisig-Tutorial/README.md b/locales/de/Multisig-Tutorial/README.md new file mode 100644 index 000000000..ae5997802 --- /dev/null +++ b/locales/de/Multisig-Tutorial/README.md @@ -0,0 +1,5 @@ +## MultiSig Wallet + +Learn how to write a MultiSig Wallet smart contract on Ethereum. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/de/Multisig-Tutorial/config.yml b/locales/de/Multisig-Tutorial/config.yml new file mode 100644 index 000000000..067de0fb9 --- /dev/null +++ b/locales/de/Multisig-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: multisigCourse +name: Multisig Wallet +summary: Learn how to create and interact with a multisig wallet. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - Multisig +steps: + - + name: 1. Introduction + path: 1-multisig-introduction + - + name: 2. Initialize the Contract + path: 2-multisig-initialization + - + name: 3. Deposits + path: 3-multisig-deposits + - + name: 4. Transactions + path: 4-multisig-transactions + - + name: 5. Revoking Confirmations + path: 5-multisig-revoke diff --git a/locales/de/NFTTokenCourse/README.md b/locales/de/NFTTokenCourse/README.md new file mode 100644 index 000000000..c3d2a183a --- /dev/null +++ b/locales/de/NFTTokenCourse/README.md @@ -0,0 +1,5 @@ +## Solidity NFT Course + +Learn how to create your own NFTs (non-fungible tokens). + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/de/NFTTokenCourse/config.yml b/locales/de/NFTTokenCourse/config.yml new file mode 100644 index 000000000..af82db834 --- /dev/null +++ b/locales/de/NFTTokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: nftTokenCourse +name: Solidity NFT Course +summary: Learn how to create your own NFT tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc721-interface + - + name: 3. Metadata Interface + path: erc721-interface-metadata + - + name: 4. Token Creation + path: erc721-token-creation + - + name: 5. Metadata IPFS + path: erc721-metadata-ipfs + - + name: 6. Deploy to Testnet + path: erc721-deploy-testnet-opensea diff --git a/locales/de/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md b/locales/de/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md new file mode 100644 index 000000000..40576500c --- /dev/null +++ b/locales/de/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md @@ -0,0 +1,50 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to the Rinkeby testnet of the Ethereum blockchain, mint an NFT, and look at it on the NFT marketplace OpenSea. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token for Rinkeby + +In order to make transactions on the testnet, we need Ethereum testnet tokens. + +**2.1** Switch your Metamask from "Ethereum Mainnetwork" to "Rinkeby Test Network". + +**2.2** Go to https://faucet.paradigm.xyz/, enter the address of your account and claim testnet ETH. +You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Contract Deployment + +**3.1** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It should then ask you to connect your account, which you should confirm. Then you should see the Rinkeby network badge under "Injected Web3". + +**3.2** Deploy your token contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. + +### 4. Mint an NFT + +**4.1** Expand your contract in the IDE so you can see the buttons for the functions. + +**4.2** Expand the input fields next to the safeMint button. Enter the Ethereum address of the account that is connected to Remix in the “to:” input field. Enter “0” in the input field "tokenID:". Click on transact. + +**4.3** In Metamask click on assets, then click on the “Import tokens” link, and paste the address of your contract in the input field. You can set decimals to 0. + +You should now see the name of the symbol of your token contract (e.g. GEO) in your “Assets” view in Metamask. You should have one of these tokens. + +### 5. See your NFT on OpenSea + +OpenSea is one of the most popular online marketplace for NFTs. OpenSea also provides a version where you can see assets on the testnet, under https://testnets.opensea.io/ + +**5.1** Go to https://testnets.opensea.io/login. + +**5.2** Connect with your Metamask wallet. You should be redirected to your account https://testnets.opensea.io/account view on OpenSea, where you should be able to see your NFT. You should see the image of your NFT; when you click on it, you should see the name, description, and under properties, also the attributes that you created. + +If you successfully completed this course and are familiar with the basics of Solidity development, we encourage you to continue your learning journey by learning how to create your own NFT auction contract from the Learneth resources. diff --git a/locales/de/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md b/locales/de/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md new file mode 100644 index 000000000..a43162feb --- /dev/null +++ b/locales/de/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md @@ -0,0 +1,44 @@ +The metadata extension is optional. It allows us to add additional information to our ERC721 tokens. We can specify a name, a symbol, and an URI (Uniform Resource Identifier) that can point to a file where we can add even more information in the form of a JSON. + +## ERC721 Metadata Functions + +### name + +The function `name` (line 16) returns the name of the token collection. A token collection means all tokens created with your ERC721 token contract implementation. Every token in this collection will have this name, regardless of their tokenId. + +### symbol + +The function `symbol` (line 21) returns the symbol of the token collection. + +### tokenURI + +The function `tokenURI` (line 26) returns the URI for the token with the id `tokenId`. In this case it’s not the URI of the whole collection but of an individual token in the collection. + +## ERC721 Metadata JSON Schema + +The file that the tokenURI points to should conform to the Metadata JSON Schema as it is specified in the EIP-721. + +``` +{ + "title": "Asset Metadata", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Identifies the asset to which this NFT represents" + }, + "description": { + "type": "string", + "description": "Describes the asset to which this NFT represents" + }, + "image": { + "type": "string", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." + } + } +} +``` + +The root element must be of the type object. This root object should have properties with the keys: name, description, and image that should be all of the type string. + +The ERC721 standard is pretty flexible, the tokenURI does not need to point to a JSON document and the JSON does not need to have all properties and often has additional properties. diff --git a/locales/de/NFTTokenCourse/erc721-interface/erc721Interface.md b/locales/de/NFTTokenCourse/erc721-interface/erc721Interface.md new file mode 100644 index 000000000..468e8e640 --- /dev/null +++ b/locales/de/NFTTokenCourse/erc721-interface/erc721Interface.md @@ -0,0 +1,100 @@ +ERC721 is a standard for token contracts that manage non-fungible tokens (NFTs) on the Ethereum blockchain. + +Each non-fungible token is unique and not interchangeable. NFTs can have different properties, behavior, or rights. Non-fungible tokens are used to represent ownership of unique digital and physical assets like art, collectibles, or real estate. + +If you want to know more about the ERC721 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +The ERC721 standard is more complex than the ERC20 standard and it features optional extensions. ERC721 compliant contracts must, at a minimum, implement the ERC721 and ERC165 interfaces, which we will look at in this section. + +This interface (line 11) is part of the open-source contract library provided by OpenZeppelin. + +## Basic IERC721 Functions + +Contracts compliant with the ERC721 standard have to implement the following functions: + +### balanceOf + +The function `balanceOf` (line 30) returns the amount of tokens owned by the account with the address `owner`. + +### ownerOf + +The function `ownerOf` (line 39) returns the address `owner` of the account that holds the token with the id `tokenId`. + +### safeTransferFrom + +The function `safeTransferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +The function `safeTransferFrom` (line 137) is almost identical to the function `safeTransferFrom` (line 55) .The only difference is that this function has a non-empty payload `data`. + +A smart contract must implement the ERC721TokenReceiver Interface if it is to receive a transfer. This will ensure that the contract can handle ERC721 token transfers and prevent the tokens from being locked in a contract that can’t. + +### transferFrom + +The function `transferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +**It is recommended to use safeTransferFrom instead of transferFrom whenever possible.** +The `transferFrom` function is not secure because it doesn’t check if the smart contract that is the recipient of the transfer has implemented the ERC721TokenReceiver interface and is capable of handling ERC721 tokens. + +## Advanced IERC721 Functions + +### approve + +The function `approve` (line 94) gives the account with the address `to` the permission to manage the token with the id `tokenId` on behalf of the account calling the function. + +### getApproved + +The function `getApproved` (line 103) returns the address of the account (return var `operator`) that is approved to manage the token with the id `tokenId`. + +### setApprovalForAll + +The function `setApprovalForAll` (line 115) sets the permission (`_approved`) for the account with the specified address (input param - `operator`) to manage all tokens of the account calling the function. + +### isApprovedForAll + +The function `getApproved` (line 103) returns the boolean true if the account with the address `operator` is approved to manage all tokens of the account with the address `owner`. + +## IERC721 Events + +ERC721 contracts must also emit the following events: + +### Transfer + +The `Transfer` event (line 15) must be emitted when the token with the id `tokenId` is transferred from the account with the address `from` to the account with the address `to`. + +### Approval + +The `Approval` event (line 20) must be emitted when the account with the address `owner` approves the account with the address `spender` to manage the token with the id `tokenId` on its behalf. + +### ApprovalForAll + +The `ApprovalForAll` event (line 25) must be emitted when the account with the address `owner` gives or removes the permission (`_approved`) of the account with the address `operator` to manage all its tokens. + +## IERC165 + +In addition to the ERC721 interface, ERC721 compliant contracts must also implement the ERC165 interface. + +With the implementation of the ERC165 interface, contracts can declare the support of specific interfaces. A contract that wants to interact with another contract can then query if the other contract supports this interface before making a transaction e.g. sending tokens to it that they might not support. + +Our IERC721 interface here imports (line 6) and inherits (line 11) from the IERC165 interface. + +This is how OpenZeppelins implementation of the ERC165 interface looks like: + +``` +interface IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +For example, the ERC165 identifier for the ERC721 interface as specified in the EIP721 is “0x80ac58cd”. Learn how to calculate an interface identifier and more about the ERC165 in its improvement proposal. + +## Other interfaces + +The IERC721TokenReceiver interface must be implemented to accept safe transfers. + +There are two optional extensions for ERC721 contracts specified in the EIP721: + +IERC721Enumerable enables a contract to publish its full list of tokens and make them discoverable. + +IERC721Metadata enables a contract to associate additional information to a token. We will have a more detailed look into this in the next section. diff --git a/locales/de/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md b/locales/de/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md new file mode 100644 index 000000000..27876b068 --- /dev/null +++ b/locales/de/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md @@ -0,0 +1,101 @@ +In this section, we will create our metadata and store it in a decentralized way. + +IPFS ( InterPlanetary File System) is a peer-to-peer network for storing files in a distributed way. Pinata.cloud is a pinning service that allows users to easily host files on the IPFS network. + +We want to host our images and the JSON files with their metadata on IPFS. + +### Create Image Folder + +In this example, we will create metadata for three tokens. As you can see below, we create three images that we stored in a folder. + +``` +geo-img +├── geo_1.png +├── geo_2.png +├── geo_3.png +``` + +### Register on Pinata + +Now, we want to host these images somewhere so we can point to them in the metadata of our tokens. Let's do it in a decentralized way and use Pinata to host them on IPFS. + +First you need an account on Pinata. Go to Pinata.cloud and create an account. On Pinata you can upload up to 1 GB of data for free. + +Once you have signed up, you should be in the Pin Manager view. + +Pin Manager Pinata + +### Upload Images to IPFS + +Click on the upload button and upload the folder with your images. +Once you've uploaded your folder, you should see the name of your folder and the CID (content identifier) associated with it. If the content in the folder changes, the CID will also change. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P + +You can access a specific image by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png + +### Create JSON files + +We create another folder where we store three JSON files. + +``` +geo-json +├── 0 +├── 1 +├── 2 +``` + +Inside the JSON files, create the metadata for the tokens, like name, description, and image. +For the image URL, we are going to use the URL of our images on IPFS. You can add additional data if you like; in this example, we added some unique attributes for each token. + +This is how the JSON for the first token could look: + +``` +{ + "name": "Geometry#0", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png +", + "attributes": [ + { "trait_type": "background", "value": "cyan" }, + { "trait_type": "color", "value": "red" }, + { "trait_type": "shape", "value": "circle" } + ] +} +``` + +This is how the JSON for the second token could look: + +``` +{ + "name": "Geometry#1", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_2.png", + "attributes": [ + { "trait_type": "background", "value": "magenta" }, + { "trait_type": "color", "value": "green" }, + { "trait_type": "shape", "value": "square" } + ] +} +``` + +As shown above, the folder in this example is called "geo-json". Inside this folder, we have three JSON files. +The first JSON file is called "0", the second JSON file is called "1", and the third JSON file is called "2". + +Make sure that your JSON files don't have a file ending and are named like their corresponding tokenIds. +In the pin manager on pinata.cloud, click on the upload button and upload the folder with your JSON files. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. +For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp +This will become our baseURI. + +You can access a specific JSON file then by just adding a slash and the tokenId by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/0 + +In the contract, replace the baseURI with your own baseURI. In this example, the baseURI consists of the URL +"https://ipfs.io/ipfs/", the CID containing the JSON files, and a slash at the end "/". + +An individual tokenURI will now be created for each token by adding the tokenId to the baseURI — exactly what we did manually in the example above to access the JSON file. diff --git a/locales/de/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md b/locales/de/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md new file mode 100644 index 000000000..891fe00a7 --- /dev/null +++ b/locales/de/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md @@ -0,0 +1,35 @@ +In this contract, we use an ERC721 token contract implementation from OpenZeppelin (line 4). + +Have a look at their implementation of a ERC721 contract. Apart from the functionality specified in the ERC721 standard, the contract provides additional functions which we will see in a bit. + +## myToken + +We create our own contract called MyToken (line 7), which inherits (line 7) the functionality from the OpenZepplin `ERC721` token contract implementation and `Ownable` that we imported (line 4). If you don't remember the Ownable contract module, have a look at the ERC20 extensions section. + +This ERC721 implementation makes use of the IERC721Metadata extension that is specified in the EIP. Our contract inherits the functions `name()` and `symbol()` +and has a constructor that allows their values to be set during the deployment of the contract (line 8). +In this case, we are going to use the default values. We name our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +### Base URI + +With an ERC721 contract, we are able to mint various tokens, each with its own tokenId. As we saw in the IERC721Metadata interface, each token can have its own `tokenURI`, which typically points to a JSON file to store metadata like name, description, and image link. +If a contract mints multiple tokens, ERC721 implementations often use the same URI as a base (`baseURI`) for all tokens and only differentiate them by adding their unique `tokenId` at the end via concatenation. In the next part, we will see what this looks like in practice. + +In this example, we are storing our data on IPFS — more on that in the next section. Our baseURI is https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/ (line 11). +Through concatenation the tokenURI for the token with the id 0 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/0 , the tokenURI for the token with the id 1 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/1, and so on. + +When using IPFS and you run into "504 Gateway Time-out" errors, you might have to wait and retry until the data is available. + +### safeMint + +With the safeMint function (line 14) we enable the owner to create new tokens with a dedicated token id after contract deployment. +The safeMint function is part of the ERC721 implementation of OpenZeppelin and lets us safely mint a token with the id `tokenId` to the account with the address `to`. For access control, we use the `onlyOwner` modifier from the Ownable access control contract module that we imported (line 5). + +In the next section, we will see how we can create and host the metadata for our NFTs. + +## ⭐️ Assignment + +1. Rename your contract to `Geometry`. +2. Rename your token to `Geometry`. +3. Change the symbol of your token to `GEO`. +4. Change the `_baseURI` to https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/. diff --git a/locales/de/NFTTokenCourse/introduction/introduction.md b/locales/de/NFTTokenCourse/introduction/introduction.md new file mode 100644 index 000000000..13beea567 --- /dev/null +++ b/locales/de/NFTTokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with NFTs, tokens created with the ERC721 token standard. + +If you want to learn more about fungible tokens and the ERC20 token standard, have a look at the Learneth ERC20 Token Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain-based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/de/OpcodesInTheDebugger/1_intro/step.md b/locales/de/OpcodesInTheDebugger/1_intro/step.md new file mode 100644 index 000000000..c1d9a2448 --- /dev/null +++ b/locales/de/OpcodesInTheDebugger/1_intro/step.md @@ -0,0 +1,5 @@ +This workshop aims to give a better understanding about how a contract get deployed. +`SimpleStore` is a very basic contract. +It has a very simple constructor - which just uses the first parameter `_o` and saves it to `s`. + +Using the debugger, we'll try to see, what the opcode `CODECOPY` does. diff --git a/locales/de/OpcodesInTheDebugger/2_memory/step.md b/locales/de/OpcodesInTheDebugger/2_memory/step.md new file mode 100644 index 000000000..577169a5e --- /dev/null +++ b/locales/de/OpcodesInTheDebugger/2_memory/step.md @@ -0,0 +1,8 @@ +Before we start, just quick reminder: + +The runtime of the EVM has several kinds of memory: + +- `calldata`: This is the input value given to the transaction. +- `stack`: Basically, this is a list of values, each value is limited in size (32 bytes). +- `memory`: Memory is used when the **type** of value getting stored is more complex like an array or a mapping. This memory is **temporary** and is **released** at the end of the execution. +- `storage`: This is a mapping, each value stored is **persisted** and saved on chain. diff --git a/locales/de/OpcodesInTheDebugger/3_codecopy/step.md b/locales/de/OpcodesInTheDebugger/3_codecopy/step.md new file mode 100644 index 000000000..b0c9f7d52 --- /dev/null +++ b/locales/de/OpcodesInTheDebugger/3_codecopy/step.md @@ -0,0 +1,7 @@ +CODECOPY is one of the many opcodes run by the EVM. Check out the complete list of opcodes at https://ethervm.io/ . + +CODECOPY takes the **running code** (or part of it) and to copies it from the `calldata` to the `memory`. + +The solidity implementation is: **codecopy(t, f, s)** - copy **s** bytes from code at position **f** to memory at position **t**. + +Every contract deployment uses **CODECOPY**. diff --git a/locales/de/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md b/locales/de/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md new file mode 100644 index 000000000..63950051d --- /dev/null +++ b/locales/de/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md @@ -0,0 +1,11 @@ +Let's go back to our contract. +Please make sure the `solidity compiler` and `Deploy & Run Transactions` are activated. + +Alternatively, you can click on `Solidity` from the `Home Page` **Environments** section. + +- Compile the contract from the `solidity compiler`. +- Go to the `Deploy & Run Transactions` and make sure `SimpleStore` is selected contract. +- In the textbox to the right of `Deploy`, input a positive integer. +- Click on `Deploy`. + +In the next step, we'll watch the deployment in the debugger. diff --git a/locales/de/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md b/locales/de/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md new file mode 100644 index 000000000..3ef3cd146 --- /dev/null +++ b/locales/de/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md @@ -0,0 +1,7 @@ +From the Remix terminal, identify the transaction that deployed the contract and click `Debug` + +In the gutter of the editor, put a breakpoint on the line `s = _o`, and click on `Jump to the next Breakpoint` (bottom right button). + +Click on `Step into`, to move along the opcodes until you reach `SSTORE`. + +`SSTORE` is the opcode for storing the value `_o` in the storage. Let's continue further to the `CODECOPY`. diff --git a/locales/de/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md b/locales/de/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md new file mode 100644 index 000000000..1480728e6 --- /dev/null +++ b/locales/de/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md @@ -0,0 +1,57 @@ +The goal here is to store the code in the blockchain. The EVM needs to tell the client (geth, parity) which what part of the **Call Data** to store. In this step, we are saving the contract MINUS its constructor (because that gets inplmented only 1 time) and MINUS the input parameter does not need to be stored. + +`CODECOPY` is the first step: it copies the bytecode to memory, then the ethereum client will be able to consume it. MUNCH! + +But wait... before the client can **MUNCH** bytecode, it needs an instruction - an opcode to tell it to MUNCH. `RETURN` is this opcode! + +As stated in the general spec, at the end of the contract creation, the client (geth, parity) takes the targeted value by the opcode `RETURN` and **persists** it by making it part of the deployed bytecode. + +Once you are in the `CODECOPY`, look at the top 3 items in the **Stack**: + +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x0000000000000000000000000000000000000000000000000000000000000055` +`2: 0x000000000000000000000000000000000000000000000000000000000000003e` + +_In your Stack - `1` & `2` may be slightly different. The difference may be due to a different compiler version._ + +**These are the parameters for `CODECOPY`.** + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +`0` is the offset where the copied code should be placed in the **memory**. In this example, ( all zeros) the code is copied to the beginning of the memory. (**t**) +`1` is the offset in **calldata** where to copy from (**f**) +`2` number of bytes to copy - (**s**) + +After `CODECOPY` is executed, (click the _step into_ button) the copied code should be: +`0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c63430005110032` in memory. **I'll refer to this value as (X)**. + +Let's look at the debugger's **Memory** panel. +The 0x number I gave above is not what you will see in the **Memory** panel -what you will see is this: +0x0: 6080604052600080fdfea265627a7a72 ????R??????ebzzr +0x10: 31582029bb0975555a15a155e2cf28e0 1X ?? uUZ??U???? +0x20: 25c8d492f0613bfb5cbf96399f6dbd4e ?????a?????9?m?N +0x30: a6fc9164736f6c634300051100320000 ???dsolcC????2?? +0x40: 00000000000000000000000000000000 ???????????????? +0x50: 000000000000000000000000000000a0 ??????????????? +0x60: 00000000000000000000000000000000 ???????????????? +0x70: 00000000000000000000000000000000 ???????????????? +0x80: 00000000000000000000000000000000 ???????????????? +0x90: 00000000000000000000000000000002 ???????????????? + +The `0x0`, `0x10`, etc is the position. The next number is the bytecode for that position. This is followed by question marks and seemingly random letters & numbers. This is **Remix**'s attempt to convert this into a string. + +So if we glue the first four sections of bytecode together, we'll get: +**0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e0a6fc9164736f6c63430005110032** The last section - `0x90` has 2 which is what I input for the constructors parameter. + +The input data from the **Call Data** panel is: +`0x6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c634300051100320000000000000000000000000000000000000000000000000000000000000002` +**I'll refer to this value as (Y).** + +This shows us that `(X)` is a subset of the original calldata `(Y)`: + +`(X)` is calldata without the input parameter `0000000000000000000000000000000000000000000000000000000000000002` (we don't need to store this) +and without the constructor code `6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe` which should be executed only 1 time. + +So `CODECOPY` extracts the bytecode from the calldata and copies it to the memory. + +Let's move to the next step. diff --git a/locales/de/OpcodesInTheDebugger/7_returnAndStore/step.md b/locales/de/OpcodesInTheDebugger/7_returnAndStore/step.md new file mode 100644 index 000000000..b375a24fb --- /dev/null +++ b/locales/de/OpcodesInTheDebugger/7_returnAndStore/step.md @@ -0,0 +1,18 @@ +# The Opcode RETURN + +At the end of the last chapter we had moved to one step after **CODECOPY** to see what happened in the memory. + +Now that CODECOPY has been executed, we are on the opcode `PUSH1 00`. + +`PUSH1 00` prepares the stack for the `RETURN` opcode. +`RETURN` is the last part of this process. It is where the code is returned to the client. + +We push `00` to the stack because this is the offset position of the contract bytecode in memory. + +Now we can call the all important `RETURN` opcode. + +The **stack inspector** shows: +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x000000000000000000000000000000000000000000000000000000000000003e` + +Which is to say it returns to the client the bytecode starting `0x00` with length `0x3e`. diff --git a/locales/de/OpcodesInTheDebugger/8_findTheOffset/step.md b/locales/de/OpcodesInTheDebugger/8_findTheOffset/step.md new file mode 100644 index 000000000..6b1ddc5cf --- /dev/null +++ b/locales/de/OpcodesInTheDebugger/8_findTheOffset/step.md @@ -0,0 +1,18 @@ +# Find the offset ;) + +And now for a slightly different example: + +- Compile notSimpleStore.sol +- Deploy the contract `notSoSimpleStore` +- Make sure you have a successful deployment - if not check that you used **the correct input type** in the constructor. +- Go to the Debugger by clicking the **debug** button at the (successful) creation transaction. +- Find the value of the parameter of `CODECOPY` which represents the offset in calldata where to copy from. + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +If you look in the **Stack**, you should see that the 2nd element is: +0x0000000000000000000000000000000000000000000000000000000000000083 + +And this is the **f** of the input params of codecopy. + +### Hope you picked up a thing or 2 about how opcodes work! diff --git a/locales/de/OpcodesInTheDebugger/config.yml b/locales/de/OpcodesInTheDebugger/config.yml new file mode 100644 index 000000000..74a1bf3a1 --- /dev/null +++ b/locales/de/OpcodesInTheDebugger/config.yml @@ -0,0 +1,10 @@ +--- +id: opcodesdebug +name: Opcodes in the Debugger +summary: Using the Debugger, we'll check out what the CODECOPY opcode does and how it is used by the EVM during contract creation. +level: 3 +tags: + - Remix + - Debugging + - EVM + - Opcodes diff --git a/locales/de/ProxyContract/1_Why/step1.md b/locales/de/ProxyContract/1_Why/step1.md new file mode 100644 index 000000000..b4a38aaeb --- /dev/null +++ b/locales/de/ProxyContract/1_Why/step1.md @@ -0,0 +1,27 @@ +# Proxy Contract AKA the Dispatcher + +## Why? + +This is a great pattern that is used mainly in **library development**. + +It helps in the following ways: + +- **Save gas cost at deployment time** + The purpose of a high gas cost is to discourage the operations that cost a lot for their execution and to encourage optimized code. + +- Proxy contracts are useful when a lot of instances of the same contract need to be deployed because they reduce the duplications in the deployment. + +- **Avoid code repetition in the blockchain.** + Heavy computations are expensive because every node will need to perform them, this is of course slowing the network. + +- **Develop upgradable(versioned) contracts** + When the contract is deployed, it’s immutable. By re-designing the code into different contracts, it is possible to allow logic upgrades while keeping the storage the same. + +## Example of gas cost + +Storing contract code at creation time can cost up to: + +- 200 \* max_byte_code_length gas +- 200 \* 24576 = 49152004915200 \* 10 gwei = 49152000 gwei = 0.049152 ether = 9 EUR + +see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md for more info on max_byte_code_length. diff --git a/locales/de/ProxyContract/2_How/step2.md b/locales/de/ProxyContract/2_How/step2.md new file mode 100644 index 000000000..d80b6557c --- /dev/null +++ b/locales/de/ProxyContract/2_How/step2.md @@ -0,0 +1,13 @@ +# How it works? + +**EIP-7 DelegateCall** opcode allows a separate execution in another contract while maintaining the original execution context. + +All **message calls** from the user go through a **Proxy contract**. + +The **Proxy contract** then will redirect them to the **Logic contract**. + +And when you need to **upgrade** the logic, you'll **just** deploy that - **HOWEVER** - the implementation of Proxy will remain the same. + +You'll only need to update the address of Logic contract in Proxy. + +The Proxy Contract uses **Delegate calls** and **Solidity assembly** because without it, it's impossible to return any value from **delegatecall**. diff --git a/locales/de/ProxyContract/3_Delegatecall/step3.md b/locales/de/ProxyContract/3_Delegatecall/step3.md new file mode 100644 index 000000000..8693e5567 --- /dev/null +++ b/locales/de/ProxyContract/3_Delegatecall/step3.md @@ -0,0 +1,9 @@ +# Delegate call + +It's a special variant of a **message call**, which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract so **msg.sender** and **msg.value** do not change their values. + +This means that a contract can dynamically load code from a different address at runtime. + +The storage, the current address and balance still refer to the calling contract, only the code is taken from the called address. + +So when a **Proxy** delegates calls to the Logic contract, every storage modification will impact the storage of Logic contract. diff --git a/locales/de/ProxyContract/4_Generic_proxy_example/step4.md b/locales/de/ProxyContract/4_Generic_proxy_example/step4.md new file mode 100644 index 000000000..d20fdd16d --- /dev/null +++ b/locales/de/ProxyContract/4_Generic_proxy_example/step4.md @@ -0,0 +1,15 @@ +# A Basic Generic Proxy Example + +In the associated solidity file, **step4.sol**, there are 2 contracts - **ProxyContract** and **LogicContract**. + +To use this system, we first deploy the LogicContract. + +And then when we go to deploy the ProxyContract, we pass the LogicContract's address as an argument of the ProxyContract's constructor. + +The ProxyContract is deployed only once. + +The code of LogicContract will be called at the line 20. It will be forwarded with delegate call while keeping the context of LogicContract. + +In case we need to change the logic we would deploy a new LogicContract and set the address of it with setLogicContractAddress setter function. + +_Note: The LogicContract we have here does not use the storage. Once you need to use the storage the implementation becomes a bit more complicated because those contracts share the context._ diff --git a/locales/de/ProxyContract/5_Test/step5.md b/locales/de/ProxyContract/5_Test/step5.md new file mode 100644 index 000000000..120a15e13 --- /dev/null +++ b/locales/de/ProxyContract/5_Test/step5.md @@ -0,0 +1,6 @@ +# Let's test what we've learned + +- Write a contract named "LogicContract" which implements a public function named "getNumber" which returns 10 +- Write a proxy contract named "ProxyContract". This ProxyContract should take an address of LogicContract as a first parameter. + +Good Luck! diff --git a/locales/de/ProxyContract/6_Storage_Problem/step6.md b/locales/de/ProxyContract/6_Storage_Problem/step6.md new file mode 100644 index 000000000..d2b804284 --- /dev/null +++ b/locales/de/ProxyContract/6_Storage_Problem/step6.md @@ -0,0 +1,13 @@ +# What if we have state variables? + +Things are more complicated once we need to deal with state variables. State variable are saved to **storage**. + +`storage`: is a mapping; each value stored there is persisted and saved on chain. + +_Note: Statically-sized state variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position 0. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible. For contracts that use inheritance, the ordering of state variables is determined by the C3-linearized order of contracts starting with the most base-ward contract_ + +Once we execute **delegate call**, the storage of both contracts get **"merged"** into a single messy state. + +We have to "tell" ProxyContract what the **state** of the **Logic contract** looks like. + +The easiest way to do this is to create a separate contract - in this example - named **StorageContract** which will represent the **state** and which proxyContract will inherit from. diff --git a/locales/de/ProxyContract/7_links/step7.md b/locales/de/ProxyContract/7_links/step7.md new file mode 100644 index 000000000..c2784c3cc --- /dev/null +++ b/locales/de/ProxyContract/7_links/step7.md @@ -0,0 +1,19 @@ +# Check out some links for more info + +- ERC DelegateProxy + https://github.com/ethereum/EIPs/pull/897 + +- The joint post by Zeppelin Solutions and Aragon. + https://blog.openzeppelin.com/proxy-libraries-in-solidity-79fbe4b970fd/ + +- Proxy Patterns by OpenZeppelin + https://blog.openzeppelin.com/proxy-patterns/ + +- The most mature implementation of Proxy pattern is The Unstructure Storage pattern that is released as part of ZeppelinOS + https://blog.openzeppelin.com/upgradeability-using-unstructured-storage/ + +- Great blog post by Jack Tanner + https://blog.indorse.io/ethereum-upgradeable-smart-contract-strategies-456350d0557c + +- Upgradeable Ethereum Smart Contracts + https://medium.com/@daonomic/upgradeable-ethereum-smart-contracts-d036cb373d6 diff --git a/locales/de/ProxyContract/README.md b/locales/de/ProxyContract/README.md new file mode 100644 index 000000000..6a5364c94 --- /dev/null +++ b/locales/de/ProxyContract/README.md @@ -0,0 +1,3 @@ +## Learn the Proxy Pattern + +Save gas & make upgradable contracts diff --git a/locales/de/ProxyContract/config.yml b/locales/de/ProxyContract/config.yml new file mode 100644 index 000000000..e36e640b8 --- /dev/null +++ b/locales/de/ProxyContract/config.yml @@ -0,0 +1,9 @@ +--- +id: proxycontract +name: All about Proxy Contracts +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 3 +tags: + - Remix + - Solidity + - Code Patterns diff --git a/locales/de/README.md b/locales/de/README.md new file mode 100644 index 000000000..cb799bd20 --- /dev/null +++ b/locales/de/README.md @@ -0,0 +1,36 @@ +# This is a repo of tutorials for the Remix's LearnEth Plugin + +### To use these tutorials: + +**1. Open Remix** + +https://remix.ethereum.org + +**2. In the plugin manager activate LEARNETH** + +**3. Go to the Learneth plugin and these tutorials will load by default** + +**4. You may need to sign into Github especially during an in-person workshop** + +Github will block too many requests from the same location, unless you are signed into Github and have input your token. Generally, this is only an issue during in person workshops, when there can be many requests from the same location. + +To input your Github token: + +``` +- In one browser window - go to https://remix.ethereum.org and go to the settings tab +- In another browser window go to: + +https://github.com/settings/tokens + +and create a new token and save it in Remix in the you just opened on the settings tab. +``` + +--- + +### Write your own tutorials for LEARNETH: + +See this site for instructions: + +https://remix-learneth-plugin.readthedocs.io/en/latest/index.html#creating-tutorials + +--- diff --git a/locales/de/Recorder/1_Usecases/1_usecases.md b/locales/de/Recorder/1_Usecases/1_usecases.md new file mode 100644 index 000000000..0c624393c --- /dev/null +++ b/locales/de/Recorder/1_Usecases/1_usecases.md @@ -0,0 +1,7 @@ +1. You want to show someone what happens when you do a number of transactions with a contract and you don't want to explain each step - you just want to get them to the last step. + + - To show someone a problem in their code. + + - In a class, to get the students to a certain place and have them start working from there. + +2. You want to start your development in the JavascriptVM because it is quick and then to switch to another testnet - but you don't want to manually repeat all the tedious clicking for each different network. diff --git a/locales/de/Recorder/2_Record/README.md b/locales/de/Recorder/2_Record/README.md new file mode 100644 index 000000000..41d214277 --- /dev/null +++ b/locales/de/Recorder/2_Record/README.md @@ -0,0 +1,32 @@ +# Setting up a tedious series of steps + +## Following this could get tedious but that's the point. + +We are going to: + +- Deploy a voting contract where there are 3 proposals input in the constructor. +- Give voting privileges to 2 additional address (so we have a total of 3 voting addresses). +- Have one address vote for proposal 1 (0-based index) and the other two vote for proposal 2. + +1. Take the 3_Ballot.sol from the sample solidity files and compile it. Then go to the **Deploy & Run** Module. + +2. Select the **JavaScript VM** Environment. + +3. In the constructor's parameter - put in **["0x5031000000000000000000000000000000000000000000000000000000000000", "0x5032000000000000000000000000000000000000000000000000000000000000", "0x5033000000000000000000000000000000000000000000000000000000000000"]** Then click the **Deploy** button. + +4. Open up the deployed contract. + +5. In the **vote** function put in 2. This means that you as the msg.sender & chairperson are voting for proposal at position 2, which is the last proposal in our list. + +6. Now you need to give other addresses the right to vote. Select another address in the **account** pulldown and copy it and then **go back to the 1st address**. Paste the copy address into the textbox next to the giveRightToVote function. And again, select another address and copy it and **then go back to the 1st address** again and paste it into giveRightToVote. + +7. Now you have 3 addresses with the right to vote. + +8. Switch to one of the addresses that you gave the right to vote and vote for proposal **1**. (Put **1** in the textbox next to the vote function). And then switch to the other address and vote for proposal **2** with that one. + +9. Open up the **Transactions recorded** section of the module - by clicking on the caret. Click the hard disk icon in the **Transactions recorded** section to save your steps. + ![recorder](https://github.com/ethereum/remix-workshops/blob/master/Recorder/2_Record/images/recorder.png?raw=true "recorder") + +10. You will get a modal window that tells you it wants to save a file called **scenario.json**. Click OK. + +11. Click on the function **winningProposal** to confirm that the final proposal won - which is the proposal at position 2 in the array. **0: uint256: winningProposal_ 2** diff --git a/locales/de/Recorder/3_Editing_a_Senario/README.md b/locales/de/Recorder/3_Editing_a_Senario/README.md new file mode 100644 index 000000000..d23dfb95c --- /dev/null +++ b/locales/de/Recorder/3_Editing_a_Senario/README.md @@ -0,0 +1,54 @@ +# Editing a scenario + +Here's the first few lines of the scenario that I recorded. The addresses on my machine will be different from your's. + +``` +{ + "accounts": { + "account{0}": "0xca35b7d915458ef540ade6068dfe2f44e8fa733c", + "account{4}": "0xdd870fa1b7c4700f2bd7f44238821c26f7392148", + "account{3}": "0x583031d1113ad414f02576bd6afabfb302140225" + } +``` + +So if you wanted to play this scenario in another testnet, you'd need to change these addresses to address that you have test ETH on so that you could pay for the transactions. But other than swapping out the addresses, you can quickly run this on other nets. + +And you might change the parameters for the functions. + +For example here is a bit of the scenario.json a bit further down where proposal 2 was voted for by one of the addresses: + +``` +{ + "timestamp": 1566428184043, + "record": { + "value": "0", + "parameters": [ + "2" + ], + "to": "created{1566428035436}", + "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", + "name": "vote", + "inputs": "(uint8)", + "type": "function", + "from": "account{4}" + } + }, +``` + +Let's edit this so that another proposal wins in the playback. + +Change the **parameters** array which now is: + +``` +"parameters": [ + "2" + ] +``` + +to: + +``` +"parameters": [ + "1" + ] +``` diff --git a/locales/de/Recorder/4_Play/README.md b/locales/de/Recorder/4_Play/README.md new file mode 100644 index 000000000..196664550 --- /dev/null +++ b/locales/de/Recorder/4_Play/README.md @@ -0,0 +1,8 @@ +# Playing a scenario + +1. Click the play icon to the right of the floppy disk icon to play the steps you did. + +2. You'll see another instance of the contract deployed. Open it up. + +3. Click the winningProposal function and you should see now that proposal 1 won. + It should print out: **0: uint256: winningProposal_ 1** diff --git a/locales/de/Recorder/README.md b/locales/de/Recorder/README.md new file mode 100644 index 000000000..94d928383 --- /dev/null +++ b/locales/de/Recorder/README.md @@ -0,0 +1,3 @@ +## Get yourself Remixing! + +The recorder is used for recording a set of transactions in the Deploy & Run module, editing their parameters and then playing them back in another context. It really is the remix of Remix! diff --git a/locales/de/Recorder/config.yml b/locales/de/Recorder/config.yml new file mode 100644 index 000000000..b8980e042 --- /dev/null +++ b/locales/de/Recorder/config.yml @@ -0,0 +1,7 @@ +--- +id: recorder +name: Recorder +summary: Save a set of actions and replay and replay and replay +level: 2 +tags: + - Remix diff --git a/locales/de/SolidityBeginnerCourse/README.md b/locales/de/SolidityBeginnerCourse/README.md new file mode 100644 index 000000000..ae0b6d882 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Course + +Learn the most important Solidity beginner concepts interactively, based on the popular https://solidity-by-example.org/ contracts. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/de/SolidityBeginnerCourse/basic-syntax/basicSyntax.md b/locales/de/SolidityBeginnerCourse/basic-syntax/basicSyntax.md new file mode 100644 index 000000000..e9f77871e --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/basic-syntax/basicSyntax.md @@ -0,0 +1,26 @@ +In this section, we will create our first _smart contract_. This contract only consists of a string that holds the value "Hello World!". + +In the first line, we should specify the license that we want to use. You can find a comprehensive list of licenses here: https://spdx.org/licenses/. + +Using the `pragma` keyword (line 3), we specify the Solidity version we want the compiler to use. In this case, it should be greater than or equal to `0.8.3` but less than 0.9.0. + +We define a contract with the keyword `contract` and give it a name, in this case, `HelloWorld` (line 5). + +Inside our contract, we define a _state variable_ `greet` that holds the string `"Hello World!"` (line 6). + +Solidity is a _statically typed_ language, which means that you need to specify the type of the variable when you declare it. In this case, `greet` is a `string`. + +We also define the _visibility_ of the variable, which specifies from where you can access it. In this case, it's a `public` variable that you can access from inside and outside the contract. + +Don't worry if you didn't understand some concepts like _visibility_, _data types_, or _state variables_. We will look into them in the following sections. + +To help you understand the code, we will link in all following sections to video tutorials from the creator of the Solidity by Example contracts. + +Watch a video tutorial on Basic Syntax. + +## ⭐️ Assignment + +1. Delete the HelloWorld contract and its content. +2. Create a new contract named "MyContract". +3. The contract should have a public state variable called "name" of the type string. +4. Assign the value "Alice" to your new variable. diff --git a/locales/de/SolidityBeginnerCourse/config.yml b/locales/de/SolidityBeginnerCourse/config.yml new file mode 100644 index 000000000..a729093d8 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/config.yml @@ -0,0 +1,65 @@ +--- +id: soliditybeginner +name: Solidity Beginner Course +summary: Solidity Beginner Course based on the popular https://solidity-by-example.org/ contracts. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Basic Syntax + path: basic-syntax + - + name: 3. Primitive Data Types + path: primitive-data-types + - + name: 4. Variables + path: variables + - + name: 5.1 Functions - Reading and Writing to a State Variable + path: functions-reading-and-writing + - + name: 5.2 Functions - View and Pure + path: functions-view-and-pure + - + name: 5.3 Functions - Modifiers and Constructors + path: functions-modifiers-and-constructors + - + name: 5.4 Functions - Inputs and Outputs + path: functions-inputs-and-outputs + - + name: 6. Visibility + path: visibility + - + name: 7.1 Control Flow - If/Else + path: control-flow-if-else + - + name: 7.2 Control Flow - Loops + path: control-flow-loops + - + name: 8.1 Data Structures - Arrays + path: data-structures-arrays + - + name: 8.2 Data Structures - Mappings + path: data-structures-mappings + - + name: 8.3 Data Structures - Structs + path: data-structures-structs + - + name: 8.4 Data Structures - Enums + path: data-structures-enums + - + name: 9. Data Locations + path: data-locations + - + name: 10.1 Transactions - Ether and Wei + path: transactions-ether-and-wei + - + name: 10.2 Transactions - Gas and Gas Price + path: transactions-gas-and-gas-price + - + name: 10.3 Transactions - Sending Ether + path: transactions-sending-ether diff --git a/locales/de/SolidityBeginnerCourse/control-flow-if-else/ifElse.md b/locales/de/SolidityBeginnerCourse/control-flow-if-else/ifElse.md new file mode 100644 index 000000000..634e27689 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/control-flow-if-else/ifElse.md @@ -0,0 +1,33 @@ +Solidity supports different control flow statements that determine which parts of the contract will be executed. The conditional _If/Else statement_ enables contracts to make decisions depending on whether boolean conditions are either `true` or `false`. + +Solidity differentiates between three different If/Else statements: `if`, `else`, and `else if`. + +### if + +The `if` statement is the most basic statement that allows the contract to perform an action based on a boolean expression. + +In this contract’s `foo` function (line 5) the if statement (line 6) checks if `x` is smaller than `10`. If the statement is true, the function returns `0`. + +### else + +The `else` statement enables our contract to perform an action if conditions are not met. + +In this contract, the `foo` function uses the `else` statement (line 10) to return `2` if none of the other conditions are met. + +### else if + +With the `else if` statement we can combine several conditions. + +If the first condition (line 6) of the foo function is not met, but the condition of the `else if` statement (line 8) becomes true, the function returns `1`. + +Watch a video tutorial on the If/Else statement. + +## ⭐️ Assignment + +Create a new function called `evenCheck` in the `IfElse` contract: + +- That takes in a `uint` as an argument. +- The function returns `true` if the argument is even, and `false` if the argument is odd. +- Use a ternery operator to return the result of the `evenCheck` function. + +Tip: The modulo (%) operator produces the remainder of an integer division. diff --git a/locales/de/SolidityBeginnerCourse/control-flow-loops/loops.md b/locales/de/SolidityBeginnerCourse/control-flow-loops/loops.md new file mode 100644 index 000000000..ffaa30650 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/control-flow-loops/loops.md @@ -0,0 +1,32 @@ +Solidity supports iterative control flow statements that allow contracts to execute code repeatedly. + +Solidity differentiates between three types of loops: `for`, `while`, and `do while` loops. + +### for + +Generally, `for` loops (line 7) are great if you know how many times you want to execute a certain block of code. In solidity, you should specify this amount to avoid transactions running out of gas and failing if the amount of iterations is too high. + +### while + +If you don’t know how many times you want to execute the code but want to break the loop based on a condition, you can use a `while` loop (line 20). +Loops are seldom used in Solidity since transactions might run out of gas and fail if there is no limit to the number of iterations that can occur. + +### do while + +The `do while` loop is a special kind of while loop where you can ensure the code is executed at least once, before checking on the condition. + +### continue + +The `continue` statement is used to skip the remaining code block and start the next iteration of the loop. In this contract, the `continue` statement (line 10) will prevent the second if statement (line 12) from being executed. + +### break + +The `break` statement is used to exit a loop. In this contract, the break statement (line 14) will cause the for loop to be terminated after the sixth iteration. + +Watch a video tutorial on Loop statements. + +## ⭐️ Assignment + +1. Create a public `uint` state variable called count in the `Loop` contract. +2. At the end of the for loop, increment the count variable by 1. +3. Try to get the count variable to be equal to 9, but make sure you don’t edit the `break` statement. diff --git a/locales/de/SolidityBeginnerCourse/data-locations/dataLocations.md b/locales/de/SolidityBeginnerCourse/data-locations/dataLocations.md new file mode 100644 index 000000000..881bf8ffc --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/data-locations/dataLocations.md @@ -0,0 +1,54 @@ +The values of variables in Solidity can be stored in different data locations: _memory_, _storage_, and _calldata_. + +As we have discussed before, variables of the value type store an independent copy of a value, while variables of the reference type (array, struct, mapping) only store the location (reference) of the value. + +If we use a reference type in a function, we have to specify in which data location their values are stored. The price for the execution of the function is influenced by the data location; creating copies from reference types costs gas. + +### Storage + +Values stored in _storage_ are stored permanently on the blockchain and, therefore, are expensive to use. + +In this contract, the state variables `arr`, `map`, and `myStructs` (lines 5, 6, and 10) are stored in storage. State variables are always stored in storage. + +### Memory + +Values stored in _memory_ are only stored temporarily and are not on the blockchain. They only exist during the execution of an external function and are discarded afterward. They are cheaper to use than values stored in _storage_. + +In this contract, the local variable `myMemstruct` (line 19), as well as the parameter `_arr` (line 31), are stored in memory. Function parameters need to have the data location _memory_ or _calldata_. + +### Calldata + +_Calldata_ stores function arguments. Like _memory_, _calldata_ is only stored temporarily during the execution of an external function. In contrast to values stored in _memory_, values stored in _calldata_ can not be changed. Calldata is the cheapest data location to use. + +In this contract, the parameter `_arr` (line 35) has the data location _calldata_. If we wanted to assign a new value to the first element of the array `_arr`, we could do that in the `function g` (line 31) but not in the `function h` (line 35). This is because `_arr` in `function g `has the data location _memory_ and _function h_ has the data location `calldata`. + +## Assignments + +### Memory to memory + +Assignments from _memory_ to _memory_ create references instead of copies. If you change the value in one variable, the value of all other variables that reference the same data will be changed. + +If we were to create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myMemStruct` (line 19), any change to `myMemStruct2` would also change the value of `myMemStruct`. + +### Storage to local storage + +Assignments from _storage_ to _local storage_ also create references, not copies. + +If we change the value of the local variable `myStruct` (line 17), the value of our state variable `myStructs` (line 10) changes as well. + +## Storage and memory/calldata + +Assignments between _storage_ and _memory_ (or _calldata_) create independent copies, not references. + +If we were to create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myStruct`, changes in `myMemStruct3` would not affect the values stored in the mapping `myStructs` (line 10). + +As we said in the beginning, when creating contracts we have to be mindful of gas costs. Therefore, we need to use data locations that require the lowest amount of gas possible. + +## ⭐️ Assignment + +1. Change the value of the `myStruct` member `foo`, inside the `function f`, to 4. +2. Create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` and assign it the value of `myMemStruct`. Change the value of the `myMemStruct2` member `foo` to 1. +3. Create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` and assign it the value of `myStruct`. Change the value of the `myMemStruct3` member `foo` to 3. +4. Let the function f return `myStruct`, `myMemStruct2`, and `myMemStruct3`. + +Tip: Make sure to create the correct return types for the function `f`. diff --git a/locales/de/SolidityBeginnerCourse/data-structures-arrays/arrays.md b/locales/de/SolidityBeginnerCourse/data-structures-arrays/arrays.md new file mode 100644 index 000000000..19af3de49 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/data-structures-arrays/arrays.md @@ -0,0 +1,44 @@ +In the next sections, we will look into the data structures that we can use to organize and store our data in Solidity. + +_Arrays_, _mappings_ and _structs_ are all _reference types_. Unlike _value types_ (e.g. _booleans_ or _integers_) reference types don't store their value directly. Instead, they store the location where the value is being stored. Multiple reference type variables could reference the same location, and a change in one variable would affect the others, therefore they need to be handled carefully. + +In Solidity, an array stores an ordered list of values of the same type that are indexed numerically. + +There are two types of arrays, compile-time _fixed-size_ and _dynamic arrays_. For fixed-size arrays, we need to declare the size of the array before it is compiled. The size of dynamic arrays can be changed after the contract has been compiled. + +### Declaring arrays + +We declare a fixed-size array by providing its type, array size (as an integer in square brackets), visibility, and name (line 9). + +We declare a dynamic array in the same manner. However, we don’t provide an array size and leave the brackets empty (line 6). + +### Initializing arrays + +We can initialize the elements of an array all at once (line 7), or initiate new elements one by one (arr[0] = 1;). If we declare an array, we automatically initialize its elements with the default value 0 (line 9). + +### Accessing array elements + +We access elements inside an array by providing the name of the array and the index in brackets (line 12). + +### Adding array elements + +Using the `push()` member function, we add an element to the end of a dynamic array (line 25). + +### Removing array elements + +Using the `pop()` member function, we delete the last element of a dynamic array (line 31). + +We can use the `delete` operator to remove an element with a specific index from an array (line 42). +When we remove an element with the `delete` operator all other elements stay the same, which means that the length of the array will stay the same. This will create a gap in our array. +If the order of the array is not important, then we can move the last element of the array to the place of the deleted element (line 46), or use a mapping. A mapping might be a better choice if we plan to remove elements in our data structure. + +### Array length + +Using the length member, we can read the number of elements that are stored in an array (line 35). + +Watch a video tutorial on Arrays. + +## ⭐️ Assignment + +1. Initialize a public fixed-sized array called `arr3` with the values 0, 1, 2. Make the size as small as possible. +2. Change the `getArr()` function to return the value of `arr3`. diff --git a/locales/de/SolidityBeginnerCourse/data-structures-enums/enums.md b/locales/de/SolidityBeginnerCourse/data-structures-enums/enums.md new file mode 100644 index 000000000..40411db67 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/data-structures-enums/enums.md @@ -0,0 +1,33 @@ +In Solidity _enums_ are custom data types consisting of a limited set of constant values. We use enums when our variables should only get assigned a value from a predefined set of values. + +In this contract, the state variable `status` can get assigned a value from the limited set of provided values of the enum `Status` representing the various states of a shipping status. + +### Defining enums + +We define an enum with the enum keyword, followed by the name of the custom type we want to create (line 6). Inside the curly braces, we define all available members of the enum. + +### Initializing an enum variable + +We can initialize a new variable of an enum type by providing the name of the enum, the visibility, and the name of the variable (line 16). Upon its initialization, the variable will be assigned the value of the first member of the enum, in this case, Pending (line 7). + +Even though enum members are named when you define them, they are stored as unsigned integers, not strings. They are numbered in the order that they were defined, the first member starting at 0. The initial value of status, in this case, is 0. + +### Accessing an enum value + +To access the enum value of a variable, we simply need to provide the name of the variable that is storing the value (line 25). + +### Updating an enum value + +We can update the enum value of a variable by assigning it the `uint` representing the enum member (line 30). Shipped would be 1 in this example. Another way to update the value is using the dot operator by providing the name of the enum and its member (line 35). + +### Removing an enum value + +We can use the delete operator to delete the enum value of the variable, which means as for arrays and mappings, to set the default value to 0. + +Watch a video tutorial on Enums. + +## ⭐️ Assignment + +1. Define an enum type called `Size` with the members `S`, `M`, and `L`. +2. Initialize the variable `sizes` of the enum type `Size`. +3. Create a getter function `getSize()` that returns the value of the variable `sizes`. diff --git a/locales/de/SolidityBeginnerCourse/data-structures-mappings/mappings.md b/locales/de/SolidityBeginnerCourse/data-structures-mappings/mappings.md new file mode 100644 index 000000000..72fc4acb4 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/data-structures-mappings/mappings.md @@ -0,0 +1,37 @@ +In Solidity, _mappings_ are a collection of key types and corresponding value type pairs. + +The biggest difference between a mapping and an array is that you can't iterate over mappings. If we don't know a key we won't be able to access its value. If we need to know all of our data or iterate over it, we should use an array. + +If we want to retrieve a value based on a known key we can use a mapping (e.g. addresses are often used as keys). Looking up values with a mapping is easier and cheaper than iterating over arrays. If arrays become too large, the gas cost of iterating over it could become too high and cause the transaction to fail. + +We could also store the keys of a mapping in an array that we can iterate over. + +### Creating mappings + +Mappings are declared with the syntax `mapping(KeyType => ValueType) VariableName`. +The key type can be any built-in value type or any contract, but not a reference type. The value type can be of any type. + +In this contract, we are creating the public mapping `myMap` (line 6) that associates the key type `address` with the value type `uint`. + +### Accessing values + +The syntax for interacting with key-value pairs of mappings is similar to that of arrays. +To find the value associated with a specific key, we provide the name of the mapping and the key in brackets (line 11). + +In contrast to arrays, we won't get an error if we try to access the value of a key whose value has not been set yet. When we create a mapping, every possible key is mapped to the default value 0. + +### Setting values + +We set a new value for a key by providing the mapping’s name and key in brackets and assigning it a new value (line 16). + +### Removing values + +We can use the delete operator to delete a value associated with a key, which will set it to the default value of 0. As we have seen in the arrays section. + +Watch a video tutorial on Mappings. + +## ⭐️ Assignment + +1. Create a public mapping `balances` that associates the key type `address` with the value type `uint`. +2. Change the functions `get` and `remove` to work with the mapping balances. +3. Change the function `set` to create a new entry to the balances mapping, where the key is the address of the parameter and the value is the balance associated with the address of the parameter. diff --git a/locales/de/SolidityBeginnerCourse/data-structures-structs/structs.md b/locales/de/SolidityBeginnerCourse/data-structures-structs/structs.md new file mode 100644 index 000000000..fba0d93b0 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/data-structures-structs/structs.md @@ -0,0 +1,29 @@ +In Solidity, we can define custom data types in the form of _structs_. Structs are a collection of variables that can consist of different data types. + +### Defining structs + +We define a struct using the `struct` keyword and a name (line 5). Inside curly braces, we can define our struct’s members, which consist of the variable names and their data types. + +### Initializing structs + +There are different ways to initialize a struct. + +Positional parameters: We can provide the name of the struct and the values of its members as parameters in parentheses (line 16). + +Key-value mapping: We provide the name of the struct and the keys and values as a mapping inside curly braces (line 19). + +Initialize and update a struct: We initialize an empty struct first and then update its member by assigning it a new value (line 23). + +### Accessing structs + +To access a member of a struct we can use the dot operator (line 33). + +### Updating structs + +To update a structs’ member we also use the dot operator and assign it a new value (lines 39 and 45). + +Watch a video tutorial on Structs. + +## ⭐️ Assignment + +Create a function `remove` that takes a `uint` as a parameter and deletes a struct member with the given index in the `todos` mapping. diff --git a/locales/de/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md b/locales/de/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md new file mode 100644 index 000000000..d0e628f6b --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md @@ -0,0 +1,37 @@ +In this section, we will learn more about the inputs and outputs of functions. + +### Multiple named Outputs + +Functions can return multiple values that can be named and assigned to their name. + +The `returnMany` function (line 6) shows how to return multiple values. +You will often return multiple values. It could be a function that collects outputs of various functions and returns them in a single function call for example. + +The `named` function (line 19) shows how to name return values. +Naming return values helps with the readability of your contracts. Named return values make it easier to keep track of the values and the order in which they are returned. You can also assign values to a name. + +The `assigned` function (line 33) shows how to assign values to a name. +When you assign values to a name you can omit (leave out) the return statement and return them individually. + +### Deconstructing Assignments + +You can use deconstructing assignments to unpack values into distinct variables. + +The `destructingAssigments` function (line 49) assigns the values of the `returnMany` function to the new local variables `i`, `b`, and `j` (line 60). + +### Input and Output restrictions + +There are a few restrictions and best practices for the input and output parameters of contract functions. + +"_[Mappings] cannot be used as parameters or return parameters of contract functions that are publicly visible._" +From the Solidity documentation. + +Arrays can be used as parameters, as shown in the function `arrayInput` (line 71). Arrays can also be used as return parameters as shown in the function `arrayOutput` (line 76). + +You have to be cautious with arrays of arbitrary size because of their gas consumption. While a function using very large arrays as inputs might fail when the gas costs are too high, a function using a smaller array might still be able to execute. + +Watch a video tutorial on Function Outputs. + +## ⭐️ Assignment + +Create a new function called `returnTwo` that returns the values `-2` and `true` without using a return statement. diff --git a/locales/de/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md b/locales/de/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md new file mode 100644 index 000000000..d707a987b --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md @@ -0,0 +1,39 @@ +In this section, we will learn how to modify the behavior of a function and how to run contract initialization code. + +### Function Modifier + +_Function Modifiers_ are used to change the behavior of a function. For example, they often check for a condition prior to executing a function to restrict access or validate inputs. + +This first part of this contract is about changing ownership of a contract. Ownership in this contract is expressed by the value of the state variable `owner` that is of the type `address` (line 7). + +The function `changeOwner` (line 33) can change this ownership. It takes an input parameter of the type `address` and assigns its value to the state variable `owner`. + +However, this function cannot simply be executed under all conditions; it has two modifiers, `onlyOwner` and `validAddress`. + +Let's look at `onlyOwner` first (line 18). +Function modifiers are defined with the `modifier` keyword and a unique name; they can also have parameters. + +The underscore `_` (line 23) is used inside modifiers to represent the rest of the code that will be executed in the body of the modified function. +The code you place before the underscore in the modifier will be executed before the code in the body of the modified function. The code after the underscore will be executed after the code in the body of the modified function. + +In this case, the `require` function (line 19) checks if the address executing the contract is the same as the value stored in the variable `owner`. If it is, the rest of the code will be executed, otherwise it will throw an error. + +You can learn more about `assert` and `require` in the Solidity documentation, they are used to check for conditions and throw errors if they are not met. + +The `validAddress` modifier (line 28) has a parameter of type `address` and checks if the provided address is valid. If it is, it continues to execute the code. + +### Constructor + +A constructor function is executed upon the creation of a contract. You can use it to run contract initialization code. The constructor can have parameters and is especially useful when you don't know certain initialization values before the deployment of the contract. + +You declare a constructor using the `constructor` keyword. The constructor in this contract (line 11) sets the initial value of the owner variable upon the creation of the contract. + +Watch a video tutorial on Function Modifiers. + +## ⭐️ Assignment + +1. Create a new function, `increaseX` in the contract. The function should take an input parameter of type `uint` and increase the value of the variable `x` by the value of the input parameter. +2. Make sure that x can only be increased. +3. The body of the function `increaseX` should be empty. + +Tip: Use modifiers. diff --git a/locales/de/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md b/locales/de/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md new file mode 100644 index 000000000..3670c03e2 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md @@ -0,0 +1,23 @@ +This section will give a short introduction to functions and teach you how to use them to read from and write to a state variable. + +As in other languages, we use functions in Solidity to create modular, reusable code. However, Solidity functions have some particularities. + +Solidity functions can be split into two types: + +1. Functions that modify the state of the blockchain, like writing to a state variable. In this contract, the `set` function (line 9) changes the state variable `num`. +2. Functions that don't modify the state of the blockchain. These functions are marked `view` or `pure`. For example, in this contract, the `get` function (line 14) marked `view` that only returns `num` does not change the state. + +To define a function, use the `function` keyword followed by a unique name. + +If the function takes inputs like our `set` function (line 9), you must specify the parameter types and names. A common convention is to use an underscore as a prefix for the parameter name to distinguish them from state variables. + +You can then set the visibility of a function and declare them `view` or `pure` as we do for the `get` function if they don't modify the state. Our `get` function also returns values, so we have to specify the return types. In this case, it's a `uint` since the state variable `num` that the function returns is a `uint`. + +We will explore the particularities of Solidity functions in more detail in the following sections. + +Watch a video tutorial on Functions. + +## ⭐️ Assignment + +1. Create a public state variable called `b` that is of type `bool` and initialize it to `true`. +2. Create a public function called `get_b` that returns the value of `b`. diff --git a/locales/de/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md b/locales/de/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md new file mode 100644 index 000000000..b846c7d99 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md @@ -0,0 +1,44 @@ +This section will look into the types of functions that don't modify the state of the blockchain: _view_ and _pure_ functions. + +### View Functions + +_View functions_ promise to not modify the state. + +"The following statements are considered modifying the state: + +1. Writing to state variables. +2. Emitting events. +3. Creating other contracts. +4. Using selfdestruct. +5. Sending Ether via calls. +6. Calling any function not marked view or pure. +7. Using low-level calls. +8. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a view function using the keyword `view`. In this contract, `addToX` (line 8) is a view function. This function takes the parameter `y` and returns the sum of the parameter and the state variable `x`. It reads `x` but does not modify it. + +### Pure functions + +_Pure functions_ promise to neither modify nor to read the state. + +"In addition to the list of state modifying statements explained above, the following are considered reading from the state: + +1. Reading from state variables. +2. Accessing `address(this).balance` or `
.balance`. +3. Accessing any of the members of block, tx, msg (with the exception of `msg.sig` and `msg.data`). +4. Calling any function not marked pure. +5. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a pure function using the keyword `pure`. In this contract, `add` (line 13) is a pure function. This function takes the parameters `i` and `j`, and returns the sum of them. It neither reads nor modifies the state variable `x`. + +In Solidity development, you need to optimise your code for saving computation cost (gas cost). Declaring functions view and pure can save gas cost and make the code more readable and easier to maintain. Pure functions don't have any side effects and will always return the same result if you pass the same arguments. + +Watch a video tutorial on View and Pure Functions. + +## ⭐️ Assignment + +Create a function called `addToX2` that takes the parameter `y` and updates the state variable `x` with the sum of the parameter and the state variable `x`. diff --git a/locales/de/SolidityBeginnerCourse/introduction/introduction.md b/locales/de/SolidityBeginnerCourse/introduction/introduction.md new file mode 100644 index 000000000..cc821a46a --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/introduction/introduction.md @@ -0,0 +1,32 @@ +Welcome to this interactive Solidity course for beginners. + +In this first section, we will give you a short preview of the concepts we will cover in this course, look at an example smart contract, and show you how you can interact with this contract in the Remix IDE. + +This contract is a counter contract that has the functionality to increase, decrease, and return the state of a counter variable. + +If we look at the top of the contract, we can see some information about the contract like the license (line 1), the Solidity version (line 2), as well as the keyword `contract` and it's name, `Counter` (line 4). We will cover these concepts in the next section about the **Basic Syntax**. + +With `uint public count` (line 5) we declare a state variable of the type `uint` with the visibility `public`. We will cover these concepts in our sections about **Variables**, **Primitive Data Types**, and **Visibility**. + +We then create a `get` function (line 8) that is defined with the `view` keyword and returns a `uint` type. Specifically, it returns the `count` variable. This contract has two more functions, an `inc` (line 13) and `dec` (line 18) function that increases or decreases our count variable. +We will talk about these concepts in our sections about **Functions - Reading and Writing to a State Variable** and **Functions - View and pure**. + +## Compile and Deploy through Remix + +**GIF** Interacting with the contract: Compile and deploy contract + +1. We can compile your `Counter` contract in the "Solidity compiler" module of the Remix IDE. + +2. In the "Deploy & run transactions" module, we select our contract "Counter" in the contract input field and click on the "Deploy" button. + +3. We expand the token contract functions in the IDE, and test its `get`, `inc`, and `dec` functions. + +## ⭐️ Assignment + +Throughout this course, we will give you assignments to test and consolidate your newly acquired knowledge. + +Your first assignment is to: + +1. Compile this contract. +2. Deploy it to the Remix VM. +3. Interact with your contract. diff --git a/locales/de/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md b/locales/de/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md new file mode 100644 index 000000000..9ea6b8626 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md @@ -0,0 +1,33 @@ +In this section, we will show you Solidity’s primitive data types, how to declare them, and their characteristics. + +### bool + +You can declare data a boolean type by using the keyword ‘bool’. Booleans can either have the value `true` or `false`. + +### uint + +We use the keywords `uint` and `uint8` to `uint256` to declare an _unsigned integer type_ (they don’t have a sign, unlike -12, for example). Uints are integers that are positive or zero and range from 8 bits to 256 bits. The type `uint` is the same as `uint256`. + +### int + +We use the keywords `int` and `int8` to `int256` to declare an integer type. Integers can be positive, negative, or zero and range from 8 bits to 256 bits. The type `int` is the same as `int256`. + +### address + +Variables of the type `address` hold a 20-byte value, which is the size of an Ethereum address. There is also a special kind of Ethereum address, `address payable`, which can receive ether from the contract. + +All these data types have default values, as shown in the contract (line 29). + +You can learn more about these data types as well as _Fixed Point Numbers_, _Byte Arrays_, _Strings_, and more in the Solidity documentation. + +Later in the course, we will look at data structures like **Mappings**, **Arrays**, **Enums**, and **Structs**. + +Watch a video tutorial on Primitive Data Types. + +## ⭐️ Assignment + +1. Create a new variable `newAddr` that is a `public` `address` and give it a value that is not the same as the available variable `addr`. +2. Create a `public` variable called `neg` that is a negative number, decide upon the type. +3. Create a new variable, `newU` that has the smallest `uint` size type and the smallest `uint` value and is `public`. + +Tip: Look at the other address in the contract or search the internet for an Ethereum address. diff --git a/locales/de/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md b/locales/de/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md new file mode 100644 index 000000000..57208c555 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md @@ -0,0 +1,26 @@ +_Ether_ (ETH) is a cryptocurrency. _Ether_ is also used to pay fees for using the Ethereum network, like making transactions in the form of sending _Ether_ to an address or interacting with an Ethereum application. + +### Ether Units + +To specify a unit of _Ether_, we can add the suffixes `wei`, `gwei`, or `ether` to a literal number. + +#### `wei` + +_Wei_ is the smallest subunit of _Ether_, named after the cryptographer [Wei Dai](https://en.wikipedia.org/wiki/Wei_Dai). _Ether_ numbers without a suffix are treated as `wei` (line 7). + +#### `gwei` + +One `gwei` (giga-wei) is equal to 1,000,000,000 (10^9) `wei`. + +#### `ether` + +One `ether` is equal to 1,000,000,000,000,000,000 (10^18) `wei` (line 11). + +Watch a video tutorial on Ether and Wei. + +## ⭐️ Assignment + +1. Create a `public` `uint` called `oneGWei` and set it to 1 `gwei`. +2. Create a `public` `bool` called `isOneGWei` and set it to the result of a comparison operation between 1 gwei and 10^9. + +Tip: Look at how this is written for `gwei` and `ether` in the contract. diff --git a/locales/de/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md b/locales/de/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md new file mode 100644 index 000000000..bbc25575c --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md @@ -0,0 +1,29 @@ +As we have seen in the previous section, executing code via transactions on the Ethereum Network costs transaction fees in the form of Ether. The amount of fees that have to be paid to execute a transaction depends on the amount of _gas_ that the execution of the transaction costs. + +### Gas + +_Gas_ is the unit that measures the amount of computational effort that is required to execute a specific operation on the Ethereum network. + +### Gas price + +The _gas_ that fuels Ethereum is sometimes compared to the gas that fuels a car. The amount of gas your car consumes is mostly the same, but the price you pay for gas depends on the market. + +Similarly, the amount of _gas_ that a transaction requires is always the same for the same computational work that is associated with it. However the price that the sender of the transaction is willing to pay for the _gas_ is up to them. Transactions with higher _gas prices_ are going through faster; transactions with very low _gas prices_ might not go through at all. + +When sending a transaction, the sender has to pay the _gas_ fee (gas_price \* gas) upon execution of the transaction. If _gas_ is left over after the execution is completed, the sender gets refunded. + +_Gas_ prices are denoted in gwei. + +### Gas limit + +When sending a transaction, the sender specifies the maximum amount of gas that they are willing to pay for. If they set the limit too low, their transaction can run out of _gas_ before being completed, reverting any changes being made. In this case, the _gas_ was consumed and can’t be refunded. + +Learn more about _gas_ on ethereum.org. + +Watch a video tutorial on Gas and Gas Price. + +## ⭐️ Assignment + +Create a new `public` state variable in the `Gas` contract called `cost` of the type `uint`. Store the value of the gas cost for deploying the contract in the new variable, including the cost for the value you are storing. + +Tip: You can check in the Remix terminal the details of a transaction, including the gas cost. You can also use the Remix plugin _Gas Profiler_ to check for the gas cost of transactions. diff --git a/locales/de/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md b/locales/de/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md new file mode 100644 index 000000000..58fb4c5a6 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md @@ -0,0 +1,86 @@ +In this section, we will learn how a contract can send and receive Ether. + +### Sending Ether + +We have three different options to transfer Ether: `transfer()`, `send()` and `call()`. + +#### **transfer** + +`
.transfer(uint256 amount)` + +- `transfer()` throws an exception on failure +- Forwards a fixed 2300 gas stipend + +An example of `transfer()` can be seen in the `SendEther` contract (line 35). +**`Transfer()` is not recommended to be used anymore.** + +#### **send** + +`
.send(uint256 amount) returns (bool)` + +- `send()` returns false on failure +- Forwards a fixed 2300 gas stipend + +An example of `send()` can be seen in the `SendEther` contract (line 41). +**`Send()` is not recommended to be used anymore.** + +#### **call** + +`
.call(bytes memory) returns (bool, bytes memory)` + +- `call()` returns false on failure +- Forwards the maximum amount of gas, but this is adjustable + +An example of `call()` can be seen in the `SendEther` contract (line 48). +`Call()` is currently recommended if you are transfering Ether. + +The reason `transfer()` and `send()` were introduced was to guard against _reentry attacks_ by limiting the forwarded gas to 2300, which would be insufficient to make a reentrant call that can modify storage. + +As we discussed in the last section, each operation on Ethereum has a specific cost associated with it. Certain operations have become more cost intensive over time, so the gas costs associated with them are also raised. When gas costs for operations are subject to change it is not good to use a hardcoded gas amount like transfer(), and send() do. + +That’s why `call()` instead of `transfer()` is now recommended to send Ether. + +Learn more about the subject in this Consensys blog post. + +### Reentrancy attack + +A _reentrancy attack_ occurs when a function makes an external call to an untrusted contract and the attacker uses the contract to make recursive calls back to the original function before it finishes its execution. Through this method, the attacker can drain funds and manipulate data in unintended ways. + +To guard against a _reentrancy attack_, all state changes should be made before calling an external contract. This is also called the Checks-Effects-Interactions pattern. + +Another way to prevent reentrancy is to use a _Reentrancy Guard_ that checks for such calls and rejects them. You can see an example of this in the contract in our modifier section or a more gas-efficient version on Open Zepplin. + +### Receiving Ether + +If we want to enable a contract to receive Ether without a function being called, we need to create a `receive` function (line 22) or a `fallback` function (line 25); otherwise, the Ether will be rejected, and the contract will throw an exception. + +The `receive` function is executed on calls with empty calldata (e.g. plain Ether transfers via send() or transfer()), while the fallback function is executed on calls with calldata. If no receive function exists but a fallback function does, calls with empty calldata will also use the fallback function. + +### Payable function modifier + +The `payable` function modifier allows a function to receive Ether. + +The `receive` function (line 22) needs to be `payable`. If you delete the `payable` modifier you will get an error from the compiler. If you delete the `payable` modifier from the `fallback` function (line 25) it will compile, but it won’t be able to receive Ether. +The functions `sendViaTransfer`, `sendViaSend`, and `sendViaCall` (lines 33, 38, and 45) also need to be `payable` in order to receive Ether. + +### Payable address + +Solidity makes a distinction between two different flavors of the address data type: address and address payable. + +`address`: Holds a 20-byte value. +`address payable`: Holds a 20-byte value and can receive Ether via its members: transfer and send. + +If you change the parameter type for the functions `sendViaTransfer` and `sendViaSend` (line 33 and 38) from `payable address` to `address`, you won’t be able to use `transfer()` (line 35) or `send()` (line 41). + +Watch a video tutorial on Sending Ether. + +## ⭐️ Assignment + +Build a charity contract that receives Ether that can be withdrawn by a beneficiary. + +1. Create a contract called `Charity`. +2. Add a public state variable called `owner` of the type address. +3. Create a donate function that is public and payable without any parameters or function code. +4. Create a withdraw function that is public and sends the total balance of the contract to the `owner` address. + +Tip: Test your contract by deploying it from one account and then sending Ether to it from another account. Then execute the withdraw function. diff --git a/locales/de/SolidityBeginnerCourse/variables/variables.md b/locales/de/SolidityBeginnerCourse/variables/variables.md new file mode 100644 index 000000000..dfb35b382 --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/variables/variables.md @@ -0,0 +1,29 @@ +There are three different types of variables in Solidity: _State Variables_, _Local Variables_, and _Global Variables_. + +## 1. State Variables + +_State Variables_ are stored in the contract _storage_ and thereby on the blockchain. They are declared inside the contract but outside the function. +This contract has two state variables, the string `text`(line 6) and the uint `num` (line 7). + +## 2. Local Variables + +_Local Variables_ are stored in the _memory_ and their values are only accessible within the function they are defined in. Local Variables are not stored on the blockchain. +In this contract, the uint `i` (line 11) is a local variable. + +## 3. Global Variables + +_Global Variables_, also called _Special Variables_, exist in the global namespace. They don't need to be declared but can be accessed from within your contract. +Global Variables are used to retrieve information about the blockchain, particular addresses, contracts, and transactions. + +In this example, we use `block.timestamp` (line 14) to get a Unix timestamp of when the current block was generated and `msg.sender` (line 15) to get the caller of the contract function’s address. + +A list of all Global Variables is available in the Solidity documentation. + +Watch video tutorials on State Variables, Local Variables, and Global Variables. + +## ⭐️ Assignment + +1. Create a new public state variable called `blockNumber`. +2. Inside the function `doSomething()`, assign the value of the current block number to the state variable `blockNumber`. + +Tip: Look into the global variables section of the Solidity documentation to find out how to read the current block number. diff --git a/locales/de/SolidityBeginnerCourse/visibility/visibility.md b/locales/de/SolidityBeginnerCourse/visibility/visibility.md new file mode 100644 index 000000000..79e4307bf --- /dev/null +++ b/locales/de/SolidityBeginnerCourse/visibility/visibility.md @@ -0,0 +1,37 @@ +The `visibility` specifier is used to control who has access to functions and state variables. + +There are four types of visibilities: `external`, `public`, `internal`, and `private`. + +They regulate if functions and state variables can be called from inside the contract, from contracts that derive from the contract (child contracts), or from other contracts and transactions. + +### private + +- Can be called from inside the contract + +### internal + +- Can be called from inside the contract +- Can be called from a child contract + +### public + +- Can be called from inside the contract +- Can be called from a child contract +- Can be called from other contracts or transactions + +### external + +- Can be called from other contracts or transactions +- State variables can not be `external` + +In this example, we have two contracts, the `Base` contract (line 4) and the `Child` contract (line 55) which inherits the functions and state variables from the `Base` contract. + +When you uncomment the `testPrivateFunc` (lines 58-60) you get an error because the child contract doesn’t have access to the private function `privateFunc` from the `Base` contract. + +If you compile and deploy the two contracts, you will not be able to call the functions `privateFunc` and `internalFunc` directly. You will only be able to call them via `testPrivateFunc` and `testInternalFunc`. + +Watch a video tutorial on Visibility. + +## ⭐️ Assignment + +Create a new function in the `Child` contract called `testInternalVar` that returns the values of all state variables from the `Base` contract that are possible to return. diff --git a/locales/de/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md b/locales/de/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md new file mode 100644 index 000000000..801d8c582 --- /dev/null +++ b/locales/de/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md @@ -0,0 +1,47 @@ +In this tutorial, we'll explore the Uniswap V3 Swap contract to learn about how single-hop and multi-hop swaps work. + +But first, some Uniswap fundamentals. + +## What is Uniswap? + +Uniswap is a decentralized cryptocurrency exchange. It allows users to exchange tokens without the need for a centralized intermediary. Uniswap is a key player in the decentralized finance (DeFi) space. + +## How does Uniswap work? + +Instead of using an order book like a traditional centralized exchange, Uniswap uses an automated market maker (AMM) model. In Uniswap, the AMM is a smart contract that holds reserves of tokens (Liquidity Pool). Users can trade between tokens in the Liquidity Pool. The price of each token is determined by the ratio of the reserves. + +### Step-by-step example of a Uniswap trade + +1. Alice wants to trade 1 ETH for DAI. +2. Alice sends 1 ETH to the Uniswap smart contract. +3. The Uniswap smart contract calculates the amount of DAI that Alice should receive based on the current exchange rate. +4. The Uniswap smart contract sends the DAI to Alice. +5. The Uniswap smart contract adds the 1 ETH to its reserves. +6. The Uniswap smart contract recalculates the exchange rate based on the new reserves. + +The tokens in the Liquidity Pool are provided by Liquidity Providers. When a Liquidity Provider deposits tokens into a Liquidity Pool, they receive Liquidity Provider Tokens in return. Liquidity Provider Tokens represent a user's share of a Liquidity Pool. + +Users of Uniswap pay a fee for each trade. The fee is paid to the Liquidity Providers in the form of additional Liquidity Provider Tokens. + +## Uniswap Swap Contract + +The Uniswap Swap contract allows users to swap tokens using Uniswap V3. It can do single-hop swaps, which allow users to exchange one token for another directly. It can also do multi-hop swaps, which means that users can exchange one token for another by routing through multiple tokens. Routing in this context means that the swap contract will exchange the token for another token, then exchange that token for another token, and so on until it reaches the desired token. + +## Conclusion + +In this section, we learned about Uniswap, how it works, and how we are going to use it to swap tokens. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is Uniswap? + +1. A centralized exchange protocol. +2. A decentralized exchange protocol that uses an order book. +3. A decentralized exchange protocol that uses an automated market maker (AMM) model. +4. A decentralized exchange protocol that uses an order book and an automated market maker (AMM) model. + +### 2) How does Uniswap determine the price of a token? + +1. The price of a token is determined by the ratio of the reserves. +2. The price of a token is determined by the ratio of the reserves and the number of trades. +3. The price of a token is determined by the ratio of the reserves and the number of Liquidity Providers. diff --git a/locales/de/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md b/locales/de/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md new file mode 100644 index 000000000..e5cc248f5 --- /dev/null +++ b/locales/de/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md @@ -0,0 +1,41 @@ +The entire UniswapSwapExamples contract will only be presented in section 5 of this tutorial. Before then, we'll build up blocks of code. + +This section explores the `ISwapRouter` interface, which defines the functions that can be called on the Uniswap Swap contract. + +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. +Multi-hop swaps allow users to exchange one token for another by routing through multiple tokens. + +Interfaces in Solidity specify functions that must be included in a contract that inherits them. They are useful for declaring what functions be supported and allow for easier integration and interaction between different contracts. + +Structs are used to define custom data types. + +## ISwapRouter Interface + +The ISwapRouter interface defines the functions that can be called on the Uniswap Swap contract. We will need to use this interface to interact with the Uniswap Swap contract and execute swaps. + +On line 5, we define a constant variable called `router` that is of type `ISwapRouter`. We set the value of this variable to the interface instance of a smart contract that is deployed at the address `0xE592427A0AEce92De3Edee1F18E0157C05861564`. This is the address of the Uniswap V3 Swap contract on the Ethereum mainnet. + +On line 9, we define an interface called `ISwapRouter`. This interface defines two functions: `exactInputSingle` and `exactInput`. + +## exactInputSingle + +On line 25, we define a struct called `ExactInputSingleParams`. This struct defines the parameters that are required for our exactInputSingle function on line 21, which will execute a single-hop swap. The struct has the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 fee`**: The fee associated with the swap. +- **`address recipient`**: The address that will receive the output token. +- **`uint deadline`**: A timestamp by which the transaction must be processed, for time-limiting the swap. +- **`uint amountIn`**: The amount of the input token being sent. +- **`uint amountOutMinimum`**: The minimum amount of the output token that the sender is willing to accept, to protect against unfavorable price movements. +- **`uint160 sqrtPriceLimitX96`**: A limit on the price, represented in a specific format, to prevent the swap from occurring at unfavorable prices. + +## exactInput + +On line 25, we define a struct called `ExactInputParams`. This struct defines the parameters that are required for our `exactInput` function on line 33. This function will execute a multi-hop swap. The struct has the following parameters: + +- **`bytes path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address recipient`**: The address receiving the output tokens. +- **`uint deadline`**: Similar to above, a timestamp by which the transaction must be processed. +- **`uint amountIn`**: The amount of the input token. +- **`uint amountOutMinimum`**: The minimum amount of the output token the sender expects to receive. diff --git a/locales/de/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md b/locales/de/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md new file mode 100644 index 000000000..f4d70c445 --- /dev/null +++ b/locales/de/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md @@ -0,0 +1,36 @@ +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. In this section, we will learn how to use the Uniswap V3 Swap contract to execute single-hop swaps. + +## Function Parameters + +On line 8, we define a function called `swapExactInputSingleHop`. This function executes a single-hop swap. It takes the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 poolFee`**: The fee associated with the swap. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +## Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 14. +Then, we approve the Uniswap Swap contract to spend the input token on our behalf, line 15. + +On line 17, we create an instance of the `ExactInputSingleParams` struct. This struct contains the parameters that are required for our `exactInputSingle` function on line 45, which will execute the single-hop swap. We repeat `ISwapRouter.ExactInputSingleParams` two times on that line because we are making an instance of a struct that is defined in an interface. + +## Parameters of the ExactInputSingleParams Struct + +We set the parameters of the struct as follows: + +- **`tokenIn`**: We set this to the `tokenIn` parameter of our function. +- **`tokenOut`**: We set this to the `tokenOut` parameter of our function. +- **`fee`**: We set this to the `poolFee` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. +- **`sqrtPriceLimitX96`**: We set this to 0 because we do not want to specify a limit on the price. + +## Executing the Single-hop Swap + +On line 29, we assign the output of the `exactInputSingle` function to the `amountOut` variable. This function executes the single-hop swap and returns the amount of the output token that was received. diff --git a/locales/de/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md b/locales/de/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md new file mode 100644 index 000000000..7883b4718 --- /dev/null +++ b/locales/de/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md @@ -0,0 +1,30 @@ +In this section, we'll delve into the `swapExactInputMultiHop` function in the `UniswapV3SwapExamples` contract. This function enables more complex token swaps by allowing users to specify a custom path through multiple liquidity pools. + +If for example, a user wants to swap token A for token D, but there is no direct liquidity pool for A and D, the user can specify a path through multiple tokens. For example, the user can swap A for B, then B for C, and finally C for D. This is of course automatically done by the Uniswap V3 Swap contract. + +### Parameters and Return Value + +On line 32, we define a function called `swapExactInputMultiHop`. This function executes a multi-hop swap. It takes the following parameters: + +- **`bytes calldata path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address tokenIn`**: The address of the token being sent. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +### Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 38. +Then, we approve the Uniswap Swap router to spend the input token on our behalf, line 41. + +On line 43, we create an instance of the `ExactInputParams` struct, line 73. This struct contains the parameters that are required for our `exactInput` function on line 81, which will execute the multi-hop swap. + +We set the parameters of the struct as follows: + +- **`path`**: We set this to the `path` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. + +On line 53, we execute the multi-hop swap by calling the `exactInput` function. This function returns the amount of the output token that was received. diff --git a/locales/de/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md b/locales/de/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md new file mode 100644 index 000000000..b3cec34e9 --- /dev/null +++ b/locales/de/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md @@ -0,0 +1,52 @@ +In this section, we'll explore the `IERC20` interface, a standard interface for interacting with ERC-20 tokens and the `IWETH` interface, a standard interface for interacting with wrapped Ether (WETH). Understanding these interfaces is crucial as it is used in the Uniswap V3 Swap contract to handle token transfers and approvals. + +You can find a "Solidity ERC20 Token Course" for beginners in LearnEth to understand the ERC20 token standard in more detail. + +## IERC20 Interface + +On line 80, we define the `IERC20` interface. This interface defines a standard set of functions that ERC-20 tokens must implement. Let's examine the key functions within this interface: + +### 1. totalSupply + +On line 81, we define the `totalSupply` function. This function returns the total supply of the token. + +### 2. balanceOf + +On line 83, we define the `balanceOf` function. This function returns the balance of the specified address. + +### 3. transfer + +On line 85, we define the `transfer` function. This function transfers tokens from the sender to the specified recipient. + +### 4. allowance + +On line 87, we define the `allowance` function. This function returns the amount of tokens that the spender is allowed to spend on behalf of the owner. + +### 5. approve + +On line 89, we define the `approve` function. When called, this function approves a spender to spend the specified amount of tokens on behalf of the sender. + +### 6. transferFrom + +On line 91, we define the `transferFrom` function. This function transfers tokens from the specified sender to the recipient. The function can only be called by the spender if the spender is allowed to spend the specified amount of tokens on behalf of the sender. + +### 7. Events + +On lines 102-103, we define the `Transfer` and `Approval` events. These events are emitted when the `transfer` and `approve` functions are called, respectively. + +## IWETH Interface + +On line 106, we define the `IWETH` interface. This interface extends the `IERC20` interface and defines two additional functions: + +### 1. deposit + +On line 107, we define the `deposit` function. This function deposits ETH into the contract and returns the equivalent amount of WETH. This function is used to wrap ETH into WETH. +We need to wrap ETH into WETH because the Uniswap V3 Swap contract only supports ERC-20 tokens. + +### 2. withdraw + +On line 109, we define the `withdraw` function. This function withdraws the specified amount of WETH from the contract and returns the equivalent amount of ETH. This function is used to unwrap WETH into ETH. + +## Conclusion + +In this tutorial, we explored the Uniswap V3 Swap contract. To get a full sense of how Uniswap works, try making some swaps on the Uniswap DApp and go to the Uniswap docs. diff --git a/locales/de/Uniswap-Tutorial/README.md b/locales/de/Uniswap-Tutorial/README.md new file mode 100644 index 000000000..cf66c5582 --- /dev/null +++ b/locales/de/Uniswap-Tutorial/README.md @@ -0,0 +1,5 @@ +# Uniswap Swap Course + +Review the code of the Uniswap V3 Swap contract for performing token swaps. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/de/Uniswap-Tutorial/config.yml b/locales/de/Uniswap-Tutorial/config.yml new file mode 100644 index 000000000..f49f02abc --- /dev/null +++ b/locales/de/Uniswap-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: uniswapSwapCourse +name: Uniswap Swap Course +summary: Go through the Solidity code of the Uniswap V3 Swap contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - Uniswap +steps: + - + name: 1. Introduction + path: 1-introduction-to-uniswap + - + name: 2. Routers, Interfaces, and Structs + path: 2-router-interfaces-and-structs + - + name: 3. Single Hop Swaps + path: 3-single-hop-swaps + - + name: 4. Multi-Hop Swaps + path: 4-multi-hop-swaps + - + name: 5. Erc20 and Weth Interfaces + path: 5-erc20-weth-interfaces diff --git a/locales/de/Web3Client/1_Using_Web3/Running_a_script.md b/locales/de/Web3Client/1_Using_Web3/Running_a_script.md new file mode 100644 index 000000000..3b7b23332 --- /dev/null +++ b/locales/de/Web3Client/1_Using_Web3/Running_a_script.md @@ -0,0 +1,24 @@ +## Querying the Blockchain + +In this tutorial, we'll run a script that queries the blockchain using a JavaScript library. + +This means that instead of using the Remix GUI or a block explorer like Etherscan, we'll use a script in the editor and will run it from the terminal. + +The JS libraries that are used the most for interacting with the blockchain are web3.js & ethers.js. + +Let's begin with a simple web3.js example, queryBlockNum.js. + +The script's call to web3.js is wrapped in a self-executing async function that contains a try/catch block. + +We'll query the current blocknumber with: +`let blockNumber = await web3.eth.getBlockNumber()` + +Note that the object `web3` is injected by Remix. For more info on web3.js, check their docs, https://web3js.readthedocs.io. + +To use web3.js or ethers.js, you need to select the **Injected Web3** or **Web3 Provider** environment in the **Deploy & Run** module. Scripts don't currently work with the JSVM. **If you try, you'll get an error.** + +So for this example choose **Injected Web3** in the Deploy & Run module and have Metamask installed. + +From the terminal, execute `remix.execute()`. This command will execute the current JavaScript file with the line `let blockNumber = await web3.eth.getBlockNumber()`. + +In the console, you should see the current block number of the chain that metamask is connected to. diff --git a/locales/de/Web3Client/2_Querying_a_Contract/queryContract.md b/locales/de/Web3Client/2_Querying_a_Contract/queryContract.md new file mode 100644 index 000000000..461c98244 --- /dev/null +++ b/locales/de/Web3Client/2_Querying_a_Contract/queryContract.md @@ -0,0 +1,23 @@ +Now that we know how to query simple data, let's try a more complex query. + +This is a contract deployed to the mainnet - at this address: https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code + +We are going to query the contract to find the name of it's token. + +The **name** variable is a state variable of the contract. + +To access this **mainnet** contract, we need to do some setup. + +1. Switch to the mainnet in metamask. +2. You'll probably need to refresh Remix. +3. As a result of the refresh, you may need to reload this tutorial too. +4. Go to Deploy & Run and switch to **Injected Web3**. + +**Using Web3** +In the script, queryContract.js, we need to instantiate a new instance of web3.eth.Contract object. For this we need to grab the contract's ABI and its address. The source code & ABI is available in etherscan because the contract's developer intentionally published it. + +In etherscan, we can see that its name is **TetherToken**. Scrolling down to the TetherToken contract in the source code section of etherscan, we can see the state variables for the contract - the first of which is named **name**. + +There are a few syntactic hoops to jump through to return the value of the state variable. + +- To call the autogenerated getter function of the public state variable, you need to both treat the variable as a function (by adding parentheses) and also to tack on a call(). diff --git a/locales/de/Web3Client/README.md b/locales/de/Web3Client/README.md new file mode 100644 index 000000000..a319f312f --- /dev/null +++ b/locales/de/Web3Client/README.md @@ -0,0 +1 @@ +This workshop is about using the web3.js to interact with a contract and more generally to the blockchain. diff --git a/locales/de/Web3Client/config.yml b/locales/de/Web3Client/config.yml new file mode 100644 index 000000000..07cb1760c --- /dev/null +++ b/locales/de/Web3Client/config.yml @@ -0,0 +1,9 @@ +--- +id: useofweb3js +name: Basic use of web3.js +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 2 +tags: + - JS + - Remix + - Web3 diff --git a/locales/es/Basics/README.md b/locales/es/Basics/README.md new file mode 100644 index 000000000..616a61abb --- /dev/null +++ b/locales/es/Basics/README.md @@ -0,0 +1,3 @@ +## Cargar, Compilar, Desplegar + +Este tutorial de nivel principiante presenta la interfaz y los conceptos de Remix utilizados en Ethereum. diff --git a/locales/es/Basics/config.yml b/locales/es/Basics/config.yml new file mode 100644 index 000000000..8c160b545 --- /dev/null +++ b/locales/es/Basics/config.yml @@ -0,0 +1,26 @@ +--- +id: basics +name: Basics of Remix +summary: A typical workflow in Remix +level: 1 +tags: + - Remix +steps: + - + name: Intro to the Interface + path: interface_introduction + - + name: Intro to Workspaces + path: workspaces + - + name: Loading & Compiling + path: load_and_compile + - + name: Deploying to the Remix VM + path: deploy_to_the_remixvm + - + name: Interacting with Functions + path: interacting + - + name: Deploying to Public Networks + path: deploy_injected diff --git a/locales/es/Basics/deploy_injected/README.md b/locales/es/Basics/deploy_injected/README.md new file mode 100644 index 000000000..25d1a30a4 --- /dev/null +++ b/locales/es/Basics/deploy_injected/README.md @@ -0,0 +1,21 @@ +1. Si no tienes una cartera de navegador como **MetaMask**, descarga e instala una ahora. + +2. Haz clic en el icono de MetaMask en tu navegador. Inicie sesión y elija la red de prueba de Ephemery. Es posible que tengas que actualizar la configuración de tu cartera para poder ver **probar las redes**. Alternativamente, puedes ir al módulo de transacciones Deploy & Run de Remix y en la sección ENTORNO, seleccionar Ephemery. + +3. Obtener ETH de prueba para las redes de prueba públicas a menudo es molesto. Ephemery es una red pública que se actualiza mensualmente, por lo que obtener la prueba de ETH debería ser indolora. Aquí hay un enlace a alguno Ephemery faucets. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/testnet.png) + +Sepolia es otra red de pruebas popular que no se actualiza, por lo que los despliegues persistirán, pero los grifos de Sepolia son más difíciles de usar. + +En la cartera de tu navegador, asegúrate de NO haber seleccionado la red principal ni ninguna red que cueste ETH real. En el módulo Desplegar y Correr, debajo del cuadro de selección de entorno, verá una insignia con el ID de la red y, para las cadenas populares, su nombre. En el caso de abajo, su Sepolia. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/sepolia.png) + +5. Asegúrese de ver el 2_Owner.sol como una opción en el cuadro de selección **CONTRATO**, luego haz clic en el botón **Desplegar**. + +Si el cuadro de selección **CONTRATO** está vacío, tendrás que compilar 2_Owner de nuevo haciendo de 2_Owner.sol el archivo activo en el **editor** y luego ir al **Compilador de solidez** para compilarlo. + +6. Después de pulsar el botón "Desplegar", verá la ventana emergente de la cartera del navegador que le pide que pague por las transacciones. Si tienes el tipo de ETH adecuado para esta cadena, aprueba esta transacción. Revisa la impresión en la terminal. Una vez que el bloque es validado, la **instancia desplegada** aparecerá en la parte inferior de Deploy & Run + +Y con eso has terminado este tutorial. Ahora tienes experiencia con la apertura, compilación, implementación e interacción con Contratos Inteligentes en Remix IDE. diff --git a/locales/es/Basics/deploy_to_the_remixvm/README.md b/locales/es/Basics/deploy_to_the_remixvm/README.md new file mode 100644 index 000000000..f32f5dcc7 --- /dev/null +++ b/locales/es/Basics/deploy_to_the_remixvm/README.md @@ -0,0 +1,15 @@ +En el capítulo anterior, compilamos un contrato, que es decir, el código de Solidity se ha transformado en pequeños trozos de código de bytes de Ethereum Virtual Machine (EVM). + +Ahora pondremos ese código en una cadena de bloques de prueba. + +1. Haz clic en el icono Desplegar y Correr![deploy & run icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_to_the_remixvm/images/run.png "icono desplegar y correr"). + +2. Seleccione uno de los **Remix VM** en el menú desplegable **Entorno**. + +3. Haga clic en el botón Desplegar (o el botón de transacción en la vista expandida). + +4. Has desplegado tu contrato compilado en la máquina virtual Remix - una cadena de bloque simulada que se está ejecutando dentro de la ventana de su navegador. La MV Remix es una cadena de pruebas simple y rápida. No es tan realista porque usted no necesita aprobar cada transacción. + +5. Comprueba la terminal para ver los detalles de esta transacción de implementación. + +También puede usar Remix para desplegar en otras cadenas de EVM públicas. Para hacer esto, necesitarás conectarte a un **entorno** diferente - como Inyected Provider. El Injected Provider conecta Remix a la cartera del navegador (como MetaMask o similar). Intentaremos desplegar a una red pública al final de este tutorial. Pero antes de que lleguemos, cubriremos cómo interactuar con las funciones de un contrato desplegado. diff --git a/locales/es/Basics/interacting/README.md b/locales/es/Basics/interacting/README.md new file mode 100644 index 000000000..325b2d6d9 --- /dev/null +++ b/locales/es/Basics/interacting/README.md @@ -0,0 +1,19 @@ +## Acceder a las funciones en un contrato desplegado + +1. Cuando un contrato se ha desplegado con éxito, aparecerá en la parte inferior del plugin Desplegar y Ejecutar. Abre el contrato haciendo clic en el cursor - para que el cursor apunte hacia abajo. + ![desplegar contrato](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/instance.png "contrato desplegado") + +2. Hay dos funciones en este contrato. Para introducir los parámetros individualmente, haciendo clic en el cursor a la derecha del changeOwner (descrito en rojo abajo). En la vista ampliada, cada parámetro tiene su propia casilla de entrada. + +![Desplegar contrato](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/deployed_open2.png "contrato desplegado") + +Si este contrato hubiera importado otros contratos, las funciones de los contratos importados también serían visibles aquí. En algún momento, trate de jugar con un contrato ERC20 para ver todas sus funciones. + +3. Las funciones con botones azul son funciones **puras** o **vistas**. Esto significa que simplemente están leyendo una propiedad o que están devolviendo un valor. En otras palabras, no están ahorrando nada - así que son GRATIS (no cuestan gas). Funciones con otros colores - generalmente naranja (dependiendo del tema de Remix) cuestan gas porque están ahorrando información. Están creando una **transacción**. + +4. 2_Owner.sol no tiene una función **de pago**. Si así fuera, el color del botón sería rojo. Las funciones Playable permiten enviar Ether a la función. Enviar ETH con una función de playable, pones la cantidad que quieres enviar en el campo **valor** hacia la parte superior del módulo Deploy & Run. + +5. En la MV Remix no necesita aprobar una transacción. Cuando se utiliza un entorno de prueba más realista o cuando se utiliza la red principal - será necesario aprobar las transacciones para que se realicen. Aprobar una transacción cuesta gas. + +6. La elección de una red pública no se hace en Remix sino en tu cartera de navegador. Hay un icono de enchufe a la derecha del título de Entorno que enlaza a chainlist.org donde se pueden obtener las especificaciones de la cadena con la que se quiere interactuar. + ![chainlist](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/chainlist.png "lista de cadenas") diff --git a/locales/es/Basics/interface_introduction/README.md b/locales/es/Basics/interface_introduction/README.md new file mode 100644 index 000000000..3d8a48353 --- /dev/null +++ b/locales/es/Basics/interface_introduction/README.md @@ -0,0 +1,15 @@ +## Remix está compuesto por cuatro paneles. + +![Remix layout](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/a-layout1c.png "Diseño de Remix") + +- La mayoría de los complementos aparecen en el **Panel Lateral**. +- La edición de código ocurre en pestañas del **Panel Principal**. +- Los resultados de las transacciones y otras acciones son visibles en la **Terminal**. +- Cambiar entre complementos ocurre en el **Panel de iconos**. +- Para hacer un panel más grande, arrastra su borde. + +Intenta hacer clic en el icono de **Compilador de Solidity** ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/solidity-icon.png) en el **Panel de Iconos**. Luego haz clic en el icono **Desplegar y Ejecutar** ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/deploy-run.png). Luego vuelve a **LearnEth** haciendo clic en este icono![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/learneth.png). + +En el **Panel Principal** de Remix, asegúrate de ver la pestaña **Inicio**. La pestaña **Inicio** tiene un montón de enlaces útiles. Para navegar allí, haga clic en la pestaña **Inicio** en el **Panel principal** o haga clic en el icono de Remix ![Remix icon](https://raw.githubusercontent. om/ethereum/remix-workshops/master/Basics/interface_introduction/images/remix-logo.png "Remix icon") en la parte superior del panel del icono. + +- Ver todos los complementos en el **Gestor de Complementos**. Haz clic en este icono ![plugin manage](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/plugin1.png "Plugin Manager icon") en la esquina inferior izquierda Remix. diff --git a/locales/es/Basics/load_and_compile/README.md b/locales/es/Basics/load_and_compile/README.md new file mode 100644 index 000000000..d48867fbe --- /dev/null +++ b/locales/es/Basics/load_and_compile/README.md @@ -0,0 +1,20 @@ +Vamos a cargar un archivo del Explorador de archivos en el editor. + +1. En el panel de iconos, haz clic en ![file explorer icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/files1.png "file explorer icon") , el icono del Explorador de archivos. + +2. Asegúrate de estar en el **espacio de trabajo por defecto**. + +![default workspace](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/default_workspace_open.png) + +3. Abre la carpeta de contratos y haga clic en **2_Owner.sol** en la carpeta contratos. Haz clic en él. El archivo aparecerá en una pestaña del panel principal. + +4. En el panel de iconos, haz clic en el **Compilador de Solidity** ![solidity compiler icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/solidity1.png "solidity compiler icon""). Ahora el compilador de Solidity debería estar en el panel lateral. + +5. Haga clic en el botón de compilación. + ![compile 2\_owner](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/compile2owner.png "compile 2_Owner") + +6. También se puede activar la compilación pulsando **CTRL + S**. + +El hilandero girará mientras el archivo se está compilando. + +**Nota:** El hilandero también gira cuando el compilador mismo se está cargando. Para elegir una **versión diferente de Solidity**, ve a la casilla de selección en la parte superior del complemento. diff --git a/locales/es/Basics/workspaces/README.md b/locales/es/Basics/workspaces/README.md new file mode 100644 index 000000000..aa89609f3 --- /dev/null +++ b/locales/es/Basics/workspaces/README.md @@ -0,0 +1,23 @@ +## Los espacios de trabajo ayudan a organizar sus proyectos independientes. + +Si esta es su primera vez en Remix, se carga un espacio de trabajo llamado **espacio_de_trabajo_por_defecto** en el Explorador de archivos. + +![default workspace](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/default_workspace.png) + +El **espacio_de_trabajo_por_defecto** tiene tres archivos Solidity (.sol) en la carpeta contractuales. Remix has a number of other templates. Cuando se carga una plantilla, entra en un espacio de trabajo. Para ir entre espacios de trabajo, usa el cuadro de selección en la parte superior del Explorador de archivos. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/select-box.png) + +Pero los espacios de trabajo no son sólo para plantillas. Al clonar un repositorio en Remix, los archivos serán colocados en un espacio de trabajo. + +Vamos a crear un nuevo área de trabajo + +1. En la parte superior del Explorador de archivos, haz clic en el icono de hamburguesa (las 3 líneas horizontales). Lee atentamente los comandos y las herramientas de este menú. + +2. Selecciona **+ Crear** (la primera elección). + +3. En la modal que aparece, elige una de las plantillas. + +![hamburger](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/workspaces/images/popup.png) + +Ten en cuenta que en este menú emergente, puedes clonar un repositorio. La gestión de un repositorio de Git ocurre en el complemento de DGit. You can also create Github actions with the three workflow choices in the popup menu. diff --git a/locales/es/CircomHashChecker/README.md b/locales/es/CircomHashChecker/README.md new file mode 100644 index 000000000..20391a668 --- /dev/null +++ b/locales/es/CircomHashChecker/README.md @@ -0,0 +1,14 @@ +Hash Checker Tutorial + +This tutorial guides you through creating and understanding a Hash Checker circuit using Remix-IDE. You'll learn how to generate the circuit using a template, explore the code, perform a trusted setup, generate proofs, and verify them. This tutorial is suitable for beginners familiar with Circom and Zero-Knowledge Proofs. + +Prerequisites + +``` +Basic understanding of Zero-Knowledge Proofs and Circom. +Familiarity with Remix-IDE. +``` + +Estimated Time + +Approximately 1-2 hours. diff --git a/locales/es/CircomHashChecker/config.yml b/locales/es/CircomHashChecker/config.yml new file mode 100644 index 000000000..2c2aae80a --- /dev/null +++ b/locales/es/CircomHashChecker/config.yml @@ -0,0 +1,35 @@ +id: circom-hash-checker +name: Hash Checker Tutorial +summary: A tutorial on creating and understanding a Hash Checker circuit using Remix-IDE templates, including trusted setup and proof generation. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction to the Hash Checker Circuit + path: step-1 + - + name: Generating the Hash Checker Template in Remix-IDE + path: step-2 + - + name: Exploring calculate_hash.circom + path: step-3 + - + name: Compiling the Circuit + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Compute Witness + path: step-6 + - + name: Generate Proof + path: step-7 + - + name: Exploring the Trusted Setup Script (Optional) + path: step-8 + - + name: Exploring the Proof Generation Script (Optional) + path: step-9 diff --git a/locales/es/CircomHashChecker/step-1/README.md b/locales/es/CircomHashChecker/step-1/README.md new file mode 100644 index 000000000..be922e93b --- /dev/null +++ b/locales/es/CircomHashChecker/step-1/README.md @@ -0,0 +1,8 @@ +In this tutorial, we'll explore the **Hash Checker** circuit, a zero-knowledge proof (ZKP) application using Circom and Remix-IDE. The Hash Checker circuit allows you to prove knowledge of certain inputs that hash to a given value without revealing the inputs themselves. + +### What You'll Learn + +- How to generate a Hash Checker circuit using Remix-IDE's workspace templates. +- Understanding the Circom code for hashing and checking hashes. +- Performing a trusted setup using Groth16. +- Generating zero-knowledge proofs. diff --git a/locales/es/CircomHashChecker/step-2/README.md b/locales/es/CircomHashChecker/step-2/README.md new file mode 100644 index 000000000..bc827019e --- /dev/null +++ b/locales/es/CircomHashChecker/step-2/README.md @@ -0,0 +1,37 @@ +Follow these steps to create the Hash Checker workspace in Remix-IDE. + +### Step 1: Access the Workspace Templates + +1. In the **File Explorer** sidebar, click on the **hamburger menu icon** (three horizontal lines). + + hamburger-menu + +2. Select **"Create Using Template"** from the dropdown. + + create-using-template + +### Step 2: Find the Hash Checker Template + +1. In the main panel, scroll down to the **"Circom ZKP"** section. + + create-zkp-section + +2. Locate the **"Hash Checker"** item. + +### Step 3: Create the Workspace + +1. Click on the **"Create"** button on the Hash Checker item. + + create-hash-checker + +2. In the modal pop-up, provide a **workspace name** (e.g., `hash-checker-workspace`). + + workspace-name-modal + +3. Click **"OK"** to create the template. + +### Result + +- The workspace is created with the necessary files and directories. + + workspace-name-modal diff --git a/locales/es/CircomHashChecker/step-3/README.md b/locales/es/CircomHashChecker/step-3/README.md new file mode 100644 index 000000000..b3ac14050 --- /dev/null +++ b/locales/es/CircomHashChecker/step-3/README.md @@ -0,0 +1,32 @@ +## Exploring `calculate_hash.circom` + +Navigate to the `circuits` directory and open `calculate_hash.circom`. This file contains the Circom code for the Hash Checker circuit. + +### Code Breakdown + +#### Pragma and Includes: + +- `pragma circom 2.0.0;` specifies the Circom version. +- `include "circomlib/circuits/poseidon.circom";` fetch and includes the Poseidon hash function from [CircomLib](https://github.com/iden3/circomlib). + +#### `CalculateHash` Template: + +- Defines inputs `value1`, `value2`, `value3`, `value4`. +- Uses the `Poseidon` hash function to compute a hash of these values.\ +- Outputs `out`, which is the hash. + +#### `HashChecker` Template: + +- Inputs are the same values plus a `hash`. +- Instantiates `CalculateHash` as `calculateSecret`. +- Computes `calculatedHash`. +- Uses `assert(hash == calculatedHash);` to ensure the provided hash matches the calculated hash. + +#### Main Component: + +- `component main {public [hash]} = HashChecker();` +- Specifies that `hash` is a `public` input, while the values are `private`. + +### Purpose + +The circuit allows someone to prove they know `value1`, `value2`, `value3`, and `value4` that hash to a specific `hash` without revealing the values themselves. diff --git a/locales/es/CircomHashChecker/step-4/README.md b/locales/es/CircomHashChecker/step-4/README.md new file mode 100644 index 000000000..537c6a241 --- /dev/null +++ b/locales/es/CircomHashChecker/step-4/README.md @@ -0,0 +1,32 @@ +## Compiling the Circuit + +### Selecting the Compiler Version + +1. Go to the **Circuit Compiler** plugin in the sidebar. +2. Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +### Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +### Compiling the Circuit + +1. Click on the **Compile** button. +2. Wait for the compilation to complete. A success badge will appear if compilation is successful. + +compilation-success + +### Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/es/CircomHashChecker/step-5/README.md b/locales/es/CircomHashChecker/step-5/README.md new file mode 100644 index 000000000..c3ea8509b --- /dev/null +++ b/locales/es/CircomHashChecker/step-5/README.md @@ -0,0 +1,25 @@ +## Performing a Trusted Setup + +1. **Access the Setup and Exports Section**: + +- After successful compilation, the **Setup and Exports** section becomes available in the plugin. + +2. **Select Proving Scheme**: + +- Choose **Groth16** from the **Proving Scheme** dropdown. + +3. **Select Power of Tau File**: + +- Choose the appropriate **Power of Tau** file from the dropdown. If unsure, use the default option. + +4. **Export Verification Key and Contract** (optional): + +- Enable **Export Verification Key** to save the verification key to the File Explorer. +- Enable **Export Verifier Contract** to save the Solidity contract for on-chain verification. + +trusted-setup + +5. **Run the Trusted Setup**: + +- Click on the **Run Setup** button. +- Wait for the process to complete. This may take some time depending on the circuit complexity. diff --git a/locales/es/CircomHashChecker/step-6/README.md b/locales/es/CircomHashChecker/step-6/README.md new file mode 100644 index 000000000..03b848f81 --- /dev/null +++ b/locales/es/CircomHashChecker/step-6/README.md @@ -0,0 +1,28 @@ +## Compute Witness + +1. **Access the Compute Witness Section**: + - After the trusted setup, the **Compute Witness** section becomes available. + +2. **Input Values**: + - You'll see input fields for `value1`, `value2`, `value3`, `value4`, and `hash`. + - Enter values for each input. For example: + - `value1`: `1234` + - `value2`: `2` + - `value3`: `3` + - `value4`: `4` + +3. **Calculate the Hash**: + + - Compute the Poseidon hash of the four values using an external tool or library compatible with the Poseidon hash function. + - For the values above, here is the computed Poseidon hash `16382790289988537028417564277589554649233048801038362947503054340165041751802`. + - Enter the calculated `hash` value in the `hash` input field. + + compute-witness + +4. **Compute the Witness**: + + - Click on the **Compute Witness** button. + - Wait for the process to complete. A success badge will appear if the witness is computed successfully. + - If successful, you'll see `calculate_hash.wtn` created in the `.bin` directory in the file explorer. + + witness-computed diff --git a/locales/es/CircomHashChecker/step-7/README.md b/locales/es/CircomHashChecker/step-7/README.md new file mode 100644 index 000000000..e6ae80fea --- /dev/null +++ b/locales/es/CircomHashChecker/step-7/README.md @@ -0,0 +1,21 @@ +## Generate Proof + +1. **Access the Generate Proof Section**: + - After computing the witness, expand the **Generate Proof** section. + +2. **Configure Proof Generation**: + - **Export Verifier Calldata**: Enable this option if you plan to verify the proof on-chain. + +3. **Generate the Proof**: + + - Click on the **Generate Proof** button. + - Wait for the proof generation to complete. + + generate-proof + +4. **View the Proof**: + + - The proof data will be displayed in the File Explorer. + - **Congratulations!** You've successfully compiled the `Hash Checker` circuit, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + + generate-proof diff --git a/locales/es/CircomHashChecker/step-8/README.md b/locales/es/CircomHashChecker/step-8/README.md new file mode 100644 index 000000000..e489a8cab --- /dev/null +++ b/locales/es/CircomHashChecker/step-8/README.md @@ -0,0 +1,34 @@ +## Understanding `groth16_trusted_setup.ts` + +Navigate to `scripts/groth16/groth16_trusted_setup.ts`. This script performs the trusted setup necessary for generating proofs. + +### Code Breakdown + +#### Circuit Compilation: + +- Uses `remix.call('circuit-compiler', 'generateR1cs', ...)` to generate `R1CS` (Rank-1 Constraint System) from the circuit. + +#### Trusted Setup Steps: + +- `snarkjs.zKey.newZKey`: Initializes the proving key (`zkey_0`). +- `snarkjs.zKey.contribute`: Adds contributions to the proving key (`zkey_1`). +- `snarkjs.zKey.beacon`: Finalizes the proving key (`zkey_final`). + +#### Verification: + +- `snarkjs.zKey.verifyFromR1cs`: Verifies the proving key against the `R1CS` and initial parameters. + +#### Exporting Keys: + +- Exports the verification key to `scripts/groth16/zk/keys/verification_key.json`. +- Exports the final proving key (`scripts/groth16/zk/keys/zkey_final.txt`). + +### Purpose + +- Performs the trusted setup required for the `Groth16` proving system. +- Generates the necessary keys for proof generation and verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"setup done."` logged in the terminal. diff --git a/locales/es/CircomHashChecker/step-9/README.md b/locales/es/CircomHashChecker/step-9/README.md new file mode 100644 index 000000000..653d5ced1 --- /dev/null +++ b/locales/es/CircomHashChecker/step-9/README.md @@ -0,0 +1,37 @@ +## Understanding `groth16_zkproof.ts` + +Navigate to `scripts/groth16/groth16_zkproof.ts`. This script generates the zero-knowledge proof and prepares it for verification. + +### Code Overview + +#### Loading Files: + +- Reads the R1CS and WASM files generated from the circuit. +- Loads the final proving key (`zkey_final`) and verification key (`vKey`). + +#### Defining Inputs: + +- Sets the private values (`value1`, `value2`, `value3`, `value4`). +- Computes the `hash` using Poseidon from [CircomLib](https://github.com/iden3/circomlib). + +#### Witness Calculation and Proof Generation: + +- Calculates the witness (`wtns`). +- Checks the witness against the `R1CS`. +- Generates the proof using `Groth16`. +- Verifies the proof. + +#### Exporting Verifier Contract and Inputs: + +- Generates a Solidity verifier contract. +- Exports the proof inputs to `input.json`. + +### Purpose + +- Generates a zero-knowledge proof that the prover knows values hashing to a specific hash. +- Prepares the verifier contract and inputs for on-chain verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"zk proof validity"` logged in the terminal. diff --git a/locales/es/CircomIntro/README.md b/locales/es/CircomIntro/README.md new file mode 100644 index 000000000..c58b2daec --- /dev/null +++ b/locales/es/CircomIntro/README.md @@ -0,0 +1,21 @@ +Intro to Circom + +This is an introduction to Circom. You'll learn how to write, compile, and test arithmetic circuits in Circom. We'll go over how to do this within Remix-IDE. + +Tutorial Overview + +``` +Step 1: Introduction +Step 2: Setting Up Remix-IDE and Installing the Circuit-Compiler Plugin +Step 3: Writing Your First Circom Circuit +Step 4: Compiling the Circuit Using the Plugin +Step 5: Performing a Trusted Setup +Step 6: Computing the Witness +Step 7: Generating the Proof +``` + +Prerequisites: + +``` +Basic understanding of cryptography and zero-knowledge proofs is helpful but not required. +``` diff --git a/locales/es/CircomIntro/config.yml b/locales/es/CircomIntro/config.yml new file mode 100644 index 000000000..d6dfdca46 --- /dev/null +++ b/locales/es/CircomIntro/config.yml @@ -0,0 +1,29 @@ +id: circom-intro +name: Intro to Circom +summary: A intro to using Circom for creating arithmetic circuits. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction + path: step-1 + - + name: Installing the Circuit-Compiler + path: step-2 + - + name: Writing Your First Circom Circuit + path: step-3 + - + name: Compiling the Circuit Using the Plugin + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Computing the Witness + path: step-6 + - + name: Generating the Proof + path: step-7 diff --git a/locales/es/CircomIntro/step-1/README.md b/locales/es/CircomIntro/step-1/README.md new file mode 100644 index 000000000..0766ce6f4 --- /dev/null +++ b/locales/es/CircomIntro/step-1/README.md @@ -0,0 +1,13 @@ +Welcome to this beginner-level tutorial on Circom using Remix. In this tutorial, you'll learn the basics of Circom, a domain-specific language used for creating arithmetic circuits. + +**What is Circom?** + +Circom is a language designed for writing arithmetic circuits that can be used in zero-knowledge proofs, particularly zk-SNARKs. It allows developers to define complex mathematical circuits that can prove knowledge of certain data without revealing it. + +**Why Use Remix-IDE for Circom?** + +- **Ease of Use:** Remix-IDE provides a user-friendly interface that simplifies the development process. +- **Integrated Tools:** With plugins like `circuit-compiler`, you can compile Circom code, perform trusted setups, compute witnesses, and generate proofs all within the same environment. +- **No Installation Required:** As a web-based IDE, you can start coding immediately without setting up a local development environment. + +In the next steps, we'll guide you through setting up Remix-IDE for Circom development and help you write your first circuit. diff --git a/locales/es/CircomIntro/step-2/README.md b/locales/es/CircomIntro/step-2/README.md new file mode 100644 index 000000000..4b228c298 --- /dev/null +++ b/locales/es/CircomIntro/step-2/README.md @@ -0,0 +1,25 @@ +In this step, we'll set up Remix for Circom development by activating the `Circom ZKP compiler` plugin. + +## Activating the Circom ZKP compiler + +1. At the bottom of the icon panel on the left of the screen, click on the **Plugin Manager** (the plug icon). + 2.In the search bar, type **Circom**. +2. Find the **Circuit Compiler** plugin in the list and click on the **Activate** button. +3. The plugin will now appear in your sidebar. + +install-plugin + +## The Circom Compiler Interface + +- **Compiler Version Dropdown:** Select the Circom compiler version you wish to use. +- **Auto Compile Checkbox:** Enable this to automatically compile your circuit whenever you make changes. +- **Hide Warnings Checkbox:** Enable this to suppress compiler warnings. +- **Advanced Configuration:** Click to expand options for selecting the prime field (e.g., BN128, BLS12381). + +compiler-interface + +With the plugin installed, you're now ready to start writing Circom code in Remix-IDE. + +**Note:** Make sure your internet connection is stable, as Remix-IDE is a web-based tool. + +In the next step, we'll write our first Circom circuit. diff --git a/locales/es/CircomIntro/step-3/README.md b/locales/es/CircomIntro/step-3/README.md new file mode 100644 index 000000000..6424668f6 --- /dev/null +++ b/locales/es/CircomIntro/step-3/README.md @@ -0,0 +1,38 @@ +Let's write a simple Circom circuit. + +## Creating a New Circuit File + +1. In the **File Explorer** on the left sidebar, click on the **Create New File** icon. +2. Name your file `multiplier.circom` and press **Enter**. + +create-new-file + +## Writing the Circuit + +Open `multiplier.circom` and add the following code: + +```circom +pragma circom 2.0.0; + +template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; +} + +component main = Multiplier(); +``` + +## Explanation: + +- template `Multiplier()`: Defines a new circuit template called Multiplier. +- `signal input a;` and `signal input b;`: Declare input signals a and b. +- `signal output c;`: Declare an output signal c. +- `c <== a * b;`: Constrain c to be the product of a and b. +- `component main = Multiplier();`: Instantiates the Multiplier circuit as main, which is required for the compiler. + +### NB: + +Signals are values in a cryptographic circuit that are strictly determined by the circuit's equations and constraints. Think of a signal as a value that must follow specific mathematical rules defined by the circuit—once set, it can't be changed arbitrarily. In regular programming, variables are flexible and can be updated or reassigned as needed, whereas, signals can't be altered freely. diff --git a/locales/es/CircomIntro/step-4/README.md b/locales/es/CircomIntro/step-4/README.md new file mode 100644 index 000000000..ad3f2a089 --- /dev/null +++ b/locales/es/CircomIntro/step-4/README.md @@ -0,0 +1,34 @@ +With your `multiplier.circom` circuit ready, let's compile it using the Circuit Compiler plugin. + +## Selecting the Compiler Version + +Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +## Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +## Compiling the Circuit + +1. Click on the **Compile** button. +2. The compiler will process your circuit. +3. If successful, you'll see a compilation success message. + +compilation-success + +**Note:** If there are any errors, they will be displayed in the console. Check your code for typos or syntax errors. + +## Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/es/CircomIntro/step-5/README.md b/locales/es/CircomIntro/step-5/README.md new file mode 100644 index 000000000..8e8496bbd --- /dev/null +++ b/locales/es/CircomIntro/step-5/README.md @@ -0,0 +1,26 @@ +After compiling your circuit, you need to perform a trusted setup to generate proving and verification keys. + +## Understanding Trusted Setup + +- **Trusted Setup:** A process required for zk-SNARKs to generate the necessary parameters for proof generation and verification. +- You can choose between different protocols like **Groth16** and **Plonk**. + +## Performing the Trusted Setup + +1. In the **Setup and Exports** section, select the **Proving Scheme**: + - Choose between **Groth16** or **Plonk**. We'll use **Groth16** for this tutorial. + +2. Choose the appropriate **Power of Tau** file from the dropdown. This file is necessary for the trusted setup. + - If unsure, select the default option. + +3. Click on the **Setup** button to start the trusted setup process. + +4. You can enable **Export Verification Key** to get the verification parameters. + +5. You can enable **Export Verification Contract** if you intend to verify proofs on-chain. + +trusted-setup + +**Note:** The trusted setup may take some time, depending on the complexity of your circuit. + +In the next step, we'll compute the witness for our circuit. diff --git a/locales/es/CircomIntro/step-6/README.md b/locales/es/CircomIntro/step-6/README.md new file mode 100644 index 000000000..e13d33d32 --- /dev/null +++ b/locales/es/CircomIntro/step-6/README.md @@ -0,0 +1,27 @@ +With the trusted setup complete, you can now compute the witness for your circuit based on specific inputs. + +## What is a Witness? + +- A **Witness** is a set of values that satisfy all the constraints of your circuit. It includes all the intermediate numbers and results that satisfy the circuit's rules. The witness is used in zero-knowledge proofs to demonstrate that you know a valid solution to the problem without actually showing the solution itself. This allows others to verify that you did everything correctly while keeping your specific numbers and calculations private. +- It is essential for generating a proof. + +## Inputting Values + +1. In the **Compute Witness** section, you'll see input fields dynamically generated based on your circuit's inputs. +2. Enter values for `a` and `b`. For example: + - `a = 3` + - `b = 4` + +compute-witness + +## Computing the Witness + +1. After entering the inputs, click on the **Compute Witness** button. +2. The plugin will compute the witness based on your inputs. +3. If successful, you'll see `multiplier.wtn` created in the `.bin` directory in the file explorer. + +witness-computed + +**Note:** If there are any errors, ensure that your inputs are valid and satisfy the circuit's constraints. + +In the next step, we'll generate a proof using the computed witness. diff --git a/locales/es/CircomIntro/step-7/README.md b/locales/es/CircomIntro/step-7/README.md new file mode 100644 index 000000000..f5cf332a9 --- /dev/null +++ b/locales/es/CircomIntro/step-7/README.md @@ -0,0 +1,31 @@ +With the witness computed, the final step is to generate a proof that can be verified by others. + +## Generating the Proof + +1. In the **Generate Proof** section, you have the option to **Export Verifier Calldata**. + - Enable the **Export Verifier Calldata** checkbox if you plan to verify the proof on-chain. +2. Click on the **Generate Proof** button. + +generate-proof + +## Understanding the Output + +- After generating the proof, the plugin will display the proof data. +- If you enabled **Export Verifier Calldata**, it will also provide the calldata needed for on-chain verification. + +proof-generated + +## Next Steps + +- **Verification:** You can use the verification key or contract exported earlier to verify the proof. +- **On-Chain Verification:** If you're familiar with smart contracts, you can deploy the verification contract and use the calldata to perform on-chain verification. + +**Congratulations!** You've successfully written a Circom circuit, compiled it, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + +## Additional Resources + +- [Circom Documentation](https://docs.circom.io/) +- [Remix-IDE Documentation](https://remix-ide.readthedocs.io/) +- [Zero-Knowledge Proofs Explained](https://zkproof.org/) + +Feel free to experiment with more complex circuits and explore the capabilities of Circom and Remix-IDE further. diff --git a/locales/es/DeployWithLibraries/1_Writing_a_Library/step1.md b/locales/es/DeployWithLibraries/1_Writing_a_Library/step1.md new file mode 100644 index 000000000..4ecd9a6e9 --- /dev/null +++ b/locales/es/DeployWithLibraries/1_Writing_a_Library/step1.md @@ -0,0 +1,17 @@ +Las librerías parecen un **contrato** pero utiliza la palabra clave `library` + +Una librería típicamente es una colección de funciones útiles que se encuentran ahí fuera en la cadena de bloques que cualquier contrato puede usar. Debido a que la librería ya está instalada, ahorra los costos de despliegue de los muchos contratos que la utilizan. + +En el siguiente contrato: + +- Crea una librería con el nombre `LibraryForTest`. + +Es posible colocar una biblioteca en el mismo archivo con otro contrato. Así que pon la librería debajo del contrato. + +Esta librería debería tener un método llamado método `getFromLib` que devuelva `3`. + +- Actualiza el método `get` en el contrato de prueba para utilizar la librería `LibraryForTest`. La función `get` devolverá el valor que recibe de `getFromLib`. + +--------- + +Puedes encontrar más información sobre las librerías en esta sección de los documentos de Solidity. diff --git a/locales/es/DeployWithLibraries/2_Generate_Metadata/step2.md b/locales/es/DeployWithLibraries/2_Generate_Metadata/step2.md new file mode 100644 index 000000000..ccca5fbce --- /dev/null +++ b/locales/es/DeployWithLibraries/2_Generate_Metadata/step2.md @@ -0,0 +1,38 @@ +## Desplegando la Biblioteca + +La **biblioteca** del capítulo anterior se encontraba en el mismo archivo que el **contrato**. Sin embargo, no serán desplegadas juntas y tendrán direcciones diferentes. + +Para poder utilizar una biblioteca, el contrato de llamada debe tener la **dirección** de la biblioteca. + +Pero la dirección de la biblioteca no se especifica directamente en el código de solidity. El bytecode compilado del contrato de llamada contiene un **marcador de posición** donde irán las **direcciones** de la biblioteca. + +Durante el despliegue el **contrato de llamada**, Remix buscará en los **metadatos** del contrato la dirección de la biblioteca y actualizará el marcador de posición con la dirección. + +Así que antes de desplegar un contrato que llama una biblioteca, necesitas generar los metadatos del contrato (también conocido como su **artefacto de construcción**) y entonces necesitas introducir la dirección de la biblioteca en el archivo de metadatos. + +Los metadatos de un contrato se generan en el **tiempo de compilación**. + +Vamos a configurar Remix para generar el **archivo de metadatos**. + +- ¡Ve al módulo de configuración haciendo clic en la configuración![settings](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/settings.png "Settings" icon) en el panel del icono. + +![settings module](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_settings.png "Settings Module") + +- Y marca la primera opción `Generate contract metadata`. + +# Compila y genera metadatos (JSON). + +1. Abre el Compilador de Solidity ![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +2. Compila `2_contractSimpleLibrary.sol`. + +3. Cambia al Explorador de Archivos ![File Explorer](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_file_explorer.png "File Explorer") + +4. Navega hasta los archivos JSON recién creados. + - Debería estar en la carpeta: + +**browser/.learneth/DeployWithLibraries/2_Generate_Metadata/artifact/** + +5. Selecciona el nuevo archivo JSON creado del contrato. Tiene el **mismo nombre** que el contrato `sample` pero con la extensión **json**: `sample.json` (no seleccione el metadato de la librería `contractSimpleLibrary.json`). + +En el siguiente paso haremos algunos ajustes en el archivo de metadatos. diff --git a/locales/es/DeployWithLibraries/3_Edit_Metadata/step3.md b/locales/es/DeployWithLibraries/3_Edit_Metadata/step3.md new file mode 100644 index 000000000..dfbfd0adc --- /dev/null +++ b/locales/es/DeployWithLibraries/3_Edit_Metadata/step3.md @@ -0,0 +1,12 @@ +La propiedad `Deploy` en `sampleContract.json` contiene todo lo que necesitas para decirle a Remix IDE la dirección de la biblioteca para una red específica. + +- `
` contiene la dirección de la biblioteca que ya está instalada. Debe especificar esta dirección para cada red. +- `autoDeployLib` es un booleano y le dice a Remix IDE si debería desplegar automáticamente la librería antes de desplegar el contrato. + +Básicamente si `autoDeployLib` es **verdadero**, el `
` no será utilizado y Remix desplegará automáticamente la librería antes de desplegar el contrato. + +Para el propósito de esta demostración - estamos imitando una situación en la que la librería ya ha sido desplegada porque esta es una situación más común. + +Así que establece `autoDeploy` a **falso**, para la entrada `VM:-`. + +Ir al siguiente paso. diff --git a/locales/es/DeployWithLibraries/4_Linking_and_Deploying/step4.md b/locales/es/DeployWithLibraries/4_Linking_and_Deploying/step4.md new file mode 100644 index 000000000..d043c772b --- /dev/null +++ b/locales/es/DeployWithLibraries/4_Linking_and_Deploying/step4.md @@ -0,0 +1,24 @@ +Cambia al módulo `Deploy & Run` +![Run transaction](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/remix_runtransaction.png "Run transaction") + +- Seleccione el entorno VM Remix y seleccione el contrato `sampleContract` en la lista de contratos compilados. + +- Haz clic en `Desplegar` + +La terminal debe de devolver algo como `creación de ejemplo error:
no es una dirección válida. Por favor, compruebe que la dirección proporcionada es válida. `That is expected: **We have set `autoDeployLib` to false, so Remix expects to have an address and not just `
`** + +Por lo tanto, necesitamos desplegar la librería para obtener su dirección. + +- Selecciona la librería `aLib` en la lista de contrato compilado y presiona `deploy` + + ![Choose aLib](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/contract_alib.png "Choose aLib") + +- Haz clic en el icono del portapapeles para copiar la dirección de la librería. + + ![Copy lib1](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/alib_copy.png "Copy") + +- Pégalo en los metadatos JSON de la **muestra de contrato**. + +- Reelige el contrato `sampleContract` en el módulo `Run transaction` y presiona desplegar. + +- El despliegue ahora debería ser exitoso. diff --git a/locales/es/DeployWithLibraries/5_Under_The_Hood/step5.md b/locales/es/DeployWithLibraries/5_Under_The_Hood/step5.md new file mode 100644 index 000000000..cede5bc96 --- /dev/null +++ b/locales/es/DeployWithLibraries/5_Under_The_Hood/step5.md @@ -0,0 +1,29 @@ +Cambia al módulo `Solidity compiler` ![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +- Selecciona el contrato `sampleContract` en la lista de contratos compilados. +- haz clic en `ByteCode`, debería copiar lo siguiente en el portapapeles: + +``` +{ + "linkReferences": { + "browser/contractSimpleLibrary.sol": { + "lib1": [ + { + "length": 20, + "start": 115 + } + ] + } + }, + "object": "608060405234801561001057600080fd5b5060f68061001f6000396000f3fe6080604052600436106039576000357c0100000000000000000000000000000000000000000000000000000000900480636d4ce63c14603e575b600080fd5b348015604957600080fd5b5060506052565b005b73__$d42d70ba92b626965f4c69b39148e37a33$__63fea24e5f6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801560b157600080fd5b505af415801560c4573d6000803e3d6000fd5b5050505056fea165627a7a7230582068c9a3a9a5cbfd26cfdab2534abfc926912d9b89eaa14e36c8248b7e7eb0ab090029", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xF6 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x39 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x3E JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x50 PUSH1 0x52 JUMP JUMPDEST STOP JUMPDEST PUSH20 0x0 PUSH4 0xFEA24E5F PUSH1 0x40 MLOAD DUP2 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH1 0xB1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS DELEGATECALL ISZERO DUP1 ISZERO PUSH1 0xC4 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 PUSH9 0xC9A3A9A5CBFD26CFDA 0xb2 MSTORE8 0x4a 0xbf 0xc9 0x26 SWAP2 0x2d SWAP12 DUP10 0xea LOG1 0x4e CALLDATASIZE 0xc8 0x24 DUP12 PUSH31 0x7EB0AB09002900000000000000000000000000000000000000000000000000 ", + "sourceMap": "63:85:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63:85:0;;;;;;;" +} +``` + +Esto es básicamente lo que el compilador está volviendo: + +- `linkReferences` describe cuáles son las librerías utilizadas por el contrato. +- `object` es el contrato compilado (bytecode). Esto es lo que se desplegó y se guardó en la cadena de bloques. En este ejemplo, el valor `__$d42d70ba92b626965f4c69b39148e37a33$__` dentro del bytecode es solo un marcador de posición para la dirección de la librería. En tu caso, el marcador estará entre `__$` y `$__`. + +El metadato JSON del IDE Remix le dice a Remix que reemplace el marcador de posición con la dirección dada. diff --git a/locales/es/DeployWithLibraries/README.md b/locales/es/DeployWithLibraries/README.md new file mode 100644 index 000000000..ec62f648f --- /dev/null +++ b/locales/es/DeployWithLibraries/README.md @@ -0,0 +1,3 @@ +Las **Librerías** son contratos desplegados que no almacenan estado y que son utilizados por otros contratos para reducir su tamaño, y por lo tanto sus costos de implementación. + +Aprende a trabajar con **Librerías** en Remix - no necesitarás susurrar. diff --git a/locales/es/DeployWithLibraries/config.yml b/locales/es/DeployWithLibraries/config.yml new file mode 100644 index 000000000..0816e2346 --- /dev/null +++ b/locales/es/DeployWithLibraries/config.yml @@ -0,0 +1,8 @@ +--- +id: deploylibraries +name: Deploy with Libraries +summary: Write, Deploy and link a Library to a Contract +level: 3 +tags: + - Remix + - Solidity diff --git a/locales/es/ERC20TokenCourse/README.md b/locales/es/ERC20TokenCourse/README.md new file mode 100644 index 000000000..100ec81ca --- /dev/null +++ b/locales/es/ERC20TokenCourse/README.md @@ -0,0 +1,5 @@ +## Curso interactivo de autentificadores de Solidity + +Aprende a entender y crear autentificadores de ERC20. + +Desarrollado por la plataforma de aprendizaje p2p https://dacade.org. diff --git a/locales/es/ERC20TokenCourse/config.yml b/locales/es/ERC20TokenCourse/config.yml new file mode 100644 index 000000000..8c12a5213 --- /dev/null +++ b/locales/es/ERC20TokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: tokenCourse +name: Solidity ERC20 Token Course +summary: Learn how to create your own ERC20 tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - ERC20 +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc20-interface + - + name: 3. Token Creation + path: erc20-token-creation + - + name: 4. Interaction + path: erc20-interaction + - + name: 5. Testnet Deployment + path: erc20-testnet-deployment + - + name: 6. Extensions + path: erc20-extensions diff --git a/locales/es/ERC20TokenCourse/erc20-extensions/erc20extensions.md b/locales/es/ERC20TokenCourse/erc20-extensions/erc20extensions.md new file mode 100644 index 000000000..f724139a8 --- /dev/null +++ b/locales/es/ERC20TokenCourse/erc20-extensions/erc20extensions.md @@ -0,0 +1,33 @@ +El estándar ERC20 sólo describe la funcionalidad requerida y opcional que necesita tu contrato, pero puedes añadir una funcionalidad adicional. + +En esta sección, añadimos la funcionalidad de quemar y acuñar autentificadores, así como la capacidad de pausar el contrato, usando las extensiones de OpenZeppelin. + +Por supuesto, puedes escribir tu propia implementación o extensión del contrato ERC20 e importarlos en tu contrato. Pero los contratos de OpenZeppelin han sido auditados por expertos en seguridad y son una excelente manera de añadir la funcionalidad deseada. + +### Acuñable + +La función cuña permite que el creador del contrato acuñe (fichas adicionales) después de que el contrato haya sido desplegado (línea 22). Como parámetros de entrada, la función necesita la dirección a la que serán acuñados los autentificadores y la cantidad de autentificadores que deben ser acuñados. + +No tenemos que importar `mint()` de otro contrato ya que la función de la cuña ya es parte del contrato ERC20 implementación de OpenZeppelin. Importamos `Ownable` (línea 7) que es un módulo de contrato que proporciona un mecanismo de control de acceso básico que permite a un propietario tener acceso exclusivo a funciones específicas. En este contrato, añadimos el modificador heredado `onlyOwner` a la función `mint` (línea 22) y restringimos el acceso a esta función al "propietario". + +El contrato heredará funciones adicionales como propietario(), transferOwnership() y renunciará a Ownership() para administrar el acceso, desde el Ownable contract. + +### Quemable + +Importando el "ERC20Burnable" (línea 5) y heredando sus funciones (línea 9) nuestro contrato permite a los poseedores de autentificadores destruir sus autentificadores así como los autentificadores en su permiso. +Para más información, échale un vistazo al contrato ERC20Burnable. + +### En pausa + +Con el módulo "En pausa" (línea 6 y 9) el propietario puede pausar (línea 14) y desactivar (línea 18) el contrato. En el estado pausa, los autentificadores no se pueden transferir, lo que puede ser útil en escenarios de emergencia. +Para más información, échale un vistazo al Pausable contrac. + +Échale un vistazo a OpenZeppelins Contract Wizard, el cual permite añadir fácilmente funciones adicionales. + +Si completaste exitosamente este curso, prueba el curso Learneth NFT como siguiente paso en tu recorrido. + +## ⭐ Tarea + +1. Intenta acuñar autentificadores a una cuenta después del despliegue. Llama a `totalSupply()` y `balanceOf()` para confirmar la ejecución correcta. +2. Quema autentificadores y luego llama a `totalSupply()` y `balanceOf()` para confirmar la ejecución correcta. +3. Prueba la función de pausa pausando el contrato utilizando la cuenta del propietario e intentando hacer una transferencia a una segunda cuenta. La transacción no debe ser capaz de ser ejecutada y arrojará la excepción: "En pausa: pausado". diff --git a/locales/es/ERC20TokenCourse/erc20-interaction/er20interaction.md b/locales/es/ERC20TokenCourse/erc20-interaction/er20interaction.md new file mode 100644 index 000000000..d0a9fb28f --- /dev/null +++ b/locales/es/ERC20TokenCourse/erc20-interaction/er20interaction.md @@ -0,0 +1,87 @@ +En esta sección, desplegaremos un contrato en nuestro navegador y probaremos su funcionalidad. + +### 1. Despliegue del contrato + +**1.1** Compila tu contrato de EduCoin en el módulo "Compilador de Solidity" del IDE Remix. + +**1.2** En el módulo "Desplegar y correr transacciones", seleccione su contrato "EduCoin" en el campo de entrada del contrato y haga clic en el botón "Desplegar". Asegúrate siempre de seleccionar el contrato correcto en el campo de entrada del selector del contrato. + +**GIF** Compila y despliega: Compile and deploy contract + +### 2. Probar las funciones + +Expandir las funciones del contrato de autentificadores en el IDE. + +#### 2.1 decimales + +Haz clic en el botón "decimales" para llamar a la función decimals(). +Te debería devolver "18". + +#### 2.2 Nombre + +Haz clic en el botón "nombre" para llamar a la función name(). +Te debería devolver "EduCoin". + +#### 2.3 Símbolos + +Haga clic en el botón "símbolo" para llamar a la función symbol(). +Te debería devolver "EduCoin". + +#### 2,4 Suministro total + +Haga clic en el botón "totalSupply" para llamar a la función totalSupply(). +Te debería devolver 1000000000000000000 (1000\*10\*\*18). + +**GIF** Prueba los decimales, el nombre, el símbolo y las funciones de totalSupply: Test transfer function + +#### 2.5 Balance de + +**2.5.1** Ve a la sección "CUENTA" en la barra lateral y copia la dirección mostrada usando el icono de copia junto a ella. + +**2.5.2** Pega la dirección en el campo de entrada junto al botón "balanceOf" y hacer clic en el botón. +Te debería devolver 1000000000000000000000000000 (1000\*10\*\*18). + +**GIF** Prueba la función balanceOf: Test transfer function + +#### 2,6 Transferencia + +Transfiriremos EduCoin de una cuenta a otra cuenta. + +**2.6.1** Ve a la sección "CUENTA" en la barra lateral y haz clic en la dirección mostrada. Esto debería abrir un menú desplegable. Selecciona la segunda dirección que aparece y copie su dirección (cuenta 2). + +\*\*2,6. \*\* Abre el menú desplegable y selecciona de nuevo la primera cuenta (cuenta 1), porque esta es la cuenta que queremos usar para hacer la transferencia. + +**2.6.3** Pega la dirección en el campo de entrada junto al botón "transferir", ingrese el número 500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 y haz clic. + +**2.6.4** Si revisas los balances de la cuenta 1 y de la cuenta 2, ambos devolverían la cantidad 500000000000000000000000000. + +**GIF** Prueba de la función transferir: Test transfer function + +#### 2.7 Aprobar + +Ahora permitiremos que la cuenta 1 gaste autentificadores en nombre de la cuenta 2. + +**2.7.1** Ve a la sección "Cuenta", copia la dirección de la cuenta 1 y luego vuelve a establecerla en la cuenta 2. + +**2.7.2** En la función de aprobación, introduce la dirección de la cuenta 1 como la entrada para el gasto y establece la cantidad a 2500000000000000000000000000000000000. + +**GIF** Prueba de la función aprobar: Test approve function + +#### 2,8 Permiso + +Al lado del botón de "ayuda" introduzca la dirección de la cuenta 2 como propietario y la cuenta 1 como pender; haga clic en el botón. +Te debería devolver 000000000000000000000. + +**GIF** Prueba de la función permiso. Test allowance function + +#### 2.9 TransferirDesde + +Ahora la cuenta 1 transferirá 250000000000000000000000000000000 autentificadores de la cuenta 2 a su propia cuenta. + +**2.9.1** Seleccione la cuenta 1 en la sección "CUENTA". + +\*\*2,9. \*\* Junto al botón "transferDesde" introduce la dirección de la cuenta 2 como remitente y la cuenta 1 como destinatario, introduce 250000000000000000000000000 como la cantidad y haga clic en el botón. + +**2.9.3** Compruebe los balances de las cuentas 2 y 1, deberían devolver 25000000000000000000000 y 75000000000000000000000. + +**GIF** Prueba de la funcion TransferirDesde: Test transferFrom function diff --git a/locales/es/ERC20TokenCourse/erc20-interface/erc20interface.md b/locales/es/ERC20TokenCourse/erc20-interface/erc20interface.md new file mode 100644 index 000000000..394f64848 --- /dev/null +++ b/locales/es/ERC20TokenCourse/erc20-interface/erc20interface.md @@ -0,0 +1,76 @@ +ERC20 (Ethereum Request for Comments 20) es un estándar para contratos de autentificador que administran autentifiadores fungibles en la cadena de bloques Ethereum. + +Los autentificadores funcionales son todos iguales entre ellos y tienen el mismo valor, comportamiento y derechos. Las autentificadores fungibles se utilizan a menudo como un medio de cambio, como las monedas ETH o BTC. Sin embargo, también pueden tener otros casos de uso como derecho de voto o reputación. + +Si quieres saber más sobre el estándar de autentificadores ERC20, échale un vistazo a las especificaciones en su Ethereum improvement proposal. + +## Interfaz + +Para obtener una visión general de la funcionalidad requerida de un contrato de auntentificadores ERC20, examinaremos una interfaz que interactúa con un contrato ERC20. +Esta interfaz (línea 9) forma parte de la libería de contratos de código abierto proporcionada por OpenZeppelin. + +## Funciones de ERC20 + +Los contratos compatibles con la norma ERC20 deben implementar las siguientes seis funciones: + +### suministroTotal + +La función `totalSupply` (línea 13) devuelve la cantidad total de autentificadores disponibles. + +### balanceDe + +La función `balanceOf` (línea 18) devuelve la cantidad de auntentificador propiedad de la cuenta con la dirección `cuenta`. + +### transferir + +La función `transfer` (línea 27) transfiere `amount` de autentificadores a la dirección `recipient`. +Esta función **debe** emitir (producir) un evento `Transfer` (ver abajo) y **debería** lanzar una excepción cuando el remitente no tiene suficientes autentificadores para hacer la transferencia. + +### aprobar + +La función `approve` (línea 52) crea una asignación para que la dirección `spender` transfiera `amount` de autentificadores en nombre de la cuenta llamando a la función. + +### permiso + +La función `allowance` (línea 36) devuelve la cantidad de autentificadores que la dirección `spender` tiene permitido gastar en nombre de la cuenta con la dirección `owner`. + +### transferirDesde + +La función `transferFrom` (línea 63) transfiere `amount` de autentificadores en nombre de la dirección `sender` a la dirección `recipient`. +Esta función **debe** emitir un evento `Transfer`. + +## Eventos ERC20 + +Los contratos ERC20 deben emitir también dos eventos: + +### Transferencia + +El evento `Transfer` (línea 71) debe emitirse cuando `value` cantidad de autentificadores son transferidos desde la cuenta con la dirección `indexed from` a `indexed to`. Los parámetros `from` y `to` son `indexed` que nos permiten buscar estos eventos usando los parámetros indexados como filtros. + +### Aprobaciones + +El evento `Approval` (línea 77) debe ser emitido cuando la cuenta `indexed owner` aprueba la cuenta `indexed spender` para transferir la cantidad de auntentificadores `value` en su nombre. + +## Funciones opcionales de ERC20 + +Además de las funciones obligatorias y eventos, también hay tres funciones opcionales especificadas en el estándar ERC20 que no se implementan en esta interfaz: + +### nombre + +`function name() external view returns (string);` + +Devuelve el nombre del autentificador. + +### símbolos + +`function symbol() external view returns (string);` + +Devuelve el símbolo del autentificador. + +### decimales + +`function decimals() external view returns (uint8);` + +Devuelve el número de decimales que utiliza el autentificador. + +Puedes que quieras usar decimales para hacer tus autentificador divisible en cantidades arbitrarias como 1.5 ETH cuando se muestre. El EVM (Ethereum virtual machine) sólo admite números enteros. Es por eso que el estándar ERC20 sugiere implementar la funcionalidad decimal que especifica cuántos decimales tiene un autentificador. 18 decimales es la norma de la industria. diff --git a/locales/es/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md b/locales/es/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md new file mode 100644 index 000000000..9b43e5039 --- /dev/null +++ b/locales/es/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md @@ -0,0 +1,41 @@ +En esta sección, utilizaremos Metamask (una cartera de Ethereum) para desplegar nuestro contrato en una red de pruebas de la cadena de bloques Ethereum. Esta red de pruebas se comporta de manera muy similar a la cadena de bloques real (mainnet), pero no requiere ETH real para pagar las transacciones. + +### 1. Instalar MetaMask + +**1.1** Ve a metamask.io. + +**1.2** Haz clic en el botón de descarga, luego haga clic en instalar para tu navegador (por ejemplo, Chrome) y agregue la extensión a su navegador. + +**1.3** Crear una cartera como se describió. + +### 2. Obtener el autentificador de testnet + +Para realizar transacciones en la red de pruebas necesitamos autentificadores de Ethereum testnet, por lo cual puedes recibir de algo llamado _grifo_. + +**2.1** Cambia tu red Metamask haciendo clic en el menú desplegable "Ethereum Redprincipal" y seleccionando "Red de pruebas Ropsten". Si no ves ninguna red de pruebas, haga clic en el enlace "Mostrar/ocultar" y activa "Mostrar redes de prueba" en la configuración. + +**2.2** Ve a https://faucet.ropsten.be/, introduce la dirección de tu cuenta y reclama el ETH de testnet. También puede usar otros grifos de ropsteno como https://faucet.paradigm.xyz/ o https://app.mycrypto.com/faucet. Echa un vistazo a los grifos listados en ethereum.org para saber más. + +### 3. Despliegue + +Asegúratede que el contrato de EduCoin está compilado. + +**3.1.** En el módulo "DESPLEGAR & CORRER TRANSACCIONES" del IDE Remix bajo "ENTORNO" seleccione "Web3 inyectada". Te pedirá que conectes tu cuenta la cual deberías confirmarla. + +**3.2** Despliega el contrato de EduCoin y confirma la transacción en Metamask. + +**3.3** Tu contrato debería aparecer en la sección "Contratos Desplegados". Copia la dirección del contrato. + +**3.4** En Metamask, haz clic en activos, luego haz clic en el enlace "Importar autentificadores" y pega la dirección de tu contrato en el campo de entrada. + +Ahora debería ver un saldo de 1000 EDC en tu cartera. + +### 4. Realizar una transacción + +**4.1** Haz clic en el identificador (representación visual de tu dirección) en el monedero Metamask y crea una segunda cuenta (Cuenta 2). + +**4.2** Copia la dirección de la Cuenta 2. + +**4.3** Cambia a la primera cuenta (Cuenta 1) y envía 250 EDC a la Cuenta 2. Consulte los balances de la Cuenta 1 y la Cuenta 2. Puede que necesites agregar la dirección del autenticador de nuevo para la Cuenta 2 para importar los autenticadires y necesitarás testeth si deseas realizar una transacción con esta cuenta. + +También puedes ver los saldos de tu cuenta si observas el contrato en Remix y llamas a la función `balanceOf` usando las direcciones de la Cuenta 1 y la Cuenta 2. diff --git a/locales/es/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md b/locales/es/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md new file mode 100644 index 000000000..369327f21 --- /dev/null +++ b/locales/es/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md @@ -0,0 +1,18 @@ +Un estándar de autentificador nos dice qué funcionalidad necesita el contrato para cumplirlo. La manera en que se implementa esta funcionalidad depende de los desarrolladores. En este contrato, utilizaremos una implementación de un contrato ERC20 autentificador de OpenZeppelin (línea 4). En este caso, importamos la versión 4.4.0 de los contratos de OpenZeppelin. + +Echa un vistazo a su muy bien documentado contrato ERC20 contract para tener una mejor comprensión de cómo podría verse una implementación. Aparte de la funcionalidad especificada en el estándar ERC20, este contrato proporciona funcionalidad adicional. + +Vamos a crear nuestro propio contrato llamado MyToken (línea 6), que hereda la funcionalidad desde la implementación del contrato de autentificadores ERC20 de OpenZepplin que importamos (línea 4). + +Este contrato implementa las funciones opcionales `name()` y `symbol()` del estándar de autentificadores ERC20 y tiene un constructor donde sus valores pueden establecerse durante el despliegue del contrato (línea 7). +En este caso, vamos a usar los valores por defecto. Llamaremos a nuestra ficha igual que el contrato `"MyToken"` y haremos de \`"MTK" su símbolo. + +A continuación, hacemos uso de la función `_mint` heredada (línea 8) que nos permite crear autentificadores en el despligue del contrato. Dentro de los parámetros especificamos la dirección de la cuenta que recibe los autentificadores y la cantidad de autentificadores que son creados. +En este caso, la cuenta que despliega el contrato recibirá los autentificadores y establecemos la cantidad a 1000000 a la potencia de `decimals()`. La función opcional `decimals()` del estándar de autentificador ERC20 es implementada y establecida al valor por defecto de 18. Esto creará 1000000 autentificadores que tendrán 18 decimales. + +## ⭐ Tarea + +1. Renombra tu contrato a `EduCoin`. +2. Renombra tu autentificador a `EduCoin`. +3. Cambia el símbolo de tu autentificador a `EDC`. +4. Cambia la cantidad de autentificadores que serán acuñados de 1000000 a 1000. diff --git a/locales/es/ERC20TokenCourse/introduction/introduction.md b/locales/es/ERC20TokenCourse/introduction/introduction.md new file mode 100644 index 000000000..a39be7dbe --- /dev/null +++ b/locales/es/ERC20TokenCourse/introduction/introduction.md @@ -0,0 +1,65 @@ +En esta sección del curso, le daremos una introducción teórica sobre los tokens basados en blockchain. + +Los blockchain tokens son nuevos bloques tecnológicos de construcción creados sobre la tecnología blockchain (como las páginas web lo fueron para internet), que permite un internet descentralizado, apropiable (web3). + +### Introducción + +En el contexto de web3, los tokens representan propiedad. Representan la propiedad de cualquier cosa; arte, reputación, objetos en un videojuego, participaciones en una compañía, derecho a votar o divisas. + +La revolucionaria innovación de esta tecnología es que permite almacenar los datos públicamente de una manera inmutable (incambiable). +Esta nueva forma de almacenamiento de datos permite llevar una contabilidad de la propiedad y hace posible la existencia de objetos digitales realmente apropiables por primera vez. + +La tecnología blockchain fue originalmente inventada para llevar la contabilidad de la propiedad de Bitcoin, una divisa digital y token fungible. + +### Tokens fungibles y no fungibles. + +Activos como el dinero: Bitcoin o un billete de un dólar son intercambiables. Intercambiable quiere decir que todos los activos son iguales entre sí y por ello se pueden intercambiar. Activos como por ejemplo piezas de arte, los coleccionables o las propiedades inmobiliarias son no fungibles; todos los activos son distintos entre ellos y por tanto no intercambiables. + +Podemos dividir los tokens en estos dos tipos: tokens fungibles; en el que todos los tokens son iguales, y tokens no fungibles (NFTs); en el que los tokens son únicos. + +### El estándar de los tokens + +El comportamiento de un token es específico a su contrato inteligente (smart contract). El contrato debe, por ejemplo, incluir la funcionalidad de transferir un token o comprobar el suministro total. + +Si todo el mundo crease sus propios contratos inteligentes con diferentes comportamientos y convenciones nominales, sería complicado que los contratos o aplicaciones fueran capaces de interactuar las unas con las otras. + +La comunidad de Ethereum ha desarrollado una serie de estándares que definen cómo un desarrollador puede crear tokens que son interoperables (capaces de funcionar y colaborar con otros) con otros contratos, productos y servicios. Los contratos desarrollados con esos estándares han de incluir una serie de funcionalidades y eventos. + +Los estándares de Tokens más populares son el ERC20 para tokens fungibles y el ERC721 para tokens no fungibles. En las siguientes secciones de este curso, aprenderemos cómo crear e interactuar con el estándar de token ERC20. + +Si quiere aprender más sobre NFTs y el estándar de token ERC721, puede echar un vistazo al curso de Learneth sobre NFTs. + +El ERC777 es un estándar de token fungible, como el ERC20, que incluye características más avanzadas como “hooks”, manteniéndose a su vez compatible con el estándar ERC20. Aprenda más sobre el ERC777 en su EIP (Proposición de mejora por Ethereum). + +El ER1155 es un estándar multi token que permite que un contrato simple administre diferentes tipos de tokens, fungibles, no fungibles y semi-fungibles. +Aprenda más sobre ERC1155 en su EIP. + +## ⭐️ Misión + +Para esta tarea, podremos a prueba sus conocimientos mediante un breve cuestionario. +Para esta misión vamos a poner a prueba sus conocimientos con este breve cuestionario: +Asigne el número de la respuesta correcta a las variables `question1` (línea 5), +`question2` (línea 6), `question3` (línea 7) en el contrato `Quiz` (línea 4). + +### Pregunta 1: + +¿Por qué son revolucionarios los tokens basados en blockchain? + +1. Porque ahora la gente puede invertir de forma anónima. +2. Porque representan la propiedad en los activos digitales que pueden ser apropiados y transferidos. +3. Porque puede usar tokens para hacer transacciones sin necesidad de pagar impuestos. + +### Pregunta 2: + +¿Por qué ha creado la comunidad los estándares de token? + +1. Para que la comunidad pueda controlar y aprobar los tokens que se han creado. +2. Para restringir la funcionalidad de los tokes a acciones seguras y no maliciosas. +3. Para que la comunidad pueda crear tokens que sean interoperables con otros contratos, productos y servicios. + +### Pregunta 3: + +Si tuviera que crear una aplicación descentralizada para un juego de intercambio de cromos de baseball, en el que cada jugador fuera representado por un token, ¿qué estándar de token utilizaría para crear su contrato inteligente? + +1. ERC20 +2. ERC721 diff --git a/locales/es/ERC721Auction/README.md b/locales/es/ERC721Auction/README.md new file mode 100644 index 000000000..022703c31 --- /dev/null +++ b/locales/es/ERC721Auction/README.md @@ -0,0 +1,5 @@ +## Contrato de subastas NFT + +Aprende a escribir un contrato de subasta ERC721 (NFT). + +Desarrollado por la plataforma de aprendizaje p2p https://dacade.org. diff --git a/locales/es/ERC721Auction/auction-contract-setup/auctionContractSetup.md b/locales/es/ERC721Auction/auction-contract-setup/auctionContractSetup.md new file mode 100644 index 000000000..51073639d --- /dev/null +++ b/locales/es/ERC721Auction/auction-contract-setup/auctionContractSetup.md @@ -0,0 +1,46 @@ +En este tutorial de contrato, aprenderemos cómo crear un contrato de subasta ERC721 (NFT). +Te recomendamos que hagas el curso Learneth "Solidity NFT Course" antes de comenzar este tutorial. + +En las siguientes secciones, crearemos un contrato que permitirá al vendedor subastar un NFT a la mayor oferta. Este contrato fue creado por el proyecto Solidity by Example. En esta primera sección, crearemos una interfaz, las variables de estado necesarias y el constructor. + +### Interfaz + +Creamos la interfaz (línea 5) para el autentificador ERC721 ya que nuestro contrato tendrá que interactuar con él. Necesitaremos los métodos `safeTransferFrom` (línea 5), y` transferFrom` (línea 11). + +### EnglishAuction + +Creamos los cuatro eventos `Start`, `Bid`, `Withdraw`, `End` (línea 19-22) para poder registrar interacciones importantes. + +A continuación, crearemos las variables de estado que almacenarán toda la información necesaria sobre nuestra subasta en cadena. + +Creamos dos variables de estado para el NFT que queremos subastar. En la variable `nft` (línea 24) guardamos una representación del contrato NFT, que nos permitirá llamar a sus funciones combinando la interfaz IERC721 con la dirección del contrato NFT. +En `nftId` (línea 25), almacenamos el identificador de autentificador específico en nuestro contrato NFT que se subastará. + +A continuación, necesitamos una variable para almacenar la dirección de la persona que subasta del NFT, el `seller` (línea 27). +Queremos que nuestro contrato NFT envíe al vendedor los ingresos de la subasta cuando haya terminado, por eso utiliza `address payable`. + +Creamos una variable de estado `endAt` (línea 28) donde almacenaremos la fecha de fin de la subasta. +También creamos los dos booleanos, `started` (línea 29) y `ended` (línea 30), que hacen un seguimiento de si la subasta ha comenzado o terminado. + +Creamos una variable `highestBidder` (línea 32) donde almacenaremos la dirección de la mayor oferta. Enviaremos la oferta más alta el NFT una vez que la subasta haya terminado. + +Por último, necesitamos un uint `highestBid` (línea 33) para almacenar la oferta más alta y un mapeo de `bids` (línea 34), donde podemos almacenar el valor total de las ofertas que una cuenta ha realizado antes de retirarse; más sobre esto en la próxima sección. + +### Constructor + +Cuando el subastador despliegue el contrato, necesitan proveer algunos argumentos: +la dirección del contrato del NFT que quieren subastar `_nft` (línea 37), el id del token del NFT que quieren subastar `_nftId` (línea 38), y un precio inicial que debe ser sobrepujada para hacer la primera oferta en la subasta,`_startingBid` (línea 39). + +Una vez desplegadas, las variables de estado `nft` (línea 41), `nftId` (línea 42), `highestBid` (línea 45) serán asignadas a los valores de los argumentos. La dirección del 'sellerr' que desplegó el contrato será automáticamente leída a través de msg.sender y almacenada en la variable de estado 'seller' (línea 44). + +En la siguiente sección, vamos a permitir que el subastador inicie la subasta y los licitadores hagan sus ofertas. + +## ⭐ Tarea + +Utilizaremos la parte de asignación de las siguientes secciones para darle instrucciones sobre la prueba de su contrato en el entorno de Remix VM. + +1. Desplegar un contrato de NFT. Puedes utilizar el contrato de NFT que creamos en nuestra sección "3.3 ERC721 - Creación de Token". + +2. Despliegue de este contrato EnglishAuction. Usa la dirección del contrato de NFT como argumento para el parámetro `_nft`, 0 para `_nftId` y 1 para `_startingBid`. + +3. Después de desplegar tu contrato, prueba si las funciones del contrato como `nft`, `nftId` y `started` funcionan como se esperaba. diff --git a/locales/es/ERC721Auction/auction-start-bid/auctionContractStartBid.md b/locales/es/ERC721Auction/auction-start-bid/auctionContractStartBid.md new file mode 100644 index 000000000..6cfd2a2d5 --- /dev/null +++ b/locales/es/ERC721Auction/auction-start-bid/auctionContractStartBid.md @@ -0,0 +1,42 @@ +En esta sección, crearemos una función para iniciar la subasta y una función para pujar en el NFT. + +### Inicio + +Utilizamos algunas estructuras de control para comprobar si se cumplen las condiciones necesarias antes de dejar que el vendedor inicie la subasta. + +En primer lugar, comprobamos si la subasta ya ha comenzado (línea 49). Si se ha iniciado y nuestra variable de estado `started` devuelve `true` salimos de la función y arrojamos una excepción. + +La segunda condición que verificamos es si el vendedor está ejecutando la función (línea 50). Ya hemos creado una función para almacenar la dirección del vendedor cuando desplieguen el contrato en la variable de estado 'seller' y ahora podemos comprobar si la cuenta que ejecuta la función de inicio es el vendedor. Si no es así, lanzamos una excepción. + +Después, queremos transferir el NFT que está en subasta del vendedor al contrato (línea 52). +Establecemos la variable de estado `started` a `true` (línea 53), y creamos una fecha de fin para la subasta (línea 54). En este caso, serán siete días desde que se haya llamado la función de inicio. Podemos utilizar un sufijo como `days` después de un número literal para especificar unidades de tiempo. Si desea obtener más información sobre las unidades de tiempo, consulte la solidity documentation. + +Finalmente, emitiremos nuestro evento `Start()` (línea 56). + +### Puja + +Antes de que la llamada a la función pueda hacer una oferta, tenemos que estar seguros de que ciertas condiciones se cumplen. La subasta tiene que haber comenzado (línea 60), la subasta no puede haber terminado (línea 61) y la oferta (el valor adjunto a la llamada) debe ser mayor que la actual mayor oferta (línea 62). + +Ahora queremos guardar la oferta de la oferta más alta actual antes de hacer una nueva oferta. +En primer lugar, comprobamos si hay un postor (línea 64). Si esta llamada de función es la primera oferta, entonces la siguiente línea sería irrelevante. +En nuestro mapeo `bids` (línea 34) asignamos la clave, la `address ` del postor, al valor, un `uint` que representa la cantidad total de ETH un postor tiene puja en la subasta antes de retirar. +Si existe un postor, añadimos la última oferta (`highestBid`) del `highestBidder` al valor total de las ofertas que han hecho (línea 65) antes de retirar. +Almacenamos las ofertas porque queremos permitir que la oferta retire el ETH que usaron para hacer pujas si ya no son la oferta más alta. + +A continuación, establecemos el `highestBidder` en la cuenta llamando a la función (línea 68), y la `highestBid` a su oferta, el valor que fue enviado con la llamada (línea 69). + +Por último, emitimos el evento `Bid` (línea 71). + +## ⭐ Tarea + +1. Despliegue del contrato de NFT. Puedes usar el contrato de NFT que creamos en nuestro curso de Learneth "Solidity NFT Course". + +2. Publica un NFT con el tokenid que tenga valor 0. + +3. Despliegue de este contrato EnglishAuction. Usa la dirección del contrato NFT como argumento para el parámetro `_nft`, 0 para `_nftId` y 1 para `_startingBid`. + +4. Llama a la función 'approve' de tu contrato NFT con la dirección del contrato de subasta como argumento para el parámetro 'to', y 0 para 'tokenId'. Esto permitirá que el contrato transfiera el token para ser subastado. + +5. Llama la función `start` de tu contrato de subasta. Si llamas ahora a la función `started`, te debería devolver `true`. Si llamas a la función `highestBid` debería devolver 1. + +6. Establece el valor que puedes adjuntar a las transacciones a 3 Wei y llamar a la función 'bid' del contrato de subasta. Si llamas a la función `highestBid` ahora te debería devolver 3. diff --git a/locales/es/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md b/locales/es/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md new file mode 100644 index 000000000..f2ecfdf72 --- /dev/null +++ b/locales/es/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md @@ -0,0 +1,45 @@ +En esta sección, terminaremos el contrato, crear una función para retirar las ofertas que una cuenta ha hecho, y crear una función para terminar la subasta. + +### Retirar + +Creamos una variable local `bal` (balance) que almacena el valor total de las ofertas que el llamador de función ha realizado (línea 75) desde su último retiro. Podemos asignar este valor a `bal` accediendo al mapeo de pujas usando la dirección del llamador de función como clave. + +A continuación, establecemos el valor de la dirección de la llamada a la función a 0 en el mapeo de las pujas porque retirarán el valor total de sus ofertas (línea 76). + +Ahora transferimos esa cantidad de ETH desde el contrato al llamador de función y emitimos el evento `Withdraw` (línea 79). + +### Finalizar + +Antes de que la llamador de la función pueda ejecutar esta función y terminar la subasta, tenemos que comprobar si se cumplen ciertas condiciones. La subasta necesita haber comenzado (línea 83), la fecha final de la subasta debe haber sido alcanzada (línea 84), y la subasta no debe de haber terminado ya (línea 85). + +Una vez que la subasta ha terminado, establecemos la variable de estado `ended` a `true` (línea 87). + +Comprobamos si alguien participó en la subasta y pujó en el NFT (línea 88). + +Si había una oferta, transferimos el NFT del contrato a la oferta más alta (línea 89) y transferimos el ETH que fue enviado de la oferta más alta al contrato, ahora a la dirección del subastador, el vendedor de la NFT (línea 90). + +Si nadie puja en el NFT, le devolvemos el NFT a la subastador (línea 92). + +Finalmente, emitimos el evento `End` (línea 95). + +## ⭐ Tarea + +1. Despliega un contrato de NFT. Puedes utilizar el contrato NFT que hemos creado en nuestro curso Learneth "Solidity NFT Course". + +2. Conéctate a ti mismo un NFT con el token 0. + +3. Para propósitos de prueba, cambia el valor asignado a la variable de estado `endAt` (línea 54) de `7 days` a `5 minutes`. + +4. Despliega este contrato EnglishAuctio. Usa la dirección del contrato NFT como argumento para el parámetro `_nft`, 0 para `_nftId` y 1 para `_startingBid`. + +5. Llama a la función `approve` de tu contrato NFT con la dirección del contrato de subasta como argumento para el parámetro `to`, y 0 para el `tokenId`. + +6. Llama a la función `start` de tu contrato de subasta. + +7. Puja 2 Ether utilizando la cuenta 1, y 3 Ether usando la cuenta 2. Si llama a la función `highestBidder`, ahora debería devolver la dirección de la cuenta 2. + +8. Llama a la función `retirar` con la cuenta 1. En el balance de la cuenta 1, debería ver el 2 Ether menos algunas comisiones de transacción. + +9. Después de pasar 5 minutos, llama a la función 'end'. Luego, llama a la función `ended` la cual debería devolver `true`. + +En el contrato de NFT, si llamas a la función `ownerOf` con el tokenid 0, debería devolver la dirección de la cuenta 2. Si observas el balance de la cuenta 1, debería haber aumentado en 3 Ether menos algunas tasas de transacción. diff --git a/locales/es/ERC721Auction/config.yml b/locales/es/ERC721Auction/config.yml new file mode 100644 index 000000000..0783a37a1 --- /dev/null +++ b/locales/es/ERC721Auction/config.yml @@ -0,0 +1,19 @@ +--- +id: er721Auction +name: NFT Auction Contract +summary: Learn how to write an ERC721 (NFT) auction contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: Contract Setup + path: auction-contract-setup + - + name: Start and Bid Functions + path: auction-start-bid + - + name: Withdraw and End Functions + path: auction-withdraw-end diff --git a/locales/es/Interoperability/1_Intro/intro.md b/locales/es/Interoperability/1_Intro/intro.md new file mode 100644 index 000000000..558031043 --- /dev/null +++ b/locales/es/Interoperability/1_Intro/intro.md @@ -0,0 +1,5 @@ +As the web3 world grows, there will be more blockchains. A menos que las cadenas puedan comunicarse entre ellas, el ecosistema se fragmentará cada vez más. + +La red Axelar permite a los protocolos tener funcionalidad de cadena cruzada entre dos cadenas de bloque cualesquiera. + +Construir un protocolo que sea interoperable entre ecosistemas es esencial para el crecimiento. diff --git a/locales/es/Interoperability/2_Gateway/gateway.md b/locales/es/Interoperability/2_Gateway/gateway.md new file mode 100644 index 000000000..7739bd7e4 --- /dev/null +++ b/locales/es/Interoperability/2_Gateway/gateway.md @@ -0,0 +1,25 @@ +El Portal Axelar es el punto de entrada para tu contrato inteligente en el ecosistema Axelli. Una vez que hayas activado la función apropiada en la puerta de enlace, tu transacción iniciará su viaje intercadena desde su cadena de origen a través de la red Axelar hasta la cadena de destino. Cada cadena que está conectada a Axelar tiene un contrato de pasarela desplegado con el que interactuar con ella. + +The following are the two more relevant functions you will need to be familiar with. + +## callContract() + +Esta función activa una transacción de intercadena con un mensaje de la fuente a la cadena de destino. Necesitas tres parámetros relevantes: + +1. `destinationChain`: el nombre de la cadena de destino +2. `destinationContractAddress`: La dirección de la cadena de destino en la que se ejecutará esta transacción. +3. `payload`: El mensaje que esta siendo enviado + +Los primeros dos parámetros son bastante intuitivos. Consisten tanto en el nombre de la cadena a la que deseas que esta transacción vaya y en la dirección de esa cadena a la que deseas terminar la ejecución. El último parámetro es la carga útil. Este carga útil representa un mensaje general que es enviado a la cadena de destino. El mensaje puede utilizarse de muchas maneras diferentes en la cadena de destino. Por ejemplo, puedes enviar datos para ser usados como parámetro en otra función de la cadena de destino, puedes enviar una firma de función como un mensaje que luego será ejecutado en una cadena de destino, y mucho más. + +## callContractWithToken() + +Esta función activa una intercadena con un mensaje y un símbolo fungible de la cadena de origen a la de destino. Se necesitan cinco parámetros relevantes: + +1. `destinationChain`: El nombre de la cadena de destino +2. `destinationContractAddress`: La dirección en la cadena de destino en la que se ejecutará esta transacción. +3. `payload`: El mensaje que está siendo enviado +4. `symbol`: El símbolo del token siendo enviado +5. `amount`: La cantidad de ese token que está siendo enviado + +Los primeros tres parámetros aquí son los mismos que en `callContract()`. Los dos últimos parámetros son relevantes para el token que se envía junto con el mensaje. Estos son el símbolo de la ficha y la cantidad del token que se está enviando. diff --git a/locales/es/Interoperability/3_GasService/GasService.md b/locales/es/Interoperability/3_GasService/GasService.md new file mode 100644 index 000000000..7df3fc3e1 --- /dev/null +++ b/locales/es/Interoperability/3_GasService/GasService.md @@ -0,0 +1,29 @@ +El Servicio de Gas Axelar es una herramienta extremadamente útil disponible para pagar gas por una transacción intercadena. Te permite pagar el costo de una transacción en el token de la cadena de origen, para una experiencia mucho más fácil de usuario final (y también al desarrollador). Si por ejemplo la cadena de origen es Ethereum y la cadena de destino es Polygon, entonces el servicio de gas recibirá el pago completo de la transacción en ETH y no se necesita un mático de la persona que llama a pagar por la ejecución en la cadena de destino de Polígono. + +A continuación se detallan las dos funciones más relevantes que necesitarás conocer en relación con el Servicio de Gas. + +## payNativeGasForContractCall() + +Esta función te permite pagar por la totalidad de una transacción intercadena en el token nativo de la cadena de origen. Se necesitan cinco parámetros relevantes: + +1. `sender`: La dirección que hace el pago +2. `destinationAddress`: La dirección en la cadena de destino a la que se envía la transacción +3. `destinationChain`: El nombre de la cadena de destino +4. `payload`: El mensaje que está siendo enviado +5. `refundAddress`: La dirección de cualquier reembolso debería ser enviada a si se envió demasiado gas junto con esta transacción. + +Los parámetros se solapan con los parámetros requeridos por la función `callContract()` en el contrato de Puerta de Enlace. Los dos parámetros no discutidos en la sección Puerta de Enlace son `sender` y `refundAddress`. El remitente es la dirección de pago de la transacción y la dirección de reembolso es la dirección que recibirá cualquier fondo excedente enviado al servicio de gas. + +## payNativeGasForContractCallWithToken() + +This function allows you to pay for the entirety of an interchain transaction (that includes a token transfer) in the native token of the source chain. Necesitas tres parámetros relevantes: + +1. `sender`: La dirección que realiza el pago +2. `destinationContractAddress`: La dirección en la cadena de destino en la que se ejecutará esta transacción +3. `destinationAddress`: La dirección en la cadena de destino a la que se envía la transacción +4. `payload`: El mensaje que está siendo enviado +5. `symbol`: El símbolo del token que fue enviado +6. "amount": La cantidad del token que se envió +7. `refundAddress`: La dirección de cualquier reembolso debería ser enviada a si se envió demasiado gas junto con esta transacción. + +This function is nearly identical to the first top one the main difference being that it is used for message + token transfer transactions as opposed to just interchain message transactions (aka GMP Transactions). Como resultado, GasService también necesita conocer el `symbol` y `amount` del token que se está enviando. diff --git a/locales/es/Interoperability/4_Executable/executable.md b/locales/es/Interoperability/4_Executable/executable.md new file mode 100644 index 000000000..7bda74bb4 --- /dev/null +++ b/locales/es/Interoperability/4_Executable/executable.md @@ -0,0 +1,27 @@ +El ejecutable de Axelar contiene funciones de ayuda relevantes que se ejecutarán automáticamente en la cadena de destino en correspondencia con la transacción entrante relevante desde la cadena de origen. + +Las siguientes son las funciones relevantes que necesitarás usar desde el ejecutable de Axelar + +## \_execute() + +Esta función gestiona la ejecución en la cadena de destino. Necesitas los siguientes cuatro parámetros: + +1. `commandId`: Un id de transacción único en la cadena Axelar. +2. `sourceChain`: La cadena de bloque desde el cual la transacción ha sido enviada +3. `sourceAddress`: La dirección de la cadena de origen desde la que la transacción ha sido enviada +4. `payload`: El mensaje que está siendo enviado + +The `sourceChain` and `sourceAddress` are key parameters which you receive out of the box that can be used for verifying authenticity of messages on the destination chain. La carga útil (tal como se describe en la sección de la puerta de enlace) es el mensaje que fue enviado desde la cadena fuente para ser utilizado en tu cadena de destino. El `commandId` no será utilizado durante el resto de este módulo. + +## \_executeWithToken() + +Esta función maneja la ejecución en la cadena de destino para un mensaje enviado con un token fungible. Necesitas seis parámetros relevantes: + +1. `commandId`: Un identificador de transacción único en la cadena Axelar. +2. `sourceChain`: La cadena de bloque del cual la transacción ha sido enviada desde +3. `sourceAddress`: La dirección de la cadena de origen desde la que se ha enviado la transacción +4. `payload`: El mensaje que está siendo enviado +5. `tokenSymbol`: El símbolo del token que fue enviado +6. "amount": La cantidad del token que se envió + +Los cuatro primeros parámetros son idénticos a los de la función `_execute()`. Los dos últimos parámetros de `tokenSymbol` y `amount` se refieren al token que se está enviando junto con el mensaje. Te permite en la cadena de destino interactuar con el token en consecuencia, por ejemplo transfiriéndolo a otra dirección receptora. El `commandId` no será usado durante el resto de este módulo. diff --git a/locales/es/Interoperability/5_InterchainMessage/interchainMessage.md b/locales/es/Interoperability/5_InterchainMessage/interchainMessage.md new file mode 100644 index 000000000..aa5a42741 --- /dev/null +++ b/locales/es/Interoperability/5_InterchainMessage/interchainMessage.md @@ -0,0 +1,53 @@ +En esta sección crearemos un contrato que enviará un mensaje de "Hola mundo" entre dos cadenas de bloque. + +## Constructor + +The first thing you will need to create is the `constructor` for the function. Esto te permitirá establecer los contratos `Gateway` y `Gas Service` que hemos discutido en las secciones anteriores. + +Al desplegar el contrato pasarás en la dirección de la `Gateway` y `GasService` para Ethereum Sepolia esas direcciones son `0xe432150cce91c13a887f7D836923d5597adD8E31` para la Puerta de Enlace y `0xbE406F0189A0B4cf3A05C286473D23791D44Cc6` para el Servicio de Gas. + +Para la lista completa de direcciones Axelar relevantes see here + +## Enviar Mensaje Intercadena + +Ahora que el constructor ha establecido las direcciones Axelar relevantes necesarias para desencadenar una transacción de intercadena, puedes pasar a `setRemoteValue()`, que desencadenará esta transacción. + +Esta función requiere tres parámetros: + +1. `_destinationChain`: La cadena a la que va a ir la transacción +2. `_destinationAddress`: La dirección en la cadena de destino en la que se ejecutará esta transacción +3. `_message`: El mensaje siendo pasado a la cadena de destino + +First, you have a `require` statement which ensures that the `msg.value` contains a value. Este `msg.value` será usado para pagar el `GasService`. Si no se han enviado fondos, entonces la transacción debe ser revertida ya que la transacción no puede ejecutarse en la cadena de bloques Axelar y de destino sin ningún gas. + +Después, codificas el `_message` que fue pasado. Observa que el `_message` se establece como un tipo de `string`. Axelar espera que este mensaje se envíe como un tipo `bytes` para convertir la `string` a `bytes` simplemente pasarla a través de `abi.encode()`. + +Ahora, con tu mensaje codificado puedes comenzar a interactuar con el `GasService` y la `Gateway` + +Para pagar toda la transacción intercadena activarás la función `payNativeGasForContractCall`, que se define en el `GasService`. + +Esta función necesita los parámetros explicados anteriormente en la sección GasService. El `sender` para esta transacción será este contrato, que es `address(this)`. El `destinationChain` y `destinationAddress` simplemente pueden pasarse desde estos parámetros de funciones, el `payload` es el \_message codificado que escribimos antes. Por último, necesita especificar cuál es la dirección de reembolso, esta puede ser la dirección que activa esta función, que se obtiene escribiendo `msg.sender`. + +Once you trigger this function you will have successfully sent a transaction from the source chain via Axelar to the destination chain! But there is still one final step that needs to be complete. + +### Recibir mensajes en la cadena de destino + +En la cadena de destino la transacción de intercadena entrante necesita ser recogida y manejada por la función `_execute()` de `AxelarExecutable`. + +La función `_execute()` se define en el contrato `AxelarExecutable`, así que al definir esta función debes recordar incluir la palabra clave `override`. + +Esta función toma tres parámetros. + +1. `_sourceChain`: La cadena de bloque de la que procede la transacción +2. `_sourceAddress`: La dirección en la cadena de origen desde la que se ha enviado la transacción +3. `_payload`: El mensaje que ha sido enviado desde la cadena origen + +Lo primero que hay que hacer en este contrato es obtener acceso a tu `message` que fue enviado. Recuerda, antes de enviar el mensaje que fue enviado a través de `abi.encode()` para convertir el mensaje de tipo `string` para escribir `bytes`. Para convertir tu mensaje de regreso de escribe `bytes` para escribir `string` simplemente pasa el `_payload` a la función `abi. ecode()` y especifica que quieres que el `_payload` decodificado para escribir `string`. Esto devolverá el mensaje como cadena. + +Ahora que tienes tu mensaje como una cadena de tipo puedes establecer las variables de almacenamiento `sourceChain` y `sourceAddress` como `_sourceChain` y `_sourceAddress` para tener una referencia fácil a los datos que fueron pasados. También puedes emitir el evento `Executed` con el evento `sourceAddres` y `message` que acabas de decodificar. + +¡Excelente! En este punto ahora está manejando la transacción intercadena en la cadena de destino. + +Para interactuar con este contrato, asegúrate de desplegarlo en al menos dos cadenas de bloques para que puedas llamar a `setRemoteValue()` desde una cadena y luego tener la función `_execute()` activada automáticamente en otra cadena. Podrás consultar las variables `sourceChain` y `sourceAddress` en la cadena de destino para asegurar que la ejecución de la intercadena funcionó correctamente. + +Para ver el paso a paso completo de la compra de transacciones de la intercadena, el Axelarscan (testnet) block explorer. diff --git a/locales/es/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md b/locales/es/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md new file mode 100644 index 000000000..58a455b69 --- /dev/null +++ b/locales/es/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md @@ -0,0 +1,39 @@ +At this point we have gone over an example of how to send a general message between one blockchain to another. Ahora, vamos a implementar un contrato que envía un mensaje y un token de un cadena de bloque a otro. + +## General + +Este contrato debería parecer bastante familiar. Al igual que la sección anterior, el `constructor` recibe las direcciones `Gateway` y `Gas Service`. + +Posteriormente tiene una función que será llamada desde la cadena fuente llamada `sendToMany` que toma parámetros similares a la sección anterior. + +1. `_destinationChain`: La cadena a la que la transacción está enviando +2. `_destinationAddress`: La dirección en la cadena de destino en la que se ejecutará esta transacción +3. `_destinationAddresses`: El mensaje que enviarás junto a tu transferencia de token. En este ejemplo, el mensaje es una lista de direcciones receptoras para la transferencia de token. +4. `_symbol`: El símbolo de la dirección del token siendo enviado +5. "amount": La cantidad del token siendo enviado + +En la función ya tenemos la instrucción `require` implementada para asegurar que el gas sea enviado + +También tenemos la funcionalidad básica ERC20 para enviar el token desde la cartera de llamadas a este contrato inteligente. The contract also calls the `approve` function to allow the Gateway to eventually transfer funds on its behalf. + +Finalmente, la función `_executeWithToken()` también se implementa desde la caja. + +Utiliza los siguientes parámetros: + +1. `_payload`: El mensaje entrante de la cadena fuente +2. `_tokenSymbol`: El símbolo del token que fue enviado desde la cadena origen +3. `_amount`: La cantidad del token que fue enviado desde la cadena origen + +Ahora con estos parámetros pasados, la función `_execute()` puede enviar los tokens que fueron enviados a los receptores apropiados. + +## Desafio + +Tu desafío aquí es terminar la función `sendToMany()` usando el servicio Axelar Puerta de Enlace y el servicio Gas para desencadenar una transacción de intercadena. + +Al final debería ser capaz de implementar este contrato en dos redes de pruebas, activa la función `sendToMany()` y ve la transacción en vivo en Axelarscan (testnet) block explorer. + +### Probando Notas + +Nota 1: El ERC20 recomendado para usar es `aUSDC` una versión envuelta del token USDC que puede obtenerse de the discord faucet bot. Al activar la función `sendToMany()` simplemente pasa el símbolo `aUSDC` al cuarto parámetro. + +Nota2: Al activar la función `sendToMany()` debes recordar `approve` tu contrato para gastar los tokens `aUSDC` en tu nombre, de lo contrario `transferFrom()` en la línea 49 arrojará un error. diff --git a/locales/es/Interoperability/7_FurtherReading/furtherReading.md b/locales/es/Interoperability/7_FurtherReading/furtherReading.md new file mode 100644 index 000000000..517055cf6 --- /dev/null +++ b/locales/es/Interoperability/7_FurtherReading/furtherReading.md @@ -0,0 +1,11 @@ +¡Felicitaciones por llegar al final del módulo de interoperabilidad! 🎉🎉 + +Para continuar con tu aprendizaje de interoperabilidad con Axelar. There are many useful resources available. + +- Para documentation 📚 + +- Para more technical examples 💻 + +- Para live coding demos 📹 + +- Para the developer blog 📝 diff --git a/locales/es/Interoperability/README.md b/locales/es/Interoperability/README.md new file mode 100644 index 000000000..1eaf563df --- /dev/null +++ b/locales/es/Interoperability/README.md @@ -0,0 +1,3 @@ +## Interoperabilidad entre las cadenas de bloques + +Aprende cómo construir contratos inteligentes interoperables que pueden enviar mensajes y activos entre diferentes blockchains usando tecnología Axelli. diff --git a/locales/es/Interoperability/config.yml b/locales/es/Interoperability/config.yml new file mode 100644 index 000000000..39f1be7ed --- /dev/null +++ b/locales/es/Interoperability/config.yml @@ -0,0 +1,31 @@ +--- +id: interopCourse +name: Multichain Protocols with Axelar +summary: Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. +level: 2 +tags: + - Solidity + - Interoperability + - Axelar +steps: + - + name: An Intro to Axelar + path: 1_Intro + - + name: Axelar Gateway + path: 2_Gateway + - + name: Axelar Gas Service + path: 3_GasService + - + name: Axelar Executable + path: 4_Executable + - + name: Interchain Messages + path: 5_InterchainMessage + - + name: Interchain Token Transfers + path: 6_InterchainTokenTransfer + - + name: Further Reading + path: 7_FurtherReading diff --git a/locales/es/Multisig-Tutorial/1-multisig-introduction/introduction.md b/locales/es/Multisig-Tutorial/1-multisig-introduction/introduction.md new file mode 100644 index 000000000..f324b52e1 --- /dev/null +++ b/locales/es/Multisig-Tutorial/1-multisig-introduction/introduction.md @@ -0,0 +1,41 @@ +¡Bienvenido al curso de Monedero Multifirma! En esta sección, exploraremos los fundamentos de las billeteras Multifirma (Multisig) y pasaremos por un contrato de monedero multisig. + +## ¿Qué es una cartera multifirma? + +Una cartera multifirma (multifirma) es un tipo de cartera digital que requiere varias claves para autorizar una transacción de criptomonedas. + +Imagina una cartera multifirma como una bóveda segura con múltiples bloqueos. To open the vault, each keyholder must open their individual lock. Esta configuración asegura que ninguna persona puede acceder a los contenidos de la bóveda sin el consentimiento de los demás. + +## ¿Cómo funciona una Cartera Multifirma Multisig? + +En una configuración multifirma, cada transacción debe recibir un número predeterminado de aprobaciones de un grupo determinado de personas. Por ejemplo, en una configuración de cartera 3-de-5, hay cinco direcciones autorizadas, pero una transacción solo se realiza cuando al menos tres de ellas dan su aprobación. Cuando se inicia una transacción, se presenta como una **propuesta** al grupo. Cada miembro que está de acuerdo con la transacción, utiliza su clave privada para firmarla digitalmente. + +Estas **firmas digitales** son únicas y se generan a partir de la combinación de los datos de la transacción y la clave privada. + +Cuando se alcanza el número necesario de firmas, la transacción se transmite a la cadena de bloques para su ejecución. + +## ¿Por qué utilizar una Cartera Multifirma? + +Las carteras multifirma son cruciales para mejorar la seguridad en las transacciones de criptomonedas. Mitigan el riesgo de robo o pérdida de una sola clave. En las empresas, las carteras multifirma, se utilizan para garantizar que los fondos no puedan moverse sin el consenso de las partes interesadas. Por ejemplo, en una empresa que gestiona activos en criptomoneda, una cartera multifirma podría requerir que el director financiero, el director general y un miembro de consejo de administración aprueben todas las transacciones importantes, protegiendo así contra el fraude interno o los hackeos externos. + +## Conclusión + +En esta sección, aprendimos que una cartera multifirma (multisig) requiere múltiples claves (llaves) para autorizar una transacción de criptomoneda propuesta y que una multifirma mitiga el riesgo de robo o pérdida de una sola clave (llave). + +## Asignación: Prueba de Elección Múltiple + +### 1. ¿Qué es una Cartera Multifirma? + +1. Una cartera digital que requiere una única firma para las transacciones. +2. Una cartera digital que requiere múltiples firmas para las transacciones. +3. Una cartera física utilizada para almacenar criptomonedas. +4. Una cartera que solo puede contener varios tipos de criptomonedas. + +### 2) ¿Cómo mejora la seguridad una Cartera Multifirma? + +1. Al exigir una única clave privada para las transacciones. +2. Al distribuir la aprobación de las transacciones entre varios propietarios. +3. Al almacenar los datos de las transacciones en la cadena. +4. Ninguna de las anteriores. + +Tómese su tiempo y responda a las preguntas anteriores. Una vez que esté dispuesto, pasaremos a explorar el contrato inteligente Multifirma (Multisig) y daremos a entender su estructura. diff --git a/locales/es/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md b/locales/es/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md new file mode 100644 index 000000000..0752d2911 --- /dev/null +++ b/locales/es/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md @@ -0,0 +1,60 @@ +En esta sección, exploraremos el **proceso de inicialización** del contrato inteligente multifirma. Examinaremos la función constructora y repasaremos cómo se configura el estado inicial del contrato. + +## Nota + +A partir de esta sección en este tutorial, iremos construyendo un contrato multifirma. En las secciones posteriores, el contrato se completará cada vez más. + +## General + +En esta sección, el contrato consiste en eventos, variables de estado, modificadores y funciones. **Eventos** proporcionan transparencia al registrar las actividades especificadas en la cadena de bloques, mientras que **modificadores** se aseguran de que sólo los usuarios autorizados puedan ejecutar ciertas funciones. + +## Variables de la escena + +En la línea 4, tenemos el contrato MultisigWallet propiamente dicho. Al principio del contrato, tenemos tres variables estatales. + +1. **`owners`:** Una matriz que contiene las direcciones de todos los propietarios de la cartera multifirma (línea 5). +2. **`isOwner`:** Un mapeo que indica si una dirección es un propietario (Linea 6). +3. **`numConfirmationsRequired`:** El número de confirmaciones requeridas para una transacción (Linea 7). + +La configuración de mapeo y mapeo nos permite recuperar fácilmente la lista de propietarios y verificar si una dirección es propietaria. + +## Modificadores + +A continuación, tenemos un modificador llamado `onlyOwner` (línea 9). Los modificadores en Solidity son palabras clave especiales que pueden ser usadas para enmendar el comportamiento de las funciones. En nuestro caso, el modificador `onlyOwner` asegura que sólo los propietarios pueden ejecutar una función. Esto lo hace comprobando si la dirección del **llamador** es un propietario. + +## Función Constructor + +La función `constructor` (Line 14) se ejecuta sólo una vez durante el despliegue del contrato. Inicializa parámetros esenciales, en este caso, la lista de propietarios y el número requerido de confirmaciones (Línea 14). + +En las líneas 15 y 16, tenemos dos sentencias `require` para asegurar que las entradas sean válidas. En este caso exigimos que haya al menos un propietario y que el número de confirmaciones requeridas sea mayor que cero y menor o igual que el número de propietarios. + +El constructor entonces inicializa el estado del contrato verificando que no es address(0) (Línea 25) y que el propietario es único (Línea 26). Luego añade un par clave/valor al mapeo isOwner (línea 28), y luego rellena la matriz `owners` con las direcciones del propietario proporcionadas (Linea 29). + +Por último, establece la variable `numConfirmationsRequired` con el valor especificado (línea 32). + +## función getOwners + +La función `getOwners` (línea 36) permite a los usuarios recuperar la lista de propietarios de la cartera multifirma. Devuelve el conjunto `owners` (Línea 37). + +## función getNumConfirmationsRequired + +La función `getNumConfirmationsRequired` (línea 41) permite a los usuarios recuperar el número de confirmaciones necesarias para una transacción. Devuelve la variable `numConfirmationsRequired` (Línea 42). + +## Conclusión + +En esta sección, exploramos el proceso de inicialización del contrato inteligente Multisig. Examinamos la función del constructor y entendimos cómo establece el estado inicial del contrato. + +## ⭐ Tarea: Desplegar una cartera multifirma + +Implemente un contrato Multifirma con tres propietarios y requiera dos confirmaciones para la ejecución de la transacción. + +1. Compilar contractInitialization.sol +2. Ir a Desplegar y Correr transacciones en Remix. +3. Expandir la sección "Desplegar". +4. Bajo "_OWNERS", introduzca tres, un arreglo de tres direcciones. +5. Bajo "_NUM_CONFIRMATIONS_REQUIRED", introduzca el número de confirmaciones requeridas para una transacción. + +**Sugerencias:** + +- Puede obtener direcciones del menú desplegable "CUENTAS". +- El conjunto de direcciones debe estar en el formato: ["0x123...", "0x456...", "0x789..."]. diff --git a/locales/es/Multisig-Tutorial/3-multisig-deposits/deposits.md b/locales/es/Multisig-Tutorial/3-multisig-deposits/deposits.md new file mode 100644 index 000000000..0e0cec5bd --- /dev/null +++ b/locales/es/Multisig-Tutorial/3-multisig-deposits/deposits.md @@ -0,0 +1,34 @@ +En esta sección, exploraremos a la función `receive` y el evento Deposit asociado. Examinaremos cómo se utiliza la función 'receptor' para depositar a Ether en la cartera multifirma y cómo el evento Deposite proporciona transparencia. + +## Evento Deposit + +En la línea 9 tenemos el evento Deposit. El evento Deposit se emite cada vez que se deposita Ether en la cartera multifirma. Incluye tres parámetros: + +1. `sender`: La dirección que envió el Éter. +2. `amount`: La cantidad de Ether depositada. +3. `balance`: El saldo actualizado del contrato después del depósito. + +Podemos usar el evento Deposit para rastrear el flujo de Ether hacia la cartera multifirma y tal vez activar otras acciones basadas en el evento. + +## Función receive + +En la línea 43, tenemos la función `receive`. La función `receive` es una función especial que se ejecuta cada vez que Ether se envía al contrato. + +La función `receive` se marca como `external` y `payable`. El modificador `external` significa que la función sólo puede llamarse desde fuera del contrato. El modificador `payable` significa que la función puede recibir Ether. + +La función 'receive' emite el evento Deposit (Línea 44) con la dirección del emisor, la cantidad de Ether enviada y el saldo actualizado del contrato. Esta no devuelve nada. + +Para recibir a Ether, un contrato debe tener un `receive`, `fallback` o una función con el modificador `payable`. Si ninguno de ellos está presente, el contrato rechazará cualquier Ether que se le envíe. + +## Conclusión + +En esta sección, exploramos la función `receive` y el evento Deposit asociado. Examinamos cómo se utiliza la función 'receive' para depositar a Ether en la cartera multifirma y cómo el evento Deposit proporciona transparencia. + +## Asignación: Depositar Ether + +Deposite 2 Ether en el contrato Multifirma (Multisig). + +1. Despliegue el contrato Multifirma como en la asignación anterior. +2. Introduzca un valor de 2 Ether en el campo Valor y seleccione Ether en el menú desplegable. +3. En la parte inferior de su contrato desplegado, en la sección de "Interacciones de bajo nivel", haga clic en el botón "Transact". +4. En la parte superior de su contrato desplegado, ahora debería decir "Balance: 2 Ether". diff --git a/locales/es/Multisig-Tutorial/4-multisig-transactions/transactions.md b/locales/es/Multisig-Tutorial/4-multisig-transactions/transactions.md new file mode 100644 index 000000000..b80d56be2 --- /dev/null +++ b/locales/es/Multisig-Tutorial/4-multisig-transactions/transactions.md @@ -0,0 +1,73 @@ +En esta sección, exploraremos el proceso de envío y confirmación de transacciones. + +## Modificadores + +Tenemos nuevos modificadores en esta iteración del contrato. Examinémoslos uno por uno. + +1. **Modificador `txExists`:** (Línea 13) asegura que la transacción exista. Para ello, comprueba si el índice de transacciones es menor que la longitud de la matriz `transacciones`. Hablaremos más sobre este modificador más adelante en esta sección. +2. **Modificador `notExecuted`:** (Línea 18) asegura que la transacción no haya sido ejecutada. Hace esto verificando si la variable `executed` de la transacción es falsa. +3. **Modificador `notConfirmed`:** (línea 23) asegura que la transacción no ha sido confirmada por el invocaaador. Hace esto comprobando si el mapeo `isConfirmed` del índice de transacción y la dirección del invocador es falso. + +## Estructura de la Transacción + +En línea 28, tenemos una estructura llamada `Transaction`. Almacenamos a los miembros de la estructura: `to`, `value`, `data`, `executed` y `numConfirmations` en variables individuales. + +## Mapeo de Confirmaciones + +En la línea 37, tenemos un mapeo llamado `isConfirmed`. Este mapeo se utiliza para hacer un seguimiento de las confirmaciones de cada transacción. Asigna el índice de la transacción a un mapeo de una dirección de propietario a un valor booleano. El valor booleano indica si este propietario ha confirmado la transacción. + +## Arreglo de transacciones + +En la línea 39, tenemos un arreglo llamado `transacciones`. El conjunto se utiliza para almacenar todas las transacciones enviadas a la cartera multifirma. + +## Eventos + +Tenemos cuatro nuevos eventos en esta iteración del contrato: + +1. **Evento `SubmitTransaction`:** emitido cada vez que se envía una transacción a la cartera multifirma. +2. **Evento `ConfirmTransaction`:** emitido daca vez que una transacción es confirmada por un propietario. +3. **Evento `RevokeConfirmation`:** emitido cada vez que un propietario revoca la confirmación de una transacción. +4. **Evento `ExecuteTransaction`:** emitido cada vez que se ejecuta una transacción. + +## Función submitTransaction + +La función `submitTransaction` (Línea 78) permite a los usuarios enviar una transacción a la cartera multifirma. Se toman tres parámetros: `to`, `value` y `data`. El parámetro `to` es la dirección del destinatario de la transacción. El parámetro `value` es la cantidad de Ether a ser enviado. El parámetro `data` es los datos que se enviarán al destinatario. Solo los propietarios pueden enviar transacciones. + +En línea 85, creamos una nueva estructura de transacción y la introducimos en el arreglo `transactions` y emitemos el evento `SubmitTransaction`. La variable `txIndex` se utiliza para hacer un seguimiento del índice de transacción. + +## Función confirmTransaction + +La función `confirmTransaction` (Línea 98) permite a los usuarios confirmar una transacción. Toma un parámetro: `txIndex`. +Tiene tres modificadores: `onlyOwner`, `txExists` y `notExecuted`. El modificador `onlyOwner` asegura que solo los propietarios puedan confirmar las transacciones. El modificador `txExists` asegura que la transacción exista. El modificador `notExecuted` asegura que la transacción no haya sido ejecutada. + +En la línea 101, guardamos la transacción en una variable local llamada `transaction`. A continuación incrementamos la variable `numConfirmations` de la transacción y establecemos el mapeo `isConfirmed` del índice de la transacción y la dirección del invocador a true. Finalmente, emitimos el evento `ConfirmTransaction`. + +## Función executeTransaction + +La función `executeTransaction` (Line 108) permite a los usuarios ejecutar una transacción. En la línea 113, requerimos que el número de confirmaciones de la transacción sea mayor o igual al número requerido de confirmaciones. Luego establecemos la variable `executed` de la transacción a true. Finalmente, envía los fondos usando la función `call`. Esta es la `call` de la dirección del destinatario con el valor y los datos de la transacción. Si la transacción tiene éxito, emitimos el evento `ExecuteTransaction`. + +## Función getTransactionCount + +La función `getTransactionCount` (Línea 132) permite a los usuarios recuperar el número de transacciones en la cartera multifirma. Devuelve la longitud del arreglo `transactions`. + +## Función getTransaction + +La función `confirmTransaction` (Línea 136) permite a los usuarios confirmar una transacción. Devuelve los miembros de la estructura de transacciones que exploramos anteriormente en esta sección. + +## Cierre + +En esta sección, sondeamos el proceso de envío, confirmación y ejecución de transacciones. Hemos examinado las funciones `submitTransaction`, `confirmTransaction` y `executeTransaction` y hemos entendido cómo trabajan juntas para permitir que varios usuarios envíen y confirmen las transacciones. + +## Asignación: Realizar una transacción + +Envíe, confirme y ejecute una transacción para enviar 2 Ether a la primera cuenta del menú desplegable "CUENTAS". + +1. Despliegue el contrato Multifirma (Multisig) como en la tarea anterior. Asegúrese de que el número requerido de confirmaciones es 2. +2. Financia el multifirma desde cualquier dirección enviando a 4 Ether como hiciste en la asignación anterior. +3. Pruebe enviar 2 Ether a la primera cuenta del menú desplegable "CUENTAS". Una vez que haya enviado esta transacción (con la transacción), haz clic en `getTransactionCount` y debería ver una transacción o puede hacer clic en `getTransaction`, insertar 0 como el índice de transacción y ver la transacción que acaba de enviar. +4. Ahora puedes hacer clic en `confirmTransaction` e insertar 0 como el índice de transacción. Si haces clic en `getTransaction` de nuevo, deberías ver que la transacción ha sido confirmada una vez. +5. Cambiar a la segunda cuenta de propietario y confirma la transacción de nuevo. Si vuelves a hacer clic en `getTransaction`, deberías ver que la transacción se ha confirmado dos veces. +6. El ultimo paso es ejecutar la transacción. Haz clic en `executeTransaction` e inserte 0 como índice de la transacción. Si vuelves a hacer clic en `getTransaction`, deberías ver que la transacción se ha confirmado dos veces. También puede comprobar el balance de la primera cuenta en el menú desplegable "CUENTAS". Ahora debería tener 2 Ether más y el saldo de la cartera multifirma debería tener 2 Ether menos. + +**Pista:** +Si envías una transacción, asegúrese de que el valor está en Wei y de que el campo _data está correctamente rellenado. Por ejemplo, podría verse así: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 20000000000000000, 0x" para 2 Ether. diff --git a/locales/es/Multisig-Tutorial/5-multisig-revoke/revoke.md b/locales/es/Multisig-Tutorial/5-multisig-revoke/revoke.md new file mode 100644 index 000000000..b663e7200 --- /dev/null +++ b/locales/es/Multisig-Tutorial/5-multisig-revoke/revoke.md @@ -0,0 +1,30 @@ +En esta sección, exploraremos el proceso de revocación de confirmaciones. Este proceso es necesario cuando un propietario cambia de opinión sobre una transacción y quiere impedir que se ejecute. Esta transacción será bastante simple. + +## Evento revokeConfirmation + +En la línea 14, hemos añadido el evento `RevokeConfirmation`. Este evento se emite cada vez que un propietario revoca la confirmación de una transacción. + +## Función revokeConfirmation + +En la línea 129, hemos añadido la función `revokeConfirmation`. Esta permite a los usuarios revocar la confirmación de una transacción. + +`revokeconfirmation` toma un parámetro: `txIndex`. Tiene tres modificadores: `onlyOwner`, `txExists` y `notExecuted`. + +En la línea 134, requerimos que la transacción haya sido confirmada por la persona que llama. Esto garantiza que un propietario que haya confirmado la transacción solo pueda revocar su propia confirmación. +Luego decrementamos la variable "numConfirmations" de la transacción y establecemos la asignación "isConfirmed" del índice de transacciones y la dirección de la persona que llama en false. Finalmente, emitimos el evento "RevokeConfirmation". + +## Conclusión + +En esta sección, exploramos el proceso de revocación de confirmaciones. Examinamos la función "revokeConfirmation" y entendimos cómo funciona para permitir a los usuarios revocar las confirmaciones. + +## ⭐️ Asignación: Revocar una confirmación + +Confirme y revoque una transacción para enviar 2 Ether a la primera cuenta en el menú desplegable "CUENTAS". + +1. Al igual que en la asignación anterior, implemente el contrato Multisig, envíe al contrato un poco de Ether y luego envíe una transacción a la primera cuenta en el menú desplegable "CUENTAS" con un valor de 2 Ether. +2. Confirme la transacción el doble que en la asignación anterior. +3. Revoque la transacción haciendo clic en "revocar confirmación" e insertando 0 como índice de transacción. Si vuelve a hacer clic en "getTransaction", debería ver que la transacción se ha confirmado una vez. + +## Conclusión final + +En este tutorial, exploraremos el proceso de creación de una cartera multifirma. Aprendimos a iniciar el contrato, depositar Ether, enviar, confirmar y revocar transacciones. También aprendimos a ejecutar transacciones y recuperar información sobre la cartera multifirma. diff --git a/locales/es/Multisig-Tutorial/README.md b/locales/es/Multisig-Tutorial/README.md new file mode 100644 index 000000000..92600a3b1 --- /dev/null +++ b/locales/es/Multisig-Tutorial/README.md @@ -0,0 +1,5 @@ +## Billetera multifirma + +Aprende a escribir un contrato inteligente de MultiSig Wallet en Ethereum. + +Desarrollado por la plataforma de aprendizaje p2p https://dacade.org. diff --git a/locales/es/Multisig-Tutorial/config.yml b/locales/es/Multisig-Tutorial/config.yml new file mode 100644 index 000000000..067de0fb9 --- /dev/null +++ b/locales/es/Multisig-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: multisigCourse +name: Multisig Wallet +summary: Learn how to create and interact with a multisig wallet. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - Multisig +steps: + - + name: 1. Introduction + path: 1-multisig-introduction + - + name: 2. Initialize the Contract + path: 2-multisig-initialization + - + name: 3. Deposits + path: 3-multisig-deposits + - + name: 4. Transactions + path: 4-multisig-transactions + - + name: 5. Revoking Confirmations + path: 5-multisig-revoke diff --git a/locales/es/NFTTokenCourse/README.md b/locales/es/NFTTokenCourse/README.md new file mode 100644 index 000000000..665426a1a --- /dev/null +++ b/locales/es/NFTTokenCourse/README.md @@ -0,0 +1,5 @@ +## Curso de Solidity NFT + +Aprende a crear tus propios NFT (tokens no fungibles). + +Desarrollado por la plataforma de aprendizaje p2p https://dacade.org. diff --git a/locales/es/NFTTokenCourse/config.yml b/locales/es/NFTTokenCourse/config.yml new file mode 100644 index 000000000..af82db834 --- /dev/null +++ b/locales/es/NFTTokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: nftTokenCourse +name: Solidity NFT Course +summary: Learn how to create your own NFT tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc721-interface + - + name: 3. Metadata Interface + path: erc721-interface-metadata + - + name: 4. Token Creation + path: erc721-token-creation + - + name: 5. Metadata IPFS + path: erc721-metadata-ipfs + - + name: 6. Deploy to Testnet + path: erc721-deploy-testnet-opensea diff --git a/locales/es/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md b/locales/es/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md new file mode 100644 index 000000000..49985f48e --- /dev/null +++ b/locales/es/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md @@ -0,0 +1,50 @@ +En esta sección, usaremos Metamask (una cartera de Ethereum) para implementar nuestro contrato en la red de pruebas Rinkeby de la cadena de bloques de Ethereum, acuñar un NFT y verlo en el mercado NFT OpenSea. + +### 1. Instalar Metamask + +**1.1** Ir a metamask.io. + +**1.2** Haga clic en el botón de descarga, luego haga clic en instalar para su navegador (por ejemplo, Chrome) y agregue la extensión a su navegador. + +**1.3** Crea una cartera como se describe. + +### 2. Obtener token de red de prueba para Rinkeby + +Para realizar transacciones en la testnet, necesitamos tokens de Ethereum testnet. + +**2.1** Cambia tu metamáscara de "Ethereum Mainnetwork" a "Rinkeby Test Network". + +**2.2** Vaya a https://faucet.paradigm.xyz/, introduzca la dirección de su cuenta y reclame testnet ETH. +También puedes usar otros grifos de ropsten como https://faucet.paradigm.xyz/ o https://app.mycrypto.com/faucet. Eche un vistazo a los grifos que aparecen en ethereum.org para obtener más información. + +### 3. Despliegue de Contrato + +**3.1** En el módulo "DEPLOY & RUN TRANSACTIONS" del Remix IDE en "ENVIRONMENT", seleccione "Injected Web3". Luego debería pedirle que conecte su cuenta, lo que debe confirmar. Entonces deberías ver la insignia de la red Rinkeby en "Inyected Web3". + +**3.2** Implemente su contrato de token y confirme la transacción en Metamask. + +**3.3** Su contrato debe aparecer en la sección "Contratos desplegados". + +### 4. Acuñe un NFT + +**4.1** Amplíe su contrato en el IDE para que pueda ver los botones de las funciones. + +**4.2** Expande los campos de entrada junto al botón safeMint. Introduzca la dirección de Ethereum de la cuenta que está conectada a Remix en el campo de entrada "a:". Introduzca "0" en el campo de entrada "tokenID:". Haga clic en transacción. + +**4.3** En Metamask, haga clic en los activos, luego haga clic en el enlace "Importar tokens" y pegue la dirección de su contrato en el campo de entrada. Puedes poner los decimales a 0. + +Ahora debería ver el nombre del símbolo de su contrato de token (por ejemplo, GEO) en su vista "Activos" en MetaMask. Debería tener una de estas fichas. + +### 5. Vea su NFT en OpenSea + +OpenSea es uno de los mercados en línea más populares de NFTs. OpenSea también ofrece una versión en la que se pueden ver los activos en la red de pruebas, en https://testnets.opensea.io + +**5.1** Vaya a https://testnets.opensea.io/login. + +**5.2** Conecte con su cartera de MetaMask. Debería ser redirigido a la vista de su cuenta https://testnets.opensea.io/account en Opensea, donde debería poder ver su NFT. Debería ver la imagen de su NFT; al hacer clic en ella, debería ver el nombre, la descripción y, en propiedades, también los atributos que ha creado. + +Si ha completado con éxito este curso y está familiarizado con los fundamentos del desarrollo en Solidity, le animamos a que continúe su viaje de aprendizaje aprendiendo a crear su propio contrato de subasta NFT a partir de los recursos de Learneth. diff --git a/locales/es/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md b/locales/es/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md new file mode 100644 index 000000000..c2951e609 --- /dev/null +++ b/locales/es/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md @@ -0,0 +1,61 @@ +La extensión de metadatos es opcional. Nos permite añadir información adicional a nuestros tokens ERC721. Podemos especificar un nombre, un símbolo y un URI (Identificador Uniforme de Recursos) que puede apuntar a un archivo donde podemos agregar aún más información en forma de JSON. + +## Funciones de metadatos ERC721 + +### nombre + +La función "nombre" (línea 16) devuelve el nombre de la colección de tokens. Una colección de tokens significa todos los tokens creados con la implementación de su contrato de tokens ERC721. Cada token de esta colección tendrá este nombre, independientemente de su tokenId. + +### símbolo + +La función "símbolo" (línea 21) devuelve el símbolo de la colección de tokens. + +### tokenURI + +La función `tokenURI` (línea 26) devuelve el URI del token con el id `tokenId`. En este caso, no es el URI de toda la colección, sino de un token individual en la colección. + +## Esquema JSON de metadatos ERC721 + +El archivo al que apunta el tokenURI debe ajustarse al esquema JSON de metadatos tal y como se especifica en el EIP-721. + +``` +{ + +"Título": "Metadatos de activos", + +"Tipo": "objeto", + +"Propiedades": { + +"Nombre": { + +"Tipo": "cadena", + +"Descripción": "Identifica el activo al que representa este NFT" + +}, + +"Descripción": { + +"Tipo": "cadena", + +"Descripción": "Describe el activo al que representa este NFT" + +}, + +"Imagen": { + +"Tipo": "cadena", + +"Descripción": "Un URI que apunta a un recurso con una imagen de tipo mimo/* que representa el activo al que representa este NFT. Considere la posibilidad de hacer cualquier imagen con un ancho entre 320 y 1080 píxeles y una relación de aspecto entre 1,91:1 y 4:5 inclusive". + +} + +} + +} +``` + +El elemento raíz debe ser del tipo de objeto. Este objeto raíz debe tener propiedades con las claves: nombre, descripción e imagen que deben ser toda la cadena de tipo. + +El estándar ERC721 es bastante flexible, el tokenURI no necesita apuntar a un documento JSON y el JSON no necesita tener todas las propiedades y a menudo tiene propiedades adicionales. diff --git a/locales/es/NFTTokenCourse/erc721-interface/erc721Interface.md b/locales/es/NFTTokenCourse/erc721-interface/erc721Interface.md new file mode 100644 index 000000000..46dfbf943 --- /dev/null +++ b/locales/es/NFTTokenCourse/erc721-interface/erc721Interface.md @@ -0,0 +1,100 @@ +ERC721 es un estándar para los contratos de tokens que gestionan tokens no fungibles (NFT) en la cadena de bloques de Ethereum. + +Cada token no fungible es único y no es intercambiable. Los NFT pueden tener diferentes propiedades, comportamientos o derechos. Los tokens no fungibles se utilizan para representar la propiedad de activos digitales y físicos únicos como arte, objetos de colección o bienes raíces. + +Si desea saber más sobre el estándar de tokens ERC721, eche un vistazo a las especificaciones en su Propuesta de mejora de Ethereum. + +## Interfaz + +El estándar ERC721 es más complejo que el estándar ERC20 y cuenta con extensiones opcionales. Los contratos que cumplen con ERC721 deben, como mínimo, implementar las interfaces ERC721 y ERC165, que examinaremos en esta sección. + +Esta interfaz (línea 11) forma parte de la biblioteca de contratos de código abierto proporcionada por OpenZeppelin. + +## Funciones básicas de IERC721 + +Los contratos que cumplen con el estándar ERC721 tienen que implementar las siguientes funciones: + +### balanceOf + +La función "balanceOf" (línea 30) devuelve la cantidad de tokens propiedad de la cuenta con la dirección "propietario". + +### ownerOf + +La función `ownerOf` (línea 39) devuelve la dirección `owner` de la cuenta que contiene el token con el id `tokenId`. + +### safeTransferFrom + +La función `safeTransferFrom` (línea 55) transfiere la propiedad de un token con el id `tokenId` desde la cuenta con la dirección `from` a la cuenta con la dirección `to`. + +La función `safeTransferFrom` (línea 137) es casi idéntica a la función `safeTransferFrom` (línea 55). La única diferencia es que esta función tiene un "datos" de carga útil no vacía. + +Un contrato inteligente debe implementar la interfaz ERC721TokenReceiver si va a recibir una transferencia. Esto garantizará que el contrato pueda manejar las transferencias de tokens ERC721 y evitar que los tokens se bloqueen en un contrato que no puede. + +### transferFrom + +La función `transferFrom` (línea 55) transfiere la propiedad de un token con el id `tokenId` de la cuenta con la dirección `from` a la cuenta con la dirección `to`. + +\*\*Se recomienda usar safeTransferFrom en lugar de transferFrom siempre que sea posible. \*\* +La función "transferFrom" no es segura porque no comprueba si el contrato inteligente que es el destinatario de la transferencia ha implementado la interfaz ERC721TokenReceiver y es capaz de manejar los tokens ERC721. + +## Funciones avanzadas de IERC721 + +### approve + +La función "approve" (línea 94) le da a la cuenta con la dirección "a" el permiso para administrar el token con el id "tokenId" en nombre de la cuenta que llama a la función. + +### getApproved + +La función `getApproved` (línea 103) devuelve la dirección de la cuenta (return var `operator`) que está aprobada para administrar el token con el id `tokenId`. + +### setApprovalForAll + +La función `setApprovalForAll` (línea 115) establece el permiso (`_approved`) para la cuenta con la dirección especificada (input param - `operator`) para administrar todos los tokens de la cuenta que llama a la función. + +### isApprovedForAll + +La función "getApproved" (línea 103) devuelve el booleano verdadero si la cuenta con la dirección "operador" está aprobada para administrar todos los tokens de la cuenta con la dirección "propietario". + +## Eventos IERC721 + +Los contratos ERC721 también deben emitir los siguientes eventos: + +### Transferir + +El evento "Transferencia" (línea 15) debe emitirse cuando el token con el id `tokenId` se transfiere desde la cuenta con la dirección `from` a la cuenta con la dirección `to`. + +### Aprobación + +El evento "Aprobación" (línea 20) debe emitirse cuando la cuenta con la dirección "propietario" aprueba la cuenta con la dirección "propisador" para administrar el token con el id "tokenId" en su nombre. + +### Aprobación para todos + +El evento `ApprovalForAll` (línea 25) debe emitirse cuando la cuenta con la dirección "propietario" da o elimina el permiso (`_aprobado`) de la cuenta con la dirección "operador" para administrar todos sus tokens. + +## IERC165 + +Además de la interfaz ERC721, los contratos que cumplen con ERC721 también deben implementar la interfaz ERC165. + +Con la implementación de la interfaz ERC165, los contratos pueden declarar el soporte de interfaces específicas. Un contrato que quiere interactuar con otro contrato puede preguntar si el otro contrato es compatible con esta interfaz antes de realizar una transacción, por ejemplo, enviarle tokens que podrían no admitir. + +Nuestra interfaz IERC721 aquí importa (línea 6) y hereda (línea 11) de la interfaz IERC165. + +Así es como se ve la implementación de OpenZeppelins de la interfaz ERC165: + +``` +interfaz IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +Por ejemplo, el identificador ERC165 para la interfaz ERC721 como se especifica en el EIP721 es "0x80ac58cd". Aprenda a calcular un identificador de interfaz y más sobre el ERC165 en su propuesta de mejora. + +## Otras interfaces + +La interfaz IERC721TokenReceiver debe implementarse para aceptar transferencias seguras. + +Hay dos extensiones opcionales para los contratos ERC721 especificadas en el EIP721: + +IERC721Enumerable permite a un contrato publicar su lista completa de tokens y hacerlos detectables. + +IERC721Metadata permite a un contrato asociar información adicional a un token. Tendremos un vistazo más detallado a esto en la siguiente sección. diff --git a/locales/es/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md b/locales/es/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md new file mode 100644 index 000000000..e3a9a57d3 --- /dev/null +++ b/locales/es/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md @@ -0,0 +1,101 @@ +En esta sección, crearemos nuestros metadatos y los almacenaremos de forma descentralizada. + +IPFS (InterPlanetary File System) es una red de igual a igual para almacenar archivos de forma distribuida. Pinata.cloud es un servicio de fijación que permite a los usuarios alojar fácilmente archivos en la red IPFS. + +Queremos alojar nuestras imágenes y los archivos JSON con sus metadatos en IPFS. + +### Crear carpeta de imágenes + +En este ejemplo, crearemos metadatos para tres tokens. Como puedes ver a continuación, creamos tres imágenes que almacenamos en una carpeta. + +``` +geo-img +├── geo_1.png +├── geo_2.png +├── geo_3.png +``` + +### Regístrate en Pinata + +Ahora, queremos alojar estas imágenes en algún lugar para poder señalarlas en los metadatos de nuestros tokens. Hagámoslo de forma descentralizada y usemos Pinata para alojarlos en IPFS. + +Primero necesitas una cuenta en Pinata. Vaya a Pinata.cloud y cree una cuenta. En Pinata puedes subir hasta 1 GB de datos de forma gratuita. + +Una vez que te hayas registrado, deberías estar en la vista del Administrador de Pines. + +Pin Manager Pinata + +### Subir imágenes a IPFS + +Haz clic en el botón de carga y sube la carpeta con tus imágenes. +Una vez que haya cargado su carpeta, debería ver el nombre de su carpeta y el CID (identificador de contenido) asociado a ella. Si el contenido de la carpeta cambia, el CID también cambiará. + +Para acceder a su carpeta en IPFS, introduzca esta dirección "https://ipfs.io/ipfs/" y agregue su CID. Para nuestro ejemplo actual, puede acceder a su carpeta utilizando: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P + +Puede acceder a una imagen específica usando: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png + +### Crear archivos JSON + +Creamos otra carpeta donde almacenamos tres archivos JSON. + +``` +geo-json +├── 0 +├── 1 +├── 2 +``` + +Dentro de los archivos JSON, crea los metadatos para los tokens, como el nombre, la descripción y la imagen. +Para la URL de la imagen, vamos a usar la URL de nuestras imágenes en IPFS. Puede agregar datos adicionales si lo desea; en este ejemplo, hemos añadido algunos atributos únicos para cada token. + +Así es como podría verse el JSON para el primer token: + +``` +{ + "name": "Geometry#0", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png +", + "attributes": [ + { "trait_type": "background", "value": "cyan" }, + { "trait_type": "color", "value": "red" }, + { "trait_type": "shape", "value": "circle" } + ] +} +``` + +Así es como podría verse el JSON para el segundo token: + +``` +{ + "name": "Geometry#1", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_2.png", + "attributes": [ + { "trait_type": "background", "value": "magenta" }, + { "trait_type": "color", "value": "green" }, + { "trait_type": "shape", "value": "square" } + ] +} +``` + +Como se muestra arriba, la carpeta de este ejemplo se llama "geo-json". Dentro de esta carpeta, tenemos tres archivos JSON. +El primer archivo JSON se llama "0", el segundo archivo JSON se llama "1" y el tercer archivo JSON se llama "2". + +Asegúrese de que sus archivos JSON no tengan un final de archivo y tengan el nombre de sus tokensIds correspondientes. +En el administrador de pines de pinata.cloud, haga clic en el botón de carga y cargue la carpeta con sus archivos JSON. + +Para acceder a su carpeta en IPFS, introduzca esta dirección "https://ipfs.io/ipfs/" y agregue su CID. +Para nuestro ejemplo actual, puede acceder a su carpeta utilizando: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp +Esto se convertirá en nuestra Uri base. + +Puede acceder a un archivo JSON específico simplemente agregando una barra diagonal y el tokenId usando: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/0 + +En el contrato, reemplace el baseURI con su propio baseURI. En este ejemplo, la URI base consiste en la URL +"https://ipfs.io/ipfs/", the CID containing the JSON files, and a slash at the end "/". + +Ahora se creará un tokenURI individual para cada token agregando el tokenId a la baseURI, exactamente lo que hicimos manualmente en el ejemplo anterior para acceder al archivo JSON. diff --git a/locales/es/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md b/locales/es/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md new file mode 100644 index 000000000..06924fc4e --- /dev/null +++ b/locales/es/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md @@ -0,0 +1,35 @@ +En este contrato, utilizamos una implementación de contrato de token ERC721 de OpenZeppelin (línea 4). + +Eche un vistazo a su implementación de un contrato ERC721. Además de la funcionalidad especificada en el estándar ERC721, el contrato proporciona funciones adicionales que veremos en un momento. + +## myToken + +Creamos nuestro propio contrato llamado MyToken (línea 7), que hereda (línea 7) la funcionalidad de la implementación del contrato de tokens OpenZepplin `ERC721` y "Ownable\` que importamos (línea 4). Si no recuerdas el módulo de contrato propietario, eche un vistazo a la sección de extensiones de ERC20. + +Esta implementación de ERC721 hace uso de la extensión de metadatos IERC721 que se especifica en el EIP. Nuestro contrato hereda las funciones `name()` y `symbol()` +Y tiene un constructor que permite establecer sus valores durante el despliegue del contrato (línea 8). +En este caso, vamos a usar los valores predeterminados. Nombramos nuestro token igual que el contrato "MyToken"\` y hacemos de "MTK" su símbolo. + +### Base URI + +Con un contrato ERC721, podemos acuñar varios tokens, cada uno con su propio tokenId. Como vimos en la interfaz de metadatos IERC721, cada token puede tener su propio "tokenURI", que normalmente apunta a un archivo JSON para almacenar metadatos como el nombre, la descripción y el enlace de la imagen. +Si un contrato acuña varios tokens, las implementaciones de ERC721 a menudo utilizan el mismo URI como base (`baseURI`) para todos los tokens y solo los diferencian agregando su `tokenId` único al final a través de la concatenación. En la siguiente parte, veremos cómo se ve esto en la práctica. + +En este ejemplo, estamos almacenando nuestros datos en IPFS; más sobre eso en la siguiente sección. Nuestra Uri base es https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/ (línea 11). +A través de la concatenación, el tokenURI para el token con la identificación 0 sería https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/0 , el tokenURI para el token con la identificación 1 sería https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/1, y así sucesivamente. + +Al usar IPFS y se topa con errores de "504 Gateway Time-out", es posible que tenga que esperar y volver a intentarlo hasta que los datos estén disponibles. + +### safeMint + +Con la función safeMint (línea 14) permitimos al propietario crear nuevos tokens con un Id de token dedicado después de la implementación del contrato. +La función safeMint es parte de la implementación ERC721 de OpenZeppelin y nos permite acuñar de forma segura un token con el id `tokenId` a la cuenta con la dirección `to`. Para el control de acceso, utilizamos el modificador "onlyOwner" del módulo de contrato de control de acceso propietario que importamos (línea 5). + +En la siguiente sección, veremos cómo podemos crear y alojar los metadatos para nuestros NFT. + +## ⭐️ Asignación + +1. Renombra tu contrato a "Geometry". +2. Campie el nombre de su token a "Geometry". +3. Cambia el símbolo de tu token a `GEO`. +4. Cambie el `_baseURI` a https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/. diff --git a/locales/es/NFTTokenCourse/introduction/introduction.md b/locales/es/NFTTokenCourse/introduction/introduction.md new file mode 100644 index 000000000..580a95a1b --- /dev/null +++ b/locales/es/NFTTokenCourse/introduction/introduction.md @@ -0,0 +1,63 @@ +En esta sección del curso, te daremos una introducción teórica a los tokens basados en blockchain. + +Los tokens de cadena de bloques son un nuevo bloque tecnológico creado por la tecnología de cadena de bloques (como los sitios web eran para Internet) que permite un Internet descentralizado y propietario (web3). + +### Introducción + +En el contexto de web3, los tokens representan la propiedad. Los tokens pueden representar la propiedad de cualquier cosa: arte, reputación, artículos en un videojuego, acciones de una empresa, derechos de voto o monedas. + +La innovación revolucionaria de la tecnología blockchain es que permite que los datos se almacenen públicamente de una manera inmutable (inmutable). +Esta nueva forma de almacenamiento de datos nos permite realizar un seguimiento de la propiedad y habilitar artículos digitales verdaderamente propietarios por primera vez. + +La tecnología Blockchain se inventó originalmente para realizar un seguimiento de la propiedad de Bitcoin, una moneda digital descentralizada y un token fungible. + +### Tokens fungibles y no fungibles + +Activos como el dinero: Bitcoin o un billete de un dólar, por ejemplo, son fungibles. Fungible significa que todos los activos son iguales y son intercambiables. Los activos como el arte, los coleccionables o las casas no son fungibles; todos son diferentes y no son intercambiables. + +Podemos dividir los tokens en estos dos tipos: tokens fungibles, donde todos los tokens son iguales, y tokens no fungibles (NFT), donde cada token es único. + +### Estándar de tokens + +El comportamiento de un token se especifica en su contrato inteligente (contrato de token). El contrato podría, por ejemplo, incluir la funcionalidad de transferir un token o comprobar su suministro total. + +Si todo el mundo creara sus propios contratos simbólicos con diferentes convenciones de comportamiento y nomenclatura, sería muy difícil para las personas crear contratos o aplicaciones que sean capaces de interactuar entre sí. + +La comunidad de Ethereum ha desarrollado estándares de tokens que definen cómo un desarrollador puede crear tokens que son interoperables (capaces de trabajar con otros) con otros contratos, productos y servicios. Los contratos desarrollados bajo estos estándares deben incluir un cierto conjunto de funciones y eventos. + +Los estándares de tokens más populares son el ERC20 para tokens fungibles y el ERC721 para tokens no fungibles. En este curso, aprenderemos a crear e interactuar con NFT, tokens creados con el estándar de tokens ERC721. + +Si quieres aprender más sobre los tokens fungibles y el estándar de tokens ERC20, echa un vistazo al curso de tokens Learneth ERC20. + +El ERC777 es un estándar de token fungible, como el ERC20, que incluye características más avanzadas como ganchos, a la vez que sigue siendo compatible con ERC20. Obtenga más información sobre el ERC777 en su EIP (Propuesta de mejora de Ethereum). + +El ERC1155 es un estándar multitoken que permite a un solo contrato gestionar diferentes tipos de tokens, como tokens fungibles, no fungibles o semifungibles. +Obtenga más información sobre el ERC1155 en su EIP. + +## ⭐️ Asignación + +Para esta tarea, probaremos sus conocimientos a través de un breve cuestionario. +Asigne el número de la mejor respuesta a las variables "pregunta 1" (línea 5),`question2` (línea 6), `question3` (línea 7) en el contrato `Quiz` (línea 4). + +### Pregunta 1: + +¿Por qué los tokens basados en blockchain son tan revolucionarios? + +1. Porque la gente ahora puede hacer inversiones de forma anónima. +2. Porque representan la propiedad de activos digitales que se pueden poseer y transferir. +3. Porque puedes usar tokens para hacer transacciones sin tener que pagar impuestos. + +### Pregunta 2: + +¿Por qué la comunidad creó estándares de tokens? + +1. Para que la comunidad pueda controlar y aprobar los tokens que se crean. +2. Con el fin de restringir la funcionalidad de los tokens a acciones seguras y no maliciosas. +3. Para que la comunidad pueda crear tokens que sean interoperables con otros contratos, productos y servicios. + +### Pregunta 3: + +Si crearas una aplicación descentralizada para un juego de cartas coleccionables de béisbol en el que cada jugador de béisbol estaría representado por un token, ¿qué estándar de token usarías para escribir el contrato de token? + +1. ERC20 +2. ERC721 diff --git a/locales/es/OpcodesInTheDebugger/1_intro/step.md b/locales/es/OpcodesInTheDebugger/1_intro/step.md new file mode 100644 index 000000000..f5c7179e8 --- /dev/null +++ b/locales/es/OpcodesInTheDebugger/1_intro/step.md @@ -0,0 +1,5 @@ +Este taller tiene como objetivo dar una mejor comprensión de cómo se implementa un contrato. +"SimpleStore" es un contrato muy básico. +Tiene un constructor muy simple, que solo utiliza el primer parámetro `_o` y lo guarda en `s`. + +Usando el depurador, trataremos de ver qué hace el opcode `CODECOPY`. diff --git a/locales/es/OpcodesInTheDebugger/2_memory/step.md b/locales/es/OpcodesInTheDebugger/2_memory/step.md new file mode 100644 index 000000000..082c013d3 --- /dev/null +++ b/locales/es/OpcodesInTheDebugger/2_memory/step.md @@ -0,0 +1,8 @@ +Antes de empezar, solo un recordatorio rápido: + +El tiempo de ejecución de la EVM tiene varios tipos de memoria: + +- `calldata`: Este es el valor de entrada dado a la transacción. +- `pila`: Básicamente, esta es una lista de valores, cada valor tiene un tamaño limitado (32 bytes). +- `memoria`: La memoria se utiliza cuando el **tipo** de valor almacenado es más complejo, como una matriz o una asignación. Esta memoria es **temporal** y se **libera** al final de la ejecución. +- `almacenamiento`: Este es un mapeo, cada valor almacenado se **persiste** y se guarda en cadena. diff --git a/locales/es/OpcodesInTheDebugger/3_codecopy/step.md b/locales/es/OpcodesInTheDebugger/3_codecopy/step.md new file mode 100644 index 000000000..8eb181703 --- /dev/null +++ b/locales/es/OpcodesInTheDebugger/3_codecopy/step.md @@ -0,0 +1,7 @@ +CODECOPY es uno de los muchos códigos de operación ejecutados por la EVM. Echa un vistazo a la lista completa de opcodes en https://ethervm.io/ . + +CODECOPY toma el **código de ejecución** (o parte de él) y lo copia de los "datos de llamada" a la "memoria". + +La implementación de Solidity es: **codecopy(t, f, s)** - copia **s** bytes del código en la posición **f** a la memoria en la posición **t**. + +Cada implementación de contrato utiliza **CODECOPY**. diff --git a/locales/es/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md b/locales/es/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md new file mode 100644 index 000000000..910455651 --- /dev/null +++ b/locales/es/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md @@ -0,0 +1,11 @@ +Volvamos a nuestro contrato. +Por favor, asegúrese de que el "compilador de Solidity" y "Despliegue y ejecute de transacciones" estén activados. + +Alternativamente, puede hacer clic en `Solidity` en la sección `Página de inicio` **Entornos**. + +- Compilar el contrato desde el "compilador de solidity". +- Vaya a `Deploy & Run Transactions` y asegúrese de que `SimpleStore` esté seleccionado el contrato. +- En el cuadro de texto a la derecha de "Desplegar", introduzca un entero positivo. +- Haga clic en `Desplegar`. + +En el siguiente paso, veremos el despliegue en el depurador. diff --git a/locales/es/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md b/locales/es/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md new file mode 100644 index 000000000..feb47905a --- /dev/null +++ b/locales/es/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md @@ -0,0 +1,7 @@ +Desde la terminal Remix, identifique la transacción que implementó el contrato y haga clic en "Depurar" + +En el canalón del editor, ponga un punto de interrupción en la línea `s = _o`, y haga clic en `Saltar al siguiente punto de interrupción` (botón inferior derecho). + +Haga clic en "Entrar en", para moverse a lo largo de los códigos de operación hasta llegar a "SSTORE". + +`SSTORE` es el código de operación para almacenar el valor `_o` en el almacenamiento. Sigamos con el `CODECOPY`. diff --git a/locales/es/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md b/locales/es/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md new file mode 100644 index 000000000..8eb481b9a --- /dev/null +++ b/locales/es/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md @@ -0,0 +1,53 @@ +El objetivo aquí es almacenar el código en la cadena de bloques. El EVM necesita decirle al cliente (geth, paridad) qué parte de los **datos de llamada** almacenar. En este paso, estamos guardando el contrato MINUS su constructor (porque eso se inplmente solo 1 vez) y MINUS el parámetro de entrada no necesita ser almacenado. + +`CODECOPY` es el primer paso: copia el código de bytes a la memoria, luego el cliente de ethereum podrá consumirlo. MUNCH! + +Pero espera... antes de que el cliente pueda **MUNCH** bytecode, necesita una instrucción: un opcode para decirle a MUNCH. ¡`RETURN` es este código! + +Como se indica en la especificación general, al final de la creación del contrato, el cliente (geth, paridad) toma el valor objetivo por el código de operación `RETURN` y **lo persiste** haciéndolo parte del código de bytes desplegado. + +Una vez que estés en el `CODECOPY`, mira los 3 elementos principales de la **pila**: + +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x0000000000000000000000000000000000000000000000000000000000000055` +`2: 0x000000000000000000000000000000000000000000000000000000000000003e` + +\*En tu pila, `1` y `2` pueden ser ligeramente diferentes. La diferencia puede deberse a una versión de compilador diferente. \* + +\*\*Estos son los parámetros para `CODECOPY`. \*\* + +Recuerde: _codecopy(t, f, s)_ - copie **s** bytes del código en la posición **f** a la memoria en la posición **t** + +`0` es el desplazamiento en el que el código copiado debe colocarse en la **memoria**. En este ejemplo, (todos los ceros) el código se copia al principio de la memoria. (**T**) +`1` es el desplazamiento en **calldata** desde donde copiar (**f**) +`2` número de bytes para copiar - (**s**) + +Después de ejecutar `CODECOPY`, (haga clic en el botón _entrar en_) el código copiado debe ser: +`0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c63430005110032` en memoria. **Me referiré a este valor como (X)**. + +Echemos un vistazo al panel **Memoria** del depurador. +El número 0x que di arriba no es lo que verás en el panel **Memoria** - lo que verás es esto: +0x0: 6080604052600080fdfea265627a7a72 ???? R?????? Ebzzr +0x10: 31582029bb0975555a15a155e2cf28e0 1X ?? uUZ??U???? +0x20: 25c8d492f0613bfb5cbf96399f6dbd4e ?????a?????9?m?N +0x30: a6fc9164736f6c634300051100320000 ???dsolcC????2?? +0x40: 00000000000000000000000000000000 ???????????????? +0x50: 000000000000000000000000000000a0 ??????????????? +0x60: 00000000000000000000000000000000 ???????????????? +0x70: 00000000000000000000000000000000 ???????????????? +0x80: 00000000000000000000000000000000 ???????????????? +0x90: 00000000000000000000000000000002 ???????????????? + +El `0x0`, `0x10`, etc. es la posición. El siguiente número es el código de bytes para esa posición. A esto le siguen signos de interrogación y letras y números aparentemente aleatorios. Este es el intento de **Remix** de convertir esto en una cadena. + +Así que si pegamos las primeras cuatro secciones del código de bytes, obtendremos:**0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e0a6fc9164736f6c63430005110032** La última sección - `0x90` tiene 2, que es lo que ingreso para el parámetro de constructores. + +Los datos de entrada del panel **Datos de llamada** son:`0x6080604052348015600f57600080fd5b50604051609338038060938398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe6080604052600080fdfea265627a7a723158029bb097555a15a155e2cf28e025c8d492f0613bf5cbf96399f6dbd4ea6fc9164736f6c6343000511003200000000000000000000000000000000000000000000000002`\*\*Me referiré a este valor como (Y). \*\* + +Esto nos muestra que `(X)` es un subconjunto de los datos de llamada originales `(Y)`: + +`(X)` son datos de llamada sin el parámetro de entrada `000000000000000000000000000000000000000000000000000000000002` (no necesitamos almacenar esto)Y sin el código de constructor `6080604052348015600f5760080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe` que debe ejecutarse solo 1 vez. + +Así que `CODECOPY` extrae el código de bytes de los datos de llamada y lo copia en la memoria. + +Vamos al siguiente paso. diff --git a/locales/es/OpcodesInTheDebugger/7_returnAndStore/step.md b/locales/es/OpcodesInTheDebugger/7_returnAndStore/step.md new file mode 100644 index 000000000..815130ba0 --- /dev/null +++ b/locales/es/OpcodesInTheDebugger/7_returnAndStore/step.md @@ -0,0 +1,16 @@ +# El Opcode RETURN + +Al final del último capítulo, habíamos pasado a un paso después de **CODECOPY** para ver lo que sucedió en la memoria. + +Ahora que se ha ejecutado CODECOPY, estamos en el código de operación `PUSH1 00`. + +`PUSH1 00` prepara la pila para el código de operación `RETURN`. +"RETORNO" es la última parte de este proceso. Es donde se devuelve el código al cliente. + +Empujamos `00` a la pila porque esta es la posición de desplazamiento del código de bytes del contrato en la memoria. + +Ahora podemos llamar al código de operación "RETURN" más importante. + +El **inspector de pila** muestra:`0: 0x0000000000000000000000000000000000000000000000000000000000000000``1: 0x000000000000000000000000000000000000000000000000000000000000000003e` + +Es decir, devuelve al cliente el código de bytes que comienza `0x00` con la longitud `0x3e`. diff --git a/locales/es/OpcodesInTheDebugger/8_findTheOffset/step.md b/locales/es/OpcodesInTheDebugger/8_findTheOffset/step.md new file mode 100644 index 000000000..1f1a5925a --- /dev/null +++ b/locales/es/OpcodesInTheDebugger/8_findTheOffset/step.md @@ -0,0 +1,17 @@ +# Encuentra la compensación ;) + +Y ahora por un ejemplo ligeramente diferente: + +- Compila notSimpleStore.sol +- Implementar el contrato `notSoSimpleStore` +- Asegúrese de tener una implementación exitosa; si no, compruebe que utilizó **el tipo de entrada correcto** en el constructor. +- Vaya al depurador haciendo clic en el botón **depurar** en la transacción de creación (exitosa). +- Encuentre el valor del parámetro de `CODECOPY` que representa el desplazamiento en los datos de llamada desde donde copiar. + +Recuerde: _codecopy(t, f, s)_ - copie **s** bytes del código en la posición **f** a la memoria en la posición **t** + +Si miras en la **pila**, deberías ver que el segundo elemento es:0x00000000000000000000000000000000000000000000000000000000000000083 + +Y este es el **f** de los parámetros de entrada de codecopy. + +### ¡Espero que hayas aprendido una cosa o 2 sobre cómo funcionan los códigos de operación! diff --git a/locales/es/OpcodesInTheDebugger/config.yml b/locales/es/OpcodesInTheDebugger/config.yml new file mode 100644 index 000000000..74a1bf3a1 --- /dev/null +++ b/locales/es/OpcodesInTheDebugger/config.yml @@ -0,0 +1,10 @@ +--- +id: opcodesdebug +name: Opcodes in the Debugger +summary: Using the Debugger, we'll check out what the CODECOPY opcode does and how it is used by the EVM during contract creation. +level: 3 +tags: + - Remix + - Debugging + - EVM + - Opcodes diff --git a/locales/es/ProxyContract/1_Why/step1.md b/locales/es/ProxyContract/1_Why/step1.md new file mode 100644 index 000000000..3ad273d36 --- /dev/null +++ b/locales/es/ProxyContract/1_Why/step1.md @@ -0,0 +1,25 @@ +# Contrato de proxy, también conocido como el despachador + +## ¿Por qué? + +Este es un gran patrón que se utiliza principalmente en **desarrollo de bibliotecas**. + +Ayuda de las siguientes maneras: + +- **Ahorre costos de gas en el momento de la implementación**El propósito de un alto costo de gas es desalentar las operaciones que cuestan mucho para su ejecución y fomentar un código optimizado. + +- Los contratos de proxy son útiles cuando es necesario implementar muchas instancias del mismo contrato porque reducen las duplicaciones en la implementación. + +- \*\*Evite la repetición de código en la cadena de bloques. \*\*Los cálculos pesados son caros porque cada nodo tendrá que realizarlos, esto, por supuesto, ralentiza la red. + +- **Desarrollar contratos actualizables (versionados)** + Cuando se implementa el contrato, es inmutable. Al rediseñar el código en diferentes contratos, es posible permitir actualizaciones lógicas mientras se mantiene el almacenamiento igual. + +## Ejemplo de costo de gas + +Almacenar el código de contrato en el momento de la creación puede costar hasta: + +- 200 \* max_byte_code_length gas +- 200 \* 24576 = 49152004915200 \* 10 gwei = 49152000 gwei = 0.049152 ether = 9 EUR + +vea https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md Para obtener más información sobremax_byte_code_length. diff --git a/locales/es/ProxyContract/2_How/step2.md b/locales/es/ProxyContract/2_How/step2.md new file mode 100644 index 000000000..4a62b40b1 --- /dev/null +++ b/locales/es/ProxyContract/2_How/step2.md @@ -0,0 +1,13 @@ +# ¿Cómo funciona? + +**EIP-7 DelegateCall** opcode permite una ejecución separada en otro contrato mientras se mantiene el contexto de ejecución original. + +Todas las **llamadas de mensajes** del usuario pasan por un **contrato de proxy**. + +El **contrato de proxy** los redirigirá al **contrato lógico**. + +Y cuando necesites **actualizar** la lógica, **solo** implementarás que - **SIN EMBARGO** - la implementación de Proxy seguirá siendo la misma. + +Solo tendrás que actualizar la dirección del contrato de Logic en Proxy. + +El contrato de proxy utiliza **llamadas de delegado** y **ensamblaje de solidez** porque sin él, es imposible devolver cualquier valor de **delegatecall**. diff --git a/locales/es/ProxyContract/3_Delegatecall/step3.md b/locales/es/ProxyContract/3_Delegatecall/step3.md new file mode 100644 index 000000000..3eeb6c83c --- /dev/null +++ b/locales/es/ProxyContract/3_Delegatecall/step3.md @@ -0,0 +1,9 @@ +# Llamada de delegados + +Es una variante especial de una **llamada de mensaje**, que es idéntica a una llamada de mensaje, aparte del hecho de que el código en la dirección de destino se ejecuta en el contexto del contrato de llamada, por lo que **msg.sender** y **msg.value** no cambian sus valores. + +Esto significa que un contrato puede cargar dinámicamente código desde una dirección diferente en tiempo de ejecución. + +El almacenamiento, la dirección actual y el saldo todavía se refieren al contrato de llamada, solo el código se toma de la dirección llamada. + +Por lo tanto, cuando un **Proxy** delega llamadas al contrato de Logic, cada modificación de almacenamiento afectará al almacenamiento del contrato de Logic. diff --git a/locales/es/ProxyContract/4_Generic_proxy_example/step4.md b/locales/es/ProxyContract/4_Generic_proxy_example/step4.md new file mode 100644 index 000000000..f94090fe3 --- /dev/null +++ b/locales/es/ProxyContract/4_Generic_proxy_example/step4.md @@ -0,0 +1,15 @@ +# Un ejemplo básico de proxy genérico + +En el archivo de solidity asociado, **step4.sol**, hay 2 contratos: **ProxyContract** y **LogicContract**. + +Para usar este sistema, primero implementamos el LogicContract. + +Y luego, cuando vamos a implementar el ProxyContract, pasamos la dirección de LogicContract como argumento del constructor del ProxyContract. + +El ProxyContract se implementa únicamente una vez. + +El código de LogicContract se llamará en la línea 20. Se reenviará con una llamada de delegado mientras se mantiene el contexto de LogicContract. + +En caso de que necesitemos cambiar la lógica, desplegaríamos un nuevo LogicContract y estableceríamos la dirección del mismo con la función setter setLogicContractAddress. + +\*Nota: El LogicContract que tenemos aquí no utiliza el almacenamiento. Una vez que necesitas usar el almacenamiento, la implementación se vuelve un poco más complicada porque esos contratos comparten el contexto. \* diff --git a/locales/es/ProxyContract/5_Test/step5.md b/locales/es/ProxyContract/5_Test/step5.md new file mode 100644 index 000000000..f763a0f2e --- /dev/null +++ b/locales/es/ProxyContract/5_Test/step5.md @@ -0,0 +1,6 @@ +# Vamos a probar lo que hemos aprendido + +- Escribe un contrato llamado "LogicContract" que implementa una función pública llamada "getNumber" que devuelve 10 +- Escriba un contrato de representación llamado "ProxyContract". Este ProxyContract debería tomar una dirección de LogicContract como primer parámetro. + +¡Buena suerte! diff --git a/locales/es/ProxyContract/6_Storage_Problem/step6.md b/locales/es/ProxyContract/6_Storage_Problem/step6.md new file mode 100644 index 000000000..6f4423426 --- /dev/null +++ b/locales/es/ProxyContract/6_Storage_Problem/step6.md @@ -0,0 +1,13 @@ +# ¿Qué pasa si tenemos variables de estado? + +Las cosas son más complicadas una vez que tenemos que lidiar con las variables de estado. Las variables de estado se guardan en **almacenamiento**. + +"Almacenamiento": es una asignación; cada valor almacenado allí se persiste y se guarda en cadena. + +_Nota: Las variables de estado de tamaño estático (todo excepto el mapeo y los tipos de matriz de tamaño dinámico) se diseñan de forma contigua en el almacenamiento a partir de la posición 0. Múltiples elementos contiguos que necesitan menos de 32 bytes se empaquetan en una sola ranura de almacenamiento si es posible. Para los contratos que utilizan la herencia, el orden de las variables de estado está determinado por el orden linealizado C3 de los contratos que comienza con el contrato más básico_ + +Una vez que ejecutamos **llamada de delegación**, el almacenamiento de ambos contratos se **"fusiona"** en un solo estado desordenado. + +Tenemos que "decirle" a ProxyContract cómo es el **estado** del **contrato lógico**. + +La forma más fácil de hacer esto es crear un contrato separado, en este ejemplo, llamado **StorageContract** que representará el **estado** y del que proxyContract heredará. diff --git a/locales/es/ProxyContract/7_links/step7.md b/locales/es/ProxyContract/7_links/step7.md new file mode 100644 index 000000000..b69c2039a --- /dev/null +++ b/locales/es/ProxyContract/7_links/step7.md @@ -0,0 +1,18 @@ +# Echa un vistazo a algunos enlaces para obtener más información + +- Proxy de delegado de ERChttps://github.com/ethereum/EIPs/pull/897 + +- La publicación conjunta de Zeppelin Solutions y Aragon. + https://blog.openzeppelin.com/proxy-libraries-in-solidity-79fbe4b970fd/ + +- Patrones de proxy de OpenZeppelin + Https://blog.openzeppelin.com/proxy-patterns/ + +- La implementación más madura del patrón Proxy es el patrón de almacenamiento no estructurado que se lanza como parte de ZeppelinOS + https://blog.openzeppelin.com/upgradeability-using-unstructured-storage/ + +- Gran publicación de blog de Jack Tanner + https://blog.indorse.io/ethereum-upgradeable-smart-contract-strategies-456350d0557c + +- Contratos inteligentes de Ethereum actualizables + https://medium.com/@daonomic/upgradeable-ethereum-smart-contracts-d036cb373d6 diff --git a/locales/es/ProxyContract/README.md b/locales/es/ProxyContract/README.md new file mode 100644 index 000000000..06cf8d46e --- /dev/null +++ b/locales/es/ProxyContract/README.md @@ -0,0 +1,3 @@ +## Aprende el Proxy Pattern + +Ahorra gas y crea contratos actualizables diff --git a/locales/es/ProxyContract/config.yml b/locales/es/ProxyContract/config.yml new file mode 100644 index 000000000..e36e640b8 --- /dev/null +++ b/locales/es/ProxyContract/config.yml @@ -0,0 +1,9 @@ +--- +id: proxycontract +name: All about Proxy Contracts +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 3 +tags: + - Remix + - Solidity + - Code Patterns diff --git a/locales/es/README.md b/locales/es/README.md new file mode 100644 index 000000000..a40425c6f --- /dev/null +++ b/locales/es/README.md @@ -0,0 +1,37 @@ +# Este es un repositorio de tutoriales para el complemento LearnEth de Remix + +### Para usar estos tutoriales: + +**1. Abra Remix** + +https://remix.ethereum.org + +**2. En el administrador de complementos, activa LEARNETH** + +**3. Ve al complemento Learneth y estos tutoriales se cargarán de forma predeterminada** + +**4. Es posible que tengas que iniciar sesión en Github, especialmente durante un taller en persona** + +Github bloqueará demasiadas solicitudes desde la misma ubicación, a menos que haya iniciado sesión en Github y haya introducido su token. En general, esto solo es un problema durante los talleres en persona, cuando puede haber muchas solicitudes desde el mismo lugar. + +Para introducir tu token de Github: + +``` +- En una ventana del navegador, vaya a https://remix.ethereum.org y vaya a la pestaña de configuración + +- En otra ventana del navegador, vaya a: + +Https://github.com/settings/tokens + +Y crea un nuevo token y guárdalo en Remix en el que acabas de abrir en la pestaña de configuración. +``` + +--- + +### Escribe tus propios tutoriales para LEARNETH: + +Consulte este sitio para obtener instrucciones: + +https://remix-learneth-plugin.readthedocs.io/en/latest/index.html#creating-tutorials + +--- diff --git a/locales/es/Recorder/1_Usecases/1_usecases.md b/locales/es/Recorder/1_Usecases/1_usecases.md new file mode 100644 index 000000000..aaf1042e8 --- /dev/null +++ b/locales/es/Recorder/1_Usecases/1_usecases.md @@ -0,0 +1,7 @@ +1. Quieres mostrarle a alguien lo que sucede cuando haces una serie de transacciones con un contrato y no quieres explicar cada paso, solo quieres llevarlos al último paso. + + - Para mostrar a alguien un problema en su código. + + - En una clase, para que los estudiantes lleguen a un lugar determinado y que empiecen a trabajar desde allí. + +2. Quieres iniciar tu desarrollo en JavascriptVM porque es rápido y luego cambiar a otra testnet, pero no quieres repetir manualmente todos los tediosos clics para cada red diferente. diff --git a/locales/es/Recorder/2_Record/README.md b/locales/es/Recorder/2_Record/README.md new file mode 100644 index 000000000..826c32e3c --- /dev/null +++ b/locales/es/Recorder/2_Record/README.md @@ -0,0 +1,32 @@ +# Establecer una tediosa serie de pasos + +## Seguir esto podría ser tedioso, pero ese es el punto. + +Vamos a: + +- Implementar un contrato de votación en el que haya 3 propuestas introducidas en el constructor. +- Otorgue privilegios de voto a 2 direcciones adicionales (por lo que tenemos un total de 3 direcciones de votación). +- Tenga un voto de dirección para la propuesta 1 (índice basado en 0) y los otros dos voto para la propuesta 2. + +1. Toma el 3_Ballot.sol de los archivos de solidity de muestra y compílalo. A continuación, vaya al módulo **Despliegue y ejecución**. + +2. Seleccione el entorno **JavaScript VM**. + +3. En el parámetro del constructor - ponga **["0x5031000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "0x503200000000000000000000000000000000000000000000000000000000", "0x50330000000000000000000000000000000000000000000000000000"]**\*\* Luego haga clic en el botón **Desplegar**. + +4. Abra el contrato desplegado. + +5. En la función **votar** poner en 2. Esto significa que usted, como msg.sender y presidente, está votando por la propuesta en la posición 2, que es la última propuesta de nuestra lista. + +6. Ahora tienes que dar a otras direcciones el derecho a votar. Seleccione otra dirección en el menú desplegable **cuenta** y cópiela y luego **vuelva a la primera dirección**. Pegue la dirección de copia en el cuadro de texto junto a la función giveRightToVote. Y de nuevo, seleccione otra dirección y cópiela y **luego vuelva a la primera dirección** de nuevo y péguela en giveRightToVote. + +7. Ahora tienes 3 direcciones con derecho a voto. + +8. Cambie a una de las direcciones a las que dio derecho a votar y votar por la propuesta **1**. (Pon **1** en el cuadro de texto junto a la función de voto). Y luego cambia a la otra dirección y vota por la propuesta **2** con esa. + +9. Abra la sección **Transacciones registradas** del módulo, haciendo clic en el sin. Haga clic en el icono del disco duro en la sección **Transacciones grabadas** para guardar sus pasos. + ![recorder](https://github.com/ethereum/remix-workshops/blob/master/Recorder/2_Record/images/recorder.png?raw=true "recorder") + +10. Obarás una ventana modal que te dice que quiere guardar un archivo llamado **scenario.json**. Haz clic en Aceptar. + +11. Haga clic en la función **propuesta ganadora** para confirmar que la propuesta final ganó, que es la propuesta en la posición 2 de la matriz. **0: uint256: winningProposal_ 2** diff --git a/locales/es/Recorder/3_Editing_a_Senario/README.md b/locales/es/Recorder/3_Editing_a_Senario/README.md new file mode 100644 index 000000000..7aa612a2f --- /dev/null +++ b/locales/es/Recorder/3_Editing_a_Senario/README.md @@ -0,0 +1,58 @@ +# Editando un escenario + +Aquí están las primeras líneas del escenario que grabé. Las direcciones de mi máquina serán diferentes a las tuyas. + +``` +{ +"Cuentas": { + +"Cuenta{0}": "0xca35b7d915458ef540ade6068dfe2f44e8fa733c", + +"Cuenta{4}": "0xdd870fa1b7c4700f2bd7f44238821c26f7392148", + +"Cuenta{3}": "0x583031d1113ad414f02576bd6afabfb302140225" + +} +``` + +Así que si querías jugar a este escenario en otra testnet, tendrías que cambiar estas direcciones a la dirección en la que has probado ETH para poder pagar las transacciones. Pero aparte de intercambiar las direcciones, puedes ejecutar esto rápidamente en otras redes. + +Y podrías cambiar los parámetros de las funciones. + +Por ejemplo, aquí hay un poco del scenario.json un poco más abajo, donde la propuesta 2 fue votada por una de las direcciones: + +``` +{ + "timestamp": 1566428184043, + "record": { + "value": "0", + "parameters": [ + "2" + ], + "to": "created{1566428035436}", + "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", + "name": "vote", + "inputs": "(uint8)", + "type": "function", + "from": "account{4}" + } + }, +``` + +Editemos esto para que otra propuesta gane en la reproducción. + +Cambia la matriz de **parámetros** que ahora es: + +``` +"parameters": [ + "2" + ] +``` + +para: + +``` +"parameters": [ + "1" + ] +``` diff --git a/locales/es/Recorder/4_Play/README.md b/locales/es/Recorder/4_Play/README.md new file mode 100644 index 000000000..6994fa916 --- /dev/null +++ b/locales/es/Recorder/4_Play/README.md @@ -0,0 +1,8 @@ +# Reproduciendo un escenario + +1. Haz clic en el icono de reproducción a la derecha del icono del disquete para reproducir los pasos que hiciste. + +2. Verás otra instancia del contrato desplegada. Ábrelo. + +3. Haz clic en la función de propuesta ganadora y deberías ver ahora que la propuesta 1 ganó. + Debería imprimirse: **0: uint256: winningProposal_ 1** diff --git a/locales/es/Recorder/README.md b/locales/es/Recorder/README.md new file mode 100644 index 000000000..0190a8f55 --- /dev/null +++ b/locales/es/Recorder/README.md @@ -0,0 +1,3 @@ +## ¡Ponte a Remixear! + +La grabadora se utiliza para grabar un conjunto de transacciones en el módulo Deploy & Run, editar sus parámetros y luego reproducirlos en otro contexto. ¡Realmente es el remix de Remix! diff --git a/locales/es/Recorder/config.yml b/locales/es/Recorder/config.yml new file mode 100644 index 000000000..b8980e042 --- /dev/null +++ b/locales/es/Recorder/config.yml @@ -0,0 +1,7 @@ +--- +id: recorder +name: Recorder +summary: Save a set of actions and replay and replay and replay +level: 2 +tags: + - Remix diff --git a/locales/es/SolidityBeginnerCourse/README.md b/locales/es/SolidityBeginnerCourse/README.md new file mode 100644 index 000000000..d0532ab11 --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/README.md @@ -0,0 +1,5 @@ +## Curso interactivo de Solidity + +Este curso de Solidity para principiantes se basa en los populares contratos https://solidity-by-example.org/. + +Desarrollados por la plataforma educativa p2p https://dacade.org. diff --git a/locales/es/SolidityBeginnerCourse/basic-syntax/basicSyntax.md b/locales/es/SolidityBeginnerCourse/basic-syntax/basicSyntax.md new file mode 100644 index 000000000..5ded1e409 --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/basic-syntax/basicSyntax.md @@ -0,0 +1,27 @@ +En esta sección, crearemos nuestro primer “contrato inteligente”. Este contrato consiste solamente en un texto (string) que contiene el valor “Hola Mundo!” + +En la primera línea, debemos especificar la licencia que queremos utilizar. Puedes encontrar una detallada lista de licencias aquí: https://spdx.org/licenses/. + +Usando la clave `pragma` (línea 3), especificamos la versión de Solidity que queremos compilar para usar. En este caso, debería de ser mayor o igual a `0.8.3` pero menos de 0.9.0. + +Definimos un contrato con la clave `contract` y le damos un nombre, en este caso `HelloWorld` +(línea 5). + +En nuestro contrato definimos una _variable de estado_ (state variable) `greet` que contiene el texto (string) `¡Hola Mundo!"` (línea 6). + +Solidity es un lenguaje _estadísticamente mecanografiado_, que significa que usted necesita especificar el tipo de variable cuando la declara. En este caso `greet` es un `string` (texto). + +También definiremos la “visibilidad” de la variable, que especifica desde dónde se puede acceder a ella. En este caso, es una variable `pública` a la que se puede acceder desde dentro y fuera del contrato. + +No se preocupe si no entiende algunos conceptos como el de _visibilidad_, _tipos de data_, o _variables de estado_. Vamos a observarlas en las siguientes secciones. + +Para ayudarle a entender el código, vamos a vincular las siguientes secciones con tutoriales en vídeo creador de Solidity en los contratos de ejemplo. + +Mire un tutorial sobre la sintaxis básica. + +## ⭐️ Misión + +1. Borre el contrato HelloWorld y su contenido. +2. Cree un nuevo contrato llamado "MyContract". +3. El contrato ha de tener una variable de estado pública llamada “nombre” (name) del tipo “string”. +4. Asigne el valor “Alice” a tu nueva variable. diff --git a/locales/es/SolidityBeginnerCourse/config.yml b/locales/es/SolidityBeginnerCourse/config.yml new file mode 100644 index 000000000..a729093d8 --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/config.yml @@ -0,0 +1,65 @@ +--- +id: soliditybeginner +name: Solidity Beginner Course +summary: Solidity Beginner Course based on the popular https://solidity-by-example.org/ contracts. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Basic Syntax + path: basic-syntax + - + name: 3. Primitive Data Types + path: primitive-data-types + - + name: 4. Variables + path: variables + - + name: 5.1 Functions - Reading and Writing to a State Variable + path: functions-reading-and-writing + - + name: 5.2 Functions - View and Pure + path: functions-view-and-pure + - + name: 5.3 Functions - Modifiers and Constructors + path: functions-modifiers-and-constructors + - + name: 5.4 Functions - Inputs and Outputs + path: functions-inputs-and-outputs + - + name: 6. Visibility + path: visibility + - + name: 7.1 Control Flow - If/Else + path: control-flow-if-else + - + name: 7.2 Control Flow - Loops + path: control-flow-loops + - + name: 8.1 Data Structures - Arrays + path: data-structures-arrays + - + name: 8.2 Data Structures - Mappings + path: data-structures-mappings + - + name: 8.3 Data Structures - Structs + path: data-structures-structs + - + name: 8.4 Data Structures - Enums + path: data-structures-enums + - + name: 9. Data Locations + path: data-locations + - + name: 10.1 Transactions - Ether and Wei + path: transactions-ether-and-wei + - + name: 10.2 Transactions - Gas and Gas Price + path: transactions-gas-and-gas-price + - + name: 10.3 Transactions - Sending Ether + path: transactions-sending-ether diff --git a/locales/es/SolidityBeginnerCourse/control-flow-if-else/ifElse.md b/locales/es/SolidityBeginnerCourse/control-flow-if-else/ifElse.md new file mode 100644 index 000000000..bb3e62629 --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/control-flow-if-else/ifElse.md @@ -0,0 +1,34 @@ +Solidity soporta declaraciones de flujos de control que determina qué partes del contrato van a ser ejecutadas. El condicional _declaraciones If/Else_ (If/Else statement) facilita contratos para tomar decisiones dependiendo de si las condiciones booleanas son verdaderas o falsas. + +Solidity diferencia entre tres diferentes declaraciones If/Else: `if`, `else`, and `else if`. + +### if + +La declaración `if` es la más básica que permite al contrato ejecutar una acción basada en una expresión booleana. + +En la función `foo` de este contrato (línea 5) la declaración if (línea 6) mira si `x` es menor que `10`. Si la declaración es verdad, la función devuelve `0`. + +### else + +La declaración `else` facilita que el contrato ejecute una acción si las condiciones no se cumplen. + +En este contrato, la función `foo` utiliza la declaración `else` (línea 10) para devolver `2` si ninguna de las otras condiciones se cumple. + +### else if + +Con la declaración `else if` podemos combinar diferentes condiciones. + +Si la primera condición (línea 6) de la función foo no se cumple pero la condición de la declaración `else if`(línea 8) torna verdadera, la función devuelve `1`. + +Mire un tutorial con vídeos sobre las declaraciones If/Else . + +## ⭐️ Misión + +Crear una función llamada `evenCheck` en el contrato `IfElse`: +Que toma un `uint` como argumento . + +- Eso toma un "uint" como argumento. +- La función devuelve `verdadero` si el argumento es par y `falso`si el argumento es impar. +- Usa un operador ternario para devolver el resultado de una función `evenCheck`. + +Consejo: El operador de módulo (%) produce la diferencia de una división numérica. diff --git a/locales/es/SolidityBeginnerCourse/control-flow-loops/loops.md b/locales/es/SolidityBeginnerCourse/control-flow-loops/loops.md new file mode 100644 index 000000000..3220dbf27 --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/control-flow-loops/loops.md @@ -0,0 +1,32 @@ +Solidity soporta declaraciones de flujos de control iterativos que permiten que los contratos ejecuten el código repetidamente. + +Solidity diferencia entre tres tipos de loops: `for`, `while`, y `do while` + +### for + +Generalmente los loops `for` (línea 7) vienen bien si se sabe cuántas veces se quiere ejecutar un determinado bloque de código. En solidity se debe especificar esta cantidad para evitar que se agote el gas de las transacciones y que estas fallen si el número de iteraciones es demasiado elevado. + +### while + +Si no sabe cuántas veces quiere ejecutar el código pero quiere parar el loop basándose en una condición, puede usar un `while` loop (línea 20). +Los loops no se utilizan mucho en Solidity porque las transacciones pueden agotar el gas y fallar si no hay un límite para el número de iteraciones que pueden ocurrir. + +### do while + +El loop `do while` es un tipo especial de while loop en el que se puede asegurar que el código se ejecute al menos una vez, antes de chequear la condición. + +### continue + +La declaración `continue` se usa para saltar el bloque de código restante y comenzar la siguiente iteración del loop. En este contrato, la declaración `continue` (línea 10) evitará que la segunda declaración if (línea 12) sea ejecutada. + +### break + +La declaración `break` se usa para salir de un loop. En este contrato la declaración de paro (break) (línea 14) causará un for loop que terminará después de la sexta interacción. + +Mire un vídeo con un tutorial sobre declaraciones de Loop. + +## ⭐️ Misión + +1. 1.Crear una variable de estado `uint` llamada count en el contrato `Loop`. +2. Al final del for loop, incrementar la variable contable en 1. +3. Intente que la variable contable sea igual a 9, pero asegúrese de que no edita la declaración `break`. diff --git a/locales/es/SolidityBeginnerCourse/data-locations/dataLocations.md b/locales/es/SolidityBeginnerCourse/data-locations/dataLocations.md new file mode 100644 index 000000000..e5f90fdcb --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/data-locations/dataLocations.md @@ -0,0 +1,54 @@ +Los valores de variables en Solidity pueden almacenarse en diferentes localizaciones de data: _memoria_ (memory), _almacenamiento_ (storage) y _calldata_. + +Como hemos explicado antes, las variables de tipo de valor almacenan una copia independiente de un valor, mientras variables de tipo de referencia (array, struct, mapping), solo almacena la localización (reference). + +Si usamos un tipo de referencia en una función, hemos de especificar en qué localización de data se almacenan sus valores. El precio por la ejecución de la función es influenciado por la localización del data; creando copias de tipos de referencia y costes de gas. + +### Almacenaje + +Los valores almacenados en _storage_ son almacenados permanentemente en el blockchain y, por ello, el coste para su uso es alto. + +En este contrato, el estado de variables `arr`, `map` y `myStructs` (líneas 5, 6, and 10) se almacenan en el almacén (storage). Las variables de estado siempre se almacenan en el almacén (storage). + +### Memoria + +Los valores almacenados en la memoria _memory_ solo se almacenan temporalmente y no están en la blockchain. Solamente existen durante la ejecución externa y son descartados después. Son más asequibles que los valores almacenados en el almacén (_storage_). + +En este contrato, la variable local `myMemstruct` (línea 19), así como el parámetro `_arr` (línea 31), se almacenan en la memoria. Los parámetros de una función necesitan tener la localización de data _memory_ o _calldata_. + +### Calldata + +_Calldata_ almacena los argumentos de las funciones. Como en _memory_, _calldata_ solamente se almacena temporalmente durante la ejecución de una función externa. En contraste con valores almacenados en _memory_, valores almacenados en _calldata_ no pueden cambiarse. Calldata es la localización de data más asequible. + +En este contrato, el parámetro `_arr` (line 35) tiene la localización de data _calldata_. Si queremos asignar un nuevo valor al primer elemento de la colección `_arr`, podríamos hacerlo en la `function g` (línea 31) pero no en la `function h` (line 35). Esto es porque `_arr` en la `function g` tiene la localización de data _memory_ y _function h_ tiene la localización de data `calldata`. + +## Asignaciones + +### De Memoria a memoria + +Las misiones de _memory_ a _memory_ crean referencias en ver de copias. Si cambiamos el valor en una variable, el valor de todas las demás variables que referencian la misma data serán cambiadas. + +Si tuviésemos que crear un nuevo struct `myMemstruct2` con la localización de data _memory_ en la `function f` (línea 12) y asignarle el valor de `myMemstruct` (línea 19), cualquier cambio a `myMemstruct2` cambiará también el valor de `myMemstruct`. + +### De almacén a almacén local. + +Las asignaciones del _storage_ al _local storage_ también crean referencias, no copias. + +Si cambiamos el valor de una variable local `myStruct` (línea 17), el valor de nuestra variable de estado `myStructs` (línea 10) cambia también. + +## Almacenaje y memoria/calldata + +Las asignaciones entre _storage_ y _memory_ (or _calldata_) crean copias independientes, no referencias. + +Si tuviéramos que crear un nuevo struct `myMemstruct3` con la localización de data _memory_ dentro de la función `function f` (línea 12) y asignarle el valor de `myStruct`, cambios en `myMemstruct3` no afectarían los valores almacenados en el mapeo `myStructs` (línea 10). + +Como hemos dicho al principio, cuando creamos contratos hemos de tener en mente los gastos de gas. Por ello, necesitamos usar las localizaciones de data que requieren la menor cantidad posible de gas. + +## ⭐️ Misión + +1. Cambiar el valor del miembro `myStruct` llamado `foo`, en la función `function f`, a 4. +2. Crear un nuevo struct `myMemstruct2` con la localización de data _memory_dentro de `function f` y asígnale el valor de `myMemstruct`. Cambia el valor del miembro `myMemstruct2` llamado `foo` a 1. +3. Crear un nuevo struct `myMemstruct3`con la localización de data _memory_ en la `function f` y asígnale el valor de `myStruct`.Cambia el valor del miembro `myMemstruct3` llamado `foo` a 3. Misiones +4. Dejar que la función f devuelva `myStruct`, `myMemStruct2` y `myMemStruct3`. + +Consejo: Asegúrese de crear los tipos de retorno correctos para la función `f`. diff --git a/locales/es/SolidityBeginnerCourse/data-structures-arrays/arrays.md b/locales/es/SolidityBeginnerCourse/data-structures-arrays/arrays.md new file mode 100644 index 000000000..ab4b8d9bd --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/data-structures-arrays/arrays.md @@ -0,0 +1,44 @@ +En las próximas secciones miraremos las estructuras de data que se pueden usar para organizar y almacenar nuestro data en Solidity. + +_Arrays_, _mappings_ y _structs_ son _tipos de referencia_ (reference types). Al contrario que los _tipos de valor_ (e.g. _booleans_ o _integers_), los tipos de referencia no almacenan su valor directamente. En su lugar, almacenan su localización en la que el valor se almacena. Las variables de múltiple referencia podrían hacer referencia a la misma ubicación y un cambio en una variable podría afectar a las demás. + +En Solidity las colecciones (arrays) almacenan listas ordenadas de valores del mismo tipo de las que estaban indexadas numéricamente. + +Hay dos tipos de colecciones, de _tamaño-fijo_ (fixed-size) compila-tiempo y _colecciones dinámicas_ (dynamic arrays). Para las colecciones de tamaño fijo necesitamos declarar la talla de las colecciones antes de que se compile. El tamaño de las colecciones dinámicas puede ser cambiado después de que el contrato se haya compilado. + +### Declaraciones de matrices + +Declaramos una colección de tamaño fijo proporcionando su tipo, el tamaño de la colección (como un número entre corchetes), visibilidad y nombre (línea 9). + +Declaramos una colección dinámica de la misma manera. No obstante, no proporcionamos el tamaño de la colección y dejamos los corchetes vacíos (línea 6). + +### Inicialización de matrices + +Podemos inicializar los elementos de una colección todos a la vez (línea 7), o inicializar nuevos elementos uno por uno (arr[0] = 1;). Si declaramos una colección, automáticamente inicializamos sus elementos con el valor inicial 0 (línea 9). + +### Acceso a los elementos de la matriz + +Accedemos elementos dentro de una colección proporcionando el nombre de la colección y el índice de los paréntesis (línea 12). + +### Añadir elementos de una colección + +Usando la función de miembro `push()`, añadimos un elemento al final de la colección dinámica (línea 25). + +### Eliminar los elementos de una colección + +Usando la función de miembro `pop()`, eliminamos el último elemento de una colección dinámica (línea 31). + +Podemos usar el operador `delete` para eliminar un elemento con un índice específico de una colección (línea 42). +Cuando eliminamos el elemento con el operador `delete` todos los demás elementos permanecen iguales, lo que significa que la extensión de la colección permanece igual. Esto creará un espacio en nuestra colección. +Si el orden de la colección no es importante, entonces podemos mover el último elemento de la colección al lugar del elemento eliminado (línea 46) o usar un mapeo. Un mapeo puede ser una mejor opción si planeamos eliminar elementos en nuestra estructura de datos. + +### Longitud de la matriz + +Usando el miembro de extensión, podemos leer el número de elementos que están almacenados en una colección (línea 35) + +Mira un vídeo tutorial sobre matrices. + +## ⭐️ Misión + +1. Inicializar una colección `arr3` con los valores 0, 1, 2. El tamaño ha de ser lo menor posible. +2. Cambiar la función `getArr()` para devolver el valor de `arr3`. diff --git a/locales/es/SolidityBeginnerCourse/data-structures-enums/enums.md b/locales/es/SolidityBeginnerCourse/data-structures-enums/enums.md new file mode 100644 index 000000000..570477c46 --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/data-structures-enums/enums.md @@ -0,0 +1,33 @@ +En Solidity los _enums_ son tipos de data customizados que consisten en un set limitado de valores constantes. Usamos enums cuando a nuestras variables se les asigna un valor de un set predeterminado de valores. + +En este contrato, a la variable de estado `status` se le puede asignar un valor desde el set limitado de valores del enum `Status`, que representa los varios estados de un estado de envío. + +### Definiendo enums + +Definimos un enum con la palabra clave enum, seguida del nombre del tipo a medida que queremos crear (línea 6). Dentro de las llaves (curly braces) definimos todos los miembros del enum disponibles. + +### Inicializando una variable de enum + +Podemos inicializar una nueva variable de un tipo de enum proporcionando el nombre del enum, la visibilidad, y el nombre de la variable (línea 16). Tras su inicialización, a la variable se le asignará el valor del primer miembro del enum, en este caso, Pendiente (Pending) (línea 7). + +A pesar de que los miembros de enum son nombrados cuando se definen, son almacenados como números (integers), no texto (strings). Son numerados en el orden en que son definidos, el primer miembro comenzando con 0. El valor inicial de estado, en este caso, es 0. + +### Accediendo un valor de enum + +Para acceder el valor de enum de una variable simplemente necesitamos proporcionar el nombre de variable que está almacenado en el valor (línea 25). + +### Actualizando un valor enum + +Podemos actualizar el valor enum de una variable asignándole en el `uint` representando el miembro de enum (línea 30). Enviado sería 1 en este ejemplo. Otra forma de actualizar el valor es usando el operador de punto proporcionando el nombre del enum y sus miembros (línea 35). + +### Eliminar un valor de enum + +Podemos usar el operador delete para eliminar el valor enum de la variable, lo que significa respecto a las colecciones y mapeos que el valor inicial es 0. + +Mira este vídeo con tutoriales sobre Enums. + +## ⭐️ Misión + +1. Definir un tipo de enum llamado `Size` con los miembros `S`, `M`, y `L`. +2. Inicializar la variable `sizes` del tipo de enum `Size`. +3. Crear una función getter `getSize()` que devuelve el valor de la variable `sizes`. diff --git a/locales/es/SolidityBeginnerCourse/data-structures-mappings/mappings.md b/locales/es/SolidityBeginnerCourse/data-structures-mappings/mappings.md new file mode 100644 index 000000000..a6e02d93b --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/data-structures-mappings/mappings.md @@ -0,0 +1,37 @@ +En Solidity, _mapeos_ (mappings) son una colección de tipos de claves (keys) y correspondiendo con pares de tipo de valor. + +La mayor diferencia entre un mapeo y una colección es que no puedes iterar los mapeos. Si no sabemos la clave no seremos capaces de acceder su valor. Si necesitamos saber todo nuestro data e iterar sobre ello, debemos usar una colección. + +Si queremos recuperar un valor basado en una clave conocida podemos usar un mapeo (por ejemplo direcciones a menudo usadas como claves). Mirando a valores con un mapeo es fácil y más asequible que iterar las colecciones. Si las colecciones se vuelven demasiado largas, los costes de gas de iterar pueden volverse demasiado altos y causar que la transacción falle. + +También podemos almacenar las claves de un mapeo en una colección que podrá ser iterada. + +### Creando mapeos + +Los mapeos son declarados con la sintaxis `mapping(KeyType => ValueType) VariableName`. +El tipo key puede tener cualquier valor incorporado o cualquier contrato, pero no cualquier tipo de referencia. El tipo de valor puede ser de cualquier tipo. + +En este contrato, estamos creando el mapeado público `myMap` (línea 6), que asocia el tipo de key `address` con el tipo de valor `uint`. + +### Accediendo valores + +La sintaxis para interactuar con pares de valores-clave de los mapeados es similar a la de las colecciones. +Para encontrar el valor asociado a una clave específica, proporcionamos el nombre del mapeado y la clave entre paréntesis (línea 11). + +En contraste con las colecciones, no recibiremos un error si intentamos acceder al valor de una clave cuyos valores no han sido aún establecidos. Si creamos un mapeado, todas las claves posibles son mapeadas hasta el valor por inicial 0. + +### Establecer valores + +Establecemos un nuevo valor para una clave, proporcionando el nombre del mapeo y llave entre paréntesis y asignando un nuevo valor (línea 16). + +### Eliminar valores + +Podemos usar el operador delete para eliminar un valor asociado a la clave, el cual reestablecerá el valor inicial de 0. Como lo hemos visto en la sección de colecciones. + +Mire un tutorial con vídeaos sobre mapeos. + +## ⭐️ Misión + +1. Crear un mapeo público `balances` que asocie el tipo de clave `address`con el tipo de valor `uint`. +2. Cambiar las funciones `get` y`remove` para trabajar con los balances de mapeo. +3. 3.Cambiar la función `set` para crear una nueva entrada a los mapeos de balance, en el que la clave es la dirección de los parámetros y el valor es balance asociado con la dirección del parámetro. diff --git a/locales/es/SolidityBeginnerCourse/data-structures-structs/structs.md b/locales/es/SolidityBeginnerCourse/data-structures-structs/structs.md new file mode 100644 index 000000000..78ed2294c --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/data-structures-structs/structs.md @@ -0,0 +1,29 @@ +En Solidity podemos definir los tipos de data a medida en forma de _structs_. Structs son una colección de variables que pueden consistir en tipos de data diferentes. + +### Definiendo structs + +Definimos struct usando la palabra clave `struct` y un nombre (línea 5). Dentro de unas llaves (curly braces), podemos definir los miembros de nuestros structs, que consisten en los nombres de las variables y sus tipos de data. + +### Inicialización de estructuras + +Hay diferentes maneras de inicializar un struct. + +Parámetros posicionales: podemos proporcionar el nombre del struct y los valores de sus miembros como parámetros entre paréntesis (línea 16). + +Mapeo de valor-clave: Proporcionamos el nombre del struct y las claves y valores como un mapeo dentro de llaves (línea 19). + +Inicializamos un struct vacío primero y después su miembro asignándole un nuevo valor (línea 23). + +### Accediendo a structs + +Para acceder un miembro de un struct podemos usar el operador de punto (línea 33). + +### Actualizando structs + +Para actualizar los miembros de un struct también usamos el operador de punto y le asignamos un nuevo valor (líneas 39 y 45). + +Mira un vídeo con tutoriales sobre Structs. + +## ⭐️ Misión + +Crear una función `remove` que tome `uint` como un parámetro y elimine un miembro de struct con el índice dado en el mapeo de `todos`. diff --git a/locales/es/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md b/locales/es/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md new file mode 100644 index 000000000..a5d74676e --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md @@ -0,0 +1,37 @@ +En esta sección, aprenderemos sobre los inputs y outputs de las funciones. + +### Outputs llamados de manera múltiple + +Las funciones pueden retornar múltiples valores que pueden ser nombrados o designados un nombre. + +La función `returnMany` (line 6) muestra cómo devolver múltiples valores. +A menudo habrá de retornar múltiples valores. Puede tratarse de una función que colecciona outputs de varias funciones y las devuelve en una sola llamada por ejemplo. + +La función `named` (línea 19) muestra cómo nombrar valores de retorno. +Nombrar valores de retorno ayuda a la legibilidad de nuestros contratos. Valores de retorno nombrados facilitan el llevar un registro de los valores y el orden en que son devueltos. También puedes asignar valores a un nombre. + +La función `assigned` (línea 33) muestra cómo asignar valores a un nombre. +Si asigna valores a un nombre puede omitir (dejar fuera) la declaración de retorno y devolverlos individualmente. + +### Constructora + +Puede deconstruir misiones para desempaquetar valores dentro de variables distintas. + +La función `destructingAssigments` (línea 49) asigna los valores de la función `returnMany` a las nuevas variables locales `i`, `b`, y `j` (línea 60). + +### restricciones de Input y Output + +Existen algunas restricciones y buenas prácticas para los parámetros de input y output de las funciones de contratos. + +"_[Los Mapeos] no pueden ser usados como parámetros o parámetros de retorno de funciones de contratos que son visibles públicamente._” +De documentación de Solidity + +Las colecciones pueden ser usadas como parámetros , como se ha mostrado en la función `arrayInput` (línea 71). Las colecciones pueden también ser usadas como parámetros de retorno, como hemos mostrado en la función `arrayOutput` (línea 76). + +Ha de tener cuidado con las colecciones de tamaño aleatorio, por su consumo de gas. Mientras que una función con largas colecciones como inputs puede fallar cuando los costes de gas son elevados, una función que usa una colección más pequeña podría ser ejecutada. + +Mira un vídeo con tutoriales sobre modificadores de funciones. + +## ⭐️ Misión + +Crear una nueva función llamada `returnTwo` que devuelva los valores `-2` y `true` sin usar una declaración de retorno. diff --git a/locales/es/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md b/locales/es/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md new file mode 100644 index 000000000..c091fd8fe --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md @@ -0,0 +1,39 @@ +En esta sección, aprenderemos cómo modificar el comportamiento de una función y cómo ejecutar el código de inicialización del contrato. + +### Función Modificar + +_Los modificadores de función_ se utilizan para cambiar el comportamiento de una función. Por ejemplo, a menudo comprueban una condición antes de ejecutar una función para restringir el acceso o validar las entradas. + +Esta primera parte de este contrato trata de cambiar la propiedad de un contrato. La propiedad de este contrato se expresa por el valor de la variable de estado "propietario" que es del tipo "dirección" (línea 7). + +La función "cambio de propietario" (línea 33) puede cambiar esta propiedad. Toma un parámetro de entrada del tipo "dirección" y asigna su valor a la variable de estado "propietario". + +Sin embargo, esta función no se puede ejecutar simplemente en todas las condiciones; tiene dos modificadores, "onlyOwner" y "validAddress". + +Echemos un vistazo a "onlyOwner" primero (línea 18). +Los modificadores de funciones se definen con la palabra clave "modificador" y un nombre único; también pueden tener parámetros. + +El guión bajo `_` (línea 23) se utiliza dentro de los modificadores para representar el resto del código que se ejecutará en el cuerpo de la función modificada. +El código que coloque antes del guión bajo en el modificador se ejecutará antes del código en el cuerpo de la función modificada. El código después del guión bajo se ejecutará después del código en el cuerpo de la función modificada. + +En este caso, la función "requiere" (línea 19) comprueba si la dirección que ejecuta el contrato es la misma que el valor almacenado en la variable "propietario". Si lo es, el resto del código se ejecutará, de lo contrario se generará un error. + +Puede obtener más información sobre "afirmar" y "requerir" en la documentación de solidity, se utilizan para comprobar las condiciones y lanzar errores si no se cumplen. + +El modificador "dirección válida" (línea 28) tiene un parámetro de tipo "dirección" y comprueba si la dirección proporcionada es válida. Si lo es, continúa ejecutando el código. + +### Constructor + +Una función de constructor se ejecuta tras la creación de un contrato. Puedes usarlo para ejecutar el código de inicialización del contrato. El constructor puede tener parámetros y es especialmente útil cuando no se conocen ciertos valores de inicialización antes de la implementación del contrato. + +Declaras un constructor usando la palabra clave `constructor`. El constructor de este contrato (línea 11) establece el valor inicial de la variable propietario en el momento de la creación del contrato. + +Mira un vídeo tutorial sobre modificadores de funciones. + +## ⭐️ Asignación + +1. Crea una nueva función, "increaseX" en el contrato. La función debe tomar un parámetro de entrada de tipo `uint` y aumentar el valor de la variable `x` en el valor del parámetro de entrada. +2. Asegúrese de que x solo se pueda aumentar. +3. El cuerpo de la función "increaseX" debe estar vacío. + +Consejo: Utilice modificadores. diff --git a/locales/es/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md b/locales/es/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md new file mode 100644 index 000000000..3087a4a62 --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md @@ -0,0 +1,23 @@ +Esta sección dará una breve introducción a funciones y enseñará cómo usarlas para leer y escribir sobre una variable de estado. + +Como en otros lenguajes, usamos funciones en Solidity para crear código modular y reutilizable. Sin embargo, las funciones de Solidity tienen particularidades. + +Las funciones de Solidity pueden dividirse en dos tipos: + +1. Funciones que modifican el estado de la blockchain, como escribir a una variable de estado. En este contrato, la función `set` (línea 9) cambia la variable de estado `num`. +2. Funciones que no modifican el estado de la blockchain. Estas funciones están marcadas como `view` o `pure`. Por ejemplo, en este contrato, la función `get` (línea 14) marcada como `view` que solamente devuelve `num`. + +Para definir una función, use la palabra clave `function`, seguida de un nombre único. + +Para definir una función que toma inputs como nuestra función `set` (línea 9), ha de especificar los tipos y nombres de los parámetros. Una convención común es usar el guión bajo como prefijo para los nombres de los parámetros para distinguirlos de las variables de estado. + +Puede establecer la visibilidad de una función y declararla como `view` o `pure`, como lo hacemos para la función `get`, si no se modifica el estado. Nuestra función `get` también devuelve valores, así que debemos especificar los tipos de retorno. En este caso, es un `uint` porque la variable de estado `num` que devuelve la función es una `uint`. + +Vamos a explorar las particularidades de las funciones de Solidity en más detalle en las siguientes secciones. + +Mire un tutorial sobre funciones. + +## ⭐️ Misión + +1. 1.Crear una variable de estado público llamada `b`, que es del tipo`bool` e inicia con `true`. +2. Crear una función pública llamada `get_b` que devuelva el valor de `b`. diff --git a/locales/es/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md b/locales/es/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md new file mode 100644 index 000000000..9d4c196e6 --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md @@ -0,0 +1,44 @@ +Esta sección prestará atención a los tipos de funciones que no modifican el estado de la blockchain: funciones _view_ y _pure_ + +### Funciones View + +Las funciones View prometen no modificar el estado + +“Las siguientes declaraciones se considera que modifican el estado” + +1. Escribir a variables de estados. +2. Emitir eventos. +3. Crear otros contratos. +4. Usar la auto desestructuración (self-destruct). +5. Enviar Ether vía llamadas. +6. Llamar cualquier función no marcada como view o pure. +7. Usar llamadas de bajo nivel. +8. Usando asambleas en línea que contienen determinados opcodes." + +De documentación sobre Solidity. + +Puede declarar una función vista (view) usando la palabra clave `view`. En este contrato, `addToX` (línea 8) es una función vista. Esta función toma el parámetro `y` y devuelve la suma de los parámetros y de las variables de estado `x`. Lee `x` pero no lo modifica. + +### Funciones Pure + +Las _Pure functions_ prometen no modificar ni leer el estado. + +“Además de la lista de declaraciones de estados modificando explicadas anteriormente, las siguientes se considera que leen desde el estado: + +1. Leyendo desde las variables de estado, . +2. Accediendo `address(this).balance` o `
.balance`. +3. Accediendo alguno de los miembros de un bloque, tx, mensaje (con la excepción de `msg.sig` and `msg.data`) +4. Llamando a cualquier función no marcada como pura. +5. Usar asamblea en línea que contiene ciertos opcódigos." + +De documentación de Solidity. + +Puede declarar una función pura usando la palabra clave `pure`. En este contrato, `add` (línea 13) es una función pura. Esta función toma los parámetros `i` y `j`, y devuelve la suma de ellos. No lee ni modifica la variable de estado `x`. + +En el desarrollo de Solidity, necesita optimizar su código para ahorrar costes de computación (gas cost). Declarar funciones view y pure puede ahorrar mucho coste de gas y hacer el código más legible y fácil de mantener. Las funciones pure no tienen efectos secundarios y devolverán siempre el mismo resultado si se pasan los mismos argumentos. + +Mire un video con tutoriales sobre funciones View y Pure. + +## ⭐️ Misión + +Crear una función llamada `addToX2` que tome el parámetro `y` y actualizar las variables de estado `x` con la suma de los parámetros y el estado de variable `x`. diff --git a/locales/es/SolidityBeginnerCourse/introduction/introduction.md b/locales/es/SolidityBeginnerCourse/introduction/introduction.md new file mode 100644 index 000000000..45f9163cb --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/introduction/introduction.md @@ -0,0 +1,33 @@ +Bienvenido a este curso interactivo en Solidity para principiantes. + +En esta primera sección, daremos una breve introducción sobre los conceptos que cubrirá este curso, miraremos ejemplos de contratos inteligentes y le enseñaremos cómo puede interactuar con este contrato en el IDE Remix. + +Este contrato es un contrato contador cuya función es incrementar, decrementar y retornar el estado de una variable contadora. + +Si miramos el principio de los contratos, podemos ver información sobre el contrato como la licencia (línea 1), la versión de Solidity (línea 2), así como la palabra clave `contract` y su nombre `Counter` (línea 4). Cubriremos estos conceptos en la próxima sección sobre la +**Syntaxis Básica** (Basic Syntax). + +Con `uint public count` (el contador público uint) (íinea 5), declaramos una variable de estado de tipo `uint` con la visibilidad `public`. Cubriremos estos conceptos en nuestra sección sobre **Variables**, **Tipos de data primitivos** (Primitive Data Types), y **Visibilidad** (Visibility). + +Creamos la función `get` (línea 8) que se define con la palabra clave `view` y devuelve un tipo `uint`. Específicamente devuelve la variable `count`. Este contrato tiene dos funciones más, una función `inc` (línea 13) y`dec` (línea 18) que incrementa o decrementa las variables contables. +Hablaremos de estos conceptos en nuestras secciones sobre **Funciones - Leyendo y escribiendo una variable de estado** (Functions - Reading and Writing to a State Variable) y **Funciones - Vista y pura** (Functions - View and pure). + +## Compilar e implemente a través de Remix + +**GIF** Interactuando con el contrato: Compile and deploy contract + +1. Podemos compilar su contrato "Counter" en el módulo "Solidity compiler" del Remix IDE. + +2. En el módulo "Desplegar y ejecutar transacciones", seleccionamos nuestro contrato "Contador" en el campo de entrada del contrato y hacemos clic en el botón "Desplegar". + +3. Interactuamos con el contrato y probamos sus funciones `get`, `inc`, y `dec`. + +## ⭐️ Misión + +A través de este curso, le daremos una misión para probar y consolidar los conocimientos adquiridos. + +Su primera misión es: + +1. Compilar este contrato. +2. Despliégalo en la máquina virtual Remix. +3. Interactuar con tu contrato. diff --git a/locales/es/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md b/locales/es/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md new file mode 100644 index 000000000..f823c4679 --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md @@ -0,0 +1,33 @@ +En esta sección, vamos a enseñarle los tipos de variables primitivas, como declararlas y sus características. + +### bool + +Puede declarar data del tipo boolean usando la palabra clave ‘bool’. Booleans pueden tener el valor `verdadero` o `falso` + +### uint + +Usamos las palabras clave `uint` y `uint8` hasta `uint256` para declarar un _tipo numérico no firmado_ (unsigned integer type) (no tienen un signo, al contrario que -12, por ejemplo). Uints son números (integers) positivos o cero y oscilan entre los 8 bits hasta los 256 bits. El tipo `uint` es el mismo que `uint256`. + +### int + +Usamos las palabras clave `int` e `int8` hasta `int256` para declarar un tipo numérico (integer). Los Integers pueden ser positivos, negativos o cero y oscilar entre los 8 bits y los 256 bits. El tipo `int` es el mismo que `int256`. + +### address (dirección) + +Variables del tipo `address` tienen un valor de 20 bytes, que es el tamaño de una dirección de Ethereum. Hay también un tipo de dirección de Ethereum especial, `address payable`, que puede recibir Ether del contrato. + +Todos estos tipos de data tienen valores por defecto, como es mostrado en el contrato (línea 29). + +Puede aprender más sobre estos tipos de data, así como _Fixed Point Numbers_, _Byte Arrays_, _Strings_ y más en documentación de Solidity . + +Más adelante en el curso miraremos estructuras de data como **Mappings**, **Arrays**, **Enums** y **Structs**. + +Puede ver un tutorial en video sobre tipos de data primitivos. + +## ⭐️ Misión + +1. Crear una nueva variable `newAddr` que es una `public` `address` que le da un valor que no es el mismo que que la variable `addr` disponible. +2. Crear una variable `public` llamada `neg`que es un número negativo, decidir sobre el tipo. +3. Crear una nueva variable, `newU` que es el `uint` el tipo de tamaño más pequeño y de valor de `uint` más pequeño y es `public`. + +Consejo: Mire la otra dirección en el contrato o busca el internet para la dirección de Ethereum. diff --git a/locales/es/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md b/locales/es/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md new file mode 100644 index 000000000..ea963daa4 --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md @@ -0,0 +1,26 @@ +_Ether_ (ETH) es una criptomoneda. _Ether_ es también usada para pagar honorarios por usar la red de ethereum, como haciendo transacciones en forma de envío de _Ether_ a una dirección o interactuando con una aplicación de Ethereum. + +### Unidades de Ether + +Para especificar una unidad de _Ether_, podemos añadir los sufijos `wei`, `gwei`, o `ether` a un número literal. + +#### `wei` + +_Wei_ es la subunidad más pequeña de _Ether_, nombrada en honor al criptógrafo [Wei Dai](https://en.wikipedia.org/wiki/Wei_Dai). Los números _Ether_ sin un sufijo son tratados como `wei` (línea 7). + +#### `gwei` + +Un `gwei` (giga-wei) es igual a 1,000,000,000 (10^9) `wei`. + +#### `ether` + +Un `ether` es igual a 1,000,000,000,000,000,000 (10^18) `wei` (línea 11). + +Mire un video con tutoriales sobre Ether y Wei. + +## ⭐️Misión + +1. Crear una `uint` pública (`public`) llamada `oneGWei` y ponla a un `gwei`. +2. Crear una `bool` pública (`public`) llamada `isOneGWei` y ponla como el resultado de una operación de comparación entre 1 gwei y 10^9. + +Consejo: Mire como esto está escrito para `gwei` y `ether` en el contrato. diff --git a/locales/es/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md b/locales/es/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md new file mode 100644 index 000000000..1303f799b --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md @@ -0,0 +1,29 @@ +Como hemos visto en la sección anterior, ejecutar código vía transacciones en la red Ethereum exige cargos en forma de Ether. La cantidad de la tarifa que ha de ser pagada para ejecutar una transacción depende de la cantidad de _gas_ que cueste la ejecución de la transacción. + +### Gas + +_Gas_ es la unidad que mide la cantidad de esfuerzo computacional que es requerido para ejecutar una operación concreta en la red Ethereum. + +### Precio del Gas + +El _gas_ que alimenta a Ethereum es a veces comparado con la gasolina que alimenta a un coche. La cantidad de gas que consume un coche es casi siempre la misma, pero el precio que se paga por el gas depende del mercado. + +Del mismo modo, la cantidad de gas que requiere una transacción es siempre la misma para el mismo trabajo computacional con el. Sin embargo, el precio que el emisor de la transacción quiere pagar por el gas depende de ellos. Transacciones con precios de gas más altos pasan más rápido; transacciones con precios de gas más bajos quizá nunca lleguen a pasar. + +Cuando se envía una transacción, el emisor ha de pagar la tasa de gas (gas_price \* gas) cuando la transacción es ejecutada. Si el _gas_ sobra después de que la ejecución se complete, el emisor recibe el importe de vuelta. + +_Gas_ es referido como gwei. + +### Límite de Gas + +Cuando se envía una transacción el emisor especifica la máxima cantidad de gas que está dispuesto a pagar por la transacción. Si el límite es demasiado bajo, la transacción puede quedarse sin gas antes de ser completada, revirtiendo cualquier cambio que se haya hecho. En este caso, el gas se consume y no podrá ser reembolsado. + +Aprenda más sobre _gas_ en ethereum.org. + +Mire un vídeo con tutoriales sobre Gas y los precios del Gas. + +## ⭐️ Misión + +Crear una nueva variable de estado `public` en el contrato de `Gas` llamado `cost` del tipo `uint`. Almacenar el valor del coste del gas para desplegar el contrato en una nueva variable, incluyendo el coste por el nuevo valor que se está almacenando. + +Consejo: Puede revisar en la terminal de Remix los detalles de una transacción incluyendo los costes de gas. También puede usar el plugin de Remix _Gas Profiler_ para buscar los costes de gas de las transacciones. diff --git a/locales/es/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md b/locales/es/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md new file mode 100644 index 000000000..c7825431c --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md @@ -0,0 +1,88 @@ +En esta sección, aprenderemos cómo un contrato puede enviar y recibir Ether. + +### Enviar Ether + +Tenemos tres opciones diferentes para transferir Ether: `transfer()`, `send()` y `call()` + +#### **transferir** + +`
.transfer(uint256 amount)` + +- `transfer()` hace una excepción si hay un fallo +- Reenvía un estipendio fijo de 2300 gas + +Un ejemplo de `transfer()` se puede ver en el contrato `SendEther` (línea 35) +\*\* No se recomienda usar `Transfer()` más.\*\* +Si se elimina la modificadora + +#### **enviar** + +`
.send(uint256 amount) regresa (bool)` + +- `send()` devuelve falso o un fallo. +- Reenvía un estipendio fijo de 2300 gas + +Un ejemplo de `send()` puede verse en el contrato SendEther`(línea 41). ** No se recomienda usar `Send()\` más.\*\* + +#### **llamar** + +`
.call(bytes memory) devuelve (bool, bytes memory)` + +- `call()` devuelve falso o un fallo +- Devuelve un número máximo de gas, pero este es ajustable. + +Un ejemplo de `call()` puede verse en el contrato `SendEther` (línea 48) +`Call()` es recomendable actualmente si se quiere transferir Ether. +Sino, el Ether sera denegada y el contrato lanzará una excepción. + +La razón por la que `transfer()` y `send()` fueron introducidos fue cubrirse de los _reentry attacks_, limitando el gas reenviado hasta 2300, que sería insuficiente para hacer una llamada reentrante que pueda modificar el almacenaje. + +Como hemos explicado en la sección anterior, cada operación en Ethereum tiene un coste específico asociado a ella. Ciertas operaciones se han hecho más costosas a lo largo del tiempo, asi que los costes de gas asociados con ellas también se han elevado. Cuando los costes por las operaciones están sujetos a cambios no conviene usar la cantidad de gas escrito a mano (hardcoded) como por ejemplo lo hacen transfer() o send(). + +Esto es por lo que `call()` en lugar de `transfer()` es ahora recomendado para enviar Ether. + +Aprende más sobre la materia en Blog post sobre Consensys. + +### Ataque de reentrada + +Un _ataque de reentrada_ (reentrancy attack) ocurre cuando una función crea una llamada externa a un contrato no confiable y el atacante usa el contrato para hacer llamadas recurrentes de vuelta a la función original antes de que finalice su ejecución. A través de este método, el atacante puede absorber fondos y manipular data de maneras no deseables. + +Para protegerse de los ataques de reentrada, todos los cambios de estado han de hacerse antes de llamar a un contrato externo. Esto también es llamado el patrón Checks-Effects-Interactions + +Otra manera de protegerse de las reentradas es usar un _Guardia de Reentrada_ que chequea esas llamadas y las deniega. Puedes ver el ejemplo de esto en el contrato en la sección de modificaciones o una versión más eficiente con el gas en Open Zepplin. + +### Recibir Ether + +Si queremos habilitar un contrato para recibir Ether sin tener que llamar a una función, necesitamos crear una función `receive` (línea 22) o una función `fallback` (línea 25). + +La función `receive` se ejecuta con llamadas de calldata vacío (por ejemplo transferencias de Ether básicas vía send() o transfer()), mientras que la función fallback se ejecuta en llamadas con calldata. Si no existe ninguna función `receive`pero sí una función `fallback`, las llamadas con un calldata vacío también usarán la función fallback. + +### Función de pago modificar + +La función `payable`modificadora, habilita que las funciones puedan recibir Ether. + +La función `receive` (línea 22) necesita ser `payable` (pagable). Se borras el modificador `payable` recibirás un error del compilador. Si borras el modificador `payable` de la función `fallback` (línea 25) que compilará, pero no será capay de recibir Ether. +Las funciones `sendViaTransfer`, `sendViaSend` y `sendViaCall` (líneas 33, 38 y 45) también necesitan ser pagables para poder recibir Ether. + +### Dirección pagable + +Solidity hace una distinción entre dos sabores diferentes del tipo de data de la dirección: dirección y dirección pagable. + +La función `receive` (línea 22) necesita ser `payable` (pagable). +`address`: contiene un valor de 20-byte +`address payable`: tiene un valor de 20-byte y puede recibir Ether via transferencias y envíos de sus miembros. + +Si se cambia el tipo de parámetros para las funciones `sendViaTransfer` y `sendViaSend` (línea 33 and 38) de`payable address` a `address`, no se podrá usar `transfer()` (línea 35) o `send()` (línea 41). + +Mire un vídeo con tutoriales sobre envío de Ether. + +## ⭐️ Misión + +Crear un contrato caritativo que recibe Ether que puede ser retirado por un beneficiario. + +1. Crear un contrato llamado `Charity`. +2. Añadir una variable de estado público llamada `owner` del tipo address. +3. Crear una función donar que es pública y pagable sin ningún parámetro o código de función. +4. Crear una función de retirada que es pública y envía el balance total de los contratos de la dirección `owner`. + +Consejo: Pruebe su contrato desplegándolo desde una cuenta y después enviando Ether a ella desde otra cuenta. Después ejecute la función de retirada. diff --git a/locales/es/SolidityBeginnerCourse/variables/variables.md b/locales/es/SolidityBeginnerCourse/variables/variables.md new file mode 100644 index 000000000..9847d63ae --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/variables/variables.md @@ -0,0 +1,29 @@ +Hay tres tipos diferentes de variables en Solidity: _Variables estatales_, _Variables locales_ y _Variables globales_. + +## 1. Variables de estado + +_Las variables de estado_ se almacenan en el contrato _almacenamiento_ y, por lo tanto, en la cadena de bloques. Se declaran dentro del contrato, pero fuera de la función. +Este contrato tiene dos variables de estado, la cadena `text` (línea 6) y la uint `num` (línea 7). + +## 2. Variables Locales + +_Las variables locales_ se almacenan en la _memoria_ y sus valores solo son accesibles dentro de la función en la que se definen. Las variables locales no se almacenan en la cadena de bloques. +En este contrato, la uint `i` (línea 11) es una variable local. + +## 3. Variables globales + +_Variables globales_, también llamadas _Variables especiales_, existen en el espacio de nombres global. No es necesario declararlos, pero se puede acceder a ellos desde su contrato. +Las variables globales se utilizan para recuperar información sobre la cadena de bloques, direcciones particulares, contratos y transacciones. + +En este ejemplo, usamos `block.timestamp` (línea 14) para obtener una marca de tiempo Unix de cuándo se generó el bloque actual y `msg.sender` (línea 15) para obtener la llamada de la dirección de la función del contrato. + +Una lista de todas las variables globales está disponible en la documentación de solidez. + +Vea tutoriales en vídeo sobre Variables de estado, Variables locales y Variables globales. + +## ⭐️ Asignación + +1. Crea una nueva variable de estado público llamada "número de bloque". +2. Dentro de la función `doSomething()`, asigna el valor del número de bloque actual a la variable de estado `blockNumber`. + +Consejo: Mire la sección de variables globales de la documentación de Solidity para averiguar cómo leer el número de bloque actual. diff --git a/locales/es/SolidityBeginnerCourse/visibility/visibility.md b/locales/es/SolidityBeginnerCourse/visibility/visibility.md new file mode 100644 index 000000000..b16cf15ac --- /dev/null +++ b/locales/es/SolidityBeginnerCourse/visibility/visibility.md @@ -0,0 +1,37 @@ +El especificador de "visibilidad" se utiliza para controlar quién tiene acceso a funciones y variables de estado. + +Hay cuatro tipos de visibilidades: "externa", "público", "interno" y "privado". + +Regulan si las funciones y las variables de estado se pueden llamar desde el interior del contrato, de los contratos que se derivan del contrato (contratos infantiles) o de otros contratos y transacciones. + +### privado + +- Se puede llamar desde dentro del contrato + +### internal + +- Se puede llamar desde dentro del contrato +- Se puede llamar desde un contrato infantil + +### público + +- Se puede llamar desde dentro del contrato +- Se puede llamar desde un contrato infantil +- Se puede llamar desde otros contratos o transacciones + +### externo + +- Se puede llamar desde otros contratos o transacciones +- Las variables de estado no pueden ser "externas" + +En este ejemplo, tenemos dos contratos, el contrato "Base" (línea 4) y el contrato "Hijo" (línea 55) que hereda las funciones y las variables de estado del contrato "Base". + +Cuando anulas el comentario en el `testPrivateFunc` (líneas 58-60), obtienes un error porque el contrato infantil no tiene acceso a la función privada `privateFunc` del contrato `Base`. + +Si compila e implementa los dos contratos, no podrá llamar a las funciones "privateFunc" e "internalFunc" directamente. Solo podrás llamarlos a través de `testPrivateFunc` y `testInternalFunc`. + +Mira un vídeo tutorial sobre Visibilidad. + +## ⭐️ Asignación + +Cree una nueva función en el contrato "Hijo" llamada "testInternalVar" que devuelva los valores de todas las variables de estado del contrato "Base" que se pueden devolver. diff --git a/locales/es/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md b/locales/es/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md new file mode 100644 index 000000000..62e81d2ee --- /dev/null +++ b/locales/es/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md @@ -0,0 +1,47 @@ +En este tutorial, exploraremos el contrato Uniswap V3 Swap para aprender sobre cómo funcionan los swaps de un solo salto y varios saltos. + +Pero primero, algunos fundamentos de Uniswap. + +## ¿Qué es Uniswap? + +Uniswap es un intercambio descentralizado de criptomonedas. Permite a los usuarios intercambiar tokens sin necesidad de un intermediario centralizado. Uniswap es un jugador clave en el espacio de las finanzas descentralizadas (DeFi). + +## ¿Cómo funciona Uniswap? + +En lugar de utilizar un libro de pedidos como un intercambio centralizado tradicional, Uniswap utiliza un modelo de creador de mercado automatizado (AMM). En Uniswap, el AMM es un contrato inteligente que tiene reservas de tokens (Liquidity Pool). Los usuarios pueden comerciar entre tokens en el grupo de liquidez. El precio de cada token está determinado por la proporción de las reservas. + +### Ejemplo paso a paso de una operación Uniswap + +1. Alice quiere comerciar con 1 ETH para DAI. +2. Alice envía 1 ETH al contrato inteligente de Uniswap. +3. El contrato inteligente de Uniswap calcula la cantidad de DAI que Alice debería recibir en función del tipo de cambio actual. +4. El contrato inteligente de Uniswap envía el DAI a Alice. +5. El contrato inteligente de Uniswap añade el 1 ETH a sus reservas. +6. El contrato inteligente de Uniswap vuelve a calcular el tipo de cambio en función de las nuevas reservas. + +Los tokens en el grupo de liquidez son proporcionados por los proveedores de liquidez. Cuando un proveedor de liquidez deposita tokens en un grupo de liquidez, recibe tokens de proveedor de liquidez a cambio. Los tokens de proveedor de liquidez representan la participación de un usuario en un grupo de liquidez. + +Los usuarios de Uniswap pagan una tarifa por cada operación. La tarifa se paga a los proveedores de liquidez en forma de tokens adicionales para proveedores de liquidez. + +## Contrato de intercambio de Uniswap + +El contrato de intercambio de Uniswap permite a los usuarios intercambiar tokens utilizando Uniswap V3. Puede hacer intercambios de un solo salto, que permiten a los usuarios intercambiar un token por otro directamente. También puede hacer intercambios de varios saltos, lo que significa que los usuarios pueden intercambiar un token por otro mediante el enrutamiento a través de múltiples tokens. El enrutamiento en este contexto significa que el contrato de intercambio cambiará el token por otro token, luego cambiará ese token por otro token, y así sucesimente hasta que alcance el token deseado. + +## Conclusiones + +En esta sección, aprendimos sobre Uniswap, cómo funciona y cómo lo vamos a usar para intercambiar tokens. + +## ⭐️ Asignación: Prueba de opción múltiple + +### 1. ¿Qué es Uniswap? + +1. Un protocolo de intercambio centralizado. +2. Un protocolo de intercambio descentralizado que utiliza un libro de pedidos. +3. Un protocolo de intercambio descentralizado que utiliza un modelo de creador de mercado automatizado (AMM). +4. Un protocolo de intercambio descentralizado que utiliza un libro de pedidos y un modelo de creador de mercado automatizado (AMM). + +### 2) ¿Cómo determina Uniswap el precio de un token? + +1. El precio de un token está determinado por la proporción de las reservas. +2. El precio de un token está determinado por la proporción de las reservas y el número de operaciones. +3. El precio de un token está determinado por la proporción de las reservas y el número de proveedores de liquidez. diff --git a/locales/es/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md b/locales/es/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md new file mode 100644 index 000000000..b200f38ea --- /dev/null +++ b/locales/es/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md @@ -0,0 +1,41 @@ +Todo el contrato de UniswapSwapExamples solo se presentará en la sección 5 de este tutorial. Antes de eso, construiremos bloques de código. + +Esta sección explora la interfaz "ISwapRouter", que define las funciones que se pueden llamar en el contrato de intercambio de Uniswap. + +Los swaps de un solo salto permiten a los usuarios intercambiar un token por otro directamente dentro de un fondo de liquidez. +Los intercambios de varios saltos permiten a los usuarios intercambiar un token por otro mediante el enrutamiento a través de múltiples tokens. + +Las interfaces en Solidity especifican funciones que deben incluirse en un contrato que las herede. Son útiles para declarar qué funciones son compatibles y permiten una integración e interacción más fáciles entre los diferentes contratos. + +Las estructuras se utilizan para definir tipos de datos personalizados. + +## ISwapRouter Interfaz + +La interfaz ISwapRouter define las funciones que se pueden llamar en el contrato de intercambio de Uniswap. Tendremos que usar esta interfaz para interactuar con el contrato de intercambio de Uniswap y ejecutar swaps. + +En la línea 5, definimos una variable constante llamada `router` que es del tipo `ISwapRouter`. Establecemos el valor de esta variable en la instancia de interfaz de un contrato inteligente que se implementa en la dirección `0xE592427A0AEce92De3Edee1F18E0157C05861564`. Esta es la dirección del contrato Uniswap V3 Swap en la red principal de Ethereum. + +En la línea 9, definimos una interfaz llamada "ISwapRouter". Esta interfaz define dos funciones: `exactInputSingle` y `exactInput`. + +## exactInputSingle + +En la línea 25, definimos una estructura llamada "ExactInputSingleParams". Esta estructura define los parámetros que se requieren para nuestra función exactInputSingle en la línea 21, que ejecutará un intercambio de un solo salto. La estructura tiene los siguientes parámetros: + +- **`dirección tokenIn`**: La dirección del token que se está enviando. +- **`address tokenOut`**: La dirección del token que se recibe. +- **`tarifa uint24`**: La tarifa asociada con el intercambio. +- **`destinatario de la dirección`**: La dirección que recibirá el token de salida. +- **`uint deadline`**: Una marca de tiempo con la que se debe procesar la transacción, para limitar el tiempo de la operación. +- **`uint amountIn`**: La cantidad del token de entrada que se envía. +- **`uint amountOutMinimum`**: La cantidad mínima del token de salida que el remitente está dispuesto a aceptar, para proteger contra los movimientos de precios desfavorables. +- **`uint160 sqrtPriceLimitX96`**: Un límite en el precio, representado en un formato específico, para evitar que el intercambio se produzca a precios desfavorables. + +## exactInput + +En la línea 25, definimos una estructura llamada "ExactInputParams". Esta estructura define los parámetros necesarios para nuestra función "exactInput" en la línea 33. Esta función ejecutará un intercambio de varios saltos. La estructura tiene los siguientes parámetros: + +- **`ruta de bytes`**: Información codificada sobre la ruta de intercambio (es decir, a través de qué tokens intercambiar). +- **`receptor de la dirección`**: La dirección que recibe los tokens de salida. +- **`fecha límite`**: Similar a la anterior, una marca de tiempo con la que se debe procesar la transacción. +- **`uint amountIn`**: La cantidad del token de entrada. +- **`uint amountOutMinimum`**: La cantidad mínima del token de salida que el remitente espera recibir. diff --git a/locales/es/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md b/locales/es/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md new file mode 100644 index 000000000..484f61d13 --- /dev/null +++ b/locales/es/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md @@ -0,0 +1,36 @@ +Los swaps de un solo salto permiten a los usuarios intercambiar un token por otro directamente dentro de un fondo de liquidez. En esta sección, aprenderemos a usar el contrato de intercambio V3 de Uniswap para ejecutar swaps de un solo salto. + +## Parámetros de función + +En la línea 8, definimos una función llamada "swapExactInputSingleHop". Esta función ejecuta un intercambio de un solo salto. Toma los siguientes parámetros: + +- **`dirección tokenIn`**: La dirección del token que se está enviando. +- **`address tokenOut`**: La dirección del token que se recibe. +- **`uint24 poolFee`**: La tarifa asociada con el intercambio. +- **`uint amountIn`**: La cantidad del token de entrada que se envía. + +Devuelve un `uint` llamado `amountOut`, que es la cantidad del token de salida que se recibió. + +## Cuerpo de función + +En el cuerpo de la función, primero transferimos el token de entrada del remitente a nuestro contrato, línea 14. +Luego, aprobamos el contrato de intercambio de Uniswap para gastar el token de entrada en nuestro nombre, línea 15. + +En la línea 17, creamos una instancia de la estructura "ExactInputSingleParams". Esta estructura contiene los parámetros que se requieren para nuestra función "exactInputSingle" en la línea 45, que ejecutará el intercambio de un solo salto. Repetimos `ISwapRouter.ExactInputSingleParams` dos veces en esa línea porque estamos haciendo una instancia de una estructura que está definida en una interfaz. + +## Parámetros de la estructura ExactInputSingleParams + +Estapuemos los parámetros de la estructura de la siguiente manera: + +- **`tokenIn`**: Establamos esto en el parámetro `tokenIn` de nuestra función. +- **`tokenOut`**: Establamos esto en el parámetro `tokenOut` de nuestra función. +- **`tarifa`**: Establamos esto en el parámetro `poolFee` de nuestra función. +- **`destinatario`**: Lo establecemos en el remitente de la transacción. +- **`fecha límite`**: Estamos esto en la marca de tiempo actual. Hacemos esto porque queremos que la transacción se procese lo antes posible. +- **`amountIn`**: Establecimos esto en el parámetro `amountIn` de nuestra función. +- **`amountOutMinimum`**: Establemos esto en 0 porque no queremos especificar una cantidad mínima del token de salida que estamos dispuestos a aceptar. +- **`sqrtPriceLimitX96`**: Establecemos esto en 0 porque no queremos especificar un límite en el precio. + +## Ejecución del intercambio de un solo salto + +En la línea 29, asignamos la salida de la función "exactInputSingle" a la variable "mountOut". Esta función ejecuta el intercambio de un solo salto y devuelve la cantidad del token de salida que se recibió. diff --git a/locales/es/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md b/locales/es/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md new file mode 100644 index 000000000..2034c0d0f --- /dev/null +++ b/locales/es/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md @@ -0,0 +1,30 @@ +En esta sección, profundizaremos en la función `swapExactInputMultiHop` en el contrato `UniswapV3SwapExamples`. Esta función permite intercambios de tokens más complejos al permitir a los usuarios especificar una ruta personalizada a través de múltiples grupos de liquidez. + +Si, por ejemplo, un usuario quiere cambiar el token A por el token D, pero no hay un fondo de liquidez directo para A y D, el usuario puede especificar una ruta a través de varios tokens. Por ejemplo, el usuario puede cambiar A por B, luego B por C y, finalmente, C por D. Por supuesto, esto se hace automáticamente mediante el contrato de intercambio V3 de Uniswap. + +### Parámetros y valor de devolución + +En la línea 32, definimos una función llamada `swapExactInputMultiHop`. Esta función ejecuta un intercambio de varios saltos. Toma los siguientes parámetros: + +- **`ruta de datos de llamada de bytes`**: información codificada sobre la ruta de intercambio (es decir, a través de qué tokens intercambiar). +- **`address tokenIn`**: La dirección del token que se está enviando. +- **`uint amountIn`**: La cantidad del token de entrada que se envía. + +Devuelve un `uint` llamado `amountOut`, que es la cantidad del token de salida que se recibió. + +### Cuerpo de función + +En el cuerpo de la función, primero transferimos el token de entrada del remitente a nuestro contrato, línea 38. +Luego, aprobamos el enrutador Uniswap Swap para gastar el token de entrada en nuestro nombre, línea 41. + +En la línea 43, creamos una instancia de la estructura "ExactInputParams", línea 73. Esta estructura contiene los parámetros necesarios para nuestra función "exactInput" en la línea 81, que ejecutará el intercambio de varios saltos. + +Estapuemos los parámetros de la estructura de la siguiente manera: + +- **`ruta`**: Establamos esto en el parámetro `ruta` de nuestra función. +- **`destinatario`**: Lo establecemos en el remitente de la transacción. +- **`fecha límite`**: Estamos esto en la marca de tiempo actual. Hacemos esto porque queremos que la transacción se procese lo antes posible. +- **`amountIn`**: Establecimos esto en el parámetro `amountIn` de nuestra función. +- **`amountOutMinimum`**: Establemos esto en 0 porque no queremos especificar una cantidad mínima del token de salida que estamos dispuestos a aceptar. + +En la línea 53, ejecutamos el intercambio de varios saltos llamando a la función "exactInput". Esta función devuelve la cantidad del token de salida que se recibió. diff --git a/locales/es/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md b/locales/es/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md new file mode 100644 index 000000000..a15940640 --- /dev/null +++ b/locales/es/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md @@ -0,0 +1,52 @@ +En esta sección, exploraremos la interfaz `IERC20`, una interfaz estándar para interactuar con los tokens ERC-20 y la interfaz `IWETH`, una interfaz estándar para interactuar con Ether envuelto (WETH). Comprender estas interfaces es crucial, ya que se utiliza en el contrato Uniswap V3 Swap para manejar las transferencias y aprobaciones de tokens. + +Puedes encontrar un "Curso de tokens ERC20 de solidez" para principiantes en LearnEth para entender el estándar de tokens ERC20 con más detalle. + +## Interfaz IERC20 + +En la línea 80, definimos la interfaz `IERC20`. Esta interfaz define un conjunto estándar de funciones que los tokens ERC-20 deben implementar. Examinemos las funciones clave dentro de esta interfaz: + +### 1. totalSupply + +En la línea 81, definimos la función "totalSupply". Esta función devuelve el suministro total del token. + +### 2. balanceOf + +En la línea 83, definimos la función `balanceOf`. Esta función devuelve el saldo de la dirección especificada. + +### 3. transfer + +En la línea 85, definimos la función de "transferencia". Esta función transfiere tokens del remitente al destinatario especificado. + +### 4. allowance + +En la línea 87, definimos la función "subsidia". Esta función devuelve la cantidad de fichas que el gastante puede gastar en nombre del propietario. + +### 5. approve + +En la línea 89, definimos la función "aprobar". Cuando se llama, esta función aprueba que un gastante gaste la cantidad especificada de tokens en nombre del remitente. + +### 6. transferFrom + +En la línea 91, definimos la función "transferFrom". Esta función transfiere tokens del remitente especificado al destinatario. El gastador solo puede llamar a la función si al gastador se le permite gastar la cantidad especificada de tokens en nombre del remitente. + +### 7. Eventos + +En las líneas 102-103, definimos los eventos de "Transferencia" y "Aprobación". Estos eventos se emiten cuando se llaman a las funciones "transferir" y "aprobar", respectivamente. + +## IWETH Interface + +En la línea 106, definimos la interfaz "IWETH". Esta interfaz amplía la interfaz "IERC20" y define dos funciones adicionales: + +### 1. deposit + +En la línea 107, definimos la función "depósito". Esta función deposita ETH en el contrato y devuelve la cantidad equivalente de WETH. Esta función se utiliza para envolver ETH en WETH. +Necesitamos envolver ETH en WETH porque el contrato Uniswap V3 Swap solo admite tokens ERC-20. + +### 2. retirar + +En la línea 109, definimos la función "retirar". Esta función retira la cantidad especificada de WETH del contrato y devuelve la cantidad equivalente de ETH. Esta función se utiliza para desenvolver WETH en ETH. + +## Conclusión + +En este tutorial, exploramos el contrato de intercambio V3 de Uniswap. Para tener una idea completa de cómo funciona Uniswap, intente hacer algunos intercambios en el Uniswap DApp y vaya a los documentos de Uniswap. diff --git a/locales/es/Uniswap-Tutorial/README.md b/locales/es/Uniswap-Tutorial/README.md new file mode 100644 index 000000000..549ebc94a --- /dev/null +++ b/locales/es/Uniswap-Tutorial/README.md @@ -0,0 +1,5 @@ +# Curso de intercambio de uniswap + +Revise el código del contrato Uniswap V3 Swap para realizar permutas de tokens. + +Desarrollado por la plataforma de aprendizaje p2p https://dacade.org. diff --git a/locales/es/Uniswap-Tutorial/config.yml b/locales/es/Uniswap-Tutorial/config.yml new file mode 100644 index 000000000..f49f02abc --- /dev/null +++ b/locales/es/Uniswap-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: uniswapSwapCourse +name: Uniswap Swap Course +summary: Go through the Solidity code of the Uniswap V3 Swap contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - Uniswap +steps: + - + name: 1. Introduction + path: 1-introduction-to-uniswap + - + name: 2. Routers, Interfaces, and Structs + path: 2-router-interfaces-and-structs + - + name: 3. Single Hop Swaps + path: 3-single-hop-swaps + - + name: 4. Multi-Hop Swaps + path: 4-multi-hop-swaps + - + name: 5. Erc20 and Weth Interfaces + path: 5-erc20-weth-interfaces diff --git a/locales/es/Web3Client/1_Using_Web3/Running_a_script.md b/locales/es/Web3Client/1_Using_Web3/Running_a_script.md new file mode 100644 index 000000000..2943d8c70 --- /dev/null +++ b/locales/es/Web3Client/1_Using_Web3/Running_a_script.md @@ -0,0 +1,24 @@ +## Consultando la cadena de bloques + +En este tutorial, ejecutaremos un script que consulta la cadena de bloques utilizando una biblioteca de JavaScript. + +Esto significa que en lugar de usar la interfaz gráfica de usuario de Remix o un explorador de bloques como Etherscan, usaremos un script en el editor y lo ejecutaremos desde el terminal. + +Las bibliotecas JS que más se utilizan para interactuar con la cadena de bloques son web3.js y ethers.js. + +Comencemos con un simple ejemplo de web3.js, queryBlockNum.js. + +La llamada del script a web3.js está envuelta en una función asíncrona de autoejecución que contiene un bloque try/catch. + +Consultaremos el número de bloque actual con: +`let blockNumber = await web3.eth.getBlockNumber()` + +Tenga en cuenta que el objeto "web3" es inyectado por Remix. Para obtener más información sobre web3.js, consulte sus documentos, https://web3js.readthedocs.io. + +Para usar web3.js o ethers.js, debe seleccionar el entorno **Inyected Web3** o **Web3 Provider** en el módulo **Deploy & Run**. Los scripts no funcionan actualmente con la JSVM. \*\*Si lo intentas, obtendrás un error. \*\* + +Así que para este ejemplo, elija **Injected Web3** en el módulo Deploy & Run y tenga Metamask instalada. + +Desde el terminal, ejecute `remix.execute()`. Este comando ejecutará el archivo JavaScript actual con la línea `let blockNumber = await web3.eth.getBlockNumber()`. + +En la consola, deberías ver el número de bloque actual de la cadena a la que está conectado metamask. diff --git a/locales/es/Web3Client/2_Querying_a_Contract/queryContract.md b/locales/es/Web3Client/2_Querying_a_Contract/queryContract.md new file mode 100644 index 000000000..f191b3b54 --- /dev/null +++ b/locales/es/Web3Client/2_Querying_a_Contract/queryContract.md @@ -0,0 +1,22 @@ +Ahora que sabemos cómo consultar datos simples, intentemos una consulta más compleja. + +Este es un contrato desplegado en la red principal - en esta dirección: https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code + +Vamos a consultar el contrato para encontrar el nombre de su token. + +La variable **nombre** es una variable de estado del contrato. + +Para acceder a este contrato **mainnet**, tenemos que hacer algo de configuración. + +1. Cambie a la red principal en metamask. +2. Probablemente tendrás que actualizar Remix. +3. Como resultado de la actualización, es posible que también tengas que volver a cargar este tutorial. +4. Vaya a Implementar y ejecutar y cambie a **Inyected Web3**. + +**Uso de Web3**En el script, queryContract.js, necesitamos crear una instancia de una nueva instancia del objeto web3.eth.Contract. Para esto necesitamos tomar el ABI del contrato y su dirección. El código fuente y el ABI están disponibles en etherscan porque el desarrollador del contrato lo publicó intencionalmente. + +En etherscan, podemos ver que su nombre es **TetherToken**. Al desplazarse hacia abajo hasta el contrato TetherToken en la sección de código fuente de etherscan, podemos ver las variables de estado del contrato, la primera de las cuales se llama **nombre**. + +Hay algunos aros sintácticos por los que saltar para devolver el valor de la variable de estado. + +- Para llamar a la función getter generada automáticamente de la variable de estado público, debe tratar la variable como una función (añadiendo paréntesis) y también agregar una llamada(). diff --git a/locales/es/Web3Client/README.md b/locales/es/Web3Client/README.md new file mode 100644 index 000000000..1058b8264 --- /dev/null +++ b/locales/es/Web3Client/README.md @@ -0,0 +1 @@ +Este taller trata sobre el uso de web3.js para interactuar con un contrato y, en general, con la cadena de bloques. diff --git a/locales/es/Web3Client/config.yml b/locales/es/Web3Client/config.yml new file mode 100644 index 000000000..07cb1760c --- /dev/null +++ b/locales/es/Web3Client/config.yml @@ -0,0 +1,9 @@ +--- +id: useofweb3js +name: Basic use of web3.js +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 2 +tags: + - JS + - Remix + - Web3 diff --git a/locales/fa/Basics/README.md b/locales/fa/Basics/README.md new file mode 100644 index 000000000..6b065b830 --- /dev/null +++ b/locales/fa/Basics/README.md @@ -0,0 +1,3 @@ +## Loading, Compiling, Deploying + +This beginner level tutorial introduces Remix's interface and concepts used in Ethereum. diff --git a/locales/fa/Basics/config.yml b/locales/fa/Basics/config.yml new file mode 100644 index 000000000..8c160b545 --- /dev/null +++ b/locales/fa/Basics/config.yml @@ -0,0 +1,26 @@ +--- +id: basics +name: Basics of Remix +summary: A typical workflow in Remix +level: 1 +tags: + - Remix +steps: + - + name: Intro to the Interface + path: interface_introduction + - + name: Intro to Workspaces + path: workspaces + - + name: Loading & Compiling + path: load_and_compile + - + name: Deploying to the Remix VM + path: deploy_to_the_remixvm + - + name: Interacting with Functions + path: interacting + - + name: Deploying to Public Networks + path: deploy_injected diff --git a/locales/fa/Basics/deploy_injected/README.md b/locales/fa/Basics/deploy_injected/README.md new file mode 100644 index 000000000..172396527 --- /dev/null +++ b/locales/fa/Basics/deploy_injected/README.md @@ -0,0 +1,21 @@ +1. If you don't have a browser wallet like **MetaMask** download and install one now. + +2. Click the MetaMask icon in your browser. Sign in and choose the Ephemery test network. You might need to update your wallet's settings so that you can see **test networks**. Alternatively, you can go to Remix's Deploy & Run transation module and in the ENVIRONMENT section select Ephemery. + +3. Getting test ETH for public test networks is often annoying. Ephemery is a public network that is refreshed monthly, so getting test ETH should be painless. Here is a link to some Ephemery faucets. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/testnet.png) + +Sepolia is another popular testnet that is not refreshed, so deployments will persist, but Sepolia faucets are more difficult to use. + +In your browser wallet make sure that you have NOT selected mainnet or any network that will cost real ETH. In the Deploy & Run module, below the Environment select box, you'll see a badge with the network's ID and for popular chains, its name. In the case below its Sepolia. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/sepolia.png) + +5. Make sure you see the 2_Owner.sol as a choice in the **CONTRACT** select box, then click the **Deploy** button. + +If the **CONTRACT** select box is empty, you'll need to compile 2_Owner again by making 2_Owner.sol the active file in the **editor** and then go to the **Solidity Compiler** to compile it. + +6. After you hit the `Deploy` button, you'll see the browser wallet popup asking you to pay for the transactions. If you have the appropriate kind of ETH for this chain, approve this transaction. Check the printout in the terminal. Once the block is validated, the **deployed instance** will appear at the bottom of Deploy & Run + +And with that you have finished this tutorial. You now have experience with opening, compiling, deploying and interacting with Smart Contracts in Remix IDE. diff --git a/locales/fa/Basics/deploy_to_the_remixvm/README.md b/locales/fa/Basics/deploy_to_the_remixvm/README.md new file mode 100644 index 000000000..8035d631b --- /dev/null +++ b/locales/fa/Basics/deploy_to_the_remixvm/README.md @@ -0,0 +1,15 @@ +In the previous chapter, we compiled a contract - which is to say the Solidity code has been transformed into little chunks of Ethereum Virtual Machine (EVM) bytecode. + +Now we will put that code on a test blockchain. + +1. Click the Deploy and Run icon ![deploy & run icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_to_the_remixvm/images/run.png "deploy & run icon"). + +2. Select one of the **Remix VM**s from the **Environment** pulldown. + +3. Click the Deploy button (or the transact button in the expanded view). + +4. You have deployed your compiled contract to the Remix VM - a simulated blockchain that is running inside of your browser window. The Remix VM is simple, fast test chain. It is not that realistic because you don't need to approve each transaction. + +5. Check the terminal to see detail of this deployment transaction. + +You can also use Remix to deploy to other public EVM chains. To do this, you'll need to connect to a different **Environment** - like Injected Provider. The Injected Provider connects Remix to browser wallet (like MetaMask or similar). We'll try deploying to a public network at the end of this tutorial. But before we get there, we'll cover how to interact with a deployed contract's functions. diff --git a/locales/fa/Basics/interacting/README.md b/locales/fa/Basics/interacting/README.md new file mode 100644 index 000000000..59ef44200 --- /dev/null +++ b/locales/fa/Basics/interacting/README.md @@ -0,0 +1,19 @@ +## Accessing functions in a deployed contract + +1. When a contract has been successfully deployed, it will appear at the bottom of the Deploy and Run plugin. Open up the contract by clicking the caret - so the caret points down. + ![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/instance.png "deployed contract") + +2. There are 2 functions in this contract. To input the parameters individually, clicking the caret to the right of changeOwner (outlined in red below). In the expanded view, each parameter has its own input box. + +![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/deployed_open2.png "deployed contract") + +If this contract had imported other contracts, then the functions of the imported contracts would also be visible here. At some point, try playing with An ERC20 contract to see all its many functions. + +3. Functions with blue buttons are either **pure** or **view** functions. This means that they are just reading a property or are returning a value. In other words, they aren't saving anything - so they are FREE (they don’t cost gas). Functions with other colors - usually orange (depending on the Remix theme) cost gas because they are saving information. They are creating a **transaction**. + +4. 2_Owner.sol does not have a **payable** function. If it did, the button's color would be red. Payable functions allow you to send Ether to the function. To send ETH with a payable function, you put the amount you want to send in the **value** field towards the top of the Deploy & Run module. + +5. In the Remix VM, you don't need to approve a transaction. When using a more realistic test environment or when using the mainnet - you will need to approve the transactions for them to go through. Approving a transaction costs gas. + +6. Choosing a public network is not done in Remix but in your Browser Wallet. There is a plug icon to the right of the Environment title that links to chainlist.org where you can get the specs of the chain you want to interact with. + ![chainlist](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/chainlist.png "chainlist") diff --git a/locales/fa/Basics/interface_introduction/README.md b/locales/fa/Basics/interface_introduction/README.md new file mode 100644 index 000000000..76c953fbd --- /dev/null +++ b/locales/fa/Basics/interface_introduction/README.md @@ -0,0 +1,15 @@ +## Remix is composed of four panels. + +![Remix layout](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/a-layout1c.png "Remix layout") + +- Most plugins appear in the **Side Panel**. +- Editing code happens in tabs in the **Main Panel**. +- The results of transactions and other actions are visible in the **Terminal**. +- Switching between plugins happens in the **Icons Panel**. +- To make a panel larger, drag its border. + +Try clicking the **Solidity Compiler** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/solidity-icon.png) in the **Icons Panel**. Then click the **Deploy & Run** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/deploy-run.png). Then come back to **LearnEth** by clicking this icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/learneth.png). + +In the **Main Panel** of Remix, make sure you see the **Home** tab. The **Home** tab has lots of useful links. To navigate there, either click the **Home** tab in the **Main Panel** or click the Remix icon ![Remix icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/remix-logo.png "Remix icon") on the top of the icon panel. + +- See all the plugins in the **Plugin Manager**. Click this icon ![plugin manager](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/plugin1.png "Plugin Manager icon") in the lower left corner Remix. diff --git a/locales/fa/Basics/load_and_compile/README.md b/locales/fa/Basics/load_and_compile/README.md new file mode 100644 index 000000000..a666d5d13 --- /dev/null +++ b/locales/fa/Basics/load_and_compile/README.md @@ -0,0 +1,20 @@ +Let's load a file from the File Explorer into the Editor. + +1. In the icon panel, click ![file explorer icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/files1.png "file explorer icon") , the File Explorer's icon. + +2. Make sure you are in the **default_workspace**. + +![default workspace](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/default_workspace_open.png) + +3. Open the contracts folder and click on **2_Owner.sol** in the contracts folder. Click it. The file will appear in a tab in the main panel. + +4. In the icon panel, click the **Solidity Compiler** ![solidity compiler icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/solidity1.png "solidity compiler icon"). The Solidity compiler should now be in the side panel. + +5. Click the compile button. + ![compile 2\_owner](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/compile2owner.png "compile 2_Owner") + +6. Compiling can also be triggered by hitting **CTRL + S**. + +The spinner will turn while the file is compiling. + +**Note:** The spinner also turns when the compiler itself is loading. To choose a **different version of Solidity**, go to the select box at the top of the plugin. diff --git a/locales/fa/Basics/workspaces/README.md b/locales/fa/Basics/workspaces/README.md new file mode 100644 index 000000000..97a47d283 --- /dev/null +++ b/locales/fa/Basics/workspaces/README.md @@ -0,0 +1,23 @@ +## Workspaces help organize your separate projects. + +If this is your first time to Remix, a Workspace named **default_workspace** is loaded in the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/default_workspace.png) + +The **default_workspace** has three Solidity (.sol) files in the contracts folder. Remix has a number of other templates. When you load a template, it goes into a Workspace. To go between Workspaces, use the select box at the top of the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/select-box.png) + +But Workspaces are not only for templates. When cloning a repo into Remix, the files will be put into a Workspace. + +Let's create a new Workspace + +1. At the top of the File Explorer, click the hamburger icon (the 3 horizontal lines). Read through the commands and tools in this menu. + +2. Select **+ Create** (the first choice). + +3. In the modal the comes up, choose one of the templates. + +![hamburger](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/workspaces/images/popup.png) + +Notice that in this popup menu, you can clone a repo. Managing a Git repo happens in the DGit plugin. You can also create Github actions with the three workflow choices in the popup menu. diff --git a/locales/fa/CircomHashChecker/README.md b/locales/fa/CircomHashChecker/README.md new file mode 100644 index 000000000..20391a668 --- /dev/null +++ b/locales/fa/CircomHashChecker/README.md @@ -0,0 +1,14 @@ +Hash Checker Tutorial + +This tutorial guides you through creating and understanding a Hash Checker circuit using Remix-IDE. You'll learn how to generate the circuit using a template, explore the code, perform a trusted setup, generate proofs, and verify them. This tutorial is suitable for beginners familiar with Circom and Zero-Knowledge Proofs. + +Prerequisites + +``` +Basic understanding of Zero-Knowledge Proofs and Circom. +Familiarity with Remix-IDE. +``` + +Estimated Time + +Approximately 1-2 hours. diff --git a/locales/fa/CircomHashChecker/config.yml b/locales/fa/CircomHashChecker/config.yml new file mode 100644 index 000000000..2c2aae80a --- /dev/null +++ b/locales/fa/CircomHashChecker/config.yml @@ -0,0 +1,35 @@ +id: circom-hash-checker +name: Hash Checker Tutorial +summary: A tutorial on creating and understanding a Hash Checker circuit using Remix-IDE templates, including trusted setup and proof generation. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction to the Hash Checker Circuit + path: step-1 + - + name: Generating the Hash Checker Template in Remix-IDE + path: step-2 + - + name: Exploring calculate_hash.circom + path: step-3 + - + name: Compiling the Circuit + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Compute Witness + path: step-6 + - + name: Generate Proof + path: step-7 + - + name: Exploring the Trusted Setup Script (Optional) + path: step-8 + - + name: Exploring the Proof Generation Script (Optional) + path: step-9 diff --git a/locales/fa/CircomHashChecker/step-1/README.md b/locales/fa/CircomHashChecker/step-1/README.md new file mode 100644 index 000000000..be922e93b --- /dev/null +++ b/locales/fa/CircomHashChecker/step-1/README.md @@ -0,0 +1,8 @@ +In this tutorial, we'll explore the **Hash Checker** circuit, a zero-knowledge proof (ZKP) application using Circom and Remix-IDE. The Hash Checker circuit allows you to prove knowledge of certain inputs that hash to a given value without revealing the inputs themselves. + +### What You'll Learn + +- How to generate a Hash Checker circuit using Remix-IDE's workspace templates. +- Understanding the Circom code for hashing and checking hashes. +- Performing a trusted setup using Groth16. +- Generating zero-knowledge proofs. diff --git a/locales/fa/CircomHashChecker/step-2/README.md b/locales/fa/CircomHashChecker/step-2/README.md new file mode 100644 index 000000000..bc827019e --- /dev/null +++ b/locales/fa/CircomHashChecker/step-2/README.md @@ -0,0 +1,37 @@ +Follow these steps to create the Hash Checker workspace in Remix-IDE. + +### Step 1: Access the Workspace Templates + +1. In the **File Explorer** sidebar, click on the **hamburger menu icon** (three horizontal lines). + + hamburger-menu + +2. Select **"Create Using Template"** from the dropdown. + + create-using-template + +### Step 2: Find the Hash Checker Template + +1. In the main panel, scroll down to the **"Circom ZKP"** section. + + create-zkp-section + +2. Locate the **"Hash Checker"** item. + +### Step 3: Create the Workspace + +1. Click on the **"Create"** button on the Hash Checker item. + + create-hash-checker + +2. In the modal pop-up, provide a **workspace name** (e.g., `hash-checker-workspace`). + + workspace-name-modal + +3. Click **"OK"** to create the template. + +### Result + +- The workspace is created with the necessary files and directories. + + workspace-name-modal diff --git a/locales/fa/CircomHashChecker/step-3/README.md b/locales/fa/CircomHashChecker/step-3/README.md new file mode 100644 index 000000000..b3ac14050 --- /dev/null +++ b/locales/fa/CircomHashChecker/step-3/README.md @@ -0,0 +1,32 @@ +## Exploring `calculate_hash.circom` + +Navigate to the `circuits` directory and open `calculate_hash.circom`. This file contains the Circom code for the Hash Checker circuit. + +### Code Breakdown + +#### Pragma and Includes: + +- `pragma circom 2.0.0;` specifies the Circom version. +- `include "circomlib/circuits/poseidon.circom";` fetch and includes the Poseidon hash function from [CircomLib](https://github.com/iden3/circomlib). + +#### `CalculateHash` Template: + +- Defines inputs `value1`, `value2`, `value3`, `value4`. +- Uses the `Poseidon` hash function to compute a hash of these values.\ +- Outputs `out`, which is the hash. + +#### `HashChecker` Template: + +- Inputs are the same values plus a `hash`. +- Instantiates `CalculateHash` as `calculateSecret`. +- Computes `calculatedHash`. +- Uses `assert(hash == calculatedHash);` to ensure the provided hash matches the calculated hash. + +#### Main Component: + +- `component main {public [hash]} = HashChecker();` +- Specifies that `hash` is a `public` input, while the values are `private`. + +### Purpose + +The circuit allows someone to prove they know `value1`, `value2`, `value3`, and `value4` that hash to a specific `hash` without revealing the values themselves. diff --git a/locales/fa/CircomHashChecker/step-4/README.md b/locales/fa/CircomHashChecker/step-4/README.md new file mode 100644 index 000000000..537c6a241 --- /dev/null +++ b/locales/fa/CircomHashChecker/step-4/README.md @@ -0,0 +1,32 @@ +## Compiling the Circuit + +### Selecting the Compiler Version + +1. Go to the **Circuit Compiler** plugin in the sidebar. +2. Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +### Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +### Compiling the Circuit + +1. Click on the **Compile** button. +2. Wait for the compilation to complete. A success badge will appear if compilation is successful. + +compilation-success + +### Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/fa/CircomHashChecker/step-5/README.md b/locales/fa/CircomHashChecker/step-5/README.md new file mode 100644 index 000000000..c3ea8509b --- /dev/null +++ b/locales/fa/CircomHashChecker/step-5/README.md @@ -0,0 +1,25 @@ +## Performing a Trusted Setup + +1. **Access the Setup and Exports Section**: + +- After successful compilation, the **Setup and Exports** section becomes available in the plugin. + +2. **Select Proving Scheme**: + +- Choose **Groth16** from the **Proving Scheme** dropdown. + +3. **Select Power of Tau File**: + +- Choose the appropriate **Power of Tau** file from the dropdown. If unsure, use the default option. + +4. **Export Verification Key and Contract** (optional): + +- Enable **Export Verification Key** to save the verification key to the File Explorer. +- Enable **Export Verifier Contract** to save the Solidity contract for on-chain verification. + +trusted-setup + +5. **Run the Trusted Setup**: + +- Click on the **Run Setup** button. +- Wait for the process to complete. This may take some time depending on the circuit complexity. diff --git a/locales/fa/CircomHashChecker/step-6/README.md b/locales/fa/CircomHashChecker/step-6/README.md new file mode 100644 index 000000000..03b848f81 --- /dev/null +++ b/locales/fa/CircomHashChecker/step-6/README.md @@ -0,0 +1,28 @@ +## Compute Witness + +1. **Access the Compute Witness Section**: + - After the trusted setup, the **Compute Witness** section becomes available. + +2. **Input Values**: + - You'll see input fields for `value1`, `value2`, `value3`, `value4`, and `hash`. + - Enter values for each input. For example: + - `value1`: `1234` + - `value2`: `2` + - `value3`: `3` + - `value4`: `4` + +3. **Calculate the Hash**: + + - Compute the Poseidon hash of the four values using an external tool or library compatible with the Poseidon hash function. + - For the values above, here is the computed Poseidon hash `16382790289988537028417564277589554649233048801038362947503054340165041751802`. + - Enter the calculated `hash` value in the `hash` input field. + + compute-witness + +4. **Compute the Witness**: + + - Click on the **Compute Witness** button. + - Wait for the process to complete. A success badge will appear if the witness is computed successfully. + - If successful, you'll see `calculate_hash.wtn` created in the `.bin` directory in the file explorer. + + witness-computed diff --git a/locales/fa/CircomHashChecker/step-7/README.md b/locales/fa/CircomHashChecker/step-7/README.md new file mode 100644 index 000000000..e6ae80fea --- /dev/null +++ b/locales/fa/CircomHashChecker/step-7/README.md @@ -0,0 +1,21 @@ +## Generate Proof + +1. **Access the Generate Proof Section**: + - After computing the witness, expand the **Generate Proof** section. + +2. **Configure Proof Generation**: + - **Export Verifier Calldata**: Enable this option if you plan to verify the proof on-chain. + +3. **Generate the Proof**: + + - Click on the **Generate Proof** button. + - Wait for the proof generation to complete. + + generate-proof + +4. **View the Proof**: + + - The proof data will be displayed in the File Explorer. + - **Congratulations!** You've successfully compiled the `Hash Checker` circuit, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + + generate-proof diff --git a/locales/fa/CircomHashChecker/step-8/README.md b/locales/fa/CircomHashChecker/step-8/README.md new file mode 100644 index 000000000..e489a8cab --- /dev/null +++ b/locales/fa/CircomHashChecker/step-8/README.md @@ -0,0 +1,34 @@ +## Understanding `groth16_trusted_setup.ts` + +Navigate to `scripts/groth16/groth16_trusted_setup.ts`. This script performs the trusted setup necessary for generating proofs. + +### Code Breakdown + +#### Circuit Compilation: + +- Uses `remix.call('circuit-compiler', 'generateR1cs', ...)` to generate `R1CS` (Rank-1 Constraint System) from the circuit. + +#### Trusted Setup Steps: + +- `snarkjs.zKey.newZKey`: Initializes the proving key (`zkey_0`). +- `snarkjs.zKey.contribute`: Adds contributions to the proving key (`zkey_1`). +- `snarkjs.zKey.beacon`: Finalizes the proving key (`zkey_final`). + +#### Verification: + +- `snarkjs.zKey.verifyFromR1cs`: Verifies the proving key against the `R1CS` and initial parameters. + +#### Exporting Keys: + +- Exports the verification key to `scripts/groth16/zk/keys/verification_key.json`. +- Exports the final proving key (`scripts/groth16/zk/keys/zkey_final.txt`). + +### Purpose + +- Performs the trusted setup required for the `Groth16` proving system. +- Generates the necessary keys for proof generation and verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"setup done."` logged in the terminal. diff --git a/locales/fa/CircomHashChecker/step-9/README.md b/locales/fa/CircomHashChecker/step-9/README.md new file mode 100644 index 000000000..653d5ced1 --- /dev/null +++ b/locales/fa/CircomHashChecker/step-9/README.md @@ -0,0 +1,37 @@ +## Understanding `groth16_zkproof.ts` + +Navigate to `scripts/groth16/groth16_zkproof.ts`. This script generates the zero-knowledge proof and prepares it for verification. + +### Code Overview + +#### Loading Files: + +- Reads the R1CS and WASM files generated from the circuit. +- Loads the final proving key (`zkey_final`) and verification key (`vKey`). + +#### Defining Inputs: + +- Sets the private values (`value1`, `value2`, `value3`, `value4`). +- Computes the `hash` using Poseidon from [CircomLib](https://github.com/iden3/circomlib). + +#### Witness Calculation and Proof Generation: + +- Calculates the witness (`wtns`). +- Checks the witness against the `R1CS`. +- Generates the proof using `Groth16`. +- Verifies the proof. + +#### Exporting Verifier Contract and Inputs: + +- Generates a Solidity verifier contract. +- Exports the proof inputs to `input.json`. + +### Purpose + +- Generates a zero-knowledge proof that the prover knows values hashing to a specific hash. +- Prepares the verifier contract and inputs for on-chain verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"zk proof validity"` logged in the terminal. diff --git a/locales/fa/CircomIntro/README.md b/locales/fa/CircomIntro/README.md new file mode 100644 index 000000000..c58b2daec --- /dev/null +++ b/locales/fa/CircomIntro/README.md @@ -0,0 +1,21 @@ +Intro to Circom + +This is an introduction to Circom. You'll learn how to write, compile, and test arithmetic circuits in Circom. We'll go over how to do this within Remix-IDE. + +Tutorial Overview + +``` +Step 1: Introduction +Step 2: Setting Up Remix-IDE and Installing the Circuit-Compiler Plugin +Step 3: Writing Your First Circom Circuit +Step 4: Compiling the Circuit Using the Plugin +Step 5: Performing a Trusted Setup +Step 6: Computing the Witness +Step 7: Generating the Proof +``` + +Prerequisites: + +``` +Basic understanding of cryptography and zero-knowledge proofs is helpful but not required. +``` diff --git a/locales/fa/CircomIntro/config.yml b/locales/fa/CircomIntro/config.yml new file mode 100644 index 000000000..d6dfdca46 --- /dev/null +++ b/locales/fa/CircomIntro/config.yml @@ -0,0 +1,29 @@ +id: circom-intro +name: Intro to Circom +summary: A intro to using Circom for creating arithmetic circuits. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction + path: step-1 + - + name: Installing the Circuit-Compiler + path: step-2 + - + name: Writing Your First Circom Circuit + path: step-3 + - + name: Compiling the Circuit Using the Plugin + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Computing the Witness + path: step-6 + - + name: Generating the Proof + path: step-7 diff --git a/locales/fa/CircomIntro/step-1/README.md b/locales/fa/CircomIntro/step-1/README.md new file mode 100644 index 000000000..0766ce6f4 --- /dev/null +++ b/locales/fa/CircomIntro/step-1/README.md @@ -0,0 +1,13 @@ +Welcome to this beginner-level tutorial on Circom using Remix. In this tutorial, you'll learn the basics of Circom, a domain-specific language used for creating arithmetic circuits. + +**What is Circom?** + +Circom is a language designed for writing arithmetic circuits that can be used in zero-knowledge proofs, particularly zk-SNARKs. It allows developers to define complex mathematical circuits that can prove knowledge of certain data without revealing it. + +**Why Use Remix-IDE for Circom?** + +- **Ease of Use:** Remix-IDE provides a user-friendly interface that simplifies the development process. +- **Integrated Tools:** With plugins like `circuit-compiler`, you can compile Circom code, perform trusted setups, compute witnesses, and generate proofs all within the same environment. +- **No Installation Required:** As a web-based IDE, you can start coding immediately without setting up a local development environment. + +In the next steps, we'll guide you through setting up Remix-IDE for Circom development and help you write your first circuit. diff --git a/locales/fa/CircomIntro/step-2/README.md b/locales/fa/CircomIntro/step-2/README.md new file mode 100644 index 000000000..4b228c298 --- /dev/null +++ b/locales/fa/CircomIntro/step-2/README.md @@ -0,0 +1,25 @@ +In this step, we'll set up Remix for Circom development by activating the `Circom ZKP compiler` plugin. + +## Activating the Circom ZKP compiler + +1. At the bottom of the icon panel on the left of the screen, click on the **Plugin Manager** (the plug icon). + 2.In the search bar, type **Circom**. +2. Find the **Circuit Compiler** plugin in the list and click on the **Activate** button. +3. The plugin will now appear in your sidebar. + +install-plugin + +## The Circom Compiler Interface + +- **Compiler Version Dropdown:** Select the Circom compiler version you wish to use. +- **Auto Compile Checkbox:** Enable this to automatically compile your circuit whenever you make changes. +- **Hide Warnings Checkbox:** Enable this to suppress compiler warnings. +- **Advanced Configuration:** Click to expand options for selecting the prime field (e.g., BN128, BLS12381). + +compiler-interface + +With the plugin installed, you're now ready to start writing Circom code in Remix-IDE. + +**Note:** Make sure your internet connection is stable, as Remix-IDE is a web-based tool. + +In the next step, we'll write our first Circom circuit. diff --git a/locales/fa/CircomIntro/step-3/README.md b/locales/fa/CircomIntro/step-3/README.md new file mode 100644 index 000000000..6424668f6 --- /dev/null +++ b/locales/fa/CircomIntro/step-3/README.md @@ -0,0 +1,38 @@ +Let's write a simple Circom circuit. + +## Creating a New Circuit File + +1. In the **File Explorer** on the left sidebar, click on the **Create New File** icon. +2. Name your file `multiplier.circom` and press **Enter**. + +create-new-file + +## Writing the Circuit + +Open `multiplier.circom` and add the following code: + +```circom +pragma circom 2.0.0; + +template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; +} + +component main = Multiplier(); +``` + +## Explanation: + +- template `Multiplier()`: Defines a new circuit template called Multiplier. +- `signal input a;` and `signal input b;`: Declare input signals a and b. +- `signal output c;`: Declare an output signal c. +- `c <== a * b;`: Constrain c to be the product of a and b. +- `component main = Multiplier();`: Instantiates the Multiplier circuit as main, which is required for the compiler. + +### NB: + +Signals are values in a cryptographic circuit that are strictly determined by the circuit's equations and constraints. Think of a signal as a value that must follow specific mathematical rules defined by the circuit—once set, it can't be changed arbitrarily. In regular programming, variables are flexible and can be updated or reassigned as needed, whereas, signals can't be altered freely. diff --git a/locales/fa/CircomIntro/step-4/README.md b/locales/fa/CircomIntro/step-4/README.md new file mode 100644 index 000000000..ad3f2a089 --- /dev/null +++ b/locales/fa/CircomIntro/step-4/README.md @@ -0,0 +1,34 @@ +With your `multiplier.circom` circuit ready, let's compile it using the Circuit Compiler plugin. + +## Selecting the Compiler Version + +Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +## Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +## Compiling the Circuit + +1. Click on the **Compile** button. +2. The compiler will process your circuit. +3. If successful, you'll see a compilation success message. + +compilation-success + +**Note:** If there are any errors, they will be displayed in the console. Check your code for typos or syntax errors. + +## Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/fa/CircomIntro/step-5/README.md b/locales/fa/CircomIntro/step-5/README.md new file mode 100644 index 000000000..8e8496bbd --- /dev/null +++ b/locales/fa/CircomIntro/step-5/README.md @@ -0,0 +1,26 @@ +After compiling your circuit, you need to perform a trusted setup to generate proving and verification keys. + +## Understanding Trusted Setup + +- **Trusted Setup:** A process required for zk-SNARKs to generate the necessary parameters for proof generation and verification. +- You can choose between different protocols like **Groth16** and **Plonk**. + +## Performing the Trusted Setup + +1. In the **Setup and Exports** section, select the **Proving Scheme**: + - Choose between **Groth16** or **Plonk**. We'll use **Groth16** for this tutorial. + +2. Choose the appropriate **Power of Tau** file from the dropdown. This file is necessary for the trusted setup. + - If unsure, select the default option. + +3. Click on the **Setup** button to start the trusted setup process. + +4. You can enable **Export Verification Key** to get the verification parameters. + +5. You can enable **Export Verification Contract** if you intend to verify proofs on-chain. + +trusted-setup + +**Note:** The trusted setup may take some time, depending on the complexity of your circuit. + +In the next step, we'll compute the witness for our circuit. diff --git a/locales/fa/CircomIntro/step-6/README.md b/locales/fa/CircomIntro/step-6/README.md new file mode 100644 index 000000000..e13d33d32 --- /dev/null +++ b/locales/fa/CircomIntro/step-6/README.md @@ -0,0 +1,27 @@ +With the trusted setup complete, you can now compute the witness for your circuit based on specific inputs. + +## What is a Witness? + +- A **Witness** is a set of values that satisfy all the constraints of your circuit. It includes all the intermediate numbers and results that satisfy the circuit's rules. The witness is used in zero-knowledge proofs to demonstrate that you know a valid solution to the problem without actually showing the solution itself. This allows others to verify that you did everything correctly while keeping your specific numbers and calculations private. +- It is essential for generating a proof. + +## Inputting Values + +1. In the **Compute Witness** section, you'll see input fields dynamically generated based on your circuit's inputs. +2. Enter values for `a` and `b`. For example: + - `a = 3` + - `b = 4` + +compute-witness + +## Computing the Witness + +1. After entering the inputs, click on the **Compute Witness** button. +2. The plugin will compute the witness based on your inputs. +3. If successful, you'll see `multiplier.wtn` created in the `.bin` directory in the file explorer. + +witness-computed + +**Note:** If there are any errors, ensure that your inputs are valid and satisfy the circuit's constraints. + +In the next step, we'll generate a proof using the computed witness. diff --git a/locales/fa/CircomIntro/step-7/README.md b/locales/fa/CircomIntro/step-7/README.md new file mode 100644 index 000000000..f5cf332a9 --- /dev/null +++ b/locales/fa/CircomIntro/step-7/README.md @@ -0,0 +1,31 @@ +With the witness computed, the final step is to generate a proof that can be verified by others. + +## Generating the Proof + +1. In the **Generate Proof** section, you have the option to **Export Verifier Calldata**. + - Enable the **Export Verifier Calldata** checkbox if you plan to verify the proof on-chain. +2. Click on the **Generate Proof** button. + +generate-proof + +## Understanding the Output + +- After generating the proof, the plugin will display the proof data. +- If you enabled **Export Verifier Calldata**, it will also provide the calldata needed for on-chain verification. + +proof-generated + +## Next Steps + +- **Verification:** You can use the verification key or contract exported earlier to verify the proof. +- **On-Chain Verification:** If you're familiar with smart contracts, you can deploy the verification contract and use the calldata to perform on-chain verification. + +**Congratulations!** You've successfully written a Circom circuit, compiled it, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + +## Additional Resources + +- [Circom Documentation](https://docs.circom.io/) +- [Remix-IDE Documentation](https://remix-ide.readthedocs.io/) +- [Zero-Knowledge Proofs Explained](https://zkproof.org/) + +Feel free to experiment with more complex circuits and explore the capabilities of Circom and Remix-IDE further. diff --git a/locales/fa/DeployWithLibraries/1_Writing_a_Library/step1.md b/locales/fa/DeployWithLibraries/1_Writing_a_Library/step1.md new file mode 100644 index 000000000..1ad984835 --- /dev/null +++ b/locales/fa/DeployWithLibraries/1_Writing_a_Library/step1.md @@ -0,0 +1,17 @@ +A libraries looks like a **contract** but use the keyword `library` + +A library typically is a collection of useful functions sitting out there on the blockchain that any contract can use. Because the library is already deployed, it saves the deployment costs of the many contracts that use it. + +In the following contract: + +- Make a library with the name `LibraryForTest`. + +It is possible to put a library in same file with another contract. So put the library below the contract. + +This library should have a method called `getFromLib` method which returns `3`. + +- Update the `get` method in the `test` contract to use the `LibraryForTest` library. The function `get` should return the value it receives from `getFromLib`. + +--------- + +You can find more info about libraries in this section of the Solidity Docs. diff --git a/locales/fa/DeployWithLibraries/2_Generate_Metadata/step2.md b/locales/fa/DeployWithLibraries/2_Generate_Metadata/step2.md new file mode 100644 index 000000000..218c86ff9 --- /dev/null +++ b/locales/fa/DeployWithLibraries/2_Generate_Metadata/step2.md @@ -0,0 +1,38 @@ +## Deploying Library + +The **library** from the previous chapter was in the same file as the **contract**. However, they won't be deployed together and will have different addresses. + +In order to use a library, the calling contract must have the library's **address**. + +But the library's address is not directly specified in the solidity code. The calling contract's compiled bytecode contains a **placeholder** where library's **addresses** will go. + +At deployment of the **calling contract**, Remix will look in the contract's **metadata** for the library's address and will update the placeholder with the address. + +So before deploying a contract that calls a library, you need to generate the contract's metadata (AKA its **build artifact**) and then you need to input the library's address into the metadata file. + +A contract's metadata is generated at **compile time**. + +Let's setup Remix to generate the **metadata file**. + +- Go to the settings module by clicking on the settings ![settings](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/settings.png "Settings") icon in the icon panel. + +![settings module](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_settings.png "Settings Module") + +- And check the first option `Generate contract metadata`. + +# Compile and generate metadata (JSON) file. + +1. Open the Solidity Compiler ![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +2. Compile `2_contractSimpleLibrary.sol`. + +3. Switch to the File Explorer ![File Explorer](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_file_explorer.png "File Explorer") + +4. Navigate to the newly create JSON files. + - It should be in the folder: + +**browser/.learneth/DeployWithLibraries/2_Generate_Metadata/artifacts/** + +5. Select the newly created JSON file created from the contract. It has the **same name** as the contract `sample` but with the extension **json**: `sample.json` (don't select the library's metadata `contractSimpleLibrary.json`). + +In the next step we'll make some adjustments to the metadata file. diff --git a/locales/fa/DeployWithLibraries/3_Edit_Metadata/step3.md b/locales/fa/DeployWithLibraries/3_Edit_Metadata/step3.md new file mode 100644 index 000000000..1555d645d --- /dev/null +++ b/locales/fa/DeployWithLibraries/3_Edit_Metadata/step3.md @@ -0,0 +1,12 @@ +The `Deploy` property in `sampleContract.json` contains everything you need for telling Remix IDE the address of the library for a specific network. + +- `
` contains the address of the library that is already deployed. You have to specify this address for each network. +- `autoDeployLib` is a boolean and tells Remix IDE if it should autodeploy the library before deploying the contract. + +Basically if `autoDeployLib` is **true**, the `
` will not be used and Remix will automatically deploy the library before deploying the contract. + +For the purpose of this demo - we are mimicking a situation where the library has already been deployed because this is a more common situation. + +So set `autoDeploy` to **false**, for the `VM:-` entry. + +Move to next Step. diff --git a/locales/fa/DeployWithLibraries/4_Linking_and_Deploying/step4.md b/locales/fa/DeployWithLibraries/4_Linking_and_Deploying/step4.md new file mode 100644 index 000000000..ad5f52e2d --- /dev/null +++ b/locales/fa/DeployWithLibraries/4_Linking_and_Deploying/step4.md @@ -0,0 +1,25 @@ +Switch to the `Deploy & Run` module +![Run transaction](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/remix_runtransaction.png "Run Transaction") + +- Select the Remix VM Environment and select the `sampleContract` contract in the list of compiled contracts. + +- Click on `Deploy` + +The terminal should output something like `creation of sample errored:
is not a valid address. Please check the provided address is valid.` +That is expected: **We have set `autoDeployLib` to false, so Remix expects to have an address and not just `
`** + +So we need deploy the library to get its address. + +- Select the library `aLib` in the list of compiled contract and hit `deploy` + + ![Choose aLib](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/contract_alib.png "Choose aLib") + +- Click the clipboard icon to copy the address of the library. + + ![Copy lib1](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/alib_copy.png "Copy") + +- Paste it into the **contract sample's** metadata JSON. + +- Reselect the `sampleContract` contract in the `Run transaction` module and hit deploy. + +- Deploy should now be successful. diff --git a/locales/fa/DeployWithLibraries/5_Under_The_Hood/step5.md b/locales/fa/DeployWithLibraries/5_Under_The_Hood/step5.md new file mode 100644 index 000000000..860b48b24 --- /dev/null +++ b/locales/fa/DeployWithLibraries/5_Under_The_Hood/step5.md @@ -0,0 +1,30 @@ +Switch to the `Solidity compiler` module +![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +- Select the `sampleContract` contract in the list of compiled contracts. +- click on `ByteCode`, it should copy the following to the clipboard: + +``` +{ + "linkReferences": { + "browser/contractSimpleLibrary.sol": { + "lib1": [ + { + "length": 20, + "start": 115 + } + ] + } + }, + "object": "608060405234801561001057600080fd5b5060f68061001f6000396000f3fe6080604052600436106039576000357c0100000000000000000000000000000000000000000000000000000000900480636d4ce63c14603e575b600080fd5b348015604957600080fd5b5060506052565b005b73__$d42d70ba92b626965f4c69b39148e37a33$__63fea24e5f6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801560b157600080fd5b505af415801560c4573d6000803e3d6000fd5b5050505056fea165627a7a7230582068c9a3a9a5cbfd26cfdab2534abfc926912d9b89eaa14e36c8248b7e7eb0ab090029", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xF6 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x39 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x3E JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x50 PUSH1 0x52 JUMP JUMPDEST STOP JUMPDEST PUSH20 0x0 PUSH4 0xFEA24E5F PUSH1 0x40 MLOAD DUP2 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH1 0xB1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS DELEGATECALL ISZERO DUP1 ISZERO PUSH1 0xC4 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 PUSH9 0xC9A3A9A5CBFD26CFDA 0xb2 MSTORE8 0x4a 0xbf 0xc9 0x26 SWAP2 0x2d SWAP12 DUP10 0xea LOG1 0x4e CALLDATASIZE 0xc8 0x24 DUP12 PUSH31 0x7EB0AB09002900000000000000000000000000000000000000000000000000 ", + "sourceMap": "63:85:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63:85:0;;;;;;;" +} +``` + +This is basically what the compiler is returning: + +- `linkReferences` describes what are the libraries used by the contract. +- `object` is the compiled contract (bytecode). This is what gets deployed and saved onto the blockchain. In this example, the value `__$d42d70ba92b626965f4c69b39148e37a33$__` inside the bytecode is just a placeholder for the library address. In your case, the placeholder will be between `__$` and `$__`. + +The metadata JSON from Remix IDE tells Remix to replace the placeholder with the given address. diff --git a/locales/fa/DeployWithLibraries/README.md b/locales/fa/DeployWithLibraries/README.md new file mode 100644 index 000000000..fb31b1264 --- /dev/null +++ b/locales/fa/DeployWithLibraries/README.md @@ -0,0 +1,3 @@ +**Libraries** are deployed contracts that do not store state and are used by other contracts to decrease their size and thus their deployment costs. + +Learn to work with **Libraries** in Remix - you won't need to whisper. diff --git a/locales/fa/DeployWithLibraries/config.yml b/locales/fa/DeployWithLibraries/config.yml new file mode 100644 index 000000000..0816e2346 --- /dev/null +++ b/locales/fa/DeployWithLibraries/config.yml @@ -0,0 +1,8 @@ +--- +id: deploylibraries +name: Deploy with Libraries +summary: Write, Deploy and link a Library to a Contract +level: 3 +tags: + - Remix + - Solidity diff --git a/locales/fa/ERC20TokenCourse/README.md b/locales/fa/ERC20TokenCourse/README.md new file mode 100644 index 000000000..25a6ccf95 --- /dev/null +++ b/locales/fa/ERC20TokenCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Token Course + +Learn to understand and create ERC20 tokens. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/fa/ERC20TokenCourse/config.yml b/locales/fa/ERC20TokenCourse/config.yml new file mode 100644 index 000000000..8c12a5213 --- /dev/null +++ b/locales/fa/ERC20TokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: tokenCourse +name: Solidity ERC20 Token Course +summary: Learn how to create your own ERC20 tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - ERC20 +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc20-interface + - + name: 3. Token Creation + path: erc20-token-creation + - + name: 4. Interaction + path: erc20-interaction + - + name: 5. Testnet Deployment + path: erc20-testnet-deployment + - + name: 6. Extensions + path: erc20-extensions diff --git a/locales/fa/ERC20TokenCourse/erc20-extensions/erc20extensions.md b/locales/fa/ERC20TokenCourse/erc20-extensions/erc20extensions.md new file mode 100644 index 000000000..b3649fbba --- /dev/null +++ b/locales/fa/ERC20TokenCourse/erc20-extensions/erc20extensions.md @@ -0,0 +1,33 @@ +The ERC20 standard only describes the required and optional functionality that your contract needs, but you can add additional functionality. + +In this section, we added the functionality to burn and mint tokens, as well as the ability to pause the contract, by using OpenZeppelin extensions. + +Of course, you can write your own ERC20 token contract implementation or extensions and import them into your contract. But OpenZeppelin contracts have been audited by security experts and are a great way to add desired functionality. + +### Mintable + +The mint function allows the creator of the contract to mint (create) additional tokens after the contract has been deployed (line 22). As input parameters, the function needs the address that the tokens will be minted to, and the amount of tokens that should be minted. + +We don't have to import `mint()` from another contract since the mint function is already part of the ERC20 contract implementation of OpenZeppelin. We import `Ownable` (line 7) which is a contract module that provides a basic access control mechanism that allows an owner to have exclusive access to specific functions. In this contract, we add the inherited `onlyOwner` modifier to the `mint` function (line 22) and restrict access to this function to the "owner". + +The contract will inherit additional functions like owner(), transferOwnership() and renounceOwnership() to manage access, from the Ownable contract. + +### Burnable + +By importing the "ERC20Burnable" (line 5) and inheriting its functions (line 9) our contract allows token holders to destroy their tokens as well as the tokens in their allowance. +For more information, have a look at the ERC20Burnable contract. + +### Pausable + +With the "Pausable" contract module (line 6 and 9) the owner is able to pause (line 14) and unpause (line 18) the contract. In the pause state, tokens can't be transferred, which can be helpful in emergency scenarios. +For more information, have a look at the Pausable contract. + +Have a look at the OpenZeppelins Contract Wizard, which allows you to easily add additional functionality. + +If you successfully completed this course, try the Learneth NFT Course as the next step in your journey. + +## ⭐️ Assignment + +1. Try to mint tokens to an account after deployment. Call `totalSupply()` and `balanceOf()` to confirm the correct execution. +2. Burn tokens and then call `totalSupply()` and `balanceOf()` to confirm the correct execution. +3. Test the pause function by pausing the contract using the owner account and trying to make a transfer with a second account. The transaction should not be able to be executed and will throw the exception: "Pausable: paused". diff --git a/locales/fa/ERC20TokenCourse/erc20-interaction/er20interaction.md b/locales/fa/ERC20TokenCourse/erc20-interaction/er20interaction.md new file mode 100644 index 000000000..5c082b248 --- /dev/null +++ b/locales/fa/ERC20TokenCourse/erc20-interaction/er20interaction.md @@ -0,0 +1,87 @@ +In this section, we will deploy a contract in our browser and test its functionality. + +### 1. Deploy the contract + +**1.1** Compile your EduCoin contract in the "Solidity compiler" module of the Remix IDE. + +**1.2** In the "Deploy & run transactions" module, select your contract "EduCoin" in the contract input field and click on the "Deploy" button. Always make sure to select the correct contract in the contract selector input field. + +**GIF** Compile and deploy: Compile and deploy contract + +### 2. Test the functions + +Expand the token contract functions in the IDE. + +#### 2.1 Decimals + +Click on the "decimals" button to call the decimals() function. +It should return "18". + +#### 2.2 Name + +Click on the "name" button to call the name() function. +It should return "EduCoin". + +#### 2.3 Symbol + +Click on the "symbol" button to call the symbol() function. +It should return "EDC". + +#### 2.4 Total supply + +Click on the "totalSupply" button to call the totalSupply() function. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test decimals, name, symbol, and totalSupply functions: Test transfer function + +#### 2.5 Balance of + +**2.5.1** Go to the "ACCOUNT" section in the sidebar and copy the displayed address by using the copy icon next to it. + +**2.5.2** Paste the address in the input field next to the "balanceOf" function button and click on the button. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test balanceOf function: Test transfer function + +#### 2.6 Transfer + +We will transfer EduCoin from one account to a second account. + +**2.6.1** Go to the "ACCOUNT" section in the sidebar and click on the displayed address. This should open a dropdown. Select the second address displayed and copy its address (account 2). + +**2.6.2** Open the dropdown and select the first account again (account 1), because this is the account that we want to use to make the transfer. + +**2.6.3** Paste the address in the input field next to the "transfer" function button, input the number 500000000000000000000, and click on the button. + +**2.6.4** If you check the balances for account 1 and account 2, they should both return the amount 500000000000000000000. + +**GIF** Test transfer function: Test transfer function + +#### 2.7 Approve + +We will now allow account 1 to spend tokens on behalf of account 2. + +**2.7.1** Go to the "Account" section, copy the address of account 1, then set it to account 2 again. + +**2.7.2** In the approve function, enter the address of account 1 as the input for spender and set the amount to 250000000000000000000. + +**GIF** Test approve function: Test approve function + +#### 2.8 Allowance + +Next to the "allowance" button enter the address of account 2 as the owner and account 1 as the spender; click on the button. +It should return 1000000000000000000000. + +**GIF** Test allowance function: Test allowance function + +#### 2.9 TransferFrom + +Now account 1 will transfer 250000000000000000000 tokens from account 2 to its own account. + +**2.9.1** Select account 1 in the "ACCOUNT" section. + +**2.9.2** Next to the "transferFrom" button enter the address of account 2 as the sender and account 1 as the recipient, enter 250000000000000000000 as the amount and click on the button. + +**2.9.3** Check the balances of accounts 2 and 1, they should return 250000000000000000000 and 750000000000000000000. + +**GIF** Test transferFrom function: Test transferFrom function diff --git a/locales/fa/ERC20TokenCourse/erc20-interface/erc20interface.md b/locales/fa/ERC20TokenCourse/erc20-interface/erc20interface.md new file mode 100644 index 000000000..5c4e8137c --- /dev/null +++ b/locales/fa/ERC20TokenCourse/erc20-interface/erc20interface.md @@ -0,0 +1,76 @@ +ERC20 (Ethereum Request for Comments 20) is a standard for token contracts that manages fungible tokens on the Ethereum blockchain. + +Fungible tokens are all equal to each other and have the same value, behavior, and rights. Fungible tokens are often used as a medium of exchange, like the currencies ETH or BTC. However, they can also have other use cases like voting rights or reputation. + +If you want to know more about the ERC20 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +To get an overview of the required functionality of an ERC20 token contract, we will look at an interface that interacts with an ERC20 contract. +This interface (line 9) is part of the open-source contract library provided by OpenZeppelin. + +## ERC20 Functions + +Contracts compliant with the ERC20 standard must implement the following six functions: + +### totalSupply + +The function `totalSupply` (line 13) returns the total amount of tokens available. + +### balanceOf + +The function `balanceOf` (line 18) returns the amount of tokens owned by the account with the address `account`. + +### transfer + +The function `transfer` (line 27) transfers `amount` of tokens to the address `recipient`. +This function **must** emit (produce) a `Transfer` event (see below) and **should** throw an exception when the sender doesn't have enough tokens to make the transfer. + +### approve + +The function `approve` (line 52) creates an allowance for the address `spender` to transfer `amount` of tokens on behalf of the account calling the function. + +### allowance + +The function `allowance` (line 36) returns the amount of tokens that the address `spender` is allowed to spend on behalf of the account with the address `owner`. + +### transferFrom + +The function `transferFrom` (line 63) transfers `amount` of tokens on behalf of the address `sender` to the address `recipient`. +This function **must** emit a `Transfer` event. + +## ERC20 Events + +ERC20 contracts must also emit two events: + +### Transfer + +The `Transfer` (line 71) event must be emitted when `value` amount of tokens are transferred from the account with the address `indexed from` to `indexed to`. The parameters `from` and `to` are `indexed` allowing us to search for these events using the indexed parameters as filters. + +### Approval + +The `Approval` (line 77) event must be emitted when the account `indexed owner` approves the account `indexed spender` to transfer `value` amount of tokens on its behalf. + +## ERC20 Optional functions + +In addition to the mandatory functions and events, there are also three optional functions specified in the ERC20 standard that are not implemented in this interface: + +### name + +`function name() external view returns (string);` + +Returns the name of the token. + +### symbol + +`function symbol() external view returns (string);` + +Returns the symbol of the token. + +### decimals + +`function decimals() external view returns (uint8);` + +Returns the number of decimal places the token uses. + +You may want to use decimals to make your token divisible into arbitrary amounts like 1.5 ETH when displayed. The EVM (Ethereum virtual machine) only supports integer numbers. That's why the ERC20 standard suggests to implement the decimal functionality that specifies how many decimal places a token has. 18 decimal places is the industry standard. diff --git a/locales/fa/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md b/locales/fa/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md new file mode 100644 index 000000000..94b513922 --- /dev/null +++ b/locales/fa/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md @@ -0,0 +1,41 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to a testnet of the Ethereum blockchain. This testnet behaves very similarly to the real blockchain (mainnet), but does not require real ETH to pay for transactions. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token + +In order to make transactions on the testnet we need Ethereum testnet tokens, which you can receive from something called a _faucet_. + +**2.1** Switch your Metamask network by clicking on the "Ethereum Mainnetwork" drop down and selecting "Ropsten Test Network". If you don’t see any test networks, click on the "Show/hide" link and enable "Show test networks" in the settings. + +**2.2** Go to https://faucet.ropsten.be/, enter the address of your account, and claim testnet ETH. You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Deployment + +Make sure the EduCoin contract is compiled. + +**3.1.** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It will ask you to connect your account which you should confirm. + +**3.2** Deploy the EduCoin contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. Copy the contract address. + +**3.4** In Metamask, click on assets, then click on the "Import tokens" link, and paste the address of your contract in the input field. + +You should now see a balance of 1000 EDC in your wallet. + +### 4. Make a transaction + +**4.1** Click on the identicon (visual representation of your address) in the Metamask wallet and create a second account (Account 2). + +**4.2** Copy the address of Account 2. + +**4.3** Switch to the first account (Account 1) and send 250 EDC to Account 2. Check the balances of Account 1 and Account 2. You might need to add the token address again for Account 2 to import the tokens and you will need testeth if you want to make a transaction with this account. + +You can also see your account balances if you look at the contract in Remix and call the `balanceOf` function using the addresses of Account 1 and Account 2. diff --git a/locales/fa/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md b/locales/fa/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md new file mode 100644 index 000000000..49b71abdd --- /dev/null +++ b/locales/fa/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md @@ -0,0 +1,18 @@ +A token standard tells us what functionality the contract needs to comply with it. How this functionality is implemented is up to the developers. In this contract, we will use an ERC20 token contract implementation from OpenZeppelin (line 4). In this case, we import version 4.4.0 of the OpenZeppelin contracts. + +Have a look at their nicely documented ERC20 contract to have a better understanding of how an implementation might look. Apart from the functionality specified in the ERC20 standard, this contract provides additional functionality. + +We will create our own contract called MyToken (line 6), which inherits the functionality from the OpenZepplin ERC20 token contract implementation that we imported (line 4). + +This contract implements the optional functions `name()` and `symbol()` of the ERC20 Token standard and has a constructor where their values can be set during the deployment of the contract (line 7). +In this case, we are going to use the default values. We will call our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +Next, we make use of the inherited `_mint` function (line 8) that allows us to create tokens upon deployment of the contract. Inside the parameters, we specify the address of the account that receives the tokens and the amount of tokens that are created. +In this case, the account that deploys the contract will receive the tokens and we set the amount to 1000000 to the power of `decimals()`. The optional function `decimals()` of the ERC20 token standard is implemented and set to the default value of 18. This will create 1000000 tokens that will have 18 decimal places. + +## ⭐️ Assignment + +1. Rename your contract to `EduCoin`. +2. Rename your token to `EduCoin`. +3. Change the symbol of your token to `EDC`. +4. Change the amount of tokens that will be minted from 1000000 to 1000. diff --git a/locales/fa/ERC20TokenCourse/introduction/introduction.md b/locales/fa/ERC20TokenCourse/introduction/introduction.md new file mode 100644 index 000000000..4eaf7583c --- /dev/null +++ b/locales/fa/ERC20TokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with the ERC20 token standard in the following sections. + +If you want to learn more about NFTs and the ERC721 token standard, have a look at the Learneth NFT Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/fa/ERC721Auction/README.md b/locales/fa/ERC721Auction/README.md new file mode 100644 index 000000000..325e4d60e --- /dev/null +++ b/locales/fa/ERC721Auction/README.md @@ -0,0 +1,5 @@ +## NFT Auction Contract + +Learn how to write an ERC721 (NFT) auction contract. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/fa/ERC721Auction/auction-contract-setup/auctionContractSetup.md b/locales/fa/ERC721Auction/auction-contract-setup/auctionContractSetup.md new file mode 100644 index 000000000..945f0f803 --- /dev/null +++ b/locales/fa/ERC721Auction/auction-contract-setup/auctionContractSetup.md @@ -0,0 +1,46 @@ +In this contract tutorial, we will learn how to create an ERC721 (NFT) auction contract. +We recommend to you, to do the Learneth "Solidity NFT Course" before starting this tutorial. + +In the following sections, we will create a contract that will enable a seller to auction an NFT to the highest bidder. This contract was created by the Solidity by Example project. In this first section, we will create an interface, the necessary state variables, and the constructor. + +### Interface + +We create the interface (line 5) for the ERC721 token since our contract will need to interact with it. We will need the `safeTransferFrom` (line 5), and` transferFrom` (line 11) methods. + +### EnglishAuction + +We create the four events `Start`, `Bid`, `Withdraw`, `End` (line 19-22) so we can log important interactions. + +Next, we will create the state variables that store all the necessary information about our auction on-chain. + +We create two state variables for the NFT we want to auction. In the variable `nft` (line 24) we store a representation of the NFT contract, that will allow us to call its functions by combining the interface IERC721 and the address of the NFT contract. +In `nftId` (line 25), we store the specific token id in our NFT contract that will be auctioned. + +Next, we need a variable to store the address of the person that is auctioning off the NFT, the `seller` (line 27). +We want our NFT contract to send the seller the proceeds of the auction when it is finished, that’s why use `address payable`. + +We create a state variable `endAt` (line 28) where we will store the end date of the auction. +We also create the two booleans, `started` (line 29) and `ended` (line 30), that keep track of whether the auction has started or ended. + +We create a variable `highestBidder` (line 32) where we will store the address of the highest bidder. We will send the highest bidder the NFT once the auction has ended. + +Finally, we need a uint `highestBid` (line 33) to store the highest bid and a mapping `bids` (line 34), where we can store the total value of bids that an account has made before withdrawing; more on this in the next section. + +### Constructor + +When the auctioneer deploys the contract, they need to provide a few arguments: +the address of the contract of the NFT they want to auction `_nft` (line 37), the token id of the NFT they want to auction `_nftId` (line 38), and a starting price that must be overbid to place the first bid in the auction,`_startingBid` (line 39). + +Once deployed, the state variables `nft` (line 41), `nftId` (line 42), `highestBid` (line 45) will be assigned the values from the arguments. The address of the `seller` that deployed the contract will be automatically read out via msg.sender and stored in the state variable `seller` (line 44). + +In the next section, we will enable the auctioneer to start the auction and bidders to place their bids. + +## ⭐️ Assignment + +We will use the assignment part of the following sections to give you instructions on testing your contract in the Remix VM environment of Remix. + +1. Deploy an NFT contract. You can use the NFT contract that we created in our "3.3 ERC721 - Token Creation" section. + +2. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +3. After deploying your contract, test if contract functions like `nft`, `nftId`, and `started` work as expected. diff --git a/locales/fa/ERC721Auction/auction-start-bid/auctionContractStartBid.md b/locales/fa/ERC721Auction/auction-start-bid/auctionContractStartBid.md new file mode 100644 index 000000000..c2b944e0c --- /dev/null +++ b/locales/fa/ERC721Auction/auction-start-bid/auctionContractStartBid.md @@ -0,0 +1,42 @@ +In this section, we will create a function to start the auction and a function to bid on the NFT. + +### Start + +We use some control structures to check if necessary conditions are met before we let the seller start the auction. + +First, we check if the auction has already started (line 49). If it has started and our state variable `started` returns `true` we exit the function and throw an exception. + +The second condition we check for is whether the seller is executing the function (line 50). We have already created a function to store the seller's address when they deploy the contract in the `seller` state variable and can now check if the account executing the start function is the seller. If not we throw an exception. + +Next, we want to transfer the NFT that is up for auction from the seller to the contract (line 52). +We set the state variable `started` to `true` (line 53), and create an end date for the auction (line 54). In this case, it will be seven days from when the start function has been called. We can use a suffix like `days` after a literal number to specify units of time. If you want to learn more about time units have a look at the solidity documentation. + +Finally, we will emit our `Start()` event (line 56). + +### Bid + +Before the function caller can make a bid, we need to be sure that certain conditions are met. The auction needs to have started (line 60), the auction can not have ended (line 61) and the bid (the value attached to the call) needs to be higher than the current highest bid (line 62). + +Now we want to store the bid of the current highest bidder before we make a new bid. +First, we check if there is a bidder (line 64). If this function call is the first bid then the next line would be irrelevant. +In our mapping `bids` (line 34) we map the key, the `address` of the bidder, to the value, a `uint` that represents the total amount of ETH a bidder has bid in the auction before withdrawing. +If there is a bidder, we add the last bid (`highestBid`) of the `highestBidder` to the total value of the bids they have made (line 65) before withdrawing. +We store the bids because we want to enable the bidder to withdraw the ETH they used to make bids if they are no longer the highest bidder. + +Next, we set the `highestBidder` to the account calling the function (line 68), and the `highestBid` to their bid, the value that was sent with the call (line 69). + +Finally, we emit the `Bid` event (line 71). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we create in our "Solidity NFT Course" Learneth course. + +2. Mint yourself an NFT with the tokenId 0. + +3. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +4. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for `tokenId`. This will allow the contract to transfer the token to be auctioned. + +5. Call the `start` function of your auction contract. If you call the `started` function now, it should return `true`. If you call the `highestBid` function it should return 1. + +6. Set the value that you can attach to transactions to 3 Wei and call the `bid` function of the auction contract. If you call the `highestBid` function it should now return 3. diff --git a/locales/fa/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md b/locales/fa/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md new file mode 100644 index 000000000..e324a5c6e --- /dev/null +++ b/locales/fa/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md @@ -0,0 +1,45 @@ +In this section, we will finish the contract, create a function to withdraw the bids that an account has made, and create a function to end the auction. + +### Withdraw + +We create a local variable `bal` (balance) that stores the total value of bids that the function caller has made (line 75) since their last withdrawal. We can assign this value to `bal` by accessing the bids mapping using the address of the function caller as the key. + +Next, we set the value of the address of the function caller to 0 in the bids mapping because they will withdraw the total value of their bids (line 76). + +Now we transfer that amount of ETH from the contract to the function caller and emit the `Withdraw` event (line 79). + +### End + +Before the function caller can execute this function and end the auction, we need to check if certain conditions are met. The auction needs to have started (line 83), the end date of the auction needs to have been reached (line 84), and the auction must not have ended already (line 85). + +Once the auction has ended, we set the state variable `ended` to `true` (line 87). + +We check if anybody participated in the auction and bid on the NFT (line 88). + +If there was a bid, we transfer the NFT from the contract to the highest bidder (line 89) and transfer the ETH that was sent from the highest bidder to the contract, now to the address of the auctioneer, the seller of the NFT (line 90). + +If nobody bids on the NFT, we send the NFT back to the auctioneer (line 92). + +Finally, we emit the `End` event (line 95). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we created in our Learneth "Solidity NFT Course". + +2. Mint yourself an NFT with the tokenId 0. + +3. For testing purposes, change the value that is assigned to the `endAt` state variable (line 54) from `7 days` to `5 minutes`. + +4. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +5. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for the `tokenId`. + +6. Call the `start` function of your auction contract. + +7. Bid 2 Ether using account 1, and 3 Ether using account 2. If you call the `highestBidder` function, it should now return the address of account 2. + +8. Call the `withdraw` function with account 1. In the balance of account 1, you should see the 2 Ether minus some transaction fees. + +9. After 5 minutes have passed, call the `end` function. Then, call the `ended` function which should return `true`. + +In the NFT contract, if you call the `ownerOf` function with the tokenId 0, it should return the address of account 2. If you look at the balance of account 1 it should have increased by 3 Ether minus some transaction fees. diff --git a/locales/fa/ERC721Auction/config.yml b/locales/fa/ERC721Auction/config.yml new file mode 100644 index 000000000..0783a37a1 --- /dev/null +++ b/locales/fa/ERC721Auction/config.yml @@ -0,0 +1,19 @@ +--- +id: er721Auction +name: NFT Auction Contract +summary: Learn how to write an ERC721 (NFT) auction contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: Contract Setup + path: auction-contract-setup + - + name: Start and Bid Functions + path: auction-start-bid + - + name: Withdraw and End Functions + path: auction-withdraw-end diff --git a/locales/fa/Interoperability/1_Intro/intro.md b/locales/fa/Interoperability/1_Intro/intro.md new file mode 100644 index 000000000..ab26f4f6d --- /dev/null +++ b/locales/fa/Interoperability/1_Intro/intro.md @@ -0,0 +1,5 @@ +As the web3 world grows, there will be more blockchains. Unless the chains can communicate with one another, the ecosystem will become increasingly fragmented. + +The Axelar network enables protocols to have cross-chain functionality between any two blockchains. + +Building a protocol that is interoperable between ecosystems is essential for growth. diff --git a/locales/fa/Interoperability/2_Gateway/gateway.md b/locales/fa/Interoperability/2_Gateway/gateway.md new file mode 100644 index 000000000..dc752d3eb --- /dev/null +++ b/locales/fa/Interoperability/2_Gateway/gateway.md @@ -0,0 +1,25 @@ +The Axelar Gateway is the entrypoint for your smart contract into the Axelar ecosystem. Once you have triggered the appropriate function on the Gateway, your transaction will begin its interchain journey from your source chain across the Axelar network to the destination chain. Each chain that is connected to Axelar has a deployed gateway contract for you to interact with. + +The following are the two more relevant functions you will need to be familiar with. + +## callContract() + +This function triggers an interchain transaction with a message from the source to the destination chain. It takes three relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent + +The first two parameters are quite intuitive. They consist of both the name of the chain you want this transaction to go to and the address on that chain you want to end execute at. The final parameter is the payload. This payload represents a general message that is sent to the destination chain. The message can be used in many different ways on the destination chain. For example, you can send data to be used as a parameter in another function on the destination chain, you can send a function signature as a message that will then get executed on a destination chain, and much more. + +## callContractWithToken() + +This function triggers an interchain with a message and a fungible token from the source to the destination chain. It takes five relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent +4. `symbol`: The symbol of the token being sent +5. `amount`: The amount of that token that is being sent + +The first three parameters here are the same as in `callContract()`. The final two parameters are relevant to the token that is being sent along with the message. These are the symbol of the token and the amount of the token that is being sent. diff --git a/locales/fa/Interoperability/3_GasService/GasService.md b/locales/fa/Interoperability/3_GasService/GasService.md new file mode 100644 index 000000000..4ed0afbbf --- /dev/null +++ b/locales/fa/Interoperability/3_GasService/GasService.md @@ -0,0 +1,29 @@ +The Axelar Gas Service is an extremely useful tool made available to pay gas for an interchain transaction. It allows you to pay for the cost of a transaction in the token of the source chain, making for a much easier end user (and developer) experience. If for example the source chain is Ethereum and the destination chain is Polygon then the gas service will receive the complete payment for the transaction in ETH and no matic is needed from the caller to pay for the execution on the Polygon destination chain. + +The following are the two more relevant functions you will need to be familiar with in regards to the Gas Service. + +## payNativeGasForContractCall() + +This function allows you to pay for the entirety of an interchain transaction in the native token of the source chain. It takes five relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +The parameters overlap with the parameters required by the `callContract()` function in the Gateway contract. The two parameters not discussed in the Gateway section are `sender` and `refundAddress`. The sender is the address paying for the transaction and the refund address is the address that will receive any surplus funds sent to the gas service. + +## payNativeGasForContractCallWithToken() + +This function allows you to pay for the entirety of an interchain transaction (that includes a token transfer) in the native token of the source chain. It takes seven relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `symbol`: The symbol of the token that was sent +6. `amount`: The amount of the token that was sent +7. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +This function is nearly identical to the first top one the main difference being that it is used for message + token transfer transactions as opposed to just interchain message transactions (aka GMP Transactions). As a result the GasService needs to also know the `symbol` and `amount` of the token that is being sent. diff --git a/locales/fa/Interoperability/4_Executable/executable.md b/locales/fa/Interoperability/4_Executable/executable.md new file mode 100644 index 000000000..1f72c6be4 --- /dev/null +++ b/locales/fa/Interoperability/4_Executable/executable.md @@ -0,0 +1,27 @@ +The Axelar executable contains relevant helper functions that will be automatically executed on the destination chain in correspondence to the relevant inbound transaction from the source chain. + +The following are the relevant functions you will need to use from Axelar Executable + +## \_execute() + +This function handles the execution on the destination chain. It takes the following four parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent + +The `sourceChain` and `sourceAddress` are key parameters which you receive out of the box that can be used for verifying authenticity of messages on the destination chain. The payload (as discussed in the gateway section) is the message that was sent from the source chain to be used on your destination chain. The `commandId` will not be used during the rest of this module. + +## \_executeWithToken() + +This function handles the execution on the destination chain for a message being sent with a fungible token. It takes six relevant parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent +5. `tokenSymbol`: The symbol of the token being sent +6. `amount`: The amount of that token that is being sent + +The first four parameters are identical to that of the `_execute()` function. The final two parameters of `tokenSymbol` and `amount` are in reference to the token that is being sent along with the message. It allows you on the destination chain to interact with the token accordingly, for example transferring it to another receiving address. The `commandId` will not be used during the rest of this module. diff --git a/locales/fa/Interoperability/5_InterchainMessage/interchainMessage.md b/locales/fa/Interoperability/5_InterchainMessage/interchainMessage.md new file mode 100644 index 000000000..029f642ce --- /dev/null +++ b/locales/fa/Interoperability/5_InterchainMessage/interchainMessage.md @@ -0,0 +1,53 @@ +In this section we will create a contract that will send a "hello world" message between two blockchains. + +## Constructor + +The first thing you will need to create is the `constructor` for the function. This will allow you to set the `Gateway` and `Gas Service` contracts we discussed in the previous sections. + +When deploying the contract you will pass in the address of the `Gateway` and `GasService` for Ethereum Sepolia those addresses are `0xe432150cce91c13a887f7D836923d5597adD8E31` for the Gateway and `0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6` for the Gas Service. + +For the full list of relevant Axelar addresses see here + +## Send Interchain Message + +Now that the constructor has set the relevant Axelar addresses needed to trigger an interchain transaction you can move on to the `setRemoteValue()`, which will trigger this transaction. + +This function takes three parameters: + +1. `_destinationChain`: The chain which the transaction is going to +2. `_destinationAddress`: The address on the destination chain the transaction will execute at +3. `_message`: The message being passed to the destination chain + +First, you have a `require` statement which ensures that the `msg.value` contains a value. This `msg.value` will be used to pay the `GasService`. If no funds were sent, then the transaction should be reverted as the transaction cannot execute on the Axelar blockchain and destination chain without any gas. + +Next, you encode the `_message` that was passed in. Notice that the `_message` is set as a `string` type. Axelar expects this message to be submitted as a `bytes` type so to convert the `string` to `bytes` you simply pass it through `abi.encode()`. + +Now, with your message encoded you can begin to interact with the `GasService` and the `Gateway` + +To pay for the entire interchain transaction you will trigger the function `payNativeGasForContractCall`, which is defined in the `GasService`. + +This function needs the parameters explained earlier in the GasService section. The `sender` for this transaction will be this contract, which is `address(this)`. The `destinationChain` and `destinationAddress` can simply be passed in from this functions parameters, the `payload` is the encoded \_message we wrote earlier. Finally, you need to specify what the refund address is, this can be the address that triggers this function, which you get by writing `msg.sender`. + +Once you trigger this function you will have successfully sent a transaction from the source chain via Axelar to the destination chain! But there is still one final step that needs to be complete. + +### Receive Message on Destination Chain + +On the destination chain the inbound interchain transaction needs to be picked up and handled by the `AxelarExecutable`'s `_execute()` function. + +The `_execute()` function is defined in the `AxelarExecutable` contract so when defining this function you must remember to include the `override` keyword. + +This function takes three parameters. + +1. `_sourceChain`: The blockchain which the transaction has originated from +2. `_sourceAddress`: The address on the source chain which the transaction has been sent from +3. `_payload`: The message that has been sent from the source chain + +The first thing that needs to be done in this contract is to get access to your `message` that was sent. Recall, before sending the message it was sent through `abi.encode()` to convert the message from type `string` to type `bytes`. To convert your message back from type `bytes` to type `string` simply pass the `_payload` to the function `abi.decode()` and specify that you want the `_payload` decoded to type `string`. This will return the message as a string. + +Now that you have your message as a type string you can set the `sourceChain` and `sourceAddress` storage variables as `_sourceChain` and `_sourceAddress` to have an easy reference to the data that was passed in. You can also emit the `Executed` event with the `sourceAddress` and `message` event that you just decoded. + +Great! At this point you are now handling the interchain transaction on the destination chain. + +To interact with this contract make sure you deploy it on at least two blockchains so that you can call `setRemoteValue()` from the one chain and then have the `_execute()` function automatically triggered on another chain. You will be able to query the `sourceChain` and `sourceAddress` variables on the destination chain to ensure that the interchain execution worked correctly. + +To view the full step by step of the interchain transaction checkout the Axelarscan (testnet) block explorer. diff --git a/locales/fa/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md b/locales/fa/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md new file mode 100644 index 000000000..11915eb32 --- /dev/null +++ b/locales/fa/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md @@ -0,0 +1,39 @@ +At this point we have gone over an example of how to send a general message between one blockchain to another. Now, let's implement a contract that sends a message and a token from one blockchain to another. + +## Overview + +This contract should seem largely familiar. Much like the previous section the `constructor` receives the `Gateway` and `Gas Service` addresses. + +It then has a function that will be called from the source chain called `sendToMany` that takes in parameters similar to the previous section. + +1. `_destinationChain`: The chain the transaction is sending to +2. `_destinationAddress`: The address on the destination chain your transaction is sending to +3. `_destinationAddresses`: The message that you will be sending along with your token transfer. In this example the message is a list of receiving addresses for the token transfer. +4. `_symbol`: The symbol of the token address being sent +5. `_amount`: The amount of the token being sent + +In the function we already have the `require` statement implemented to ensure gas is sent + +We also have the basic ERC20 functionality to send the token from the calling wallet to this smart contract. The contract also calls the `approve` function to allow the Gateway to eventually transfer funds on its behalf. + +Finally, the `_executeWithToken()` function is also implemented out of the box. + +It makes use of the following params: + +1. `_payload`: The incoming message from the source chain +2. `_tokenSymbol`: The symbol of the token that was sent from the source chain +3. `_amount`: The amount of the token that was sent from the source chain + +Now with these params that were passed in, the `_execute()` function can send the tokens that were sent to the appropriate receivers. + +## Challenge + +Your challenge here is to finish off the `sendToMany()` function using the Axelar Gateway and Gas Service to trigger an interchain transaction. + +In the end you should be able to deploy this contract on two testnets, trigger the `sendToMany()` function and see the live transaction on Axelarscan (testnet) block explorer. + +### Testing Notes + +Note 1: The recommended ERC20 to use is `aUSDC` a wrapped version of the USDC token that can be obtained from the discord faucet bot. When triggering the `sendToMany()` function simply pass in the symbol `aUSDC` to the fourth param. + +Note2: When triggering the `sendToMany()` function you must remember to `approve` your contract to spend `aUSDC` tokens on your behalf, otherwise `transferFrom()` on line49 will throw an error. diff --git a/locales/fa/Interoperability/7_FurtherReading/furtherReading.md b/locales/fa/Interoperability/7_FurtherReading/furtherReading.md new file mode 100644 index 000000000..a601d7ac7 --- /dev/null +++ b/locales/fa/Interoperability/7_FurtherReading/furtherReading.md @@ -0,0 +1,11 @@ +Congratulations on making it to the end of the interoperability module! 🎉🎉 + +To continue your learning journey of interoperability with Axelar. There are many useful resources available. + +- For documentation 📚 + +- For more technical examples 💻 + +- For live coding demos 📹 + +- For the developer blog 📝 diff --git a/locales/fa/Interoperability/README.md b/locales/fa/Interoperability/README.md new file mode 100644 index 000000000..a43fc5dd5 --- /dev/null +++ b/locales/fa/Interoperability/README.md @@ -0,0 +1,3 @@ +## Interoperability Between Blockchains + +Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. diff --git a/locales/fa/Interoperability/config.yml b/locales/fa/Interoperability/config.yml new file mode 100644 index 000000000..39f1be7ed --- /dev/null +++ b/locales/fa/Interoperability/config.yml @@ -0,0 +1,31 @@ +--- +id: interopCourse +name: Multichain Protocols with Axelar +summary: Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. +level: 2 +tags: + - Solidity + - Interoperability + - Axelar +steps: + - + name: An Intro to Axelar + path: 1_Intro + - + name: Axelar Gateway + path: 2_Gateway + - + name: Axelar Gas Service + path: 3_GasService + - + name: Axelar Executable + path: 4_Executable + - + name: Interchain Messages + path: 5_InterchainMessage + - + name: Interchain Token Transfers + path: 6_InterchainTokenTransfer + - + name: Further Reading + path: 7_FurtherReading diff --git a/locales/fa/Multisig-Tutorial/1-multisig-introduction/introduction.md b/locales/fa/Multisig-Tutorial/1-multisig-introduction/introduction.md new file mode 100644 index 000000000..3e9f18938 --- /dev/null +++ b/locales/fa/Multisig-Tutorial/1-multisig-introduction/introduction.md @@ -0,0 +1,41 @@ +Welcome to the Multisignature Wallet course! In this section, we'll explore the fundamentals of Multisignature (Multisig) wallets and we'll go through a multisig wallet contract. + +## What is a Multisignature Wallet? + +A multisignature (multisig) wallet is a type of digital wallet that requires multiple keys to authorize a cryptocurrency transaction. + +Imagine a multisig wallet as a secure vault with multiple locks. To open the vault, each keyholder must open their individual lock. This setup ensures that no single person can access the vault's contents without the others' consent. + +## How Does a Multisig Wallet Work? + +In a multisig setup, each transaction must receive a predetermined number of approvals from a set group of individuals. For instance, in a 3-of-5 wallet configuration, there are five authorized addresses, but a transaction only goes through when at least three of them give their approval. When a transaction is initiated, it's presented as a **proposal** to the group. Each member who agrees to the transaction uses their private key to digitally sign it. + +These **digital signatures** are unique and are generated based on the combination of the transaction data and the private key. + +When the required number of signatures is reached, the transaction is broadcasted to the blockchain for execution. + +## Why Use a Multisig Wallet? + +Multisig wallets are crucial for enhanced security in cryptocurrency transactions. They mitigate the risk of theft or loss of a single key. In business, they're used to ensure that funds can't be moved without consensus among stakeholders. For instance, in a company managing cryptocurrency assets, a multisig wallet might require the CFO, CEO, and a board member to all approve significant transactions, protecting against internal fraud or external hacks. + +## Conclusion + +In this section, we learned that a multisig wallet requires multiple keys to authorize a proposed cryptocurrency transaction and that a multisigs mitigates the risk of theft or loss of a single key. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is a Multisignature Wallet? + +1. A digital wallet that requires a single signature for transactions. +2. A digital wallet that requires multiple signatures for transactions. +3. A physical wallet used for storing cryptocurrency. +4. A wallet that can only hold multiple types of cryptocurrencies. + +### 2) How does a Multisignature Wallet enhance security? + +1. By requiring a single private key for transactions. +2. By distributing transaction approval across multiple owners. +3. By storing transaction data on-chain. +4. None of the above. + +Feel free to take your time and answer the questions above. Once you're ready, we'll move on to exploring the Multisig smart contract and understanding its structure. diff --git a/locales/fa/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md b/locales/fa/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md new file mode 100644 index 000000000..17b0a924f --- /dev/null +++ b/locales/fa/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md @@ -0,0 +1,60 @@ +In this section, we'll explore the **initialization process** of the Multisig smart contract. We'll examine the constructor function and review how it sets up the initial state of the contract. + +## Note + +From this section on in this tutorial, we will be building up a multisig contract. In subsequent sections, the contract will become increasingly complete. + +## Overview + +In this section, the contract consists of events, state variables, modifiers, and functions. **Events** provide transparency by logging specified activities on the blockchain, while **modifiers** ensure that only authorized users can execute certain functions. + +## State Variables + +In Line 4, we have the MultisigWallet contract itself. At the beginning of the contract, we have three state variables. + +1. **`owners`:** An array containing the addresses of all owners of the multi-signature wallet (Line 5). +2. **`isOwner`:** A mapping indicating whether an address is an owner (Line 6). +3. **`numConfirmationsRequired`:** The number of confirmations required for a transaction (Line 7). + +The setup of array and mapping allows us to easily retrieve the list of owners and verify whether an address is an owner. + +## Modifiers + +Next, we have a modifier called `onlyOwner` (Line 9). Modifiers in Solidity are special keywords that can be used to amend the behavior of functions. In our case, the `onlyOwner` modifier ensures that only owners can execute a function. It does this by checking whether the address of the **caller** is an owner. + +## Constructor Function + +The `constructor` function (Line 14) is executed only once during the deployment of the contract. It initializes essential parameters, in this case, the list of owners and the required number of confirmations (Line 14). + +On lines 15 and 16, we have two `require` statements to ensure that the inputs are valid. In this case, we require that there must be at least one owner and that the number of required confirmations must be greater than zero and less than or equal to the number of owners. + +The constructor then initializes the contract state by verifying that is not address(0) (Line 25) and that the owner is unique (Line 26). Then it adds a key/ value pair to the isOwner mapping (Line 28), and then it populates the `owners` array with the provided owner addresses (Line 29). + +Finally, it sets the `numConfirmationsRequired` variable with the specified value (Line 32). + +## getOwners Function + +The `getOwners` function (Line 36) allows users to retrieve the list of owners of the multi-signature wallet. It returns the `owners` array (Line 37). + +## getNumConfirmationsRequired Function + +The `getNumConfirmationsRequired` function (Line 41) allows users to retrieve the number of confirmations required for a transaction. It returns the `numConfirmationsRequired` variable (Line 42). + +## Conclusion + +In this section, we explored the initialization process of the Multisig smart contract. We examined the constructor function and understood how it sets up the initial state of the contract. + +## ⭐️ Assignment: Deploy a Multisig Wallet + +Deploy a Multisig contract with three owners and require two confirmations for transaction execution. + +1. Compile contractInitialization.sol +2. Go to Deploy & Run Transactions in Remix. +3. Expand the "Deploy" section. +4. Under "_OWNERS", enter three an array of three addresses. +5. Under "_NUM_CONFIRMATIONS_REQUIRED", enter the number of confirmations required for a transaction. + +**Hints:** + +- You can get addresses from the "ACCOUNTS" dropdown menu. +- The array of addresses should be in the format: ["0x123...", "0x456...", "0x789..."]. diff --git a/locales/fa/Multisig-Tutorial/3-multisig-deposits/deposits.md b/locales/fa/Multisig-Tutorial/3-multisig-deposits/deposits.md new file mode 100644 index 000000000..a8a14213b --- /dev/null +++ b/locales/fa/Multisig-Tutorial/3-multisig-deposits/deposits.md @@ -0,0 +1,34 @@ +In this section, we'll explore the `receive` function and the associated Deposit event. We'll examine how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## Deposit Event + +On line, 9 we have the Deposit event. The Deposit event is emitted whenever Ether is deposited into the multi-signature wallet. It includes three parameters: + +1. `sender`: The address that sent the Ether. +2. `amount`: The amount of Ether deposited. +3. `balance`: The updated balance of the contract after the deposit. + +We can use the Deposit event to track the flow of Ether into the multi-signature wallet and maybe trigger other actions based on the event. + +## receive Function + +On line 43, we have the `receive` function. The `receive` function is a special function that is executed whenever Ether is sent to the contract. + +The `receive` function is marked as `external` and `payable`. The `external` modifier means that the function can only be called from outside the contract. The `payable` modifier means that the function can receive Ether. + +The `receive` function emits the Deposit event (Line 44) with the address of the sender, the amount of Ether sent, and the updated balance of the contract. It doesn't return anything. + +To receive Ether, a contract must have a `receive`, `fallback`, or a function with the `payable` modifier. If none of these are present, the contract will reject any Ether sent to it. + +## Conclusion + +In this section, we explored the `receive` function and the associated Deposit event. We examined how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## ⭐️ Assignment: Deposit Ether + +Deposit 2 Ether into the Multisig contract. + +1. Deploy the Multisig contract as in the previous assignment. +2. Enter a Value of 2 Ether in the Value field and select Ether in the dropdown menu. +3. At the bottom of your deployed contract in the "Low level interactions" section, click on the "Transact" button. +4. On top of your deployed contract, it should now say "Balance: 2 Ether". diff --git a/locales/fa/Multisig-Tutorial/4-multisig-transactions/transactions.md b/locales/fa/Multisig-Tutorial/4-multisig-transactions/transactions.md new file mode 100644 index 000000000..f62fd48a0 --- /dev/null +++ b/locales/fa/Multisig-Tutorial/4-multisig-transactions/transactions.md @@ -0,0 +1,73 @@ +In this section, we'll explore the process of submitting and confirming transactions. + +## Modifiers + +We have new modifiers in this iteration of the contract. Let's examine them one by one. + +1. **`txExists` modifier:** (Line 13) ensures that the transaction exists. It does this by checking whether the transaction index is less than the length of the `transactions` array. We'll go into more about in this modifier later in this section. +2. **`notExecuted` modifier:** (Line 18) ensures that the transaction has not been executed. It does this by checking whether the `executed` variable of the transaction is false. +3. **`notConfirmed` modifier:** (Line 23) ensures that the transaction has not been confirmed by the caller. It does this by checking whether the `isConfirmed` mapping of the transaction index and the caller's address is false. + +## Transaction Struct + +On line 28, we have a struct called `Transaction`. We store the struct members: `to`, `value`, `data`, `executed`, and `numConfirmations` in individual variables. + +## Mapping of Confirmations + +On line 37, we have a mapping called `isConfirmed`. This mapping is used to keep track of the confirmations of each transaction. It maps the transaction's index to a mapping of an owner addresse to a boolean value. The boolean value indicates whether this owner has confirmed the transaction. + +## Transactions Array + +On line 39, we have an array called `transactions`. The array is used to store all the transactions submitted to the multi-signature wallet. + +## Events + +We have four new events in this iteration of the contract: + +1. **`SubmitTransaction` event:** emitted whenever a transaction is submitted to the multi-signature wallet. +2. **`ConfirmTransaction` event:** emitted whenever a transaction is confirmed by an owner. +3. **`RevokeConfirmation` event:** emitted whenever a transaction confirmation is revoked by an owner. +4. **`ExecuteTransaction` event:** emitted whenever a transaction is executed. + +## submitTransaction Function + +The `submitTransaction` function (Line 78) allows users to submit a transaction to the multi-sig wallet. It takes three parameters: `to`, `value`, and `data`. The `to` parameter is the address of the recipient of the transaction. The `value` parameter is the amount of Ether to be sent. The `data` parameter is the data to be sent to the recipient. Only owners can submit transactions. + +On line, 85 we create a new transaction struct and push it to the `transactions` array and emit the `SubmitTransaction` event. The `txIndex` variable is used to keep track of the transaction index. + +## confirmTransaction Function + +The `confirmTransaction` function (Line 98) allows users to confirm a transaction. It takes one parameter: `txIndex`. +It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. The `onlyOwner` modifier ensures that only owners can confirm transactions. The `txExists` modifier ensures that the transaction exists. The `notExecuted` modifier ensures that the transaction has not been executed. + +On line 101, we store the transaction in a local variable called `transaction`. We then increment the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to true. Finally, we emit the `ConfirmTransaction` event. + +## executeTransaction Function + +The `executeTransaction` function (Line 108) allows users to execute a transaction. On line 113, we require that the number of confirmations of the transaction is greater than or equal to the required number of confirmations. We then set the `executed` variable of the transaction to true. Finally, send the funds using the `call` function. This is the `call` of the recipient address with the value and data of the transaction. If the transaction is successful, we emit the `ExecuteTransaction` event. + +## getTransactionCount Function + +The `getTransactionCount` function (Line 132) allows users to retrieve the number of transactions in the multi-signature wallet. It returns the length of the `transactions` array. + +## getTransaction Function + +The `getTransaction` function (Line 136) allows users to retrieve a transaction. It returns the transaction struct members that we explored earlier in this section. + +## Conclusion + +In this section, we explored the process of submitting, confirming, and executing transactions. We examined the `submitTransaction`, `confirmTransaction`, and `executeTransaction` functions and understood how they work together to allow multiple users to submit and confirm transactions. + +## ⭐️ Assignment: Make a Transaction + +Submit, confirm, and execute a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. Deploy the Multisig contract as in the previous assignment. Make sure that the required number of confirmations is 2. +2. Fund the multisig from any address by sending 4 Ether as you did in the previous assignment. +3. Try sending 2 Ether to the first account in the "ACCOUNTS" dropdown menu. Once you have submitted this transaction (with submitTransaction), click on `getTransactionCount` and should see one transaction or you can click on `getTransaction`, insert 0 as the transaction index and see the transaction you just submitted. +4. Now you can click on `confirmTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. +5. Switch to the second owner account and confirm the transaction again. If you click on `getTransaction` again, you should see that the transaction has been confirmed twice. +6. The last step is to execute the transaction. Click on `executeTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been executed. You can also check the balance of the first account in the "ACCOUNTS" dropdown menu. It should now be 2 Ether higher and the balance of the multi-signature wallet should be 2 Ether lower. + +**Hint:** +If you submit a transaction make sure that the value is in Wei and that the _data field is correctly filled in. E.g. it could look like this: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 2000000000000000000, 0x" for 2 Ether. diff --git a/locales/fa/Multisig-Tutorial/5-multisig-revoke/revoke.md b/locales/fa/Multisig-Tutorial/5-multisig-revoke/revoke.md new file mode 100644 index 000000000..1bf085343 --- /dev/null +++ b/locales/fa/Multisig-Tutorial/5-multisig-revoke/revoke.md @@ -0,0 +1,30 @@ +In this section, we'll explore the process of revoking confirmations. This process is necessary when an owner changes their mind about a transaction and wants to stop it from being executed. This section will be pretty straightforward. + +## revokeConfirmation Event + +On line 14, we have added the `RevokeConfirmation` event. This event is emitted whenever a transaction confirmation is revoked by an owner. + +## revokeConfirmation Function + +On line 129, we have added the `revokeConfirmation` function. It allows users to revoke a transaction confirmation. + +`revokeConfirmation` takes one parameter: `txIndex`. It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. + +On line 134, we require that the transaction has been confirmed by the caller. This ensures that an owner who has confirmed the transaction can only revoke their own confirmation. +We then decrement the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to false. Finally, we emit the `RevokeConfirmation` event. + +## Conclusion + +In this section, we explored the process of revoking confirmations. We examined the `revokeConfirmation` function and understood how it works to allow users to revoke confirmations. + +## ⭐️ Assignment: Revoke a Confirmation + +Confirm and revoke a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. As in the previous assignment, deploy the Multisig contract, send the contract some Ether, and then submit a transaction to the first account in the "ACCOUNTS" dropdown menu with a value of 2 Ether. +2. Confirm the transaction twice as in the previous assignment. +3. Revoke the transaction by clicking on `revokeConfirmation` and inserting 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. + +## Final Conclusion + +In this tutorial, we explored the process of creating a multi-signature wallet. We learned how to initialize the contract, deposit Ether, submit, confirm, and revoke transactions. We also learned how to execute transactions and retrieve information about the multi-signature wallet. diff --git a/locales/fa/Multisig-Tutorial/README.md b/locales/fa/Multisig-Tutorial/README.md new file mode 100644 index 000000000..ae5997802 --- /dev/null +++ b/locales/fa/Multisig-Tutorial/README.md @@ -0,0 +1,5 @@ +## MultiSig Wallet + +Learn how to write a MultiSig Wallet smart contract on Ethereum. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/fa/Multisig-Tutorial/config.yml b/locales/fa/Multisig-Tutorial/config.yml new file mode 100644 index 000000000..067de0fb9 --- /dev/null +++ b/locales/fa/Multisig-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: multisigCourse +name: Multisig Wallet +summary: Learn how to create and interact with a multisig wallet. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - Multisig +steps: + - + name: 1. Introduction + path: 1-multisig-introduction + - + name: 2. Initialize the Contract + path: 2-multisig-initialization + - + name: 3. Deposits + path: 3-multisig-deposits + - + name: 4. Transactions + path: 4-multisig-transactions + - + name: 5. Revoking Confirmations + path: 5-multisig-revoke diff --git a/locales/fa/NFTTokenCourse/README.md b/locales/fa/NFTTokenCourse/README.md new file mode 100644 index 000000000..c3d2a183a --- /dev/null +++ b/locales/fa/NFTTokenCourse/README.md @@ -0,0 +1,5 @@ +## Solidity NFT Course + +Learn how to create your own NFTs (non-fungible tokens). + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/fa/NFTTokenCourse/config.yml b/locales/fa/NFTTokenCourse/config.yml new file mode 100644 index 000000000..af82db834 --- /dev/null +++ b/locales/fa/NFTTokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: nftTokenCourse +name: Solidity NFT Course +summary: Learn how to create your own NFT tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc721-interface + - + name: 3. Metadata Interface + path: erc721-interface-metadata + - + name: 4. Token Creation + path: erc721-token-creation + - + name: 5. Metadata IPFS + path: erc721-metadata-ipfs + - + name: 6. Deploy to Testnet + path: erc721-deploy-testnet-opensea diff --git a/locales/fa/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md b/locales/fa/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md new file mode 100644 index 000000000..40576500c --- /dev/null +++ b/locales/fa/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md @@ -0,0 +1,50 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to the Rinkeby testnet of the Ethereum blockchain, mint an NFT, and look at it on the NFT marketplace OpenSea. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token for Rinkeby + +In order to make transactions on the testnet, we need Ethereum testnet tokens. + +**2.1** Switch your Metamask from "Ethereum Mainnetwork" to "Rinkeby Test Network". + +**2.2** Go to https://faucet.paradigm.xyz/, enter the address of your account and claim testnet ETH. +You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Contract Deployment + +**3.1** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It should then ask you to connect your account, which you should confirm. Then you should see the Rinkeby network badge under "Injected Web3". + +**3.2** Deploy your token contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. + +### 4. Mint an NFT + +**4.1** Expand your contract in the IDE so you can see the buttons for the functions. + +**4.2** Expand the input fields next to the safeMint button. Enter the Ethereum address of the account that is connected to Remix in the “to:” input field. Enter “0” in the input field "tokenID:". Click on transact. + +**4.3** In Metamask click on assets, then click on the “Import tokens” link, and paste the address of your contract in the input field. You can set decimals to 0. + +You should now see the name of the symbol of your token contract (e.g. GEO) in your “Assets” view in Metamask. You should have one of these tokens. + +### 5. See your NFT on OpenSea + +OpenSea is one of the most popular online marketplace for NFTs. OpenSea also provides a version where you can see assets on the testnet, under https://testnets.opensea.io/ + +**5.1** Go to https://testnets.opensea.io/login. + +**5.2** Connect with your Metamask wallet. You should be redirected to your account https://testnets.opensea.io/account view on OpenSea, where you should be able to see your NFT. You should see the image of your NFT; when you click on it, you should see the name, description, and under properties, also the attributes that you created. + +If you successfully completed this course and are familiar with the basics of Solidity development, we encourage you to continue your learning journey by learning how to create your own NFT auction contract from the Learneth resources. diff --git a/locales/fa/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md b/locales/fa/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md new file mode 100644 index 000000000..a43162feb --- /dev/null +++ b/locales/fa/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md @@ -0,0 +1,44 @@ +The metadata extension is optional. It allows us to add additional information to our ERC721 tokens. We can specify a name, a symbol, and an URI (Uniform Resource Identifier) that can point to a file where we can add even more information in the form of a JSON. + +## ERC721 Metadata Functions + +### name + +The function `name` (line 16) returns the name of the token collection. A token collection means all tokens created with your ERC721 token contract implementation. Every token in this collection will have this name, regardless of their tokenId. + +### symbol + +The function `symbol` (line 21) returns the symbol of the token collection. + +### tokenURI + +The function `tokenURI` (line 26) returns the URI for the token with the id `tokenId`. In this case it’s not the URI of the whole collection but of an individual token in the collection. + +## ERC721 Metadata JSON Schema + +The file that the tokenURI points to should conform to the Metadata JSON Schema as it is specified in the EIP-721. + +``` +{ + "title": "Asset Metadata", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Identifies the asset to which this NFT represents" + }, + "description": { + "type": "string", + "description": "Describes the asset to which this NFT represents" + }, + "image": { + "type": "string", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." + } + } +} +``` + +The root element must be of the type object. This root object should have properties with the keys: name, description, and image that should be all of the type string. + +The ERC721 standard is pretty flexible, the tokenURI does not need to point to a JSON document and the JSON does not need to have all properties and often has additional properties. diff --git a/locales/fa/NFTTokenCourse/erc721-interface/erc721Interface.md b/locales/fa/NFTTokenCourse/erc721-interface/erc721Interface.md new file mode 100644 index 000000000..468e8e640 --- /dev/null +++ b/locales/fa/NFTTokenCourse/erc721-interface/erc721Interface.md @@ -0,0 +1,100 @@ +ERC721 is a standard for token contracts that manage non-fungible tokens (NFTs) on the Ethereum blockchain. + +Each non-fungible token is unique and not interchangeable. NFTs can have different properties, behavior, or rights. Non-fungible tokens are used to represent ownership of unique digital and physical assets like art, collectibles, or real estate. + +If you want to know more about the ERC721 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +The ERC721 standard is more complex than the ERC20 standard and it features optional extensions. ERC721 compliant contracts must, at a minimum, implement the ERC721 and ERC165 interfaces, which we will look at in this section. + +This interface (line 11) is part of the open-source contract library provided by OpenZeppelin. + +## Basic IERC721 Functions + +Contracts compliant with the ERC721 standard have to implement the following functions: + +### balanceOf + +The function `balanceOf` (line 30) returns the amount of tokens owned by the account with the address `owner`. + +### ownerOf + +The function `ownerOf` (line 39) returns the address `owner` of the account that holds the token with the id `tokenId`. + +### safeTransferFrom + +The function `safeTransferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +The function `safeTransferFrom` (line 137) is almost identical to the function `safeTransferFrom` (line 55) .The only difference is that this function has a non-empty payload `data`. + +A smart contract must implement the ERC721TokenReceiver Interface if it is to receive a transfer. This will ensure that the contract can handle ERC721 token transfers and prevent the tokens from being locked in a contract that can’t. + +### transferFrom + +The function `transferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +**It is recommended to use safeTransferFrom instead of transferFrom whenever possible.** +The `transferFrom` function is not secure because it doesn’t check if the smart contract that is the recipient of the transfer has implemented the ERC721TokenReceiver interface and is capable of handling ERC721 tokens. + +## Advanced IERC721 Functions + +### approve + +The function `approve` (line 94) gives the account with the address `to` the permission to manage the token with the id `tokenId` on behalf of the account calling the function. + +### getApproved + +The function `getApproved` (line 103) returns the address of the account (return var `operator`) that is approved to manage the token with the id `tokenId`. + +### setApprovalForAll + +The function `setApprovalForAll` (line 115) sets the permission (`_approved`) for the account with the specified address (input param - `operator`) to manage all tokens of the account calling the function. + +### isApprovedForAll + +The function `getApproved` (line 103) returns the boolean true if the account with the address `operator` is approved to manage all tokens of the account with the address `owner`. + +## IERC721 Events + +ERC721 contracts must also emit the following events: + +### Transfer + +The `Transfer` event (line 15) must be emitted when the token with the id `tokenId` is transferred from the account with the address `from` to the account with the address `to`. + +### Approval + +The `Approval` event (line 20) must be emitted when the account with the address `owner` approves the account with the address `spender` to manage the token with the id `tokenId` on its behalf. + +### ApprovalForAll + +The `ApprovalForAll` event (line 25) must be emitted when the account with the address `owner` gives or removes the permission (`_approved`) of the account with the address `operator` to manage all its tokens. + +## IERC165 + +In addition to the ERC721 interface, ERC721 compliant contracts must also implement the ERC165 interface. + +With the implementation of the ERC165 interface, contracts can declare the support of specific interfaces. A contract that wants to interact with another contract can then query if the other contract supports this interface before making a transaction e.g. sending tokens to it that they might not support. + +Our IERC721 interface here imports (line 6) and inherits (line 11) from the IERC165 interface. + +This is how OpenZeppelins implementation of the ERC165 interface looks like: + +``` +interface IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +For example, the ERC165 identifier for the ERC721 interface as specified in the EIP721 is “0x80ac58cd”. Learn how to calculate an interface identifier and more about the ERC165 in its improvement proposal. + +## Other interfaces + +The IERC721TokenReceiver interface must be implemented to accept safe transfers. + +There are two optional extensions for ERC721 contracts specified in the EIP721: + +IERC721Enumerable enables a contract to publish its full list of tokens and make them discoverable. + +IERC721Metadata enables a contract to associate additional information to a token. We will have a more detailed look into this in the next section. diff --git a/locales/fa/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md b/locales/fa/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md new file mode 100644 index 000000000..27876b068 --- /dev/null +++ b/locales/fa/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md @@ -0,0 +1,101 @@ +In this section, we will create our metadata and store it in a decentralized way. + +IPFS ( InterPlanetary File System) is a peer-to-peer network for storing files in a distributed way. Pinata.cloud is a pinning service that allows users to easily host files on the IPFS network. + +We want to host our images and the JSON files with their metadata on IPFS. + +### Create Image Folder + +In this example, we will create metadata for three tokens. As you can see below, we create three images that we stored in a folder. + +``` +geo-img +├── geo_1.png +├── geo_2.png +├── geo_3.png +``` + +### Register on Pinata + +Now, we want to host these images somewhere so we can point to them in the metadata of our tokens. Let's do it in a decentralized way and use Pinata to host them on IPFS. + +First you need an account on Pinata. Go to Pinata.cloud and create an account. On Pinata you can upload up to 1 GB of data for free. + +Once you have signed up, you should be in the Pin Manager view. + +Pin Manager Pinata + +### Upload Images to IPFS + +Click on the upload button and upload the folder with your images. +Once you've uploaded your folder, you should see the name of your folder and the CID (content identifier) associated with it. If the content in the folder changes, the CID will also change. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P + +You can access a specific image by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png + +### Create JSON files + +We create another folder where we store three JSON files. + +``` +geo-json +├── 0 +├── 1 +├── 2 +``` + +Inside the JSON files, create the metadata for the tokens, like name, description, and image. +For the image URL, we are going to use the URL of our images on IPFS. You can add additional data if you like; in this example, we added some unique attributes for each token. + +This is how the JSON for the first token could look: + +``` +{ + "name": "Geometry#0", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png +", + "attributes": [ + { "trait_type": "background", "value": "cyan" }, + { "trait_type": "color", "value": "red" }, + { "trait_type": "shape", "value": "circle" } + ] +} +``` + +This is how the JSON for the second token could look: + +``` +{ + "name": "Geometry#1", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_2.png", + "attributes": [ + { "trait_type": "background", "value": "magenta" }, + { "trait_type": "color", "value": "green" }, + { "trait_type": "shape", "value": "square" } + ] +} +``` + +As shown above, the folder in this example is called "geo-json". Inside this folder, we have three JSON files. +The first JSON file is called "0", the second JSON file is called "1", and the third JSON file is called "2". + +Make sure that your JSON files don't have a file ending and are named like their corresponding tokenIds. +In the pin manager on pinata.cloud, click on the upload button and upload the folder with your JSON files. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. +For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp +This will become our baseURI. + +You can access a specific JSON file then by just adding a slash and the tokenId by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/0 + +In the contract, replace the baseURI with your own baseURI. In this example, the baseURI consists of the URL +"https://ipfs.io/ipfs/", the CID containing the JSON files, and a slash at the end "/". + +An individual tokenURI will now be created for each token by adding the tokenId to the baseURI — exactly what we did manually in the example above to access the JSON file. diff --git a/locales/fa/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md b/locales/fa/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md new file mode 100644 index 000000000..891fe00a7 --- /dev/null +++ b/locales/fa/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md @@ -0,0 +1,35 @@ +In this contract, we use an ERC721 token contract implementation from OpenZeppelin (line 4). + +Have a look at their implementation of a ERC721 contract. Apart from the functionality specified in the ERC721 standard, the contract provides additional functions which we will see in a bit. + +## myToken + +We create our own contract called MyToken (line 7), which inherits (line 7) the functionality from the OpenZepplin `ERC721` token contract implementation and `Ownable` that we imported (line 4). If you don't remember the Ownable contract module, have a look at the ERC20 extensions section. + +This ERC721 implementation makes use of the IERC721Metadata extension that is specified in the EIP. Our contract inherits the functions `name()` and `symbol()` +and has a constructor that allows their values to be set during the deployment of the contract (line 8). +In this case, we are going to use the default values. We name our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +### Base URI + +With an ERC721 contract, we are able to mint various tokens, each with its own tokenId. As we saw in the IERC721Metadata interface, each token can have its own `tokenURI`, which typically points to a JSON file to store metadata like name, description, and image link. +If a contract mints multiple tokens, ERC721 implementations often use the same URI as a base (`baseURI`) for all tokens and only differentiate them by adding their unique `tokenId` at the end via concatenation. In the next part, we will see what this looks like in practice. + +In this example, we are storing our data on IPFS — more on that in the next section. Our baseURI is https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/ (line 11). +Through concatenation the tokenURI for the token with the id 0 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/0 , the tokenURI for the token with the id 1 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/1, and so on. + +When using IPFS and you run into "504 Gateway Time-out" errors, you might have to wait and retry until the data is available. + +### safeMint + +With the safeMint function (line 14) we enable the owner to create new tokens with a dedicated token id after contract deployment. +The safeMint function is part of the ERC721 implementation of OpenZeppelin and lets us safely mint a token with the id `tokenId` to the account with the address `to`. For access control, we use the `onlyOwner` modifier from the Ownable access control contract module that we imported (line 5). + +In the next section, we will see how we can create and host the metadata for our NFTs. + +## ⭐️ Assignment + +1. Rename your contract to `Geometry`. +2. Rename your token to `Geometry`. +3. Change the symbol of your token to `GEO`. +4. Change the `_baseURI` to https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/. diff --git a/locales/fa/NFTTokenCourse/introduction/introduction.md b/locales/fa/NFTTokenCourse/introduction/introduction.md new file mode 100644 index 000000000..13beea567 --- /dev/null +++ b/locales/fa/NFTTokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with NFTs, tokens created with the ERC721 token standard. + +If you want to learn more about fungible tokens and the ERC20 token standard, have a look at the Learneth ERC20 Token Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain-based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/fa/OpcodesInTheDebugger/1_intro/step.md b/locales/fa/OpcodesInTheDebugger/1_intro/step.md new file mode 100644 index 000000000..c1d9a2448 --- /dev/null +++ b/locales/fa/OpcodesInTheDebugger/1_intro/step.md @@ -0,0 +1,5 @@ +This workshop aims to give a better understanding about how a contract get deployed. +`SimpleStore` is a very basic contract. +It has a very simple constructor - which just uses the first parameter `_o` and saves it to `s`. + +Using the debugger, we'll try to see, what the opcode `CODECOPY` does. diff --git a/locales/fa/OpcodesInTheDebugger/2_memory/step.md b/locales/fa/OpcodesInTheDebugger/2_memory/step.md new file mode 100644 index 000000000..577169a5e --- /dev/null +++ b/locales/fa/OpcodesInTheDebugger/2_memory/step.md @@ -0,0 +1,8 @@ +Before we start, just quick reminder: + +The runtime of the EVM has several kinds of memory: + +- `calldata`: This is the input value given to the transaction. +- `stack`: Basically, this is a list of values, each value is limited in size (32 bytes). +- `memory`: Memory is used when the **type** of value getting stored is more complex like an array or a mapping. This memory is **temporary** and is **released** at the end of the execution. +- `storage`: This is a mapping, each value stored is **persisted** and saved on chain. diff --git a/locales/fa/OpcodesInTheDebugger/3_codecopy/step.md b/locales/fa/OpcodesInTheDebugger/3_codecopy/step.md new file mode 100644 index 000000000..b0c9f7d52 --- /dev/null +++ b/locales/fa/OpcodesInTheDebugger/3_codecopy/step.md @@ -0,0 +1,7 @@ +CODECOPY is one of the many opcodes run by the EVM. Check out the complete list of opcodes at https://ethervm.io/ . + +CODECOPY takes the **running code** (or part of it) and to copies it from the `calldata` to the `memory`. + +The solidity implementation is: **codecopy(t, f, s)** - copy **s** bytes from code at position **f** to memory at position **t**. + +Every contract deployment uses **CODECOPY**. diff --git a/locales/fa/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md b/locales/fa/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md new file mode 100644 index 000000000..63950051d --- /dev/null +++ b/locales/fa/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md @@ -0,0 +1,11 @@ +Let's go back to our contract. +Please make sure the `solidity compiler` and `Deploy & Run Transactions` are activated. + +Alternatively, you can click on `Solidity` from the `Home Page` **Environments** section. + +- Compile the contract from the `solidity compiler`. +- Go to the `Deploy & Run Transactions` and make sure `SimpleStore` is selected contract. +- In the textbox to the right of `Deploy`, input a positive integer. +- Click on `Deploy`. + +In the next step, we'll watch the deployment in the debugger. diff --git a/locales/fa/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md b/locales/fa/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md new file mode 100644 index 000000000..3ef3cd146 --- /dev/null +++ b/locales/fa/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md @@ -0,0 +1,7 @@ +From the Remix terminal, identify the transaction that deployed the contract and click `Debug` + +In the gutter of the editor, put a breakpoint on the line `s = _o`, and click on `Jump to the next Breakpoint` (bottom right button). + +Click on `Step into`, to move along the opcodes until you reach `SSTORE`. + +`SSTORE` is the opcode for storing the value `_o` in the storage. Let's continue further to the `CODECOPY`. diff --git a/locales/fa/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md b/locales/fa/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md new file mode 100644 index 000000000..1480728e6 --- /dev/null +++ b/locales/fa/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md @@ -0,0 +1,57 @@ +The goal here is to store the code in the blockchain. The EVM needs to tell the client (geth, parity) which what part of the **Call Data** to store. In this step, we are saving the contract MINUS its constructor (because that gets inplmented only 1 time) and MINUS the input parameter does not need to be stored. + +`CODECOPY` is the first step: it copies the bytecode to memory, then the ethereum client will be able to consume it. MUNCH! + +But wait... before the client can **MUNCH** bytecode, it needs an instruction - an opcode to tell it to MUNCH. `RETURN` is this opcode! + +As stated in the general spec, at the end of the contract creation, the client (geth, parity) takes the targeted value by the opcode `RETURN` and **persists** it by making it part of the deployed bytecode. + +Once you are in the `CODECOPY`, look at the top 3 items in the **Stack**: + +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x0000000000000000000000000000000000000000000000000000000000000055` +`2: 0x000000000000000000000000000000000000000000000000000000000000003e` + +_In your Stack - `1` & `2` may be slightly different. The difference may be due to a different compiler version._ + +**These are the parameters for `CODECOPY`.** + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +`0` is the offset where the copied code should be placed in the **memory**. In this example, ( all zeros) the code is copied to the beginning of the memory. (**t**) +`1` is the offset in **calldata** where to copy from (**f**) +`2` number of bytes to copy - (**s**) + +After `CODECOPY` is executed, (click the _step into_ button) the copied code should be: +`0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c63430005110032` in memory. **I'll refer to this value as (X)**. + +Let's look at the debugger's **Memory** panel. +The 0x number I gave above is not what you will see in the **Memory** panel -what you will see is this: +0x0: 6080604052600080fdfea265627a7a72 ????R??????ebzzr +0x10: 31582029bb0975555a15a155e2cf28e0 1X ?? uUZ??U???? +0x20: 25c8d492f0613bfb5cbf96399f6dbd4e ?????a?????9?m?N +0x30: a6fc9164736f6c634300051100320000 ???dsolcC????2?? +0x40: 00000000000000000000000000000000 ???????????????? +0x50: 000000000000000000000000000000a0 ??????????????? +0x60: 00000000000000000000000000000000 ???????????????? +0x70: 00000000000000000000000000000000 ???????????????? +0x80: 00000000000000000000000000000000 ???????????????? +0x90: 00000000000000000000000000000002 ???????????????? + +The `0x0`, `0x10`, etc is the position. The next number is the bytecode for that position. This is followed by question marks and seemingly random letters & numbers. This is **Remix**'s attempt to convert this into a string. + +So if we glue the first four sections of bytecode together, we'll get: +**0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e0a6fc9164736f6c63430005110032** The last section - `0x90` has 2 which is what I input for the constructors parameter. + +The input data from the **Call Data** panel is: +`0x6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c634300051100320000000000000000000000000000000000000000000000000000000000000002` +**I'll refer to this value as (Y).** + +This shows us that `(X)` is a subset of the original calldata `(Y)`: + +`(X)` is calldata without the input parameter `0000000000000000000000000000000000000000000000000000000000000002` (we don't need to store this) +and without the constructor code `6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe` which should be executed only 1 time. + +So `CODECOPY` extracts the bytecode from the calldata and copies it to the memory. + +Let's move to the next step. diff --git a/locales/fa/OpcodesInTheDebugger/7_returnAndStore/step.md b/locales/fa/OpcodesInTheDebugger/7_returnAndStore/step.md new file mode 100644 index 000000000..b375a24fb --- /dev/null +++ b/locales/fa/OpcodesInTheDebugger/7_returnAndStore/step.md @@ -0,0 +1,18 @@ +# The Opcode RETURN + +At the end of the last chapter we had moved to one step after **CODECOPY** to see what happened in the memory. + +Now that CODECOPY has been executed, we are on the opcode `PUSH1 00`. + +`PUSH1 00` prepares the stack for the `RETURN` opcode. +`RETURN` is the last part of this process. It is where the code is returned to the client. + +We push `00` to the stack because this is the offset position of the contract bytecode in memory. + +Now we can call the all important `RETURN` opcode. + +The **stack inspector** shows: +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x000000000000000000000000000000000000000000000000000000000000003e` + +Which is to say it returns to the client the bytecode starting `0x00` with length `0x3e`. diff --git a/locales/fa/OpcodesInTheDebugger/8_findTheOffset/step.md b/locales/fa/OpcodesInTheDebugger/8_findTheOffset/step.md new file mode 100644 index 000000000..6b1ddc5cf --- /dev/null +++ b/locales/fa/OpcodesInTheDebugger/8_findTheOffset/step.md @@ -0,0 +1,18 @@ +# Find the offset ;) + +And now for a slightly different example: + +- Compile notSimpleStore.sol +- Deploy the contract `notSoSimpleStore` +- Make sure you have a successful deployment - if not check that you used **the correct input type** in the constructor. +- Go to the Debugger by clicking the **debug** button at the (successful) creation transaction. +- Find the value of the parameter of `CODECOPY` which represents the offset in calldata where to copy from. + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +If you look in the **Stack**, you should see that the 2nd element is: +0x0000000000000000000000000000000000000000000000000000000000000083 + +And this is the **f** of the input params of codecopy. + +### Hope you picked up a thing or 2 about how opcodes work! diff --git a/locales/fa/OpcodesInTheDebugger/config.yml b/locales/fa/OpcodesInTheDebugger/config.yml new file mode 100644 index 000000000..74a1bf3a1 --- /dev/null +++ b/locales/fa/OpcodesInTheDebugger/config.yml @@ -0,0 +1,10 @@ +--- +id: opcodesdebug +name: Opcodes in the Debugger +summary: Using the Debugger, we'll check out what the CODECOPY opcode does and how it is used by the EVM during contract creation. +level: 3 +tags: + - Remix + - Debugging + - EVM + - Opcodes diff --git a/locales/fa/ProxyContract/1_Why/step1.md b/locales/fa/ProxyContract/1_Why/step1.md new file mode 100644 index 000000000..b4a38aaeb --- /dev/null +++ b/locales/fa/ProxyContract/1_Why/step1.md @@ -0,0 +1,27 @@ +# Proxy Contract AKA the Dispatcher + +## Why? + +This is a great pattern that is used mainly in **library development**. + +It helps in the following ways: + +- **Save gas cost at deployment time** + The purpose of a high gas cost is to discourage the operations that cost a lot for their execution and to encourage optimized code. + +- Proxy contracts are useful when a lot of instances of the same contract need to be deployed because they reduce the duplications in the deployment. + +- **Avoid code repetition in the blockchain.** + Heavy computations are expensive because every node will need to perform them, this is of course slowing the network. + +- **Develop upgradable(versioned) contracts** + When the contract is deployed, it’s immutable. By re-designing the code into different contracts, it is possible to allow logic upgrades while keeping the storage the same. + +## Example of gas cost + +Storing contract code at creation time can cost up to: + +- 200 \* max_byte_code_length gas +- 200 \* 24576 = 49152004915200 \* 10 gwei = 49152000 gwei = 0.049152 ether = 9 EUR + +see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md for more info on max_byte_code_length. diff --git a/locales/fa/ProxyContract/2_How/step2.md b/locales/fa/ProxyContract/2_How/step2.md new file mode 100644 index 000000000..d80b6557c --- /dev/null +++ b/locales/fa/ProxyContract/2_How/step2.md @@ -0,0 +1,13 @@ +# How it works? + +**EIP-7 DelegateCall** opcode allows a separate execution in another contract while maintaining the original execution context. + +All **message calls** from the user go through a **Proxy contract**. + +The **Proxy contract** then will redirect them to the **Logic contract**. + +And when you need to **upgrade** the logic, you'll **just** deploy that - **HOWEVER** - the implementation of Proxy will remain the same. + +You'll only need to update the address of Logic contract in Proxy. + +The Proxy Contract uses **Delegate calls** and **Solidity assembly** because without it, it's impossible to return any value from **delegatecall**. diff --git a/locales/fa/ProxyContract/3_Delegatecall/step3.md b/locales/fa/ProxyContract/3_Delegatecall/step3.md new file mode 100644 index 000000000..8693e5567 --- /dev/null +++ b/locales/fa/ProxyContract/3_Delegatecall/step3.md @@ -0,0 +1,9 @@ +# Delegate call + +It's a special variant of a **message call**, which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract so **msg.sender** and **msg.value** do not change their values. + +This means that a contract can dynamically load code from a different address at runtime. + +The storage, the current address and balance still refer to the calling contract, only the code is taken from the called address. + +So when a **Proxy** delegates calls to the Logic contract, every storage modification will impact the storage of Logic contract. diff --git a/locales/fa/ProxyContract/4_Generic_proxy_example/step4.md b/locales/fa/ProxyContract/4_Generic_proxy_example/step4.md new file mode 100644 index 000000000..d20fdd16d --- /dev/null +++ b/locales/fa/ProxyContract/4_Generic_proxy_example/step4.md @@ -0,0 +1,15 @@ +# A Basic Generic Proxy Example + +In the associated solidity file, **step4.sol**, there are 2 contracts - **ProxyContract** and **LogicContract**. + +To use this system, we first deploy the LogicContract. + +And then when we go to deploy the ProxyContract, we pass the LogicContract's address as an argument of the ProxyContract's constructor. + +The ProxyContract is deployed only once. + +The code of LogicContract will be called at the line 20. It will be forwarded with delegate call while keeping the context of LogicContract. + +In case we need to change the logic we would deploy a new LogicContract and set the address of it with setLogicContractAddress setter function. + +_Note: The LogicContract we have here does not use the storage. Once you need to use the storage the implementation becomes a bit more complicated because those contracts share the context._ diff --git a/locales/fa/ProxyContract/5_Test/step5.md b/locales/fa/ProxyContract/5_Test/step5.md new file mode 100644 index 000000000..120a15e13 --- /dev/null +++ b/locales/fa/ProxyContract/5_Test/step5.md @@ -0,0 +1,6 @@ +# Let's test what we've learned + +- Write a contract named "LogicContract" which implements a public function named "getNumber" which returns 10 +- Write a proxy contract named "ProxyContract". This ProxyContract should take an address of LogicContract as a first parameter. + +Good Luck! diff --git a/locales/fa/ProxyContract/6_Storage_Problem/step6.md b/locales/fa/ProxyContract/6_Storage_Problem/step6.md new file mode 100644 index 000000000..d2b804284 --- /dev/null +++ b/locales/fa/ProxyContract/6_Storage_Problem/step6.md @@ -0,0 +1,13 @@ +# What if we have state variables? + +Things are more complicated once we need to deal with state variables. State variable are saved to **storage**. + +`storage`: is a mapping; each value stored there is persisted and saved on chain. + +_Note: Statically-sized state variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position 0. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible. For contracts that use inheritance, the ordering of state variables is determined by the C3-linearized order of contracts starting with the most base-ward contract_ + +Once we execute **delegate call**, the storage of both contracts get **"merged"** into a single messy state. + +We have to "tell" ProxyContract what the **state** of the **Logic contract** looks like. + +The easiest way to do this is to create a separate contract - in this example - named **StorageContract** which will represent the **state** and which proxyContract will inherit from. diff --git a/locales/fa/ProxyContract/7_links/step7.md b/locales/fa/ProxyContract/7_links/step7.md new file mode 100644 index 000000000..c2784c3cc --- /dev/null +++ b/locales/fa/ProxyContract/7_links/step7.md @@ -0,0 +1,19 @@ +# Check out some links for more info + +- ERC DelegateProxy + https://github.com/ethereum/EIPs/pull/897 + +- The joint post by Zeppelin Solutions and Aragon. + https://blog.openzeppelin.com/proxy-libraries-in-solidity-79fbe4b970fd/ + +- Proxy Patterns by OpenZeppelin + https://blog.openzeppelin.com/proxy-patterns/ + +- The most mature implementation of Proxy pattern is The Unstructure Storage pattern that is released as part of ZeppelinOS + https://blog.openzeppelin.com/upgradeability-using-unstructured-storage/ + +- Great blog post by Jack Tanner + https://blog.indorse.io/ethereum-upgradeable-smart-contract-strategies-456350d0557c + +- Upgradeable Ethereum Smart Contracts + https://medium.com/@daonomic/upgradeable-ethereum-smart-contracts-d036cb373d6 diff --git a/locales/fa/ProxyContract/README.md b/locales/fa/ProxyContract/README.md new file mode 100644 index 000000000..6a5364c94 --- /dev/null +++ b/locales/fa/ProxyContract/README.md @@ -0,0 +1,3 @@ +## Learn the Proxy Pattern + +Save gas & make upgradable contracts diff --git a/locales/fa/ProxyContract/config.yml b/locales/fa/ProxyContract/config.yml new file mode 100644 index 000000000..e36e640b8 --- /dev/null +++ b/locales/fa/ProxyContract/config.yml @@ -0,0 +1,9 @@ +--- +id: proxycontract +name: All about Proxy Contracts +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 3 +tags: + - Remix + - Solidity + - Code Patterns diff --git a/locales/fa/README.md b/locales/fa/README.md new file mode 100644 index 000000000..cb799bd20 --- /dev/null +++ b/locales/fa/README.md @@ -0,0 +1,36 @@ +# This is a repo of tutorials for the Remix's LearnEth Plugin + +### To use these tutorials: + +**1. Open Remix** + +https://remix.ethereum.org + +**2. In the plugin manager activate LEARNETH** + +**3. Go to the Learneth plugin and these tutorials will load by default** + +**4. You may need to sign into Github especially during an in-person workshop** + +Github will block too many requests from the same location, unless you are signed into Github and have input your token. Generally, this is only an issue during in person workshops, when there can be many requests from the same location. + +To input your Github token: + +``` +- In one browser window - go to https://remix.ethereum.org and go to the settings tab +- In another browser window go to: + +https://github.com/settings/tokens + +and create a new token and save it in Remix in the you just opened on the settings tab. +``` + +--- + +### Write your own tutorials for LEARNETH: + +See this site for instructions: + +https://remix-learneth-plugin.readthedocs.io/en/latest/index.html#creating-tutorials + +--- diff --git a/locales/fa/Recorder/1_Usecases/1_usecases.md b/locales/fa/Recorder/1_Usecases/1_usecases.md new file mode 100644 index 000000000..0c624393c --- /dev/null +++ b/locales/fa/Recorder/1_Usecases/1_usecases.md @@ -0,0 +1,7 @@ +1. You want to show someone what happens when you do a number of transactions with a contract and you don't want to explain each step - you just want to get them to the last step. + + - To show someone a problem in their code. + + - In a class, to get the students to a certain place and have them start working from there. + +2. You want to start your development in the JavascriptVM because it is quick and then to switch to another testnet - but you don't want to manually repeat all the tedious clicking for each different network. diff --git a/locales/fa/Recorder/2_Record/README.md b/locales/fa/Recorder/2_Record/README.md new file mode 100644 index 000000000..41d214277 --- /dev/null +++ b/locales/fa/Recorder/2_Record/README.md @@ -0,0 +1,32 @@ +# Setting up a tedious series of steps + +## Following this could get tedious but that's the point. + +We are going to: + +- Deploy a voting contract where there are 3 proposals input in the constructor. +- Give voting privileges to 2 additional address (so we have a total of 3 voting addresses). +- Have one address vote for proposal 1 (0-based index) and the other two vote for proposal 2. + +1. Take the 3_Ballot.sol from the sample solidity files and compile it. Then go to the **Deploy & Run** Module. + +2. Select the **JavaScript VM** Environment. + +3. In the constructor's parameter - put in **["0x5031000000000000000000000000000000000000000000000000000000000000", "0x5032000000000000000000000000000000000000000000000000000000000000", "0x5033000000000000000000000000000000000000000000000000000000000000"]** Then click the **Deploy** button. + +4. Open up the deployed contract. + +5. In the **vote** function put in 2. This means that you as the msg.sender & chairperson are voting for proposal at position 2, which is the last proposal in our list. + +6. Now you need to give other addresses the right to vote. Select another address in the **account** pulldown and copy it and then **go back to the 1st address**. Paste the copy address into the textbox next to the giveRightToVote function. And again, select another address and copy it and **then go back to the 1st address** again and paste it into giveRightToVote. + +7. Now you have 3 addresses with the right to vote. + +8. Switch to one of the addresses that you gave the right to vote and vote for proposal **1**. (Put **1** in the textbox next to the vote function). And then switch to the other address and vote for proposal **2** with that one. + +9. Open up the **Transactions recorded** section of the module - by clicking on the caret. Click the hard disk icon in the **Transactions recorded** section to save your steps. + ![recorder](https://github.com/ethereum/remix-workshops/blob/master/Recorder/2_Record/images/recorder.png?raw=true "recorder") + +10. You will get a modal window that tells you it wants to save a file called **scenario.json**. Click OK. + +11. Click on the function **winningProposal** to confirm that the final proposal won - which is the proposal at position 2 in the array. **0: uint256: winningProposal_ 2** diff --git a/locales/fa/Recorder/3_Editing_a_Senario/README.md b/locales/fa/Recorder/3_Editing_a_Senario/README.md new file mode 100644 index 000000000..d23dfb95c --- /dev/null +++ b/locales/fa/Recorder/3_Editing_a_Senario/README.md @@ -0,0 +1,54 @@ +# Editing a scenario + +Here's the first few lines of the scenario that I recorded. The addresses on my machine will be different from your's. + +``` +{ + "accounts": { + "account{0}": "0xca35b7d915458ef540ade6068dfe2f44e8fa733c", + "account{4}": "0xdd870fa1b7c4700f2bd7f44238821c26f7392148", + "account{3}": "0x583031d1113ad414f02576bd6afabfb302140225" + } +``` + +So if you wanted to play this scenario in another testnet, you'd need to change these addresses to address that you have test ETH on so that you could pay for the transactions. But other than swapping out the addresses, you can quickly run this on other nets. + +And you might change the parameters for the functions. + +For example here is a bit of the scenario.json a bit further down where proposal 2 was voted for by one of the addresses: + +``` +{ + "timestamp": 1566428184043, + "record": { + "value": "0", + "parameters": [ + "2" + ], + "to": "created{1566428035436}", + "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", + "name": "vote", + "inputs": "(uint8)", + "type": "function", + "from": "account{4}" + } + }, +``` + +Let's edit this so that another proposal wins in the playback. + +Change the **parameters** array which now is: + +``` +"parameters": [ + "2" + ] +``` + +to: + +``` +"parameters": [ + "1" + ] +``` diff --git a/locales/fa/Recorder/4_Play/README.md b/locales/fa/Recorder/4_Play/README.md new file mode 100644 index 000000000..196664550 --- /dev/null +++ b/locales/fa/Recorder/4_Play/README.md @@ -0,0 +1,8 @@ +# Playing a scenario + +1. Click the play icon to the right of the floppy disk icon to play the steps you did. + +2. You'll see another instance of the contract deployed. Open it up. + +3. Click the winningProposal function and you should see now that proposal 1 won. + It should print out: **0: uint256: winningProposal_ 1** diff --git a/locales/fa/Recorder/README.md b/locales/fa/Recorder/README.md new file mode 100644 index 000000000..94d928383 --- /dev/null +++ b/locales/fa/Recorder/README.md @@ -0,0 +1,3 @@ +## Get yourself Remixing! + +The recorder is used for recording a set of transactions in the Deploy & Run module, editing their parameters and then playing them back in another context. It really is the remix of Remix! diff --git a/locales/fa/Recorder/config.yml b/locales/fa/Recorder/config.yml new file mode 100644 index 000000000..b8980e042 --- /dev/null +++ b/locales/fa/Recorder/config.yml @@ -0,0 +1,7 @@ +--- +id: recorder +name: Recorder +summary: Save a set of actions and replay and replay and replay +level: 2 +tags: + - Remix diff --git a/locales/fa/SolidityBeginnerCourse/README.md b/locales/fa/SolidityBeginnerCourse/README.md new file mode 100644 index 000000000..ae0b6d882 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Course + +Learn the most important Solidity beginner concepts interactively, based on the popular https://solidity-by-example.org/ contracts. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/fa/SolidityBeginnerCourse/basic-syntax/basicSyntax.md b/locales/fa/SolidityBeginnerCourse/basic-syntax/basicSyntax.md new file mode 100644 index 000000000..e9f77871e --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/basic-syntax/basicSyntax.md @@ -0,0 +1,26 @@ +In this section, we will create our first _smart contract_. This contract only consists of a string that holds the value "Hello World!". + +In the first line, we should specify the license that we want to use. You can find a comprehensive list of licenses here: https://spdx.org/licenses/. + +Using the `pragma` keyword (line 3), we specify the Solidity version we want the compiler to use. In this case, it should be greater than or equal to `0.8.3` but less than 0.9.0. + +We define a contract with the keyword `contract` and give it a name, in this case, `HelloWorld` (line 5). + +Inside our contract, we define a _state variable_ `greet` that holds the string `"Hello World!"` (line 6). + +Solidity is a _statically typed_ language, which means that you need to specify the type of the variable when you declare it. In this case, `greet` is a `string`. + +We also define the _visibility_ of the variable, which specifies from where you can access it. In this case, it's a `public` variable that you can access from inside and outside the contract. + +Don't worry if you didn't understand some concepts like _visibility_, _data types_, or _state variables_. We will look into them in the following sections. + +To help you understand the code, we will link in all following sections to video tutorials from the creator of the Solidity by Example contracts. + +Watch a video tutorial on Basic Syntax. + +## ⭐️ Assignment + +1. Delete the HelloWorld contract and its content. +2. Create a new contract named "MyContract". +3. The contract should have a public state variable called "name" of the type string. +4. Assign the value "Alice" to your new variable. diff --git a/locales/fa/SolidityBeginnerCourse/config.yml b/locales/fa/SolidityBeginnerCourse/config.yml new file mode 100644 index 000000000..a729093d8 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/config.yml @@ -0,0 +1,65 @@ +--- +id: soliditybeginner +name: Solidity Beginner Course +summary: Solidity Beginner Course based on the popular https://solidity-by-example.org/ contracts. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Basic Syntax + path: basic-syntax + - + name: 3. Primitive Data Types + path: primitive-data-types + - + name: 4. Variables + path: variables + - + name: 5.1 Functions - Reading and Writing to a State Variable + path: functions-reading-and-writing + - + name: 5.2 Functions - View and Pure + path: functions-view-and-pure + - + name: 5.3 Functions - Modifiers and Constructors + path: functions-modifiers-and-constructors + - + name: 5.4 Functions - Inputs and Outputs + path: functions-inputs-and-outputs + - + name: 6. Visibility + path: visibility + - + name: 7.1 Control Flow - If/Else + path: control-flow-if-else + - + name: 7.2 Control Flow - Loops + path: control-flow-loops + - + name: 8.1 Data Structures - Arrays + path: data-structures-arrays + - + name: 8.2 Data Structures - Mappings + path: data-structures-mappings + - + name: 8.3 Data Structures - Structs + path: data-structures-structs + - + name: 8.4 Data Structures - Enums + path: data-structures-enums + - + name: 9. Data Locations + path: data-locations + - + name: 10.1 Transactions - Ether and Wei + path: transactions-ether-and-wei + - + name: 10.2 Transactions - Gas and Gas Price + path: transactions-gas-and-gas-price + - + name: 10.3 Transactions - Sending Ether + path: transactions-sending-ether diff --git a/locales/fa/SolidityBeginnerCourse/control-flow-if-else/ifElse.md b/locales/fa/SolidityBeginnerCourse/control-flow-if-else/ifElse.md new file mode 100644 index 000000000..634e27689 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/control-flow-if-else/ifElse.md @@ -0,0 +1,33 @@ +Solidity supports different control flow statements that determine which parts of the contract will be executed. The conditional _If/Else statement_ enables contracts to make decisions depending on whether boolean conditions are either `true` or `false`. + +Solidity differentiates between three different If/Else statements: `if`, `else`, and `else if`. + +### if + +The `if` statement is the most basic statement that allows the contract to perform an action based on a boolean expression. + +In this contract’s `foo` function (line 5) the if statement (line 6) checks if `x` is smaller than `10`. If the statement is true, the function returns `0`. + +### else + +The `else` statement enables our contract to perform an action if conditions are not met. + +In this contract, the `foo` function uses the `else` statement (line 10) to return `2` if none of the other conditions are met. + +### else if + +With the `else if` statement we can combine several conditions. + +If the first condition (line 6) of the foo function is not met, but the condition of the `else if` statement (line 8) becomes true, the function returns `1`. + +Watch a video tutorial on the If/Else statement. + +## ⭐️ Assignment + +Create a new function called `evenCheck` in the `IfElse` contract: + +- That takes in a `uint` as an argument. +- The function returns `true` if the argument is even, and `false` if the argument is odd. +- Use a ternery operator to return the result of the `evenCheck` function. + +Tip: The modulo (%) operator produces the remainder of an integer division. diff --git a/locales/fa/SolidityBeginnerCourse/control-flow-loops/loops.md b/locales/fa/SolidityBeginnerCourse/control-flow-loops/loops.md new file mode 100644 index 000000000..ffaa30650 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/control-flow-loops/loops.md @@ -0,0 +1,32 @@ +Solidity supports iterative control flow statements that allow contracts to execute code repeatedly. + +Solidity differentiates between three types of loops: `for`, `while`, and `do while` loops. + +### for + +Generally, `for` loops (line 7) are great if you know how many times you want to execute a certain block of code. In solidity, you should specify this amount to avoid transactions running out of gas and failing if the amount of iterations is too high. + +### while + +If you don’t know how many times you want to execute the code but want to break the loop based on a condition, you can use a `while` loop (line 20). +Loops are seldom used in Solidity since transactions might run out of gas and fail if there is no limit to the number of iterations that can occur. + +### do while + +The `do while` loop is a special kind of while loop where you can ensure the code is executed at least once, before checking on the condition. + +### continue + +The `continue` statement is used to skip the remaining code block and start the next iteration of the loop. In this contract, the `continue` statement (line 10) will prevent the second if statement (line 12) from being executed. + +### break + +The `break` statement is used to exit a loop. In this contract, the break statement (line 14) will cause the for loop to be terminated after the sixth iteration. + +Watch a video tutorial on Loop statements. + +## ⭐️ Assignment + +1. Create a public `uint` state variable called count in the `Loop` contract. +2. At the end of the for loop, increment the count variable by 1. +3. Try to get the count variable to be equal to 9, but make sure you don’t edit the `break` statement. diff --git a/locales/fa/SolidityBeginnerCourse/data-locations/dataLocations.md b/locales/fa/SolidityBeginnerCourse/data-locations/dataLocations.md new file mode 100644 index 000000000..881bf8ffc --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/data-locations/dataLocations.md @@ -0,0 +1,54 @@ +The values of variables in Solidity can be stored in different data locations: _memory_, _storage_, and _calldata_. + +As we have discussed before, variables of the value type store an independent copy of a value, while variables of the reference type (array, struct, mapping) only store the location (reference) of the value. + +If we use a reference type in a function, we have to specify in which data location their values are stored. The price for the execution of the function is influenced by the data location; creating copies from reference types costs gas. + +### Storage + +Values stored in _storage_ are stored permanently on the blockchain and, therefore, are expensive to use. + +In this contract, the state variables `arr`, `map`, and `myStructs` (lines 5, 6, and 10) are stored in storage. State variables are always stored in storage. + +### Memory + +Values stored in _memory_ are only stored temporarily and are not on the blockchain. They only exist during the execution of an external function and are discarded afterward. They are cheaper to use than values stored in _storage_. + +In this contract, the local variable `myMemstruct` (line 19), as well as the parameter `_arr` (line 31), are stored in memory. Function parameters need to have the data location _memory_ or _calldata_. + +### Calldata + +_Calldata_ stores function arguments. Like _memory_, _calldata_ is only stored temporarily during the execution of an external function. In contrast to values stored in _memory_, values stored in _calldata_ can not be changed. Calldata is the cheapest data location to use. + +In this contract, the parameter `_arr` (line 35) has the data location _calldata_. If we wanted to assign a new value to the first element of the array `_arr`, we could do that in the `function g` (line 31) but not in the `function h` (line 35). This is because `_arr` in `function g `has the data location _memory_ and _function h_ has the data location `calldata`. + +## Assignments + +### Memory to memory + +Assignments from _memory_ to _memory_ create references instead of copies. If you change the value in one variable, the value of all other variables that reference the same data will be changed. + +If we were to create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myMemStruct` (line 19), any change to `myMemStruct2` would also change the value of `myMemStruct`. + +### Storage to local storage + +Assignments from _storage_ to _local storage_ also create references, not copies. + +If we change the value of the local variable `myStruct` (line 17), the value of our state variable `myStructs` (line 10) changes as well. + +## Storage and memory/calldata + +Assignments between _storage_ and _memory_ (or _calldata_) create independent copies, not references. + +If we were to create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myStruct`, changes in `myMemStruct3` would not affect the values stored in the mapping `myStructs` (line 10). + +As we said in the beginning, when creating contracts we have to be mindful of gas costs. Therefore, we need to use data locations that require the lowest amount of gas possible. + +## ⭐️ Assignment + +1. Change the value of the `myStruct` member `foo`, inside the `function f`, to 4. +2. Create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` and assign it the value of `myMemStruct`. Change the value of the `myMemStruct2` member `foo` to 1. +3. Create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` and assign it the value of `myStruct`. Change the value of the `myMemStruct3` member `foo` to 3. +4. Let the function f return `myStruct`, `myMemStruct2`, and `myMemStruct3`. + +Tip: Make sure to create the correct return types for the function `f`. diff --git a/locales/fa/SolidityBeginnerCourse/data-structures-arrays/arrays.md b/locales/fa/SolidityBeginnerCourse/data-structures-arrays/arrays.md new file mode 100644 index 000000000..19af3de49 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/data-structures-arrays/arrays.md @@ -0,0 +1,44 @@ +In the next sections, we will look into the data structures that we can use to organize and store our data in Solidity. + +_Arrays_, _mappings_ and _structs_ are all _reference types_. Unlike _value types_ (e.g. _booleans_ or _integers_) reference types don't store their value directly. Instead, they store the location where the value is being stored. Multiple reference type variables could reference the same location, and a change in one variable would affect the others, therefore they need to be handled carefully. + +In Solidity, an array stores an ordered list of values of the same type that are indexed numerically. + +There are two types of arrays, compile-time _fixed-size_ and _dynamic arrays_. For fixed-size arrays, we need to declare the size of the array before it is compiled. The size of dynamic arrays can be changed after the contract has been compiled. + +### Declaring arrays + +We declare a fixed-size array by providing its type, array size (as an integer in square brackets), visibility, and name (line 9). + +We declare a dynamic array in the same manner. However, we don’t provide an array size and leave the brackets empty (line 6). + +### Initializing arrays + +We can initialize the elements of an array all at once (line 7), or initiate new elements one by one (arr[0] = 1;). If we declare an array, we automatically initialize its elements with the default value 0 (line 9). + +### Accessing array elements + +We access elements inside an array by providing the name of the array and the index in brackets (line 12). + +### Adding array elements + +Using the `push()` member function, we add an element to the end of a dynamic array (line 25). + +### Removing array elements + +Using the `pop()` member function, we delete the last element of a dynamic array (line 31). + +We can use the `delete` operator to remove an element with a specific index from an array (line 42). +When we remove an element with the `delete` operator all other elements stay the same, which means that the length of the array will stay the same. This will create a gap in our array. +If the order of the array is not important, then we can move the last element of the array to the place of the deleted element (line 46), or use a mapping. A mapping might be a better choice if we plan to remove elements in our data structure. + +### Array length + +Using the length member, we can read the number of elements that are stored in an array (line 35). + +Watch a video tutorial on Arrays. + +## ⭐️ Assignment + +1. Initialize a public fixed-sized array called `arr3` with the values 0, 1, 2. Make the size as small as possible. +2. Change the `getArr()` function to return the value of `arr3`. diff --git a/locales/fa/SolidityBeginnerCourse/data-structures-enums/enums.md b/locales/fa/SolidityBeginnerCourse/data-structures-enums/enums.md new file mode 100644 index 000000000..40411db67 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/data-structures-enums/enums.md @@ -0,0 +1,33 @@ +In Solidity _enums_ are custom data types consisting of a limited set of constant values. We use enums when our variables should only get assigned a value from a predefined set of values. + +In this contract, the state variable `status` can get assigned a value from the limited set of provided values of the enum `Status` representing the various states of a shipping status. + +### Defining enums + +We define an enum with the enum keyword, followed by the name of the custom type we want to create (line 6). Inside the curly braces, we define all available members of the enum. + +### Initializing an enum variable + +We can initialize a new variable of an enum type by providing the name of the enum, the visibility, and the name of the variable (line 16). Upon its initialization, the variable will be assigned the value of the first member of the enum, in this case, Pending (line 7). + +Even though enum members are named when you define them, they are stored as unsigned integers, not strings. They are numbered in the order that they were defined, the first member starting at 0. The initial value of status, in this case, is 0. + +### Accessing an enum value + +To access the enum value of a variable, we simply need to provide the name of the variable that is storing the value (line 25). + +### Updating an enum value + +We can update the enum value of a variable by assigning it the `uint` representing the enum member (line 30). Shipped would be 1 in this example. Another way to update the value is using the dot operator by providing the name of the enum and its member (line 35). + +### Removing an enum value + +We can use the delete operator to delete the enum value of the variable, which means as for arrays and mappings, to set the default value to 0. + +Watch a video tutorial on Enums. + +## ⭐️ Assignment + +1. Define an enum type called `Size` with the members `S`, `M`, and `L`. +2. Initialize the variable `sizes` of the enum type `Size`. +3. Create a getter function `getSize()` that returns the value of the variable `sizes`. diff --git a/locales/fa/SolidityBeginnerCourse/data-structures-mappings/mappings.md b/locales/fa/SolidityBeginnerCourse/data-structures-mappings/mappings.md new file mode 100644 index 000000000..72fc4acb4 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/data-structures-mappings/mappings.md @@ -0,0 +1,37 @@ +In Solidity, _mappings_ are a collection of key types and corresponding value type pairs. + +The biggest difference between a mapping and an array is that you can't iterate over mappings. If we don't know a key we won't be able to access its value. If we need to know all of our data or iterate over it, we should use an array. + +If we want to retrieve a value based on a known key we can use a mapping (e.g. addresses are often used as keys). Looking up values with a mapping is easier and cheaper than iterating over arrays. If arrays become too large, the gas cost of iterating over it could become too high and cause the transaction to fail. + +We could also store the keys of a mapping in an array that we can iterate over. + +### Creating mappings + +Mappings are declared with the syntax `mapping(KeyType => ValueType) VariableName`. +The key type can be any built-in value type or any contract, but not a reference type. The value type can be of any type. + +In this contract, we are creating the public mapping `myMap` (line 6) that associates the key type `address` with the value type `uint`. + +### Accessing values + +The syntax for interacting with key-value pairs of mappings is similar to that of arrays. +To find the value associated with a specific key, we provide the name of the mapping and the key in brackets (line 11). + +In contrast to arrays, we won't get an error if we try to access the value of a key whose value has not been set yet. When we create a mapping, every possible key is mapped to the default value 0. + +### Setting values + +We set a new value for a key by providing the mapping’s name and key in brackets and assigning it a new value (line 16). + +### Removing values + +We can use the delete operator to delete a value associated with a key, which will set it to the default value of 0. As we have seen in the arrays section. + +Watch a video tutorial on Mappings. + +## ⭐️ Assignment + +1. Create a public mapping `balances` that associates the key type `address` with the value type `uint`. +2. Change the functions `get` and `remove` to work with the mapping balances. +3. Change the function `set` to create a new entry to the balances mapping, where the key is the address of the parameter and the value is the balance associated with the address of the parameter. diff --git a/locales/fa/SolidityBeginnerCourse/data-structures-structs/structs.md b/locales/fa/SolidityBeginnerCourse/data-structures-structs/structs.md new file mode 100644 index 000000000..fba0d93b0 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/data-structures-structs/structs.md @@ -0,0 +1,29 @@ +In Solidity, we can define custom data types in the form of _structs_. Structs are a collection of variables that can consist of different data types. + +### Defining structs + +We define a struct using the `struct` keyword and a name (line 5). Inside curly braces, we can define our struct’s members, which consist of the variable names and their data types. + +### Initializing structs + +There are different ways to initialize a struct. + +Positional parameters: We can provide the name of the struct and the values of its members as parameters in parentheses (line 16). + +Key-value mapping: We provide the name of the struct and the keys and values as a mapping inside curly braces (line 19). + +Initialize and update a struct: We initialize an empty struct first and then update its member by assigning it a new value (line 23). + +### Accessing structs + +To access a member of a struct we can use the dot operator (line 33). + +### Updating structs + +To update a structs’ member we also use the dot operator and assign it a new value (lines 39 and 45). + +Watch a video tutorial on Structs. + +## ⭐️ Assignment + +Create a function `remove` that takes a `uint` as a parameter and deletes a struct member with the given index in the `todos` mapping. diff --git a/locales/fa/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md b/locales/fa/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md new file mode 100644 index 000000000..d0e628f6b --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md @@ -0,0 +1,37 @@ +In this section, we will learn more about the inputs and outputs of functions. + +### Multiple named Outputs + +Functions can return multiple values that can be named and assigned to their name. + +The `returnMany` function (line 6) shows how to return multiple values. +You will often return multiple values. It could be a function that collects outputs of various functions and returns them in a single function call for example. + +The `named` function (line 19) shows how to name return values. +Naming return values helps with the readability of your contracts. Named return values make it easier to keep track of the values and the order in which they are returned. You can also assign values to a name. + +The `assigned` function (line 33) shows how to assign values to a name. +When you assign values to a name you can omit (leave out) the return statement and return them individually. + +### Deconstructing Assignments + +You can use deconstructing assignments to unpack values into distinct variables. + +The `destructingAssigments` function (line 49) assigns the values of the `returnMany` function to the new local variables `i`, `b`, and `j` (line 60). + +### Input and Output restrictions + +There are a few restrictions and best practices for the input and output parameters of contract functions. + +"_[Mappings] cannot be used as parameters or return parameters of contract functions that are publicly visible._" +From the Solidity documentation. + +Arrays can be used as parameters, as shown in the function `arrayInput` (line 71). Arrays can also be used as return parameters as shown in the function `arrayOutput` (line 76). + +You have to be cautious with arrays of arbitrary size because of their gas consumption. While a function using very large arrays as inputs might fail when the gas costs are too high, a function using a smaller array might still be able to execute. + +Watch a video tutorial on Function Outputs. + +## ⭐️ Assignment + +Create a new function called `returnTwo` that returns the values `-2` and `true` without using a return statement. diff --git a/locales/fa/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md b/locales/fa/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md new file mode 100644 index 000000000..d707a987b --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md @@ -0,0 +1,39 @@ +In this section, we will learn how to modify the behavior of a function and how to run contract initialization code. + +### Function Modifier + +_Function Modifiers_ are used to change the behavior of a function. For example, they often check for a condition prior to executing a function to restrict access or validate inputs. + +This first part of this contract is about changing ownership of a contract. Ownership in this contract is expressed by the value of the state variable `owner` that is of the type `address` (line 7). + +The function `changeOwner` (line 33) can change this ownership. It takes an input parameter of the type `address` and assigns its value to the state variable `owner`. + +However, this function cannot simply be executed under all conditions; it has two modifiers, `onlyOwner` and `validAddress`. + +Let's look at `onlyOwner` first (line 18). +Function modifiers are defined with the `modifier` keyword and a unique name; they can also have parameters. + +The underscore `_` (line 23) is used inside modifiers to represent the rest of the code that will be executed in the body of the modified function. +The code you place before the underscore in the modifier will be executed before the code in the body of the modified function. The code after the underscore will be executed after the code in the body of the modified function. + +In this case, the `require` function (line 19) checks if the address executing the contract is the same as the value stored in the variable `owner`. If it is, the rest of the code will be executed, otherwise it will throw an error. + +You can learn more about `assert` and `require` in the Solidity documentation, they are used to check for conditions and throw errors if they are not met. + +The `validAddress` modifier (line 28) has a parameter of type `address` and checks if the provided address is valid. If it is, it continues to execute the code. + +### Constructor + +A constructor function is executed upon the creation of a contract. You can use it to run contract initialization code. The constructor can have parameters and is especially useful when you don't know certain initialization values before the deployment of the contract. + +You declare a constructor using the `constructor` keyword. The constructor in this contract (line 11) sets the initial value of the owner variable upon the creation of the contract. + +Watch a video tutorial on Function Modifiers. + +## ⭐️ Assignment + +1. Create a new function, `increaseX` in the contract. The function should take an input parameter of type `uint` and increase the value of the variable `x` by the value of the input parameter. +2. Make sure that x can only be increased. +3. The body of the function `increaseX` should be empty. + +Tip: Use modifiers. diff --git a/locales/fa/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md b/locales/fa/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md new file mode 100644 index 000000000..3670c03e2 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md @@ -0,0 +1,23 @@ +This section will give a short introduction to functions and teach you how to use them to read from and write to a state variable. + +As in other languages, we use functions in Solidity to create modular, reusable code. However, Solidity functions have some particularities. + +Solidity functions can be split into two types: + +1. Functions that modify the state of the blockchain, like writing to a state variable. In this contract, the `set` function (line 9) changes the state variable `num`. +2. Functions that don't modify the state of the blockchain. These functions are marked `view` or `pure`. For example, in this contract, the `get` function (line 14) marked `view` that only returns `num` does not change the state. + +To define a function, use the `function` keyword followed by a unique name. + +If the function takes inputs like our `set` function (line 9), you must specify the parameter types and names. A common convention is to use an underscore as a prefix for the parameter name to distinguish them from state variables. + +You can then set the visibility of a function and declare them `view` or `pure` as we do for the `get` function if they don't modify the state. Our `get` function also returns values, so we have to specify the return types. In this case, it's a `uint` since the state variable `num` that the function returns is a `uint`. + +We will explore the particularities of Solidity functions in more detail in the following sections. + +Watch a video tutorial on Functions. + +## ⭐️ Assignment + +1. Create a public state variable called `b` that is of type `bool` and initialize it to `true`. +2. Create a public function called `get_b` that returns the value of `b`. diff --git a/locales/fa/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md b/locales/fa/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md new file mode 100644 index 000000000..b846c7d99 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md @@ -0,0 +1,44 @@ +This section will look into the types of functions that don't modify the state of the blockchain: _view_ and _pure_ functions. + +### View Functions + +_View functions_ promise to not modify the state. + +"The following statements are considered modifying the state: + +1. Writing to state variables. +2. Emitting events. +3. Creating other contracts. +4. Using selfdestruct. +5. Sending Ether via calls. +6. Calling any function not marked view or pure. +7. Using low-level calls. +8. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a view function using the keyword `view`. In this contract, `addToX` (line 8) is a view function. This function takes the parameter `y` and returns the sum of the parameter and the state variable `x`. It reads `x` but does not modify it. + +### Pure functions + +_Pure functions_ promise to neither modify nor to read the state. + +"In addition to the list of state modifying statements explained above, the following are considered reading from the state: + +1. Reading from state variables. +2. Accessing `address(this).balance` or `
.balance`. +3. Accessing any of the members of block, tx, msg (with the exception of `msg.sig` and `msg.data`). +4. Calling any function not marked pure. +5. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a pure function using the keyword `pure`. In this contract, `add` (line 13) is a pure function. This function takes the parameters `i` and `j`, and returns the sum of them. It neither reads nor modifies the state variable `x`. + +In Solidity development, you need to optimise your code for saving computation cost (gas cost). Declaring functions view and pure can save gas cost and make the code more readable and easier to maintain. Pure functions don't have any side effects and will always return the same result if you pass the same arguments. + +Watch a video tutorial on View and Pure Functions. + +## ⭐️ Assignment + +Create a function called `addToX2` that takes the parameter `y` and updates the state variable `x` with the sum of the parameter and the state variable `x`. diff --git a/locales/fa/SolidityBeginnerCourse/introduction/introduction.md b/locales/fa/SolidityBeginnerCourse/introduction/introduction.md new file mode 100644 index 000000000..cc821a46a --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/introduction/introduction.md @@ -0,0 +1,32 @@ +Welcome to this interactive Solidity course for beginners. + +In this first section, we will give you a short preview of the concepts we will cover in this course, look at an example smart contract, and show you how you can interact with this contract in the Remix IDE. + +This contract is a counter contract that has the functionality to increase, decrease, and return the state of a counter variable. + +If we look at the top of the contract, we can see some information about the contract like the license (line 1), the Solidity version (line 2), as well as the keyword `contract` and it's name, `Counter` (line 4). We will cover these concepts in the next section about the **Basic Syntax**. + +With `uint public count` (line 5) we declare a state variable of the type `uint` with the visibility `public`. We will cover these concepts in our sections about **Variables**, **Primitive Data Types**, and **Visibility**. + +We then create a `get` function (line 8) that is defined with the `view` keyword and returns a `uint` type. Specifically, it returns the `count` variable. This contract has two more functions, an `inc` (line 13) and `dec` (line 18) function that increases or decreases our count variable. +We will talk about these concepts in our sections about **Functions - Reading and Writing to a State Variable** and **Functions - View and pure**. + +## Compile and Deploy through Remix + +**GIF** Interacting with the contract: Compile and deploy contract + +1. We can compile your `Counter` contract in the "Solidity compiler" module of the Remix IDE. + +2. In the "Deploy & run transactions" module, we select our contract "Counter" in the contract input field and click on the "Deploy" button. + +3. We expand the token contract functions in the IDE, and test its `get`, `inc`, and `dec` functions. + +## ⭐️ Assignment + +Throughout this course, we will give you assignments to test and consolidate your newly acquired knowledge. + +Your first assignment is to: + +1. Compile this contract. +2. Deploy it to the Remix VM. +3. Interact with your contract. diff --git a/locales/fa/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md b/locales/fa/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md new file mode 100644 index 000000000..9ea6b8626 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md @@ -0,0 +1,33 @@ +In this section, we will show you Solidity’s primitive data types, how to declare them, and their characteristics. + +### bool + +You can declare data a boolean type by using the keyword ‘bool’. Booleans can either have the value `true` or `false`. + +### uint + +We use the keywords `uint` and `uint8` to `uint256` to declare an _unsigned integer type_ (they don’t have a sign, unlike -12, for example). Uints are integers that are positive or zero and range from 8 bits to 256 bits. The type `uint` is the same as `uint256`. + +### int + +We use the keywords `int` and `int8` to `int256` to declare an integer type. Integers can be positive, negative, or zero and range from 8 bits to 256 bits. The type `int` is the same as `int256`. + +### address + +Variables of the type `address` hold a 20-byte value, which is the size of an Ethereum address. There is also a special kind of Ethereum address, `address payable`, which can receive ether from the contract. + +All these data types have default values, as shown in the contract (line 29). + +You can learn more about these data types as well as _Fixed Point Numbers_, _Byte Arrays_, _Strings_, and more in the Solidity documentation. + +Later in the course, we will look at data structures like **Mappings**, **Arrays**, **Enums**, and **Structs**. + +Watch a video tutorial on Primitive Data Types. + +## ⭐️ Assignment + +1. Create a new variable `newAddr` that is a `public` `address` and give it a value that is not the same as the available variable `addr`. +2. Create a `public` variable called `neg` that is a negative number, decide upon the type. +3. Create a new variable, `newU` that has the smallest `uint` size type and the smallest `uint` value and is `public`. + +Tip: Look at the other address in the contract or search the internet for an Ethereum address. diff --git a/locales/fa/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md b/locales/fa/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md new file mode 100644 index 000000000..57208c555 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md @@ -0,0 +1,26 @@ +_Ether_ (ETH) is a cryptocurrency. _Ether_ is also used to pay fees for using the Ethereum network, like making transactions in the form of sending _Ether_ to an address or interacting with an Ethereum application. + +### Ether Units + +To specify a unit of _Ether_, we can add the suffixes `wei`, `gwei`, or `ether` to a literal number. + +#### `wei` + +_Wei_ is the smallest subunit of _Ether_, named after the cryptographer [Wei Dai](https://en.wikipedia.org/wiki/Wei_Dai). _Ether_ numbers without a suffix are treated as `wei` (line 7). + +#### `gwei` + +One `gwei` (giga-wei) is equal to 1,000,000,000 (10^9) `wei`. + +#### `ether` + +One `ether` is equal to 1,000,000,000,000,000,000 (10^18) `wei` (line 11). + +Watch a video tutorial on Ether and Wei. + +## ⭐️ Assignment + +1. Create a `public` `uint` called `oneGWei` and set it to 1 `gwei`. +2. Create a `public` `bool` called `isOneGWei` and set it to the result of a comparison operation between 1 gwei and 10^9. + +Tip: Look at how this is written for `gwei` and `ether` in the contract. diff --git a/locales/fa/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md b/locales/fa/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md new file mode 100644 index 000000000..bbc25575c --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md @@ -0,0 +1,29 @@ +As we have seen in the previous section, executing code via transactions on the Ethereum Network costs transaction fees in the form of Ether. The amount of fees that have to be paid to execute a transaction depends on the amount of _gas_ that the execution of the transaction costs. + +### Gas + +_Gas_ is the unit that measures the amount of computational effort that is required to execute a specific operation on the Ethereum network. + +### Gas price + +The _gas_ that fuels Ethereum is sometimes compared to the gas that fuels a car. The amount of gas your car consumes is mostly the same, but the price you pay for gas depends on the market. + +Similarly, the amount of _gas_ that a transaction requires is always the same for the same computational work that is associated with it. However the price that the sender of the transaction is willing to pay for the _gas_ is up to them. Transactions with higher _gas prices_ are going through faster; transactions with very low _gas prices_ might not go through at all. + +When sending a transaction, the sender has to pay the _gas_ fee (gas_price \* gas) upon execution of the transaction. If _gas_ is left over after the execution is completed, the sender gets refunded. + +_Gas_ prices are denoted in gwei. + +### Gas limit + +When sending a transaction, the sender specifies the maximum amount of gas that they are willing to pay for. If they set the limit too low, their transaction can run out of _gas_ before being completed, reverting any changes being made. In this case, the _gas_ was consumed and can’t be refunded. + +Learn more about _gas_ on ethereum.org. + +Watch a video tutorial on Gas and Gas Price. + +## ⭐️ Assignment + +Create a new `public` state variable in the `Gas` contract called `cost` of the type `uint`. Store the value of the gas cost for deploying the contract in the new variable, including the cost for the value you are storing. + +Tip: You can check in the Remix terminal the details of a transaction, including the gas cost. You can also use the Remix plugin _Gas Profiler_ to check for the gas cost of transactions. diff --git a/locales/fa/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md b/locales/fa/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md new file mode 100644 index 000000000..58fb4c5a6 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md @@ -0,0 +1,86 @@ +In this section, we will learn how a contract can send and receive Ether. + +### Sending Ether + +We have three different options to transfer Ether: `transfer()`, `send()` and `call()`. + +#### **transfer** + +`
.transfer(uint256 amount)` + +- `transfer()` throws an exception on failure +- Forwards a fixed 2300 gas stipend + +An example of `transfer()` can be seen in the `SendEther` contract (line 35). +**`Transfer()` is not recommended to be used anymore.** + +#### **send** + +`
.send(uint256 amount) returns (bool)` + +- `send()` returns false on failure +- Forwards a fixed 2300 gas stipend + +An example of `send()` can be seen in the `SendEther` contract (line 41). +**`Send()` is not recommended to be used anymore.** + +#### **call** + +`
.call(bytes memory) returns (bool, bytes memory)` + +- `call()` returns false on failure +- Forwards the maximum amount of gas, but this is adjustable + +An example of `call()` can be seen in the `SendEther` contract (line 48). +`Call()` is currently recommended if you are transfering Ether. + +The reason `transfer()` and `send()` were introduced was to guard against _reentry attacks_ by limiting the forwarded gas to 2300, which would be insufficient to make a reentrant call that can modify storage. + +As we discussed in the last section, each operation on Ethereum has a specific cost associated with it. Certain operations have become more cost intensive over time, so the gas costs associated with them are also raised. When gas costs for operations are subject to change it is not good to use a hardcoded gas amount like transfer(), and send() do. + +That’s why `call()` instead of `transfer()` is now recommended to send Ether. + +Learn more about the subject in this Consensys blog post. + +### Reentrancy attack + +A _reentrancy attack_ occurs when a function makes an external call to an untrusted contract and the attacker uses the contract to make recursive calls back to the original function before it finishes its execution. Through this method, the attacker can drain funds and manipulate data in unintended ways. + +To guard against a _reentrancy attack_, all state changes should be made before calling an external contract. This is also called the Checks-Effects-Interactions pattern. + +Another way to prevent reentrancy is to use a _Reentrancy Guard_ that checks for such calls and rejects them. You can see an example of this in the contract in our modifier section or a more gas-efficient version on Open Zepplin. + +### Receiving Ether + +If we want to enable a contract to receive Ether without a function being called, we need to create a `receive` function (line 22) or a `fallback` function (line 25); otherwise, the Ether will be rejected, and the contract will throw an exception. + +The `receive` function is executed on calls with empty calldata (e.g. plain Ether transfers via send() or transfer()), while the fallback function is executed on calls with calldata. If no receive function exists but a fallback function does, calls with empty calldata will also use the fallback function. + +### Payable function modifier + +The `payable` function modifier allows a function to receive Ether. + +The `receive` function (line 22) needs to be `payable`. If you delete the `payable` modifier you will get an error from the compiler. If you delete the `payable` modifier from the `fallback` function (line 25) it will compile, but it won’t be able to receive Ether. +The functions `sendViaTransfer`, `sendViaSend`, and `sendViaCall` (lines 33, 38, and 45) also need to be `payable` in order to receive Ether. + +### Payable address + +Solidity makes a distinction between two different flavors of the address data type: address and address payable. + +`address`: Holds a 20-byte value. +`address payable`: Holds a 20-byte value and can receive Ether via its members: transfer and send. + +If you change the parameter type for the functions `sendViaTransfer` and `sendViaSend` (line 33 and 38) from `payable address` to `address`, you won’t be able to use `transfer()` (line 35) or `send()` (line 41). + +Watch a video tutorial on Sending Ether. + +## ⭐️ Assignment + +Build a charity contract that receives Ether that can be withdrawn by a beneficiary. + +1. Create a contract called `Charity`. +2. Add a public state variable called `owner` of the type address. +3. Create a donate function that is public and payable without any parameters or function code. +4. Create a withdraw function that is public and sends the total balance of the contract to the `owner` address. + +Tip: Test your contract by deploying it from one account and then sending Ether to it from another account. Then execute the withdraw function. diff --git a/locales/fa/SolidityBeginnerCourse/variables/variables.md b/locales/fa/SolidityBeginnerCourse/variables/variables.md new file mode 100644 index 000000000..dfb35b382 --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/variables/variables.md @@ -0,0 +1,29 @@ +There are three different types of variables in Solidity: _State Variables_, _Local Variables_, and _Global Variables_. + +## 1. State Variables + +_State Variables_ are stored in the contract _storage_ and thereby on the blockchain. They are declared inside the contract but outside the function. +This contract has two state variables, the string `text`(line 6) and the uint `num` (line 7). + +## 2. Local Variables + +_Local Variables_ are stored in the _memory_ and their values are only accessible within the function they are defined in. Local Variables are not stored on the blockchain. +In this contract, the uint `i` (line 11) is a local variable. + +## 3. Global Variables + +_Global Variables_, also called _Special Variables_, exist in the global namespace. They don't need to be declared but can be accessed from within your contract. +Global Variables are used to retrieve information about the blockchain, particular addresses, contracts, and transactions. + +In this example, we use `block.timestamp` (line 14) to get a Unix timestamp of when the current block was generated and `msg.sender` (line 15) to get the caller of the contract function’s address. + +A list of all Global Variables is available in the Solidity documentation. + +Watch video tutorials on State Variables, Local Variables, and Global Variables. + +## ⭐️ Assignment + +1. Create a new public state variable called `blockNumber`. +2. Inside the function `doSomething()`, assign the value of the current block number to the state variable `blockNumber`. + +Tip: Look into the global variables section of the Solidity documentation to find out how to read the current block number. diff --git a/locales/fa/SolidityBeginnerCourse/visibility/visibility.md b/locales/fa/SolidityBeginnerCourse/visibility/visibility.md new file mode 100644 index 000000000..79e4307bf --- /dev/null +++ b/locales/fa/SolidityBeginnerCourse/visibility/visibility.md @@ -0,0 +1,37 @@ +The `visibility` specifier is used to control who has access to functions and state variables. + +There are four types of visibilities: `external`, `public`, `internal`, and `private`. + +They regulate if functions and state variables can be called from inside the contract, from contracts that derive from the contract (child contracts), or from other contracts and transactions. + +### private + +- Can be called from inside the contract + +### internal + +- Can be called from inside the contract +- Can be called from a child contract + +### public + +- Can be called from inside the contract +- Can be called from a child contract +- Can be called from other contracts or transactions + +### external + +- Can be called from other contracts or transactions +- State variables can not be `external` + +In this example, we have two contracts, the `Base` contract (line 4) and the `Child` contract (line 55) which inherits the functions and state variables from the `Base` contract. + +When you uncomment the `testPrivateFunc` (lines 58-60) you get an error because the child contract doesn’t have access to the private function `privateFunc` from the `Base` contract. + +If you compile and deploy the two contracts, you will not be able to call the functions `privateFunc` and `internalFunc` directly. You will only be able to call them via `testPrivateFunc` and `testInternalFunc`. + +Watch a video tutorial on Visibility. + +## ⭐️ Assignment + +Create a new function in the `Child` contract called `testInternalVar` that returns the values of all state variables from the `Base` contract that are possible to return. diff --git a/locales/fa/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md b/locales/fa/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md new file mode 100644 index 000000000..801d8c582 --- /dev/null +++ b/locales/fa/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md @@ -0,0 +1,47 @@ +In this tutorial, we'll explore the Uniswap V3 Swap contract to learn about how single-hop and multi-hop swaps work. + +But first, some Uniswap fundamentals. + +## What is Uniswap? + +Uniswap is a decentralized cryptocurrency exchange. It allows users to exchange tokens without the need for a centralized intermediary. Uniswap is a key player in the decentralized finance (DeFi) space. + +## How does Uniswap work? + +Instead of using an order book like a traditional centralized exchange, Uniswap uses an automated market maker (AMM) model. In Uniswap, the AMM is a smart contract that holds reserves of tokens (Liquidity Pool). Users can trade between tokens in the Liquidity Pool. The price of each token is determined by the ratio of the reserves. + +### Step-by-step example of a Uniswap trade + +1. Alice wants to trade 1 ETH for DAI. +2. Alice sends 1 ETH to the Uniswap smart contract. +3. The Uniswap smart contract calculates the amount of DAI that Alice should receive based on the current exchange rate. +4. The Uniswap smart contract sends the DAI to Alice. +5. The Uniswap smart contract adds the 1 ETH to its reserves. +6. The Uniswap smart contract recalculates the exchange rate based on the new reserves. + +The tokens in the Liquidity Pool are provided by Liquidity Providers. When a Liquidity Provider deposits tokens into a Liquidity Pool, they receive Liquidity Provider Tokens in return. Liquidity Provider Tokens represent a user's share of a Liquidity Pool. + +Users of Uniswap pay a fee for each trade. The fee is paid to the Liquidity Providers in the form of additional Liquidity Provider Tokens. + +## Uniswap Swap Contract + +The Uniswap Swap contract allows users to swap tokens using Uniswap V3. It can do single-hop swaps, which allow users to exchange one token for another directly. It can also do multi-hop swaps, which means that users can exchange one token for another by routing through multiple tokens. Routing in this context means that the swap contract will exchange the token for another token, then exchange that token for another token, and so on until it reaches the desired token. + +## Conclusion + +In this section, we learned about Uniswap, how it works, and how we are going to use it to swap tokens. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is Uniswap? + +1. A centralized exchange protocol. +2. A decentralized exchange protocol that uses an order book. +3. A decentralized exchange protocol that uses an automated market maker (AMM) model. +4. A decentralized exchange protocol that uses an order book and an automated market maker (AMM) model. + +### 2) How does Uniswap determine the price of a token? + +1. The price of a token is determined by the ratio of the reserves. +2. The price of a token is determined by the ratio of the reserves and the number of trades. +3. The price of a token is determined by the ratio of the reserves and the number of Liquidity Providers. diff --git a/locales/fa/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md b/locales/fa/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md new file mode 100644 index 000000000..e5cc248f5 --- /dev/null +++ b/locales/fa/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md @@ -0,0 +1,41 @@ +The entire UniswapSwapExamples contract will only be presented in section 5 of this tutorial. Before then, we'll build up blocks of code. + +This section explores the `ISwapRouter` interface, which defines the functions that can be called on the Uniswap Swap contract. + +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. +Multi-hop swaps allow users to exchange one token for another by routing through multiple tokens. + +Interfaces in Solidity specify functions that must be included in a contract that inherits them. They are useful for declaring what functions be supported and allow for easier integration and interaction between different contracts. + +Structs are used to define custom data types. + +## ISwapRouter Interface + +The ISwapRouter interface defines the functions that can be called on the Uniswap Swap contract. We will need to use this interface to interact with the Uniswap Swap contract and execute swaps. + +On line 5, we define a constant variable called `router` that is of type `ISwapRouter`. We set the value of this variable to the interface instance of a smart contract that is deployed at the address `0xE592427A0AEce92De3Edee1F18E0157C05861564`. This is the address of the Uniswap V3 Swap contract on the Ethereum mainnet. + +On line 9, we define an interface called `ISwapRouter`. This interface defines two functions: `exactInputSingle` and `exactInput`. + +## exactInputSingle + +On line 25, we define a struct called `ExactInputSingleParams`. This struct defines the parameters that are required for our exactInputSingle function on line 21, which will execute a single-hop swap. The struct has the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 fee`**: The fee associated with the swap. +- **`address recipient`**: The address that will receive the output token. +- **`uint deadline`**: A timestamp by which the transaction must be processed, for time-limiting the swap. +- **`uint amountIn`**: The amount of the input token being sent. +- **`uint amountOutMinimum`**: The minimum amount of the output token that the sender is willing to accept, to protect against unfavorable price movements. +- **`uint160 sqrtPriceLimitX96`**: A limit on the price, represented in a specific format, to prevent the swap from occurring at unfavorable prices. + +## exactInput + +On line 25, we define a struct called `ExactInputParams`. This struct defines the parameters that are required for our `exactInput` function on line 33. This function will execute a multi-hop swap. The struct has the following parameters: + +- **`bytes path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address recipient`**: The address receiving the output tokens. +- **`uint deadline`**: Similar to above, a timestamp by which the transaction must be processed. +- **`uint amountIn`**: The amount of the input token. +- **`uint amountOutMinimum`**: The minimum amount of the output token the sender expects to receive. diff --git a/locales/fa/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md b/locales/fa/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md new file mode 100644 index 000000000..f4d70c445 --- /dev/null +++ b/locales/fa/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md @@ -0,0 +1,36 @@ +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. In this section, we will learn how to use the Uniswap V3 Swap contract to execute single-hop swaps. + +## Function Parameters + +On line 8, we define a function called `swapExactInputSingleHop`. This function executes a single-hop swap. It takes the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 poolFee`**: The fee associated with the swap. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +## Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 14. +Then, we approve the Uniswap Swap contract to spend the input token on our behalf, line 15. + +On line 17, we create an instance of the `ExactInputSingleParams` struct. This struct contains the parameters that are required for our `exactInputSingle` function on line 45, which will execute the single-hop swap. We repeat `ISwapRouter.ExactInputSingleParams` two times on that line because we are making an instance of a struct that is defined in an interface. + +## Parameters of the ExactInputSingleParams Struct + +We set the parameters of the struct as follows: + +- **`tokenIn`**: We set this to the `tokenIn` parameter of our function. +- **`tokenOut`**: We set this to the `tokenOut` parameter of our function. +- **`fee`**: We set this to the `poolFee` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. +- **`sqrtPriceLimitX96`**: We set this to 0 because we do not want to specify a limit on the price. + +## Executing the Single-hop Swap + +On line 29, we assign the output of the `exactInputSingle` function to the `amountOut` variable. This function executes the single-hop swap and returns the amount of the output token that was received. diff --git a/locales/fa/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md b/locales/fa/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md new file mode 100644 index 000000000..7883b4718 --- /dev/null +++ b/locales/fa/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md @@ -0,0 +1,30 @@ +In this section, we'll delve into the `swapExactInputMultiHop` function in the `UniswapV3SwapExamples` contract. This function enables more complex token swaps by allowing users to specify a custom path through multiple liquidity pools. + +If for example, a user wants to swap token A for token D, but there is no direct liquidity pool for A and D, the user can specify a path through multiple tokens. For example, the user can swap A for B, then B for C, and finally C for D. This is of course automatically done by the Uniswap V3 Swap contract. + +### Parameters and Return Value + +On line 32, we define a function called `swapExactInputMultiHop`. This function executes a multi-hop swap. It takes the following parameters: + +- **`bytes calldata path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address tokenIn`**: The address of the token being sent. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +### Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 38. +Then, we approve the Uniswap Swap router to spend the input token on our behalf, line 41. + +On line 43, we create an instance of the `ExactInputParams` struct, line 73. This struct contains the parameters that are required for our `exactInput` function on line 81, which will execute the multi-hop swap. + +We set the parameters of the struct as follows: + +- **`path`**: We set this to the `path` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. + +On line 53, we execute the multi-hop swap by calling the `exactInput` function. This function returns the amount of the output token that was received. diff --git a/locales/fa/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md b/locales/fa/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md new file mode 100644 index 000000000..b3cec34e9 --- /dev/null +++ b/locales/fa/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md @@ -0,0 +1,52 @@ +In this section, we'll explore the `IERC20` interface, a standard interface for interacting with ERC-20 tokens and the `IWETH` interface, a standard interface for interacting with wrapped Ether (WETH). Understanding these interfaces is crucial as it is used in the Uniswap V3 Swap contract to handle token transfers and approvals. + +You can find a "Solidity ERC20 Token Course" for beginners in LearnEth to understand the ERC20 token standard in more detail. + +## IERC20 Interface + +On line 80, we define the `IERC20` interface. This interface defines a standard set of functions that ERC-20 tokens must implement. Let's examine the key functions within this interface: + +### 1. totalSupply + +On line 81, we define the `totalSupply` function. This function returns the total supply of the token. + +### 2. balanceOf + +On line 83, we define the `balanceOf` function. This function returns the balance of the specified address. + +### 3. transfer + +On line 85, we define the `transfer` function. This function transfers tokens from the sender to the specified recipient. + +### 4. allowance + +On line 87, we define the `allowance` function. This function returns the amount of tokens that the spender is allowed to spend on behalf of the owner. + +### 5. approve + +On line 89, we define the `approve` function. When called, this function approves a spender to spend the specified amount of tokens on behalf of the sender. + +### 6. transferFrom + +On line 91, we define the `transferFrom` function. This function transfers tokens from the specified sender to the recipient. The function can only be called by the spender if the spender is allowed to spend the specified amount of tokens on behalf of the sender. + +### 7. Events + +On lines 102-103, we define the `Transfer` and `Approval` events. These events are emitted when the `transfer` and `approve` functions are called, respectively. + +## IWETH Interface + +On line 106, we define the `IWETH` interface. This interface extends the `IERC20` interface and defines two additional functions: + +### 1. deposit + +On line 107, we define the `deposit` function. This function deposits ETH into the contract and returns the equivalent amount of WETH. This function is used to wrap ETH into WETH. +We need to wrap ETH into WETH because the Uniswap V3 Swap contract only supports ERC-20 tokens. + +### 2. withdraw + +On line 109, we define the `withdraw` function. This function withdraws the specified amount of WETH from the contract and returns the equivalent amount of ETH. This function is used to unwrap WETH into ETH. + +## Conclusion + +In this tutorial, we explored the Uniswap V3 Swap contract. To get a full sense of how Uniswap works, try making some swaps on the Uniswap DApp and go to the Uniswap docs. diff --git a/locales/fa/Uniswap-Tutorial/README.md b/locales/fa/Uniswap-Tutorial/README.md new file mode 100644 index 000000000..cf66c5582 --- /dev/null +++ b/locales/fa/Uniswap-Tutorial/README.md @@ -0,0 +1,5 @@ +# Uniswap Swap Course + +Review the code of the Uniswap V3 Swap contract for performing token swaps. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/fa/Uniswap-Tutorial/config.yml b/locales/fa/Uniswap-Tutorial/config.yml new file mode 100644 index 000000000..f49f02abc --- /dev/null +++ b/locales/fa/Uniswap-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: uniswapSwapCourse +name: Uniswap Swap Course +summary: Go through the Solidity code of the Uniswap V3 Swap contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - Uniswap +steps: + - + name: 1. Introduction + path: 1-introduction-to-uniswap + - + name: 2. Routers, Interfaces, and Structs + path: 2-router-interfaces-and-structs + - + name: 3. Single Hop Swaps + path: 3-single-hop-swaps + - + name: 4. Multi-Hop Swaps + path: 4-multi-hop-swaps + - + name: 5. Erc20 and Weth Interfaces + path: 5-erc20-weth-interfaces diff --git a/locales/fa/Web3Client/1_Using_Web3/Running_a_script.md b/locales/fa/Web3Client/1_Using_Web3/Running_a_script.md new file mode 100644 index 000000000..3b7b23332 --- /dev/null +++ b/locales/fa/Web3Client/1_Using_Web3/Running_a_script.md @@ -0,0 +1,24 @@ +## Querying the Blockchain + +In this tutorial, we'll run a script that queries the blockchain using a JavaScript library. + +This means that instead of using the Remix GUI or a block explorer like Etherscan, we'll use a script in the editor and will run it from the terminal. + +The JS libraries that are used the most for interacting with the blockchain are web3.js & ethers.js. + +Let's begin with a simple web3.js example, queryBlockNum.js. + +The script's call to web3.js is wrapped in a self-executing async function that contains a try/catch block. + +We'll query the current blocknumber with: +`let blockNumber = await web3.eth.getBlockNumber()` + +Note that the object `web3` is injected by Remix. For more info on web3.js, check their docs, https://web3js.readthedocs.io. + +To use web3.js or ethers.js, you need to select the **Injected Web3** or **Web3 Provider** environment in the **Deploy & Run** module. Scripts don't currently work with the JSVM. **If you try, you'll get an error.** + +So for this example choose **Injected Web3** in the Deploy & Run module and have Metamask installed. + +From the terminal, execute `remix.execute()`. This command will execute the current JavaScript file with the line `let blockNumber = await web3.eth.getBlockNumber()`. + +In the console, you should see the current block number of the chain that metamask is connected to. diff --git a/locales/fa/Web3Client/2_Querying_a_Contract/queryContract.md b/locales/fa/Web3Client/2_Querying_a_Contract/queryContract.md new file mode 100644 index 000000000..461c98244 --- /dev/null +++ b/locales/fa/Web3Client/2_Querying_a_Contract/queryContract.md @@ -0,0 +1,23 @@ +Now that we know how to query simple data, let's try a more complex query. + +This is a contract deployed to the mainnet - at this address: https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code + +We are going to query the contract to find the name of it's token. + +The **name** variable is a state variable of the contract. + +To access this **mainnet** contract, we need to do some setup. + +1. Switch to the mainnet in metamask. +2. You'll probably need to refresh Remix. +3. As a result of the refresh, you may need to reload this tutorial too. +4. Go to Deploy & Run and switch to **Injected Web3**. + +**Using Web3** +In the script, queryContract.js, we need to instantiate a new instance of web3.eth.Contract object. For this we need to grab the contract's ABI and its address. The source code & ABI is available in etherscan because the contract's developer intentionally published it. + +In etherscan, we can see that its name is **TetherToken**. Scrolling down to the TetherToken contract in the source code section of etherscan, we can see the state variables for the contract - the first of which is named **name**. + +There are a few syntactic hoops to jump through to return the value of the state variable. + +- To call the autogenerated getter function of the public state variable, you need to both treat the variable as a function (by adding parentheses) and also to tack on a call(). diff --git a/locales/fa/Web3Client/README.md b/locales/fa/Web3Client/README.md new file mode 100644 index 000000000..a319f312f --- /dev/null +++ b/locales/fa/Web3Client/README.md @@ -0,0 +1 @@ +This workshop is about using the web3.js to interact with a contract and more generally to the blockchain. diff --git a/locales/fa/Web3Client/config.yml b/locales/fa/Web3Client/config.yml new file mode 100644 index 000000000..07cb1760c --- /dev/null +++ b/locales/fa/Web3Client/config.yml @@ -0,0 +1,9 @@ +--- +id: useofweb3js +name: Basic use of web3.js +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 2 +tags: + - JS + - Remix + - Web3 diff --git a/locales/fr/Basics/README.md b/locales/fr/Basics/README.md new file mode 100644 index 000000000..6b065b830 --- /dev/null +++ b/locales/fr/Basics/README.md @@ -0,0 +1,3 @@ +## Loading, Compiling, Deploying + +This beginner level tutorial introduces Remix's interface and concepts used in Ethereum. diff --git a/locales/fr/Basics/config.yml b/locales/fr/Basics/config.yml new file mode 100644 index 000000000..8c160b545 --- /dev/null +++ b/locales/fr/Basics/config.yml @@ -0,0 +1,26 @@ +--- +id: basics +name: Basics of Remix +summary: A typical workflow in Remix +level: 1 +tags: + - Remix +steps: + - + name: Intro to the Interface + path: interface_introduction + - + name: Intro to Workspaces + path: workspaces + - + name: Loading & Compiling + path: load_and_compile + - + name: Deploying to the Remix VM + path: deploy_to_the_remixvm + - + name: Interacting with Functions + path: interacting + - + name: Deploying to Public Networks + path: deploy_injected diff --git a/locales/fr/Basics/deploy_injected/README.md b/locales/fr/Basics/deploy_injected/README.md new file mode 100644 index 000000000..25ed6930e --- /dev/null +++ b/locales/fr/Basics/deploy_injected/README.md @@ -0,0 +1,21 @@ +1. If you don't have a browser wallet like **MetaMask** download and install one now. + +2. Cliquez sur l'icône MetaMask dans votre navigateur. Sign in and choose the Ephemery test network. You might need to update your wallet's settings so that you can see **test networks**. Alternatively, you can go to Remix's Deploy & Run transation module and in the ENVIRONMENT section select Ephemery. + +3. Getting test ETH for public test networks is often annoying. Ephemery is a public network that is refreshed monthly, so getting test ETH should be painless. Here is a link to some Ephemery faucets. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/testnet.png) + +Sepolia is another popular testnet that is not refreshed, so deployments will persist, but Sepolia faucets are more difficult to use. + +In your browser wallet make sure that you have NOT selected mainnet or any network that will cost real ETH. In the Deploy & Run module, below the Environment select box, you'll see a badge with the network's ID and for popular chains, its name. In the case below its Sepolia. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/sepolia.png) + +5. Make sure you see the 2_Owner.sol as a choice in the **CONTRACT** select box, then click the **Deploy** button. + +If the **CONTRACT** select box is empty, you'll need to compile 2_Owner again by making 2_Owner.sol the active file in the **editor** and then go to the **Solidity Compiler** to compile it. + +6. After you hit the `Deploy` button, you'll see the browser wallet popup asking you to pay for the transactions. If you have the appropriate kind of ETH for this chain, approve this transaction. Check the printout in the terminal. Once the block is validated, the **deployed instance** will appear at the bottom of Deploy & Run + +And with that you have finished this tutorial. You now have experience with opening, compiling, deploying and interacting with Smart Contracts in Remix IDE. diff --git a/locales/fr/Basics/deploy_to_the_remixvm/README.md b/locales/fr/Basics/deploy_to_the_remixvm/README.md new file mode 100644 index 000000000..8035d631b --- /dev/null +++ b/locales/fr/Basics/deploy_to_the_remixvm/README.md @@ -0,0 +1,15 @@ +In the previous chapter, we compiled a contract - which is to say the Solidity code has been transformed into little chunks of Ethereum Virtual Machine (EVM) bytecode. + +Now we will put that code on a test blockchain. + +1. Click the Deploy and Run icon ![deploy & run icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_to_the_remixvm/images/run.png "deploy & run icon"). + +2. Select one of the **Remix VM**s from the **Environment** pulldown. + +3. Click the Deploy button (or the transact button in the expanded view). + +4. You have deployed your compiled contract to the Remix VM - a simulated blockchain that is running inside of your browser window. The Remix VM is simple, fast test chain. It is not that realistic because you don't need to approve each transaction. + +5. Check the terminal to see detail of this deployment transaction. + +You can also use Remix to deploy to other public EVM chains. To do this, you'll need to connect to a different **Environment** - like Injected Provider. The Injected Provider connects Remix to browser wallet (like MetaMask or similar). We'll try deploying to a public network at the end of this tutorial. But before we get there, we'll cover how to interact with a deployed contract's functions. diff --git a/locales/fr/Basics/interacting/README.md b/locales/fr/Basics/interacting/README.md new file mode 100644 index 000000000..59ef44200 --- /dev/null +++ b/locales/fr/Basics/interacting/README.md @@ -0,0 +1,19 @@ +## Accessing functions in a deployed contract + +1. When a contract has been successfully deployed, it will appear at the bottom of the Deploy and Run plugin. Open up the contract by clicking the caret - so the caret points down. + ![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/instance.png "deployed contract") + +2. There are 2 functions in this contract. To input the parameters individually, clicking the caret to the right of changeOwner (outlined in red below). In the expanded view, each parameter has its own input box. + +![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/deployed_open2.png "deployed contract") + +If this contract had imported other contracts, then the functions of the imported contracts would also be visible here. At some point, try playing with An ERC20 contract to see all its many functions. + +3. Functions with blue buttons are either **pure** or **view** functions. This means that they are just reading a property or are returning a value. In other words, they aren't saving anything - so they are FREE (they don’t cost gas). Functions with other colors - usually orange (depending on the Remix theme) cost gas because they are saving information. They are creating a **transaction**. + +4. 2_Owner.sol does not have a **payable** function. If it did, the button's color would be red. Payable functions allow you to send Ether to the function. To send ETH with a payable function, you put the amount you want to send in the **value** field towards the top of the Deploy & Run module. + +5. In the Remix VM, you don't need to approve a transaction. When using a more realistic test environment or when using the mainnet - you will need to approve the transactions for them to go through. Approving a transaction costs gas. + +6. Choosing a public network is not done in Remix but in your Browser Wallet. There is a plug icon to the right of the Environment title that links to chainlist.org where you can get the specs of the chain you want to interact with. + ![chainlist](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/chainlist.png "chainlist") diff --git a/locales/fr/Basics/interface_introduction/README.md b/locales/fr/Basics/interface_introduction/README.md new file mode 100644 index 000000000..76c953fbd --- /dev/null +++ b/locales/fr/Basics/interface_introduction/README.md @@ -0,0 +1,15 @@ +## Remix is composed of four panels. + +![Remix layout](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/a-layout1c.png "Remix layout") + +- Most plugins appear in the **Side Panel**. +- Editing code happens in tabs in the **Main Panel**. +- The results of transactions and other actions are visible in the **Terminal**. +- Switching between plugins happens in the **Icons Panel**. +- To make a panel larger, drag its border. + +Try clicking the **Solidity Compiler** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/solidity-icon.png) in the **Icons Panel**. Then click the **Deploy & Run** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/deploy-run.png). Then come back to **LearnEth** by clicking this icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/learneth.png). + +In the **Main Panel** of Remix, make sure you see the **Home** tab. The **Home** tab has lots of useful links. To navigate there, either click the **Home** tab in the **Main Panel** or click the Remix icon ![Remix icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/remix-logo.png "Remix icon") on the top of the icon panel. + +- See all the plugins in the **Plugin Manager**. Click this icon ![plugin manager](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/plugin1.png "Plugin Manager icon") in the lower left corner Remix. diff --git a/locales/fr/Basics/load_and_compile/README.md b/locales/fr/Basics/load_and_compile/README.md new file mode 100644 index 000000000..a666d5d13 --- /dev/null +++ b/locales/fr/Basics/load_and_compile/README.md @@ -0,0 +1,20 @@ +Let's load a file from the File Explorer into the Editor. + +1. In the icon panel, click ![file explorer icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/files1.png "file explorer icon") , the File Explorer's icon. + +2. Make sure you are in the **default_workspace**. + +![default workspace](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/default_workspace_open.png) + +3. Open the contracts folder and click on **2_Owner.sol** in the contracts folder. Click it. The file will appear in a tab in the main panel. + +4. In the icon panel, click the **Solidity Compiler** ![solidity compiler icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/solidity1.png "solidity compiler icon"). The Solidity compiler should now be in the side panel. + +5. Click the compile button. + ![compile 2\_owner](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/compile2owner.png "compile 2_Owner") + +6. Compiling can also be triggered by hitting **CTRL + S**. + +The spinner will turn while the file is compiling. + +**Note:** The spinner also turns when the compiler itself is loading. To choose a **different version of Solidity**, go to the select box at the top of the plugin. diff --git a/locales/fr/Basics/workspaces/README.md b/locales/fr/Basics/workspaces/README.md new file mode 100644 index 000000000..97a47d283 --- /dev/null +++ b/locales/fr/Basics/workspaces/README.md @@ -0,0 +1,23 @@ +## Workspaces help organize your separate projects. + +If this is your first time to Remix, a Workspace named **default_workspace** is loaded in the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/default_workspace.png) + +The **default_workspace** has three Solidity (.sol) files in the contracts folder. Remix has a number of other templates. When you load a template, it goes into a Workspace. To go between Workspaces, use the select box at the top of the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/select-box.png) + +But Workspaces are not only for templates. When cloning a repo into Remix, the files will be put into a Workspace. + +Let's create a new Workspace + +1. At the top of the File Explorer, click the hamburger icon (the 3 horizontal lines). Read through the commands and tools in this menu. + +2. Select **+ Create** (the first choice). + +3. In the modal the comes up, choose one of the templates. + +![hamburger](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/workspaces/images/popup.png) + +Notice that in this popup menu, you can clone a repo. Managing a Git repo happens in the DGit plugin. You can also create Github actions with the three workflow choices in the popup menu. diff --git a/locales/fr/CircomHashChecker/README.md b/locales/fr/CircomHashChecker/README.md new file mode 100644 index 000000000..20391a668 --- /dev/null +++ b/locales/fr/CircomHashChecker/README.md @@ -0,0 +1,14 @@ +Hash Checker Tutorial + +This tutorial guides you through creating and understanding a Hash Checker circuit using Remix-IDE. You'll learn how to generate the circuit using a template, explore the code, perform a trusted setup, generate proofs, and verify them. This tutorial is suitable for beginners familiar with Circom and Zero-Knowledge Proofs. + +Prerequisites + +``` +Basic understanding of Zero-Knowledge Proofs and Circom. +Familiarity with Remix-IDE. +``` + +Estimated Time + +Approximately 1-2 hours. diff --git a/locales/fr/CircomHashChecker/config.yml b/locales/fr/CircomHashChecker/config.yml new file mode 100644 index 000000000..2c2aae80a --- /dev/null +++ b/locales/fr/CircomHashChecker/config.yml @@ -0,0 +1,35 @@ +id: circom-hash-checker +name: Hash Checker Tutorial +summary: A tutorial on creating and understanding a Hash Checker circuit using Remix-IDE templates, including trusted setup and proof generation. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction to the Hash Checker Circuit + path: step-1 + - + name: Generating the Hash Checker Template in Remix-IDE + path: step-2 + - + name: Exploring calculate_hash.circom + path: step-3 + - + name: Compiling the Circuit + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Compute Witness + path: step-6 + - + name: Generate Proof + path: step-7 + - + name: Exploring the Trusted Setup Script (Optional) + path: step-8 + - + name: Exploring the Proof Generation Script (Optional) + path: step-9 diff --git a/locales/fr/CircomHashChecker/step-1/README.md b/locales/fr/CircomHashChecker/step-1/README.md new file mode 100644 index 000000000..be922e93b --- /dev/null +++ b/locales/fr/CircomHashChecker/step-1/README.md @@ -0,0 +1,8 @@ +In this tutorial, we'll explore the **Hash Checker** circuit, a zero-knowledge proof (ZKP) application using Circom and Remix-IDE. The Hash Checker circuit allows you to prove knowledge of certain inputs that hash to a given value without revealing the inputs themselves. + +### What You'll Learn + +- How to generate a Hash Checker circuit using Remix-IDE's workspace templates. +- Understanding the Circom code for hashing and checking hashes. +- Performing a trusted setup using Groth16. +- Generating zero-knowledge proofs. diff --git a/locales/fr/CircomHashChecker/step-2/README.md b/locales/fr/CircomHashChecker/step-2/README.md new file mode 100644 index 000000000..bc827019e --- /dev/null +++ b/locales/fr/CircomHashChecker/step-2/README.md @@ -0,0 +1,37 @@ +Follow these steps to create the Hash Checker workspace in Remix-IDE. + +### Step 1: Access the Workspace Templates + +1. In the **File Explorer** sidebar, click on the **hamburger menu icon** (three horizontal lines). + + hamburger-menu + +2. Select **"Create Using Template"** from the dropdown. + + create-using-template + +### Step 2: Find the Hash Checker Template + +1. In the main panel, scroll down to the **"Circom ZKP"** section. + + create-zkp-section + +2. Locate the **"Hash Checker"** item. + +### Step 3: Create the Workspace + +1. Click on the **"Create"** button on the Hash Checker item. + + create-hash-checker + +2. In the modal pop-up, provide a **workspace name** (e.g., `hash-checker-workspace`). + + workspace-name-modal + +3. Click **"OK"** to create the template. + +### Result + +- The workspace is created with the necessary files and directories. + + workspace-name-modal diff --git a/locales/fr/CircomHashChecker/step-3/README.md b/locales/fr/CircomHashChecker/step-3/README.md new file mode 100644 index 000000000..b3ac14050 --- /dev/null +++ b/locales/fr/CircomHashChecker/step-3/README.md @@ -0,0 +1,32 @@ +## Exploring `calculate_hash.circom` + +Navigate to the `circuits` directory and open `calculate_hash.circom`. This file contains the Circom code for the Hash Checker circuit. + +### Code Breakdown + +#### Pragma and Includes: + +- `pragma circom 2.0.0;` specifies the Circom version. +- `include "circomlib/circuits/poseidon.circom";` fetch and includes the Poseidon hash function from [CircomLib](https://github.com/iden3/circomlib). + +#### `CalculateHash` Template: + +- Defines inputs `value1`, `value2`, `value3`, `value4`. +- Uses the `Poseidon` hash function to compute a hash of these values.\ +- Outputs `out`, which is the hash. + +#### `HashChecker` Template: + +- Inputs are the same values plus a `hash`. +- Instantiates `CalculateHash` as `calculateSecret`. +- Computes `calculatedHash`. +- Uses `assert(hash == calculatedHash);` to ensure the provided hash matches the calculated hash. + +#### Main Component: + +- `component main {public [hash]} = HashChecker();` +- Specifies that `hash` is a `public` input, while the values are `private`. + +### Purpose + +The circuit allows someone to prove they know `value1`, `value2`, `value3`, and `value4` that hash to a specific `hash` without revealing the values themselves. diff --git a/locales/fr/CircomHashChecker/step-4/README.md b/locales/fr/CircomHashChecker/step-4/README.md new file mode 100644 index 000000000..537c6a241 --- /dev/null +++ b/locales/fr/CircomHashChecker/step-4/README.md @@ -0,0 +1,32 @@ +## Compiling the Circuit + +### Selecting the Compiler Version + +1. Go to the **Circuit Compiler** plugin in the sidebar. +2. Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +### Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +### Compiling the Circuit + +1. Click on the **Compile** button. +2. Wait for the compilation to complete. A success badge will appear if compilation is successful. + +compilation-success + +### Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/fr/CircomHashChecker/step-5/README.md b/locales/fr/CircomHashChecker/step-5/README.md new file mode 100644 index 000000000..c3ea8509b --- /dev/null +++ b/locales/fr/CircomHashChecker/step-5/README.md @@ -0,0 +1,25 @@ +## Performing a Trusted Setup + +1. **Access the Setup and Exports Section**: + +- After successful compilation, the **Setup and Exports** section becomes available in the plugin. + +2. **Select Proving Scheme**: + +- Choose **Groth16** from the **Proving Scheme** dropdown. + +3. **Select Power of Tau File**: + +- Choose the appropriate **Power of Tau** file from the dropdown. If unsure, use the default option. + +4. **Export Verification Key and Contract** (optional): + +- Enable **Export Verification Key** to save the verification key to the File Explorer. +- Enable **Export Verifier Contract** to save the Solidity contract for on-chain verification. + +trusted-setup + +5. **Run the Trusted Setup**: + +- Click on the **Run Setup** button. +- Wait for the process to complete. This may take some time depending on the circuit complexity. diff --git a/locales/fr/CircomHashChecker/step-6/README.md b/locales/fr/CircomHashChecker/step-6/README.md new file mode 100644 index 000000000..03b848f81 --- /dev/null +++ b/locales/fr/CircomHashChecker/step-6/README.md @@ -0,0 +1,28 @@ +## Compute Witness + +1. **Access the Compute Witness Section**: + - After the trusted setup, the **Compute Witness** section becomes available. + +2. **Input Values**: + - You'll see input fields for `value1`, `value2`, `value3`, `value4`, and `hash`. + - Enter values for each input. For example: + - `value1`: `1234` + - `value2`: `2` + - `value3`: `3` + - `value4`: `4` + +3. **Calculate the Hash**: + + - Compute the Poseidon hash of the four values using an external tool or library compatible with the Poseidon hash function. + - For the values above, here is the computed Poseidon hash `16382790289988537028417564277589554649233048801038362947503054340165041751802`. + - Enter the calculated `hash` value in the `hash` input field. + + compute-witness + +4. **Compute the Witness**: + + - Click on the **Compute Witness** button. + - Wait for the process to complete. A success badge will appear if the witness is computed successfully. + - If successful, you'll see `calculate_hash.wtn` created in the `.bin` directory in the file explorer. + + witness-computed diff --git a/locales/fr/CircomHashChecker/step-7/README.md b/locales/fr/CircomHashChecker/step-7/README.md new file mode 100644 index 000000000..e6ae80fea --- /dev/null +++ b/locales/fr/CircomHashChecker/step-7/README.md @@ -0,0 +1,21 @@ +## Generate Proof + +1. **Access the Generate Proof Section**: + - After computing the witness, expand the **Generate Proof** section. + +2. **Configure Proof Generation**: + - **Export Verifier Calldata**: Enable this option if you plan to verify the proof on-chain. + +3. **Generate the Proof**: + + - Click on the **Generate Proof** button. + - Wait for the proof generation to complete. + + generate-proof + +4. **View the Proof**: + + - The proof data will be displayed in the File Explorer. + - **Congratulations!** You've successfully compiled the `Hash Checker` circuit, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + + generate-proof diff --git a/locales/fr/CircomHashChecker/step-8/README.md b/locales/fr/CircomHashChecker/step-8/README.md new file mode 100644 index 000000000..e489a8cab --- /dev/null +++ b/locales/fr/CircomHashChecker/step-8/README.md @@ -0,0 +1,34 @@ +## Understanding `groth16_trusted_setup.ts` + +Navigate to `scripts/groth16/groth16_trusted_setup.ts`. This script performs the trusted setup necessary for generating proofs. + +### Code Breakdown + +#### Circuit Compilation: + +- Uses `remix.call('circuit-compiler', 'generateR1cs', ...)` to generate `R1CS` (Rank-1 Constraint System) from the circuit. + +#### Trusted Setup Steps: + +- `snarkjs.zKey.newZKey`: Initializes the proving key (`zkey_0`). +- `snarkjs.zKey.contribute`: Adds contributions to the proving key (`zkey_1`). +- `snarkjs.zKey.beacon`: Finalizes the proving key (`zkey_final`). + +#### Verification: + +- `snarkjs.zKey.verifyFromR1cs`: Verifies the proving key against the `R1CS` and initial parameters. + +#### Exporting Keys: + +- Exports the verification key to `scripts/groth16/zk/keys/verification_key.json`. +- Exports the final proving key (`scripts/groth16/zk/keys/zkey_final.txt`). + +### Purpose + +- Performs the trusted setup required for the `Groth16` proving system. +- Generates the necessary keys for proof generation and verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"setup done."` logged in the terminal. diff --git a/locales/fr/CircomHashChecker/step-9/README.md b/locales/fr/CircomHashChecker/step-9/README.md new file mode 100644 index 000000000..653d5ced1 --- /dev/null +++ b/locales/fr/CircomHashChecker/step-9/README.md @@ -0,0 +1,37 @@ +## Understanding `groth16_zkproof.ts` + +Navigate to `scripts/groth16/groth16_zkproof.ts`. This script generates the zero-knowledge proof and prepares it for verification. + +### Code Overview + +#### Loading Files: + +- Reads the R1CS and WASM files generated from the circuit. +- Loads the final proving key (`zkey_final`) and verification key (`vKey`). + +#### Defining Inputs: + +- Sets the private values (`value1`, `value2`, `value3`, `value4`). +- Computes the `hash` using Poseidon from [CircomLib](https://github.com/iden3/circomlib). + +#### Witness Calculation and Proof Generation: + +- Calculates the witness (`wtns`). +- Checks the witness against the `R1CS`. +- Generates the proof using `Groth16`. +- Verifies the proof. + +#### Exporting Verifier Contract and Inputs: + +- Generates a Solidity verifier contract. +- Exports the proof inputs to `input.json`. + +### Purpose + +- Generates a zero-knowledge proof that the prover knows values hashing to a specific hash. +- Prepares the verifier contract and inputs for on-chain verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"zk proof validity"` logged in the terminal. diff --git a/locales/fr/CircomIntro/README.md b/locales/fr/CircomIntro/README.md new file mode 100644 index 000000000..c58b2daec --- /dev/null +++ b/locales/fr/CircomIntro/README.md @@ -0,0 +1,21 @@ +Intro to Circom + +This is an introduction to Circom. You'll learn how to write, compile, and test arithmetic circuits in Circom. We'll go over how to do this within Remix-IDE. + +Tutorial Overview + +``` +Step 1: Introduction +Step 2: Setting Up Remix-IDE and Installing the Circuit-Compiler Plugin +Step 3: Writing Your First Circom Circuit +Step 4: Compiling the Circuit Using the Plugin +Step 5: Performing a Trusted Setup +Step 6: Computing the Witness +Step 7: Generating the Proof +``` + +Prerequisites: + +``` +Basic understanding of cryptography and zero-knowledge proofs is helpful but not required. +``` diff --git a/locales/fr/CircomIntro/config.yml b/locales/fr/CircomIntro/config.yml new file mode 100644 index 000000000..d6dfdca46 --- /dev/null +++ b/locales/fr/CircomIntro/config.yml @@ -0,0 +1,29 @@ +id: circom-intro +name: Intro to Circom +summary: A intro to using Circom for creating arithmetic circuits. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction + path: step-1 + - + name: Installing the Circuit-Compiler + path: step-2 + - + name: Writing Your First Circom Circuit + path: step-3 + - + name: Compiling the Circuit Using the Plugin + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Computing the Witness + path: step-6 + - + name: Generating the Proof + path: step-7 diff --git a/locales/fr/CircomIntro/step-1/README.md b/locales/fr/CircomIntro/step-1/README.md new file mode 100644 index 000000000..0766ce6f4 --- /dev/null +++ b/locales/fr/CircomIntro/step-1/README.md @@ -0,0 +1,13 @@ +Welcome to this beginner-level tutorial on Circom using Remix. In this tutorial, you'll learn the basics of Circom, a domain-specific language used for creating arithmetic circuits. + +**What is Circom?** + +Circom is a language designed for writing arithmetic circuits that can be used in zero-knowledge proofs, particularly zk-SNARKs. It allows developers to define complex mathematical circuits that can prove knowledge of certain data without revealing it. + +**Why Use Remix-IDE for Circom?** + +- **Ease of Use:** Remix-IDE provides a user-friendly interface that simplifies the development process. +- **Integrated Tools:** With plugins like `circuit-compiler`, you can compile Circom code, perform trusted setups, compute witnesses, and generate proofs all within the same environment. +- **No Installation Required:** As a web-based IDE, you can start coding immediately without setting up a local development environment. + +In the next steps, we'll guide you through setting up Remix-IDE for Circom development and help you write your first circuit. diff --git a/locales/fr/CircomIntro/step-2/README.md b/locales/fr/CircomIntro/step-2/README.md new file mode 100644 index 000000000..4b228c298 --- /dev/null +++ b/locales/fr/CircomIntro/step-2/README.md @@ -0,0 +1,25 @@ +In this step, we'll set up Remix for Circom development by activating the `Circom ZKP compiler` plugin. + +## Activating the Circom ZKP compiler + +1. At the bottom of the icon panel on the left of the screen, click on the **Plugin Manager** (the plug icon). + 2.In the search bar, type **Circom**. +2. Find the **Circuit Compiler** plugin in the list and click on the **Activate** button. +3. The plugin will now appear in your sidebar. + +install-plugin + +## The Circom Compiler Interface + +- **Compiler Version Dropdown:** Select the Circom compiler version you wish to use. +- **Auto Compile Checkbox:** Enable this to automatically compile your circuit whenever you make changes. +- **Hide Warnings Checkbox:** Enable this to suppress compiler warnings. +- **Advanced Configuration:** Click to expand options for selecting the prime field (e.g., BN128, BLS12381). + +compiler-interface + +With the plugin installed, you're now ready to start writing Circom code in Remix-IDE. + +**Note:** Make sure your internet connection is stable, as Remix-IDE is a web-based tool. + +In the next step, we'll write our first Circom circuit. diff --git a/locales/fr/CircomIntro/step-3/README.md b/locales/fr/CircomIntro/step-3/README.md new file mode 100644 index 000000000..6424668f6 --- /dev/null +++ b/locales/fr/CircomIntro/step-3/README.md @@ -0,0 +1,38 @@ +Let's write a simple Circom circuit. + +## Creating a New Circuit File + +1. In the **File Explorer** on the left sidebar, click on the **Create New File** icon. +2. Name your file `multiplier.circom` and press **Enter**. + +create-new-file + +## Writing the Circuit + +Open `multiplier.circom` and add the following code: + +```circom +pragma circom 2.0.0; + +template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; +} + +component main = Multiplier(); +``` + +## Explanation: + +- template `Multiplier()`: Defines a new circuit template called Multiplier. +- `signal input a;` and `signal input b;`: Declare input signals a and b. +- `signal output c;`: Declare an output signal c. +- `c <== a * b;`: Constrain c to be the product of a and b. +- `component main = Multiplier();`: Instantiates the Multiplier circuit as main, which is required for the compiler. + +### NB: + +Signals are values in a cryptographic circuit that are strictly determined by the circuit's equations and constraints. Think of a signal as a value that must follow specific mathematical rules defined by the circuit—once set, it can't be changed arbitrarily. In regular programming, variables are flexible and can be updated or reassigned as needed, whereas, signals can't be altered freely. diff --git a/locales/fr/CircomIntro/step-4/README.md b/locales/fr/CircomIntro/step-4/README.md new file mode 100644 index 000000000..ad3f2a089 --- /dev/null +++ b/locales/fr/CircomIntro/step-4/README.md @@ -0,0 +1,34 @@ +With your `multiplier.circom` circuit ready, let's compile it using the Circuit Compiler plugin. + +## Selecting the Compiler Version + +Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +## Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +## Compiling the Circuit + +1. Click on the **Compile** button. +2. The compiler will process your circuit. +3. If successful, you'll see a compilation success message. + +compilation-success + +**Note:** If there are any errors, they will be displayed in the console. Check your code for typos or syntax errors. + +## Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/fr/CircomIntro/step-5/README.md b/locales/fr/CircomIntro/step-5/README.md new file mode 100644 index 000000000..8e8496bbd --- /dev/null +++ b/locales/fr/CircomIntro/step-5/README.md @@ -0,0 +1,26 @@ +After compiling your circuit, you need to perform a trusted setup to generate proving and verification keys. + +## Understanding Trusted Setup + +- **Trusted Setup:** A process required for zk-SNARKs to generate the necessary parameters for proof generation and verification. +- You can choose between different protocols like **Groth16** and **Plonk**. + +## Performing the Trusted Setup + +1. In the **Setup and Exports** section, select the **Proving Scheme**: + - Choose between **Groth16** or **Plonk**. We'll use **Groth16** for this tutorial. + +2. Choose the appropriate **Power of Tau** file from the dropdown. This file is necessary for the trusted setup. + - If unsure, select the default option. + +3. Click on the **Setup** button to start the trusted setup process. + +4. You can enable **Export Verification Key** to get the verification parameters. + +5. You can enable **Export Verification Contract** if you intend to verify proofs on-chain. + +trusted-setup + +**Note:** The trusted setup may take some time, depending on the complexity of your circuit. + +In the next step, we'll compute the witness for our circuit. diff --git a/locales/fr/CircomIntro/step-6/README.md b/locales/fr/CircomIntro/step-6/README.md new file mode 100644 index 000000000..e13d33d32 --- /dev/null +++ b/locales/fr/CircomIntro/step-6/README.md @@ -0,0 +1,27 @@ +With the trusted setup complete, you can now compute the witness for your circuit based on specific inputs. + +## What is a Witness? + +- A **Witness** is a set of values that satisfy all the constraints of your circuit. It includes all the intermediate numbers and results that satisfy the circuit's rules. The witness is used in zero-knowledge proofs to demonstrate that you know a valid solution to the problem without actually showing the solution itself. This allows others to verify that you did everything correctly while keeping your specific numbers and calculations private. +- It is essential for generating a proof. + +## Inputting Values + +1. In the **Compute Witness** section, you'll see input fields dynamically generated based on your circuit's inputs. +2. Enter values for `a` and `b`. For example: + - `a = 3` + - `b = 4` + +compute-witness + +## Computing the Witness + +1. After entering the inputs, click on the **Compute Witness** button. +2. The plugin will compute the witness based on your inputs. +3. If successful, you'll see `multiplier.wtn` created in the `.bin` directory in the file explorer. + +witness-computed + +**Note:** If there are any errors, ensure that your inputs are valid and satisfy the circuit's constraints. + +In the next step, we'll generate a proof using the computed witness. diff --git a/locales/fr/CircomIntro/step-7/README.md b/locales/fr/CircomIntro/step-7/README.md new file mode 100644 index 000000000..f5cf332a9 --- /dev/null +++ b/locales/fr/CircomIntro/step-7/README.md @@ -0,0 +1,31 @@ +With the witness computed, the final step is to generate a proof that can be verified by others. + +## Generating the Proof + +1. In the **Generate Proof** section, you have the option to **Export Verifier Calldata**. + - Enable the **Export Verifier Calldata** checkbox if you plan to verify the proof on-chain. +2. Click on the **Generate Proof** button. + +generate-proof + +## Understanding the Output + +- After generating the proof, the plugin will display the proof data. +- If you enabled **Export Verifier Calldata**, it will also provide the calldata needed for on-chain verification. + +proof-generated + +## Next Steps + +- **Verification:** You can use the verification key or contract exported earlier to verify the proof. +- **On-Chain Verification:** If you're familiar with smart contracts, you can deploy the verification contract and use the calldata to perform on-chain verification. + +**Congratulations!** You've successfully written a Circom circuit, compiled it, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + +## Additional Resources + +- [Circom Documentation](https://docs.circom.io/) +- [Remix-IDE Documentation](https://remix-ide.readthedocs.io/) +- [Zero-Knowledge Proofs Explained](https://zkproof.org/) + +Feel free to experiment with more complex circuits and explore the capabilities of Circom and Remix-IDE further. diff --git a/locales/fr/DeployWithLibraries/1_Writing_a_Library/step1.md b/locales/fr/DeployWithLibraries/1_Writing_a_Library/step1.md new file mode 100644 index 000000000..1ad984835 --- /dev/null +++ b/locales/fr/DeployWithLibraries/1_Writing_a_Library/step1.md @@ -0,0 +1,17 @@ +A libraries looks like a **contract** but use the keyword `library` + +A library typically is a collection of useful functions sitting out there on the blockchain that any contract can use. Because the library is already deployed, it saves the deployment costs of the many contracts that use it. + +In the following contract: + +- Make a library with the name `LibraryForTest`. + +It is possible to put a library in same file with another contract. So put the library below the contract. + +This library should have a method called `getFromLib` method which returns `3`. + +- Update the `get` method in the `test` contract to use the `LibraryForTest` library. The function `get` should return the value it receives from `getFromLib`. + +--------- + +You can find more info about libraries in this section of the Solidity Docs. diff --git a/locales/fr/DeployWithLibraries/2_Generate_Metadata/step2.md b/locales/fr/DeployWithLibraries/2_Generate_Metadata/step2.md new file mode 100644 index 000000000..218c86ff9 --- /dev/null +++ b/locales/fr/DeployWithLibraries/2_Generate_Metadata/step2.md @@ -0,0 +1,38 @@ +## Deploying Library + +The **library** from the previous chapter was in the same file as the **contract**. However, they won't be deployed together and will have different addresses. + +In order to use a library, the calling contract must have the library's **address**. + +But the library's address is not directly specified in the solidity code. The calling contract's compiled bytecode contains a **placeholder** where library's **addresses** will go. + +At deployment of the **calling contract**, Remix will look in the contract's **metadata** for the library's address and will update the placeholder with the address. + +So before deploying a contract that calls a library, you need to generate the contract's metadata (AKA its **build artifact**) and then you need to input the library's address into the metadata file. + +A contract's metadata is generated at **compile time**. + +Let's setup Remix to generate the **metadata file**. + +- Go to the settings module by clicking on the settings ![settings](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/settings.png "Settings") icon in the icon panel. + +![settings module](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_settings.png "Settings Module") + +- And check the first option `Generate contract metadata`. + +# Compile and generate metadata (JSON) file. + +1. Open the Solidity Compiler ![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +2. Compile `2_contractSimpleLibrary.sol`. + +3. Switch to the File Explorer ![File Explorer](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_file_explorer.png "File Explorer") + +4. Navigate to the newly create JSON files. + - It should be in the folder: + +**browser/.learneth/DeployWithLibraries/2_Generate_Metadata/artifacts/** + +5. Select the newly created JSON file created from the contract. It has the **same name** as the contract `sample` but with the extension **json**: `sample.json` (don't select the library's metadata `contractSimpleLibrary.json`). + +In the next step we'll make some adjustments to the metadata file. diff --git a/locales/fr/DeployWithLibraries/3_Edit_Metadata/step3.md b/locales/fr/DeployWithLibraries/3_Edit_Metadata/step3.md new file mode 100644 index 000000000..1555d645d --- /dev/null +++ b/locales/fr/DeployWithLibraries/3_Edit_Metadata/step3.md @@ -0,0 +1,12 @@ +The `Deploy` property in `sampleContract.json` contains everything you need for telling Remix IDE the address of the library for a specific network. + +- `
` contains the address of the library that is already deployed. You have to specify this address for each network. +- `autoDeployLib` is a boolean and tells Remix IDE if it should autodeploy the library before deploying the contract. + +Basically if `autoDeployLib` is **true**, the `
` will not be used and Remix will automatically deploy the library before deploying the contract. + +For the purpose of this demo - we are mimicking a situation where the library has already been deployed because this is a more common situation. + +So set `autoDeploy` to **false**, for the `VM:-` entry. + +Move to next Step. diff --git a/locales/fr/DeployWithLibraries/4_Linking_and_Deploying/step4.md b/locales/fr/DeployWithLibraries/4_Linking_and_Deploying/step4.md new file mode 100644 index 000000000..ad5f52e2d --- /dev/null +++ b/locales/fr/DeployWithLibraries/4_Linking_and_Deploying/step4.md @@ -0,0 +1,25 @@ +Switch to the `Deploy & Run` module +![Run transaction](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/remix_runtransaction.png "Run Transaction") + +- Select the Remix VM Environment and select the `sampleContract` contract in the list of compiled contracts. + +- Click on `Deploy` + +The terminal should output something like `creation of sample errored:
is not a valid address. Please check the provided address is valid.` +That is expected: **We have set `autoDeployLib` to false, so Remix expects to have an address and not just `
`** + +So we need deploy the library to get its address. + +- Select the library `aLib` in the list of compiled contract and hit `deploy` + + ![Choose aLib](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/contract_alib.png "Choose aLib") + +- Click the clipboard icon to copy the address of the library. + + ![Copy lib1](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/alib_copy.png "Copy") + +- Paste it into the **contract sample's** metadata JSON. + +- Reselect the `sampleContract` contract in the `Run transaction` module and hit deploy. + +- Deploy should now be successful. diff --git a/locales/fr/DeployWithLibraries/5_Under_The_Hood/step5.md b/locales/fr/DeployWithLibraries/5_Under_The_Hood/step5.md new file mode 100644 index 000000000..860b48b24 --- /dev/null +++ b/locales/fr/DeployWithLibraries/5_Under_The_Hood/step5.md @@ -0,0 +1,30 @@ +Switch to the `Solidity compiler` module +![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +- Select the `sampleContract` contract in the list of compiled contracts. +- click on `ByteCode`, it should copy the following to the clipboard: + +``` +{ + "linkReferences": { + "browser/contractSimpleLibrary.sol": { + "lib1": [ + { + "length": 20, + "start": 115 + } + ] + } + }, + "object": "608060405234801561001057600080fd5b5060f68061001f6000396000f3fe6080604052600436106039576000357c0100000000000000000000000000000000000000000000000000000000900480636d4ce63c14603e575b600080fd5b348015604957600080fd5b5060506052565b005b73__$d42d70ba92b626965f4c69b39148e37a33$__63fea24e5f6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801560b157600080fd5b505af415801560c4573d6000803e3d6000fd5b5050505056fea165627a7a7230582068c9a3a9a5cbfd26cfdab2534abfc926912d9b89eaa14e36c8248b7e7eb0ab090029", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xF6 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x39 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x3E JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x50 PUSH1 0x52 JUMP JUMPDEST STOP JUMPDEST PUSH20 0x0 PUSH4 0xFEA24E5F PUSH1 0x40 MLOAD DUP2 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH1 0xB1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS DELEGATECALL ISZERO DUP1 ISZERO PUSH1 0xC4 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 PUSH9 0xC9A3A9A5CBFD26CFDA 0xb2 MSTORE8 0x4a 0xbf 0xc9 0x26 SWAP2 0x2d SWAP12 DUP10 0xea LOG1 0x4e CALLDATASIZE 0xc8 0x24 DUP12 PUSH31 0x7EB0AB09002900000000000000000000000000000000000000000000000000 ", + "sourceMap": "63:85:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63:85:0;;;;;;;" +} +``` + +This is basically what the compiler is returning: + +- `linkReferences` describes what are the libraries used by the contract. +- `object` is the compiled contract (bytecode). This is what gets deployed and saved onto the blockchain. In this example, the value `__$d42d70ba92b626965f4c69b39148e37a33$__` inside the bytecode is just a placeholder for the library address. In your case, the placeholder will be between `__$` and `$__`. + +The metadata JSON from Remix IDE tells Remix to replace the placeholder with the given address. diff --git a/locales/fr/DeployWithLibraries/README.md b/locales/fr/DeployWithLibraries/README.md new file mode 100644 index 000000000..fb31b1264 --- /dev/null +++ b/locales/fr/DeployWithLibraries/README.md @@ -0,0 +1,3 @@ +**Libraries** are deployed contracts that do not store state and are used by other contracts to decrease their size and thus their deployment costs. + +Learn to work with **Libraries** in Remix - you won't need to whisper. diff --git a/locales/fr/DeployWithLibraries/config.yml b/locales/fr/DeployWithLibraries/config.yml new file mode 100644 index 000000000..0816e2346 --- /dev/null +++ b/locales/fr/DeployWithLibraries/config.yml @@ -0,0 +1,8 @@ +--- +id: deploylibraries +name: Deploy with Libraries +summary: Write, Deploy and link a Library to a Contract +level: 3 +tags: + - Remix + - Solidity diff --git a/locales/fr/ERC20TokenCourse/README.md b/locales/fr/ERC20TokenCourse/README.md new file mode 100644 index 000000000..25a6ccf95 --- /dev/null +++ b/locales/fr/ERC20TokenCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Token Course + +Learn to understand and create ERC20 tokens. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/fr/ERC20TokenCourse/config.yml b/locales/fr/ERC20TokenCourse/config.yml new file mode 100644 index 000000000..8c12a5213 --- /dev/null +++ b/locales/fr/ERC20TokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: tokenCourse +name: Solidity ERC20 Token Course +summary: Learn how to create your own ERC20 tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - ERC20 +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc20-interface + - + name: 3. Token Creation + path: erc20-token-creation + - + name: 4. Interaction + path: erc20-interaction + - + name: 5. Testnet Deployment + path: erc20-testnet-deployment + - + name: 6. Extensions + path: erc20-extensions diff --git a/locales/fr/ERC20TokenCourse/erc20-extensions/erc20extensions.md b/locales/fr/ERC20TokenCourse/erc20-extensions/erc20extensions.md new file mode 100644 index 000000000..b3649fbba --- /dev/null +++ b/locales/fr/ERC20TokenCourse/erc20-extensions/erc20extensions.md @@ -0,0 +1,33 @@ +The ERC20 standard only describes the required and optional functionality that your contract needs, but you can add additional functionality. + +In this section, we added the functionality to burn and mint tokens, as well as the ability to pause the contract, by using OpenZeppelin extensions. + +Of course, you can write your own ERC20 token contract implementation or extensions and import them into your contract. But OpenZeppelin contracts have been audited by security experts and are a great way to add desired functionality. + +### Mintable + +The mint function allows the creator of the contract to mint (create) additional tokens after the contract has been deployed (line 22). As input parameters, the function needs the address that the tokens will be minted to, and the amount of tokens that should be minted. + +We don't have to import `mint()` from another contract since the mint function is already part of the ERC20 contract implementation of OpenZeppelin. We import `Ownable` (line 7) which is a contract module that provides a basic access control mechanism that allows an owner to have exclusive access to specific functions. In this contract, we add the inherited `onlyOwner` modifier to the `mint` function (line 22) and restrict access to this function to the "owner". + +The contract will inherit additional functions like owner(), transferOwnership() and renounceOwnership() to manage access, from the Ownable contract. + +### Burnable + +By importing the "ERC20Burnable" (line 5) and inheriting its functions (line 9) our contract allows token holders to destroy their tokens as well as the tokens in their allowance. +For more information, have a look at the ERC20Burnable contract. + +### Pausable + +With the "Pausable" contract module (line 6 and 9) the owner is able to pause (line 14) and unpause (line 18) the contract. In the pause state, tokens can't be transferred, which can be helpful in emergency scenarios. +For more information, have a look at the Pausable contract. + +Have a look at the OpenZeppelins Contract Wizard, which allows you to easily add additional functionality. + +If you successfully completed this course, try the Learneth NFT Course as the next step in your journey. + +## ⭐️ Assignment + +1. Try to mint tokens to an account after deployment. Call `totalSupply()` and `balanceOf()` to confirm the correct execution. +2. Burn tokens and then call `totalSupply()` and `balanceOf()` to confirm the correct execution. +3. Test the pause function by pausing the contract using the owner account and trying to make a transfer with a second account. The transaction should not be able to be executed and will throw the exception: "Pausable: paused". diff --git a/locales/fr/ERC20TokenCourse/erc20-interaction/er20interaction.md b/locales/fr/ERC20TokenCourse/erc20-interaction/er20interaction.md new file mode 100644 index 000000000..5c082b248 --- /dev/null +++ b/locales/fr/ERC20TokenCourse/erc20-interaction/er20interaction.md @@ -0,0 +1,87 @@ +In this section, we will deploy a contract in our browser and test its functionality. + +### 1. Deploy the contract + +**1.1** Compile your EduCoin contract in the "Solidity compiler" module of the Remix IDE. + +**1.2** In the "Deploy & run transactions" module, select your contract "EduCoin" in the contract input field and click on the "Deploy" button. Always make sure to select the correct contract in the contract selector input field. + +**GIF** Compile and deploy: Compile and deploy contract + +### 2. Test the functions + +Expand the token contract functions in the IDE. + +#### 2.1 Decimals + +Click on the "decimals" button to call the decimals() function. +It should return "18". + +#### 2.2 Name + +Click on the "name" button to call the name() function. +It should return "EduCoin". + +#### 2.3 Symbol + +Click on the "symbol" button to call the symbol() function. +It should return "EDC". + +#### 2.4 Total supply + +Click on the "totalSupply" button to call the totalSupply() function. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test decimals, name, symbol, and totalSupply functions: Test transfer function + +#### 2.5 Balance of + +**2.5.1** Go to the "ACCOUNT" section in the sidebar and copy the displayed address by using the copy icon next to it. + +**2.5.2** Paste the address in the input field next to the "balanceOf" function button and click on the button. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test balanceOf function: Test transfer function + +#### 2.6 Transfer + +We will transfer EduCoin from one account to a second account. + +**2.6.1** Go to the "ACCOUNT" section in the sidebar and click on the displayed address. This should open a dropdown. Select the second address displayed and copy its address (account 2). + +**2.6.2** Open the dropdown and select the first account again (account 1), because this is the account that we want to use to make the transfer. + +**2.6.3** Paste the address in the input field next to the "transfer" function button, input the number 500000000000000000000, and click on the button. + +**2.6.4** If you check the balances for account 1 and account 2, they should both return the amount 500000000000000000000. + +**GIF** Test transfer function: Test transfer function + +#### 2.7 Approve + +We will now allow account 1 to spend tokens on behalf of account 2. + +**2.7.1** Go to the "Account" section, copy the address of account 1, then set it to account 2 again. + +**2.7.2** In the approve function, enter the address of account 1 as the input for spender and set the amount to 250000000000000000000. + +**GIF** Test approve function: Test approve function + +#### 2.8 Allowance + +Next to the "allowance" button enter the address of account 2 as the owner and account 1 as the spender; click on the button. +It should return 1000000000000000000000. + +**GIF** Test allowance function: Test allowance function + +#### 2.9 TransferFrom + +Now account 1 will transfer 250000000000000000000 tokens from account 2 to its own account. + +**2.9.1** Select account 1 in the "ACCOUNT" section. + +**2.9.2** Next to the "transferFrom" button enter the address of account 2 as the sender and account 1 as the recipient, enter 250000000000000000000 as the amount and click on the button. + +**2.9.3** Check the balances of accounts 2 and 1, they should return 250000000000000000000 and 750000000000000000000. + +**GIF** Test transferFrom function: Test transferFrom function diff --git a/locales/fr/ERC20TokenCourse/erc20-interface/erc20interface.md b/locales/fr/ERC20TokenCourse/erc20-interface/erc20interface.md new file mode 100644 index 000000000..5c4e8137c --- /dev/null +++ b/locales/fr/ERC20TokenCourse/erc20-interface/erc20interface.md @@ -0,0 +1,76 @@ +ERC20 (Ethereum Request for Comments 20) is a standard for token contracts that manages fungible tokens on the Ethereum blockchain. + +Fungible tokens are all equal to each other and have the same value, behavior, and rights. Fungible tokens are often used as a medium of exchange, like the currencies ETH or BTC. However, they can also have other use cases like voting rights or reputation. + +If you want to know more about the ERC20 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +To get an overview of the required functionality of an ERC20 token contract, we will look at an interface that interacts with an ERC20 contract. +This interface (line 9) is part of the open-source contract library provided by OpenZeppelin. + +## ERC20 Functions + +Contracts compliant with the ERC20 standard must implement the following six functions: + +### totalSupply + +The function `totalSupply` (line 13) returns the total amount of tokens available. + +### balanceOf + +The function `balanceOf` (line 18) returns the amount of tokens owned by the account with the address `account`. + +### transfer + +The function `transfer` (line 27) transfers `amount` of tokens to the address `recipient`. +This function **must** emit (produce) a `Transfer` event (see below) and **should** throw an exception when the sender doesn't have enough tokens to make the transfer. + +### approve + +The function `approve` (line 52) creates an allowance for the address `spender` to transfer `amount` of tokens on behalf of the account calling the function. + +### allowance + +The function `allowance` (line 36) returns the amount of tokens that the address `spender` is allowed to spend on behalf of the account with the address `owner`. + +### transferFrom + +The function `transferFrom` (line 63) transfers `amount` of tokens on behalf of the address `sender` to the address `recipient`. +This function **must** emit a `Transfer` event. + +## ERC20 Events + +ERC20 contracts must also emit two events: + +### Transfer + +The `Transfer` (line 71) event must be emitted when `value` amount of tokens are transferred from the account with the address `indexed from` to `indexed to`. The parameters `from` and `to` are `indexed` allowing us to search for these events using the indexed parameters as filters. + +### Approval + +The `Approval` (line 77) event must be emitted when the account `indexed owner` approves the account `indexed spender` to transfer `value` amount of tokens on its behalf. + +## ERC20 Optional functions + +In addition to the mandatory functions and events, there are also three optional functions specified in the ERC20 standard that are not implemented in this interface: + +### name + +`function name() external view returns (string);` + +Returns the name of the token. + +### symbol + +`function symbol() external view returns (string);` + +Returns the symbol of the token. + +### decimals + +`function decimals() external view returns (uint8);` + +Returns the number of decimal places the token uses. + +You may want to use decimals to make your token divisible into arbitrary amounts like 1.5 ETH when displayed. The EVM (Ethereum virtual machine) only supports integer numbers. That's why the ERC20 standard suggests to implement the decimal functionality that specifies how many decimal places a token has. 18 decimal places is the industry standard. diff --git a/locales/fr/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md b/locales/fr/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md new file mode 100644 index 000000000..94b513922 --- /dev/null +++ b/locales/fr/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md @@ -0,0 +1,41 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to a testnet of the Ethereum blockchain. This testnet behaves very similarly to the real blockchain (mainnet), but does not require real ETH to pay for transactions. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token + +In order to make transactions on the testnet we need Ethereum testnet tokens, which you can receive from something called a _faucet_. + +**2.1** Switch your Metamask network by clicking on the "Ethereum Mainnetwork" drop down and selecting "Ropsten Test Network". If you don’t see any test networks, click on the "Show/hide" link and enable "Show test networks" in the settings. + +**2.2** Go to https://faucet.ropsten.be/, enter the address of your account, and claim testnet ETH. You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Deployment + +Make sure the EduCoin contract is compiled. + +**3.1.** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It will ask you to connect your account which you should confirm. + +**3.2** Deploy the EduCoin contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. Copy the contract address. + +**3.4** In Metamask, click on assets, then click on the "Import tokens" link, and paste the address of your contract in the input field. + +You should now see a balance of 1000 EDC in your wallet. + +### 4. Make a transaction + +**4.1** Click on the identicon (visual representation of your address) in the Metamask wallet and create a second account (Account 2). + +**4.2** Copy the address of Account 2. + +**4.3** Switch to the first account (Account 1) and send 250 EDC to Account 2. Check the balances of Account 1 and Account 2. You might need to add the token address again for Account 2 to import the tokens and you will need testeth if you want to make a transaction with this account. + +You can also see your account balances if you look at the contract in Remix and call the `balanceOf` function using the addresses of Account 1 and Account 2. diff --git a/locales/fr/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md b/locales/fr/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md new file mode 100644 index 000000000..49b71abdd --- /dev/null +++ b/locales/fr/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md @@ -0,0 +1,18 @@ +A token standard tells us what functionality the contract needs to comply with it. How this functionality is implemented is up to the developers. In this contract, we will use an ERC20 token contract implementation from OpenZeppelin (line 4). In this case, we import version 4.4.0 of the OpenZeppelin contracts. + +Have a look at their nicely documented ERC20 contract to have a better understanding of how an implementation might look. Apart from the functionality specified in the ERC20 standard, this contract provides additional functionality. + +We will create our own contract called MyToken (line 6), which inherits the functionality from the OpenZepplin ERC20 token contract implementation that we imported (line 4). + +This contract implements the optional functions `name()` and `symbol()` of the ERC20 Token standard and has a constructor where their values can be set during the deployment of the contract (line 7). +In this case, we are going to use the default values. We will call our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +Next, we make use of the inherited `_mint` function (line 8) that allows us to create tokens upon deployment of the contract. Inside the parameters, we specify the address of the account that receives the tokens and the amount of tokens that are created. +In this case, the account that deploys the contract will receive the tokens and we set the amount to 1000000 to the power of `decimals()`. The optional function `decimals()` of the ERC20 token standard is implemented and set to the default value of 18. This will create 1000000 tokens that will have 18 decimal places. + +## ⭐️ Assignment + +1. Rename your contract to `EduCoin`. +2. Rename your token to `EduCoin`. +3. Change the symbol of your token to `EDC`. +4. Change the amount of tokens that will be minted from 1000000 to 1000. diff --git a/locales/fr/ERC20TokenCourse/introduction/introduction.md b/locales/fr/ERC20TokenCourse/introduction/introduction.md new file mode 100644 index 000000000..4eaf7583c --- /dev/null +++ b/locales/fr/ERC20TokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with the ERC20 token standard in the following sections. + +If you want to learn more about NFTs and the ERC721 token standard, have a look at the Learneth NFT Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/fr/ERC721Auction/README.md b/locales/fr/ERC721Auction/README.md new file mode 100644 index 000000000..325e4d60e --- /dev/null +++ b/locales/fr/ERC721Auction/README.md @@ -0,0 +1,5 @@ +## NFT Auction Contract + +Learn how to write an ERC721 (NFT) auction contract. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/fr/ERC721Auction/auction-contract-setup/auctionContractSetup.md b/locales/fr/ERC721Auction/auction-contract-setup/auctionContractSetup.md new file mode 100644 index 000000000..945f0f803 --- /dev/null +++ b/locales/fr/ERC721Auction/auction-contract-setup/auctionContractSetup.md @@ -0,0 +1,46 @@ +In this contract tutorial, we will learn how to create an ERC721 (NFT) auction contract. +We recommend to you, to do the Learneth "Solidity NFT Course" before starting this tutorial. + +In the following sections, we will create a contract that will enable a seller to auction an NFT to the highest bidder. This contract was created by the Solidity by Example project. In this first section, we will create an interface, the necessary state variables, and the constructor. + +### Interface + +We create the interface (line 5) for the ERC721 token since our contract will need to interact with it. We will need the `safeTransferFrom` (line 5), and` transferFrom` (line 11) methods. + +### EnglishAuction + +We create the four events `Start`, `Bid`, `Withdraw`, `End` (line 19-22) so we can log important interactions. + +Next, we will create the state variables that store all the necessary information about our auction on-chain. + +We create two state variables for the NFT we want to auction. In the variable `nft` (line 24) we store a representation of the NFT contract, that will allow us to call its functions by combining the interface IERC721 and the address of the NFT contract. +In `nftId` (line 25), we store the specific token id in our NFT contract that will be auctioned. + +Next, we need a variable to store the address of the person that is auctioning off the NFT, the `seller` (line 27). +We want our NFT contract to send the seller the proceeds of the auction when it is finished, that’s why use `address payable`. + +We create a state variable `endAt` (line 28) where we will store the end date of the auction. +We also create the two booleans, `started` (line 29) and `ended` (line 30), that keep track of whether the auction has started or ended. + +We create a variable `highestBidder` (line 32) where we will store the address of the highest bidder. We will send the highest bidder the NFT once the auction has ended. + +Finally, we need a uint `highestBid` (line 33) to store the highest bid and a mapping `bids` (line 34), where we can store the total value of bids that an account has made before withdrawing; more on this in the next section. + +### Constructor + +When the auctioneer deploys the contract, they need to provide a few arguments: +the address of the contract of the NFT they want to auction `_nft` (line 37), the token id of the NFT they want to auction `_nftId` (line 38), and a starting price that must be overbid to place the first bid in the auction,`_startingBid` (line 39). + +Once deployed, the state variables `nft` (line 41), `nftId` (line 42), `highestBid` (line 45) will be assigned the values from the arguments. The address of the `seller` that deployed the contract will be automatically read out via msg.sender and stored in the state variable `seller` (line 44). + +In the next section, we will enable the auctioneer to start the auction and bidders to place their bids. + +## ⭐️ Assignment + +We will use the assignment part of the following sections to give you instructions on testing your contract in the Remix VM environment of Remix. + +1. Deploy an NFT contract. You can use the NFT contract that we created in our "3.3 ERC721 - Token Creation" section. + +2. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +3. After deploying your contract, test if contract functions like `nft`, `nftId`, and `started` work as expected. diff --git a/locales/fr/ERC721Auction/auction-start-bid/auctionContractStartBid.md b/locales/fr/ERC721Auction/auction-start-bid/auctionContractStartBid.md new file mode 100644 index 000000000..c2b944e0c --- /dev/null +++ b/locales/fr/ERC721Auction/auction-start-bid/auctionContractStartBid.md @@ -0,0 +1,42 @@ +In this section, we will create a function to start the auction and a function to bid on the NFT. + +### Start + +We use some control structures to check if necessary conditions are met before we let the seller start the auction. + +First, we check if the auction has already started (line 49). If it has started and our state variable `started` returns `true` we exit the function and throw an exception. + +The second condition we check for is whether the seller is executing the function (line 50). We have already created a function to store the seller's address when they deploy the contract in the `seller` state variable and can now check if the account executing the start function is the seller. If not we throw an exception. + +Next, we want to transfer the NFT that is up for auction from the seller to the contract (line 52). +We set the state variable `started` to `true` (line 53), and create an end date for the auction (line 54). In this case, it will be seven days from when the start function has been called. We can use a suffix like `days` after a literal number to specify units of time. If you want to learn more about time units have a look at the solidity documentation. + +Finally, we will emit our `Start()` event (line 56). + +### Bid + +Before the function caller can make a bid, we need to be sure that certain conditions are met. The auction needs to have started (line 60), the auction can not have ended (line 61) and the bid (the value attached to the call) needs to be higher than the current highest bid (line 62). + +Now we want to store the bid of the current highest bidder before we make a new bid. +First, we check if there is a bidder (line 64). If this function call is the first bid then the next line would be irrelevant. +In our mapping `bids` (line 34) we map the key, the `address` of the bidder, to the value, a `uint` that represents the total amount of ETH a bidder has bid in the auction before withdrawing. +If there is a bidder, we add the last bid (`highestBid`) of the `highestBidder` to the total value of the bids they have made (line 65) before withdrawing. +We store the bids because we want to enable the bidder to withdraw the ETH they used to make bids if they are no longer the highest bidder. + +Next, we set the `highestBidder` to the account calling the function (line 68), and the `highestBid` to their bid, the value that was sent with the call (line 69). + +Finally, we emit the `Bid` event (line 71). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we create in our "Solidity NFT Course" Learneth course. + +2. Mint yourself an NFT with the tokenId 0. + +3. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +4. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for `tokenId`. This will allow the contract to transfer the token to be auctioned. + +5. Call the `start` function of your auction contract. If you call the `started` function now, it should return `true`. If you call the `highestBid` function it should return 1. + +6. Set the value that you can attach to transactions to 3 Wei and call the `bid` function of the auction contract. If you call the `highestBid` function it should now return 3. diff --git a/locales/fr/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md b/locales/fr/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md new file mode 100644 index 000000000..e324a5c6e --- /dev/null +++ b/locales/fr/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md @@ -0,0 +1,45 @@ +In this section, we will finish the contract, create a function to withdraw the bids that an account has made, and create a function to end the auction. + +### Withdraw + +We create a local variable `bal` (balance) that stores the total value of bids that the function caller has made (line 75) since their last withdrawal. We can assign this value to `bal` by accessing the bids mapping using the address of the function caller as the key. + +Next, we set the value of the address of the function caller to 0 in the bids mapping because they will withdraw the total value of their bids (line 76). + +Now we transfer that amount of ETH from the contract to the function caller and emit the `Withdraw` event (line 79). + +### End + +Before the function caller can execute this function and end the auction, we need to check if certain conditions are met. The auction needs to have started (line 83), the end date of the auction needs to have been reached (line 84), and the auction must not have ended already (line 85). + +Once the auction has ended, we set the state variable `ended` to `true` (line 87). + +We check if anybody participated in the auction and bid on the NFT (line 88). + +If there was a bid, we transfer the NFT from the contract to the highest bidder (line 89) and transfer the ETH that was sent from the highest bidder to the contract, now to the address of the auctioneer, the seller of the NFT (line 90). + +If nobody bids on the NFT, we send the NFT back to the auctioneer (line 92). + +Finally, we emit the `End` event (line 95). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we created in our Learneth "Solidity NFT Course". + +2. Mint yourself an NFT with the tokenId 0. + +3. For testing purposes, change the value that is assigned to the `endAt` state variable (line 54) from `7 days` to `5 minutes`. + +4. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +5. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for the `tokenId`. + +6. Call the `start` function of your auction contract. + +7. Bid 2 Ether using account 1, and 3 Ether using account 2. If you call the `highestBidder` function, it should now return the address of account 2. + +8. Call the `withdraw` function with account 1. In the balance of account 1, you should see the 2 Ether minus some transaction fees. + +9. After 5 minutes have passed, call the `end` function. Then, call the `ended` function which should return `true`. + +In the NFT contract, if you call the `ownerOf` function with the tokenId 0, it should return the address of account 2. If you look at the balance of account 1 it should have increased by 3 Ether minus some transaction fees. diff --git a/locales/fr/ERC721Auction/config.yml b/locales/fr/ERC721Auction/config.yml new file mode 100644 index 000000000..0783a37a1 --- /dev/null +++ b/locales/fr/ERC721Auction/config.yml @@ -0,0 +1,19 @@ +--- +id: er721Auction +name: NFT Auction Contract +summary: Learn how to write an ERC721 (NFT) auction contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: Contract Setup + path: auction-contract-setup + - + name: Start and Bid Functions + path: auction-start-bid + - + name: Withdraw and End Functions + path: auction-withdraw-end diff --git a/locales/fr/Interoperability/1_Intro/intro.md b/locales/fr/Interoperability/1_Intro/intro.md new file mode 100644 index 000000000..ab26f4f6d --- /dev/null +++ b/locales/fr/Interoperability/1_Intro/intro.md @@ -0,0 +1,5 @@ +As the web3 world grows, there will be more blockchains. Unless the chains can communicate with one another, the ecosystem will become increasingly fragmented. + +The Axelar network enables protocols to have cross-chain functionality between any two blockchains. + +Building a protocol that is interoperable between ecosystems is essential for growth. diff --git a/locales/fr/Interoperability/2_Gateway/gateway.md b/locales/fr/Interoperability/2_Gateway/gateway.md new file mode 100644 index 000000000..dc752d3eb --- /dev/null +++ b/locales/fr/Interoperability/2_Gateway/gateway.md @@ -0,0 +1,25 @@ +The Axelar Gateway is the entrypoint for your smart contract into the Axelar ecosystem. Once you have triggered the appropriate function on the Gateway, your transaction will begin its interchain journey from your source chain across the Axelar network to the destination chain. Each chain that is connected to Axelar has a deployed gateway contract for you to interact with. + +The following are the two more relevant functions you will need to be familiar with. + +## callContract() + +This function triggers an interchain transaction with a message from the source to the destination chain. It takes three relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent + +The first two parameters are quite intuitive. They consist of both the name of the chain you want this transaction to go to and the address on that chain you want to end execute at. The final parameter is the payload. This payload represents a general message that is sent to the destination chain. The message can be used in many different ways on the destination chain. For example, you can send data to be used as a parameter in another function on the destination chain, you can send a function signature as a message that will then get executed on a destination chain, and much more. + +## callContractWithToken() + +This function triggers an interchain with a message and a fungible token from the source to the destination chain. It takes five relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent +4. `symbol`: The symbol of the token being sent +5. `amount`: The amount of that token that is being sent + +The first three parameters here are the same as in `callContract()`. The final two parameters are relevant to the token that is being sent along with the message. These are the symbol of the token and the amount of the token that is being sent. diff --git a/locales/fr/Interoperability/3_GasService/GasService.md b/locales/fr/Interoperability/3_GasService/GasService.md new file mode 100644 index 000000000..4ed0afbbf --- /dev/null +++ b/locales/fr/Interoperability/3_GasService/GasService.md @@ -0,0 +1,29 @@ +The Axelar Gas Service is an extremely useful tool made available to pay gas for an interchain transaction. It allows you to pay for the cost of a transaction in the token of the source chain, making for a much easier end user (and developer) experience. If for example the source chain is Ethereum and the destination chain is Polygon then the gas service will receive the complete payment for the transaction in ETH and no matic is needed from the caller to pay for the execution on the Polygon destination chain. + +The following are the two more relevant functions you will need to be familiar with in regards to the Gas Service. + +## payNativeGasForContractCall() + +This function allows you to pay for the entirety of an interchain transaction in the native token of the source chain. It takes five relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +The parameters overlap with the parameters required by the `callContract()` function in the Gateway contract. The two parameters not discussed in the Gateway section are `sender` and `refundAddress`. The sender is the address paying for the transaction and the refund address is the address that will receive any surplus funds sent to the gas service. + +## payNativeGasForContractCallWithToken() + +This function allows you to pay for the entirety of an interchain transaction (that includes a token transfer) in the native token of the source chain. It takes seven relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `symbol`: The symbol of the token that was sent +6. `amount`: The amount of the token that was sent +7. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +This function is nearly identical to the first top one the main difference being that it is used for message + token transfer transactions as opposed to just interchain message transactions (aka GMP Transactions). As a result the GasService needs to also know the `symbol` and `amount` of the token that is being sent. diff --git a/locales/fr/Interoperability/4_Executable/executable.md b/locales/fr/Interoperability/4_Executable/executable.md new file mode 100644 index 000000000..1f72c6be4 --- /dev/null +++ b/locales/fr/Interoperability/4_Executable/executable.md @@ -0,0 +1,27 @@ +The Axelar executable contains relevant helper functions that will be automatically executed on the destination chain in correspondence to the relevant inbound transaction from the source chain. + +The following are the relevant functions you will need to use from Axelar Executable + +## \_execute() + +This function handles the execution on the destination chain. It takes the following four parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent + +The `sourceChain` and `sourceAddress` are key parameters which you receive out of the box that can be used for verifying authenticity of messages on the destination chain. The payload (as discussed in the gateway section) is the message that was sent from the source chain to be used on your destination chain. The `commandId` will not be used during the rest of this module. + +## \_executeWithToken() + +This function handles the execution on the destination chain for a message being sent with a fungible token. It takes six relevant parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent +5. `tokenSymbol`: The symbol of the token being sent +6. `amount`: The amount of that token that is being sent + +The first four parameters are identical to that of the `_execute()` function. The final two parameters of `tokenSymbol` and `amount` are in reference to the token that is being sent along with the message. It allows you on the destination chain to interact with the token accordingly, for example transferring it to another receiving address. The `commandId` will not be used during the rest of this module. diff --git a/locales/fr/Interoperability/5_InterchainMessage/interchainMessage.md b/locales/fr/Interoperability/5_InterchainMessage/interchainMessage.md new file mode 100644 index 000000000..029f642ce --- /dev/null +++ b/locales/fr/Interoperability/5_InterchainMessage/interchainMessage.md @@ -0,0 +1,53 @@ +In this section we will create a contract that will send a "hello world" message between two blockchains. + +## Constructor + +The first thing you will need to create is the `constructor` for the function. This will allow you to set the `Gateway` and `Gas Service` contracts we discussed in the previous sections. + +When deploying the contract you will pass in the address of the `Gateway` and `GasService` for Ethereum Sepolia those addresses are `0xe432150cce91c13a887f7D836923d5597adD8E31` for the Gateway and `0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6` for the Gas Service. + +For the full list of relevant Axelar addresses see here + +## Send Interchain Message + +Now that the constructor has set the relevant Axelar addresses needed to trigger an interchain transaction you can move on to the `setRemoteValue()`, which will trigger this transaction. + +This function takes three parameters: + +1. `_destinationChain`: The chain which the transaction is going to +2. `_destinationAddress`: The address on the destination chain the transaction will execute at +3. `_message`: The message being passed to the destination chain + +First, you have a `require` statement which ensures that the `msg.value` contains a value. This `msg.value` will be used to pay the `GasService`. If no funds were sent, then the transaction should be reverted as the transaction cannot execute on the Axelar blockchain and destination chain without any gas. + +Next, you encode the `_message` that was passed in. Notice that the `_message` is set as a `string` type. Axelar expects this message to be submitted as a `bytes` type so to convert the `string` to `bytes` you simply pass it through `abi.encode()`. + +Now, with your message encoded you can begin to interact with the `GasService` and the `Gateway` + +To pay for the entire interchain transaction you will trigger the function `payNativeGasForContractCall`, which is defined in the `GasService`. + +This function needs the parameters explained earlier in the GasService section. The `sender` for this transaction will be this contract, which is `address(this)`. The `destinationChain` and `destinationAddress` can simply be passed in from this functions parameters, the `payload` is the encoded \_message we wrote earlier. Finally, you need to specify what the refund address is, this can be the address that triggers this function, which you get by writing `msg.sender`. + +Once you trigger this function you will have successfully sent a transaction from the source chain via Axelar to the destination chain! But there is still one final step that needs to be complete. + +### Receive Message on Destination Chain + +On the destination chain the inbound interchain transaction needs to be picked up and handled by the `AxelarExecutable`'s `_execute()` function. + +The `_execute()` function is defined in the `AxelarExecutable` contract so when defining this function you must remember to include the `override` keyword. + +This function takes three parameters. + +1. `_sourceChain`: The blockchain which the transaction has originated from +2. `_sourceAddress`: The address on the source chain which the transaction has been sent from +3. `_payload`: The message that has been sent from the source chain + +The first thing that needs to be done in this contract is to get access to your `message` that was sent. Recall, before sending the message it was sent through `abi.encode()` to convert the message from type `string` to type `bytes`. To convert your message back from type `bytes` to type `string` simply pass the `_payload` to the function `abi.decode()` and specify that you want the `_payload` decoded to type `string`. This will return the message as a string. + +Now that you have your message as a type string you can set the `sourceChain` and `sourceAddress` storage variables as `_sourceChain` and `_sourceAddress` to have an easy reference to the data that was passed in. You can also emit the `Executed` event with the `sourceAddress` and `message` event that you just decoded. + +Great! At this point you are now handling the interchain transaction on the destination chain. + +To interact with this contract make sure you deploy it on at least two blockchains so that you can call `setRemoteValue()` from the one chain and then have the `_execute()` function automatically triggered on another chain. You will be able to query the `sourceChain` and `sourceAddress` variables on the destination chain to ensure that the interchain execution worked correctly. + +To view the full step by step of the interchain transaction checkout the Axelarscan (testnet) block explorer. diff --git a/locales/fr/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md b/locales/fr/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md new file mode 100644 index 000000000..11915eb32 --- /dev/null +++ b/locales/fr/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md @@ -0,0 +1,39 @@ +At this point we have gone over an example of how to send a general message between one blockchain to another. Now, let's implement a contract that sends a message and a token from one blockchain to another. + +## Overview + +This contract should seem largely familiar. Much like the previous section the `constructor` receives the `Gateway` and `Gas Service` addresses. + +It then has a function that will be called from the source chain called `sendToMany` that takes in parameters similar to the previous section. + +1. `_destinationChain`: The chain the transaction is sending to +2. `_destinationAddress`: The address on the destination chain your transaction is sending to +3. `_destinationAddresses`: The message that you will be sending along with your token transfer. In this example the message is a list of receiving addresses for the token transfer. +4. `_symbol`: The symbol of the token address being sent +5. `_amount`: The amount of the token being sent + +In the function we already have the `require` statement implemented to ensure gas is sent + +We also have the basic ERC20 functionality to send the token from the calling wallet to this smart contract. The contract also calls the `approve` function to allow the Gateway to eventually transfer funds on its behalf. + +Finally, the `_executeWithToken()` function is also implemented out of the box. + +It makes use of the following params: + +1. `_payload`: The incoming message from the source chain +2. `_tokenSymbol`: The symbol of the token that was sent from the source chain +3. `_amount`: The amount of the token that was sent from the source chain + +Now with these params that were passed in, the `_execute()` function can send the tokens that were sent to the appropriate receivers. + +## Challenge + +Your challenge here is to finish off the `sendToMany()` function using the Axelar Gateway and Gas Service to trigger an interchain transaction. + +In the end you should be able to deploy this contract on two testnets, trigger the `sendToMany()` function and see the live transaction on Axelarscan (testnet) block explorer. + +### Testing Notes + +Note 1: The recommended ERC20 to use is `aUSDC` a wrapped version of the USDC token that can be obtained from the discord faucet bot. When triggering the `sendToMany()` function simply pass in the symbol `aUSDC` to the fourth param. + +Note2: When triggering the `sendToMany()` function you must remember to `approve` your contract to spend `aUSDC` tokens on your behalf, otherwise `transferFrom()` on line49 will throw an error. diff --git a/locales/fr/Interoperability/7_FurtherReading/furtherReading.md b/locales/fr/Interoperability/7_FurtherReading/furtherReading.md new file mode 100644 index 000000000..a601d7ac7 --- /dev/null +++ b/locales/fr/Interoperability/7_FurtherReading/furtherReading.md @@ -0,0 +1,11 @@ +Congratulations on making it to the end of the interoperability module! 🎉🎉 + +To continue your learning journey of interoperability with Axelar. There are many useful resources available. + +- For documentation 📚 + +- For more technical examples 💻 + +- For live coding demos 📹 + +- For the developer blog 📝 diff --git a/locales/fr/Interoperability/README.md b/locales/fr/Interoperability/README.md new file mode 100644 index 000000000..a43fc5dd5 --- /dev/null +++ b/locales/fr/Interoperability/README.md @@ -0,0 +1,3 @@ +## Interoperability Between Blockchains + +Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. diff --git a/locales/fr/Interoperability/config.yml b/locales/fr/Interoperability/config.yml new file mode 100644 index 000000000..39f1be7ed --- /dev/null +++ b/locales/fr/Interoperability/config.yml @@ -0,0 +1,31 @@ +--- +id: interopCourse +name: Multichain Protocols with Axelar +summary: Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. +level: 2 +tags: + - Solidity + - Interoperability + - Axelar +steps: + - + name: An Intro to Axelar + path: 1_Intro + - + name: Axelar Gateway + path: 2_Gateway + - + name: Axelar Gas Service + path: 3_GasService + - + name: Axelar Executable + path: 4_Executable + - + name: Interchain Messages + path: 5_InterchainMessage + - + name: Interchain Token Transfers + path: 6_InterchainTokenTransfer + - + name: Further Reading + path: 7_FurtherReading diff --git a/locales/fr/Multisig-Tutorial/1-multisig-introduction/introduction.md b/locales/fr/Multisig-Tutorial/1-multisig-introduction/introduction.md new file mode 100644 index 000000000..3e9f18938 --- /dev/null +++ b/locales/fr/Multisig-Tutorial/1-multisig-introduction/introduction.md @@ -0,0 +1,41 @@ +Welcome to the Multisignature Wallet course! In this section, we'll explore the fundamentals of Multisignature (Multisig) wallets and we'll go through a multisig wallet contract. + +## What is a Multisignature Wallet? + +A multisignature (multisig) wallet is a type of digital wallet that requires multiple keys to authorize a cryptocurrency transaction. + +Imagine a multisig wallet as a secure vault with multiple locks. To open the vault, each keyholder must open their individual lock. This setup ensures that no single person can access the vault's contents without the others' consent. + +## How Does a Multisig Wallet Work? + +In a multisig setup, each transaction must receive a predetermined number of approvals from a set group of individuals. For instance, in a 3-of-5 wallet configuration, there are five authorized addresses, but a transaction only goes through when at least three of them give their approval. When a transaction is initiated, it's presented as a **proposal** to the group. Each member who agrees to the transaction uses their private key to digitally sign it. + +These **digital signatures** are unique and are generated based on the combination of the transaction data and the private key. + +When the required number of signatures is reached, the transaction is broadcasted to the blockchain for execution. + +## Why Use a Multisig Wallet? + +Multisig wallets are crucial for enhanced security in cryptocurrency transactions. They mitigate the risk of theft or loss of a single key. In business, they're used to ensure that funds can't be moved without consensus among stakeholders. For instance, in a company managing cryptocurrency assets, a multisig wallet might require the CFO, CEO, and a board member to all approve significant transactions, protecting against internal fraud or external hacks. + +## Conclusion + +In this section, we learned that a multisig wallet requires multiple keys to authorize a proposed cryptocurrency transaction and that a multisigs mitigates the risk of theft or loss of a single key. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is a Multisignature Wallet? + +1. A digital wallet that requires a single signature for transactions. +2. A digital wallet that requires multiple signatures for transactions. +3. A physical wallet used for storing cryptocurrency. +4. A wallet that can only hold multiple types of cryptocurrencies. + +### 2) How does a Multisignature Wallet enhance security? + +1. By requiring a single private key for transactions. +2. By distributing transaction approval across multiple owners. +3. By storing transaction data on-chain. +4. None of the above. + +Feel free to take your time and answer the questions above. Once you're ready, we'll move on to exploring the Multisig smart contract and understanding its structure. diff --git a/locales/fr/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md b/locales/fr/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md new file mode 100644 index 000000000..17b0a924f --- /dev/null +++ b/locales/fr/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md @@ -0,0 +1,60 @@ +In this section, we'll explore the **initialization process** of the Multisig smart contract. We'll examine the constructor function and review how it sets up the initial state of the contract. + +## Note + +From this section on in this tutorial, we will be building up a multisig contract. In subsequent sections, the contract will become increasingly complete. + +## Overview + +In this section, the contract consists of events, state variables, modifiers, and functions. **Events** provide transparency by logging specified activities on the blockchain, while **modifiers** ensure that only authorized users can execute certain functions. + +## State Variables + +In Line 4, we have the MultisigWallet contract itself. At the beginning of the contract, we have three state variables. + +1. **`owners`:** An array containing the addresses of all owners of the multi-signature wallet (Line 5). +2. **`isOwner`:** A mapping indicating whether an address is an owner (Line 6). +3. **`numConfirmationsRequired`:** The number of confirmations required for a transaction (Line 7). + +The setup of array and mapping allows us to easily retrieve the list of owners and verify whether an address is an owner. + +## Modifiers + +Next, we have a modifier called `onlyOwner` (Line 9). Modifiers in Solidity are special keywords that can be used to amend the behavior of functions. In our case, the `onlyOwner` modifier ensures that only owners can execute a function. It does this by checking whether the address of the **caller** is an owner. + +## Constructor Function + +The `constructor` function (Line 14) is executed only once during the deployment of the contract. It initializes essential parameters, in this case, the list of owners and the required number of confirmations (Line 14). + +On lines 15 and 16, we have two `require` statements to ensure that the inputs are valid. In this case, we require that there must be at least one owner and that the number of required confirmations must be greater than zero and less than or equal to the number of owners. + +The constructor then initializes the contract state by verifying that is not address(0) (Line 25) and that the owner is unique (Line 26). Then it adds a key/ value pair to the isOwner mapping (Line 28), and then it populates the `owners` array with the provided owner addresses (Line 29). + +Finally, it sets the `numConfirmationsRequired` variable with the specified value (Line 32). + +## getOwners Function + +The `getOwners` function (Line 36) allows users to retrieve the list of owners of the multi-signature wallet. It returns the `owners` array (Line 37). + +## getNumConfirmationsRequired Function + +The `getNumConfirmationsRequired` function (Line 41) allows users to retrieve the number of confirmations required for a transaction. It returns the `numConfirmationsRequired` variable (Line 42). + +## Conclusion + +In this section, we explored the initialization process of the Multisig smart contract. We examined the constructor function and understood how it sets up the initial state of the contract. + +## ⭐️ Assignment: Deploy a Multisig Wallet + +Deploy a Multisig contract with three owners and require two confirmations for transaction execution. + +1. Compile contractInitialization.sol +2. Go to Deploy & Run Transactions in Remix. +3. Expand the "Deploy" section. +4. Under "_OWNERS", enter three an array of three addresses. +5. Under "_NUM_CONFIRMATIONS_REQUIRED", enter the number of confirmations required for a transaction. + +**Hints:** + +- You can get addresses from the "ACCOUNTS" dropdown menu. +- The array of addresses should be in the format: ["0x123...", "0x456...", "0x789..."]. diff --git a/locales/fr/Multisig-Tutorial/3-multisig-deposits/deposits.md b/locales/fr/Multisig-Tutorial/3-multisig-deposits/deposits.md new file mode 100644 index 000000000..a8a14213b --- /dev/null +++ b/locales/fr/Multisig-Tutorial/3-multisig-deposits/deposits.md @@ -0,0 +1,34 @@ +In this section, we'll explore the `receive` function and the associated Deposit event. We'll examine how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## Deposit Event + +On line, 9 we have the Deposit event. The Deposit event is emitted whenever Ether is deposited into the multi-signature wallet. It includes three parameters: + +1. `sender`: The address that sent the Ether. +2. `amount`: The amount of Ether deposited. +3. `balance`: The updated balance of the contract after the deposit. + +We can use the Deposit event to track the flow of Ether into the multi-signature wallet and maybe trigger other actions based on the event. + +## receive Function + +On line 43, we have the `receive` function. The `receive` function is a special function that is executed whenever Ether is sent to the contract. + +The `receive` function is marked as `external` and `payable`. The `external` modifier means that the function can only be called from outside the contract. The `payable` modifier means that the function can receive Ether. + +The `receive` function emits the Deposit event (Line 44) with the address of the sender, the amount of Ether sent, and the updated balance of the contract. It doesn't return anything. + +To receive Ether, a contract must have a `receive`, `fallback`, or a function with the `payable` modifier. If none of these are present, the contract will reject any Ether sent to it. + +## Conclusion + +In this section, we explored the `receive` function and the associated Deposit event. We examined how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## ⭐️ Assignment: Deposit Ether + +Deposit 2 Ether into the Multisig contract. + +1. Deploy the Multisig contract as in the previous assignment. +2. Enter a Value of 2 Ether in the Value field and select Ether in the dropdown menu. +3. At the bottom of your deployed contract in the "Low level interactions" section, click on the "Transact" button. +4. On top of your deployed contract, it should now say "Balance: 2 Ether". diff --git a/locales/fr/Multisig-Tutorial/4-multisig-transactions/transactions.md b/locales/fr/Multisig-Tutorial/4-multisig-transactions/transactions.md new file mode 100644 index 000000000..f62fd48a0 --- /dev/null +++ b/locales/fr/Multisig-Tutorial/4-multisig-transactions/transactions.md @@ -0,0 +1,73 @@ +In this section, we'll explore the process of submitting and confirming transactions. + +## Modifiers + +We have new modifiers in this iteration of the contract. Let's examine them one by one. + +1. **`txExists` modifier:** (Line 13) ensures that the transaction exists. It does this by checking whether the transaction index is less than the length of the `transactions` array. We'll go into more about in this modifier later in this section. +2. **`notExecuted` modifier:** (Line 18) ensures that the transaction has not been executed. It does this by checking whether the `executed` variable of the transaction is false. +3. **`notConfirmed` modifier:** (Line 23) ensures that the transaction has not been confirmed by the caller. It does this by checking whether the `isConfirmed` mapping of the transaction index and the caller's address is false. + +## Transaction Struct + +On line 28, we have a struct called `Transaction`. We store the struct members: `to`, `value`, `data`, `executed`, and `numConfirmations` in individual variables. + +## Mapping of Confirmations + +On line 37, we have a mapping called `isConfirmed`. This mapping is used to keep track of the confirmations of each transaction. It maps the transaction's index to a mapping of an owner addresse to a boolean value. The boolean value indicates whether this owner has confirmed the transaction. + +## Transactions Array + +On line 39, we have an array called `transactions`. The array is used to store all the transactions submitted to the multi-signature wallet. + +## Events + +We have four new events in this iteration of the contract: + +1. **`SubmitTransaction` event:** emitted whenever a transaction is submitted to the multi-signature wallet. +2. **`ConfirmTransaction` event:** emitted whenever a transaction is confirmed by an owner. +3. **`RevokeConfirmation` event:** emitted whenever a transaction confirmation is revoked by an owner. +4. **`ExecuteTransaction` event:** emitted whenever a transaction is executed. + +## submitTransaction Function + +The `submitTransaction` function (Line 78) allows users to submit a transaction to the multi-sig wallet. It takes three parameters: `to`, `value`, and `data`. The `to` parameter is the address of the recipient of the transaction. The `value` parameter is the amount of Ether to be sent. The `data` parameter is the data to be sent to the recipient. Only owners can submit transactions. + +On line, 85 we create a new transaction struct and push it to the `transactions` array and emit the `SubmitTransaction` event. The `txIndex` variable is used to keep track of the transaction index. + +## confirmTransaction Function + +The `confirmTransaction` function (Line 98) allows users to confirm a transaction. It takes one parameter: `txIndex`. +It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. The `onlyOwner` modifier ensures that only owners can confirm transactions. The `txExists` modifier ensures that the transaction exists. The `notExecuted` modifier ensures that the transaction has not been executed. + +On line 101, we store the transaction in a local variable called `transaction`. We then increment the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to true. Finally, we emit the `ConfirmTransaction` event. + +## executeTransaction Function + +The `executeTransaction` function (Line 108) allows users to execute a transaction. On line 113, we require that the number of confirmations of the transaction is greater than or equal to the required number of confirmations. We then set the `executed` variable of the transaction to true. Finally, send the funds using the `call` function. This is the `call` of the recipient address with the value and data of the transaction. If the transaction is successful, we emit the `ExecuteTransaction` event. + +## getTransactionCount Function + +The `getTransactionCount` function (Line 132) allows users to retrieve the number of transactions in the multi-signature wallet. It returns the length of the `transactions` array. + +## getTransaction Function + +The `getTransaction` function (Line 136) allows users to retrieve a transaction. It returns the transaction struct members that we explored earlier in this section. + +## Conclusion + +In this section, we explored the process of submitting, confirming, and executing transactions. We examined the `submitTransaction`, `confirmTransaction`, and `executeTransaction` functions and understood how they work together to allow multiple users to submit and confirm transactions. + +## ⭐️ Assignment: Make a Transaction + +Submit, confirm, and execute a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. Deploy the Multisig contract as in the previous assignment. Make sure that the required number of confirmations is 2. +2. Fund the multisig from any address by sending 4 Ether as you did in the previous assignment. +3. Try sending 2 Ether to the first account in the "ACCOUNTS" dropdown menu. Once you have submitted this transaction (with submitTransaction), click on `getTransactionCount` and should see one transaction or you can click on `getTransaction`, insert 0 as the transaction index and see the transaction you just submitted. +4. Now you can click on `confirmTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. +5. Switch to the second owner account and confirm the transaction again. If you click on `getTransaction` again, you should see that the transaction has been confirmed twice. +6. The last step is to execute the transaction. Click on `executeTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been executed. You can also check the balance of the first account in the "ACCOUNTS" dropdown menu. It should now be 2 Ether higher and the balance of the multi-signature wallet should be 2 Ether lower. + +**Hint:** +If you submit a transaction make sure that the value is in Wei and that the _data field is correctly filled in. E.g. it could look like this: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 2000000000000000000, 0x" for 2 Ether. diff --git a/locales/fr/Multisig-Tutorial/5-multisig-revoke/revoke.md b/locales/fr/Multisig-Tutorial/5-multisig-revoke/revoke.md new file mode 100644 index 000000000..1bf085343 --- /dev/null +++ b/locales/fr/Multisig-Tutorial/5-multisig-revoke/revoke.md @@ -0,0 +1,30 @@ +In this section, we'll explore the process of revoking confirmations. This process is necessary when an owner changes their mind about a transaction and wants to stop it from being executed. This section will be pretty straightforward. + +## revokeConfirmation Event + +On line 14, we have added the `RevokeConfirmation` event. This event is emitted whenever a transaction confirmation is revoked by an owner. + +## revokeConfirmation Function + +On line 129, we have added the `revokeConfirmation` function. It allows users to revoke a transaction confirmation. + +`revokeConfirmation` takes one parameter: `txIndex`. It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. + +On line 134, we require that the transaction has been confirmed by the caller. This ensures that an owner who has confirmed the transaction can only revoke their own confirmation. +We then decrement the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to false. Finally, we emit the `RevokeConfirmation` event. + +## Conclusion + +In this section, we explored the process of revoking confirmations. We examined the `revokeConfirmation` function and understood how it works to allow users to revoke confirmations. + +## ⭐️ Assignment: Revoke a Confirmation + +Confirm and revoke a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. As in the previous assignment, deploy the Multisig contract, send the contract some Ether, and then submit a transaction to the first account in the "ACCOUNTS" dropdown menu with a value of 2 Ether. +2. Confirm the transaction twice as in the previous assignment. +3. Revoke the transaction by clicking on `revokeConfirmation` and inserting 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. + +## Final Conclusion + +In this tutorial, we explored the process of creating a multi-signature wallet. We learned how to initialize the contract, deposit Ether, submit, confirm, and revoke transactions. We also learned how to execute transactions and retrieve information about the multi-signature wallet. diff --git a/locales/fr/Multisig-Tutorial/README.md b/locales/fr/Multisig-Tutorial/README.md new file mode 100644 index 000000000..ae5997802 --- /dev/null +++ b/locales/fr/Multisig-Tutorial/README.md @@ -0,0 +1,5 @@ +## MultiSig Wallet + +Learn how to write a MultiSig Wallet smart contract on Ethereum. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/fr/Multisig-Tutorial/config.yml b/locales/fr/Multisig-Tutorial/config.yml new file mode 100644 index 000000000..067de0fb9 --- /dev/null +++ b/locales/fr/Multisig-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: multisigCourse +name: Multisig Wallet +summary: Learn how to create and interact with a multisig wallet. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - Multisig +steps: + - + name: 1. Introduction + path: 1-multisig-introduction + - + name: 2. Initialize the Contract + path: 2-multisig-initialization + - + name: 3. Deposits + path: 3-multisig-deposits + - + name: 4. Transactions + path: 4-multisig-transactions + - + name: 5. Revoking Confirmations + path: 5-multisig-revoke diff --git a/locales/fr/NFTTokenCourse/README.md b/locales/fr/NFTTokenCourse/README.md new file mode 100644 index 000000000..c3d2a183a --- /dev/null +++ b/locales/fr/NFTTokenCourse/README.md @@ -0,0 +1,5 @@ +## Solidity NFT Course + +Learn how to create your own NFTs (non-fungible tokens). + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/fr/NFTTokenCourse/config.yml b/locales/fr/NFTTokenCourse/config.yml new file mode 100644 index 000000000..af82db834 --- /dev/null +++ b/locales/fr/NFTTokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: nftTokenCourse +name: Solidity NFT Course +summary: Learn how to create your own NFT tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc721-interface + - + name: 3. Metadata Interface + path: erc721-interface-metadata + - + name: 4. Token Creation + path: erc721-token-creation + - + name: 5. Metadata IPFS + path: erc721-metadata-ipfs + - + name: 6. Deploy to Testnet + path: erc721-deploy-testnet-opensea diff --git a/locales/fr/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md b/locales/fr/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md new file mode 100644 index 000000000..40576500c --- /dev/null +++ b/locales/fr/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md @@ -0,0 +1,50 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to the Rinkeby testnet of the Ethereum blockchain, mint an NFT, and look at it on the NFT marketplace OpenSea. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token for Rinkeby + +In order to make transactions on the testnet, we need Ethereum testnet tokens. + +**2.1** Switch your Metamask from "Ethereum Mainnetwork" to "Rinkeby Test Network". + +**2.2** Go to https://faucet.paradigm.xyz/, enter the address of your account and claim testnet ETH. +You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Contract Deployment + +**3.1** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It should then ask you to connect your account, which you should confirm. Then you should see the Rinkeby network badge under "Injected Web3". + +**3.2** Deploy your token contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. + +### 4. Mint an NFT + +**4.1** Expand your contract in the IDE so you can see the buttons for the functions. + +**4.2** Expand the input fields next to the safeMint button. Enter the Ethereum address of the account that is connected to Remix in the “to:” input field. Enter “0” in the input field "tokenID:". Click on transact. + +**4.3** In Metamask click on assets, then click on the “Import tokens” link, and paste the address of your contract in the input field. You can set decimals to 0. + +You should now see the name of the symbol of your token contract (e.g. GEO) in your “Assets” view in Metamask. You should have one of these tokens. + +### 5. See your NFT on OpenSea + +OpenSea is one of the most popular online marketplace for NFTs. OpenSea also provides a version where you can see assets on the testnet, under https://testnets.opensea.io/ + +**5.1** Go to https://testnets.opensea.io/login. + +**5.2** Connect with your Metamask wallet. You should be redirected to your account https://testnets.opensea.io/account view on OpenSea, where you should be able to see your NFT. You should see the image of your NFT; when you click on it, you should see the name, description, and under properties, also the attributes that you created. + +If you successfully completed this course and are familiar with the basics of Solidity development, we encourage you to continue your learning journey by learning how to create your own NFT auction contract from the Learneth resources. diff --git a/locales/fr/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md b/locales/fr/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md new file mode 100644 index 000000000..a43162feb --- /dev/null +++ b/locales/fr/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md @@ -0,0 +1,44 @@ +The metadata extension is optional. It allows us to add additional information to our ERC721 tokens. We can specify a name, a symbol, and an URI (Uniform Resource Identifier) that can point to a file where we can add even more information in the form of a JSON. + +## ERC721 Metadata Functions + +### name + +The function `name` (line 16) returns the name of the token collection. A token collection means all tokens created with your ERC721 token contract implementation. Every token in this collection will have this name, regardless of their tokenId. + +### symbol + +The function `symbol` (line 21) returns the symbol of the token collection. + +### tokenURI + +The function `tokenURI` (line 26) returns the URI for the token with the id `tokenId`. In this case it’s not the URI of the whole collection but of an individual token in the collection. + +## ERC721 Metadata JSON Schema + +The file that the tokenURI points to should conform to the Metadata JSON Schema as it is specified in the EIP-721. + +``` +{ + "title": "Asset Metadata", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Identifies the asset to which this NFT represents" + }, + "description": { + "type": "string", + "description": "Describes the asset to which this NFT represents" + }, + "image": { + "type": "string", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." + } + } +} +``` + +The root element must be of the type object. This root object should have properties with the keys: name, description, and image that should be all of the type string. + +The ERC721 standard is pretty flexible, the tokenURI does not need to point to a JSON document and the JSON does not need to have all properties and often has additional properties. diff --git a/locales/fr/NFTTokenCourse/erc721-interface/erc721Interface.md b/locales/fr/NFTTokenCourse/erc721-interface/erc721Interface.md new file mode 100644 index 000000000..468e8e640 --- /dev/null +++ b/locales/fr/NFTTokenCourse/erc721-interface/erc721Interface.md @@ -0,0 +1,100 @@ +ERC721 is a standard for token contracts that manage non-fungible tokens (NFTs) on the Ethereum blockchain. + +Each non-fungible token is unique and not interchangeable. NFTs can have different properties, behavior, or rights. Non-fungible tokens are used to represent ownership of unique digital and physical assets like art, collectibles, or real estate. + +If you want to know more about the ERC721 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +The ERC721 standard is more complex than the ERC20 standard and it features optional extensions. ERC721 compliant contracts must, at a minimum, implement the ERC721 and ERC165 interfaces, which we will look at in this section. + +This interface (line 11) is part of the open-source contract library provided by OpenZeppelin. + +## Basic IERC721 Functions + +Contracts compliant with the ERC721 standard have to implement the following functions: + +### balanceOf + +The function `balanceOf` (line 30) returns the amount of tokens owned by the account with the address `owner`. + +### ownerOf + +The function `ownerOf` (line 39) returns the address `owner` of the account that holds the token with the id `tokenId`. + +### safeTransferFrom + +The function `safeTransferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +The function `safeTransferFrom` (line 137) is almost identical to the function `safeTransferFrom` (line 55) .The only difference is that this function has a non-empty payload `data`. + +A smart contract must implement the ERC721TokenReceiver Interface if it is to receive a transfer. This will ensure that the contract can handle ERC721 token transfers and prevent the tokens from being locked in a contract that can’t. + +### transferFrom + +The function `transferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +**It is recommended to use safeTransferFrom instead of transferFrom whenever possible.** +The `transferFrom` function is not secure because it doesn’t check if the smart contract that is the recipient of the transfer has implemented the ERC721TokenReceiver interface and is capable of handling ERC721 tokens. + +## Advanced IERC721 Functions + +### approve + +The function `approve` (line 94) gives the account with the address `to` the permission to manage the token with the id `tokenId` on behalf of the account calling the function. + +### getApproved + +The function `getApproved` (line 103) returns the address of the account (return var `operator`) that is approved to manage the token with the id `tokenId`. + +### setApprovalForAll + +The function `setApprovalForAll` (line 115) sets the permission (`_approved`) for the account with the specified address (input param - `operator`) to manage all tokens of the account calling the function. + +### isApprovedForAll + +The function `getApproved` (line 103) returns the boolean true if the account with the address `operator` is approved to manage all tokens of the account with the address `owner`. + +## IERC721 Events + +ERC721 contracts must also emit the following events: + +### Transfer + +The `Transfer` event (line 15) must be emitted when the token with the id `tokenId` is transferred from the account with the address `from` to the account with the address `to`. + +### Approval + +The `Approval` event (line 20) must be emitted when the account with the address `owner` approves the account with the address `spender` to manage the token with the id `tokenId` on its behalf. + +### ApprovalForAll + +The `ApprovalForAll` event (line 25) must be emitted when the account with the address `owner` gives or removes the permission (`_approved`) of the account with the address `operator` to manage all its tokens. + +## IERC165 + +In addition to the ERC721 interface, ERC721 compliant contracts must also implement the ERC165 interface. + +With the implementation of the ERC165 interface, contracts can declare the support of specific interfaces. A contract that wants to interact with another contract can then query if the other contract supports this interface before making a transaction e.g. sending tokens to it that they might not support. + +Our IERC721 interface here imports (line 6) and inherits (line 11) from the IERC165 interface. + +This is how OpenZeppelins implementation of the ERC165 interface looks like: + +``` +interface IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +For example, the ERC165 identifier for the ERC721 interface as specified in the EIP721 is “0x80ac58cd”. Learn how to calculate an interface identifier and more about the ERC165 in its improvement proposal. + +## Other interfaces + +The IERC721TokenReceiver interface must be implemented to accept safe transfers. + +There are two optional extensions for ERC721 contracts specified in the EIP721: + +IERC721Enumerable enables a contract to publish its full list of tokens and make them discoverable. + +IERC721Metadata enables a contract to associate additional information to a token. We will have a more detailed look into this in the next section. diff --git a/locales/fr/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md b/locales/fr/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md new file mode 100644 index 000000000..27876b068 --- /dev/null +++ b/locales/fr/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md @@ -0,0 +1,101 @@ +In this section, we will create our metadata and store it in a decentralized way. + +IPFS ( InterPlanetary File System) is a peer-to-peer network for storing files in a distributed way. Pinata.cloud is a pinning service that allows users to easily host files on the IPFS network. + +We want to host our images and the JSON files with their metadata on IPFS. + +### Create Image Folder + +In this example, we will create metadata for three tokens. As you can see below, we create three images that we stored in a folder. + +``` +geo-img +├── geo_1.png +├── geo_2.png +├── geo_3.png +``` + +### Register on Pinata + +Now, we want to host these images somewhere so we can point to them in the metadata of our tokens. Let's do it in a decentralized way and use Pinata to host them on IPFS. + +First you need an account on Pinata. Go to Pinata.cloud and create an account. On Pinata you can upload up to 1 GB of data for free. + +Once you have signed up, you should be in the Pin Manager view. + +Pin Manager Pinata + +### Upload Images to IPFS + +Click on the upload button and upload the folder with your images. +Once you've uploaded your folder, you should see the name of your folder and the CID (content identifier) associated with it. If the content in the folder changes, the CID will also change. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P + +You can access a specific image by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png + +### Create JSON files + +We create another folder where we store three JSON files. + +``` +geo-json +├── 0 +├── 1 +├── 2 +``` + +Inside the JSON files, create the metadata for the tokens, like name, description, and image. +For the image URL, we are going to use the URL of our images on IPFS. You can add additional data if you like; in this example, we added some unique attributes for each token. + +This is how the JSON for the first token could look: + +``` +{ + "name": "Geometry#0", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png +", + "attributes": [ + { "trait_type": "background", "value": "cyan" }, + { "trait_type": "color", "value": "red" }, + { "trait_type": "shape", "value": "circle" } + ] +} +``` + +This is how the JSON for the second token could look: + +``` +{ + "name": "Geometry#1", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_2.png", + "attributes": [ + { "trait_type": "background", "value": "magenta" }, + { "trait_type": "color", "value": "green" }, + { "trait_type": "shape", "value": "square" } + ] +} +``` + +As shown above, the folder in this example is called "geo-json". Inside this folder, we have three JSON files. +The first JSON file is called "0", the second JSON file is called "1", and the third JSON file is called "2". + +Make sure that your JSON files don't have a file ending and are named like their corresponding tokenIds. +In the pin manager on pinata.cloud, click on the upload button and upload the folder with your JSON files. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. +For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp +This will become our baseURI. + +You can access a specific JSON file then by just adding a slash and the tokenId by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/0 + +In the contract, replace the baseURI with your own baseURI. In this example, the baseURI consists of the URL +"https://ipfs.io/ipfs/", the CID containing the JSON files, and a slash at the end "/". + +An individual tokenURI will now be created for each token by adding the tokenId to the baseURI — exactly what we did manually in the example above to access the JSON file. diff --git a/locales/fr/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md b/locales/fr/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md new file mode 100644 index 000000000..891fe00a7 --- /dev/null +++ b/locales/fr/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md @@ -0,0 +1,35 @@ +In this contract, we use an ERC721 token contract implementation from OpenZeppelin (line 4). + +Have a look at their implementation of a ERC721 contract. Apart from the functionality specified in the ERC721 standard, the contract provides additional functions which we will see in a bit. + +## myToken + +We create our own contract called MyToken (line 7), which inherits (line 7) the functionality from the OpenZepplin `ERC721` token contract implementation and `Ownable` that we imported (line 4). If you don't remember the Ownable contract module, have a look at the ERC20 extensions section. + +This ERC721 implementation makes use of the IERC721Metadata extension that is specified in the EIP. Our contract inherits the functions `name()` and `symbol()` +and has a constructor that allows their values to be set during the deployment of the contract (line 8). +In this case, we are going to use the default values. We name our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +### Base URI + +With an ERC721 contract, we are able to mint various tokens, each with its own tokenId. As we saw in the IERC721Metadata interface, each token can have its own `tokenURI`, which typically points to a JSON file to store metadata like name, description, and image link. +If a contract mints multiple tokens, ERC721 implementations often use the same URI as a base (`baseURI`) for all tokens and only differentiate them by adding their unique `tokenId` at the end via concatenation. In the next part, we will see what this looks like in practice. + +In this example, we are storing our data on IPFS — more on that in the next section. Our baseURI is https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/ (line 11). +Through concatenation the tokenURI for the token with the id 0 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/0 , the tokenURI for the token with the id 1 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/1, and so on. + +When using IPFS and you run into "504 Gateway Time-out" errors, you might have to wait and retry until the data is available. + +### safeMint + +With the safeMint function (line 14) we enable the owner to create new tokens with a dedicated token id after contract deployment. +The safeMint function is part of the ERC721 implementation of OpenZeppelin and lets us safely mint a token with the id `tokenId` to the account with the address `to`. For access control, we use the `onlyOwner` modifier from the Ownable access control contract module that we imported (line 5). + +In the next section, we will see how we can create and host the metadata for our NFTs. + +## ⭐️ Assignment + +1. Rename your contract to `Geometry`. +2. Rename your token to `Geometry`. +3. Change the symbol of your token to `GEO`. +4. Change the `_baseURI` to https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/. diff --git a/locales/fr/NFTTokenCourse/introduction/introduction.md b/locales/fr/NFTTokenCourse/introduction/introduction.md new file mode 100644 index 000000000..13beea567 --- /dev/null +++ b/locales/fr/NFTTokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with NFTs, tokens created with the ERC721 token standard. + +If you want to learn more about fungible tokens and the ERC20 token standard, have a look at the Learneth ERC20 Token Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain-based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/fr/OpcodesInTheDebugger/1_intro/step.md b/locales/fr/OpcodesInTheDebugger/1_intro/step.md new file mode 100644 index 000000000..c1d9a2448 --- /dev/null +++ b/locales/fr/OpcodesInTheDebugger/1_intro/step.md @@ -0,0 +1,5 @@ +This workshop aims to give a better understanding about how a contract get deployed. +`SimpleStore` is a very basic contract. +It has a very simple constructor - which just uses the first parameter `_o` and saves it to `s`. + +Using the debugger, we'll try to see, what the opcode `CODECOPY` does. diff --git a/locales/fr/OpcodesInTheDebugger/2_memory/step.md b/locales/fr/OpcodesInTheDebugger/2_memory/step.md new file mode 100644 index 000000000..577169a5e --- /dev/null +++ b/locales/fr/OpcodesInTheDebugger/2_memory/step.md @@ -0,0 +1,8 @@ +Before we start, just quick reminder: + +The runtime of the EVM has several kinds of memory: + +- `calldata`: This is the input value given to the transaction. +- `stack`: Basically, this is a list of values, each value is limited in size (32 bytes). +- `memory`: Memory is used when the **type** of value getting stored is more complex like an array or a mapping. This memory is **temporary** and is **released** at the end of the execution. +- `storage`: This is a mapping, each value stored is **persisted** and saved on chain. diff --git a/locales/fr/OpcodesInTheDebugger/3_codecopy/step.md b/locales/fr/OpcodesInTheDebugger/3_codecopy/step.md new file mode 100644 index 000000000..b0c9f7d52 --- /dev/null +++ b/locales/fr/OpcodesInTheDebugger/3_codecopy/step.md @@ -0,0 +1,7 @@ +CODECOPY is one of the many opcodes run by the EVM. Check out the complete list of opcodes at https://ethervm.io/ . + +CODECOPY takes the **running code** (or part of it) and to copies it from the `calldata` to the `memory`. + +The solidity implementation is: **codecopy(t, f, s)** - copy **s** bytes from code at position **f** to memory at position **t**. + +Every contract deployment uses **CODECOPY**. diff --git a/locales/fr/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md b/locales/fr/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md new file mode 100644 index 000000000..63950051d --- /dev/null +++ b/locales/fr/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md @@ -0,0 +1,11 @@ +Let's go back to our contract. +Please make sure the `solidity compiler` and `Deploy & Run Transactions` are activated. + +Alternatively, you can click on `Solidity` from the `Home Page` **Environments** section. + +- Compile the contract from the `solidity compiler`. +- Go to the `Deploy & Run Transactions` and make sure `SimpleStore` is selected contract. +- In the textbox to the right of `Deploy`, input a positive integer. +- Click on `Deploy`. + +In the next step, we'll watch the deployment in the debugger. diff --git a/locales/fr/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md b/locales/fr/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md new file mode 100644 index 000000000..3ef3cd146 --- /dev/null +++ b/locales/fr/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md @@ -0,0 +1,7 @@ +From the Remix terminal, identify the transaction that deployed the contract and click `Debug` + +In the gutter of the editor, put a breakpoint on the line `s = _o`, and click on `Jump to the next Breakpoint` (bottom right button). + +Click on `Step into`, to move along the opcodes until you reach `SSTORE`. + +`SSTORE` is the opcode for storing the value `_o` in the storage. Let's continue further to the `CODECOPY`. diff --git a/locales/fr/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md b/locales/fr/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md new file mode 100644 index 000000000..1480728e6 --- /dev/null +++ b/locales/fr/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md @@ -0,0 +1,57 @@ +The goal here is to store the code in the blockchain. The EVM needs to tell the client (geth, parity) which what part of the **Call Data** to store. In this step, we are saving the contract MINUS its constructor (because that gets inplmented only 1 time) and MINUS the input parameter does not need to be stored. + +`CODECOPY` is the first step: it copies the bytecode to memory, then the ethereum client will be able to consume it. MUNCH! + +But wait... before the client can **MUNCH** bytecode, it needs an instruction - an opcode to tell it to MUNCH. `RETURN` is this opcode! + +As stated in the general spec, at the end of the contract creation, the client (geth, parity) takes the targeted value by the opcode `RETURN` and **persists** it by making it part of the deployed bytecode. + +Once you are in the `CODECOPY`, look at the top 3 items in the **Stack**: + +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x0000000000000000000000000000000000000000000000000000000000000055` +`2: 0x000000000000000000000000000000000000000000000000000000000000003e` + +_In your Stack - `1` & `2` may be slightly different. The difference may be due to a different compiler version._ + +**These are the parameters for `CODECOPY`.** + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +`0` is the offset where the copied code should be placed in the **memory**. In this example, ( all zeros) the code is copied to the beginning of the memory. (**t**) +`1` is the offset in **calldata** where to copy from (**f**) +`2` number of bytes to copy - (**s**) + +After `CODECOPY` is executed, (click the _step into_ button) the copied code should be: +`0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c63430005110032` in memory. **I'll refer to this value as (X)**. + +Let's look at the debugger's **Memory** panel. +The 0x number I gave above is not what you will see in the **Memory** panel -what you will see is this: +0x0: 6080604052600080fdfea265627a7a72 ????R??????ebzzr +0x10: 31582029bb0975555a15a155e2cf28e0 1X ?? uUZ??U???? +0x20: 25c8d492f0613bfb5cbf96399f6dbd4e ?????a?????9?m?N +0x30: a6fc9164736f6c634300051100320000 ???dsolcC????2?? +0x40: 00000000000000000000000000000000 ???????????????? +0x50: 000000000000000000000000000000a0 ??????????????? +0x60: 00000000000000000000000000000000 ???????????????? +0x70: 00000000000000000000000000000000 ???????????????? +0x80: 00000000000000000000000000000000 ???????????????? +0x90: 00000000000000000000000000000002 ???????????????? + +The `0x0`, `0x10`, etc is the position. The next number is the bytecode for that position. This is followed by question marks and seemingly random letters & numbers. This is **Remix**'s attempt to convert this into a string. + +So if we glue the first four sections of bytecode together, we'll get: +**0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e0a6fc9164736f6c63430005110032** The last section - `0x90` has 2 which is what I input for the constructors parameter. + +The input data from the **Call Data** panel is: +`0x6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c634300051100320000000000000000000000000000000000000000000000000000000000000002` +**I'll refer to this value as (Y).** + +This shows us that `(X)` is a subset of the original calldata `(Y)`: + +`(X)` is calldata without the input parameter `0000000000000000000000000000000000000000000000000000000000000002` (we don't need to store this) +and without the constructor code `6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe` which should be executed only 1 time. + +So `CODECOPY` extracts the bytecode from the calldata and copies it to the memory. + +Let's move to the next step. diff --git a/locales/fr/OpcodesInTheDebugger/7_returnAndStore/step.md b/locales/fr/OpcodesInTheDebugger/7_returnAndStore/step.md new file mode 100644 index 000000000..b375a24fb --- /dev/null +++ b/locales/fr/OpcodesInTheDebugger/7_returnAndStore/step.md @@ -0,0 +1,18 @@ +# The Opcode RETURN + +At the end of the last chapter we had moved to one step after **CODECOPY** to see what happened in the memory. + +Now that CODECOPY has been executed, we are on the opcode `PUSH1 00`. + +`PUSH1 00` prepares the stack for the `RETURN` opcode. +`RETURN` is the last part of this process. It is where the code is returned to the client. + +We push `00` to the stack because this is the offset position of the contract bytecode in memory. + +Now we can call the all important `RETURN` opcode. + +The **stack inspector** shows: +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x000000000000000000000000000000000000000000000000000000000000003e` + +Which is to say it returns to the client the bytecode starting `0x00` with length `0x3e`. diff --git a/locales/fr/OpcodesInTheDebugger/8_findTheOffset/step.md b/locales/fr/OpcodesInTheDebugger/8_findTheOffset/step.md new file mode 100644 index 000000000..6b1ddc5cf --- /dev/null +++ b/locales/fr/OpcodesInTheDebugger/8_findTheOffset/step.md @@ -0,0 +1,18 @@ +# Find the offset ;) + +And now for a slightly different example: + +- Compile notSimpleStore.sol +- Deploy the contract `notSoSimpleStore` +- Make sure you have a successful deployment - if not check that you used **the correct input type** in the constructor. +- Go to the Debugger by clicking the **debug** button at the (successful) creation transaction. +- Find the value of the parameter of `CODECOPY` which represents the offset in calldata where to copy from. + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +If you look in the **Stack**, you should see that the 2nd element is: +0x0000000000000000000000000000000000000000000000000000000000000083 + +And this is the **f** of the input params of codecopy. + +### Hope you picked up a thing or 2 about how opcodes work! diff --git a/locales/fr/OpcodesInTheDebugger/config.yml b/locales/fr/OpcodesInTheDebugger/config.yml new file mode 100644 index 000000000..74a1bf3a1 --- /dev/null +++ b/locales/fr/OpcodesInTheDebugger/config.yml @@ -0,0 +1,10 @@ +--- +id: opcodesdebug +name: Opcodes in the Debugger +summary: Using the Debugger, we'll check out what the CODECOPY opcode does and how it is used by the EVM during contract creation. +level: 3 +tags: + - Remix + - Debugging + - EVM + - Opcodes diff --git a/locales/fr/ProxyContract/1_Why/step1.md b/locales/fr/ProxyContract/1_Why/step1.md new file mode 100644 index 000000000..b4a38aaeb --- /dev/null +++ b/locales/fr/ProxyContract/1_Why/step1.md @@ -0,0 +1,27 @@ +# Proxy Contract AKA the Dispatcher + +## Why? + +This is a great pattern that is used mainly in **library development**. + +It helps in the following ways: + +- **Save gas cost at deployment time** + The purpose of a high gas cost is to discourage the operations that cost a lot for their execution and to encourage optimized code. + +- Proxy contracts are useful when a lot of instances of the same contract need to be deployed because they reduce the duplications in the deployment. + +- **Avoid code repetition in the blockchain.** + Heavy computations are expensive because every node will need to perform them, this is of course slowing the network. + +- **Develop upgradable(versioned) contracts** + When the contract is deployed, it’s immutable. By re-designing the code into different contracts, it is possible to allow logic upgrades while keeping the storage the same. + +## Example of gas cost + +Storing contract code at creation time can cost up to: + +- 200 \* max_byte_code_length gas +- 200 \* 24576 = 49152004915200 \* 10 gwei = 49152000 gwei = 0.049152 ether = 9 EUR + +see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md for more info on max_byte_code_length. diff --git a/locales/fr/ProxyContract/2_How/step2.md b/locales/fr/ProxyContract/2_How/step2.md new file mode 100644 index 000000000..d80b6557c --- /dev/null +++ b/locales/fr/ProxyContract/2_How/step2.md @@ -0,0 +1,13 @@ +# How it works? + +**EIP-7 DelegateCall** opcode allows a separate execution in another contract while maintaining the original execution context. + +All **message calls** from the user go through a **Proxy contract**. + +The **Proxy contract** then will redirect them to the **Logic contract**. + +And when you need to **upgrade** the logic, you'll **just** deploy that - **HOWEVER** - the implementation of Proxy will remain the same. + +You'll only need to update the address of Logic contract in Proxy. + +The Proxy Contract uses **Delegate calls** and **Solidity assembly** because without it, it's impossible to return any value from **delegatecall**. diff --git a/locales/fr/ProxyContract/3_Delegatecall/step3.md b/locales/fr/ProxyContract/3_Delegatecall/step3.md new file mode 100644 index 000000000..8693e5567 --- /dev/null +++ b/locales/fr/ProxyContract/3_Delegatecall/step3.md @@ -0,0 +1,9 @@ +# Delegate call + +It's a special variant of a **message call**, which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract so **msg.sender** and **msg.value** do not change their values. + +This means that a contract can dynamically load code from a different address at runtime. + +The storage, the current address and balance still refer to the calling contract, only the code is taken from the called address. + +So when a **Proxy** delegates calls to the Logic contract, every storage modification will impact the storage of Logic contract. diff --git a/locales/fr/ProxyContract/4_Generic_proxy_example/step4.md b/locales/fr/ProxyContract/4_Generic_proxy_example/step4.md new file mode 100644 index 000000000..d20fdd16d --- /dev/null +++ b/locales/fr/ProxyContract/4_Generic_proxy_example/step4.md @@ -0,0 +1,15 @@ +# A Basic Generic Proxy Example + +In the associated solidity file, **step4.sol**, there are 2 contracts - **ProxyContract** and **LogicContract**. + +To use this system, we first deploy the LogicContract. + +And then when we go to deploy the ProxyContract, we pass the LogicContract's address as an argument of the ProxyContract's constructor. + +The ProxyContract is deployed only once. + +The code of LogicContract will be called at the line 20. It will be forwarded with delegate call while keeping the context of LogicContract. + +In case we need to change the logic we would deploy a new LogicContract and set the address of it with setLogicContractAddress setter function. + +_Note: The LogicContract we have here does not use the storage. Once you need to use the storage the implementation becomes a bit more complicated because those contracts share the context._ diff --git a/locales/fr/ProxyContract/5_Test/step5.md b/locales/fr/ProxyContract/5_Test/step5.md new file mode 100644 index 000000000..120a15e13 --- /dev/null +++ b/locales/fr/ProxyContract/5_Test/step5.md @@ -0,0 +1,6 @@ +# Let's test what we've learned + +- Write a contract named "LogicContract" which implements a public function named "getNumber" which returns 10 +- Write a proxy contract named "ProxyContract". This ProxyContract should take an address of LogicContract as a first parameter. + +Good Luck! diff --git a/locales/fr/ProxyContract/6_Storage_Problem/step6.md b/locales/fr/ProxyContract/6_Storage_Problem/step6.md new file mode 100644 index 000000000..d2b804284 --- /dev/null +++ b/locales/fr/ProxyContract/6_Storage_Problem/step6.md @@ -0,0 +1,13 @@ +# What if we have state variables? + +Things are more complicated once we need to deal with state variables. State variable are saved to **storage**. + +`storage`: is a mapping; each value stored there is persisted and saved on chain. + +_Note: Statically-sized state variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position 0. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible. For contracts that use inheritance, the ordering of state variables is determined by the C3-linearized order of contracts starting with the most base-ward contract_ + +Once we execute **delegate call**, the storage of both contracts get **"merged"** into a single messy state. + +We have to "tell" ProxyContract what the **state** of the **Logic contract** looks like. + +The easiest way to do this is to create a separate contract - in this example - named **StorageContract** which will represent the **state** and which proxyContract will inherit from. diff --git a/locales/fr/ProxyContract/7_links/step7.md b/locales/fr/ProxyContract/7_links/step7.md new file mode 100644 index 000000000..c2784c3cc --- /dev/null +++ b/locales/fr/ProxyContract/7_links/step7.md @@ -0,0 +1,19 @@ +# Check out some links for more info + +- ERC DelegateProxy + https://github.com/ethereum/EIPs/pull/897 + +- The joint post by Zeppelin Solutions and Aragon. + https://blog.openzeppelin.com/proxy-libraries-in-solidity-79fbe4b970fd/ + +- Proxy Patterns by OpenZeppelin + https://blog.openzeppelin.com/proxy-patterns/ + +- The most mature implementation of Proxy pattern is The Unstructure Storage pattern that is released as part of ZeppelinOS + https://blog.openzeppelin.com/upgradeability-using-unstructured-storage/ + +- Great blog post by Jack Tanner + https://blog.indorse.io/ethereum-upgradeable-smart-contract-strategies-456350d0557c + +- Upgradeable Ethereum Smart Contracts + https://medium.com/@daonomic/upgradeable-ethereum-smart-contracts-d036cb373d6 diff --git a/locales/fr/ProxyContract/README.md b/locales/fr/ProxyContract/README.md new file mode 100644 index 000000000..6a5364c94 --- /dev/null +++ b/locales/fr/ProxyContract/README.md @@ -0,0 +1,3 @@ +## Learn the Proxy Pattern + +Save gas & make upgradable contracts diff --git a/locales/fr/ProxyContract/config.yml b/locales/fr/ProxyContract/config.yml new file mode 100644 index 000000000..e36e640b8 --- /dev/null +++ b/locales/fr/ProxyContract/config.yml @@ -0,0 +1,9 @@ +--- +id: proxycontract +name: All about Proxy Contracts +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 3 +tags: + - Remix + - Solidity + - Code Patterns diff --git a/locales/fr/README.md b/locales/fr/README.md new file mode 100644 index 000000000..cb799bd20 --- /dev/null +++ b/locales/fr/README.md @@ -0,0 +1,36 @@ +# This is a repo of tutorials for the Remix's LearnEth Plugin + +### To use these tutorials: + +**1. Open Remix** + +https://remix.ethereum.org + +**2. In the plugin manager activate LEARNETH** + +**3. Go to the Learneth plugin and these tutorials will load by default** + +**4. You may need to sign into Github especially during an in-person workshop** + +Github will block too many requests from the same location, unless you are signed into Github and have input your token. Generally, this is only an issue during in person workshops, when there can be many requests from the same location. + +To input your Github token: + +``` +- In one browser window - go to https://remix.ethereum.org and go to the settings tab +- In another browser window go to: + +https://github.com/settings/tokens + +and create a new token and save it in Remix in the you just opened on the settings tab. +``` + +--- + +### Write your own tutorials for LEARNETH: + +See this site for instructions: + +https://remix-learneth-plugin.readthedocs.io/en/latest/index.html#creating-tutorials + +--- diff --git a/locales/fr/Recorder/1_Usecases/1_usecases.md b/locales/fr/Recorder/1_Usecases/1_usecases.md new file mode 100644 index 000000000..0c624393c --- /dev/null +++ b/locales/fr/Recorder/1_Usecases/1_usecases.md @@ -0,0 +1,7 @@ +1. You want to show someone what happens when you do a number of transactions with a contract and you don't want to explain each step - you just want to get them to the last step. + + - To show someone a problem in their code. + + - In a class, to get the students to a certain place and have them start working from there. + +2. You want to start your development in the JavascriptVM because it is quick and then to switch to another testnet - but you don't want to manually repeat all the tedious clicking for each different network. diff --git a/locales/fr/Recorder/2_Record/README.md b/locales/fr/Recorder/2_Record/README.md new file mode 100644 index 000000000..41d214277 --- /dev/null +++ b/locales/fr/Recorder/2_Record/README.md @@ -0,0 +1,32 @@ +# Setting up a tedious series of steps + +## Following this could get tedious but that's the point. + +We are going to: + +- Deploy a voting contract where there are 3 proposals input in the constructor. +- Give voting privileges to 2 additional address (so we have a total of 3 voting addresses). +- Have one address vote for proposal 1 (0-based index) and the other two vote for proposal 2. + +1. Take the 3_Ballot.sol from the sample solidity files and compile it. Then go to the **Deploy & Run** Module. + +2. Select the **JavaScript VM** Environment. + +3. In the constructor's parameter - put in **["0x5031000000000000000000000000000000000000000000000000000000000000", "0x5032000000000000000000000000000000000000000000000000000000000000", "0x5033000000000000000000000000000000000000000000000000000000000000"]** Then click the **Deploy** button. + +4. Open up the deployed contract. + +5. In the **vote** function put in 2. This means that you as the msg.sender & chairperson are voting for proposal at position 2, which is the last proposal in our list. + +6. Now you need to give other addresses the right to vote. Select another address in the **account** pulldown and copy it and then **go back to the 1st address**. Paste the copy address into the textbox next to the giveRightToVote function. And again, select another address and copy it and **then go back to the 1st address** again and paste it into giveRightToVote. + +7. Now you have 3 addresses with the right to vote. + +8. Switch to one of the addresses that you gave the right to vote and vote for proposal **1**. (Put **1** in the textbox next to the vote function). And then switch to the other address and vote for proposal **2** with that one. + +9. Open up the **Transactions recorded** section of the module - by clicking on the caret. Click the hard disk icon in the **Transactions recorded** section to save your steps. + ![recorder](https://github.com/ethereum/remix-workshops/blob/master/Recorder/2_Record/images/recorder.png?raw=true "recorder") + +10. You will get a modal window that tells you it wants to save a file called **scenario.json**. Click OK. + +11. Click on the function **winningProposal** to confirm that the final proposal won - which is the proposal at position 2 in the array. **0: uint256: winningProposal_ 2** diff --git a/locales/fr/Recorder/3_Editing_a_Senario/README.md b/locales/fr/Recorder/3_Editing_a_Senario/README.md new file mode 100644 index 000000000..d23dfb95c --- /dev/null +++ b/locales/fr/Recorder/3_Editing_a_Senario/README.md @@ -0,0 +1,54 @@ +# Editing a scenario + +Here's the first few lines of the scenario that I recorded. The addresses on my machine will be different from your's. + +``` +{ + "accounts": { + "account{0}": "0xca35b7d915458ef540ade6068dfe2f44e8fa733c", + "account{4}": "0xdd870fa1b7c4700f2bd7f44238821c26f7392148", + "account{3}": "0x583031d1113ad414f02576bd6afabfb302140225" + } +``` + +So if you wanted to play this scenario in another testnet, you'd need to change these addresses to address that you have test ETH on so that you could pay for the transactions. But other than swapping out the addresses, you can quickly run this on other nets. + +And you might change the parameters for the functions. + +For example here is a bit of the scenario.json a bit further down where proposal 2 was voted for by one of the addresses: + +``` +{ + "timestamp": 1566428184043, + "record": { + "value": "0", + "parameters": [ + "2" + ], + "to": "created{1566428035436}", + "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", + "name": "vote", + "inputs": "(uint8)", + "type": "function", + "from": "account{4}" + } + }, +``` + +Let's edit this so that another proposal wins in the playback. + +Change the **parameters** array which now is: + +``` +"parameters": [ + "2" + ] +``` + +to: + +``` +"parameters": [ + "1" + ] +``` diff --git a/locales/fr/Recorder/4_Play/README.md b/locales/fr/Recorder/4_Play/README.md new file mode 100644 index 000000000..196664550 --- /dev/null +++ b/locales/fr/Recorder/4_Play/README.md @@ -0,0 +1,8 @@ +# Playing a scenario + +1. Click the play icon to the right of the floppy disk icon to play the steps you did. + +2. You'll see another instance of the contract deployed. Open it up. + +3. Click the winningProposal function and you should see now that proposal 1 won. + It should print out: **0: uint256: winningProposal_ 1** diff --git a/locales/fr/Recorder/README.md b/locales/fr/Recorder/README.md new file mode 100644 index 000000000..94d928383 --- /dev/null +++ b/locales/fr/Recorder/README.md @@ -0,0 +1,3 @@ +## Get yourself Remixing! + +The recorder is used for recording a set of transactions in the Deploy & Run module, editing their parameters and then playing them back in another context. It really is the remix of Remix! diff --git a/locales/fr/Recorder/config.yml b/locales/fr/Recorder/config.yml new file mode 100644 index 000000000..b8980e042 --- /dev/null +++ b/locales/fr/Recorder/config.yml @@ -0,0 +1,7 @@ +--- +id: recorder +name: Recorder +summary: Save a set of actions and replay and replay and replay +level: 2 +tags: + - Remix diff --git a/locales/fr/SolidityBeginnerCourse/README.md b/locales/fr/SolidityBeginnerCourse/README.md new file mode 100644 index 000000000..ae0b6d882 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Course + +Learn the most important Solidity beginner concepts interactively, based on the popular https://solidity-by-example.org/ contracts. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/fr/SolidityBeginnerCourse/basic-syntax/basicSyntax.md b/locales/fr/SolidityBeginnerCourse/basic-syntax/basicSyntax.md new file mode 100644 index 000000000..e9f77871e --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/basic-syntax/basicSyntax.md @@ -0,0 +1,26 @@ +In this section, we will create our first _smart contract_. This contract only consists of a string that holds the value "Hello World!". + +In the first line, we should specify the license that we want to use. You can find a comprehensive list of licenses here: https://spdx.org/licenses/. + +Using the `pragma` keyword (line 3), we specify the Solidity version we want the compiler to use. In this case, it should be greater than or equal to `0.8.3` but less than 0.9.0. + +We define a contract with the keyword `contract` and give it a name, in this case, `HelloWorld` (line 5). + +Inside our contract, we define a _state variable_ `greet` that holds the string `"Hello World!"` (line 6). + +Solidity is a _statically typed_ language, which means that you need to specify the type of the variable when you declare it. In this case, `greet` is a `string`. + +We also define the _visibility_ of the variable, which specifies from where you can access it. In this case, it's a `public` variable that you can access from inside and outside the contract. + +Don't worry if you didn't understand some concepts like _visibility_, _data types_, or _state variables_. We will look into them in the following sections. + +To help you understand the code, we will link in all following sections to video tutorials from the creator of the Solidity by Example contracts. + +Watch a video tutorial on Basic Syntax. + +## ⭐️ Assignment + +1. Delete the HelloWorld contract and its content. +2. Create a new contract named "MyContract". +3. The contract should have a public state variable called "name" of the type string. +4. Assign the value "Alice" to your new variable. diff --git a/locales/fr/SolidityBeginnerCourse/config.yml b/locales/fr/SolidityBeginnerCourse/config.yml new file mode 100644 index 000000000..a729093d8 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/config.yml @@ -0,0 +1,65 @@ +--- +id: soliditybeginner +name: Solidity Beginner Course +summary: Solidity Beginner Course based on the popular https://solidity-by-example.org/ contracts. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Basic Syntax + path: basic-syntax + - + name: 3. Primitive Data Types + path: primitive-data-types + - + name: 4. Variables + path: variables + - + name: 5.1 Functions - Reading and Writing to a State Variable + path: functions-reading-and-writing + - + name: 5.2 Functions - View and Pure + path: functions-view-and-pure + - + name: 5.3 Functions - Modifiers and Constructors + path: functions-modifiers-and-constructors + - + name: 5.4 Functions - Inputs and Outputs + path: functions-inputs-and-outputs + - + name: 6. Visibility + path: visibility + - + name: 7.1 Control Flow - If/Else + path: control-flow-if-else + - + name: 7.2 Control Flow - Loops + path: control-flow-loops + - + name: 8.1 Data Structures - Arrays + path: data-structures-arrays + - + name: 8.2 Data Structures - Mappings + path: data-structures-mappings + - + name: 8.3 Data Structures - Structs + path: data-structures-structs + - + name: 8.4 Data Structures - Enums + path: data-structures-enums + - + name: 9. Data Locations + path: data-locations + - + name: 10.1 Transactions - Ether and Wei + path: transactions-ether-and-wei + - + name: 10.2 Transactions - Gas and Gas Price + path: transactions-gas-and-gas-price + - + name: 10.3 Transactions - Sending Ether + path: transactions-sending-ether diff --git a/locales/fr/SolidityBeginnerCourse/control-flow-if-else/ifElse.md b/locales/fr/SolidityBeginnerCourse/control-flow-if-else/ifElse.md new file mode 100644 index 000000000..634e27689 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/control-flow-if-else/ifElse.md @@ -0,0 +1,33 @@ +Solidity supports different control flow statements that determine which parts of the contract will be executed. The conditional _If/Else statement_ enables contracts to make decisions depending on whether boolean conditions are either `true` or `false`. + +Solidity differentiates between three different If/Else statements: `if`, `else`, and `else if`. + +### if + +The `if` statement is the most basic statement that allows the contract to perform an action based on a boolean expression. + +In this contract’s `foo` function (line 5) the if statement (line 6) checks if `x` is smaller than `10`. If the statement is true, the function returns `0`. + +### else + +The `else` statement enables our contract to perform an action if conditions are not met. + +In this contract, the `foo` function uses the `else` statement (line 10) to return `2` if none of the other conditions are met. + +### else if + +With the `else if` statement we can combine several conditions. + +If the first condition (line 6) of the foo function is not met, but the condition of the `else if` statement (line 8) becomes true, the function returns `1`. + +Watch a video tutorial on the If/Else statement. + +## ⭐️ Assignment + +Create a new function called `evenCheck` in the `IfElse` contract: + +- That takes in a `uint` as an argument. +- The function returns `true` if the argument is even, and `false` if the argument is odd. +- Use a ternery operator to return the result of the `evenCheck` function. + +Tip: The modulo (%) operator produces the remainder of an integer division. diff --git a/locales/fr/SolidityBeginnerCourse/control-flow-loops/loops.md b/locales/fr/SolidityBeginnerCourse/control-flow-loops/loops.md new file mode 100644 index 000000000..ffaa30650 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/control-flow-loops/loops.md @@ -0,0 +1,32 @@ +Solidity supports iterative control flow statements that allow contracts to execute code repeatedly. + +Solidity differentiates between three types of loops: `for`, `while`, and `do while` loops. + +### for + +Generally, `for` loops (line 7) are great if you know how many times you want to execute a certain block of code. In solidity, you should specify this amount to avoid transactions running out of gas and failing if the amount of iterations is too high. + +### while + +If you don’t know how many times you want to execute the code but want to break the loop based on a condition, you can use a `while` loop (line 20). +Loops are seldom used in Solidity since transactions might run out of gas and fail if there is no limit to the number of iterations that can occur. + +### do while + +The `do while` loop is a special kind of while loop where you can ensure the code is executed at least once, before checking on the condition. + +### continue + +The `continue` statement is used to skip the remaining code block and start the next iteration of the loop. In this contract, the `continue` statement (line 10) will prevent the second if statement (line 12) from being executed. + +### break + +The `break` statement is used to exit a loop. In this contract, the break statement (line 14) will cause the for loop to be terminated after the sixth iteration. + +Watch a video tutorial on Loop statements. + +## ⭐️ Assignment + +1. Create a public `uint` state variable called count in the `Loop` contract. +2. At the end of the for loop, increment the count variable by 1. +3. Try to get the count variable to be equal to 9, but make sure you don’t edit the `break` statement. diff --git a/locales/fr/SolidityBeginnerCourse/data-locations/dataLocations.md b/locales/fr/SolidityBeginnerCourse/data-locations/dataLocations.md new file mode 100644 index 000000000..881bf8ffc --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/data-locations/dataLocations.md @@ -0,0 +1,54 @@ +The values of variables in Solidity can be stored in different data locations: _memory_, _storage_, and _calldata_. + +As we have discussed before, variables of the value type store an independent copy of a value, while variables of the reference type (array, struct, mapping) only store the location (reference) of the value. + +If we use a reference type in a function, we have to specify in which data location their values are stored. The price for the execution of the function is influenced by the data location; creating copies from reference types costs gas. + +### Storage + +Values stored in _storage_ are stored permanently on the blockchain and, therefore, are expensive to use. + +In this contract, the state variables `arr`, `map`, and `myStructs` (lines 5, 6, and 10) are stored in storage. State variables are always stored in storage. + +### Memory + +Values stored in _memory_ are only stored temporarily and are not on the blockchain. They only exist during the execution of an external function and are discarded afterward. They are cheaper to use than values stored in _storage_. + +In this contract, the local variable `myMemstruct` (line 19), as well as the parameter `_arr` (line 31), are stored in memory. Function parameters need to have the data location _memory_ or _calldata_. + +### Calldata + +_Calldata_ stores function arguments. Like _memory_, _calldata_ is only stored temporarily during the execution of an external function. In contrast to values stored in _memory_, values stored in _calldata_ can not be changed. Calldata is the cheapest data location to use. + +In this contract, the parameter `_arr` (line 35) has the data location _calldata_. If we wanted to assign a new value to the first element of the array `_arr`, we could do that in the `function g` (line 31) but not in the `function h` (line 35). This is because `_arr` in `function g `has the data location _memory_ and _function h_ has the data location `calldata`. + +## Assignments + +### Memory to memory + +Assignments from _memory_ to _memory_ create references instead of copies. If you change the value in one variable, the value of all other variables that reference the same data will be changed. + +If we were to create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myMemStruct` (line 19), any change to `myMemStruct2` would also change the value of `myMemStruct`. + +### Storage to local storage + +Assignments from _storage_ to _local storage_ also create references, not copies. + +If we change the value of the local variable `myStruct` (line 17), the value of our state variable `myStructs` (line 10) changes as well. + +## Storage and memory/calldata + +Assignments between _storage_ and _memory_ (or _calldata_) create independent copies, not references. + +If we were to create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myStruct`, changes in `myMemStruct3` would not affect the values stored in the mapping `myStructs` (line 10). + +As we said in the beginning, when creating contracts we have to be mindful of gas costs. Therefore, we need to use data locations that require the lowest amount of gas possible. + +## ⭐️ Assignment + +1. Change the value of the `myStruct` member `foo`, inside the `function f`, to 4. +2. Create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` and assign it the value of `myMemStruct`. Change the value of the `myMemStruct2` member `foo` to 1. +3. Create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` and assign it the value of `myStruct`. Change the value of the `myMemStruct3` member `foo` to 3. +4. Let the function f return `myStruct`, `myMemStruct2`, and `myMemStruct3`. + +Tip: Make sure to create the correct return types for the function `f`. diff --git a/locales/fr/SolidityBeginnerCourse/data-structures-arrays/arrays.md b/locales/fr/SolidityBeginnerCourse/data-structures-arrays/arrays.md new file mode 100644 index 000000000..19af3de49 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/data-structures-arrays/arrays.md @@ -0,0 +1,44 @@ +In the next sections, we will look into the data structures that we can use to organize and store our data in Solidity. + +_Arrays_, _mappings_ and _structs_ are all _reference types_. Unlike _value types_ (e.g. _booleans_ or _integers_) reference types don't store their value directly. Instead, they store the location where the value is being stored. Multiple reference type variables could reference the same location, and a change in one variable would affect the others, therefore they need to be handled carefully. + +In Solidity, an array stores an ordered list of values of the same type that are indexed numerically. + +There are two types of arrays, compile-time _fixed-size_ and _dynamic arrays_. For fixed-size arrays, we need to declare the size of the array before it is compiled. The size of dynamic arrays can be changed after the contract has been compiled. + +### Declaring arrays + +We declare a fixed-size array by providing its type, array size (as an integer in square brackets), visibility, and name (line 9). + +We declare a dynamic array in the same manner. However, we don’t provide an array size and leave the brackets empty (line 6). + +### Initializing arrays + +We can initialize the elements of an array all at once (line 7), or initiate new elements one by one (arr[0] = 1;). If we declare an array, we automatically initialize its elements with the default value 0 (line 9). + +### Accessing array elements + +We access elements inside an array by providing the name of the array and the index in brackets (line 12). + +### Adding array elements + +Using the `push()` member function, we add an element to the end of a dynamic array (line 25). + +### Removing array elements + +Using the `pop()` member function, we delete the last element of a dynamic array (line 31). + +We can use the `delete` operator to remove an element with a specific index from an array (line 42). +When we remove an element with the `delete` operator all other elements stay the same, which means that the length of the array will stay the same. This will create a gap in our array. +If the order of the array is not important, then we can move the last element of the array to the place of the deleted element (line 46), or use a mapping. A mapping might be a better choice if we plan to remove elements in our data structure. + +### Array length + +Using the length member, we can read the number of elements that are stored in an array (line 35). + +Watch a video tutorial on Arrays. + +## ⭐️ Assignment + +1. Initialize a public fixed-sized array called `arr3` with the values 0, 1, 2. Make the size as small as possible. +2. Change the `getArr()` function to return the value of `arr3`. diff --git a/locales/fr/SolidityBeginnerCourse/data-structures-enums/enums.md b/locales/fr/SolidityBeginnerCourse/data-structures-enums/enums.md new file mode 100644 index 000000000..40411db67 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/data-structures-enums/enums.md @@ -0,0 +1,33 @@ +In Solidity _enums_ are custom data types consisting of a limited set of constant values. We use enums when our variables should only get assigned a value from a predefined set of values. + +In this contract, the state variable `status` can get assigned a value from the limited set of provided values of the enum `Status` representing the various states of a shipping status. + +### Defining enums + +We define an enum with the enum keyword, followed by the name of the custom type we want to create (line 6). Inside the curly braces, we define all available members of the enum. + +### Initializing an enum variable + +We can initialize a new variable of an enum type by providing the name of the enum, the visibility, and the name of the variable (line 16). Upon its initialization, the variable will be assigned the value of the first member of the enum, in this case, Pending (line 7). + +Even though enum members are named when you define them, they are stored as unsigned integers, not strings. They are numbered in the order that they were defined, the first member starting at 0. The initial value of status, in this case, is 0. + +### Accessing an enum value + +To access the enum value of a variable, we simply need to provide the name of the variable that is storing the value (line 25). + +### Updating an enum value + +We can update the enum value of a variable by assigning it the `uint` representing the enum member (line 30). Shipped would be 1 in this example. Another way to update the value is using the dot operator by providing the name of the enum and its member (line 35). + +### Removing an enum value + +We can use the delete operator to delete the enum value of the variable, which means as for arrays and mappings, to set the default value to 0. + +Watch a video tutorial on Enums. + +## ⭐️ Assignment + +1. Define an enum type called `Size` with the members `S`, `M`, and `L`. +2. Initialize the variable `sizes` of the enum type `Size`. +3. Create a getter function `getSize()` that returns the value of the variable `sizes`. diff --git a/locales/fr/SolidityBeginnerCourse/data-structures-mappings/mappings.md b/locales/fr/SolidityBeginnerCourse/data-structures-mappings/mappings.md new file mode 100644 index 000000000..72fc4acb4 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/data-structures-mappings/mappings.md @@ -0,0 +1,37 @@ +In Solidity, _mappings_ are a collection of key types and corresponding value type pairs. + +The biggest difference between a mapping and an array is that you can't iterate over mappings. If we don't know a key we won't be able to access its value. If we need to know all of our data or iterate over it, we should use an array. + +If we want to retrieve a value based on a known key we can use a mapping (e.g. addresses are often used as keys). Looking up values with a mapping is easier and cheaper than iterating over arrays. If arrays become too large, the gas cost of iterating over it could become too high and cause the transaction to fail. + +We could also store the keys of a mapping in an array that we can iterate over. + +### Creating mappings + +Mappings are declared with the syntax `mapping(KeyType => ValueType) VariableName`. +The key type can be any built-in value type or any contract, but not a reference type. The value type can be of any type. + +In this contract, we are creating the public mapping `myMap` (line 6) that associates the key type `address` with the value type `uint`. + +### Accessing values + +The syntax for interacting with key-value pairs of mappings is similar to that of arrays. +To find the value associated with a specific key, we provide the name of the mapping and the key in brackets (line 11). + +In contrast to arrays, we won't get an error if we try to access the value of a key whose value has not been set yet. When we create a mapping, every possible key is mapped to the default value 0. + +### Setting values + +We set a new value for a key by providing the mapping’s name and key in brackets and assigning it a new value (line 16). + +### Removing values + +We can use the delete operator to delete a value associated with a key, which will set it to the default value of 0. As we have seen in the arrays section. + +Watch a video tutorial on Mappings. + +## ⭐️ Assignment + +1. Create a public mapping `balances` that associates the key type `address` with the value type `uint`. +2. Change the functions `get` and `remove` to work with the mapping balances. +3. Change the function `set` to create a new entry to the balances mapping, where the key is the address of the parameter and the value is the balance associated with the address of the parameter. diff --git a/locales/fr/SolidityBeginnerCourse/data-structures-structs/structs.md b/locales/fr/SolidityBeginnerCourse/data-structures-structs/structs.md new file mode 100644 index 000000000..fba0d93b0 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/data-structures-structs/structs.md @@ -0,0 +1,29 @@ +In Solidity, we can define custom data types in the form of _structs_. Structs are a collection of variables that can consist of different data types. + +### Defining structs + +We define a struct using the `struct` keyword and a name (line 5). Inside curly braces, we can define our struct’s members, which consist of the variable names and their data types. + +### Initializing structs + +There are different ways to initialize a struct. + +Positional parameters: We can provide the name of the struct and the values of its members as parameters in parentheses (line 16). + +Key-value mapping: We provide the name of the struct and the keys and values as a mapping inside curly braces (line 19). + +Initialize and update a struct: We initialize an empty struct first and then update its member by assigning it a new value (line 23). + +### Accessing structs + +To access a member of a struct we can use the dot operator (line 33). + +### Updating structs + +To update a structs’ member we also use the dot operator and assign it a new value (lines 39 and 45). + +Watch a video tutorial on Structs. + +## ⭐️ Assignment + +Create a function `remove` that takes a `uint` as a parameter and deletes a struct member with the given index in the `todos` mapping. diff --git a/locales/fr/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md b/locales/fr/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md new file mode 100644 index 000000000..d0e628f6b --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md @@ -0,0 +1,37 @@ +In this section, we will learn more about the inputs and outputs of functions. + +### Multiple named Outputs + +Functions can return multiple values that can be named and assigned to their name. + +The `returnMany` function (line 6) shows how to return multiple values. +You will often return multiple values. It could be a function that collects outputs of various functions and returns them in a single function call for example. + +The `named` function (line 19) shows how to name return values. +Naming return values helps with the readability of your contracts. Named return values make it easier to keep track of the values and the order in which they are returned. You can also assign values to a name. + +The `assigned` function (line 33) shows how to assign values to a name. +When you assign values to a name you can omit (leave out) the return statement and return them individually. + +### Deconstructing Assignments + +You can use deconstructing assignments to unpack values into distinct variables. + +The `destructingAssigments` function (line 49) assigns the values of the `returnMany` function to the new local variables `i`, `b`, and `j` (line 60). + +### Input and Output restrictions + +There are a few restrictions and best practices for the input and output parameters of contract functions. + +"_[Mappings] cannot be used as parameters or return parameters of contract functions that are publicly visible._" +From the Solidity documentation. + +Arrays can be used as parameters, as shown in the function `arrayInput` (line 71). Arrays can also be used as return parameters as shown in the function `arrayOutput` (line 76). + +You have to be cautious with arrays of arbitrary size because of their gas consumption. While a function using very large arrays as inputs might fail when the gas costs are too high, a function using a smaller array might still be able to execute. + +Watch a video tutorial on Function Outputs. + +## ⭐️ Assignment + +Create a new function called `returnTwo` that returns the values `-2` and `true` without using a return statement. diff --git a/locales/fr/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md b/locales/fr/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md new file mode 100644 index 000000000..d707a987b --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md @@ -0,0 +1,39 @@ +In this section, we will learn how to modify the behavior of a function and how to run contract initialization code. + +### Function Modifier + +_Function Modifiers_ are used to change the behavior of a function. For example, they often check for a condition prior to executing a function to restrict access or validate inputs. + +This first part of this contract is about changing ownership of a contract. Ownership in this contract is expressed by the value of the state variable `owner` that is of the type `address` (line 7). + +The function `changeOwner` (line 33) can change this ownership. It takes an input parameter of the type `address` and assigns its value to the state variable `owner`. + +However, this function cannot simply be executed under all conditions; it has two modifiers, `onlyOwner` and `validAddress`. + +Let's look at `onlyOwner` first (line 18). +Function modifiers are defined with the `modifier` keyword and a unique name; they can also have parameters. + +The underscore `_` (line 23) is used inside modifiers to represent the rest of the code that will be executed in the body of the modified function. +The code you place before the underscore in the modifier will be executed before the code in the body of the modified function. The code after the underscore will be executed after the code in the body of the modified function. + +In this case, the `require` function (line 19) checks if the address executing the contract is the same as the value stored in the variable `owner`. If it is, the rest of the code will be executed, otherwise it will throw an error. + +You can learn more about `assert` and `require` in the Solidity documentation, they are used to check for conditions and throw errors if they are not met. + +The `validAddress` modifier (line 28) has a parameter of type `address` and checks if the provided address is valid. If it is, it continues to execute the code. + +### Constructor + +A constructor function is executed upon the creation of a contract. You can use it to run contract initialization code. The constructor can have parameters and is especially useful when you don't know certain initialization values before the deployment of the contract. + +You declare a constructor using the `constructor` keyword. The constructor in this contract (line 11) sets the initial value of the owner variable upon the creation of the contract. + +Watch a video tutorial on Function Modifiers. + +## ⭐️ Assignment + +1. Create a new function, `increaseX` in the contract. The function should take an input parameter of type `uint` and increase the value of the variable `x` by the value of the input parameter. +2. Make sure that x can only be increased. +3. The body of the function `increaseX` should be empty. + +Tip: Use modifiers. diff --git a/locales/fr/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md b/locales/fr/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md new file mode 100644 index 000000000..3670c03e2 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md @@ -0,0 +1,23 @@ +This section will give a short introduction to functions and teach you how to use them to read from and write to a state variable. + +As in other languages, we use functions in Solidity to create modular, reusable code. However, Solidity functions have some particularities. + +Solidity functions can be split into two types: + +1. Functions that modify the state of the blockchain, like writing to a state variable. In this contract, the `set` function (line 9) changes the state variable `num`. +2. Functions that don't modify the state of the blockchain. These functions are marked `view` or `pure`. For example, in this contract, the `get` function (line 14) marked `view` that only returns `num` does not change the state. + +To define a function, use the `function` keyword followed by a unique name. + +If the function takes inputs like our `set` function (line 9), you must specify the parameter types and names. A common convention is to use an underscore as a prefix for the parameter name to distinguish them from state variables. + +You can then set the visibility of a function and declare them `view` or `pure` as we do for the `get` function if they don't modify the state. Our `get` function also returns values, so we have to specify the return types. In this case, it's a `uint` since the state variable `num` that the function returns is a `uint`. + +We will explore the particularities of Solidity functions in more detail in the following sections. + +Watch a video tutorial on Functions. + +## ⭐️ Assignment + +1. Create a public state variable called `b` that is of type `bool` and initialize it to `true`. +2. Create a public function called `get_b` that returns the value of `b`. diff --git a/locales/fr/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md b/locales/fr/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md new file mode 100644 index 000000000..b846c7d99 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md @@ -0,0 +1,44 @@ +This section will look into the types of functions that don't modify the state of the blockchain: _view_ and _pure_ functions. + +### View Functions + +_View functions_ promise to not modify the state. + +"The following statements are considered modifying the state: + +1. Writing to state variables. +2. Emitting events. +3. Creating other contracts. +4. Using selfdestruct. +5. Sending Ether via calls. +6. Calling any function not marked view or pure. +7. Using low-level calls. +8. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a view function using the keyword `view`. In this contract, `addToX` (line 8) is a view function. This function takes the parameter `y` and returns the sum of the parameter and the state variable `x`. It reads `x` but does not modify it. + +### Pure functions + +_Pure functions_ promise to neither modify nor to read the state. + +"In addition to the list of state modifying statements explained above, the following are considered reading from the state: + +1. Reading from state variables. +2. Accessing `address(this).balance` or `
.balance`. +3. Accessing any of the members of block, tx, msg (with the exception of `msg.sig` and `msg.data`). +4. Calling any function not marked pure. +5. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a pure function using the keyword `pure`. In this contract, `add` (line 13) is a pure function. This function takes the parameters `i` and `j`, and returns the sum of them. It neither reads nor modifies the state variable `x`. + +In Solidity development, you need to optimise your code for saving computation cost (gas cost). Declaring functions view and pure can save gas cost and make the code more readable and easier to maintain. Pure functions don't have any side effects and will always return the same result if you pass the same arguments. + +Watch a video tutorial on View and Pure Functions. + +## ⭐️ Assignment + +Create a function called `addToX2` that takes the parameter `y` and updates the state variable `x` with the sum of the parameter and the state variable `x`. diff --git a/locales/fr/SolidityBeginnerCourse/introduction/introduction.md b/locales/fr/SolidityBeginnerCourse/introduction/introduction.md new file mode 100644 index 000000000..cc821a46a --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/introduction/introduction.md @@ -0,0 +1,32 @@ +Welcome to this interactive Solidity course for beginners. + +In this first section, we will give you a short preview of the concepts we will cover in this course, look at an example smart contract, and show you how you can interact with this contract in the Remix IDE. + +This contract is a counter contract that has the functionality to increase, decrease, and return the state of a counter variable. + +If we look at the top of the contract, we can see some information about the contract like the license (line 1), the Solidity version (line 2), as well as the keyword `contract` and it's name, `Counter` (line 4). We will cover these concepts in the next section about the **Basic Syntax**. + +With `uint public count` (line 5) we declare a state variable of the type `uint` with the visibility `public`. We will cover these concepts in our sections about **Variables**, **Primitive Data Types**, and **Visibility**. + +We then create a `get` function (line 8) that is defined with the `view` keyword and returns a `uint` type. Specifically, it returns the `count` variable. This contract has two more functions, an `inc` (line 13) and `dec` (line 18) function that increases or decreases our count variable. +We will talk about these concepts in our sections about **Functions - Reading and Writing to a State Variable** and **Functions - View and pure**. + +## Compile and Deploy through Remix + +**GIF** Interacting with the contract: Compile and deploy contract + +1. We can compile your `Counter` contract in the "Solidity compiler" module of the Remix IDE. + +2. In the "Deploy & run transactions" module, we select our contract "Counter" in the contract input field and click on the "Deploy" button. + +3. We expand the token contract functions in the IDE, and test its `get`, `inc`, and `dec` functions. + +## ⭐️ Assignment + +Throughout this course, we will give you assignments to test and consolidate your newly acquired knowledge. + +Your first assignment is to: + +1. Compile this contract. +2. Deploy it to the Remix VM. +3. Interact with your contract. diff --git a/locales/fr/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md b/locales/fr/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md new file mode 100644 index 000000000..9ea6b8626 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md @@ -0,0 +1,33 @@ +In this section, we will show you Solidity’s primitive data types, how to declare them, and their characteristics. + +### bool + +You can declare data a boolean type by using the keyword ‘bool’. Booleans can either have the value `true` or `false`. + +### uint + +We use the keywords `uint` and `uint8` to `uint256` to declare an _unsigned integer type_ (they don’t have a sign, unlike -12, for example). Uints are integers that are positive or zero and range from 8 bits to 256 bits. The type `uint` is the same as `uint256`. + +### int + +We use the keywords `int` and `int8` to `int256` to declare an integer type. Integers can be positive, negative, or zero and range from 8 bits to 256 bits. The type `int` is the same as `int256`. + +### address + +Variables of the type `address` hold a 20-byte value, which is the size of an Ethereum address. There is also a special kind of Ethereum address, `address payable`, which can receive ether from the contract. + +All these data types have default values, as shown in the contract (line 29). + +You can learn more about these data types as well as _Fixed Point Numbers_, _Byte Arrays_, _Strings_, and more in the Solidity documentation. + +Later in the course, we will look at data structures like **Mappings**, **Arrays**, **Enums**, and **Structs**. + +Watch a video tutorial on Primitive Data Types. + +## ⭐️ Assignment + +1. Create a new variable `newAddr` that is a `public` `address` and give it a value that is not the same as the available variable `addr`. +2. Create a `public` variable called `neg` that is a negative number, decide upon the type. +3. Create a new variable, `newU` that has the smallest `uint` size type and the smallest `uint` value and is `public`. + +Tip: Look at the other address in the contract or search the internet for an Ethereum address. diff --git a/locales/fr/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md b/locales/fr/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md new file mode 100644 index 000000000..57208c555 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md @@ -0,0 +1,26 @@ +_Ether_ (ETH) is a cryptocurrency. _Ether_ is also used to pay fees for using the Ethereum network, like making transactions in the form of sending _Ether_ to an address or interacting with an Ethereum application. + +### Ether Units + +To specify a unit of _Ether_, we can add the suffixes `wei`, `gwei`, or `ether` to a literal number. + +#### `wei` + +_Wei_ is the smallest subunit of _Ether_, named after the cryptographer [Wei Dai](https://en.wikipedia.org/wiki/Wei_Dai). _Ether_ numbers without a suffix are treated as `wei` (line 7). + +#### `gwei` + +One `gwei` (giga-wei) is equal to 1,000,000,000 (10^9) `wei`. + +#### `ether` + +One `ether` is equal to 1,000,000,000,000,000,000 (10^18) `wei` (line 11). + +Watch a video tutorial on Ether and Wei. + +## ⭐️ Assignment + +1. Create a `public` `uint` called `oneGWei` and set it to 1 `gwei`. +2. Create a `public` `bool` called `isOneGWei` and set it to the result of a comparison operation between 1 gwei and 10^9. + +Tip: Look at how this is written for `gwei` and `ether` in the contract. diff --git a/locales/fr/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md b/locales/fr/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md new file mode 100644 index 000000000..bbc25575c --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md @@ -0,0 +1,29 @@ +As we have seen in the previous section, executing code via transactions on the Ethereum Network costs transaction fees in the form of Ether. The amount of fees that have to be paid to execute a transaction depends on the amount of _gas_ that the execution of the transaction costs. + +### Gas + +_Gas_ is the unit that measures the amount of computational effort that is required to execute a specific operation on the Ethereum network. + +### Gas price + +The _gas_ that fuels Ethereum is sometimes compared to the gas that fuels a car. The amount of gas your car consumes is mostly the same, but the price you pay for gas depends on the market. + +Similarly, the amount of _gas_ that a transaction requires is always the same for the same computational work that is associated with it. However the price that the sender of the transaction is willing to pay for the _gas_ is up to them. Transactions with higher _gas prices_ are going through faster; transactions with very low _gas prices_ might not go through at all. + +When sending a transaction, the sender has to pay the _gas_ fee (gas_price \* gas) upon execution of the transaction. If _gas_ is left over after the execution is completed, the sender gets refunded. + +_Gas_ prices are denoted in gwei. + +### Gas limit + +When sending a transaction, the sender specifies the maximum amount of gas that they are willing to pay for. If they set the limit too low, their transaction can run out of _gas_ before being completed, reverting any changes being made. In this case, the _gas_ was consumed and can’t be refunded. + +Learn more about _gas_ on ethereum.org. + +Watch a video tutorial on Gas and Gas Price. + +## ⭐️ Assignment + +Create a new `public` state variable in the `Gas` contract called `cost` of the type `uint`. Store the value of the gas cost for deploying the contract in the new variable, including the cost for the value you are storing. + +Tip: You can check in the Remix terminal the details of a transaction, including the gas cost. You can also use the Remix plugin _Gas Profiler_ to check for the gas cost of transactions. diff --git a/locales/fr/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md b/locales/fr/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md new file mode 100644 index 000000000..58fb4c5a6 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md @@ -0,0 +1,86 @@ +In this section, we will learn how a contract can send and receive Ether. + +### Sending Ether + +We have three different options to transfer Ether: `transfer()`, `send()` and `call()`. + +#### **transfer** + +`
.transfer(uint256 amount)` + +- `transfer()` throws an exception on failure +- Forwards a fixed 2300 gas stipend + +An example of `transfer()` can be seen in the `SendEther` contract (line 35). +**`Transfer()` is not recommended to be used anymore.** + +#### **send** + +`
.send(uint256 amount) returns (bool)` + +- `send()` returns false on failure +- Forwards a fixed 2300 gas stipend + +An example of `send()` can be seen in the `SendEther` contract (line 41). +**`Send()` is not recommended to be used anymore.** + +#### **call** + +`
.call(bytes memory) returns (bool, bytes memory)` + +- `call()` returns false on failure +- Forwards the maximum amount of gas, but this is adjustable + +An example of `call()` can be seen in the `SendEther` contract (line 48). +`Call()` is currently recommended if you are transfering Ether. + +The reason `transfer()` and `send()` were introduced was to guard against _reentry attacks_ by limiting the forwarded gas to 2300, which would be insufficient to make a reentrant call that can modify storage. + +As we discussed in the last section, each operation on Ethereum has a specific cost associated with it. Certain operations have become more cost intensive over time, so the gas costs associated with them are also raised. When gas costs for operations are subject to change it is not good to use a hardcoded gas amount like transfer(), and send() do. + +That’s why `call()` instead of `transfer()` is now recommended to send Ether. + +Learn more about the subject in this Consensys blog post. + +### Reentrancy attack + +A _reentrancy attack_ occurs when a function makes an external call to an untrusted contract and the attacker uses the contract to make recursive calls back to the original function before it finishes its execution. Through this method, the attacker can drain funds and manipulate data in unintended ways. + +To guard against a _reentrancy attack_, all state changes should be made before calling an external contract. This is also called the Checks-Effects-Interactions pattern. + +Another way to prevent reentrancy is to use a _Reentrancy Guard_ that checks for such calls and rejects them. You can see an example of this in the contract in our modifier section or a more gas-efficient version on Open Zepplin. + +### Receiving Ether + +If we want to enable a contract to receive Ether without a function being called, we need to create a `receive` function (line 22) or a `fallback` function (line 25); otherwise, the Ether will be rejected, and the contract will throw an exception. + +The `receive` function is executed on calls with empty calldata (e.g. plain Ether transfers via send() or transfer()), while the fallback function is executed on calls with calldata. If no receive function exists but a fallback function does, calls with empty calldata will also use the fallback function. + +### Payable function modifier + +The `payable` function modifier allows a function to receive Ether. + +The `receive` function (line 22) needs to be `payable`. If you delete the `payable` modifier you will get an error from the compiler. If you delete the `payable` modifier from the `fallback` function (line 25) it will compile, but it won’t be able to receive Ether. +The functions `sendViaTransfer`, `sendViaSend`, and `sendViaCall` (lines 33, 38, and 45) also need to be `payable` in order to receive Ether. + +### Payable address + +Solidity makes a distinction between two different flavors of the address data type: address and address payable. + +`address`: Holds a 20-byte value. +`address payable`: Holds a 20-byte value and can receive Ether via its members: transfer and send. + +If you change the parameter type for the functions `sendViaTransfer` and `sendViaSend` (line 33 and 38) from `payable address` to `address`, you won’t be able to use `transfer()` (line 35) or `send()` (line 41). + +Watch a video tutorial on Sending Ether. + +## ⭐️ Assignment + +Build a charity contract that receives Ether that can be withdrawn by a beneficiary. + +1. Create a contract called `Charity`. +2. Add a public state variable called `owner` of the type address. +3. Create a donate function that is public and payable without any parameters or function code. +4. Create a withdraw function that is public and sends the total balance of the contract to the `owner` address. + +Tip: Test your contract by deploying it from one account and then sending Ether to it from another account. Then execute the withdraw function. diff --git a/locales/fr/SolidityBeginnerCourse/variables/variables.md b/locales/fr/SolidityBeginnerCourse/variables/variables.md new file mode 100644 index 000000000..dfb35b382 --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/variables/variables.md @@ -0,0 +1,29 @@ +There are three different types of variables in Solidity: _State Variables_, _Local Variables_, and _Global Variables_. + +## 1. State Variables + +_State Variables_ are stored in the contract _storage_ and thereby on the blockchain. They are declared inside the contract but outside the function. +This contract has two state variables, the string `text`(line 6) and the uint `num` (line 7). + +## 2. Local Variables + +_Local Variables_ are stored in the _memory_ and their values are only accessible within the function they are defined in. Local Variables are not stored on the blockchain. +In this contract, the uint `i` (line 11) is a local variable. + +## 3. Global Variables + +_Global Variables_, also called _Special Variables_, exist in the global namespace. They don't need to be declared but can be accessed from within your contract. +Global Variables are used to retrieve information about the blockchain, particular addresses, contracts, and transactions. + +In this example, we use `block.timestamp` (line 14) to get a Unix timestamp of when the current block was generated and `msg.sender` (line 15) to get the caller of the contract function’s address. + +A list of all Global Variables is available in the Solidity documentation. + +Watch video tutorials on State Variables, Local Variables, and Global Variables. + +## ⭐️ Assignment + +1. Create a new public state variable called `blockNumber`. +2. Inside the function `doSomething()`, assign the value of the current block number to the state variable `blockNumber`. + +Tip: Look into the global variables section of the Solidity documentation to find out how to read the current block number. diff --git a/locales/fr/SolidityBeginnerCourse/visibility/visibility.md b/locales/fr/SolidityBeginnerCourse/visibility/visibility.md new file mode 100644 index 000000000..79e4307bf --- /dev/null +++ b/locales/fr/SolidityBeginnerCourse/visibility/visibility.md @@ -0,0 +1,37 @@ +The `visibility` specifier is used to control who has access to functions and state variables. + +There are four types of visibilities: `external`, `public`, `internal`, and `private`. + +They regulate if functions and state variables can be called from inside the contract, from contracts that derive from the contract (child contracts), or from other contracts and transactions. + +### private + +- Can be called from inside the contract + +### internal + +- Can be called from inside the contract +- Can be called from a child contract + +### public + +- Can be called from inside the contract +- Can be called from a child contract +- Can be called from other contracts or transactions + +### external + +- Can be called from other contracts or transactions +- State variables can not be `external` + +In this example, we have two contracts, the `Base` contract (line 4) and the `Child` contract (line 55) which inherits the functions and state variables from the `Base` contract. + +When you uncomment the `testPrivateFunc` (lines 58-60) you get an error because the child contract doesn’t have access to the private function `privateFunc` from the `Base` contract. + +If you compile and deploy the two contracts, you will not be able to call the functions `privateFunc` and `internalFunc` directly. You will only be able to call them via `testPrivateFunc` and `testInternalFunc`. + +Watch a video tutorial on Visibility. + +## ⭐️ Assignment + +Create a new function in the `Child` contract called `testInternalVar` that returns the values of all state variables from the `Base` contract that are possible to return. diff --git a/locales/fr/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md b/locales/fr/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md new file mode 100644 index 000000000..801d8c582 --- /dev/null +++ b/locales/fr/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md @@ -0,0 +1,47 @@ +In this tutorial, we'll explore the Uniswap V3 Swap contract to learn about how single-hop and multi-hop swaps work. + +But first, some Uniswap fundamentals. + +## What is Uniswap? + +Uniswap is a decentralized cryptocurrency exchange. It allows users to exchange tokens without the need for a centralized intermediary. Uniswap is a key player in the decentralized finance (DeFi) space. + +## How does Uniswap work? + +Instead of using an order book like a traditional centralized exchange, Uniswap uses an automated market maker (AMM) model. In Uniswap, the AMM is a smart contract that holds reserves of tokens (Liquidity Pool). Users can trade between tokens in the Liquidity Pool. The price of each token is determined by the ratio of the reserves. + +### Step-by-step example of a Uniswap trade + +1. Alice wants to trade 1 ETH for DAI. +2. Alice sends 1 ETH to the Uniswap smart contract. +3. The Uniswap smart contract calculates the amount of DAI that Alice should receive based on the current exchange rate. +4. The Uniswap smart contract sends the DAI to Alice. +5. The Uniswap smart contract adds the 1 ETH to its reserves. +6. The Uniswap smart contract recalculates the exchange rate based on the new reserves. + +The tokens in the Liquidity Pool are provided by Liquidity Providers. When a Liquidity Provider deposits tokens into a Liquidity Pool, they receive Liquidity Provider Tokens in return. Liquidity Provider Tokens represent a user's share of a Liquidity Pool. + +Users of Uniswap pay a fee for each trade. The fee is paid to the Liquidity Providers in the form of additional Liquidity Provider Tokens. + +## Uniswap Swap Contract + +The Uniswap Swap contract allows users to swap tokens using Uniswap V3. It can do single-hop swaps, which allow users to exchange one token for another directly. It can also do multi-hop swaps, which means that users can exchange one token for another by routing through multiple tokens. Routing in this context means that the swap contract will exchange the token for another token, then exchange that token for another token, and so on until it reaches the desired token. + +## Conclusion + +In this section, we learned about Uniswap, how it works, and how we are going to use it to swap tokens. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is Uniswap? + +1. A centralized exchange protocol. +2. A decentralized exchange protocol that uses an order book. +3. A decentralized exchange protocol that uses an automated market maker (AMM) model. +4. A decentralized exchange protocol that uses an order book and an automated market maker (AMM) model. + +### 2) How does Uniswap determine the price of a token? + +1. The price of a token is determined by the ratio of the reserves. +2. The price of a token is determined by the ratio of the reserves and the number of trades. +3. The price of a token is determined by the ratio of the reserves and the number of Liquidity Providers. diff --git a/locales/fr/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md b/locales/fr/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md new file mode 100644 index 000000000..e5cc248f5 --- /dev/null +++ b/locales/fr/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md @@ -0,0 +1,41 @@ +The entire UniswapSwapExamples contract will only be presented in section 5 of this tutorial. Before then, we'll build up blocks of code. + +This section explores the `ISwapRouter` interface, which defines the functions that can be called on the Uniswap Swap contract. + +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. +Multi-hop swaps allow users to exchange one token for another by routing through multiple tokens. + +Interfaces in Solidity specify functions that must be included in a contract that inherits them. They are useful for declaring what functions be supported and allow for easier integration and interaction between different contracts. + +Structs are used to define custom data types. + +## ISwapRouter Interface + +The ISwapRouter interface defines the functions that can be called on the Uniswap Swap contract. We will need to use this interface to interact with the Uniswap Swap contract and execute swaps. + +On line 5, we define a constant variable called `router` that is of type `ISwapRouter`. We set the value of this variable to the interface instance of a smart contract that is deployed at the address `0xE592427A0AEce92De3Edee1F18E0157C05861564`. This is the address of the Uniswap V3 Swap contract on the Ethereum mainnet. + +On line 9, we define an interface called `ISwapRouter`. This interface defines two functions: `exactInputSingle` and `exactInput`. + +## exactInputSingle + +On line 25, we define a struct called `ExactInputSingleParams`. This struct defines the parameters that are required for our exactInputSingle function on line 21, which will execute a single-hop swap. The struct has the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 fee`**: The fee associated with the swap. +- **`address recipient`**: The address that will receive the output token. +- **`uint deadline`**: A timestamp by which the transaction must be processed, for time-limiting the swap. +- **`uint amountIn`**: The amount of the input token being sent. +- **`uint amountOutMinimum`**: The minimum amount of the output token that the sender is willing to accept, to protect against unfavorable price movements. +- **`uint160 sqrtPriceLimitX96`**: A limit on the price, represented in a specific format, to prevent the swap from occurring at unfavorable prices. + +## exactInput + +On line 25, we define a struct called `ExactInputParams`. This struct defines the parameters that are required for our `exactInput` function on line 33. This function will execute a multi-hop swap. The struct has the following parameters: + +- **`bytes path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address recipient`**: The address receiving the output tokens. +- **`uint deadline`**: Similar to above, a timestamp by which the transaction must be processed. +- **`uint amountIn`**: The amount of the input token. +- **`uint amountOutMinimum`**: The minimum amount of the output token the sender expects to receive. diff --git a/locales/fr/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md b/locales/fr/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md new file mode 100644 index 000000000..f4d70c445 --- /dev/null +++ b/locales/fr/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md @@ -0,0 +1,36 @@ +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. In this section, we will learn how to use the Uniswap V3 Swap contract to execute single-hop swaps. + +## Function Parameters + +On line 8, we define a function called `swapExactInputSingleHop`. This function executes a single-hop swap. It takes the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 poolFee`**: The fee associated with the swap. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +## Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 14. +Then, we approve the Uniswap Swap contract to spend the input token on our behalf, line 15. + +On line 17, we create an instance of the `ExactInputSingleParams` struct. This struct contains the parameters that are required for our `exactInputSingle` function on line 45, which will execute the single-hop swap. We repeat `ISwapRouter.ExactInputSingleParams` two times on that line because we are making an instance of a struct that is defined in an interface. + +## Parameters of the ExactInputSingleParams Struct + +We set the parameters of the struct as follows: + +- **`tokenIn`**: We set this to the `tokenIn` parameter of our function. +- **`tokenOut`**: We set this to the `tokenOut` parameter of our function. +- **`fee`**: We set this to the `poolFee` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. +- **`sqrtPriceLimitX96`**: We set this to 0 because we do not want to specify a limit on the price. + +## Executing the Single-hop Swap + +On line 29, we assign the output of the `exactInputSingle` function to the `amountOut` variable. This function executes the single-hop swap and returns the amount of the output token that was received. diff --git a/locales/fr/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md b/locales/fr/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md new file mode 100644 index 000000000..7883b4718 --- /dev/null +++ b/locales/fr/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md @@ -0,0 +1,30 @@ +In this section, we'll delve into the `swapExactInputMultiHop` function in the `UniswapV3SwapExamples` contract. This function enables more complex token swaps by allowing users to specify a custom path through multiple liquidity pools. + +If for example, a user wants to swap token A for token D, but there is no direct liquidity pool for A and D, the user can specify a path through multiple tokens. For example, the user can swap A for B, then B for C, and finally C for D. This is of course automatically done by the Uniswap V3 Swap contract. + +### Parameters and Return Value + +On line 32, we define a function called `swapExactInputMultiHop`. This function executes a multi-hop swap. It takes the following parameters: + +- **`bytes calldata path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address tokenIn`**: The address of the token being sent. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +### Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 38. +Then, we approve the Uniswap Swap router to spend the input token on our behalf, line 41. + +On line 43, we create an instance of the `ExactInputParams` struct, line 73. This struct contains the parameters that are required for our `exactInput` function on line 81, which will execute the multi-hop swap. + +We set the parameters of the struct as follows: + +- **`path`**: We set this to the `path` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. + +On line 53, we execute the multi-hop swap by calling the `exactInput` function. This function returns the amount of the output token that was received. diff --git a/locales/fr/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md b/locales/fr/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md new file mode 100644 index 000000000..b3cec34e9 --- /dev/null +++ b/locales/fr/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md @@ -0,0 +1,52 @@ +In this section, we'll explore the `IERC20` interface, a standard interface for interacting with ERC-20 tokens and the `IWETH` interface, a standard interface for interacting with wrapped Ether (WETH). Understanding these interfaces is crucial as it is used in the Uniswap V3 Swap contract to handle token transfers and approvals. + +You can find a "Solidity ERC20 Token Course" for beginners in LearnEth to understand the ERC20 token standard in more detail. + +## IERC20 Interface + +On line 80, we define the `IERC20` interface. This interface defines a standard set of functions that ERC-20 tokens must implement. Let's examine the key functions within this interface: + +### 1. totalSupply + +On line 81, we define the `totalSupply` function. This function returns the total supply of the token. + +### 2. balanceOf + +On line 83, we define the `balanceOf` function. This function returns the balance of the specified address. + +### 3. transfer + +On line 85, we define the `transfer` function. This function transfers tokens from the sender to the specified recipient. + +### 4. allowance + +On line 87, we define the `allowance` function. This function returns the amount of tokens that the spender is allowed to spend on behalf of the owner. + +### 5. approve + +On line 89, we define the `approve` function. When called, this function approves a spender to spend the specified amount of tokens on behalf of the sender. + +### 6. transferFrom + +On line 91, we define the `transferFrom` function. This function transfers tokens from the specified sender to the recipient. The function can only be called by the spender if the spender is allowed to spend the specified amount of tokens on behalf of the sender. + +### 7. Events + +On lines 102-103, we define the `Transfer` and `Approval` events. These events are emitted when the `transfer` and `approve` functions are called, respectively. + +## IWETH Interface + +On line 106, we define the `IWETH` interface. This interface extends the `IERC20` interface and defines two additional functions: + +### 1. deposit + +On line 107, we define the `deposit` function. This function deposits ETH into the contract and returns the equivalent amount of WETH. This function is used to wrap ETH into WETH. +We need to wrap ETH into WETH because the Uniswap V3 Swap contract only supports ERC-20 tokens. + +### 2. withdraw + +On line 109, we define the `withdraw` function. This function withdraws the specified amount of WETH from the contract and returns the equivalent amount of ETH. This function is used to unwrap WETH into ETH. + +## Conclusion + +In this tutorial, we explored the Uniswap V3 Swap contract. To get a full sense of how Uniswap works, try making some swaps on the Uniswap DApp and go to the Uniswap docs. diff --git a/locales/fr/Uniswap-Tutorial/README.md b/locales/fr/Uniswap-Tutorial/README.md new file mode 100644 index 000000000..cf66c5582 --- /dev/null +++ b/locales/fr/Uniswap-Tutorial/README.md @@ -0,0 +1,5 @@ +# Uniswap Swap Course + +Review the code of the Uniswap V3 Swap contract for performing token swaps. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/fr/Uniswap-Tutorial/config.yml b/locales/fr/Uniswap-Tutorial/config.yml new file mode 100644 index 000000000..f49f02abc --- /dev/null +++ b/locales/fr/Uniswap-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: uniswapSwapCourse +name: Uniswap Swap Course +summary: Go through the Solidity code of the Uniswap V3 Swap contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - Uniswap +steps: + - + name: 1. Introduction + path: 1-introduction-to-uniswap + - + name: 2. Routers, Interfaces, and Structs + path: 2-router-interfaces-and-structs + - + name: 3. Single Hop Swaps + path: 3-single-hop-swaps + - + name: 4. Multi-Hop Swaps + path: 4-multi-hop-swaps + - + name: 5. Erc20 and Weth Interfaces + path: 5-erc20-weth-interfaces diff --git a/locales/fr/Web3Client/1_Using_Web3/Running_a_script.md b/locales/fr/Web3Client/1_Using_Web3/Running_a_script.md new file mode 100644 index 000000000..3b7b23332 --- /dev/null +++ b/locales/fr/Web3Client/1_Using_Web3/Running_a_script.md @@ -0,0 +1,24 @@ +## Querying the Blockchain + +In this tutorial, we'll run a script that queries the blockchain using a JavaScript library. + +This means that instead of using the Remix GUI or a block explorer like Etherscan, we'll use a script in the editor and will run it from the terminal. + +The JS libraries that are used the most for interacting with the blockchain are web3.js & ethers.js. + +Let's begin with a simple web3.js example, queryBlockNum.js. + +The script's call to web3.js is wrapped in a self-executing async function that contains a try/catch block. + +We'll query the current blocknumber with: +`let blockNumber = await web3.eth.getBlockNumber()` + +Note that the object `web3` is injected by Remix. For more info on web3.js, check their docs, https://web3js.readthedocs.io. + +To use web3.js or ethers.js, you need to select the **Injected Web3** or **Web3 Provider** environment in the **Deploy & Run** module. Scripts don't currently work with the JSVM. **If you try, you'll get an error.** + +So for this example choose **Injected Web3** in the Deploy & Run module and have Metamask installed. + +From the terminal, execute `remix.execute()`. This command will execute the current JavaScript file with the line `let blockNumber = await web3.eth.getBlockNumber()`. + +In the console, you should see the current block number of the chain that metamask is connected to. diff --git a/locales/fr/Web3Client/2_Querying_a_Contract/queryContract.md b/locales/fr/Web3Client/2_Querying_a_Contract/queryContract.md new file mode 100644 index 000000000..461c98244 --- /dev/null +++ b/locales/fr/Web3Client/2_Querying_a_Contract/queryContract.md @@ -0,0 +1,23 @@ +Now that we know how to query simple data, let's try a more complex query. + +This is a contract deployed to the mainnet - at this address: https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code + +We are going to query the contract to find the name of it's token. + +The **name** variable is a state variable of the contract. + +To access this **mainnet** contract, we need to do some setup. + +1. Switch to the mainnet in metamask. +2. You'll probably need to refresh Remix. +3. As a result of the refresh, you may need to reload this tutorial too. +4. Go to Deploy & Run and switch to **Injected Web3**. + +**Using Web3** +In the script, queryContract.js, we need to instantiate a new instance of web3.eth.Contract object. For this we need to grab the contract's ABI and its address. The source code & ABI is available in etherscan because the contract's developer intentionally published it. + +In etherscan, we can see that its name is **TetherToken**. Scrolling down to the TetherToken contract in the source code section of etherscan, we can see the state variables for the contract - the first of which is named **name**. + +There are a few syntactic hoops to jump through to return the value of the state variable. + +- To call the autogenerated getter function of the public state variable, you need to both treat the variable as a function (by adding parentheses) and also to tack on a call(). diff --git a/locales/fr/Web3Client/README.md b/locales/fr/Web3Client/README.md new file mode 100644 index 000000000..a319f312f --- /dev/null +++ b/locales/fr/Web3Client/README.md @@ -0,0 +1 @@ +This workshop is about using the web3.js to interact with a contract and more generally to the blockchain. diff --git a/locales/fr/Web3Client/config.yml b/locales/fr/Web3Client/config.yml new file mode 100644 index 000000000..07cb1760c --- /dev/null +++ b/locales/fr/Web3Client/config.yml @@ -0,0 +1,9 @@ +--- +id: useofweb3js +name: Basic use of web3.js +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 2 +tags: + - JS + - Remix + - Web3 diff --git a/locales/it/Basics/README.md b/locales/it/Basics/README.md new file mode 100644 index 000000000..f1f1cce4d --- /dev/null +++ b/locales/it/Basics/README.md @@ -0,0 +1,3 @@ +## Caricare, Compilare, Distribuire + +This beginner level tutorial introduces Remix's interface and concepts used in Ethereum. diff --git a/locales/it/Basics/config.yml b/locales/it/Basics/config.yml new file mode 100644 index 000000000..8c160b545 --- /dev/null +++ b/locales/it/Basics/config.yml @@ -0,0 +1,26 @@ +--- +id: basics +name: Basics of Remix +summary: A typical workflow in Remix +level: 1 +tags: + - Remix +steps: + - + name: Intro to the Interface + path: interface_introduction + - + name: Intro to Workspaces + path: workspaces + - + name: Loading & Compiling + path: load_and_compile + - + name: Deploying to the Remix VM + path: deploy_to_the_remixvm + - + name: Interacting with Functions + path: interacting + - + name: Deploying to Public Networks + path: deploy_injected diff --git a/locales/it/Basics/deploy_injected/README.md b/locales/it/Basics/deploy_injected/README.md new file mode 100644 index 000000000..172396527 --- /dev/null +++ b/locales/it/Basics/deploy_injected/README.md @@ -0,0 +1,21 @@ +1. If you don't have a browser wallet like **MetaMask** download and install one now. + +2. Click the MetaMask icon in your browser. Sign in and choose the Ephemery test network. You might need to update your wallet's settings so that you can see **test networks**. Alternatively, you can go to Remix's Deploy & Run transation module and in the ENVIRONMENT section select Ephemery. + +3. Getting test ETH for public test networks is often annoying. Ephemery is a public network that is refreshed monthly, so getting test ETH should be painless. Here is a link to some Ephemery faucets. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/testnet.png) + +Sepolia is another popular testnet that is not refreshed, so deployments will persist, but Sepolia faucets are more difficult to use. + +In your browser wallet make sure that you have NOT selected mainnet or any network that will cost real ETH. In the Deploy & Run module, below the Environment select box, you'll see a badge with the network's ID and for popular chains, its name. In the case below its Sepolia. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/sepolia.png) + +5. Make sure you see the 2_Owner.sol as a choice in the **CONTRACT** select box, then click the **Deploy** button. + +If the **CONTRACT** select box is empty, you'll need to compile 2_Owner again by making 2_Owner.sol the active file in the **editor** and then go to the **Solidity Compiler** to compile it. + +6. After you hit the `Deploy` button, you'll see the browser wallet popup asking you to pay for the transactions. If you have the appropriate kind of ETH for this chain, approve this transaction. Check the printout in the terminal. Once the block is validated, the **deployed instance** will appear at the bottom of Deploy & Run + +And with that you have finished this tutorial. You now have experience with opening, compiling, deploying and interacting with Smart Contracts in Remix IDE. diff --git a/locales/it/Basics/deploy_to_the_remixvm/README.md b/locales/it/Basics/deploy_to_the_remixvm/README.md new file mode 100644 index 000000000..8035d631b --- /dev/null +++ b/locales/it/Basics/deploy_to_the_remixvm/README.md @@ -0,0 +1,15 @@ +In the previous chapter, we compiled a contract - which is to say the Solidity code has been transformed into little chunks of Ethereum Virtual Machine (EVM) bytecode. + +Now we will put that code on a test blockchain. + +1. Click the Deploy and Run icon ![deploy & run icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_to_the_remixvm/images/run.png "deploy & run icon"). + +2. Select one of the **Remix VM**s from the **Environment** pulldown. + +3. Click the Deploy button (or the transact button in the expanded view). + +4. You have deployed your compiled contract to the Remix VM - a simulated blockchain that is running inside of your browser window. The Remix VM is simple, fast test chain. It is not that realistic because you don't need to approve each transaction. + +5. Check the terminal to see detail of this deployment transaction. + +You can also use Remix to deploy to other public EVM chains. To do this, you'll need to connect to a different **Environment** - like Injected Provider. The Injected Provider connects Remix to browser wallet (like MetaMask or similar). We'll try deploying to a public network at the end of this tutorial. But before we get there, we'll cover how to interact with a deployed contract's functions. diff --git a/locales/it/Basics/interacting/README.md b/locales/it/Basics/interacting/README.md new file mode 100644 index 000000000..088a6ac6f --- /dev/null +++ b/locales/it/Basics/interacting/README.md @@ -0,0 +1,19 @@ +## Accessing functions in a deployed contract + +1. When a contract has been successfully deployed, it will appear at the bottom of the Deploy and Run plugin. Open up the contract by clicking the caret - so the caret points down. + ![distribuisci il contratto](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/instance.png "contratto distribuito") + +2. There are 2 functions in this contract. To input the parameters individually, clicking the caret to the right of changeOwner (outlined in red below). In the expanded view, each parameter has its own input box. + +![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/deployed_open2.png "deployed contract") + +If this contract had imported other contracts, then the functions of the imported contracts would also be visible here. At some point, try playing with An ERC20 contract to see all its many functions. + +3. Functions with blue buttons are either **pure** or **view** functions. This means that they are just reading a property or are returning a value. In other words, they aren't saving anything - so they are FREE (they don’t cost gas). Functions with other colors - usually orange (depending on the Remix theme) cost gas because they are saving information. They are creating a **transaction**. + +4. 2_Owner.sol does not have a **payable** function. If it did, the button's color would be red. Payable functions allow you to send Ether to the function. To send ETH with a payable function, you put the amount you want to send in the **value** field towards the top of the Deploy & Run module. + +5. In the Remix VM, you don't need to approve a transaction. When using a more realistic test environment or when using the mainnet - you will need to approve the transactions for them to go through. Approving a transaction costs gas. + +6. Choosing a public network is not done in Remix but in your Browser Wallet. There is a plug icon to the right of the Environment title that links to chainlist.org where you can get the specs of the chain you want to interact with. + ![chainlist](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/chainlist.png "chainlist") diff --git a/locales/it/Basics/interface_introduction/README.md b/locales/it/Basics/interface_introduction/README.md new file mode 100644 index 000000000..76c953fbd --- /dev/null +++ b/locales/it/Basics/interface_introduction/README.md @@ -0,0 +1,15 @@ +## Remix is composed of four panels. + +![Remix layout](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/a-layout1c.png "Remix layout") + +- Most plugins appear in the **Side Panel**. +- Editing code happens in tabs in the **Main Panel**. +- The results of transactions and other actions are visible in the **Terminal**. +- Switching between plugins happens in the **Icons Panel**. +- To make a panel larger, drag its border. + +Try clicking the **Solidity Compiler** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/solidity-icon.png) in the **Icons Panel**. Then click the **Deploy & Run** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/deploy-run.png). Then come back to **LearnEth** by clicking this icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/learneth.png). + +In the **Main Panel** of Remix, make sure you see the **Home** tab. The **Home** tab has lots of useful links. To navigate there, either click the **Home** tab in the **Main Panel** or click the Remix icon ![Remix icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/remix-logo.png "Remix icon") on the top of the icon panel. + +- See all the plugins in the **Plugin Manager**. Click this icon ![plugin manager](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/plugin1.png "Plugin Manager icon") in the lower left corner Remix. diff --git a/locales/it/Basics/load_and_compile/README.md b/locales/it/Basics/load_and_compile/README.md new file mode 100644 index 000000000..a666d5d13 --- /dev/null +++ b/locales/it/Basics/load_and_compile/README.md @@ -0,0 +1,20 @@ +Let's load a file from the File Explorer into the Editor. + +1. In the icon panel, click ![file explorer icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/files1.png "file explorer icon") , the File Explorer's icon. + +2. Make sure you are in the **default_workspace**. + +![default workspace](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/default_workspace_open.png) + +3. Open the contracts folder and click on **2_Owner.sol** in the contracts folder. Click it. The file will appear in a tab in the main panel. + +4. In the icon panel, click the **Solidity Compiler** ![solidity compiler icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/solidity1.png "solidity compiler icon"). The Solidity compiler should now be in the side panel. + +5. Click the compile button. + ![compile 2\_owner](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/compile2owner.png "compile 2_Owner") + +6. Compiling can also be triggered by hitting **CTRL + S**. + +The spinner will turn while the file is compiling. + +**Note:** The spinner also turns when the compiler itself is loading. To choose a **different version of Solidity**, go to the select box at the top of the plugin. diff --git a/locales/it/Basics/workspaces/README.md b/locales/it/Basics/workspaces/README.md new file mode 100644 index 000000000..97a47d283 --- /dev/null +++ b/locales/it/Basics/workspaces/README.md @@ -0,0 +1,23 @@ +## Workspaces help organize your separate projects. + +If this is your first time to Remix, a Workspace named **default_workspace** is loaded in the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/default_workspace.png) + +The **default_workspace** has three Solidity (.sol) files in the contracts folder. Remix has a number of other templates. When you load a template, it goes into a Workspace. To go between Workspaces, use the select box at the top of the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/select-box.png) + +But Workspaces are not only for templates. When cloning a repo into Remix, the files will be put into a Workspace. + +Let's create a new Workspace + +1. At the top of the File Explorer, click the hamburger icon (the 3 horizontal lines). Read through the commands and tools in this menu. + +2. Select **+ Create** (the first choice). + +3. In the modal the comes up, choose one of the templates. + +![hamburger](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/workspaces/images/popup.png) + +Notice that in this popup menu, you can clone a repo. Managing a Git repo happens in the DGit plugin. You can also create Github actions with the three workflow choices in the popup menu. diff --git a/locales/it/CircomHashChecker/README.md b/locales/it/CircomHashChecker/README.md new file mode 100644 index 000000000..20391a668 --- /dev/null +++ b/locales/it/CircomHashChecker/README.md @@ -0,0 +1,14 @@ +Hash Checker Tutorial + +This tutorial guides you through creating and understanding a Hash Checker circuit using Remix-IDE. You'll learn how to generate the circuit using a template, explore the code, perform a trusted setup, generate proofs, and verify them. This tutorial is suitable for beginners familiar with Circom and Zero-Knowledge Proofs. + +Prerequisites + +``` +Basic understanding of Zero-Knowledge Proofs and Circom. +Familiarity with Remix-IDE. +``` + +Estimated Time + +Approximately 1-2 hours. diff --git a/locales/it/CircomHashChecker/config.yml b/locales/it/CircomHashChecker/config.yml new file mode 100644 index 000000000..2c2aae80a --- /dev/null +++ b/locales/it/CircomHashChecker/config.yml @@ -0,0 +1,35 @@ +id: circom-hash-checker +name: Hash Checker Tutorial +summary: A tutorial on creating and understanding a Hash Checker circuit using Remix-IDE templates, including trusted setup and proof generation. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction to the Hash Checker Circuit + path: step-1 + - + name: Generating the Hash Checker Template in Remix-IDE + path: step-2 + - + name: Exploring calculate_hash.circom + path: step-3 + - + name: Compiling the Circuit + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Compute Witness + path: step-6 + - + name: Generate Proof + path: step-7 + - + name: Exploring the Trusted Setup Script (Optional) + path: step-8 + - + name: Exploring the Proof Generation Script (Optional) + path: step-9 diff --git a/locales/it/CircomHashChecker/step-1/README.md b/locales/it/CircomHashChecker/step-1/README.md new file mode 100644 index 000000000..be922e93b --- /dev/null +++ b/locales/it/CircomHashChecker/step-1/README.md @@ -0,0 +1,8 @@ +In this tutorial, we'll explore the **Hash Checker** circuit, a zero-knowledge proof (ZKP) application using Circom and Remix-IDE. The Hash Checker circuit allows you to prove knowledge of certain inputs that hash to a given value without revealing the inputs themselves. + +### What You'll Learn + +- How to generate a Hash Checker circuit using Remix-IDE's workspace templates. +- Understanding the Circom code for hashing and checking hashes. +- Performing a trusted setup using Groth16. +- Generating zero-knowledge proofs. diff --git a/locales/it/CircomHashChecker/step-2/README.md b/locales/it/CircomHashChecker/step-2/README.md new file mode 100644 index 000000000..bc827019e --- /dev/null +++ b/locales/it/CircomHashChecker/step-2/README.md @@ -0,0 +1,37 @@ +Follow these steps to create the Hash Checker workspace in Remix-IDE. + +### Step 1: Access the Workspace Templates + +1. In the **File Explorer** sidebar, click on the **hamburger menu icon** (three horizontal lines). + + hamburger-menu + +2. Select **"Create Using Template"** from the dropdown. + + create-using-template + +### Step 2: Find the Hash Checker Template + +1. In the main panel, scroll down to the **"Circom ZKP"** section. + + create-zkp-section + +2. Locate the **"Hash Checker"** item. + +### Step 3: Create the Workspace + +1. Click on the **"Create"** button on the Hash Checker item. + + create-hash-checker + +2. In the modal pop-up, provide a **workspace name** (e.g., `hash-checker-workspace`). + + workspace-name-modal + +3. Click **"OK"** to create the template. + +### Result + +- The workspace is created with the necessary files and directories. + + workspace-name-modal diff --git a/locales/it/CircomHashChecker/step-3/README.md b/locales/it/CircomHashChecker/step-3/README.md new file mode 100644 index 000000000..b3ac14050 --- /dev/null +++ b/locales/it/CircomHashChecker/step-3/README.md @@ -0,0 +1,32 @@ +## Exploring `calculate_hash.circom` + +Navigate to the `circuits` directory and open `calculate_hash.circom`. This file contains the Circom code for the Hash Checker circuit. + +### Code Breakdown + +#### Pragma and Includes: + +- `pragma circom 2.0.0;` specifies the Circom version. +- `include "circomlib/circuits/poseidon.circom";` fetch and includes the Poseidon hash function from [CircomLib](https://github.com/iden3/circomlib). + +#### `CalculateHash` Template: + +- Defines inputs `value1`, `value2`, `value3`, `value4`. +- Uses the `Poseidon` hash function to compute a hash of these values.\ +- Outputs `out`, which is the hash. + +#### `HashChecker` Template: + +- Inputs are the same values plus a `hash`. +- Instantiates `CalculateHash` as `calculateSecret`. +- Computes `calculatedHash`. +- Uses `assert(hash == calculatedHash);` to ensure the provided hash matches the calculated hash. + +#### Main Component: + +- `component main {public [hash]} = HashChecker();` +- Specifies that `hash` is a `public` input, while the values are `private`. + +### Purpose + +The circuit allows someone to prove they know `value1`, `value2`, `value3`, and `value4` that hash to a specific `hash` without revealing the values themselves. diff --git a/locales/it/CircomHashChecker/step-4/README.md b/locales/it/CircomHashChecker/step-4/README.md new file mode 100644 index 000000000..537c6a241 --- /dev/null +++ b/locales/it/CircomHashChecker/step-4/README.md @@ -0,0 +1,32 @@ +## Compiling the Circuit + +### Selecting the Compiler Version + +1. Go to the **Circuit Compiler** plugin in the sidebar. +2. Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +### Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +### Compiling the Circuit + +1. Click on the **Compile** button. +2. Wait for the compilation to complete. A success badge will appear if compilation is successful. + +compilation-success + +### Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/it/CircomHashChecker/step-5/README.md b/locales/it/CircomHashChecker/step-5/README.md new file mode 100644 index 000000000..c3ea8509b --- /dev/null +++ b/locales/it/CircomHashChecker/step-5/README.md @@ -0,0 +1,25 @@ +## Performing a Trusted Setup + +1. **Access the Setup and Exports Section**: + +- After successful compilation, the **Setup and Exports** section becomes available in the plugin. + +2. **Select Proving Scheme**: + +- Choose **Groth16** from the **Proving Scheme** dropdown. + +3. **Select Power of Tau File**: + +- Choose the appropriate **Power of Tau** file from the dropdown. If unsure, use the default option. + +4. **Export Verification Key and Contract** (optional): + +- Enable **Export Verification Key** to save the verification key to the File Explorer. +- Enable **Export Verifier Contract** to save the Solidity contract for on-chain verification. + +trusted-setup + +5. **Run the Trusted Setup**: + +- Click on the **Run Setup** button. +- Wait for the process to complete. This may take some time depending on the circuit complexity. diff --git a/locales/it/CircomHashChecker/step-6/README.md b/locales/it/CircomHashChecker/step-6/README.md new file mode 100644 index 000000000..03b848f81 --- /dev/null +++ b/locales/it/CircomHashChecker/step-6/README.md @@ -0,0 +1,28 @@ +## Compute Witness + +1. **Access the Compute Witness Section**: + - After the trusted setup, the **Compute Witness** section becomes available. + +2. **Input Values**: + - You'll see input fields for `value1`, `value2`, `value3`, `value4`, and `hash`. + - Enter values for each input. For example: + - `value1`: `1234` + - `value2`: `2` + - `value3`: `3` + - `value4`: `4` + +3. **Calculate the Hash**: + + - Compute the Poseidon hash of the four values using an external tool or library compatible with the Poseidon hash function. + - For the values above, here is the computed Poseidon hash `16382790289988537028417564277589554649233048801038362947503054340165041751802`. + - Enter the calculated `hash` value in the `hash` input field. + + compute-witness + +4. **Compute the Witness**: + + - Click on the **Compute Witness** button. + - Wait for the process to complete. A success badge will appear if the witness is computed successfully. + - If successful, you'll see `calculate_hash.wtn` created in the `.bin` directory in the file explorer. + + witness-computed diff --git a/locales/it/CircomHashChecker/step-7/README.md b/locales/it/CircomHashChecker/step-7/README.md new file mode 100644 index 000000000..e6ae80fea --- /dev/null +++ b/locales/it/CircomHashChecker/step-7/README.md @@ -0,0 +1,21 @@ +## Generate Proof + +1. **Access the Generate Proof Section**: + - After computing the witness, expand the **Generate Proof** section. + +2. **Configure Proof Generation**: + - **Export Verifier Calldata**: Enable this option if you plan to verify the proof on-chain. + +3. **Generate the Proof**: + + - Click on the **Generate Proof** button. + - Wait for the proof generation to complete. + + generate-proof + +4. **View the Proof**: + + - The proof data will be displayed in the File Explorer. + - **Congratulations!** You've successfully compiled the `Hash Checker` circuit, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + + generate-proof diff --git a/locales/it/CircomHashChecker/step-8/README.md b/locales/it/CircomHashChecker/step-8/README.md new file mode 100644 index 000000000..e489a8cab --- /dev/null +++ b/locales/it/CircomHashChecker/step-8/README.md @@ -0,0 +1,34 @@ +## Understanding `groth16_trusted_setup.ts` + +Navigate to `scripts/groth16/groth16_trusted_setup.ts`. This script performs the trusted setup necessary for generating proofs. + +### Code Breakdown + +#### Circuit Compilation: + +- Uses `remix.call('circuit-compiler', 'generateR1cs', ...)` to generate `R1CS` (Rank-1 Constraint System) from the circuit. + +#### Trusted Setup Steps: + +- `snarkjs.zKey.newZKey`: Initializes the proving key (`zkey_0`). +- `snarkjs.zKey.contribute`: Adds contributions to the proving key (`zkey_1`). +- `snarkjs.zKey.beacon`: Finalizes the proving key (`zkey_final`). + +#### Verification: + +- `snarkjs.zKey.verifyFromR1cs`: Verifies the proving key against the `R1CS` and initial parameters. + +#### Exporting Keys: + +- Exports the verification key to `scripts/groth16/zk/keys/verification_key.json`. +- Exports the final proving key (`scripts/groth16/zk/keys/zkey_final.txt`). + +### Purpose + +- Performs the trusted setup required for the `Groth16` proving system. +- Generates the necessary keys for proof generation and verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"setup done."` logged in the terminal. diff --git a/locales/it/CircomHashChecker/step-9/README.md b/locales/it/CircomHashChecker/step-9/README.md new file mode 100644 index 000000000..653d5ced1 --- /dev/null +++ b/locales/it/CircomHashChecker/step-9/README.md @@ -0,0 +1,37 @@ +## Understanding `groth16_zkproof.ts` + +Navigate to `scripts/groth16/groth16_zkproof.ts`. This script generates the zero-knowledge proof and prepares it for verification. + +### Code Overview + +#### Loading Files: + +- Reads the R1CS and WASM files generated from the circuit. +- Loads the final proving key (`zkey_final`) and verification key (`vKey`). + +#### Defining Inputs: + +- Sets the private values (`value1`, `value2`, `value3`, `value4`). +- Computes the `hash` using Poseidon from [CircomLib](https://github.com/iden3/circomlib). + +#### Witness Calculation and Proof Generation: + +- Calculates the witness (`wtns`). +- Checks the witness against the `R1CS`. +- Generates the proof using `Groth16`. +- Verifies the proof. + +#### Exporting Verifier Contract and Inputs: + +- Generates a Solidity verifier contract. +- Exports the proof inputs to `input.json`. + +### Purpose + +- Generates a zero-knowledge proof that the prover knows values hashing to a specific hash. +- Prepares the verifier contract and inputs for on-chain verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"zk proof validity"` logged in the terminal. diff --git a/locales/it/CircomIntro/README.md b/locales/it/CircomIntro/README.md new file mode 100644 index 000000000..c58b2daec --- /dev/null +++ b/locales/it/CircomIntro/README.md @@ -0,0 +1,21 @@ +Intro to Circom + +This is an introduction to Circom. You'll learn how to write, compile, and test arithmetic circuits in Circom. We'll go over how to do this within Remix-IDE. + +Tutorial Overview + +``` +Step 1: Introduction +Step 2: Setting Up Remix-IDE and Installing the Circuit-Compiler Plugin +Step 3: Writing Your First Circom Circuit +Step 4: Compiling the Circuit Using the Plugin +Step 5: Performing a Trusted Setup +Step 6: Computing the Witness +Step 7: Generating the Proof +``` + +Prerequisites: + +``` +Basic understanding of cryptography and zero-knowledge proofs is helpful but not required. +``` diff --git a/locales/it/CircomIntro/config.yml b/locales/it/CircomIntro/config.yml new file mode 100644 index 000000000..d6dfdca46 --- /dev/null +++ b/locales/it/CircomIntro/config.yml @@ -0,0 +1,29 @@ +id: circom-intro +name: Intro to Circom +summary: A intro to using Circom for creating arithmetic circuits. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction + path: step-1 + - + name: Installing the Circuit-Compiler + path: step-2 + - + name: Writing Your First Circom Circuit + path: step-3 + - + name: Compiling the Circuit Using the Plugin + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Computing the Witness + path: step-6 + - + name: Generating the Proof + path: step-7 diff --git a/locales/it/CircomIntro/step-1/README.md b/locales/it/CircomIntro/step-1/README.md new file mode 100644 index 000000000..0766ce6f4 --- /dev/null +++ b/locales/it/CircomIntro/step-1/README.md @@ -0,0 +1,13 @@ +Welcome to this beginner-level tutorial on Circom using Remix. In this tutorial, you'll learn the basics of Circom, a domain-specific language used for creating arithmetic circuits. + +**What is Circom?** + +Circom is a language designed for writing arithmetic circuits that can be used in zero-knowledge proofs, particularly zk-SNARKs. It allows developers to define complex mathematical circuits that can prove knowledge of certain data without revealing it. + +**Why Use Remix-IDE for Circom?** + +- **Ease of Use:** Remix-IDE provides a user-friendly interface that simplifies the development process. +- **Integrated Tools:** With plugins like `circuit-compiler`, you can compile Circom code, perform trusted setups, compute witnesses, and generate proofs all within the same environment. +- **No Installation Required:** As a web-based IDE, you can start coding immediately without setting up a local development environment. + +In the next steps, we'll guide you through setting up Remix-IDE for Circom development and help you write your first circuit. diff --git a/locales/it/CircomIntro/step-2/README.md b/locales/it/CircomIntro/step-2/README.md new file mode 100644 index 000000000..4b228c298 --- /dev/null +++ b/locales/it/CircomIntro/step-2/README.md @@ -0,0 +1,25 @@ +In this step, we'll set up Remix for Circom development by activating the `Circom ZKP compiler` plugin. + +## Activating the Circom ZKP compiler + +1. At the bottom of the icon panel on the left of the screen, click on the **Plugin Manager** (the plug icon). + 2.In the search bar, type **Circom**. +2. Find the **Circuit Compiler** plugin in the list and click on the **Activate** button. +3. The plugin will now appear in your sidebar. + +install-plugin + +## The Circom Compiler Interface + +- **Compiler Version Dropdown:** Select the Circom compiler version you wish to use. +- **Auto Compile Checkbox:** Enable this to automatically compile your circuit whenever you make changes. +- **Hide Warnings Checkbox:** Enable this to suppress compiler warnings. +- **Advanced Configuration:** Click to expand options for selecting the prime field (e.g., BN128, BLS12381). + +compiler-interface + +With the plugin installed, you're now ready to start writing Circom code in Remix-IDE. + +**Note:** Make sure your internet connection is stable, as Remix-IDE is a web-based tool. + +In the next step, we'll write our first Circom circuit. diff --git a/locales/it/CircomIntro/step-3/README.md b/locales/it/CircomIntro/step-3/README.md new file mode 100644 index 000000000..6424668f6 --- /dev/null +++ b/locales/it/CircomIntro/step-3/README.md @@ -0,0 +1,38 @@ +Let's write a simple Circom circuit. + +## Creating a New Circuit File + +1. In the **File Explorer** on the left sidebar, click on the **Create New File** icon. +2. Name your file `multiplier.circom` and press **Enter**. + +create-new-file + +## Writing the Circuit + +Open `multiplier.circom` and add the following code: + +```circom +pragma circom 2.0.0; + +template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; +} + +component main = Multiplier(); +``` + +## Explanation: + +- template `Multiplier()`: Defines a new circuit template called Multiplier. +- `signal input a;` and `signal input b;`: Declare input signals a and b. +- `signal output c;`: Declare an output signal c. +- `c <== a * b;`: Constrain c to be the product of a and b. +- `component main = Multiplier();`: Instantiates the Multiplier circuit as main, which is required for the compiler. + +### NB: + +Signals are values in a cryptographic circuit that are strictly determined by the circuit's equations and constraints. Think of a signal as a value that must follow specific mathematical rules defined by the circuit—once set, it can't be changed arbitrarily. In regular programming, variables are flexible and can be updated or reassigned as needed, whereas, signals can't be altered freely. diff --git a/locales/it/CircomIntro/step-4/README.md b/locales/it/CircomIntro/step-4/README.md new file mode 100644 index 000000000..ad3f2a089 --- /dev/null +++ b/locales/it/CircomIntro/step-4/README.md @@ -0,0 +1,34 @@ +With your `multiplier.circom` circuit ready, let's compile it using the Circuit Compiler plugin. + +## Selecting the Compiler Version + +Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +## Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +## Compiling the Circuit + +1. Click on the **Compile** button. +2. The compiler will process your circuit. +3. If successful, you'll see a compilation success message. + +compilation-success + +**Note:** If there are any errors, they will be displayed in the console. Check your code for typos or syntax errors. + +## Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/it/CircomIntro/step-5/README.md b/locales/it/CircomIntro/step-5/README.md new file mode 100644 index 000000000..8e8496bbd --- /dev/null +++ b/locales/it/CircomIntro/step-5/README.md @@ -0,0 +1,26 @@ +After compiling your circuit, you need to perform a trusted setup to generate proving and verification keys. + +## Understanding Trusted Setup + +- **Trusted Setup:** A process required for zk-SNARKs to generate the necessary parameters for proof generation and verification. +- You can choose between different protocols like **Groth16** and **Plonk**. + +## Performing the Trusted Setup + +1. In the **Setup and Exports** section, select the **Proving Scheme**: + - Choose between **Groth16** or **Plonk**. We'll use **Groth16** for this tutorial. + +2. Choose the appropriate **Power of Tau** file from the dropdown. This file is necessary for the trusted setup. + - If unsure, select the default option. + +3. Click on the **Setup** button to start the trusted setup process. + +4. You can enable **Export Verification Key** to get the verification parameters. + +5. You can enable **Export Verification Contract** if you intend to verify proofs on-chain. + +trusted-setup + +**Note:** The trusted setup may take some time, depending on the complexity of your circuit. + +In the next step, we'll compute the witness for our circuit. diff --git a/locales/it/CircomIntro/step-6/README.md b/locales/it/CircomIntro/step-6/README.md new file mode 100644 index 000000000..e13d33d32 --- /dev/null +++ b/locales/it/CircomIntro/step-6/README.md @@ -0,0 +1,27 @@ +With the trusted setup complete, you can now compute the witness for your circuit based on specific inputs. + +## What is a Witness? + +- A **Witness** is a set of values that satisfy all the constraints of your circuit. It includes all the intermediate numbers and results that satisfy the circuit's rules. The witness is used in zero-knowledge proofs to demonstrate that you know a valid solution to the problem without actually showing the solution itself. This allows others to verify that you did everything correctly while keeping your specific numbers and calculations private. +- It is essential for generating a proof. + +## Inputting Values + +1. In the **Compute Witness** section, you'll see input fields dynamically generated based on your circuit's inputs. +2. Enter values for `a` and `b`. For example: + - `a = 3` + - `b = 4` + +compute-witness + +## Computing the Witness + +1. After entering the inputs, click on the **Compute Witness** button. +2. The plugin will compute the witness based on your inputs. +3. If successful, you'll see `multiplier.wtn` created in the `.bin` directory in the file explorer. + +witness-computed + +**Note:** If there are any errors, ensure that your inputs are valid and satisfy the circuit's constraints. + +In the next step, we'll generate a proof using the computed witness. diff --git a/locales/it/CircomIntro/step-7/README.md b/locales/it/CircomIntro/step-7/README.md new file mode 100644 index 000000000..f5cf332a9 --- /dev/null +++ b/locales/it/CircomIntro/step-7/README.md @@ -0,0 +1,31 @@ +With the witness computed, the final step is to generate a proof that can be verified by others. + +## Generating the Proof + +1. In the **Generate Proof** section, you have the option to **Export Verifier Calldata**. + - Enable the **Export Verifier Calldata** checkbox if you plan to verify the proof on-chain. +2. Click on the **Generate Proof** button. + +generate-proof + +## Understanding the Output + +- After generating the proof, the plugin will display the proof data. +- If you enabled **Export Verifier Calldata**, it will also provide the calldata needed for on-chain verification. + +proof-generated + +## Next Steps + +- **Verification:** You can use the verification key or contract exported earlier to verify the proof. +- **On-Chain Verification:** If you're familiar with smart contracts, you can deploy the verification contract and use the calldata to perform on-chain verification. + +**Congratulations!** You've successfully written a Circom circuit, compiled it, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + +## Additional Resources + +- [Circom Documentation](https://docs.circom.io/) +- [Remix-IDE Documentation](https://remix-ide.readthedocs.io/) +- [Zero-Knowledge Proofs Explained](https://zkproof.org/) + +Feel free to experiment with more complex circuits and explore the capabilities of Circom and Remix-IDE further. diff --git a/locales/it/DeployWithLibraries/1_Writing_a_Library/step1.md b/locales/it/DeployWithLibraries/1_Writing_a_Library/step1.md new file mode 100644 index 000000000..1ad984835 --- /dev/null +++ b/locales/it/DeployWithLibraries/1_Writing_a_Library/step1.md @@ -0,0 +1,17 @@ +A libraries looks like a **contract** but use the keyword `library` + +A library typically is a collection of useful functions sitting out there on the blockchain that any contract can use. Because the library is already deployed, it saves the deployment costs of the many contracts that use it. + +In the following contract: + +- Make a library with the name `LibraryForTest`. + +It is possible to put a library in same file with another contract. So put the library below the contract. + +This library should have a method called `getFromLib` method which returns `3`. + +- Update the `get` method in the `test` contract to use the `LibraryForTest` library. The function `get` should return the value it receives from `getFromLib`. + +--------- + +You can find more info about libraries in this section of the Solidity Docs. diff --git a/locales/it/DeployWithLibraries/2_Generate_Metadata/step2.md b/locales/it/DeployWithLibraries/2_Generate_Metadata/step2.md new file mode 100644 index 000000000..218c86ff9 --- /dev/null +++ b/locales/it/DeployWithLibraries/2_Generate_Metadata/step2.md @@ -0,0 +1,38 @@ +## Deploying Library + +The **library** from the previous chapter was in the same file as the **contract**. However, they won't be deployed together and will have different addresses. + +In order to use a library, the calling contract must have the library's **address**. + +But the library's address is not directly specified in the solidity code. The calling contract's compiled bytecode contains a **placeholder** where library's **addresses** will go. + +At deployment of the **calling contract**, Remix will look in the contract's **metadata** for the library's address and will update the placeholder with the address. + +So before deploying a contract that calls a library, you need to generate the contract's metadata (AKA its **build artifact**) and then you need to input the library's address into the metadata file. + +A contract's metadata is generated at **compile time**. + +Let's setup Remix to generate the **metadata file**. + +- Go to the settings module by clicking on the settings ![settings](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/settings.png "Settings") icon in the icon panel. + +![settings module](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_settings.png "Settings Module") + +- And check the first option `Generate contract metadata`. + +# Compile and generate metadata (JSON) file. + +1. Open the Solidity Compiler ![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +2. Compile `2_contractSimpleLibrary.sol`. + +3. Switch to the File Explorer ![File Explorer](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_file_explorer.png "File Explorer") + +4. Navigate to the newly create JSON files. + - It should be in the folder: + +**browser/.learneth/DeployWithLibraries/2_Generate_Metadata/artifacts/** + +5. Select the newly created JSON file created from the contract. It has the **same name** as the contract `sample` but with the extension **json**: `sample.json` (don't select the library's metadata `contractSimpleLibrary.json`). + +In the next step we'll make some adjustments to the metadata file. diff --git a/locales/it/DeployWithLibraries/3_Edit_Metadata/step3.md b/locales/it/DeployWithLibraries/3_Edit_Metadata/step3.md new file mode 100644 index 000000000..1555d645d --- /dev/null +++ b/locales/it/DeployWithLibraries/3_Edit_Metadata/step3.md @@ -0,0 +1,12 @@ +The `Deploy` property in `sampleContract.json` contains everything you need for telling Remix IDE the address of the library for a specific network. + +- `
` contains the address of the library that is already deployed. You have to specify this address for each network. +- `autoDeployLib` is a boolean and tells Remix IDE if it should autodeploy the library before deploying the contract. + +Basically if `autoDeployLib` is **true**, the `
` will not be used and Remix will automatically deploy the library before deploying the contract. + +For the purpose of this demo - we are mimicking a situation where the library has already been deployed because this is a more common situation. + +So set `autoDeploy` to **false**, for the `VM:-` entry. + +Move to next Step. diff --git a/locales/it/DeployWithLibraries/4_Linking_and_Deploying/step4.md b/locales/it/DeployWithLibraries/4_Linking_and_Deploying/step4.md new file mode 100644 index 000000000..ad5f52e2d --- /dev/null +++ b/locales/it/DeployWithLibraries/4_Linking_and_Deploying/step4.md @@ -0,0 +1,25 @@ +Switch to the `Deploy & Run` module +![Run transaction](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/remix_runtransaction.png "Run Transaction") + +- Select the Remix VM Environment and select the `sampleContract` contract in the list of compiled contracts. + +- Click on `Deploy` + +The terminal should output something like `creation of sample errored:
is not a valid address. Please check the provided address is valid.` +That is expected: **We have set `autoDeployLib` to false, so Remix expects to have an address and not just `
`** + +So we need deploy the library to get its address. + +- Select the library `aLib` in the list of compiled contract and hit `deploy` + + ![Choose aLib](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/contract_alib.png "Choose aLib") + +- Click the clipboard icon to copy the address of the library. + + ![Copy lib1](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/alib_copy.png "Copy") + +- Paste it into the **contract sample's** metadata JSON. + +- Reselect the `sampleContract` contract in the `Run transaction` module and hit deploy. + +- Deploy should now be successful. diff --git a/locales/it/DeployWithLibraries/5_Under_The_Hood/step5.md b/locales/it/DeployWithLibraries/5_Under_The_Hood/step5.md new file mode 100644 index 000000000..860b48b24 --- /dev/null +++ b/locales/it/DeployWithLibraries/5_Under_The_Hood/step5.md @@ -0,0 +1,30 @@ +Switch to the `Solidity compiler` module +![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +- Select the `sampleContract` contract in the list of compiled contracts. +- click on `ByteCode`, it should copy the following to the clipboard: + +``` +{ + "linkReferences": { + "browser/contractSimpleLibrary.sol": { + "lib1": [ + { + "length": 20, + "start": 115 + } + ] + } + }, + "object": "608060405234801561001057600080fd5b5060f68061001f6000396000f3fe6080604052600436106039576000357c0100000000000000000000000000000000000000000000000000000000900480636d4ce63c14603e575b600080fd5b348015604957600080fd5b5060506052565b005b73__$d42d70ba92b626965f4c69b39148e37a33$__63fea24e5f6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801560b157600080fd5b505af415801560c4573d6000803e3d6000fd5b5050505056fea165627a7a7230582068c9a3a9a5cbfd26cfdab2534abfc926912d9b89eaa14e36c8248b7e7eb0ab090029", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xF6 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x39 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x3E JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x50 PUSH1 0x52 JUMP JUMPDEST STOP JUMPDEST PUSH20 0x0 PUSH4 0xFEA24E5F PUSH1 0x40 MLOAD DUP2 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH1 0xB1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS DELEGATECALL ISZERO DUP1 ISZERO PUSH1 0xC4 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 PUSH9 0xC9A3A9A5CBFD26CFDA 0xb2 MSTORE8 0x4a 0xbf 0xc9 0x26 SWAP2 0x2d SWAP12 DUP10 0xea LOG1 0x4e CALLDATASIZE 0xc8 0x24 DUP12 PUSH31 0x7EB0AB09002900000000000000000000000000000000000000000000000000 ", + "sourceMap": "63:85:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63:85:0;;;;;;;" +} +``` + +This is basically what the compiler is returning: + +- `linkReferences` describes what are the libraries used by the contract. +- `object` is the compiled contract (bytecode). This is what gets deployed and saved onto the blockchain. In this example, the value `__$d42d70ba92b626965f4c69b39148e37a33$__` inside the bytecode is just a placeholder for the library address. In your case, the placeholder will be between `__$` and `$__`. + +The metadata JSON from Remix IDE tells Remix to replace the placeholder with the given address. diff --git a/locales/it/DeployWithLibraries/README.md b/locales/it/DeployWithLibraries/README.md new file mode 100644 index 000000000..fb31b1264 --- /dev/null +++ b/locales/it/DeployWithLibraries/README.md @@ -0,0 +1,3 @@ +**Libraries** are deployed contracts that do not store state and are used by other contracts to decrease their size and thus their deployment costs. + +Learn to work with **Libraries** in Remix - you won't need to whisper. diff --git a/locales/it/DeployWithLibraries/config.yml b/locales/it/DeployWithLibraries/config.yml new file mode 100644 index 000000000..0816e2346 --- /dev/null +++ b/locales/it/DeployWithLibraries/config.yml @@ -0,0 +1,8 @@ +--- +id: deploylibraries +name: Deploy with Libraries +summary: Write, Deploy and link a Library to a Contract +level: 3 +tags: + - Remix + - Solidity diff --git a/locales/it/ERC20TokenCourse/README.md b/locales/it/ERC20TokenCourse/README.md new file mode 100644 index 000000000..25a6ccf95 --- /dev/null +++ b/locales/it/ERC20TokenCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Token Course + +Learn to understand and create ERC20 tokens. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/it/ERC20TokenCourse/config.yml b/locales/it/ERC20TokenCourse/config.yml new file mode 100644 index 000000000..8c12a5213 --- /dev/null +++ b/locales/it/ERC20TokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: tokenCourse +name: Solidity ERC20 Token Course +summary: Learn how to create your own ERC20 tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - ERC20 +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc20-interface + - + name: 3. Token Creation + path: erc20-token-creation + - + name: 4. Interaction + path: erc20-interaction + - + name: 5. Testnet Deployment + path: erc20-testnet-deployment + - + name: 6. Extensions + path: erc20-extensions diff --git a/locales/it/ERC20TokenCourse/erc20-extensions/erc20extensions.md b/locales/it/ERC20TokenCourse/erc20-extensions/erc20extensions.md new file mode 100644 index 000000000..b3649fbba --- /dev/null +++ b/locales/it/ERC20TokenCourse/erc20-extensions/erc20extensions.md @@ -0,0 +1,33 @@ +The ERC20 standard only describes the required and optional functionality that your contract needs, but you can add additional functionality. + +In this section, we added the functionality to burn and mint tokens, as well as the ability to pause the contract, by using OpenZeppelin extensions. + +Of course, you can write your own ERC20 token contract implementation or extensions and import them into your contract. But OpenZeppelin contracts have been audited by security experts and are a great way to add desired functionality. + +### Mintable + +The mint function allows the creator of the contract to mint (create) additional tokens after the contract has been deployed (line 22). As input parameters, the function needs the address that the tokens will be minted to, and the amount of tokens that should be minted. + +We don't have to import `mint()` from another contract since the mint function is already part of the ERC20 contract implementation of OpenZeppelin. We import `Ownable` (line 7) which is a contract module that provides a basic access control mechanism that allows an owner to have exclusive access to specific functions. In this contract, we add the inherited `onlyOwner` modifier to the `mint` function (line 22) and restrict access to this function to the "owner". + +The contract will inherit additional functions like owner(), transferOwnership() and renounceOwnership() to manage access, from the Ownable contract. + +### Burnable + +By importing the "ERC20Burnable" (line 5) and inheriting its functions (line 9) our contract allows token holders to destroy their tokens as well as the tokens in their allowance. +For more information, have a look at the ERC20Burnable contract. + +### Pausable + +With the "Pausable" contract module (line 6 and 9) the owner is able to pause (line 14) and unpause (line 18) the contract. In the pause state, tokens can't be transferred, which can be helpful in emergency scenarios. +For more information, have a look at the Pausable contract. + +Have a look at the OpenZeppelins Contract Wizard, which allows you to easily add additional functionality. + +If you successfully completed this course, try the Learneth NFT Course as the next step in your journey. + +## ⭐️ Assignment + +1. Try to mint tokens to an account after deployment. Call `totalSupply()` and `balanceOf()` to confirm the correct execution. +2. Burn tokens and then call `totalSupply()` and `balanceOf()` to confirm the correct execution. +3. Test the pause function by pausing the contract using the owner account and trying to make a transfer with a second account. The transaction should not be able to be executed and will throw the exception: "Pausable: paused". diff --git a/locales/it/ERC20TokenCourse/erc20-interaction/er20interaction.md b/locales/it/ERC20TokenCourse/erc20-interaction/er20interaction.md new file mode 100644 index 000000000..5c082b248 --- /dev/null +++ b/locales/it/ERC20TokenCourse/erc20-interaction/er20interaction.md @@ -0,0 +1,87 @@ +In this section, we will deploy a contract in our browser and test its functionality. + +### 1. Deploy the contract + +**1.1** Compile your EduCoin contract in the "Solidity compiler" module of the Remix IDE. + +**1.2** In the "Deploy & run transactions" module, select your contract "EduCoin" in the contract input field and click on the "Deploy" button. Always make sure to select the correct contract in the contract selector input field. + +**GIF** Compile and deploy: Compile and deploy contract + +### 2. Test the functions + +Expand the token contract functions in the IDE. + +#### 2.1 Decimals + +Click on the "decimals" button to call the decimals() function. +It should return "18". + +#### 2.2 Name + +Click on the "name" button to call the name() function. +It should return "EduCoin". + +#### 2.3 Symbol + +Click on the "symbol" button to call the symbol() function. +It should return "EDC". + +#### 2.4 Total supply + +Click on the "totalSupply" button to call the totalSupply() function. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test decimals, name, symbol, and totalSupply functions: Test transfer function + +#### 2.5 Balance of + +**2.5.1** Go to the "ACCOUNT" section in the sidebar and copy the displayed address by using the copy icon next to it. + +**2.5.2** Paste the address in the input field next to the "balanceOf" function button and click on the button. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test balanceOf function: Test transfer function + +#### 2.6 Transfer + +We will transfer EduCoin from one account to a second account. + +**2.6.1** Go to the "ACCOUNT" section in the sidebar and click on the displayed address. This should open a dropdown. Select the second address displayed and copy its address (account 2). + +**2.6.2** Open the dropdown and select the first account again (account 1), because this is the account that we want to use to make the transfer. + +**2.6.3** Paste the address in the input field next to the "transfer" function button, input the number 500000000000000000000, and click on the button. + +**2.6.4** If you check the balances for account 1 and account 2, they should both return the amount 500000000000000000000. + +**GIF** Test transfer function: Test transfer function + +#### 2.7 Approve + +We will now allow account 1 to spend tokens on behalf of account 2. + +**2.7.1** Go to the "Account" section, copy the address of account 1, then set it to account 2 again. + +**2.7.2** In the approve function, enter the address of account 1 as the input for spender and set the amount to 250000000000000000000. + +**GIF** Test approve function: Test approve function + +#### 2.8 Allowance + +Next to the "allowance" button enter the address of account 2 as the owner and account 1 as the spender; click on the button. +It should return 1000000000000000000000. + +**GIF** Test allowance function: Test allowance function + +#### 2.9 TransferFrom + +Now account 1 will transfer 250000000000000000000 tokens from account 2 to its own account. + +**2.9.1** Select account 1 in the "ACCOUNT" section. + +**2.9.2** Next to the "transferFrom" button enter the address of account 2 as the sender and account 1 as the recipient, enter 250000000000000000000 as the amount and click on the button. + +**2.9.3** Check the balances of accounts 2 and 1, they should return 250000000000000000000 and 750000000000000000000. + +**GIF** Test transferFrom function: Test transferFrom function diff --git a/locales/it/ERC20TokenCourse/erc20-interface/erc20interface.md b/locales/it/ERC20TokenCourse/erc20-interface/erc20interface.md new file mode 100644 index 000000000..5c4e8137c --- /dev/null +++ b/locales/it/ERC20TokenCourse/erc20-interface/erc20interface.md @@ -0,0 +1,76 @@ +ERC20 (Ethereum Request for Comments 20) is a standard for token contracts that manages fungible tokens on the Ethereum blockchain. + +Fungible tokens are all equal to each other and have the same value, behavior, and rights. Fungible tokens are often used as a medium of exchange, like the currencies ETH or BTC. However, they can also have other use cases like voting rights or reputation. + +If you want to know more about the ERC20 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +To get an overview of the required functionality of an ERC20 token contract, we will look at an interface that interacts with an ERC20 contract. +This interface (line 9) is part of the open-source contract library provided by OpenZeppelin. + +## ERC20 Functions + +Contracts compliant with the ERC20 standard must implement the following six functions: + +### totalSupply + +The function `totalSupply` (line 13) returns the total amount of tokens available. + +### balanceOf + +The function `balanceOf` (line 18) returns the amount of tokens owned by the account with the address `account`. + +### transfer + +The function `transfer` (line 27) transfers `amount` of tokens to the address `recipient`. +This function **must** emit (produce) a `Transfer` event (see below) and **should** throw an exception when the sender doesn't have enough tokens to make the transfer. + +### approve + +The function `approve` (line 52) creates an allowance for the address `spender` to transfer `amount` of tokens on behalf of the account calling the function. + +### allowance + +The function `allowance` (line 36) returns the amount of tokens that the address `spender` is allowed to spend on behalf of the account with the address `owner`. + +### transferFrom + +The function `transferFrom` (line 63) transfers `amount` of tokens on behalf of the address `sender` to the address `recipient`. +This function **must** emit a `Transfer` event. + +## ERC20 Events + +ERC20 contracts must also emit two events: + +### Transfer + +The `Transfer` (line 71) event must be emitted when `value` amount of tokens are transferred from the account with the address `indexed from` to `indexed to`. The parameters `from` and `to` are `indexed` allowing us to search for these events using the indexed parameters as filters. + +### Approval + +The `Approval` (line 77) event must be emitted when the account `indexed owner` approves the account `indexed spender` to transfer `value` amount of tokens on its behalf. + +## ERC20 Optional functions + +In addition to the mandatory functions and events, there are also three optional functions specified in the ERC20 standard that are not implemented in this interface: + +### name + +`function name() external view returns (string);` + +Returns the name of the token. + +### symbol + +`function symbol() external view returns (string);` + +Returns the symbol of the token. + +### decimals + +`function decimals() external view returns (uint8);` + +Returns the number of decimal places the token uses. + +You may want to use decimals to make your token divisible into arbitrary amounts like 1.5 ETH when displayed. The EVM (Ethereum virtual machine) only supports integer numbers. That's why the ERC20 standard suggests to implement the decimal functionality that specifies how many decimal places a token has. 18 decimal places is the industry standard. diff --git a/locales/it/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md b/locales/it/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md new file mode 100644 index 000000000..94b513922 --- /dev/null +++ b/locales/it/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md @@ -0,0 +1,41 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to a testnet of the Ethereum blockchain. This testnet behaves very similarly to the real blockchain (mainnet), but does not require real ETH to pay for transactions. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token + +In order to make transactions on the testnet we need Ethereum testnet tokens, which you can receive from something called a _faucet_. + +**2.1** Switch your Metamask network by clicking on the "Ethereum Mainnetwork" drop down and selecting "Ropsten Test Network". If you don’t see any test networks, click on the "Show/hide" link and enable "Show test networks" in the settings. + +**2.2** Go to https://faucet.ropsten.be/, enter the address of your account, and claim testnet ETH. You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Deployment + +Make sure the EduCoin contract is compiled. + +**3.1.** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It will ask you to connect your account which you should confirm. + +**3.2** Deploy the EduCoin contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. Copy the contract address. + +**3.4** In Metamask, click on assets, then click on the "Import tokens" link, and paste the address of your contract in the input field. + +You should now see a balance of 1000 EDC in your wallet. + +### 4. Make a transaction + +**4.1** Click on the identicon (visual representation of your address) in the Metamask wallet and create a second account (Account 2). + +**4.2** Copy the address of Account 2. + +**4.3** Switch to the first account (Account 1) and send 250 EDC to Account 2. Check the balances of Account 1 and Account 2. You might need to add the token address again for Account 2 to import the tokens and you will need testeth if you want to make a transaction with this account. + +You can also see your account balances if you look at the contract in Remix and call the `balanceOf` function using the addresses of Account 1 and Account 2. diff --git a/locales/it/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md b/locales/it/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md new file mode 100644 index 000000000..49b71abdd --- /dev/null +++ b/locales/it/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md @@ -0,0 +1,18 @@ +A token standard tells us what functionality the contract needs to comply with it. How this functionality is implemented is up to the developers. In this contract, we will use an ERC20 token contract implementation from OpenZeppelin (line 4). In this case, we import version 4.4.0 of the OpenZeppelin contracts. + +Have a look at their nicely documented ERC20 contract to have a better understanding of how an implementation might look. Apart from the functionality specified in the ERC20 standard, this contract provides additional functionality. + +We will create our own contract called MyToken (line 6), which inherits the functionality from the OpenZepplin ERC20 token contract implementation that we imported (line 4). + +This contract implements the optional functions `name()` and `symbol()` of the ERC20 Token standard and has a constructor where their values can be set during the deployment of the contract (line 7). +In this case, we are going to use the default values. We will call our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +Next, we make use of the inherited `_mint` function (line 8) that allows us to create tokens upon deployment of the contract. Inside the parameters, we specify the address of the account that receives the tokens and the amount of tokens that are created. +In this case, the account that deploys the contract will receive the tokens and we set the amount to 1000000 to the power of `decimals()`. The optional function `decimals()` of the ERC20 token standard is implemented and set to the default value of 18. This will create 1000000 tokens that will have 18 decimal places. + +## ⭐️ Assignment + +1. Rename your contract to `EduCoin`. +2. Rename your token to `EduCoin`. +3. Change the symbol of your token to `EDC`. +4. Change the amount of tokens that will be minted from 1000000 to 1000. diff --git a/locales/it/ERC20TokenCourse/introduction/introduction.md b/locales/it/ERC20TokenCourse/introduction/introduction.md new file mode 100644 index 000000000..4eaf7583c --- /dev/null +++ b/locales/it/ERC20TokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with the ERC20 token standard in the following sections. + +If you want to learn more about NFTs and the ERC721 token standard, have a look at the Learneth NFT Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/it/ERC721Auction/README.md b/locales/it/ERC721Auction/README.md new file mode 100644 index 000000000..325e4d60e --- /dev/null +++ b/locales/it/ERC721Auction/README.md @@ -0,0 +1,5 @@ +## NFT Auction Contract + +Learn how to write an ERC721 (NFT) auction contract. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/it/ERC721Auction/auction-contract-setup/auctionContractSetup.md b/locales/it/ERC721Auction/auction-contract-setup/auctionContractSetup.md new file mode 100644 index 000000000..945f0f803 --- /dev/null +++ b/locales/it/ERC721Auction/auction-contract-setup/auctionContractSetup.md @@ -0,0 +1,46 @@ +In this contract tutorial, we will learn how to create an ERC721 (NFT) auction contract. +We recommend to you, to do the Learneth "Solidity NFT Course" before starting this tutorial. + +In the following sections, we will create a contract that will enable a seller to auction an NFT to the highest bidder. This contract was created by the Solidity by Example project. In this first section, we will create an interface, the necessary state variables, and the constructor. + +### Interface + +We create the interface (line 5) for the ERC721 token since our contract will need to interact with it. We will need the `safeTransferFrom` (line 5), and` transferFrom` (line 11) methods. + +### EnglishAuction + +We create the four events `Start`, `Bid`, `Withdraw`, `End` (line 19-22) so we can log important interactions. + +Next, we will create the state variables that store all the necessary information about our auction on-chain. + +We create two state variables for the NFT we want to auction. In the variable `nft` (line 24) we store a representation of the NFT contract, that will allow us to call its functions by combining the interface IERC721 and the address of the NFT contract. +In `nftId` (line 25), we store the specific token id in our NFT contract that will be auctioned. + +Next, we need a variable to store the address of the person that is auctioning off the NFT, the `seller` (line 27). +We want our NFT contract to send the seller the proceeds of the auction when it is finished, that’s why use `address payable`. + +We create a state variable `endAt` (line 28) where we will store the end date of the auction. +We also create the two booleans, `started` (line 29) and `ended` (line 30), that keep track of whether the auction has started or ended. + +We create a variable `highestBidder` (line 32) where we will store the address of the highest bidder. We will send the highest bidder the NFT once the auction has ended. + +Finally, we need a uint `highestBid` (line 33) to store the highest bid and a mapping `bids` (line 34), where we can store the total value of bids that an account has made before withdrawing; more on this in the next section. + +### Constructor + +When the auctioneer deploys the contract, they need to provide a few arguments: +the address of the contract of the NFT they want to auction `_nft` (line 37), the token id of the NFT they want to auction `_nftId` (line 38), and a starting price that must be overbid to place the first bid in the auction,`_startingBid` (line 39). + +Once deployed, the state variables `nft` (line 41), `nftId` (line 42), `highestBid` (line 45) will be assigned the values from the arguments. The address of the `seller` that deployed the contract will be automatically read out via msg.sender and stored in the state variable `seller` (line 44). + +In the next section, we will enable the auctioneer to start the auction and bidders to place their bids. + +## ⭐️ Assignment + +We will use the assignment part of the following sections to give you instructions on testing your contract in the Remix VM environment of Remix. + +1. Deploy an NFT contract. You can use the NFT contract that we created in our "3.3 ERC721 - Token Creation" section. + +2. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +3. After deploying your contract, test if contract functions like `nft`, `nftId`, and `started` work as expected. diff --git a/locales/it/ERC721Auction/auction-start-bid/auctionContractStartBid.md b/locales/it/ERC721Auction/auction-start-bid/auctionContractStartBid.md new file mode 100644 index 000000000..c2b944e0c --- /dev/null +++ b/locales/it/ERC721Auction/auction-start-bid/auctionContractStartBid.md @@ -0,0 +1,42 @@ +In this section, we will create a function to start the auction and a function to bid on the NFT. + +### Start + +We use some control structures to check if necessary conditions are met before we let the seller start the auction. + +First, we check if the auction has already started (line 49). If it has started and our state variable `started` returns `true` we exit the function and throw an exception. + +The second condition we check for is whether the seller is executing the function (line 50). We have already created a function to store the seller's address when they deploy the contract in the `seller` state variable and can now check if the account executing the start function is the seller. If not we throw an exception. + +Next, we want to transfer the NFT that is up for auction from the seller to the contract (line 52). +We set the state variable `started` to `true` (line 53), and create an end date for the auction (line 54). In this case, it will be seven days from when the start function has been called. We can use a suffix like `days` after a literal number to specify units of time. If you want to learn more about time units have a look at the solidity documentation. + +Finally, we will emit our `Start()` event (line 56). + +### Bid + +Before the function caller can make a bid, we need to be sure that certain conditions are met. The auction needs to have started (line 60), the auction can not have ended (line 61) and the bid (the value attached to the call) needs to be higher than the current highest bid (line 62). + +Now we want to store the bid of the current highest bidder before we make a new bid. +First, we check if there is a bidder (line 64). If this function call is the first bid then the next line would be irrelevant. +In our mapping `bids` (line 34) we map the key, the `address` of the bidder, to the value, a `uint` that represents the total amount of ETH a bidder has bid in the auction before withdrawing. +If there is a bidder, we add the last bid (`highestBid`) of the `highestBidder` to the total value of the bids they have made (line 65) before withdrawing. +We store the bids because we want to enable the bidder to withdraw the ETH they used to make bids if they are no longer the highest bidder. + +Next, we set the `highestBidder` to the account calling the function (line 68), and the `highestBid` to their bid, the value that was sent with the call (line 69). + +Finally, we emit the `Bid` event (line 71). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we create in our "Solidity NFT Course" Learneth course. + +2. Mint yourself an NFT with the tokenId 0. + +3. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +4. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for `tokenId`. This will allow the contract to transfer the token to be auctioned. + +5. Call the `start` function of your auction contract. If you call the `started` function now, it should return `true`. If you call the `highestBid` function it should return 1. + +6. Set the value that you can attach to transactions to 3 Wei and call the `bid` function of the auction contract. If you call the `highestBid` function it should now return 3. diff --git a/locales/it/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md b/locales/it/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md new file mode 100644 index 000000000..e324a5c6e --- /dev/null +++ b/locales/it/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md @@ -0,0 +1,45 @@ +In this section, we will finish the contract, create a function to withdraw the bids that an account has made, and create a function to end the auction. + +### Withdraw + +We create a local variable `bal` (balance) that stores the total value of bids that the function caller has made (line 75) since their last withdrawal. We can assign this value to `bal` by accessing the bids mapping using the address of the function caller as the key. + +Next, we set the value of the address of the function caller to 0 in the bids mapping because they will withdraw the total value of their bids (line 76). + +Now we transfer that amount of ETH from the contract to the function caller and emit the `Withdraw` event (line 79). + +### End + +Before the function caller can execute this function and end the auction, we need to check if certain conditions are met. The auction needs to have started (line 83), the end date of the auction needs to have been reached (line 84), and the auction must not have ended already (line 85). + +Once the auction has ended, we set the state variable `ended` to `true` (line 87). + +We check if anybody participated in the auction and bid on the NFT (line 88). + +If there was a bid, we transfer the NFT from the contract to the highest bidder (line 89) and transfer the ETH that was sent from the highest bidder to the contract, now to the address of the auctioneer, the seller of the NFT (line 90). + +If nobody bids on the NFT, we send the NFT back to the auctioneer (line 92). + +Finally, we emit the `End` event (line 95). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we created in our Learneth "Solidity NFT Course". + +2. Mint yourself an NFT with the tokenId 0. + +3. For testing purposes, change the value that is assigned to the `endAt` state variable (line 54) from `7 days` to `5 minutes`. + +4. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +5. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for the `tokenId`. + +6. Call the `start` function of your auction contract. + +7. Bid 2 Ether using account 1, and 3 Ether using account 2. If you call the `highestBidder` function, it should now return the address of account 2. + +8. Call the `withdraw` function with account 1. In the balance of account 1, you should see the 2 Ether minus some transaction fees. + +9. After 5 minutes have passed, call the `end` function. Then, call the `ended` function which should return `true`. + +In the NFT contract, if you call the `ownerOf` function with the tokenId 0, it should return the address of account 2. If you look at the balance of account 1 it should have increased by 3 Ether minus some transaction fees. diff --git a/locales/it/ERC721Auction/config.yml b/locales/it/ERC721Auction/config.yml new file mode 100644 index 000000000..0783a37a1 --- /dev/null +++ b/locales/it/ERC721Auction/config.yml @@ -0,0 +1,19 @@ +--- +id: er721Auction +name: NFT Auction Contract +summary: Learn how to write an ERC721 (NFT) auction contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: Contract Setup + path: auction-contract-setup + - + name: Start and Bid Functions + path: auction-start-bid + - + name: Withdraw and End Functions + path: auction-withdraw-end diff --git a/locales/it/Interoperability/1_Intro/intro.md b/locales/it/Interoperability/1_Intro/intro.md new file mode 100644 index 000000000..ab26f4f6d --- /dev/null +++ b/locales/it/Interoperability/1_Intro/intro.md @@ -0,0 +1,5 @@ +As the web3 world grows, there will be more blockchains. Unless the chains can communicate with one another, the ecosystem will become increasingly fragmented. + +The Axelar network enables protocols to have cross-chain functionality between any two blockchains. + +Building a protocol that is interoperable between ecosystems is essential for growth. diff --git a/locales/it/Interoperability/2_Gateway/gateway.md b/locales/it/Interoperability/2_Gateway/gateway.md new file mode 100644 index 000000000..dc752d3eb --- /dev/null +++ b/locales/it/Interoperability/2_Gateway/gateway.md @@ -0,0 +1,25 @@ +The Axelar Gateway is the entrypoint for your smart contract into the Axelar ecosystem. Once you have triggered the appropriate function on the Gateway, your transaction will begin its interchain journey from your source chain across the Axelar network to the destination chain. Each chain that is connected to Axelar has a deployed gateway contract for you to interact with. + +The following are the two more relevant functions you will need to be familiar with. + +## callContract() + +This function triggers an interchain transaction with a message from the source to the destination chain. It takes three relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent + +The first two parameters are quite intuitive. They consist of both the name of the chain you want this transaction to go to and the address on that chain you want to end execute at. The final parameter is the payload. This payload represents a general message that is sent to the destination chain. The message can be used in many different ways on the destination chain. For example, you can send data to be used as a parameter in another function on the destination chain, you can send a function signature as a message that will then get executed on a destination chain, and much more. + +## callContractWithToken() + +This function triggers an interchain with a message and a fungible token from the source to the destination chain. It takes five relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent +4. `symbol`: The symbol of the token being sent +5. `amount`: The amount of that token that is being sent + +The first three parameters here are the same as in `callContract()`. The final two parameters are relevant to the token that is being sent along with the message. These are the symbol of the token and the amount of the token that is being sent. diff --git a/locales/it/Interoperability/3_GasService/GasService.md b/locales/it/Interoperability/3_GasService/GasService.md new file mode 100644 index 000000000..4ed0afbbf --- /dev/null +++ b/locales/it/Interoperability/3_GasService/GasService.md @@ -0,0 +1,29 @@ +The Axelar Gas Service is an extremely useful tool made available to pay gas for an interchain transaction. It allows you to pay for the cost of a transaction in the token of the source chain, making for a much easier end user (and developer) experience. If for example the source chain is Ethereum and the destination chain is Polygon then the gas service will receive the complete payment for the transaction in ETH and no matic is needed from the caller to pay for the execution on the Polygon destination chain. + +The following are the two more relevant functions you will need to be familiar with in regards to the Gas Service. + +## payNativeGasForContractCall() + +This function allows you to pay for the entirety of an interchain transaction in the native token of the source chain. It takes five relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +The parameters overlap with the parameters required by the `callContract()` function in the Gateway contract. The two parameters not discussed in the Gateway section are `sender` and `refundAddress`. The sender is the address paying for the transaction and the refund address is the address that will receive any surplus funds sent to the gas service. + +## payNativeGasForContractCallWithToken() + +This function allows you to pay for the entirety of an interchain transaction (that includes a token transfer) in the native token of the source chain. It takes seven relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `symbol`: The symbol of the token that was sent +6. `amount`: The amount of the token that was sent +7. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +This function is nearly identical to the first top one the main difference being that it is used for message + token transfer transactions as opposed to just interchain message transactions (aka GMP Transactions). As a result the GasService needs to also know the `symbol` and `amount` of the token that is being sent. diff --git a/locales/it/Interoperability/4_Executable/executable.md b/locales/it/Interoperability/4_Executable/executable.md new file mode 100644 index 000000000..1f72c6be4 --- /dev/null +++ b/locales/it/Interoperability/4_Executable/executable.md @@ -0,0 +1,27 @@ +The Axelar executable contains relevant helper functions that will be automatically executed on the destination chain in correspondence to the relevant inbound transaction from the source chain. + +The following are the relevant functions you will need to use from Axelar Executable + +## \_execute() + +This function handles the execution on the destination chain. It takes the following four parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent + +The `sourceChain` and `sourceAddress` are key parameters which you receive out of the box that can be used for verifying authenticity of messages on the destination chain. The payload (as discussed in the gateway section) is the message that was sent from the source chain to be used on your destination chain. The `commandId` will not be used during the rest of this module. + +## \_executeWithToken() + +This function handles the execution on the destination chain for a message being sent with a fungible token. It takes six relevant parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent +5. `tokenSymbol`: The symbol of the token being sent +6. `amount`: The amount of that token that is being sent + +The first four parameters are identical to that of the `_execute()` function. The final two parameters of `tokenSymbol` and `amount` are in reference to the token that is being sent along with the message. It allows you on the destination chain to interact with the token accordingly, for example transferring it to another receiving address. The `commandId` will not be used during the rest of this module. diff --git a/locales/it/Interoperability/5_InterchainMessage/interchainMessage.md b/locales/it/Interoperability/5_InterchainMessage/interchainMessage.md new file mode 100644 index 000000000..029f642ce --- /dev/null +++ b/locales/it/Interoperability/5_InterchainMessage/interchainMessage.md @@ -0,0 +1,53 @@ +In this section we will create a contract that will send a "hello world" message between two blockchains. + +## Constructor + +The first thing you will need to create is the `constructor` for the function. This will allow you to set the `Gateway` and `Gas Service` contracts we discussed in the previous sections. + +When deploying the contract you will pass in the address of the `Gateway` and `GasService` for Ethereum Sepolia those addresses are `0xe432150cce91c13a887f7D836923d5597adD8E31` for the Gateway and `0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6` for the Gas Service. + +For the full list of relevant Axelar addresses see here + +## Send Interchain Message + +Now that the constructor has set the relevant Axelar addresses needed to trigger an interchain transaction you can move on to the `setRemoteValue()`, which will trigger this transaction. + +This function takes three parameters: + +1. `_destinationChain`: The chain which the transaction is going to +2. `_destinationAddress`: The address on the destination chain the transaction will execute at +3. `_message`: The message being passed to the destination chain + +First, you have a `require` statement which ensures that the `msg.value` contains a value. This `msg.value` will be used to pay the `GasService`. If no funds were sent, then the transaction should be reverted as the transaction cannot execute on the Axelar blockchain and destination chain without any gas. + +Next, you encode the `_message` that was passed in. Notice that the `_message` is set as a `string` type. Axelar expects this message to be submitted as a `bytes` type so to convert the `string` to `bytes` you simply pass it through `abi.encode()`. + +Now, with your message encoded you can begin to interact with the `GasService` and the `Gateway` + +To pay for the entire interchain transaction you will trigger the function `payNativeGasForContractCall`, which is defined in the `GasService`. + +This function needs the parameters explained earlier in the GasService section. The `sender` for this transaction will be this contract, which is `address(this)`. The `destinationChain` and `destinationAddress` can simply be passed in from this functions parameters, the `payload` is the encoded \_message we wrote earlier. Finally, you need to specify what the refund address is, this can be the address that triggers this function, which you get by writing `msg.sender`. + +Once you trigger this function you will have successfully sent a transaction from the source chain via Axelar to the destination chain! But there is still one final step that needs to be complete. + +### Receive Message on Destination Chain + +On the destination chain the inbound interchain transaction needs to be picked up and handled by the `AxelarExecutable`'s `_execute()` function. + +The `_execute()` function is defined in the `AxelarExecutable` contract so when defining this function you must remember to include the `override` keyword. + +This function takes three parameters. + +1. `_sourceChain`: The blockchain which the transaction has originated from +2. `_sourceAddress`: The address on the source chain which the transaction has been sent from +3. `_payload`: The message that has been sent from the source chain + +The first thing that needs to be done in this contract is to get access to your `message` that was sent. Recall, before sending the message it was sent through `abi.encode()` to convert the message from type `string` to type `bytes`. To convert your message back from type `bytes` to type `string` simply pass the `_payload` to the function `abi.decode()` and specify that you want the `_payload` decoded to type `string`. This will return the message as a string. + +Now that you have your message as a type string you can set the `sourceChain` and `sourceAddress` storage variables as `_sourceChain` and `_sourceAddress` to have an easy reference to the data that was passed in. You can also emit the `Executed` event with the `sourceAddress` and `message` event that you just decoded. + +Great! At this point you are now handling the interchain transaction on the destination chain. + +To interact with this contract make sure you deploy it on at least two blockchains so that you can call `setRemoteValue()` from the one chain and then have the `_execute()` function automatically triggered on another chain. You will be able to query the `sourceChain` and `sourceAddress` variables on the destination chain to ensure that the interchain execution worked correctly. + +To view the full step by step of the interchain transaction checkout the Axelarscan (testnet) block explorer. diff --git a/locales/it/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md b/locales/it/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md new file mode 100644 index 000000000..11915eb32 --- /dev/null +++ b/locales/it/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md @@ -0,0 +1,39 @@ +At this point we have gone over an example of how to send a general message between one blockchain to another. Now, let's implement a contract that sends a message and a token from one blockchain to another. + +## Overview + +This contract should seem largely familiar. Much like the previous section the `constructor` receives the `Gateway` and `Gas Service` addresses. + +It then has a function that will be called from the source chain called `sendToMany` that takes in parameters similar to the previous section. + +1. `_destinationChain`: The chain the transaction is sending to +2. `_destinationAddress`: The address on the destination chain your transaction is sending to +3. `_destinationAddresses`: The message that you will be sending along with your token transfer. In this example the message is a list of receiving addresses for the token transfer. +4. `_symbol`: The symbol of the token address being sent +5. `_amount`: The amount of the token being sent + +In the function we already have the `require` statement implemented to ensure gas is sent + +We also have the basic ERC20 functionality to send the token from the calling wallet to this smart contract. The contract also calls the `approve` function to allow the Gateway to eventually transfer funds on its behalf. + +Finally, the `_executeWithToken()` function is also implemented out of the box. + +It makes use of the following params: + +1. `_payload`: The incoming message from the source chain +2. `_tokenSymbol`: The symbol of the token that was sent from the source chain +3. `_amount`: The amount of the token that was sent from the source chain + +Now with these params that were passed in, the `_execute()` function can send the tokens that were sent to the appropriate receivers. + +## Challenge + +Your challenge here is to finish off the `sendToMany()` function using the Axelar Gateway and Gas Service to trigger an interchain transaction. + +In the end you should be able to deploy this contract on two testnets, trigger the `sendToMany()` function and see the live transaction on Axelarscan (testnet) block explorer. + +### Testing Notes + +Note 1: The recommended ERC20 to use is `aUSDC` a wrapped version of the USDC token that can be obtained from the discord faucet bot. When triggering the `sendToMany()` function simply pass in the symbol `aUSDC` to the fourth param. + +Note2: When triggering the `sendToMany()` function you must remember to `approve` your contract to spend `aUSDC` tokens on your behalf, otherwise `transferFrom()` on line49 will throw an error. diff --git a/locales/it/Interoperability/7_FurtherReading/furtherReading.md b/locales/it/Interoperability/7_FurtherReading/furtherReading.md new file mode 100644 index 000000000..a601d7ac7 --- /dev/null +++ b/locales/it/Interoperability/7_FurtherReading/furtherReading.md @@ -0,0 +1,11 @@ +Congratulations on making it to the end of the interoperability module! 🎉🎉 + +To continue your learning journey of interoperability with Axelar. There are many useful resources available. + +- For documentation 📚 + +- For more technical examples 💻 + +- For live coding demos 📹 + +- For the developer blog 📝 diff --git a/locales/it/Interoperability/README.md b/locales/it/Interoperability/README.md new file mode 100644 index 000000000..a43fc5dd5 --- /dev/null +++ b/locales/it/Interoperability/README.md @@ -0,0 +1,3 @@ +## Interoperability Between Blockchains + +Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. diff --git a/locales/it/Interoperability/config.yml b/locales/it/Interoperability/config.yml new file mode 100644 index 000000000..39f1be7ed --- /dev/null +++ b/locales/it/Interoperability/config.yml @@ -0,0 +1,31 @@ +--- +id: interopCourse +name: Multichain Protocols with Axelar +summary: Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. +level: 2 +tags: + - Solidity + - Interoperability + - Axelar +steps: + - + name: An Intro to Axelar + path: 1_Intro + - + name: Axelar Gateway + path: 2_Gateway + - + name: Axelar Gas Service + path: 3_GasService + - + name: Axelar Executable + path: 4_Executable + - + name: Interchain Messages + path: 5_InterchainMessage + - + name: Interchain Token Transfers + path: 6_InterchainTokenTransfer + - + name: Further Reading + path: 7_FurtherReading diff --git a/locales/it/Multisig-Tutorial/1-multisig-introduction/introduction.md b/locales/it/Multisig-Tutorial/1-multisig-introduction/introduction.md new file mode 100644 index 000000000..3e9f18938 --- /dev/null +++ b/locales/it/Multisig-Tutorial/1-multisig-introduction/introduction.md @@ -0,0 +1,41 @@ +Welcome to the Multisignature Wallet course! In this section, we'll explore the fundamentals of Multisignature (Multisig) wallets and we'll go through a multisig wallet contract. + +## What is a Multisignature Wallet? + +A multisignature (multisig) wallet is a type of digital wallet that requires multiple keys to authorize a cryptocurrency transaction. + +Imagine a multisig wallet as a secure vault with multiple locks. To open the vault, each keyholder must open their individual lock. This setup ensures that no single person can access the vault's contents without the others' consent. + +## How Does a Multisig Wallet Work? + +In a multisig setup, each transaction must receive a predetermined number of approvals from a set group of individuals. For instance, in a 3-of-5 wallet configuration, there are five authorized addresses, but a transaction only goes through when at least three of them give their approval. When a transaction is initiated, it's presented as a **proposal** to the group. Each member who agrees to the transaction uses their private key to digitally sign it. + +These **digital signatures** are unique and are generated based on the combination of the transaction data and the private key. + +When the required number of signatures is reached, the transaction is broadcasted to the blockchain for execution. + +## Why Use a Multisig Wallet? + +Multisig wallets are crucial for enhanced security in cryptocurrency transactions. They mitigate the risk of theft or loss of a single key. In business, they're used to ensure that funds can't be moved without consensus among stakeholders. For instance, in a company managing cryptocurrency assets, a multisig wallet might require the CFO, CEO, and a board member to all approve significant transactions, protecting against internal fraud or external hacks. + +## Conclusion + +In this section, we learned that a multisig wallet requires multiple keys to authorize a proposed cryptocurrency transaction and that a multisigs mitigates the risk of theft or loss of a single key. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is a Multisignature Wallet? + +1. A digital wallet that requires a single signature for transactions. +2. A digital wallet that requires multiple signatures for transactions. +3. A physical wallet used for storing cryptocurrency. +4. A wallet that can only hold multiple types of cryptocurrencies. + +### 2) How does a Multisignature Wallet enhance security? + +1. By requiring a single private key for transactions. +2. By distributing transaction approval across multiple owners. +3. By storing transaction data on-chain. +4. None of the above. + +Feel free to take your time and answer the questions above. Once you're ready, we'll move on to exploring the Multisig smart contract and understanding its structure. diff --git a/locales/it/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md b/locales/it/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md new file mode 100644 index 000000000..17b0a924f --- /dev/null +++ b/locales/it/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md @@ -0,0 +1,60 @@ +In this section, we'll explore the **initialization process** of the Multisig smart contract. We'll examine the constructor function and review how it sets up the initial state of the contract. + +## Note + +From this section on in this tutorial, we will be building up a multisig contract. In subsequent sections, the contract will become increasingly complete. + +## Overview + +In this section, the contract consists of events, state variables, modifiers, and functions. **Events** provide transparency by logging specified activities on the blockchain, while **modifiers** ensure that only authorized users can execute certain functions. + +## State Variables + +In Line 4, we have the MultisigWallet contract itself. At the beginning of the contract, we have three state variables. + +1. **`owners`:** An array containing the addresses of all owners of the multi-signature wallet (Line 5). +2. **`isOwner`:** A mapping indicating whether an address is an owner (Line 6). +3. **`numConfirmationsRequired`:** The number of confirmations required for a transaction (Line 7). + +The setup of array and mapping allows us to easily retrieve the list of owners and verify whether an address is an owner. + +## Modifiers + +Next, we have a modifier called `onlyOwner` (Line 9). Modifiers in Solidity are special keywords that can be used to amend the behavior of functions. In our case, the `onlyOwner` modifier ensures that only owners can execute a function. It does this by checking whether the address of the **caller** is an owner. + +## Constructor Function + +The `constructor` function (Line 14) is executed only once during the deployment of the contract. It initializes essential parameters, in this case, the list of owners and the required number of confirmations (Line 14). + +On lines 15 and 16, we have two `require` statements to ensure that the inputs are valid. In this case, we require that there must be at least one owner and that the number of required confirmations must be greater than zero and less than or equal to the number of owners. + +The constructor then initializes the contract state by verifying that is not address(0) (Line 25) and that the owner is unique (Line 26). Then it adds a key/ value pair to the isOwner mapping (Line 28), and then it populates the `owners` array with the provided owner addresses (Line 29). + +Finally, it sets the `numConfirmationsRequired` variable with the specified value (Line 32). + +## getOwners Function + +The `getOwners` function (Line 36) allows users to retrieve the list of owners of the multi-signature wallet. It returns the `owners` array (Line 37). + +## getNumConfirmationsRequired Function + +The `getNumConfirmationsRequired` function (Line 41) allows users to retrieve the number of confirmations required for a transaction. It returns the `numConfirmationsRequired` variable (Line 42). + +## Conclusion + +In this section, we explored the initialization process of the Multisig smart contract. We examined the constructor function and understood how it sets up the initial state of the contract. + +## ⭐️ Assignment: Deploy a Multisig Wallet + +Deploy a Multisig contract with three owners and require two confirmations for transaction execution. + +1. Compile contractInitialization.sol +2. Go to Deploy & Run Transactions in Remix. +3. Expand the "Deploy" section. +4. Under "_OWNERS", enter three an array of three addresses. +5. Under "_NUM_CONFIRMATIONS_REQUIRED", enter the number of confirmations required for a transaction. + +**Hints:** + +- You can get addresses from the "ACCOUNTS" dropdown menu. +- The array of addresses should be in the format: ["0x123...", "0x456...", "0x789..."]. diff --git a/locales/it/Multisig-Tutorial/3-multisig-deposits/deposits.md b/locales/it/Multisig-Tutorial/3-multisig-deposits/deposits.md new file mode 100644 index 000000000..a8a14213b --- /dev/null +++ b/locales/it/Multisig-Tutorial/3-multisig-deposits/deposits.md @@ -0,0 +1,34 @@ +In this section, we'll explore the `receive` function and the associated Deposit event. We'll examine how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## Deposit Event + +On line, 9 we have the Deposit event. The Deposit event is emitted whenever Ether is deposited into the multi-signature wallet. It includes three parameters: + +1. `sender`: The address that sent the Ether. +2. `amount`: The amount of Ether deposited. +3. `balance`: The updated balance of the contract after the deposit. + +We can use the Deposit event to track the flow of Ether into the multi-signature wallet and maybe trigger other actions based on the event. + +## receive Function + +On line 43, we have the `receive` function. The `receive` function is a special function that is executed whenever Ether is sent to the contract. + +The `receive` function is marked as `external` and `payable`. The `external` modifier means that the function can only be called from outside the contract. The `payable` modifier means that the function can receive Ether. + +The `receive` function emits the Deposit event (Line 44) with the address of the sender, the amount of Ether sent, and the updated balance of the contract. It doesn't return anything. + +To receive Ether, a contract must have a `receive`, `fallback`, or a function with the `payable` modifier. If none of these are present, the contract will reject any Ether sent to it. + +## Conclusion + +In this section, we explored the `receive` function and the associated Deposit event. We examined how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## ⭐️ Assignment: Deposit Ether + +Deposit 2 Ether into the Multisig contract. + +1. Deploy the Multisig contract as in the previous assignment. +2. Enter a Value of 2 Ether in the Value field and select Ether in the dropdown menu. +3. At the bottom of your deployed contract in the "Low level interactions" section, click on the "Transact" button. +4. On top of your deployed contract, it should now say "Balance: 2 Ether". diff --git a/locales/it/Multisig-Tutorial/4-multisig-transactions/transactions.md b/locales/it/Multisig-Tutorial/4-multisig-transactions/transactions.md new file mode 100644 index 000000000..f62fd48a0 --- /dev/null +++ b/locales/it/Multisig-Tutorial/4-multisig-transactions/transactions.md @@ -0,0 +1,73 @@ +In this section, we'll explore the process of submitting and confirming transactions. + +## Modifiers + +We have new modifiers in this iteration of the contract. Let's examine them one by one. + +1. **`txExists` modifier:** (Line 13) ensures that the transaction exists. It does this by checking whether the transaction index is less than the length of the `transactions` array. We'll go into more about in this modifier later in this section. +2. **`notExecuted` modifier:** (Line 18) ensures that the transaction has not been executed. It does this by checking whether the `executed` variable of the transaction is false. +3. **`notConfirmed` modifier:** (Line 23) ensures that the transaction has not been confirmed by the caller. It does this by checking whether the `isConfirmed` mapping of the transaction index and the caller's address is false. + +## Transaction Struct + +On line 28, we have a struct called `Transaction`. We store the struct members: `to`, `value`, `data`, `executed`, and `numConfirmations` in individual variables. + +## Mapping of Confirmations + +On line 37, we have a mapping called `isConfirmed`. This mapping is used to keep track of the confirmations of each transaction. It maps the transaction's index to a mapping of an owner addresse to a boolean value. The boolean value indicates whether this owner has confirmed the transaction. + +## Transactions Array + +On line 39, we have an array called `transactions`. The array is used to store all the transactions submitted to the multi-signature wallet. + +## Events + +We have four new events in this iteration of the contract: + +1. **`SubmitTransaction` event:** emitted whenever a transaction is submitted to the multi-signature wallet. +2. **`ConfirmTransaction` event:** emitted whenever a transaction is confirmed by an owner. +3. **`RevokeConfirmation` event:** emitted whenever a transaction confirmation is revoked by an owner. +4. **`ExecuteTransaction` event:** emitted whenever a transaction is executed. + +## submitTransaction Function + +The `submitTransaction` function (Line 78) allows users to submit a transaction to the multi-sig wallet. It takes three parameters: `to`, `value`, and `data`. The `to` parameter is the address of the recipient of the transaction. The `value` parameter is the amount of Ether to be sent. The `data` parameter is the data to be sent to the recipient. Only owners can submit transactions. + +On line, 85 we create a new transaction struct and push it to the `transactions` array and emit the `SubmitTransaction` event. The `txIndex` variable is used to keep track of the transaction index. + +## confirmTransaction Function + +The `confirmTransaction` function (Line 98) allows users to confirm a transaction. It takes one parameter: `txIndex`. +It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. The `onlyOwner` modifier ensures that only owners can confirm transactions. The `txExists` modifier ensures that the transaction exists. The `notExecuted` modifier ensures that the transaction has not been executed. + +On line 101, we store the transaction in a local variable called `transaction`. We then increment the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to true. Finally, we emit the `ConfirmTransaction` event. + +## executeTransaction Function + +The `executeTransaction` function (Line 108) allows users to execute a transaction. On line 113, we require that the number of confirmations of the transaction is greater than or equal to the required number of confirmations. We then set the `executed` variable of the transaction to true. Finally, send the funds using the `call` function. This is the `call` of the recipient address with the value and data of the transaction. If the transaction is successful, we emit the `ExecuteTransaction` event. + +## getTransactionCount Function + +The `getTransactionCount` function (Line 132) allows users to retrieve the number of transactions in the multi-signature wallet. It returns the length of the `transactions` array. + +## getTransaction Function + +The `getTransaction` function (Line 136) allows users to retrieve a transaction. It returns the transaction struct members that we explored earlier in this section. + +## Conclusion + +In this section, we explored the process of submitting, confirming, and executing transactions. We examined the `submitTransaction`, `confirmTransaction`, and `executeTransaction` functions and understood how they work together to allow multiple users to submit and confirm transactions. + +## ⭐️ Assignment: Make a Transaction + +Submit, confirm, and execute a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. Deploy the Multisig contract as in the previous assignment. Make sure that the required number of confirmations is 2. +2. Fund the multisig from any address by sending 4 Ether as you did in the previous assignment. +3. Try sending 2 Ether to the first account in the "ACCOUNTS" dropdown menu. Once you have submitted this transaction (with submitTransaction), click on `getTransactionCount` and should see one transaction or you can click on `getTransaction`, insert 0 as the transaction index and see the transaction you just submitted. +4. Now you can click on `confirmTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. +5. Switch to the second owner account and confirm the transaction again. If you click on `getTransaction` again, you should see that the transaction has been confirmed twice. +6. The last step is to execute the transaction. Click on `executeTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been executed. You can also check the balance of the first account in the "ACCOUNTS" dropdown menu. It should now be 2 Ether higher and the balance of the multi-signature wallet should be 2 Ether lower. + +**Hint:** +If you submit a transaction make sure that the value is in Wei and that the _data field is correctly filled in. E.g. it could look like this: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 2000000000000000000, 0x" for 2 Ether. diff --git a/locales/it/Multisig-Tutorial/5-multisig-revoke/revoke.md b/locales/it/Multisig-Tutorial/5-multisig-revoke/revoke.md new file mode 100644 index 000000000..1bf085343 --- /dev/null +++ b/locales/it/Multisig-Tutorial/5-multisig-revoke/revoke.md @@ -0,0 +1,30 @@ +In this section, we'll explore the process of revoking confirmations. This process is necessary when an owner changes their mind about a transaction and wants to stop it from being executed. This section will be pretty straightforward. + +## revokeConfirmation Event + +On line 14, we have added the `RevokeConfirmation` event. This event is emitted whenever a transaction confirmation is revoked by an owner. + +## revokeConfirmation Function + +On line 129, we have added the `revokeConfirmation` function. It allows users to revoke a transaction confirmation. + +`revokeConfirmation` takes one parameter: `txIndex`. It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. + +On line 134, we require that the transaction has been confirmed by the caller. This ensures that an owner who has confirmed the transaction can only revoke their own confirmation. +We then decrement the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to false. Finally, we emit the `RevokeConfirmation` event. + +## Conclusion + +In this section, we explored the process of revoking confirmations. We examined the `revokeConfirmation` function and understood how it works to allow users to revoke confirmations. + +## ⭐️ Assignment: Revoke a Confirmation + +Confirm and revoke a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. As in the previous assignment, deploy the Multisig contract, send the contract some Ether, and then submit a transaction to the first account in the "ACCOUNTS" dropdown menu with a value of 2 Ether. +2. Confirm the transaction twice as in the previous assignment. +3. Revoke the transaction by clicking on `revokeConfirmation` and inserting 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. + +## Final Conclusion + +In this tutorial, we explored the process of creating a multi-signature wallet. We learned how to initialize the contract, deposit Ether, submit, confirm, and revoke transactions. We also learned how to execute transactions and retrieve information about the multi-signature wallet. diff --git a/locales/it/Multisig-Tutorial/README.md b/locales/it/Multisig-Tutorial/README.md new file mode 100644 index 000000000..ae5997802 --- /dev/null +++ b/locales/it/Multisig-Tutorial/README.md @@ -0,0 +1,5 @@ +## MultiSig Wallet + +Learn how to write a MultiSig Wallet smart contract on Ethereum. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/it/Multisig-Tutorial/config.yml b/locales/it/Multisig-Tutorial/config.yml new file mode 100644 index 000000000..067de0fb9 --- /dev/null +++ b/locales/it/Multisig-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: multisigCourse +name: Multisig Wallet +summary: Learn how to create and interact with a multisig wallet. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - Multisig +steps: + - + name: 1. Introduction + path: 1-multisig-introduction + - + name: 2. Initialize the Contract + path: 2-multisig-initialization + - + name: 3. Deposits + path: 3-multisig-deposits + - + name: 4. Transactions + path: 4-multisig-transactions + - + name: 5. Revoking Confirmations + path: 5-multisig-revoke diff --git a/locales/it/NFTTokenCourse/README.md b/locales/it/NFTTokenCourse/README.md new file mode 100644 index 000000000..c3d2a183a --- /dev/null +++ b/locales/it/NFTTokenCourse/README.md @@ -0,0 +1,5 @@ +## Solidity NFT Course + +Learn how to create your own NFTs (non-fungible tokens). + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/it/NFTTokenCourse/config.yml b/locales/it/NFTTokenCourse/config.yml new file mode 100644 index 000000000..af82db834 --- /dev/null +++ b/locales/it/NFTTokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: nftTokenCourse +name: Solidity NFT Course +summary: Learn how to create your own NFT tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc721-interface + - + name: 3. Metadata Interface + path: erc721-interface-metadata + - + name: 4. Token Creation + path: erc721-token-creation + - + name: 5. Metadata IPFS + path: erc721-metadata-ipfs + - + name: 6. Deploy to Testnet + path: erc721-deploy-testnet-opensea diff --git a/locales/it/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md b/locales/it/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md new file mode 100644 index 000000000..40576500c --- /dev/null +++ b/locales/it/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md @@ -0,0 +1,50 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to the Rinkeby testnet of the Ethereum blockchain, mint an NFT, and look at it on the NFT marketplace OpenSea. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token for Rinkeby + +In order to make transactions on the testnet, we need Ethereum testnet tokens. + +**2.1** Switch your Metamask from "Ethereum Mainnetwork" to "Rinkeby Test Network". + +**2.2** Go to https://faucet.paradigm.xyz/, enter the address of your account and claim testnet ETH. +You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Contract Deployment + +**3.1** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It should then ask you to connect your account, which you should confirm. Then you should see the Rinkeby network badge under "Injected Web3". + +**3.2** Deploy your token contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. + +### 4. Mint an NFT + +**4.1** Expand your contract in the IDE so you can see the buttons for the functions. + +**4.2** Expand the input fields next to the safeMint button. Enter the Ethereum address of the account that is connected to Remix in the “to:” input field. Enter “0” in the input field "tokenID:". Click on transact. + +**4.3** In Metamask click on assets, then click on the “Import tokens” link, and paste the address of your contract in the input field. You can set decimals to 0. + +You should now see the name of the symbol of your token contract (e.g. GEO) in your “Assets” view in Metamask. You should have one of these tokens. + +### 5. See your NFT on OpenSea + +OpenSea is one of the most popular online marketplace for NFTs. OpenSea also provides a version where you can see assets on the testnet, under https://testnets.opensea.io/ + +**5.1** Go to https://testnets.opensea.io/login. + +**5.2** Connect with your Metamask wallet. You should be redirected to your account https://testnets.opensea.io/account view on OpenSea, where you should be able to see your NFT. You should see the image of your NFT; when you click on it, you should see the name, description, and under properties, also the attributes that you created. + +If you successfully completed this course and are familiar with the basics of Solidity development, we encourage you to continue your learning journey by learning how to create your own NFT auction contract from the Learneth resources. diff --git a/locales/it/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md b/locales/it/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md new file mode 100644 index 000000000..a43162feb --- /dev/null +++ b/locales/it/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md @@ -0,0 +1,44 @@ +The metadata extension is optional. It allows us to add additional information to our ERC721 tokens. We can specify a name, a symbol, and an URI (Uniform Resource Identifier) that can point to a file where we can add even more information in the form of a JSON. + +## ERC721 Metadata Functions + +### name + +The function `name` (line 16) returns the name of the token collection. A token collection means all tokens created with your ERC721 token contract implementation. Every token in this collection will have this name, regardless of their tokenId. + +### symbol + +The function `symbol` (line 21) returns the symbol of the token collection. + +### tokenURI + +The function `tokenURI` (line 26) returns the URI for the token with the id `tokenId`. In this case it’s not the URI of the whole collection but of an individual token in the collection. + +## ERC721 Metadata JSON Schema + +The file that the tokenURI points to should conform to the Metadata JSON Schema as it is specified in the EIP-721. + +``` +{ + "title": "Asset Metadata", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Identifies the asset to which this NFT represents" + }, + "description": { + "type": "string", + "description": "Describes the asset to which this NFT represents" + }, + "image": { + "type": "string", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." + } + } +} +``` + +The root element must be of the type object. This root object should have properties with the keys: name, description, and image that should be all of the type string. + +The ERC721 standard is pretty flexible, the tokenURI does not need to point to a JSON document and the JSON does not need to have all properties and often has additional properties. diff --git a/locales/it/NFTTokenCourse/erc721-interface/erc721Interface.md b/locales/it/NFTTokenCourse/erc721-interface/erc721Interface.md new file mode 100644 index 000000000..468e8e640 --- /dev/null +++ b/locales/it/NFTTokenCourse/erc721-interface/erc721Interface.md @@ -0,0 +1,100 @@ +ERC721 is a standard for token contracts that manage non-fungible tokens (NFTs) on the Ethereum blockchain. + +Each non-fungible token is unique and not interchangeable. NFTs can have different properties, behavior, or rights. Non-fungible tokens are used to represent ownership of unique digital and physical assets like art, collectibles, or real estate. + +If you want to know more about the ERC721 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +The ERC721 standard is more complex than the ERC20 standard and it features optional extensions. ERC721 compliant contracts must, at a minimum, implement the ERC721 and ERC165 interfaces, which we will look at in this section. + +This interface (line 11) is part of the open-source contract library provided by OpenZeppelin. + +## Basic IERC721 Functions + +Contracts compliant with the ERC721 standard have to implement the following functions: + +### balanceOf + +The function `balanceOf` (line 30) returns the amount of tokens owned by the account with the address `owner`. + +### ownerOf + +The function `ownerOf` (line 39) returns the address `owner` of the account that holds the token with the id `tokenId`. + +### safeTransferFrom + +The function `safeTransferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +The function `safeTransferFrom` (line 137) is almost identical to the function `safeTransferFrom` (line 55) .The only difference is that this function has a non-empty payload `data`. + +A smart contract must implement the ERC721TokenReceiver Interface if it is to receive a transfer. This will ensure that the contract can handle ERC721 token transfers and prevent the tokens from being locked in a contract that can’t. + +### transferFrom + +The function `transferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +**It is recommended to use safeTransferFrom instead of transferFrom whenever possible.** +The `transferFrom` function is not secure because it doesn’t check if the smart contract that is the recipient of the transfer has implemented the ERC721TokenReceiver interface and is capable of handling ERC721 tokens. + +## Advanced IERC721 Functions + +### approve + +The function `approve` (line 94) gives the account with the address `to` the permission to manage the token with the id `tokenId` on behalf of the account calling the function. + +### getApproved + +The function `getApproved` (line 103) returns the address of the account (return var `operator`) that is approved to manage the token with the id `tokenId`. + +### setApprovalForAll + +The function `setApprovalForAll` (line 115) sets the permission (`_approved`) for the account with the specified address (input param - `operator`) to manage all tokens of the account calling the function. + +### isApprovedForAll + +The function `getApproved` (line 103) returns the boolean true if the account with the address `operator` is approved to manage all tokens of the account with the address `owner`. + +## IERC721 Events + +ERC721 contracts must also emit the following events: + +### Transfer + +The `Transfer` event (line 15) must be emitted when the token with the id `tokenId` is transferred from the account with the address `from` to the account with the address `to`. + +### Approval + +The `Approval` event (line 20) must be emitted when the account with the address `owner` approves the account with the address `spender` to manage the token with the id `tokenId` on its behalf. + +### ApprovalForAll + +The `ApprovalForAll` event (line 25) must be emitted when the account with the address `owner` gives or removes the permission (`_approved`) of the account with the address `operator` to manage all its tokens. + +## IERC165 + +In addition to the ERC721 interface, ERC721 compliant contracts must also implement the ERC165 interface. + +With the implementation of the ERC165 interface, contracts can declare the support of specific interfaces. A contract that wants to interact with another contract can then query if the other contract supports this interface before making a transaction e.g. sending tokens to it that they might not support. + +Our IERC721 interface here imports (line 6) and inherits (line 11) from the IERC165 interface. + +This is how OpenZeppelins implementation of the ERC165 interface looks like: + +``` +interface IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +For example, the ERC165 identifier for the ERC721 interface as specified in the EIP721 is “0x80ac58cd”. Learn how to calculate an interface identifier and more about the ERC165 in its improvement proposal. + +## Other interfaces + +The IERC721TokenReceiver interface must be implemented to accept safe transfers. + +There are two optional extensions for ERC721 contracts specified in the EIP721: + +IERC721Enumerable enables a contract to publish its full list of tokens and make them discoverable. + +IERC721Metadata enables a contract to associate additional information to a token. We will have a more detailed look into this in the next section. diff --git a/locales/it/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md b/locales/it/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md new file mode 100644 index 000000000..27876b068 --- /dev/null +++ b/locales/it/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md @@ -0,0 +1,101 @@ +In this section, we will create our metadata and store it in a decentralized way. + +IPFS ( InterPlanetary File System) is a peer-to-peer network for storing files in a distributed way. Pinata.cloud is a pinning service that allows users to easily host files on the IPFS network. + +We want to host our images and the JSON files with their metadata on IPFS. + +### Create Image Folder + +In this example, we will create metadata for three tokens. As you can see below, we create three images that we stored in a folder. + +``` +geo-img +├── geo_1.png +├── geo_2.png +├── geo_3.png +``` + +### Register on Pinata + +Now, we want to host these images somewhere so we can point to them in the metadata of our tokens. Let's do it in a decentralized way and use Pinata to host them on IPFS. + +First you need an account on Pinata. Go to Pinata.cloud and create an account. On Pinata you can upload up to 1 GB of data for free. + +Once you have signed up, you should be in the Pin Manager view. + +Pin Manager Pinata + +### Upload Images to IPFS + +Click on the upload button and upload the folder with your images. +Once you've uploaded your folder, you should see the name of your folder and the CID (content identifier) associated with it. If the content in the folder changes, the CID will also change. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P + +You can access a specific image by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png + +### Create JSON files + +We create another folder where we store three JSON files. + +``` +geo-json +├── 0 +├── 1 +├── 2 +``` + +Inside the JSON files, create the metadata for the tokens, like name, description, and image. +For the image URL, we are going to use the URL of our images on IPFS. You can add additional data if you like; in this example, we added some unique attributes for each token. + +This is how the JSON for the first token could look: + +``` +{ + "name": "Geometry#0", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png +", + "attributes": [ + { "trait_type": "background", "value": "cyan" }, + { "trait_type": "color", "value": "red" }, + { "trait_type": "shape", "value": "circle" } + ] +} +``` + +This is how the JSON for the second token could look: + +``` +{ + "name": "Geometry#1", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_2.png", + "attributes": [ + { "trait_type": "background", "value": "magenta" }, + { "trait_type": "color", "value": "green" }, + { "trait_type": "shape", "value": "square" } + ] +} +``` + +As shown above, the folder in this example is called "geo-json". Inside this folder, we have three JSON files. +The first JSON file is called "0", the second JSON file is called "1", and the third JSON file is called "2". + +Make sure that your JSON files don't have a file ending and are named like their corresponding tokenIds. +In the pin manager on pinata.cloud, click on the upload button and upload the folder with your JSON files. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. +For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp +This will become our baseURI. + +You can access a specific JSON file then by just adding a slash and the tokenId by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/0 + +In the contract, replace the baseURI with your own baseURI. In this example, the baseURI consists of the URL +"https://ipfs.io/ipfs/", the CID containing the JSON files, and a slash at the end "/". + +An individual tokenURI will now be created for each token by adding the tokenId to the baseURI — exactly what we did manually in the example above to access the JSON file. diff --git a/locales/it/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md b/locales/it/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md new file mode 100644 index 000000000..891fe00a7 --- /dev/null +++ b/locales/it/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md @@ -0,0 +1,35 @@ +In this contract, we use an ERC721 token contract implementation from OpenZeppelin (line 4). + +Have a look at their implementation of a ERC721 contract. Apart from the functionality specified in the ERC721 standard, the contract provides additional functions which we will see in a bit. + +## myToken + +We create our own contract called MyToken (line 7), which inherits (line 7) the functionality from the OpenZepplin `ERC721` token contract implementation and `Ownable` that we imported (line 4). If you don't remember the Ownable contract module, have a look at the ERC20 extensions section. + +This ERC721 implementation makes use of the IERC721Metadata extension that is specified in the EIP. Our contract inherits the functions `name()` and `symbol()` +and has a constructor that allows their values to be set during the deployment of the contract (line 8). +In this case, we are going to use the default values. We name our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +### Base URI + +With an ERC721 contract, we are able to mint various tokens, each with its own tokenId. As we saw in the IERC721Metadata interface, each token can have its own `tokenURI`, which typically points to a JSON file to store metadata like name, description, and image link. +If a contract mints multiple tokens, ERC721 implementations often use the same URI as a base (`baseURI`) for all tokens and only differentiate them by adding their unique `tokenId` at the end via concatenation. In the next part, we will see what this looks like in practice. + +In this example, we are storing our data on IPFS — more on that in the next section. Our baseURI is https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/ (line 11). +Through concatenation the tokenURI for the token with the id 0 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/0 , the tokenURI for the token with the id 1 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/1, and so on. + +When using IPFS and you run into "504 Gateway Time-out" errors, you might have to wait and retry until the data is available. + +### safeMint + +With the safeMint function (line 14) we enable the owner to create new tokens with a dedicated token id after contract deployment. +The safeMint function is part of the ERC721 implementation of OpenZeppelin and lets us safely mint a token with the id `tokenId` to the account with the address `to`. For access control, we use the `onlyOwner` modifier from the Ownable access control contract module that we imported (line 5). + +In the next section, we will see how we can create and host the metadata for our NFTs. + +## ⭐️ Assignment + +1. Rename your contract to `Geometry`. +2. Rename your token to `Geometry`. +3. Change the symbol of your token to `GEO`. +4. Change the `_baseURI` to https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/. diff --git a/locales/it/NFTTokenCourse/introduction/introduction.md b/locales/it/NFTTokenCourse/introduction/introduction.md new file mode 100644 index 000000000..13beea567 --- /dev/null +++ b/locales/it/NFTTokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with NFTs, tokens created with the ERC721 token standard. + +If you want to learn more about fungible tokens and the ERC20 token standard, have a look at the Learneth ERC20 Token Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain-based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/it/OpcodesInTheDebugger/1_intro/step.md b/locales/it/OpcodesInTheDebugger/1_intro/step.md new file mode 100644 index 000000000..c1d9a2448 --- /dev/null +++ b/locales/it/OpcodesInTheDebugger/1_intro/step.md @@ -0,0 +1,5 @@ +This workshop aims to give a better understanding about how a contract get deployed. +`SimpleStore` is a very basic contract. +It has a very simple constructor - which just uses the first parameter `_o` and saves it to `s`. + +Using the debugger, we'll try to see, what the opcode `CODECOPY` does. diff --git a/locales/it/OpcodesInTheDebugger/2_memory/step.md b/locales/it/OpcodesInTheDebugger/2_memory/step.md new file mode 100644 index 000000000..577169a5e --- /dev/null +++ b/locales/it/OpcodesInTheDebugger/2_memory/step.md @@ -0,0 +1,8 @@ +Before we start, just quick reminder: + +The runtime of the EVM has several kinds of memory: + +- `calldata`: This is the input value given to the transaction. +- `stack`: Basically, this is a list of values, each value is limited in size (32 bytes). +- `memory`: Memory is used when the **type** of value getting stored is more complex like an array or a mapping. This memory is **temporary** and is **released** at the end of the execution. +- `storage`: This is a mapping, each value stored is **persisted** and saved on chain. diff --git a/locales/it/OpcodesInTheDebugger/3_codecopy/step.md b/locales/it/OpcodesInTheDebugger/3_codecopy/step.md new file mode 100644 index 000000000..b0c9f7d52 --- /dev/null +++ b/locales/it/OpcodesInTheDebugger/3_codecopy/step.md @@ -0,0 +1,7 @@ +CODECOPY is one of the many opcodes run by the EVM. Check out the complete list of opcodes at https://ethervm.io/ . + +CODECOPY takes the **running code** (or part of it) and to copies it from the `calldata` to the `memory`. + +The solidity implementation is: **codecopy(t, f, s)** - copy **s** bytes from code at position **f** to memory at position **t**. + +Every contract deployment uses **CODECOPY**. diff --git a/locales/it/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md b/locales/it/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md new file mode 100644 index 000000000..63950051d --- /dev/null +++ b/locales/it/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md @@ -0,0 +1,11 @@ +Let's go back to our contract. +Please make sure the `solidity compiler` and `Deploy & Run Transactions` are activated. + +Alternatively, you can click on `Solidity` from the `Home Page` **Environments** section. + +- Compile the contract from the `solidity compiler`. +- Go to the `Deploy & Run Transactions` and make sure `SimpleStore` is selected contract. +- In the textbox to the right of `Deploy`, input a positive integer. +- Click on `Deploy`. + +In the next step, we'll watch the deployment in the debugger. diff --git a/locales/it/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md b/locales/it/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md new file mode 100644 index 000000000..3ef3cd146 --- /dev/null +++ b/locales/it/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md @@ -0,0 +1,7 @@ +From the Remix terminal, identify the transaction that deployed the contract and click `Debug` + +In the gutter of the editor, put a breakpoint on the line `s = _o`, and click on `Jump to the next Breakpoint` (bottom right button). + +Click on `Step into`, to move along the opcodes until you reach `SSTORE`. + +`SSTORE` is the opcode for storing the value `_o` in the storage. Let's continue further to the `CODECOPY`. diff --git a/locales/it/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md b/locales/it/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md new file mode 100644 index 000000000..1480728e6 --- /dev/null +++ b/locales/it/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md @@ -0,0 +1,57 @@ +The goal here is to store the code in the blockchain. The EVM needs to tell the client (geth, parity) which what part of the **Call Data** to store. In this step, we are saving the contract MINUS its constructor (because that gets inplmented only 1 time) and MINUS the input parameter does not need to be stored. + +`CODECOPY` is the first step: it copies the bytecode to memory, then the ethereum client will be able to consume it. MUNCH! + +But wait... before the client can **MUNCH** bytecode, it needs an instruction - an opcode to tell it to MUNCH. `RETURN` is this opcode! + +As stated in the general spec, at the end of the contract creation, the client (geth, parity) takes the targeted value by the opcode `RETURN` and **persists** it by making it part of the deployed bytecode. + +Once you are in the `CODECOPY`, look at the top 3 items in the **Stack**: + +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x0000000000000000000000000000000000000000000000000000000000000055` +`2: 0x000000000000000000000000000000000000000000000000000000000000003e` + +_In your Stack - `1` & `2` may be slightly different. The difference may be due to a different compiler version._ + +**These are the parameters for `CODECOPY`.** + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +`0` is the offset where the copied code should be placed in the **memory**. In this example, ( all zeros) the code is copied to the beginning of the memory. (**t**) +`1` is the offset in **calldata** where to copy from (**f**) +`2` number of bytes to copy - (**s**) + +After `CODECOPY` is executed, (click the _step into_ button) the copied code should be: +`0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c63430005110032` in memory. **I'll refer to this value as (X)**. + +Let's look at the debugger's **Memory** panel. +The 0x number I gave above is not what you will see in the **Memory** panel -what you will see is this: +0x0: 6080604052600080fdfea265627a7a72 ????R??????ebzzr +0x10: 31582029bb0975555a15a155e2cf28e0 1X ?? uUZ??U???? +0x20: 25c8d492f0613bfb5cbf96399f6dbd4e ?????a?????9?m?N +0x30: a6fc9164736f6c634300051100320000 ???dsolcC????2?? +0x40: 00000000000000000000000000000000 ???????????????? +0x50: 000000000000000000000000000000a0 ??????????????? +0x60: 00000000000000000000000000000000 ???????????????? +0x70: 00000000000000000000000000000000 ???????????????? +0x80: 00000000000000000000000000000000 ???????????????? +0x90: 00000000000000000000000000000002 ???????????????? + +The `0x0`, `0x10`, etc is the position. The next number is the bytecode for that position. This is followed by question marks and seemingly random letters & numbers. This is **Remix**'s attempt to convert this into a string. + +So if we glue the first four sections of bytecode together, we'll get: +**0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e0a6fc9164736f6c63430005110032** The last section - `0x90` has 2 which is what I input for the constructors parameter. + +The input data from the **Call Data** panel is: +`0x6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c634300051100320000000000000000000000000000000000000000000000000000000000000002` +**I'll refer to this value as (Y).** + +This shows us that `(X)` is a subset of the original calldata `(Y)`: + +`(X)` is calldata without the input parameter `0000000000000000000000000000000000000000000000000000000000000002` (we don't need to store this) +and without the constructor code `6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe` which should be executed only 1 time. + +So `CODECOPY` extracts the bytecode from the calldata and copies it to the memory. + +Let's move to the next step. diff --git a/locales/it/OpcodesInTheDebugger/7_returnAndStore/step.md b/locales/it/OpcodesInTheDebugger/7_returnAndStore/step.md new file mode 100644 index 000000000..b375a24fb --- /dev/null +++ b/locales/it/OpcodesInTheDebugger/7_returnAndStore/step.md @@ -0,0 +1,18 @@ +# The Opcode RETURN + +At the end of the last chapter we had moved to one step after **CODECOPY** to see what happened in the memory. + +Now that CODECOPY has been executed, we are on the opcode `PUSH1 00`. + +`PUSH1 00` prepares the stack for the `RETURN` opcode. +`RETURN` is the last part of this process. It is where the code is returned to the client. + +We push `00` to the stack because this is the offset position of the contract bytecode in memory. + +Now we can call the all important `RETURN` opcode. + +The **stack inspector** shows: +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x000000000000000000000000000000000000000000000000000000000000003e` + +Which is to say it returns to the client the bytecode starting `0x00` with length `0x3e`. diff --git a/locales/it/OpcodesInTheDebugger/8_findTheOffset/step.md b/locales/it/OpcodesInTheDebugger/8_findTheOffset/step.md new file mode 100644 index 000000000..6b1ddc5cf --- /dev/null +++ b/locales/it/OpcodesInTheDebugger/8_findTheOffset/step.md @@ -0,0 +1,18 @@ +# Find the offset ;) + +And now for a slightly different example: + +- Compile notSimpleStore.sol +- Deploy the contract `notSoSimpleStore` +- Make sure you have a successful deployment - if not check that you used **the correct input type** in the constructor. +- Go to the Debugger by clicking the **debug** button at the (successful) creation transaction. +- Find the value of the parameter of `CODECOPY` which represents the offset in calldata where to copy from. + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +If you look in the **Stack**, you should see that the 2nd element is: +0x0000000000000000000000000000000000000000000000000000000000000083 + +And this is the **f** of the input params of codecopy. + +### Hope you picked up a thing or 2 about how opcodes work! diff --git a/locales/it/OpcodesInTheDebugger/config.yml b/locales/it/OpcodesInTheDebugger/config.yml new file mode 100644 index 000000000..74a1bf3a1 --- /dev/null +++ b/locales/it/OpcodesInTheDebugger/config.yml @@ -0,0 +1,10 @@ +--- +id: opcodesdebug +name: Opcodes in the Debugger +summary: Using the Debugger, we'll check out what the CODECOPY opcode does and how it is used by the EVM during contract creation. +level: 3 +tags: + - Remix + - Debugging + - EVM + - Opcodes diff --git a/locales/it/ProxyContract/1_Why/step1.md b/locales/it/ProxyContract/1_Why/step1.md new file mode 100644 index 000000000..b4a38aaeb --- /dev/null +++ b/locales/it/ProxyContract/1_Why/step1.md @@ -0,0 +1,27 @@ +# Proxy Contract AKA the Dispatcher + +## Why? + +This is a great pattern that is used mainly in **library development**. + +It helps in the following ways: + +- **Save gas cost at deployment time** + The purpose of a high gas cost is to discourage the operations that cost a lot for their execution and to encourage optimized code. + +- Proxy contracts are useful when a lot of instances of the same contract need to be deployed because they reduce the duplications in the deployment. + +- **Avoid code repetition in the blockchain.** + Heavy computations are expensive because every node will need to perform them, this is of course slowing the network. + +- **Develop upgradable(versioned) contracts** + When the contract is deployed, it’s immutable. By re-designing the code into different contracts, it is possible to allow logic upgrades while keeping the storage the same. + +## Example of gas cost + +Storing contract code at creation time can cost up to: + +- 200 \* max_byte_code_length gas +- 200 \* 24576 = 49152004915200 \* 10 gwei = 49152000 gwei = 0.049152 ether = 9 EUR + +see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md for more info on max_byte_code_length. diff --git a/locales/it/ProxyContract/2_How/step2.md b/locales/it/ProxyContract/2_How/step2.md new file mode 100644 index 000000000..d80b6557c --- /dev/null +++ b/locales/it/ProxyContract/2_How/step2.md @@ -0,0 +1,13 @@ +# How it works? + +**EIP-7 DelegateCall** opcode allows a separate execution in another contract while maintaining the original execution context. + +All **message calls** from the user go through a **Proxy contract**. + +The **Proxy contract** then will redirect them to the **Logic contract**. + +And when you need to **upgrade** the logic, you'll **just** deploy that - **HOWEVER** - the implementation of Proxy will remain the same. + +You'll only need to update the address of Logic contract in Proxy. + +The Proxy Contract uses **Delegate calls** and **Solidity assembly** because without it, it's impossible to return any value from **delegatecall**. diff --git a/locales/it/ProxyContract/3_Delegatecall/step3.md b/locales/it/ProxyContract/3_Delegatecall/step3.md new file mode 100644 index 000000000..8693e5567 --- /dev/null +++ b/locales/it/ProxyContract/3_Delegatecall/step3.md @@ -0,0 +1,9 @@ +# Delegate call + +It's a special variant of a **message call**, which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract so **msg.sender** and **msg.value** do not change their values. + +This means that a contract can dynamically load code from a different address at runtime. + +The storage, the current address and balance still refer to the calling contract, only the code is taken from the called address. + +So when a **Proxy** delegates calls to the Logic contract, every storage modification will impact the storage of Logic contract. diff --git a/locales/it/ProxyContract/4_Generic_proxy_example/step4.md b/locales/it/ProxyContract/4_Generic_proxy_example/step4.md new file mode 100644 index 000000000..d20fdd16d --- /dev/null +++ b/locales/it/ProxyContract/4_Generic_proxy_example/step4.md @@ -0,0 +1,15 @@ +# A Basic Generic Proxy Example + +In the associated solidity file, **step4.sol**, there are 2 contracts - **ProxyContract** and **LogicContract**. + +To use this system, we first deploy the LogicContract. + +And then when we go to deploy the ProxyContract, we pass the LogicContract's address as an argument of the ProxyContract's constructor. + +The ProxyContract is deployed only once. + +The code of LogicContract will be called at the line 20. It will be forwarded with delegate call while keeping the context of LogicContract. + +In case we need to change the logic we would deploy a new LogicContract and set the address of it with setLogicContractAddress setter function. + +_Note: The LogicContract we have here does not use the storage. Once you need to use the storage the implementation becomes a bit more complicated because those contracts share the context._ diff --git a/locales/it/ProxyContract/5_Test/step5.md b/locales/it/ProxyContract/5_Test/step5.md new file mode 100644 index 000000000..120a15e13 --- /dev/null +++ b/locales/it/ProxyContract/5_Test/step5.md @@ -0,0 +1,6 @@ +# Let's test what we've learned + +- Write a contract named "LogicContract" which implements a public function named "getNumber" which returns 10 +- Write a proxy contract named "ProxyContract". This ProxyContract should take an address of LogicContract as a first parameter. + +Good Luck! diff --git a/locales/it/ProxyContract/6_Storage_Problem/step6.md b/locales/it/ProxyContract/6_Storage_Problem/step6.md new file mode 100644 index 000000000..d2b804284 --- /dev/null +++ b/locales/it/ProxyContract/6_Storage_Problem/step6.md @@ -0,0 +1,13 @@ +# What if we have state variables? + +Things are more complicated once we need to deal with state variables. State variable are saved to **storage**. + +`storage`: is a mapping; each value stored there is persisted and saved on chain. + +_Note: Statically-sized state variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position 0. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible. For contracts that use inheritance, the ordering of state variables is determined by the C3-linearized order of contracts starting with the most base-ward contract_ + +Once we execute **delegate call**, the storage of both contracts get **"merged"** into a single messy state. + +We have to "tell" ProxyContract what the **state** of the **Logic contract** looks like. + +The easiest way to do this is to create a separate contract - in this example - named **StorageContract** which will represent the **state** and which proxyContract will inherit from. diff --git a/locales/it/ProxyContract/7_links/step7.md b/locales/it/ProxyContract/7_links/step7.md new file mode 100644 index 000000000..c2784c3cc --- /dev/null +++ b/locales/it/ProxyContract/7_links/step7.md @@ -0,0 +1,19 @@ +# Check out some links for more info + +- ERC DelegateProxy + https://github.com/ethereum/EIPs/pull/897 + +- The joint post by Zeppelin Solutions and Aragon. + https://blog.openzeppelin.com/proxy-libraries-in-solidity-79fbe4b970fd/ + +- Proxy Patterns by OpenZeppelin + https://blog.openzeppelin.com/proxy-patterns/ + +- The most mature implementation of Proxy pattern is The Unstructure Storage pattern that is released as part of ZeppelinOS + https://blog.openzeppelin.com/upgradeability-using-unstructured-storage/ + +- Great blog post by Jack Tanner + https://blog.indorse.io/ethereum-upgradeable-smart-contract-strategies-456350d0557c + +- Upgradeable Ethereum Smart Contracts + https://medium.com/@daonomic/upgradeable-ethereum-smart-contracts-d036cb373d6 diff --git a/locales/it/ProxyContract/README.md b/locales/it/ProxyContract/README.md new file mode 100644 index 000000000..6a5364c94 --- /dev/null +++ b/locales/it/ProxyContract/README.md @@ -0,0 +1,3 @@ +## Learn the Proxy Pattern + +Save gas & make upgradable contracts diff --git a/locales/it/ProxyContract/config.yml b/locales/it/ProxyContract/config.yml new file mode 100644 index 000000000..e36e640b8 --- /dev/null +++ b/locales/it/ProxyContract/config.yml @@ -0,0 +1,9 @@ +--- +id: proxycontract +name: All about Proxy Contracts +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 3 +tags: + - Remix + - Solidity + - Code Patterns diff --git a/locales/it/README.md b/locales/it/README.md new file mode 100644 index 000000000..cb799bd20 --- /dev/null +++ b/locales/it/README.md @@ -0,0 +1,36 @@ +# This is a repo of tutorials for the Remix's LearnEth Plugin + +### To use these tutorials: + +**1. Open Remix** + +https://remix.ethereum.org + +**2. In the plugin manager activate LEARNETH** + +**3. Go to the Learneth plugin and these tutorials will load by default** + +**4. You may need to sign into Github especially during an in-person workshop** + +Github will block too many requests from the same location, unless you are signed into Github and have input your token. Generally, this is only an issue during in person workshops, when there can be many requests from the same location. + +To input your Github token: + +``` +- In one browser window - go to https://remix.ethereum.org and go to the settings tab +- In another browser window go to: + +https://github.com/settings/tokens + +and create a new token and save it in Remix in the you just opened on the settings tab. +``` + +--- + +### Write your own tutorials for LEARNETH: + +See this site for instructions: + +https://remix-learneth-plugin.readthedocs.io/en/latest/index.html#creating-tutorials + +--- diff --git a/locales/it/Recorder/1_Usecases/1_usecases.md b/locales/it/Recorder/1_Usecases/1_usecases.md new file mode 100644 index 000000000..0c624393c --- /dev/null +++ b/locales/it/Recorder/1_Usecases/1_usecases.md @@ -0,0 +1,7 @@ +1. You want to show someone what happens when you do a number of transactions with a contract and you don't want to explain each step - you just want to get them to the last step. + + - To show someone a problem in their code. + + - In a class, to get the students to a certain place and have them start working from there. + +2. You want to start your development in the JavascriptVM because it is quick and then to switch to another testnet - but you don't want to manually repeat all the tedious clicking for each different network. diff --git a/locales/it/Recorder/2_Record/README.md b/locales/it/Recorder/2_Record/README.md new file mode 100644 index 000000000..41d214277 --- /dev/null +++ b/locales/it/Recorder/2_Record/README.md @@ -0,0 +1,32 @@ +# Setting up a tedious series of steps + +## Following this could get tedious but that's the point. + +We are going to: + +- Deploy a voting contract where there are 3 proposals input in the constructor. +- Give voting privileges to 2 additional address (so we have a total of 3 voting addresses). +- Have one address vote for proposal 1 (0-based index) and the other two vote for proposal 2. + +1. Take the 3_Ballot.sol from the sample solidity files and compile it. Then go to the **Deploy & Run** Module. + +2. Select the **JavaScript VM** Environment. + +3. In the constructor's parameter - put in **["0x5031000000000000000000000000000000000000000000000000000000000000", "0x5032000000000000000000000000000000000000000000000000000000000000", "0x5033000000000000000000000000000000000000000000000000000000000000"]** Then click the **Deploy** button. + +4. Open up the deployed contract. + +5. In the **vote** function put in 2. This means that you as the msg.sender & chairperson are voting for proposal at position 2, which is the last proposal in our list. + +6. Now you need to give other addresses the right to vote. Select another address in the **account** pulldown and copy it and then **go back to the 1st address**. Paste the copy address into the textbox next to the giveRightToVote function. And again, select another address and copy it and **then go back to the 1st address** again and paste it into giveRightToVote. + +7. Now you have 3 addresses with the right to vote. + +8. Switch to one of the addresses that you gave the right to vote and vote for proposal **1**. (Put **1** in the textbox next to the vote function). And then switch to the other address and vote for proposal **2** with that one. + +9. Open up the **Transactions recorded** section of the module - by clicking on the caret. Click the hard disk icon in the **Transactions recorded** section to save your steps. + ![recorder](https://github.com/ethereum/remix-workshops/blob/master/Recorder/2_Record/images/recorder.png?raw=true "recorder") + +10. You will get a modal window that tells you it wants to save a file called **scenario.json**. Click OK. + +11. Click on the function **winningProposal** to confirm that the final proposal won - which is the proposal at position 2 in the array. **0: uint256: winningProposal_ 2** diff --git a/locales/it/Recorder/3_Editing_a_Senario/README.md b/locales/it/Recorder/3_Editing_a_Senario/README.md new file mode 100644 index 000000000..d23dfb95c --- /dev/null +++ b/locales/it/Recorder/3_Editing_a_Senario/README.md @@ -0,0 +1,54 @@ +# Editing a scenario + +Here's the first few lines of the scenario that I recorded. The addresses on my machine will be different from your's. + +``` +{ + "accounts": { + "account{0}": "0xca35b7d915458ef540ade6068dfe2f44e8fa733c", + "account{4}": "0xdd870fa1b7c4700f2bd7f44238821c26f7392148", + "account{3}": "0x583031d1113ad414f02576bd6afabfb302140225" + } +``` + +So if you wanted to play this scenario in another testnet, you'd need to change these addresses to address that you have test ETH on so that you could pay for the transactions. But other than swapping out the addresses, you can quickly run this on other nets. + +And you might change the parameters for the functions. + +For example here is a bit of the scenario.json a bit further down where proposal 2 was voted for by one of the addresses: + +``` +{ + "timestamp": 1566428184043, + "record": { + "value": "0", + "parameters": [ + "2" + ], + "to": "created{1566428035436}", + "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", + "name": "vote", + "inputs": "(uint8)", + "type": "function", + "from": "account{4}" + } + }, +``` + +Let's edit this so that another proposal wins in the playback. + +Change the **parameters** array which now is: + +``` +"parameters": [ + "2" + ] +``` + +to: + +``` +"parameters": [ + "1" + ] +``` diff --git a/locales/it/Recorder/4_Play/README.md b/locales/it/Recorder/4_Play/README.md new file mode 100644 index 000000000..196664550 --- /dev/null +++ b/locales/it/Recorder/4_Play/README.md @@ -0,0 +1,8 @@ +# Playing a scenario + +1. Click the play icon to the right of the floppy disk icon to play the steps you did. + +2. You'll see another instance of the contract deployed. Open it up. + +3. Click the winningProposal function and you should see now that proposal 1 won. + It should print out: **0: uint256: winningProposal_ 1** diff --git a/locales/it/Recorder/README.md b/locales/it/Recorder/README.md new file mode 100644 index 000000000..94d928383 --- /dev/null +++ b/locales/it/Recorder/README.md @@ -0,0 +1,3 @@ +## Get yourself Remixing! + +The recorder is used for recording a set of transactions in the Deploy & Run module, editing their parameters and then playing them back in another context. It really is the remix of Remix! diff --git a/locales/it/Recorder/config.yml b/locales/it/Recorder/config.yml new file mode 100644 index 000000000..b8980e042 --- /dev/null +++ b/locales/it/Recorder/config.yml @@ -0,0 +1,7 @@ +--- +id: recorder +name: Recorder +summary: Save a set of actions and replay and replay and replay +level: 2 +tags: + - Remix diff --git a/locales/it/SolidityBeginnerCourse/README.md b/locales/it/SolidityBeginnerCourse/README.md new file mode 100644 index 000000000..ae0b6d882 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Course + +Learn the most important Solidity beginner concepts interactively, based on the popular https://solidity-by-example.org/ contracts. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/it/SolidityBeginnerCourse/basic-syntax/basicSyntax.md b/locales/it/SolidityBeginnerCourse/basic-syntax/basicSyntax.md new file mode 100644 index 000000000..e9f77871e --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/basic-syntax/basicSyntax.md @@ -0,0 +1,26 @@ +In this section, we will create our first _smart contract_. This contract only consists of a string that holds the value "Hello World!". + +In the first line, we should specify the license that we want to use. You can find a comprehensive list of licenses here: https://spdx.org/licenses/. + +Using the `pragma` keyword (line 3), we specify the Solidity version we want the compiler to use. In this case, it should be greater than or equal to `0.8.3` but less than 0.9.0. + +We define a contract with the keyword `contract` and give it a name, in this case, `HelloWorld` (line 5). + +Inside our contract, we define a _state variable_ `greet` that holds the string `"Hello World!"` (line 6). + +Solidity is a _statically typed_ language, which means that you need to specify the type of the variable when you declare it. In this case, `greet` is a `string`. + +We also define the _visibility_ of the variable, which specifies from where you can access it. In this case, it's a `public` variable that you can access from inside and outside the contract. + +Don't worry if you didn't understand some concepts like _visibility_, _data types_, or _state variables_. We will look into them in the following sections. + +To help you understand the code, we will link in all following sections to video tutorials from the creator of the Solidity by Example contracts. + +Watch a video tutorial on Basic Syntax. + +## ⭐️ Assignment + +1. Delete the HelloWorld contract and its content. +2. Create a new contract named "MyContract". +3. The contract should have a public state variable called "name" of the type string. +4. Assign the value "Alice" to your new variable. diff --git a/locales/it/SolidityBeginnerCourse/config.yml b/locales/it/SolidityBeginnerCourse/config.yml new file mode 100644 index 000000000..a729093d8 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/config.yml @@ -0,0 +1,65 @@ +--- +id: soliditybeginner +name: Solidity Beginner Course +summary: Solidity Beginner Course based on the popular https://solidity-by-example.org/ contracts. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Basic Syntax + path: basic-syntax + - + name: 3. Primitive Data Types + path: primitive-data-types + - + name: 4. Variables + path: variables + - + name: 5.1 Functions - Reading and Writing to a State Variable + path: functions-reading-and-writing + - + name: 5.2 Functions - View and Pure + path: functions-view-and-pure + - + name: 5.3 Functions - Modifiers and Constructors + path: functions-modifiers-and-constructors + - + name: 5.4 Functions - Inputs and Outputs + path: functions-inputs-and-outputs + - + name: 6. Visibility + path: visibility + - + name: 7.1 Control Flow - If/Else + path: control-flow-if-else + - + name: 7.2 Control Flow - Loops + path: control-flow-loops + - + name: 8.1 Data Structures - Arrays + path: data-structures-arrays + - + name: 8.2 Data Structures - Mappings + path: data-structures-mappings + - + name: 8.3 Data Structures - Structs + path: data-structures-structs + - + name: 8.4 Data Structures - Enums + path: data-structures-enums + - + name: 9. Data Locations + path: data-locations + - + name: 10.1 Transactions - Ether and Wei + path: transactions-ether-and-wei + - + name: 10.2 Transactions - Gas and Gas Price + path: transactions-gas-and-gas-price + - + name: 10.3 Transactions - Sending Ether + path: transactions-sending-ether diff --git a/locales/it/SolidityBeginnerCourse/control-flow-if-else/ifElse.md b/locales/it/SolidityBeginnerCourse/control-flow-if-else/ifElse.md new file mode 100644 index 000000000..634e27689 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/control-flow-if-else/ifElse.md @@ -0,0 +1,33 @@ +Solidity supports different control flow statements that determine which parts of the contract will be executed. The conditional _If/Else statement_ enables contracts to make decisions depending on whether boolean conditions are either `true` or `false`. + +Solidity differentiates between three different If/Else statements: `if`, `else`, and `else if`. + +### if + +The `if` statement is the most basic statement that allows the contract to perform an action based on a boolean expression. + +In this contract’s `foo` function (line 5) the if statement (line 6) checks if `x` is smaller than `10`. If the statement is true, the function returns `0`. + +### else + +The `else` statement enables our contract to perform an action if conditions are not met. + +In this contract, the `foo` function uses the `else` statement (line 10) to return `2` if none of the other conditions are met. + +### else if + +With the `else if` statement we can combine several conditions. + +If the first condition (line 6) of the foo function is not met, but the condition of the `else if` statement (line 8) becomes true, the function returns `1`. + +Watch a video tutorial on the If/Else statement. + +## ⭐️ Assignment + +Create a new function called `evenCheck` in the `IfElse` contract: + +- That takes in a `uint` as an argument. +- The function returns `true` if the argument is even, and `false` if the argument is odd. +- Use a ternery operator to return the result of the `evenCheck` function. + +Tip: The modulo (%) operator produces the remainder of an integer division. diff --git a/locales/it/SolidityBeginnerCourse/control-flow-loops/loops.md b/locales/it/SolidityBeginnerCourse/control-flow-loops/loops.md new file mode 100644 index 000000000..ffaa30650 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/control-flow-loops/loops.md @@ -0,0 +1,32 @@ +Solidity supports iterative control flow statements that allow contracts to execute code repeatedly. + +Solidity differentiates between three types of loops: `for`, `while`, and `do while` loops. + +### for + +Generally, `for` loops (line 7) are great if you know how many times you want to execute a certain block of code. In solidity, you should specify this amount to avoid transactions running out of gas and failing if the amount of iterations is too high. + +### while + +If you don’t know how many times you want to execute the code but want to break the loop based on a condition, you can use a `while` loop (line 20). +Loops are seldom used in Solidity since transactions might run out of gas and fail if there is no limit to the number of iterations that can occur. + +### do while + +The `do while` loop is a special kind of while loop where you can ensure the code is executed at least once, before checking on the condition. + +### continue + +The `continue` statement is used to skip the remaining code block and start the next iteration of the loop. In this contract, the `continue` statement (line 10) will prevent the second if statement (line 12) from being executed. + +### break + +The `break` statement is used to exit a loop. In this contract, the break statement (line 14) will cause the for loop to be terminated after the sixth iteration. + +Watch a video tutorial on Loop statements. + +## ⭐️ Assignment + +1. Create a public `uint` state variable called count in the `Loop` contract. +2. At the end of the for loop, increment the count variable by 1. +3. Try to get the count variable to be equal to 9, but make sure you don’t edit the `break` statement. diff --git a/locales/it/SolidityBeginnerCourse/data-locations/dataLocations.md b/locales/it/SolidityBeginnerCourse/data-locations/dataLocations.md new file mode 100644 index 000000000..881bf8ffc --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/data-locations/dataLocations.md @@ -0,0 +1,54 @@ +The values of variables in Solidity can be stored in different data locations: _memory_, _storage_, and _calldata_. + +As we have discussed before, variables of the value type store an independent copy of a value, while variables of the reference type (array, struct, mapping) only store the location (reference) of the value. + +If we use a reference type in a function, we have to specify in which data location their values are stored. The price for the execution of the function is influenced by the data location; creating copies from reference types costs gas. + +### Storage + +Values stored in _storage_ are stored permanently on the blockchain and, therefore, are expensive to use. + +In this contract, the state variables `arr`, `map`, and `myStructs` (lines 5, 6, and 10) are stored in storage. State variables are always stored in storage. + +### Memory + +Values stored in _memory_ are only stored temporarily and are not on the blockchain. They only exist during the execution of an external function and are discarded afterward. They are cheaper to use than values stored in _storage_. + +In this contract, the local variable `myMemstruct` (line 19), as well as the parameter `_arr` (line 31), are stored in memory. Function parameters need to have the data location _memory_ or _calldata_. + +### Calldata + +_Calldata_ stores function arguments. Like _memory_, _calldata_ is only stored temporarily during the execution of an external function. In contrast to values stored in _memory_, values stored in _calldata_ can not be changed. Calldata is the cheapest data location to use. + +In this contract, the parameter `_arr` (line 35) has the data location _calldata_. If we wanted to assign a new value to the first element of the array `_arr`, we could do that in the `function g` (line 31) but not in the `function h` (line 35). This is because `_arr` in `function g `has the data location _memory_ and _function h_ has the data location `calldata`. + +## Assignments + +### Memory to memory + +Assignments from _memory_ to _memory_ create references instead of copies. If you change the value in one variable, the value of all other variables that reference the same data will be changed. + +If we were to create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myMemStruct` (line 19), any change to `myMemStruct2` would also change the value of `myMemStruct`. + +### Storage to local storage + +Assignments from _storage_ to _local storage_ also create references, not copies. + +If we change the value of the local variable `myStruct` (line 17), the value of our state variable `myStructs` (line 10) changes as well. + +## Storage and memory/calldata + +Assignments between _storage_ and _memory_ (or _calldata_) create independent copies, not references. + +If we were to create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myStruct`, changes in `myMemStruct3` would not affect the values stored in the mapping `myStructs` (line 10). + +As we said in the beginning, when creating contracts we have to be mindful of gas costs. Therefore, we need to use data locations that require the lowest amount of gas possible. + +## ⭐️ Assignment + +1. Change the value of the `myStruct` member `foo`, inside the `function f`, to 4. +2. Create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` and assign it the value of `myMemStruct`. Change the value of the `myMemStruct2` member `foo` to 1. +3. Create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` and assign it the value of `myStruct`. Change the value of the `myMemStruct3` member `foo` to 3. +4. Let the function f return `myStruct`, `myMemStruct2`, and `myMemStruct3`. + +Tip: Make sure to create the correct return types for the function `f`. diff --git a/locales/it/SolidityBeginnerCourse/data-structures-arrays/arrays.md b/locales/it/SolidityBeginnerCourse/data-structures-arrays/arrays.md new file mode 100644 index 000000000..19af3de49 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/data-structures-arrays/arrays.md @@ -0,0 +1,44 @@ +In the next sections, we will look into the data structures that we can use to organize and store our data in Solidity. + +_Arrays_, _mappings_ and _structs_ are all _reference types_. Unlike _value types_ (e.g. _booleans_ or _integers_) reference types don't store their value directly. Instead, they store the location where the value is being stored. Multiple reference type variables could reference the same location, and a change in one variable would affect the others, therefore they need to be handled carefully. + +In Solidity, an array stores an ordered list of values of the same type that are indexed numerically. + +There are two types of arrays, compile-time _fixed-size_ and _dynamic arrays_. For fixed-size arrays, we need to declare the size of the array before it is compiled. The size of dynamic arrays can be changed after the contract has been compiled. + +### Declaring arrays + +We declare a fixed-size array by providing its type, array size (as an integer in square brackets), visibility, and name (line 9). + +We declare a dynamic array in the same manner. However, we don’t provide an array size and leave the brackets empty (line 6). + +### Initializing arrays + +We can initialize the elements of an array all at once (line 7), or initiate new elements one by one (arr[0] = 1;). If we declare an array, we automatically initialize its elements with the default value 0 (line 9). + +### Accessing array elements + +We access elements inside an array by providing the name of the array and the index in brackets (line 12). + +### Adding array elements + +Using the `push()` member function, we add an element to the end of a dynamic array (line 25). + +### Removing array elements + +Using the `pop()` member function, we delete the last element of a dynamic array (line 31). + +We can use the `delete` operator to remove an element with a specific index from an array (line 42). +When we remove an element with the `delete` operator all other elements stay the same, which means that the length of the array will stay the same. This will create a gap in our array. +If the order of the array is not important, then we can move the last element of the array to the place of the deleted element (line 46), or use a mapping. A mapping might be a better choice if we plan to remove elements in our data structure. + +### Array length + +Using the length member, we can read the number of elements that are stored in an array (line 35). + +Watch a video tutorial on Arrays. + +## ⭐️ Assignment + +1. Initialize a public fixed-sized array called `arr3` with the values 0, 1, 2. Make the size as small as possible. +2. Change the `getArr()` function to return the value of `arr3`. diff --git a/locales/it/SolidityBeginnerCourse/data-structures-enums/enums.md b/locales/it/SolidityBeginnerCourse/data-structures-enums/enums.md new file mode 100644 index 000000000..40411db67 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/data-structures-enums/enums.md @@ -0,0 +1,33 @@ +In Solidity _enums_ are custom data types consisting of a limited set of constant values. We use enums when our variables should only get assigned a value from a predefined set of values. + +In this contract, the state variable `status` can get assigned a value from the limited set of provided values of the enum `Status` representing the various states of a shipping status. + +### Defining enums + +We define an enum with the enum keyword, followed by the name of the custom type we want to create (line 6). Inside the curly braces, we define all available members of the enum. + +### Initializing an enum variable + +We can initialize a new variable of an enum type by providing the name of the enum, the visibility, and the name of the variable (line 16). Upon its initialization, the variable will be assigned the value of the first member of the enum, in this case, Pending (line 7). + +Even though enum members are named when you define them, they are stored as unsigned integers, not strings. They are numbered in the order that they were defined, the first member starting at 0. The initial value of status, in this case, is 0. + +### Accessing an enum value + +To access the enum value of a variable, we simply need to provide the name of the variable that is storing the value (line 25). + +### Updating an enum value + +We can update the enum value of a variable by assigning it the `uint` representing the enum member (line 30). Shipped would be 1 in this example. Another way to update the value is using the dot operator by providing the name of the enum and its member (line 35). + +### Removing an enum value + +We can use the delete operator to delete the enum value of the variable, which means as for arrays and mappings, to set the default value to 0. + +Watch a video tutorial on Enums. + +## ⭐️ Assignment + +1. Define an enum type called `Size` with the members `S`, `M`, and `L`. +2. Initialize the variable `sizes` of the enum type `Size`. +3. Create a getter function `getSize()` that returns the value of the variable `sizes`. diff --git a/locales/it/SolidityBeginnerCourse/data-structures-mappings/mappings.md b/locales/it/SolidityBeginnerCourse/data-structures-mappings/mappings.md new file mode 100644 index 000000000..72fc4acb4 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/data-structures-mappings/mappings.md @@ -0,0 +1,37 @@ +In Solidity, _mappings_ are a collection of key types and corresponding value type pairs. + +The biggest difference between a mapping and an array is that you can't iterate over mappings. If we don't know a key we won't be able to access its value. If we need to know all of our data or iterate over it, we should use an array. + +If we want to retrieve a value based on a known key we can use a mapping (e.g. addresses are often used as keys). Looking up values with a mapping is easier and cheaper than iterating over arrays. If arrays become too large, the gas cost of iterating over it could become too high and cause the transaction to fail. + +We could also store the keys of a mapping in an array that we can iterate over. + +### Creating mappings + +Mappings are declared with the syntax `mapping(KeyType => ValueType) VariableName`. +The key type can be any built-in value type or any contract, but not a reference type. The value type can be of any type. + +In this contract, we are creating the public mapping `myMap` (line 6) that associates the key type `address` with the value type `uint`. + +### Accessing values + +The syntax for interacting with key-value pairs of mappings is similar to that of arrays. +To find the value associated with a specific key, we provide the name of the mapping and the key in brackets (line 11). + +In contrast to arrays, we won't get an error if we try to access the value of a key whose value has not been set yet. When we create a mapping, every possible key is mapped to the default value 0. + +### Setting values + +We set a new value for a key by providing the mapping’s name and key in brackets and assigning it a new value (line 16). + +### Removing values + +We can use the delete operator to delete a value associated with a key, which will set it to the default value of 0. As we have seen in the arrays section. + +Watch a video tutorial on Mappings. + +## ⭐️ Assignment + +1. Create a public mapping `balances` that associates the key type `address` with the value type `uint`. +2. Change the functions `get` and `remove` to work with the mapping balances. +3. Change the function `set` to create a new entry to the balances mapping, where the key is the address of the parameter and the value is the balance associated with the address of the parameter. diff --git a/locales/it/SolidityBeginnerCourse/data-structures-structs/structs.md b/locales/it/SolidityBeginnerCourse/data-structures-structs/structs.md new file mode 100644 index 000000000..fba0d93b0 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/data-structures-structs/structs.md @@ -0,0 +1,29 @@ +In Solidity, we can define custom data types in the form of _structs_. Structs are a collection of variables that can consist of different data types. + +### Defining structs + +We define a struct using the `struct` keyword and a name (line 5). Inside curly braces, we can define our struct’s members, which consist of the variable names and their data types. + +### Initializing structs + +There are different ways to initialize a struct. + +Positional parameters: We can provide the name of the struct and the values of its members as parameters in parentheses (line 16). + +Key-value mapping: We provide the name of the struct and the keys and values as a mapping inside curly braces (line 19). + +Initialize and update a struct: We initialize an empty struct first and then update its member by assigning it a new value (line 23). + +### Accessing structs + +To access a member of a struct we can use the dot operator (line 33). + +### Updating structs + +To update a structs’ member we also use the dot operator and assign it a new value (lines 39 and 45). + +Watch a video tutorial on Structs. + +## ⭐️ Assignment + +Create a function `remove` that takes a `uint` as a parameter and deletes a struct member with the given index in the `todos` mapping. diff --git a/locales/it/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md b/locales/it/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md new file mode 100644 index 000000000..d0e628f6b --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md @@ -0,0 +1,37 @@ +In this section, we will learn more about the inputs and outputs of functions. + +### Multiple named Outputs + +Functions can return multiple values that can be named and assigned to their name. + +The `returnMany` function (line 6) shows how to return multiple values. +You will often return multiple values. It could be a function that collects outputs of various functions and returns them in a single function call for example. + +The `named` function (line 19) shows how to name return values. +Naming return values helps with the readability of your contracts. Named return values make it easier to keep track of the values and the order in which they are returned. You can also assign values to a name. + +The `assigned` function (line 33) shows how to assign values to a name. +When you assign values to a name you can omit (leave out) the return statement and return them individually. + +### Deconstructing Assignments + +You can use deconstructing assignments to unpack values into distinct variables. + +The `destructingAssigments` function (line 49) assigns the values of the `returnMany` function to the new local variables `i`, `b`, and `j` (line 60). + +### Input and Output restrictions + +There are a few restrictions and best practices for the input and output parameters of contract functions. + +"_[Mappings] cannot be used as parameters or return parameters of contract functions that are publicly visible._" +From the Solidity documentation. + +Arrays can be used as parameters, as shown in the function `arrayInput` (line 71). Arrays can also be used as return parameters as shown in the function `arrayOutput` (line 76). + +You have to be cautious with arrays of arbitrary size because of their gas consumption. While a function using very large arrays as inputs might fail when the gas costs are too high, a function using a smaller array might still be able to execute. + +Watch a video tutorial on Function Outputs. + +## ⭐️ Assignment + +Create a new function called `returnTwo` that returns the values `-2` and `true` without using a return statement. diff --git a/locales/it/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md b/locales/it/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md new file mode 100644 index 000000000..d707a987b --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md @@ -0,0 +1,39 @@ +In this section, we will learn how to modify the behavior of a function and how to run contract initialization code. + +### Function Modifier + +_Function Modifiers_ are used to change the behavior of a function. For example, they often check for a condition prior to executing a function to restrict access or validate inputs. + +This first part of this contract is about changing ownership of a contract. Ownership in this contract is expressed by the value of the state variable `owner` that is of the type `address` (line 7). + +The function `changeOwner` (line 33) can change this ownership. It takes an input parameter of the type `address` and assigns its value to the state variable `owner`. + +However, this function cannot simply be executed under all conditions; it has two modifiers, `onlyOwner` and `validAddress`. + +Let's look at `onlyOwner` first (line 18). +Function modifiers are defined with the `modifier` keyword and a unique name; they can also have parameters. + +The underscore `_` (line 23) is used inside modifiers to represent the rest of the code that will be executed in the body of the modified function. +The code you place before the underscore in the modifier will be executed before the code in the body of the modified function. The code after the underscore will be executed after the code in the body of the modified function. + +In this case, the `require` function (line 19) checks if the address executing the contract is the same as the value stored in the variable `owner`. If it is, the rest of the code will be executed, otherwise it will throw an error. + +You can learn more about `assert` and `require` in the Solidity documentation, they are used to check for conditions and throw errors if they are not met. + +The `validAddress` modifier (line 28) has a parameter of type `address` and checks if the provided address is valid. If it is, it continues to execute the code. + +### Constructor + +A constructor function is executed upon the creation of a contract. You can use it to run contract initialization code. The constructor can have parameters and is especially useful when you don't know certain initialization values before the deployment of the contract. + +You declare a constructor using the `constructor` keyword. The constructor in this contract (line 11) sets the initial value of the owner variable upon the creation of the contract. + +Watch a video tutorial on Function Modifiers. + +## ⭐️ Assignment + +1. Create a new function, `increaseX` in the contract. The function should take an input parameter of type `uint` and increase the value of the variable `x` by the value of the input parameter. +2. Make sure that x can only be increased. +3. The body of the function `increaseX` should be empty. + +Tip: Use modifiers. diff --git a/locales/it/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md b/locales/it/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md new file mode 100644 index 000000000..3670c03e2 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md @@ -0,0 +1,23 @@ +This section will give a short introduction to functions and teach you how to use them to read from and write to a state variable. + +As in other languages, we use functions in Solidity to create modular, reusable code. However, Solidity functions have some particularities. + +Solidity functions can be split into two types: + +1. Functions that modify the state of the blockchain, like writing to a state variable. In this contract, the `set` function (line 9) changes the state variable `num`. +2. Functions that don't modify the state of the blockchain. These functions are marked `view` or `pure`. For example, in this contract, the `get` function (line 14) marked `view` that only returns `num` does not change the state. + +To define a function, use the `function` keyword followed by a unique name. + +If the function takes inputs like our `set` function (line 9), you must specify the parameter types and names. A common convention is to use an underscore as a prefix for the parameter name to distinguish them from state variables. + +You can then set the visibility of a function and declare them `view` or `pure` as we do for the `get` function if they don't modify the state. Our `get` function also returns values, so we have to specify the return types. In this case, it's a `uint` since the state variable `num` that the function returns is a `uint`. + +We will explore the particularities of Solidity functions in more detail in the following sections. + +Watch a video tutorial on Functions. + +## ⭐️ Assignment + +1. Create a public state variable called `b` that is of type `bool` and initialize it to `true`. +2. Create a public function called `get_b` that returns the value of `b`. diff --git a/locales/it/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md b/locales/it/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md new file mode 100644 index 000000000..b846c7d99 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md @@ -0,0 +1,44 @@ +This section will look into the types of functions that don't modify the state of the blockchain: _view_ and _pure_ functions. + +### View Functions + +_View functions_ promise to not modify the state. + +"The following statements are considered modifying the state: + +1. Writing to state variables. +2. Emitting events. +3. Creating other contracts. +4. Using selfdestruct. +5. Sending Ether via calls. +6. Calling any function not marked view or pure. +7. Using low-level calls. +8. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a view function using the keyword `view`. In this contract, `addToX` (line 8) is a view function. This function takes the parameter `y` and returns the sum of the parameter and the state variable `x`. It reads `x` but does not modify it. + +### Pure functions + +_Pure functions_ promise to neither modify nor to read the state. + +"In addition to the list of state modifying statements explained above, the following are considered reading from the state: + +1. Reading from state variables. +2. Accessing `address(this).balance` or `
.balance`. +3. Accessing any of the members of block, tx, msg (with the exception of `msg.sig` and `msg.data`). +4. Calling any function not marked pure. +5. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a pure function using the keyword `pure`. In this contract, `add` (line 13) is a pure function. This function takes the parameters `i` and `j`, and returns the sum of them. It neither reads nor modifies the state variable `x`. + +In Solidity development, you need to optimise your code for saving computation cost (gas cost). Declaring functions view and pure can save gas cost and make the code more readable and easier to maintain. Pure functions don't have any side effects and will always return the same result if you pass the same arguments. + +Watch a video tutorial on View and Pure Functions. + +## ⭐️ Assignment + +Create a function called `addToX2` that takes the parameter `y` and updates the state variable `x` with the sum of the parameter and the state variable `x`. diff --git a/locales/it/SolidityBeginnerCourse/introduction/introduction.md b/locales/it/SolidityBeginnerCourse/introduction/introduction.md new file mode 100644 index 000000000..cc821a46a --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/introduction/introduction.md @@ -0,0 +1,32 @@ +Welcome to this interactive Solidity course for beginners. + +In this first section, we will give you a short preview of the concepts we will cover in this course, look at an example smart contract, and show you how you can interact with this contract in the Remix IDE. + +This contract is a counter contract that has the functionality to increase, decrease, and return the state of a counter variable. + +If we look at the top of the contract, we can see some information about the contract like the license (line 1), the Solidity version (line 2), as well as the keyword `contract` and it's name, `Counter` (line 4). We will cover these concepts in the next section about the **Basic Syntax**. + +With `uint public count` (line 5) we declare a state variable of the type `uint` with the visibility `public`. We will cover these concepts in our sections about **Variables**, **Primitive Data Types**, and **Visibility**. + +We then create a `get` function (line 8) that is defined with the `view` keyword and returns a `uint` type. Specifically, it returns the `count` variable. This contract has two more functions, an `inc` (line 13) and `dec` (line 18) function that increases or decreases our count variable. +We will talk about these concepts in our sections about **Functions - Reading and Writing to a State Variable** and **Functions - View and pure**. + +## Compile and Deploy through Remix + +**GIF** Interacting with the contract: Compile and deploy contract + +1. We can compile your `Counter` contract in the "Solidity compiler" module of the Remix IDE. + +2. In the "Deploy & run transactions" module, we select our contract "Counter" in the contract input field and click on the "Deploy" button. + +3. We expand the token contract functions in the IDE, and test its `get`, `inc`, and `dec` functions. + +## ⭐️ Assignment + +Throughout this course, we will give you assignments to test and consolidate your newly acquired knowledge. + +Your first assignment is to: + +1. Compile this contract. +2. Deploy it to the Remix VM. +3. Interact with your contract. diff --git a/locales/it/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md b/locales/it/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md new file mode 100644 index 000000000..9ea6b8626 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md @@ -0,0 +1,33 @@ +In this section, we will show you Solidity’s primitive data types, how to declare them, and their characteristics. + +### bool + +You can declare data a boolean type by using the keyword ‘bool’. Booleans can either have the value `true` or `false`. + +### uint + +We use the keywords `uint` and `uint8` to `uint256` to declare an _unsigned integer type_ (they don’t have a sign, unlike -12, for example). Uints are integers that are positive or zero and range from 8 bits to 256 bits. The type `uint` is the same as `uint256`. + +### int + +We use the keywords `int` and `int8` to `int256` to declare an integer type. Integers can be positive, negative, or zero and range from 8 bits to 256 bits. The type `int` is the same as `int256`. + +### address + +Variables of the type `address` hold a 20-byte value, which is the size of an Ethereum address. There is also a special kind of Ethereum address, `address payable`, which can receive ether from the contract. + +All these data types have default values, as shown in the contract (line 29). + +You can learn more about these data types as well as _Fixed Point Numbers_, _Byte Arrays_, _Strings_, and more in the Solidity documentation. + +Later in the course, we will look at data structures like **Mappings**, **Arrays**, **Enums**, and **Structs**. + +Watch a video tutorial on Primitive Data Types. + +## ⭐️ Assignment + +1. Create a new variable `newAddr` that is a `public` `address` and give it a value that is not the same as the available variable `addr`. +2. Create a `public` variable called `neg` that is a negative number, decide upon the type. +3. Create a new variable, `newU` that has the smallest `uint` size type and the smallest `uint` value and is `public`. + +Tip: Look at the other address in the contract or search the internet for an Ethereum address. diff --git a/locales/it/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md b/locales/it/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md new file mode 100644 index 000000000..57208c555 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md @@ -0,0 +1,26 @@ +_Ether_ (ETH) is a cryptocurrency. _Ether_ is also used to pay fees for using the Ethereum network, like making transactions in the form of sending _Ether_ to an address or interacting with an Ethereum application. + +### Ether Units + +To specify a unit of _Ether_, we can add the suffixes `wei`, `gwei`, or `ether` to a literal number. + +#### `wei` + +_Wei_ is the smallest subunit of _Ether_, named after the cryptographer [Wei Dai](https://en.wikipedia.org/wiki/Wei_Dai). _Ether_ numbers without a suffix are treated as `wei` (line 7). + +#### `gwei` + +One `gwei` (giga-wei) is equal to 1,000,000,000 (10^9) `wei`. + +#### `ether` + +One `ether` is equal to 1,000,000,000,000,000,000 (10^18) `wei` (line 11). + +Watch a video tutorial on Ether and Wei. + +## ⭐️ Assignment + +1. Create a `public` `uint` called `oneGWei` and set it to 1 `gwei`. +2. Create a `public` `bool` called `isOneGWei` and set it to the result of a comparison operation between 1 gwei and 10^9. + +Tip: Look at how this is written for `gwei` and `ether` in the contract. diff --git a/locales/it/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md b/locales/it/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md new file mode 100644 index 000000000..bbc25575c --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md @@ -0,0 +1,29 @@ +As we have seen in the previous section, executing code via transactions on the Ethereum Network costs transaction fees in the form of Ether. The amount of fees that have to be paid to execute a transaction depends on the amount of _gas_ that the execution of the transaction costs. + +### Gas + +_Gas_ is the unit that measures the amount of computational effort that is required to execute a specific operation on the Ethereum network. + +### Gas price + +The _gas_ that fuels Ethereum is sometimes compared to the gas that fuels a car. The amount of gas your car consumes is mostly the same, but the price you pay for gas depends on the market. + +Similarly, the amount of _gas_ that a transaction requires is always the same for the same computational work that is associated with it. However the price that the sender of the transaction is willing to pay for the _gas_ is up to them. Transactions with higher _gas prices_ are going through faster; transactions with very low _gas prices_ might not go through at all. + +When sending a transaction, the sender has to pay the _gas_ fee (gas_price \* gas) upon execution of the transaction. If _gas_ is left over after the execution is completed, the sender gets refunded. + +_Gas_ prices are denoted in gwei. + +### Gas limit + +When sending a transaction, the sender specifies the maximum amount of gas that they are willing to pay for. If they set the limit too low, their transaction can run out of _gas_ before being completed, reverting any changes being made. In this case, the _gas_ was consumed and can’t be refunded. + +Learn more about _gas_ on ethereum.org. + +Watch a video tutorial on Gas and Gas Price. + +## ⭐️ Assignment + +Create a new `public` state variable in the `Gas` contract called `cost` of the type `uint`. Store the value of the gas cost for deploying the contract in the new variable, including the cost for the value you are storing. + +Tip: You can check in the Remix terminal the details of a transaction, including the gas cost. You can also use the Remix plugin _Gas Profiler_ to check for the gas cost of transactions. diff --git a/locales/it/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md b/locales/it/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md new file mode 100644 index 000000000..58fb4c5a6 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md @@ -0,0 +1,86 @@ +In this section, we will learn how a contract can send and receive Ether. + +### Sending Ether + +We have three different options to transfer Ether: `transfer()`, `send()` and `call()`. + +#### **transfer** + +`
.transfer(uint256 amount)` + +- `transfer()` throws an exception on failure +- Forwards a fixed 2300 gas stipend + +An example of `transfer()` can be seen in the `SendEther` contract (line 35). +**`Transfer()` is not recommended to be used anymore.** + +#### **send** + +`
.send(uint256 amount) returns (bool)` + +- `send()` returns false on failure +- Forwards a fixed 2300 gas stipend + +An example of `send()` can be seen in the `SendEther` contract (line 41). +**`Send()` is not recommended to be used anymore.** + +#### **call** + +`
.call(bytes memory) returns (bool, bytes memory)` + +- `call()` returns false on failure +- Forwards the maximum amount of gas, but this is adjustable + +An example of `call()` can be seen in the `SendEther` contract (line 48). +`Call()` is currently recommended if you are transfering Ether. + +The reason `transfer()` and `send()` were introduced was to guard against _reentry attacks_ by limiting the forwarded gas to 2300, which would be insufficient to make a reentrant call that can modify storage. + +As we discussed in the last section, each operation on Ethereum has a specific cost associated with it. Certain operations have become more cost intensive over time, so the gas costs associated with them are also raised. When gas costs for operations are subject to change it is not good to use a hardcoded gas amount like transfer(), and send() do. + +That’s why `call()` instead of `transfer()` is now recommended to send Ether. + +Learn more about the subject in this Consensys blog post. + +### Reentrancy attack + +A _reentrancy attack_ occurs when a function makes an external call to an untrusted contract and the attacker uses the contract to make recursive calls back to the original function before it finishes its execution. Through this method, the attacker can drain funds and manipulate data in unintended ways. + +To guard against a _reentrancy attack_, all state changes should be made before calling an external contract. This is also called the Checks-Effects-Interactions pattern. + +Another way to prevent reentrancy is to use a _Reentrancy Guard_ that checks for such calls and rejects them. You can see an example of this in the contract in our modifier section or a more gas-efficient version on Open Zepplin. + +### Receiving Ether + +If we want to enable a contract to receive Ether without a function being called, we need to create a `receive` function (line 22) or a `fallback` function (line 25); otherwise, the Ether will be rejected, and the contract will throw an exception. + +The `receive` function is executed on calls with empty calldata (e.g. plain Ether transfers via send() or transfer()), while the fallback function is executed on calls with calldata. If no receive function exists but a fallback function does, calls with empty calldata will also use the fallback function. + +### Payable function modifier + +The `payable` function modifier allows a function to receive Ether. + +The `receive` function (line 22) needs to be `payable`. If you delete the `payable` modifier you will get an error from the compiler. If you delete the `payable` modifier from the `fallback` function (line 25) it will compile, but it won’t be able to receive Ether. +The functions `sendViaTransfer`, `sendViaSend`, and `sendViaCall` (lines 33, 38, and 45) also need to be `payable` in order to receive Ether. + +### Payable address + +Solidity makes a distinction between two different flavors of the address data type: address and address payable. + +`address`: Holds a 20-byte value. +`address payable`: Holds a 20-byte value and can receive Ether via its members: transfer and send. + +If you change the parameter type for the functions `sendViaTransfer` and `sendViaSend` (line 33 and 38) from `payable address` to `address`, you won’t be able to use `transfer()` (line 35) or `send()` (line 41). + +Watch a video tutorial on Sending Ether. + +## ⭐️ Assignment + +Build a charity contract that receives Ether that can be withdrawn by a beneficiary. + +1. Create a contract called `Charity`. +2. Add a public state variable called `owner` of the type address. +3. Create a donate function that is public and payable without any parameters or function code. +4. Create a withdraw function that is public and sends the total balance of the contract to the `owner` address. + +Tip: Test your contract by deploying it from one account and then sending Ether to it from another account. Then execute the withdraw function. diff --git a/locales/it/SolidityBeginnerCourse/variables/variables.md b/locales/it/SolidityBeginnerCourse/variables/variables.md new file mode 100644 index 000000000..dfb35b382 --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/variables/variables.md @@ -0,0 +1,29 @@ +There are three different types of variables in Solidity: _State Variables_, _Local Variables_, and _Global Variables_. + +## 1. State Variables + +_State Variables_ are stored in the contract _storage_ and thereby on the blockchain. They are declared inside the contract but outside the function. +This contract has two state variables, the string `text`(line 6) and the uint `num` (line 7). + +## 2. Local Variables + +_Local Variables_ are stored in the _memory_ and their values are only accessible within the function they are defined in. Local Variables are not stored on the blockchain. +In this contract, the uint `i` (line 11) is a local variable. + +## 3. Global Variables + +_Global Variables_, also called _Special Variables_, exist in the global namespace. They don't need to be declared but can be accessed from within your contract. +Global Variables are used to retrieve information about the blockchain, particular addresses, contracts, and transactions. + +In this example, we use `block.timestamp` (line 14) to get a Unix timestamp of when the current block was generated and `msg.sender` (line 15) to get the caller of the contract function’s address. + +A list of all Global Variables is available in the Solidity documentation. + +Watch video tutorials on State Variables, Local Variables, and Global Variables. + +## ⭐️ Assignment + +1. Create a new public state variable called `blockNumber`. +2. Inside the function `doSomething()`, assign the value of the current block number to the state variable `blockNumber`. + +Tip: Look into the global variables section of the Solidity documentation to find out how to read the current block number. diff --git a/locales/it/SolidityBeginnerCourse/visibility/visibility.md b/locales/it/SolidityBeginnerCourse/visibility/visibility.md new file mode 100644 index 000000000..79e4307bf --- /dev/null +++ b/locales/it/SolidityBeginnerCourse/visibility/visibility.md @@ -0,0 +1,37 @@ +The `visibility` specifier is used to control who has access to functions and state variables. + +There are four types of visibilities: `external`, `public`, `internal`, and `private`. + +They regulate if functions and state variables can be called from inside the contract, from contracts that derive from the contract (child contracts), or from other contracts and transactions. + +### private + +- Can be called from inside the contract + +### internal + +- Can be called from inside the contract +- Can be called from a child contract + +### public + +- Can be called from inside the contract +- Can be called from a child contract +- Can be called from other contracts or transactions + +### external + +- Can be called from other contracts or transactions +- State variables can not be `external` + +In this example, we have two contracts, the `Base` contract (line 4) and the `Child` contract (line 55) which inherits the functions and state variables from the `Base` contract. + +When you uncomment the `testPrivateFunc` (lines 58-60) you get an error because the child contract doesn’t have access to the private function `privateFunc` from the `Base` contract. + +If you compile and deploy the two contracts, you will not be able to call the functions `privateFunc` and `internalFunc` directly. You will only be able to call them via `testPrivateFunc` and `testInternalFunc`. + +Watch a video tutorial on Visibility. + +## ⭐️ Assignment + +Create a new function in the `Child` contract called `testInternalVar` that returns the values of all state variables from the `Base` contract that are possible to return. diff --git a/locales/it/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md b/locales/it/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md new file mode 100644 index 000000000..801d8c582 --- /dev/null +++ b/locales/it/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md @@ -0,0 +1,47 @@ +In this tutorial, we'll explore the Uniswap V3 Swap contract to learn about how single-hop and multi-hop swaps work. + +But first, some Uniswap fundamentals. + +## What is Uniswap? + +Uniswap is a decentralized cryptocurrency exchange. It allows users to exchange tokens without the need for a centralized intermediary. Uniswap is a key player in the decentralized finance (DeFi) space. + +## How does Uniswap work? + +Instead of using an order book like a traditional centralized exchange, Uniswap uses an automated market maker (AMM) model. In Uniswap, the AMM is a smart contract that holds reserves of tokens (Liquidity Pool). Users can trade between tokens in the Liquidity Pool. The price of each token is determined by the ratio of the reserves. + +### Step-by-step example of a Uniswap trade + +1. Alice wants to trade 1 ETH for DAI. +2. Alice sends 1 ETH to the Uniswap smart contract. +3. The Uniswap smart contract calculates the amount of DAI that Alice should receive based on the current exchange rate. +4. The Uniswap smart contract sends the DAI to Alice. +5. The Uniswap smart contract adds the 1 ETH to its reserves. +6. The Uniswap smart contract recalculates the exchange rate based on the new reserves. + +The tokens in the Liquidity Pool are provided by Liquidity Providers. When a Liquidity Provider deposits tokens into a Liquidity Pool, they receive Liquidity Provider Tokens in return. Liquidity Provider Tokens represent a user's share of a Liquidity Pool. + +Users of Uniswap pay a fee for each trade. The fee is paid to the Liquidity Providers in the form of additional Liquidity Provider Tokens. + +## Uniswap Swap Contract + +The Uniswap Swap contract allows users to swap tokens using Uniswap V3. It can do single-hop swaps, which allow users to exchange one token for another directly. It can also do multi-hop swaps, which means that users can exchange one token for another by routing through multiple tokens. Routing in this context means that the swap contract will exchange the token for another token, then exchange that token for another token, and so on until it reaches the desired token. + +## Conclusion + +In this section, we learned about Uniswap, how it works, and how we are going to use it to swap tokens. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is Uniswap? + +1. A centralized exchange protocol. +2. A decentralized exchange protocol that uses an order book. +3. A decentralized exchange protocol that uses an automated market maker (AMM) model. +4. A decentralized exchange protocol that uses an order book and an automated market maker (AMM) model. + +### 2) How does Uniswap determine the price of a token? + +1. The price of a token is determined by the ratio of the reserves. +2. The price of a token is determined by the ratio of the reserves and the number of trades. +3. The price of a token is determined by the ratio of the reserves and the number of Liquidity Providers. diff --git a/locales/it/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md b/locales/it/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md new file mode 100644 index 000000000..e5cc248f5 --- /dev/null +++ b/locales/it/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md @@ -0,0 +1,41 @@ +The entire UniswapSwapExamples contract will only be presented in section 5 of this tutorial. Before then, we'll build up blocks of code. + +This section explores the `ISwapRouter` interface, which defines the functions that can be called on the Uniswap Swap contract. + +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. +Multi-hop swaps allow users to exchange one token for another by routing through multiple tokens. + +Interfaces in Solidity specify functions that must be included in a contract that inherits them. They are useful for declaring what functions be supported and allow for easier integration and interaction between different contracts. + +Structs are used to define custom data types. + +## ISwapRouter Interface + +The ISwapRouter interface defines the functions that can be called on the Uniswap Swap contract. We will need to use this interface to interact with the Uniswap Swap contract and execute swaps. + +On line 5, we define a constant variable called `router` that is of type `ISwapRouter`. We set the value of this variable to the interface instance of a smart contract that is deployed at the address `0xE592427A0AEce92De3Edee1F18E0157C05861564`. This is the address of the Uniswap V3 Swap contract on the Ethereum mainnet. + +On line 9, we define an interface called `ISwapRouter`. This interface defines two functions: `exactInputSingle` and `exactInput`. + +## exactInputSingle + +On line 25, we define a struct called `ExactInputSingleParams`. This struct defines the parameters that are required for our exactInputSingle function on line 21, which will execute a single-hop swap. The struct has the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 fee`**: The fee associated with the swap. +- **`address recipient`**: The address that will receive the output token. +- **`uint deadline`**: A timestamp by which the transaction must be processed, for time-limiting the swap. +- **`uint amountIn`**: The amount of the input token being sent. +- **`uint amountOutMinimum`**: The minimum amount of the output token that the sender is willing to accept, to protect against unfavorable price movements. +- **`uint160 sqrtPriceLimitX96`**: A limit on the price, represented in a specific format, to prevent the swap from occurring at unfavorable prices. + +## exactInput + +On line 25, we define a struct called `ExactInputParams`. This struct defines the parameters that are required for our `exactInput` function on line 33. This function will execute a multi-hop swap. The struct has the following parameters: + +- **`bytes path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address recipient`**: The address receiving the output tokens. +- **`uint deadline`**: Similar to above, a timestamp by which the transaction must be processed. +- **`uint amountIn`**: The amount of the input token. +- **`uint amountOutMinimum`**: The minimum amount of the output token the sender expects to receive. diff --git a/locales/it/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md b/locales/it/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md new file mode 100644 index 000000000..f4d70c445 --- /dev/null +++ b/locales/it/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md @@ -0,0 +1,36 @@ +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. In this section, we will learn how to use the Uniswap V3 Swap contract to execute single-hop swaps. + +## Function Parameters + +On line 8, we define a function called `swapExactInputSingleHop`. This function executes a single-hop swap. It takes the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 poolFee`**: The fee associated with the swap. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +## Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 14. +Then, we approve the Uniswap Swap contract to spend the input token on our behalf, line 15. + +On line 17, we create an instance of the `ExactInputSingleParams` struct. This struct contains the parameters that are required for our `exactInputSingle` function on line 45, which will execute the single-hop swap. We repeat `ISwapRouter.ExactInputSingleParams` two times on that line because we are making an instance of a struct that is defined in an interface. + +## Parameters of the ExactInputSingleParams Struct + +We set the parameters of the struct as follows: + +- **`tokenIn`**: We set this to the `tokenIn` parameter of our function. +- **`tokenOut`**: We set this to the `tokenOut` parameter of our function. +- **`fee`**: We set this to the `poolFee` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. +- **`sqrtPriceLimitX96`**: We set this to 0 because we do not want to specify a limit on the price. + +## Executing the Single-hop Swap + +On line 29, we assign the output of the `exactInputSingle` function to the `amountOut` variable. This function executes the single-hop swap and returns the amount of the output token that was received. diff --git a/locales/it/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md b/locales/it/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md new file mode 100644 index 000000000..7883b4718 --- /dev/null +++ b/locales/it/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md @@ -0,0 +1,30 @@ +In this section, we'll delve into the `swapExactInputMultiHop` function in the `UniswapV3SwapExamples` contract. This function enables more complex token swaps by allowing users to specify a custom path through multiple liquidity pools. + +If for example, a user wants to swap token A for token D, but there is no direct liquidity pool for A and D, the user can specify a path through multiple tokens. For example, the user can swap A for B, then B for C, and finally C for D. This is of course automatically done by the Uniswap V3 Swap contract. + +### Parameters and Return Value + +On line 32, we define a function called `swapExactInputMultiHop`. This function executes a multi-hop swap. It takes the following parameters: + +- **`bytes calldata path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address tokenIn`**: The address of the token being sent. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +### Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 38. +Then, we approve the Uniswap Swap router to spend the input token on our behalf, line 41. + +On line 43, we create an instance of the `ExactInputParams` struct, line 73. This struct contains the parameters that are required for our `exactInput` function on line 81, which will execute the multi-hop swap. + +We set the parameters of the struct as follows: + +- **`path`**: We set this to the `path` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. + +On line 53, we execute the multi-hop swap by calling the `exactInput` function. This function returns the amount of the output token that was received. diff --git a/locales/it/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md b/locales/it/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md new file mode 100644 index 000000000..b3cec34e9 --- /dev/null +++ b/locales/it/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md @@ -0,0 +1,52 @@ +In this section, we'll explore the `IERC20` interface, a standard interface for interacting with ERC-20 tokens and the `IWETH` interface, a standard interface for interacting with wrapped Ether (WETH). Understanding these interfaces is crucial as it is used in the Uniswap V3 Swap contract to handle token transfers and approvals. + +You can find a "Solidity ERC20 Token Course" for beginners in LearnEth to understand the ERC20 token standard in more detail. + +## IERC20 Interface + +On line 80, we define the `IERC20` interface. This interface defines a standard set of functions that ERC-20 tokens must implement. Let's examine the key functions within this interface: + +### 1. totalSupply + +On line 81, we define the `totalSupply` function. This function returns the total supply of the token. + +### 2. balanceOf + +On line 83, we define the `balanceOf` function. This function returns the balance of the specified address. + +### 3. transfer + +On line 85, we define the `transfer` function. This function transfers tokens from the sender to the specified recipient. + +### 4. allowance + +On line 87, we define the `allowance` function. This function returns the amount of tokens that the spender is allowed to spend on behalf of the owner. + +### 5. approve + +On line 89, we define the `approve` function. When called, this function approves a spender to spend the specified amount of tokens on behalf of the sender. + +### 6. transferFrom + +On line 91, we define the `transferFrom` function. This function transfers tokens from the specified sender to the recipient. The function can only be called by the spender if the spender is allowed to spend the specified amount of tokens on behalf of the sender. + +### 7. Events + +On lines 102-103, we define the `Transfer` and `Approval` events. These events are emitted when the `transfer` and `approve` functions are called, respectively. + +## IWETH Interface + +On line 106, we define the `IWETH` interface. This interface extends the `IERC20` interface and defines two additional functions: + +### 1. deposit + +On line 107, we define the `deposit` function. This function deposits ETH into the contract and returns the equivalent amount of WETH. This function is used to wrap ETH into WETH. +We need to wrap ETH into WETH because the Uniswap V3 Swap contract only supports ERC-20 tokens. + +### 2. withdraw + +On line 109, we define the `withdraw` function. This function withdraws the specified amount of WETH from the contract and returns the equivalent amount of ETH. This function is used to unwrap WETH into ETH. + +## Conclusion + +In this tutorial, we explored the Uniswap V3 Swap contract. To get a full sense of how Uniswap works, try making some swaps on the Uniswap DApp and go to the Uniswap docs. diff --git a/locales/it/Uniswap-Tutorial/README.md b/locales/it/Uniswap-Tutorial/README.md new file mode 100644 index 000000000..cf66c5582 --- /dev/null +++ b/locales/it/Uniswap-Tutorial/README.md @@ -0,0 +1,5 @@ +# Uniswap Swap Course + +Review the code of the Uniswap V3 Swap contract for performing token swaps. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/it/Uniswap-Tutorial/config.yml b/locales/it/Uniswap-Tutorial/config.yml new file mode 100644 index 000000000..f49f02abc --- /dev/null +++ b/locales/it/Uniswap-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: uniswapSwapCourse +name: Uniswap Swap Course +summary: Go through the Solidity code of the Uniswap V3 Swap contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - Uniswap +steps: + - + name: 1. Introduction + path: 1-introduction-to-uniswap + - + name: 2. Routers, Interfaces, and Structs + path: 2-router-interfaces-and-structs + - + name: 3. Single Hop Swaps + path: 3-single-hop-swaps + - + name: 4. Multi-Hop Swaps + path: 4-multi-hop-swaps + - + name: 5. Erc20 and Weth Interfaces + path: 5-erc20-weth-interfaces diff --git a/locales/it/Web3Client/1_Using_Web3/Running_a_script.md b/locales/it/Web3Client/1_Using_Web3/Running_a_script.md new file mode 100644 index 000000000..3b7b23332 --- /dev/null +++ b/locales/it/Web3Client/1_Using_Web3/Running_a_script.md @@ -0,0 +1,24 @@ +## Querying the Blockchain + +In this tutorial, we'll run a script that queries the blockchain using a JavaScript library. + +This means that instead of using the Remix GUI or a block explorer like Etherscan, we'll use a script in the editor and will run it from the terminal. + +The JS libraries that are used the most for interacting with the blockchain are web3.js & ethers.js. + +Let's begin with a simple web3.js example, queryBlockNum.js. + +The script's call to web3.js is wrapped in a self-executing async function that contains a try/catch block. + +We'll query the current blocknumber with: +`let blockNumber = await web3.eth.getBlockNumber()` + +Note that the object `web3` is injected by Remix. For more info on web3.js, check their docs, https://web3js.readthedocs.io. + +To use web3.js or ethers.js, you need to select the **Injected Web3** or **Web3 Provider** environment in the **Deploy & Run** module. Scripts don't currently work with the JSVM. **If you try, you'll get an error.** + +So for this example choose **Injected Web3** in the Deploy & Run module and have Metamask installed. + +From the terminal, execute `remix.execute()`. This command will execute the current JavaScript file with the line `let blockNumber = await web3.eth.getBlockNumber()`. + +In the console, you should see the current block number of the chain that metamask is connected to. diff --git a/locales/it/Web3Client/2_Querying_a_Contract/queryContract.md b/locales/it/Web3Client/2_Querying_a_Contract/queryContract.md new file mode 100644 index 000000000..461c98244 --- /dev/null +++ b/locales/it/Web3Client/2_Querying_a_Contract/queryContract.md @@ -0,0 +1,23 @@ +Now that we know how to query simple data, let's try a more complex query. + +This is a contract deployed to the mainnet - at this address: https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code + +We are going to query the contract to find the name of it's token. + +The **name** variable is a state variable of the contract. + +To access this **mainnet** contract, we need to do some setup. + +1. Switch to the mainnet in metamask. +2. You'll probably need to refresh Remix. +3. As a result of the refresh, you may need to reload this tutorial too. +4. Go to Deploy & Run and switch to **Injected Web3**. + +**Using Web3** +In the script, queryContract.js, we need to instantiate a new instance of web3.eth.Contract object. For this we need to grab the contract's ABI and its address. The source code & ABI is available in etherscan because the contract's developer intentionally published it. + +In etherscan, we can see that its name is **TetherToken**. Scrolling down to the TetherToken contract in the source code section of etherscan, we can see the state variables for the contract - the first of which is named **name**. + +There are a few syntactic hoops to jump through to return the value of the state variable. + +- To call the autogenerated getter function of the public state variable, you need to both treat the variable as a function (by adding parentheses) and also to tack on a call(). diff --git a/locales/it/Web3Client/README.md b/locales/it/Web3Client/README.md new file mode 100644 index 000000000..a319f312f --- /dev/null +++ b/locales/it/Web3Client/README.md @@ -0,0 +1 @@ +This workshop is about using the web3.js to interact with a contract and more generally to the blockchain. diff --git a/locales/it/Web3Client/config.yml b/locales/it/Web3Client/config.yml new file mode 100644 index 000000000..07cb1760c --- /dev/null +++ b/locales/it/Web3Client/config.yml @@ -0,0 +1,9 @@ +--- +id: useofweb3js +name: Basic use of web3.js +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 2 +tags: + - JS + - Remix + - Web3 diff --git a/locales/ja/Basics/README.md b/locales/ja/Basics/README.md new file mode 100644 index 000000000..a68059f21 --- /dev/null +++ b/locales/ja/Basics/README.md @@ -0,0 +1,3 @@ +## ロード、コンパイル、デプロイ + +このビギナー向けのチュートリアルでは、Remixのインターフェースやイーサリアムで使用されているコンセプトを紹介します。 diff --git a/locales/ja/Basics/config.yml b/locales/ja/Basics/config.yml new file mode 100644 index 000000000..80bf550a9 --- /dev/null +++ b/locales/ja/Basics/config.yml @@ -0,0 +1,26 @@ +--- +id: 基本 +name: Remixの基本 +summary: Remixの一般的なワークフロー +level: 1 +tags: + - Remix +steps: + - + name: "インターフェースの紹介\n" + path: interface_introduction + - + name: ワークスペースの紹介 + path: ワークスペース + - + name: Loading & Compiling + path: load_and_compile + - + name: Remix VMへのデプロイ + path: deploy_to_the_remixvm + - + name: 関数とのやり取り + path: やり取り + - + name: 公開ネットワークへのデプロイ + path: deploy_injected diff --git a/locales/ja/Basics/deploy_injected/README.md b/locales/ja/Basics/deploy_injected/README.md new file mode 100644 index 000000000..3a37eb62f --- /dev/null +++ b/locales/ja/Basics/deploy_injected/README.md @@ -0,0 +1,21 @@ +1. **MetaMask** のようなブラウザウォレットが無ければ、はじめにダウンロードしてインストールしてください。 + +2. ブラウザにあるMetaMaskアイコンをクリックしてください。 サインインして、 Ephemeryテストネットワークを選択します。 **テストネットワーク** を表示するには、ウォレット設定の更新が必要になります。 他の方法として、RemixのDeploy & RunトランザクションモジュールのENVIRONMENTセクションでEphemeryを選択することもできます。 + +3. 公開テストネットワークでテスト用のETHを取得するのは、煩雑な場合があります。 Ephemeryは、公開テストネットワークで毎月リフレッシュされます。そのため、テスト用のETHを取得するのは簡単になっています。 こちらにEphemeryフォーセットのリンクがまとまっています。 + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/testnet.png) + +もう一つの人気のテストネットとしてSepoliaがあります。こちらは、リフレッシュされません。デプロイしたものが保持されますが、Sepoliaフォーセットの使用には、より困難が伴います。 + +ブラウザウォレットでメインネットや他のETHを使用するネットワークが選択されていないことを確認してください。 Deploy & Runモジュールでは、次のENVIRONMENT選択ボックスで、一般的なチェーンの名前とネットワークIDが表示されます。 以下はSepoliaのケースです。 + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/sepolia.png) + +5. **CONTRACT** 選択ボックスの欄に 2_Owner.sol があることを確認し、 **Deploy** ボタンをクリックして下さい。 + +**CONTRACT** 選択ボックスが空の場合は、**エディタ** 内にあるアクティブファイルで 2_Owner.sol を作成し、 **Solidityコンパイラ** で 2_Owner をコンパイルする必要があります。 + +6. `Deploy` ボタンを押すと、ブラウザウォレットのポップアップがトランザクションの支払を求めてきます。 使用しているチェーンにETHが十分にある場合は、トランザクションを承認してください。 ターミナルの出力を確認してください。 ブロックが検証されると、 **デプロイ済みのインスタンス** が Deploy & Run ボタンに現れます。 + +以上でこのチュートリアルは終了です。 これで、Remix IDEでスマートコントラクトを開き、デプロイし、やり取りする経験を得ることができました。 diff --git a/locales/ja/Basics/deploy_to_the_remixvm/README.md b/locales/ja/Basics/deploy_to_the_remixvm/README.md new file mode 100644 index 000000000..39a6c8d54 --- /dev/null +++ b/locales/ja/Basics/deploy_to_the_remixvm/README.md @@ -0,0 +1,15 @@ +前の章では、コントラクトをコンパイルしました。これは、Solidityコードがイーサリアム仮想マシン(EVM)におけるバイトコードの小さなチャンクに変換されたと言うことが出来ます。 + +次は、テストブロックチェーンにコードを配置しましょう。 + +1. Deploy and Run アイコン ![deploy & run icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_to_the_remixvm/images/run.png "deploy & run icon") をクリックしてください。 + +2. **Environment** プルダウンで **Remix VM** のどれか1つを選択してください。 + +3. Deployボタン(または展開したビューにあるTransactボタン)をクリックしてください。 + +4. コンパイル済みのコントラクトがRemix VMにデプロイされます。これにより、ブロックチェーンのシミュレーションがブラウザ内部のウィンドウで実行されます。 Remix VMは、シンプルで高速なテストチェーンです。 しかし、各トランザクションで承認が不要なため、現実のブロックチェーンとは異なります。 + +5. ターミナルでトランザクションのデプロイメントの詳細をご覧ください + +Remixを使用して、他の公開EVMチェーンへデプロイすることができます。 それには、 Injected Providerで違う **環境** に接続する必要があります。 Injected Providerは、Remixをブラウザウォレット(MetaMaskなど)に接続します。 チュートリアルの最後に公開ネットワークにデプロイします。 その前に、デプロイ済みのコントラクトとやり取りする方法について説明します。 diff --git a/locales/ja/Basics/interacting/README.md b/locales/ja/Basics/interacting/README.md new file mode 100644 index 000000000..feff33981 --- /dev/null +++ b/locales/ja/Basics/interacting/README.md @@ -0,0 +1,19 @@ +## デプロイ済みコントラクトの関数にアクセスする + +1. コントラクトのデプロイに成功すると、Deploy and Run プラグインの下部にボタンが現れます。 キャレットをクリックするとキャレットが下向きになりコントラクトが開きます。 + ![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/instance.png "deployed contract") + +2. このコントラクトには、2つの関数があります。 パラメータを個別に入力するには、changeOwnerの右にあるキャレット(赤枠で示された部分)をクリックしてください。 展開されたビューの各パラメータに、それぞれ入力ボックスがあります。 + +![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/deployed_open2.png "deployed contract") + +このコントラクトが他のコントラクトをインポートしている場合は、インポートされたコントラクトの関数もここに表示されます。 お時間があれば、ERC20コントラクトで多数の関数が表示されるので試してみて下さい。 + +3. 青いボタンの関数は、 **pure** または **view** 関数です。 これは、プロパティを読み込んで値を返すことのみであることを表しています。 言い換えれば、何も保存をしていないため、無料です(ガスを消費しません)。 他の色の関数は、通常オレンジ(Remixテーマによって変化)は、情報を保存するためガスを消費します。 他の色の関数は、トランザクションを作成します。 + +4. 2_Owner.sol は、 **payable** 関数がありません。 payable 関数のボタンの色は赤になります。 payable 関数では、Etherを関数に送金することができます。 payable でETHを送金するには、Deploy & Run モジュールの上部にある **value** フィールドに送金したい金額を入力します。 + +5. Remix VMでは、トランザクションの承認は不要です。 より現実に近いテスト環境やメインネットを使用する場合は、トランザクションの承認が必要になります。 トランザクションの承認では、ガスを消費します。 + +6. 公開ネットワークの選択は、Remixではなく、ブラウザウォレットで行います。 ENVIRONMENTのタイトルの右際にプラグアイコンがあり、chainlist.orgへのリンクになっており、やり取りを行いたいチェーンの仕様を得ることができます。 + ![chainlist](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/chainlist.png "chainlist") diff --git a/locales/ja/Basics/interface_introduction/README.md b/locales/ja/Basics/interface_introduction/README.md new file mode 100644 index 000000000..8dcb0fe57 --- /dev/null +++ b/locales/ja/Basics/interface_introduction/README.md @@ -0,0 +1,15 @@ +## Remixを構成する4つのパネル + +![Remix layout](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/a-layout1c.png "Remix layout") + +- **Side Panel** にプラグインが表示されます。 +- **Main Panel** のタブでコードの編集を行います。 +- **Terminal** では、トランザクションの結果やその他のアクションなどが表示されます。 +- **Icons Panel** では、プラグインの切り替えを行います。 +- パネルを大きくするには、ボーダーでドラックしてください。 + +**Icons Panel** にある **Solidity Compiler** アイコン ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/solidity-icon.png) をクリックしてみてください。 次に、**Deploy & Run** アイコン ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/deploy-run.png) をクリックしてください。 最後に、このアイコン ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/learneth.png) をクリックして **LearnEth** に戻ってください。 + +Remixの **Main Panel** に、 **Home** タブが表示されていることを確認してください。 **Home** タブには、便利なリンクが沢山あります。 **Main Panel** にある **Home** タブまたはアイコンパネルの上部にあるRemixアイコン ![Remix icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/remix-logo.png "Remix icon") をクリックすると行くことができます。 + +- **Plugin Manager** では、すべてのプラグインを確認できます。 Remixの左下部にある、このアイコン ![plugin manager](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/plugin1.png "Plugin Manager icon") をクリックしてください。 diff --git a/locales/ja/Basics/load_and_compile/README.md b/locales/ja/Basics/load_and_compile/README.md new file mode 100644 index 000000000..d4b5dfd3a --- /dev/null +++ b/locales/ja/Basics/load_and_compile/README.md @@ -0,0 +1,20 @@ +File Explorerからエディタにファイルをロードしましょう。 + +1. アイコンパネルで、File Explorerアイコン ![file explorer icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/files1.png "file explorer icon") をクリックします。 + +2. **default_workspace** にいることを確認します。 + +![default workspace](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/default_workspace_open.png) + +3. contractsフォルダを開き、contractsフォルダにある **2_Owner.sol** をクリックします。 クリックすると、 メインパネルのタブにファイルが表示されます。 + +4. アイコンパネルで、 **Solidity Compiler** ![solidity compiler icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/solidity1.png "solidity compiler icon") をクリックします。 サイドパネルにSolidityコンパイラが表示されます。 + +5. コンパイルボタンをクリックします。 + ![compile 2\_owner](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/compile2owner.png "compile 2_Owner") + +6. **CTRL + S** を押すことでもコンパイル可能です。 + +コンパイル中は、スピナーが回転します。 + +**注意:** スピナーは、コンパイラーのロード中も回転します。 **異なるバージョンのSolidity** の選択では、プラグインの上部にある選択ボックスに移動してください。 diff --git a/locales/ja/Basics/workspaces/README.md b/locales/ja/Basics/workspaces/README.md new file mode 100644 index 000000000..8794825e8 --- /dev/null +++ b/locales/ja/Basics/workspaces/README.md @@ -0,0 +1,23 @@ +## ワークスペースを個別のプロジェクトの整理に役立てる + +初期状態のRemixでは、ファイルエクスプローラに **default_workspace** という名前でワークスペースが読み込まれます。 + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/default_workspace.png) + +**default_workspace** のcontractsフォルダに3つのSolidity (.sol)ファイルがあります。 Remixは、様々なテンプレートがあります。 テンプレートをロードすると、ワークスペースに入ります。 ワークスペース間を移動するには、File Explorer上部にある選択ボックスを使います。 + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/select-box.png) + +ワークスペースは、テンプレート用途に限定するものではありません。 リポジトリをRemixにクローンする時に、ワークスペースにファイルを配置することができます。 + +新しいワークスペースを作成してみましょう。 + +1. File Explorerの上部にある、ハンバーガーアイコン(3本の横線).をクリックします。 メニューにあるコマンドとツールに目を通しましょう。 + +2. **+ Create** (最上部)を選択します。 + +3. モーダルが表示されるので、テンプレート中から1つを選んでください。 + +![hamburger](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/workspaces/images/popup.png) + +ポップアップメニューから、リポジトリのクローンができることに気づいたと思います。 Gitリポジトリの管理は、DGitプラグインによって動作します。 ポップアップメニューでは、3種類のワークフローとともにGitHub actionsの作成もできます。 diff --git a/locales/ja/CircomHashChecker/README.md b/locales/ja/CircomHashChecker/README.md new file mode 100644 index 000000000..3acbdb1cf --- /dev/null +++ b/locales/ja/CircomHashChecker/README.md @@ -0,0 +1,13 @@ +Hash Checkerチュートリアル + +このチュートリアルでは、Remix-IDEを使用したHask Checker回路の作成と解説をします。 テンプレートを使用した回路の生成方法、コードの調査、信頼されたセットアップの実行、証明の生成と検証を学びます。 このチュートリアルは、Circumやゼロ知識証明について基本的な知識がある初心者を対象としています。 + +前提条件 + +``` +ゼロ知識証明とCircomの基本的な理解。Remix-IDEの使用に慣れていること。 +``` + +推定所要時間 + +約1~2時間 diff --git a/locales/ja/CircomHashChecker/config.yml b/locales/ja/CircomHashChecker/config.yml new file mode 100644 index 000000000..94b9a4c06 --- /dev/null +++ b/locales/ja/CircomHashChecker/config.yml @@ -0,0 +1,35 @@ +id: circom-hash-checker +name: Hash Checkerチュートリアル +summary: Remix-IDEテンプレートを使用したHash Checker回路の作成と理解をするためのチュートリアルです。信頼されたセットアップ、証明の生成についても含みます。 +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Hash Checker回路の紹介 + path: ステップ1 + - + name: Remix-IDEでHash Checkerテンプレートを生成する + path: ステップ2 + - + name: calculate_hash.circomを理解する + path: ステップ3 + - + name: 回路のコンパイル + path: ステップ4 + - + name: 信頼されたセットアップの実行 + path: ステップ5 + - + name: ウィットネスの計算 + path: ステップ6 + - + name: 証明の生成 + path: ステップ7 + - + name: 信頼されたセットアップの探索(オプション) + path: ステップ8 + - + name: 証明生成スクリプトの探索(オプション) + path: ステップ9 diff --git a/locales/ja/CircomHashChecker/step-1/README.md b/locales/ja/CircomHashChecker/step-1/README.md new file mode 100644 index 000000000..c09eef6f2 --- /dev/null +++ b/locales/ja/CircomHashChecker/step-1/README.md @@ -0,0 +1,8 @@ +このチュートリアルでは、CircomやRemix-IDEを使って、 **Hash Checker** 回路やゼロ知識証明(ZKP)アプリの仕組みを学びます。 Hash Checker回路では、入力自体を明らかにすることなく、特定の値にハッシュされる特定の入力に関する知識を証明することができます。 + +### 学ぶこと + +- Remix-IDEのワークスペースのテンプレートを使用したHash Checker回路の生成方法。 +- ハッシュ化およびハッシュをチェックするCircomコードの理解。 +- Groth 16を使用した信頼されたセットアップの実行。 +- ゼロ知識証明の生成。 diff --git a/locales/ja/CircomHashChecker/step-2/README.md b/locales/ja/CircomHashChecker/step-2/README.md new file mode 100644 index 000000000..98d1263ab --- /dev/null +++ b/locales/ja/CircomHashChecker/step-2/README.md @@ -0,0 +1,37 @@ +Remix-IDEでHash Checkerワークスペースを作る手順は、以下の通りです。 + +### ステップ1: テークスペーステンプレートにアクセスする + +1. **File Explorer** サイドバーで、 **ハンバーガーメニューアイコン** (3つ横線) をクリックします。 + + hamburger-menu + +2. ドロップダウンから **「Create Using Template」** を選択します。 + + create-using-template + +### ステップ2: Hash Checkerテンプレートを見つける + +1. メインパネルで、 **"Circom ZKP"** セクションへスクロールダウンします。 + + create-zkp-section + +2. **「Hash Checker」** アイテムを見つけます。 + +### ステップ3: ワークスペースを作成する + +1. Hash Checkerアイテムの **「Create」** ボタンをクリックします。 + + create-hash-checker + +2. モーダルポップアップで、 **ワークスペース名** (例: `hash-checker-workspace`)を指定します。 + + workspace-name-modal + +3. \*\*「OK」\*\*をクリックしてテンプレートを作成します。 + +### 結果 + +- ワークスペースが必要なファイルとディレクトと共に作成されます。 + + workspace-name-modal diff --git a/locales/ja/CircomHashChecker/step-3/README.md b/locales/ja/CircomHashChecker/step-3/README.md new file mode 100644 index 000000000..cf7d27e49 --- /dev/null +++ b/locales/ja/CircomHashChecker/step-3/README.md @@ -0,0 +1,32 @@ +## `calculate_hash.circom`を理解する + +`circuits`ディレクトリに移動して、`calculate_hash.circom`を開きます。 このファイルには、Hash Checker回路のCircumコードが含まれています。 + +### コードの概要 + +#### PragmaとIncludes: + +- `pragma circom 2.0.0;` は、Circumのバージョンが記述されています。 +- `include "circomlib/circuits/poseidon.circom";`は、Poseidonハッシュ関数を [CircomLib](https://github.com/iden3/circomlib)から取得して含めます。 + +#### `CalculateHash`テンプレート: + +- 入力 `value1`、`value2`、`value3`、`value4`を定義しています。 +- `Poseidon`ハッシュ関数を使い、これらの値のハッシュを計算します。\ +- `out`でハッシュを出力します。 + +#### `HashChecker`テンプレート: + +- 入力は、同じ値に対して`hash`を加えます。 +- `calculateSecret`として`CalculateHash` をインスタンス化します。 +- `calculatedHash`を計算します。 +- `assert(hash == calculatedHash);` 使用して、計算されたハッシュと、提供されたハッシュが一致することを確認します。 + +#### メインコンポーネント: + +- `component main {public [hash]} = HashChecker();` +- `hash`は、`public`の入力であり、値は`private`であることが記述されています。 + +### 目的 + +この回路によって、値そのものを明らかにせずに、特定の`hash`にハッシュされる`value1`、`value2`、`value3`、`value4`について知っていることを証明することができます。 diff --git a/locales/ja/CircomHashChecker/step-4/README.md b/locales/ja/CircomHashChecker/step-4/README.md new file mode 100644 index 000000000..751834b26 --- /dev/null +++ b/locales/ja/CircomHashChecker/step-4/README.md @@ -0,0 +1,32 @@ +## 回路のコンパイル + +### コンパイラバージョンの選択 + +1. サイドバーにある**Circuit Compiler**プラグインに行きます。 +2. ドロップダウンメニューで必要な**コンパイラバージョン**を選びます。 このチュートリアルでは、最新の安定バージョンを選びます。 + +select-compiler-version + +### コンパイラオプションの設定 + +- **Auto Compile:** このオプションを有効にすると、回路の変更を保存した時に、自動的にコンパイルされます。 +- **Hide Warnings:** これを有効にするとコンパイラの警告が通知されなくなります。 +- **Advanced Configuration:** + - クリックすると展開します。 + - **Prime Field**を選びます。 多くの場合において`BN128`で十分です。 + +advanced-configuration + +### 回路のコンパイル + +1. **Compile**ボタンをクリックします。 +2. コンパイルが完了するまで待ちます。 コンパイルに成功するとsuccessバッジが表示されます。 + +compilation-success + +### コンパイルの出力を理解する + +- コンパイルが成功すると、 **Setup and Exports**セクションが現れます。 +- これで、信頼されたセットアップを実行する次のステップに進めます。 + +次のステップでは、信頼されたセットアップを使用して回路をコンパイルします。 diff --git a/locales/ja/CircomHashChecker/step-5/README.md b/locales/ja/CircomHashChecker/step-5/README.md new file mode 100644 index 000000000..9a2e9788d --- /dev/null +++ b/locales/ja/CircomHashChecker/step-5/README.md @@ -0,0 +1,25 @@ +## 信頼されたセットアップの実行 + +1. **Setup and Exportsセクションへのアクセス**: + +- コンパイルに成功すると、プラグインで **Setup and Exports** セクションが利用可能になります。 + +2. **Proving Schemeの選択**: + +- **Proving Scheme** ドロップダウンで **Groth16** を選びます。 + +3. **Power of Tauファイルの選択**: + +- ドロップダウンから適切な **Power of Tau** ファイルを選びます。 わからない場合は、デフォルトのオプションを使用してください。 + +4. **検証鍵とコントラクトのエクスポート** (任意): + +- **Export Verification Key** を有効にすると、検証鍵がファイルエクスプローラに保存されます。 +- **Export Verifier Contract** を有効にすると、オンチェーン検証用のSolidityコントラクトが保存されます。 + +trusted-setup + +5. **信頼されたセットアップの実行**: + +- **Run Setup** ボタンをクリックします。 +- プロセスが完了するのを待ちます。 この処理は、回路の複雑性によって時間ががかかることがあります。 diff --git a/locales/ja/CircomHashChecker/step-6/README.md b/locales/ja/CircomHashChecker/step-6/README.md new file mode 100644 index 000000000..428a26a29 --- /dev/null +++ b/locales/ja/CircomHashChecker/step-6/README.md @@ -0,0 +1,28 @@ +## ウィットネスの計算 + +1. **Compute Witnessセクションへのアクセス**: + - 信頼されたセットアップが終わると、 **Compute Witness** セクションが利用可能になります。 + +2. **入力値**: + - 入力フィールド、`value1`、`value2`、`value3`、`value4`、`hash`が表示されます。 + - それぞれの入力項目に値を入力します。 入力例: + - `value1`: `1234` + - `value2`: `2` + - `value3`: `3` + - `value4`: `4` + +3. **ハッシュの計算**: + + - Poseidonハッシュ関数と互換性のある外部ツールやライブラリを使用して4つのPoseidonハッシュ値を計算します。 + - 上記の値について計算したPoseidonハッシュは、`16382790289988537028417564277589554649233048801038362947503054340165041751802`となります。 + - 計算された`hash`値を`hash`入力フィールドに入力します。 + + compute-witness + +4. **ウィットネスの計算**: + + - **Compute Witness** ボタンをクリックします。 + - プロセスが完了するのを待ちます。 ウィットネスの計算に成功するとsuccessバッチが現れます。 + - 成功すると、`calculate_hash.wtn`がファイルエクスプローラの`.bin`ディレクトリに作成されます。 + + witness-computed diff --git a/locales/ja/CircomHashChecker/step-7/README.md b/locales/ja/CircomHashChecker/step-7/README.md new file mode 100644 index 000000000..d0b5940c7 --- /dev/null +++ b/locales/ja/CircomHashChecker/step-7/README.md @@ -0,0 +1,21 @@ +## 証明の生成 + +1. **Generate Proofセクションへアクセスする**: + - ウィットネスを計算したら、**Generate Proof** を開きます。 + +2. **Proof Generationの設定をする**: + - **Export Verifier Calldata**: このオプションを有効にすると、オンチェーンで証明の検証ができます。 + +3. **証明を生成する**: + + - **Generate Proof** ボタンをクリックします。 + - 証明の生成が完了するまで待ちます。 + + generate-proof + +4. **証明を表示する**: + + - ファイルエクスプローラ内に証明データが表示されます。 + - **おめでとうございます!** Remix-IDEを使用した`Hash Checker`回路のコンパイル、信頼されたセットアップ、ウィットネスの計算、証明の生成に成功しました。 + + generate-proof diff --git a/locales/ja/CircomHashChecker/step-8/README.md b/locales/ja/CircomHashChecker/step-8/README.md new file mode 100644 index 000000000..7cc879657 --- /dev/null +++ b/locales/ja/CircomHashChecker/step-8/README.md @@ -0,0 +1,34 @@ +## `groth16_trusted_setup.ts`について理解する + +`scripts/groth16/groth16_trusted_setup.ts`に移動します。 このスクリプトは、証明の生成に必要な信頼されたセットアップを実行します。 + +### コードの概要 + +#### 回路のコンパイル: + +- `remix.call('circuit-compiler', 'generateR1cs', ...)`を使用して、回路から`R1CS` (Rank-1 Constraint System)を生成します。 + +#### 信頼されたセットアップのステップ + +- `snarkjs.zKey.newZKey`: 証明鍵 (`zkey_0`) の初期化 +- `snarkjs.zKey.contribute`: 証明鍵(`zkey_1`)にコントリビューションを追加 +- `snarkjs.zKey.beacon`: 証明鍵(`zkey_final`)の確定 + +#### 検証: + +- `snarkjs.zKey.verifyFromR1cs`: `R1CS`と初期パラメータに対して証明鍵を検証します。 + +#### 鍵のエクスポート: + +- 検証鍵を`scripts/groth16/zk/keys/verification_key.json`にエクスポートします。 +- 最終証明鍵をエクスポートします(`scripts/groth16/zk/keys/zkey_final.txt`)。 + +### 目的 + +- `Groth16`証明システムに必要な信頼されたセットアップの実行。 +- 証明の生成と検証に必要な鍵の生成。 + +### スクリプトの実行 + +- エディタにあるPlayボタンをクリック、またはファイルで右クリックして「Run」を選択します。 +- スクリプトが完了し、 ターミナルに`"setup done."`というログが出力されるまで待ちます。 diff --git a/locales/ja/CircomHashChecker/step-9/README.md b/locales/ja/CircomHashChecker/step-9/README.md new file mode 100644 index 000000000..34450f105 --- /dev/null +++ b/locales/ja/CircomHashChecker/step-9/README.md @@ -0,0 +1,37 @@ +## `groth16_zkproof.ts`を理解する + +`scripts/groth16/groth16_zkproof.ts`に移動します。 このスクリプトは、ゼロ知識証明を生成し、その検証の準備を行います。 + +### コードの概要 + +#### ファイルのロード: + +- 回路によって生成されたR1CSとWASMファイルを読み込みます。 +- 最終証明鍵(`zkey_final`)と検証鍵(`vKey`)をロードします。 + +#### 入力の定義: + +- プライベート値の設定 (`value1`, `value2`, `value3`, `value4`)。 +- [CircomLib](https://github.com/iden3/circomlib)のPoseidonを使用した`hash`の計算。 + +#### ウィットネスの計算と証明の生成: + +- ウィットネスの計算(`wtns`)。 +- `R1CS`に対してウィットネスを確認する。 +- `Groth16`使用して証明を生成する。 +- 証明の検証 + +#### 検証コントラクトと入力のエクスポート + +- Solidity検証コントラクトを生成する。 +- 証明の入力を`input.json`にエクスポートする。 + +### 目的 + +- 証明者が知っている値を特定のハッシュにハッシュするゼロ知識証明を生成。 +- オンチェーン検証のための検証コントラクトと入力の準備。 + +### スクリプトの実行 + +- エディタにあるPlayボタンをクリック、またはファイルで右クリックして「Run」を選択します。 +- スクリプトが完了し、 ターミナルに`"zk proof validity"`というログが出力されるまで待ちます。 diff --git a/locales/ja/CircomIntro/README.md b/locales/ja/CircomIntro/README.md new file mode 100644 index 000000000..155f85b9b --- /dev/null +++ b/locales/ja/CircomIntro/README.md @@ -0,0 +1,21 @@ +Circomの紹介 + +Circomについての紹介します。 Circomでの演算回路の作成、コンパイル、テストの方法を学びます。 Remix-IDEを使って、これらの方法を試します。 + +チュートリアルの概要 + +``` +ステップ1: 紹介 +ステップ2: Remix-IDEのセットアップとCircuit-Compilerプラグインのインストール +ステップ3: はじめてのCircom回路の作成 +ステップ4: プラグインを使った回路のコンパイル +ステップ5: 信頼されたセットアップの実行 +ステップ6: ウィットネスの計算 +ステップ7: 証明の生成 +``` + +前提条件: + +``` +暗号とゼロ知識証明の基本的な知識があると良いですが、必須ではありません。 +``` diff --git a/locales/ja/CircomIntro/config.yml b/locales/ja/CircomIntro/config.yml new file mode 100644 index 000000000..d8aecd2db --- /dev/null +++ b/locales/ja/CircomIntro/config.yml @@ -0,0 +1,29 @@ +id: circomの紹介 +name: Circomの紹介 +summary: Circomを使った演算回路の作成を紹介します。 +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: はじめに + path: ステップ1 + - + name: Circuit-Compilerのインストール + path: ステップ2 + - + name: はじめてのCircom回路の作成 + path: ステップ3 + - + name: プラグインを使った回路のコンパイル + path: ステップ4 + - + name: 信頼されたセットアップの実行 + path: ステップ5 + - + name: ウィットネスの計算 + path: ステップ6 + - + name: 証明の生成 + path: ステップ7 diff --git a/locales/ja/CircomIntro/step-1/README.md b/locales/ja/CircomIntro/step-1/README.md new file mode 100644 index 000000000..6cc88e5d1 --- /dev/null +++ b/locales/ja/CircomIntro/step-1/README.md @@ -0,0 +1,13 @@ +Remixを使ったCircomの初心者向けのチュートリアルへようこそ。 このチュートリアルでは、Circomの基本である演算回路の作成に使うドメイン固有言語を学びます。 + +**Circomとは** + +Circomとは、演算回路を記述するために設計されて言語で、ゼロ知識証明、特にzk-SNARKsに使うことができます。 デベロッパーは、複雑な演算回路を定義することで、特定のデータに関する知識を明らかにすることなく証明することができます。 + +**CircomでRemix-IDEを使用する理由** + +- **使いやすさ:** Remix-IDEは、ユーザーフレンドリーなインターフェースを備えており、開発プロセスをシンプルにすることができます。 +- **統合されたツール:** `circuit-compiler`のようなプラグインを使用して、同じ環境内でCircomコードをコンパイル、信頼されたセットアップの実行、ウィットネスの計算、証明の作成が可能です。 +- **インストール不要:** WebベースのIDEなので、ローカル開発環境をセットアップしなくともコーディングを即座に開始できます。 + +次のステップでは、Remix-IDEでCircom開発の設定を行い、最初の回路の作成を手助けします。 diff --git a/locales/ja/CircomIntro/step-2/README.md b/locales/ja/CircomIntro/step-2/README.md new file mode 100644 index 000000000..720695518 --- /dev/null +++ b/locales/ja/CircomIntro/step-2/README.md @@ -0,0 +1,25 @@ +このステップでは、`Circom ZKP compiler` プラグインを有効化してCircom開発の設定を行います。 + +## Circomゼロ知識証明コンパイラの有効化 + +1. 画面左にあるアイコンパネルの下部にある **Plugin Manager** (プラグのアイコン) をクリックします。 + 2. 検索バーで、 **Circom** と入力します。 +2. リストの中から **Circuit Compiler** プラグインを見つけ、 **Activate** ボタンをクリックします。 +3. サイドバーにプラグインが表示されます。 + +install-plugin + +## Circomコンパイラのインターフェース + +- **Compiler バージョンドロップダウン:** 使いたいCircomコンパイラのバージョンを選択します。 +- **Auto Compile チェックボックス:** 有効にすると変更時に回路が自動コンパイルされます。 +- **Hide Warnings チェックボックス:** 有効にすると警告が通知されなくなります。 +- **Advanced Configuration:** クリックすると展開されPrimeフィールを選択できます(例: BN128、BLS12381)。 + +compiler-interface + +プラグインをインストールしたら、Remix-IDEでCircomコードを記述する準備は完了です。 + +**注意:** Remix-IDEはWebベースのツールなので、インターネット接続が安定していることを確認してください。 + +次のステップでは、最初のCircom回路を作成します。 diff --git a/locales/ja/CircomIntro/step-3/README.md b/locales/ja/CircomIntro/step-3/README.md new file mode 100644 index 000000000..bc003c48e --- /dev/null +++ b/locales/ja/CircomIntro/step-3/README.md @@ -0,0 +1,38 @@ +シンプルなCircom回路を作成してみましょう。 + +## 新規Circomファイルの作成 + +1. サイドバーの左の**ファイルエクスプローラ**で、 **Create New File** アイコンをクリックします。 +2. `multiplier.circom`というファイル名にして、**Enter** キーを押します。 + +create-new-file + +## 回路の記述 + +`multiplier.circom` を開いて、次のコードを加えてください。 + +```circom +pragma circom 2.0.0; + +template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; +} + +component main = Multiplier(); +``` + +## 説明: + +- template `Multiplier()`: Multiplierという新規の回路のテンプレートを定義しています。 +- `signal input a;` および `signal input b;`: 入力シグナルである a と b を宣言しています。 +- `signal output c;`: 出力シグナルである c を宣言しています。 +- `c <== a * b;`: c が a と b の積であることを制限しています。 +- `component main = Multiplier();`: mainとしてMultiplier回路をインスタンス化しています。これには、コンパイラが必要になります。 + +### 注意: + +シグナルは、暗号回路内の値で、回路の式と制約によって厳密に決定されます。 シグナルを回路によって定義される特定の数学的なルールに従わなければならない値として考えてください。一度設定されると、任意に変更することはできません。 通常のプログラミングでは、必要に応じて値を柔軟に更新したり、再割り当てすることができますが、シグナルは自由に変更できません。 diff --git a/locales/ja/CircomIntro/step-4/README.md b/locales/ja/CircomIntro/step-4/README.md new file mode 100644 index 000000000..b71b6df0c --- /dev/null +++ b/locales/ja/CircomIntro/step-4/README.md @@ -0,0 +1,34 @@ +`multiplier.circom`回路の準備ができたら、Circuit Compilerプラグインを使用してコンパイルをしましょう。 + +## コンパイラバージョンの選択 + +必要な**コンパイラバージョン**をドロップダウンから選択します。 このチュートリアルでは、最新の安定バージョンを選択します。 + +select-compiler-version + +## コンパイルオプションの設定 + +- **Auto Compile:** このオプションを有効にすると、回路の変更を保存した時に、自動的にコンパイルされます。 +- **Hide Warnings:** これを有効にするとコンパイラの警告が通知されなくなります。 +- **Advanced Configuration:** + - クリックすると展開します。 + - **Prime Field**を選びます。 多くの場合において`BN128`で十分です。 + +advanced-configuration + +## 回路のコンパイル + +1. **Compile**ボタンをクリックします。 +2. コンパイラが回路を処理します。 +3. 成功すると、コンパイルに成功したことがメッセージに表示されます。 + +compilation-success + +**注意:** 何かエラーがあると、コンソールに表示されます。 コードにタイプミスやエラーがないか確認してください。 + +## コンパイルの出力を理解する + +- コンパイルが成功すると、 **Setup and Exports**セクションが現れます。 +- これで、信頼されたセットアップを実行する次のステップに進めます。 + +次のステップでは、信頼されたセットアップを使用して回路をコンパイルします。 diff --git a/locales/ja/CircomIntro/step-5/README.md b/locales/ja/CircomIntro/step-5/README.md new file mode 100644 index 000000000..f74ece238 --- /dev/null +++ b/locales/ja/CircomIntro/step-5/README.md @@ -0,0 +1,26 @@ +回路のコンパイル後、信頼されたセットアップを実行して証明と検証鍵を生成する必要があります。 + +## 信頼されたセットアップの理解 + +- **信頼されたセットアップ:** zk-SNARKsの処理に必要となる必須パラメータを生成して証明の生成と検証をします。 +- **Groth16** や **Plonk** など、さまざまなプロトコルから選ぶことができます。 + +## 信頼されたセットアップの実行 + +1. **Setup and Exports** セクションで **Proving Scheme** を選択: + - **Groth16** または **Plonk** を選びます。 このチェートリアルでは、 **Groth16** を使用します。 + +2. ドロップダウンから適切な **Power of Tau** ファイルを選びます。 このファイルは、信頼されたセットアップで必要になります。 + - わからない場合は、デフォルトのオプションを選択してください。 + +3. **Setup** ボタンをクリックして信頼されたセットアップのプロセスを開始します。 + +4. **Export Verification Key** を有効にすると、検証パラメータを取得できます。 + +5. オンチェーンで証明を検証するならば、 **Export Verification Contract** を有効にします。 + +trusted-setup + +**注意:** 信頼されたセットアップでは、回路が複雑になるほど、ある程度時間がかかります。 + +次のステップでは、回路で使うウィットネスの計算をします。 diff --git a/locales/ja/CircomIntro/step-6/README.md b/locales/ja/CircomIntro/step-6/README.md new file mode 100644 index 000000000..2ffa20399 --- /dev/null +++ b/locales/ja/CircomIntro/step-6/README.md @@ -0,0 +1,27 @@ +信頼されたセットアップが完了すると、特定の入力に基づいた回路のウィットネスの計算ができます。 + +## ウィットネスとは + +- **ウィットネス**は、値のセットで回路の制約の全てを満たします。 ウィットネスは、中間の数値の全てを含み、結果は回路のルールを満たします。 ウィットネスは、ゼロ知識証明で使用され、問題に対して実際に解を示さなくても有効な解を知っていることを明らかにします。 これにより、あなたの特定の数値と計算を秘密にしながら、他者は、すべてにおいて正しく行っていることを確認できます。 +- 証明を生成するのに必要不可欠なのがウィットネスです。 + +## 入力値 + +1. **Compute Witness** セクションでは、回路の入力に基づいて動的に生成された入力フィールドが表示されます。 +2. `a`と`b`の値を入力します。 入力例: + - `a = 3` + - `b = 4` + +compute-witness + +## ウィットネスの計算 + +1. 入力をしたら、**Compute Witness** ボタンをクリックします。 +2. プラグインは、入力に基づいてウィットネスを計算します。 +3. 成功すると、`multiplier.wtn`がファイルエクスプローラの`.bin`ディレクトリに作成されます。 + +witness-computed + +**注意:** エラーがある場合は、入力が有効もしくは回路の制約を満たしているかを確認してください。 + +次のステップでは、計算されたウィットネスを使用して証明を生成します。 diff --git a/locales/ja/CircomIntro/step-7/README.md b/locales/ja/CircomIntro/step-7/README.md new file mode 100644 index 000000000..ce2049364 --- /dev/null +++ b/locales/ja/CircomIntro/step-7/README.md @@ -0,0 +1,31 @@ +計算されたウィットネスで、最後のステップである証明の生成します。これにより、第三者が検証できるようになります。 + +## 証明の生成 + +1. **Generate Proof** セクションに、**Export Verifier Calldata** というオプションがあります。 + - オンチェーンでの検証を想定しているならば、**Export Verifier Calldata** チェックボックスにチェックしてください。 +2. **Generate Proof** ボタンをクリックします。 + +generate-proof + +## 出力の理解 + +- 証明の生成後、プラグインは、証明データを表示します。 +- **Export Verifier Calldata**にチェックをしていると、オンチェーン検証で必要になるcalldataも提供されます。 + +proof-generated + +## 次のステップ + +- **検証:** 検証鍵または事前にエクスポートしたコントラクトを使い検証することができます。 +- **オンチェーン検証:** スマートコントラクトに詳しければ、検証コントラクトをデプロイし、calldataを使用することでオンチェーン検証が実行可能です。 + +**おめでとうございます!** Remix-IDEを使用したCircom回路のコンパイル、信頼されたセットアップ、ウィットネスの計算、証明の生成に成功しました。 + +## 関連資料 + +- [Circomドキュメント](https://docs.circom.io/) +- [Remix-IDE ドキュメント](https://remix-ide.readthedocs.io/) +- [ゼロ知識証明の解説](https://zkproof.org/) + +より複雑な回路で実験することで、CircomとRemix-IDEの可能性を探求してみてください。 diff --git a/locales/ja/DeployWithLibraries/1_Writing_a_Library/step1.md b/locales/ja/DeployWithLibraries/1_Writing_a_Library/step1.md new file mode 100644 index 000000000..1ad984835 --- /dev/null +++ b/locales/ja/DeployWithLibraries/1_Writing_a_Library/step1.md @@ -0,0 +1,17 @@ +A libraries looks like a **contract** but use the keyword `library` + +A library typically is a collection of useful functions sitting out there on the blockchain that any contract can use. Because the library is already deployed, it saves the deployment costs of the many contracts that use it. + +In the following contract: + +- Make a library with the name `LibraryForTest`. + +It is possible to put a library in same file with another contract. So put the library below the contract. + +This library should have a method called `getFromLib` method which returns `3`. + +- Update the `get` method in the `test` contract to use the `LibraryForTest` library. The function `get` should return the value it receives from `getFromLib`. + +--------- + +You can find more info about libraries in this section of the Solidity Docs. diff --git a/locales/ja/DeployWithLibraries/2_Generate_Metadata/step2.md b/locales/ja/DeployWithLibraries/2_Generate_Metadata/step2.md new file mode 100644 index 000000000..218c86ff9 --- /dev/null +++ b/locales/ja/DeployWithLibraries/2_Generate_Metadata/step2.md @@ -0,0 +1,38 @@ +## Deploying Library + +The **library** from the previous chapter was in the same file as the **contract**. However, they won't be deployed together and will have different addresses. + +In order to use a library, the calling contract must have the library's **address**. + +But the library's address is not directly specified in the solidity code. The calling contract's compiled bytecode contains a **placeholder** where library's **addresses** will go. + +At deployment of the **calling contract**, Remix will look in the contract's **metadata** for the library's address and will update the placeholder with the address. + +So before deploying a contract that calls a library, you need to generate the contract's metadata (AKA its **build artifact**) and then you need to input the library's address into the metadata file. + +A contract's metadata is generated at **compile time**. + +Let's setup Remix to generate the **metadata file**. + +- Go to the settings module by clicking on the settings ![settings](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/settings.png "Settings") icon in the icon panel. + +![settings module](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_settings.png "Settings Module") + +- And check the first option `Generate contract metadata`. + +# Compile and generate metadata (JSON) file. + +1. Open the Solidity Compiler ![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +2. Compile `2_contractSimpleLibrary.sol`. + +3. Switch to the File Explorer ![File Explorer](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_file_explorer.png "File Explorer") + +4. Navigate to the newly create JSON files. + - It should be in the folder: + +**browser/.learneth/DeployWithLibraries/2_Generate_Metadata/artifacts/** + +5. Select the newly created JSON file created from the contract. It has the **same name** as the contract `sample` but with the extension **json**: `sample.json` (don't select the library's metadata `contractSimpleLibrary.json`). + +In the next step we'll make some adjustments to the metadata file. diff --git a/locales/ja/DeployWithLibraries/3_Edit_Metadata/step3.md b/locales/ja/DeployWithLibraries/3_Edit_Metadata/step3.md new file mode 100644 index 000000000..1555d645d --- /dev/null +++ b/locales/ja/DeployWithLibraries/3_Edit_Metadata/step3.md @@ -0,0 +1,12 @@ +The `Deploy` property in `sampleContract.json` contains everything you need for telling Remix IDE the address of the library for a specific network. + +- `
` contains the address of the library that is already deployed. You have to specify this address for each network. +- `autoDeployLib` is a boolean and tells Remix IDE if it should autodeploy the library before deploying the contract. + +Basically if `autoDeployLib` is **true**, the `
` will not be used and Remix will automatically deploy the library before deploying the contract. + +For the purpose of this demo - we are mimicking a situation where the library has already been deployed because this is a more common situation. + +So set `autoDeploy` to **false**, for the `VM:-` entry. + +Move to next Step. diff --git a/locales/ja/DeployWithLibraries/4_Linking_and_Deploying/step4.md b/locales/ja/DeployWithLibraries/4_Linking_and_Deploying/step4.md new file mode 100644 index 000000000..ad5f52e2d --- /dev/null +++ b/locales/ja/DeployWithLibraries/4_Linking_and_Deploying/step4.md @@ -0,0 +1,25 @@ +Switch to the `Deploy & Run` module +![Run transaction](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/remix_runtransaction.png "Run Transaction") + +- Select the Remix VM Environment and select the `sampleContract` contract in the list of compiled contracts. + +- Click on `Deploy` + +The terminal should output something like `creation of sample errored:
is not a valid address. Please check the provided address is valid.` +That is expected: **We have set `autoDeployLib` to false, so Remix expects to have an address and not just `
`** + +So we need deploy the library to get its address. + +- Select the library `aLib` in the list of compiled contract and hit `deploy` + + ![Choose aLib](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/contract_alib.png "Choose aLib") + +- Click the clipboard icon to copy the address of the library. + + ![Copy lib1](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/alib_copy.png "Copy") + +- Paste it into the **contract sample's** metadata JSON. + +- Reselect the `sampleContract` contract in the `Run transaction` module and hit deploy. + +- Deploy should now be successful. diff --git a/locales/ja/DeployWithLibraries/5_Under_The_Hood/step5.md b/locales/ja/DeployWithLibraries/5_Under_The_Hood/step5.md new file mode 100644 index 000000000..860b48b24 --- /dev/null +++ b/locales/ja/DeployWithLibraries/5_Under_The_Hood/step5.md @@ -0,0 +1,30 @@ +Switch to the `Solidity compiler` module +![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +- Select the `sampleContract` contract in the list of compiled contracts. +- click on `ByteCode`, it should copy the following to the clipboard: + +``` +{ + "linkReferences": { + "browser/contractSimpleLibrary.sol": { + "lib1": [ + { + "length": 20, + "start": 115 + } + ] + } + }, + "object": "608060405234801561001057600080fd5b5060f68061001f6000396000f3fe6080604052600436106039576000357c0100000000000000000000000000000000000000000000000000000000900480636d4ce63c14603e575b600080fd5b348015604957600080fd5b5060506052565b005b73__$d42d70ba92b626965f4c69b39148e37a33$__63fea24e5f6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801560b157600080fd5b505af415801560c4573d6000803e3d6000fd5b5050505056fea165627a7a7230582068c9a3a9a5cbfd26cfdab2534abfc926912d9b89eaa14e36c8248b7e7eb0ab090029", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xF6 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x39 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x3E JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x50 PUSH1 0x52 JUMP JUMPDEST STOP JUMPDEST PUSH20 0x0 PUSH4 0xFEA24E5F PUSH1 0x40 MLOAD DUP2 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH1 0xB1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS DELEGATECALL ISZERO DUP1 ISZERO PUSH1 0xC4 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 PUSH9 0xC9A3A9A5CBFD26CFDA 0xb2 MSTORE8 0x4a 0xbf 0xc9 0x26 SWAP2 0x2d SWAP12 DUP10 0xea LOG1 0x4e CALLDATASIZE 0xc8 0x24 DUP12 PUSH31 0x7EB0AB09002900000000000000000000000000000000000000000000000000 ", + "sourceMap": "63:85:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63:85:0;;;;;;;" +} +``` + +This is basically what the compiler is returning: + +- `linkReferences` describes what are the libraries used by the contract. +- `object` is the compiled contract (bytecode). This is what gets deployed and saved onto the blockchain. In this example, the value `__$d42d70ba92b626965f4c69b39148e37a33$__` inside the bytecode is just a placeholder for the library address. In your case, the placeholder will be between `__$` and `$__`. + +The metadata JSON from Remix IDE tells Remix to replace the placeholder with the given address. diff --git a/locales/ja/DeployWithLibraries/README.md b/locales/ja/DeployWithLibraries/README.md new file mode 100644 index 000000000..fb31b1264 --- /dev/null +++ b/locales/ja/DeployWithLibraries/README.md @@ -0,0 +1,3 @@ +**Libraries** are deployed contracts that do not store state and are used by other contracts to decrease their size and thus their deployment costs. + +Learn to work with **Libraries** in Remix - you won't need to whisper. diff --git a/locales/ja/DeployWithLibraries/config.yml b/locales/ja/DeployWithLibraries/config.yml new file mode 100644 index 000000000..0816e2346 --- /dev/null +++ b/locales/ja/DeployWithLibraries/config.yml @@ -0,0 +1,8 @@ +--- +id: deploylibraries +name: Deploy with Libraries +summary: Write, Deploy and link a Library to a Contract +level: 3 +tags: + - Remix + - Solidity diff --git a/locales/ja/ERC20TokenCourse/README.md b/locales/ja/ERC20TokenCourse/README.md new file mode 100644 index 000000000..25a6ccf95 --- /dev/null +++ b/locales/ja/ERC20TokenCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Token Course + +Learn to understand and create ERC20 tokens. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ja/ERC20TokenCourse/config.yml b/locales/ja/ERC20TokenCourse/config.yml new file mode 100644 index 000000000..8c12a5213 --- /dev/null +++ b/locales/ja/ERC20TokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: tokenCourse +name: Solidity ERC20 Token Course +summary: Learn how to create your own ERC20 tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - ERC20 +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc20-interface + - + name: 3. Token Creation + path: erc20-token-creation + - + name: 4. Interaction + path: erc20-interaction + - + name: 5. Testnet Deployment + path: erc20-testnet-deployment + - + name: 6. Extensions + path: erc20-extensions diff --git a/locales/ja/ERC20TokenCourse/erc20-extensions/erc20extensions.md b/locales/ja/ERC20TokenCourse/erc20-extensions/erc20extensions.md new file mode 100644 index 000000000..b3649fbba --- /dev/null +++ b/locales/ja/ERC20TokenCourse/erc20-extensions/erc20extensions.md @@ -0,0 +1,33 @@ +The ERC20 standard only describes the required and optional functionality that your contract needs, but you can add additional functionality. + +In this section, we added the functionality to burn and mint tokens, as well as the ability to pause the contract, by using OpenZeppelin extensions. + +Of course, you can write your own ERC20 token contract implementation or extensions and import them into your contract. But OpenZeppelin contracts have been audited by security experts and are a great way to add desired functionality. + +### Mintable + +The mint function allows the creator of the contract to mint (create) additional tokens after the contract has been deployed (line 22). As input parameters, the function needs the address that the tokens will be minted to, and the amount of tokens that should be minted. + +We don't have to import `mint()` from another contract since the mint function is already part of the ERC20 contract implementation of OpenZeppelin. We import `Ownable` (line 7) which is a contract module that provides a basic access control mechanism that allows an owner to have exclusive access to specific functions. In this contract, we add the inherited `onlyOwner` modifier to the `mint` function (line 22) and restrict access to this function to the "owner". + +The contract will inherit additional functions like owner(), transferOwnership() and renounceOwnership() to manage access, from the Ownable contract. + +### Burnable + +By importing the "ERC20Burnable" (line 5) and inheriting its functions (line 9) our contract allows token holders to destroy their tokens as well as the tokens in their allowance. +For more information, have a look at the ERC20Burnable contract. + +### Pausable + +With the "Pausable" contract module (line 6 and 9) the owner is able to pause (line 14) and unpause (line 18) the contract. In the pause state, tokens can't be transferred, which can be helpful in emergency scenarios. +For more information, have a look at the Pausable contract. + +Have a look at the OpenZeppelins Contract Wizard, which allows you to easily add additional functionality. + +If you successfully completed this course, try the Learneth NFT Course as the next step in your journey. + +## ⭐️ Assignment + +1. Try to mint tokens to an account after deployment. Call `totalSupply()` and `balanceOf()` to confirm the correct execution. +2. Burn tokens and then call `totalSupply()` and `balanceOf()` to confirm the correct execution. +3. Test the pause function by pausing the contract using the owner account and trying to make a transfer with a second account. The transaction should not be able to be executed and will throw the exception: "Pausable: paused". diff --git a/locales/ja/ERC20TokenCourse/erc20-interaction/er20interaction.md b/locales/ja/ERC20TokenCourse/erc20-interaction/er20interaction.md new file mode 100644 index 000000000..5c082b248 --- /dev/null +++ b/locales/ja/ERC20TokenCourse/erc20-interaction/er20interaction.md @@ -0,0 +1,87 @@ +In this section, we will deploy a contract in our browser and test its functionality. + +### 1. Deploy the contract + +**1.1** Compile your EduCoin contract in the "Solidity compiler" module of the Remix IDE. + +**1.2** In the "Deploy & run transactions" module, select your contract "EduCoin" in the contract input field and click on the "Deploy" button. Always make sure to select the correct contract in the contract selector input field. + +**GIF** Compile and deploy: Compile and deploy contract + +### 2. Test the functions + +Expand the token contract functions in the IDE. + +#### 2.1 Decimals + +Click on the "decimals" button to call the decimals() function. +It should return "18". + +#### 2.2 Name + +Click on the "name" button to call the name() function. +It should return "EduCoin". + +#### 2.3 Symbol + +Click on the "symbol" button to call the symbol() function. +It should return "EDC". + +#### 2.4 Total supply + +Click on the "totalSupply" button to call the totalSupply() function. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test decimals, name, symbol, and totalSupply functions: Test transfer function + +#### 2.5 Balance of + +**2.5.1** Go to the "ACCOUNT" section in the sidebar and copy the displayed address by using the copy icon next to it. + +**2.5.2** Paste the address in the input field next to the "balanceOf" function button and click on the button. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test balanceOf function: Test transfer function + +#### 2.6 Transfer + +We will transfer EduCoin from one account to a second account. + +**2.6.1** Go to the "ACCOUNT" section in the sidebar and click on the displayed address. This should open a dropdown. Select the second address displayed and copy its address (account 2). + +**2.6.2** Open the dropdown and select the first account again (account 1), because this is the account that we want to use to make the transfer. + +**2.6.3** Paste the address in the input field next to the "transfer" function button, input the number 500000000000000000000, and click on the button. + +**2.6.4** If you check the balances for account 1 and account 2, they should both return the amount 500000000000000000000. + +**GIF** Test transfer function: Test transfer function + +#### 2.7 Approve + +We will now allow account 1 to spend tokens on behalf of account 2. + +**2.7.1** Go to the "Account" section, copy the address of account 1, then set it to account 2 again. + +**2.7.2** In the approve function, enter the address of account 1 as the input for spender and set the amount to 250000000000000000000. + +**GIF** Test approve function: Test approve function + +#### 2.8 Allowance + +Next to the "allowance" button enter the address of account 2 as the owner and account 1 as the spender; click on the button. +It should return 1000000000000000000000. + +**GIF** Test allowance function: Test allowance function + +#### 2.9 TransferFrom + +Now account 1 will transfer 250000000000000000000 tokens from account 2 to its own account. + +**2.9.1** Select account 1 in the "ACCOUNT" section. + +**2.9.2** Next to the "transferFrom" button enter the address of account 2 as the sender and account 1 as the recipient, enter 250000000000000000000 as the amount and click on the button. + +**2.9.3** Check the balances of accounts 2 and 1, they should return 250000000000000000000 and 750000000000000000000. + +**GIF** Test transferFrom function: Test transferFrom function diff --git a/locales/ja/ERC20TokenCourse/erc20-interface/erc20interface.md b/locales/ja/ERC20TokenCourse/erc20-interface/erc20interface.md new file mode 100644 index 000000000..5c4e8137c --- /dev/null +++ b/locales/ja/ERC20TokenCourse/erc20-interface/erc20interface.md @@ -0,0 +1,76 @@ +ERC20 (Ethereum Request for Comments 20) is a standard for token contracts that manages fungible tokens on the Ethereum blockchain. + +Fungible tokens are all equal to each other and have the same value, behavior, and rights. Fungible tokens are often used as a medium of exchange, like the currencies ETH or BTC. However, they can also have other use cases like voting rights or reputation. + +If you want to know more about the ERC20 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +To get an overview of the required functionality of an ERC20 token contract, we will look at an interface that interacts with an ERC20 contract. +This interface (line 9) is part of the open-source contract library provided by OpenZeppelin. + +## ERC20 Functions + +Contracts compliant with the ERC20 standard must implement the following six functions: + +### totalSupply + +The function `totalSupply` (line 13) returns the total amount of tokens available. + +### balanceOf + +The function `balanceOf` (line 18) returns the amount of tokens owned by the account with the address `account`. + +### transfer + +The function `transfer` (line 27) transfers `amount` of tokens to the address `recipient`. +This function **must** emit (produce) a `Transfer` event (see below) and **should** throw an exception when the sender doesn't have enough tokens to make the transfer. + +### approve + +The function `approve` (line 52) creates an allowance for the address `spender` to transfer `amount` of tokens on behalf of the account calling the function. + +### allowance + +The function `allowance` (line 36) returns the amount of tokens that the address `spender` is allowed to spend on behalf of the account with the address `owner`. + +### transferFrom + +The function `transferFrom` (line 63) transfers `amount` of tokens on behalf of the address `sender` to the address `recipient`. +This function **must** emit a `Transfer` event. + +## ERC20 Events + +ERC20 contracts must also emit two events: + +### Transfer + +The `Transfer` (line 71) event must be emitted when `value` amount of tokens are transferred from the account with the address `indexed from` to `indexed to`. The parameters `from` and `to` are `indexed` allowing us to search for these events using the indexed parameters as filters. + +### Approval + +The `Approval` (line 77) event must be emitted when the account `indexed owner` approves the account `indexed spender` to transfer `value` amount of tokens on its behalf. + +## ERC20 Optional functions + +In addition to the mandatory functions and events, there are also three optional functions specified in the ERC20 standard that are not implemented in this interface: + +### name + +`function name() external view returns (string);` + +Returns the name of the token. + +### symbol + +`function symbol() external view returns (string);` + +Returns the symbol of the token. + +### decimals + +`function decimals() external view returns (uint8);` + +Returns the number of decimal places the token uses. + +You may want to use decimals to make your token divisible into arbitrary amounts like 1.5 ETH when displayed. The EVM (Ethereum virtual machine) only supports integer numbers. That's why the ERC20 standard suggests to implement the decimal functionality that specifies how many decimal places a token has. 18 decimal places is the industry standard. diff --git a/locales/ja/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md b/locales/ja/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md new file mode 100644 index 000000000..94b513922 --- /dev/null +++ b/locales/ja/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md @@ -0,0 +1,41 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to a testnet of the Ethereum blockchain. This testnet behaves very similarly to the real blockchain (mainnet), but does not require real ETH to pay for transactions. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token + +In order to make transactions on the testnet we need Ethereum testnet tokens, which you can receive from something called a _faucet_. + +**2.1** Switch your Metamask network by clicking on the "Ethereum Mainnetwork" drop down and selecting "Ropsten Test Network". If you don’t see any test networks, click on the "Show/hide" link and enable "Show test networks" in the settings. + +**2.2** Go to https://faucet.ropsten.be/, enter the address of your account, and claim testnet ETH. You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Deployment + +Make sure the EduCoin contract is compiled. + +**3.1.** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It will ask you to connect your account which you should confirm. + +**3.2** Deploy the EduCoin contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. Copy the contract address. + +**3.4** In Metamask, click on assets, then click on the "Import tokens" link, and paste the address of your contract in the input field. + +You should now see a balance of 1000 EDC in your wallet. + +### 4. Make a transaction + +**4.1** Click on the identicon (visual representation of your address) in the Metamask wallet and create a second account (Account 2). + +**4.2** Copy the address of Account 2. + +**4.3** Switch to the first account (Account 1) and send 250 EDC to Account 2. Check the balances of Account 1 and Account 2. You might need to add the token address again for Account 2 to import the tokens and you will need testeth if you want to make a transaction with this account. + +You can also see your account balances if you look at the contract in Remix and call the `balanceOf` function using the addresses of Account 1 and Account 2. diff --git a/locales/ja/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md b/locales/ja/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md new file mode 100644 index 000000000..49b71abdd --- /dev/null +++ b/locales/ja/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md @@ -0,0 +1,18 @@ +A token standard tells us what functionality the contract needs to comply with it. How this functionality is implemented is up to the developers. In this contract, we will use an ERC20 token contract implementation from OpenZeppelin (line 4). In this case, we import version 4.4.0 of the OpenZeppelin contracts. + +Have a look at their nicely documented ERC20 contract to have a better understanding of how an implementation might look. Apart from the functionality specified in the ERC20 standard, this contract provides additional functionality. + +We will create our own contract called MyToken (line 6), which inherits the functionality from the OpenZepplin ERC20 token contract implementation that we imported (line 4). + +This contract implements the optional functions `name()` and `symbol()` of the ERC20 Token standard and has a constructor where their values can be set during the deployment of the contract (line 7). +In this case, we are going to use the default values. We will call our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +Next, we make use of the inherited `_mint` function (line 8) that allows us to create tokens upon deployment of the contract. Inside the parameters, we specify the address of the account that receives the tokens and the amount of tokens that are created. +In this case, the account that deploys the contract will receive the tokens and we set the amount to 1000000 to the power of `decimals()`. The optional function `decimals()` of the ERC20 token standard is implemented and set to the default value of 18. This will create 1000000 tokens that will have 18 decimal places. + +## ⭐️ Assignment + +1. Rename your contract to `EduCoin`. +2. Rename your token to `EduCoin`. +3. Change the symbol of your token to `EDC`. +4. Change the amount of tokens that will be minted from 1000000 to 1000. diff --git a/locales/ja/ERC20TokenCourse/introduction/introduction.md b/locales/ja/ERC20TokenCourse/introduction/introduction.md new file mode 100644 index 000000000..4eaf7583c --- /dev/null +++ b/locales/ja/ERC20TokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with the ERC20 token standard in the following sections. + +If you want to learn more about NFTs and the ERC721 token standard, have a look at the Learneth NFT Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/ja/ERC721Auction/README.md b/locales/ja/ERC721Auction/README.md new file mode 100644 index 000000000..325e4d60e --- /dev/null +++ b/locales/ja/ERC721Auction/README.md @@ -0,0 +1,5 @@ +## NFT Auction Contract + +Learn how to write an ERC721 (NFT) auction contract. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ja/ERC721Auction/auction-contract-setup/auctionContractSetup.md b/locales/ja/ERC721Auction/auction-contract-setup/auctionContractSetup.md new file mode 100644 index 000000000..945f0f803 --- /dev/null +++ b/locales/ja/ERC721Auction/auction-contract-setup/auctionContractSetup.md @@ -0,0 +1,46 @@ +In this contract tutorial, we will learn how to create an ERC721 (NFT) auction contract. +We recommend to you, to do the Learneth "Solidity NFT Course" before starting this tutorial. + +In the following sections, we will create a contract that will enable a seller to auction an NFT to the highest bidder. This contract was created by the Solidity by Example project. In this first section, we will create an interface, the necessary state variables, and the constructor. + +### Interface + +We create the interface (line 5) for the ERC721 token since our contract will need to interact with it. We will need the `safeTransferFrom` (line 5), and` transferFrom` (line 11) methods. + +### EnglishAuction + +We create the four events `Start`, `Bid`, `Withdraw`, `End` (line 19-22) so we can log important interactions. + +Next, we will create the state variables that store all the necessary information about our auction on-chain. + +We create two state variables for the NFT we want to auction. In the variable `nft` (line 24) we store a representation of the NFT contract, that will allow us to call its functions by combining the interface IERC721 and the address of the NFT contract. +In `nftId` (line 25), we store the specific token id in our NFT contract that will be auctioned. + +Next, we need a variable to store the address of the person that is auctioning off the NFT, the `seller` (line 27). +We want our NFT contract to send the seller the proceeds of the auction when it is finished, that’s why use `address payable`. + +We create a state variable `endAt` (line 28) where we will store the end date of the auction. +We also create the two booleans, `started` (line 29) and `ended` (line 30), that keep track of whether the auction has started or ended. + +We create a variable `highestBidder` (line 32) where we will store the address of the highest bidder. We will send the highest bidder the NFT once the auction has ended. + +Finally, we need a uint `highestBid` (line 33) to store the highest bid and a mapping `bids` (line 34), where we can store the total value of bids that an account has made before withdrawing; more on this in the next section. + +### Constructor + +When the auctioneer deploys the contract, they need to provide a few arguments: +the address of the contract of the NFT they want to auction `_nft` (line 37), the token id of the NFT they want to auction `_nftId` (line 38), and a starting price that must be overbid to place the first bid in the auction,`_startingBid` (line 39). + +Once deployed, the state variables `nft` (line 41), `nftId` (line 42), `highestBid` (line 45) will be assigned the values from the arguments. The address of the `seller` that deployed the contract will be automatically read out via msg.sender and stored in the state variable `seller` (line 44). + +In the next section, we will enable the auctioneer to start the auction and bidders to place their bids. + +## ⭐️ Assignment + +We will use the assignment part of the following sections to give you instructions on testing your contract in the Remix VM environment of Remix. + +1. Deploy an NFT contract. You can use the NFT contract that we created in our "3.3 ERC721 - Token Creation" section. + +2. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +3. After deploying your contract, test if contract functions like `nft`, `nftId`, and `started` work as expected. diff --git a/locales/ja/ERC721Auction/auction-start-bid/auctionContractStartBid.md b/locales/ja/ERC721Auction/auction-start-bid/auctionContractStartBid.md new file mode 100644 index 000000000..c2b944e0c --- /dev/null +++ b/locales/ja/ERC721Auction/auction-start-bid/auctionContractStartBid.md @@ -0,0 +1,42 @@ +In this section, we will create a function to start the auction and a function to bid on the NFT. + +### Start + +We use some control structures to check if necessary conditions are met before we let the seller start the auction. + +First, we check if the auction has already started (line 49). If it has started and our state variable `started` returns `true` we exit the function and throw an exception. + +The second condition we check for is whether the seller is executing the function (line 50). We have already created a function to store the seller's address when they deploy the contract in the `seller` state variable and can now check if the account executing the start function is the seller. If not we throw an exception. + +Next, we want to transfer the NFT that is up for auction from the seller to the contract (line 52). +We set the state variable `started` to `true` (line 53), and create an end date for the auction (line 54). In this case, it will be seven days from when the start function has been called. We can use a suffix like `days` after a literal number to specify units of time. If you want to learn more about time units have a look at the solidity documentation. + +Finally, we will emit our `Start()` event (line 56). + +### Bid + +Before the function caller can make a bid, we need to be sure that certain conditions are met. The auction needs to have started (line 60), the auction can not have ended (line 61) and the bid (the value attached to the call) needs to be higher than the current highest bid (line 62). + +Now we want to store the bid of the current highest bidder before we make a new bid. +First, we check if there is a bidder (line 64). If this function call is the first bid then the next line would be irrelevant. +In our mapping `bids` (line 34) we map the key, the `address` of the bidder, to the value, a `uint` that represents the total amount of ETH a bidder has bid in the auction before withdrawing. +If there is a bidder, we add the last bid (`highestBid`) of the `highestBidder` to the total value of the bids they have made (line 65) before withdrawing. +We store the bids because we want to enable the bidder to withdraw the ETH they used to make bids if they are no longer the highest bidder. + +Next, we set the `highestBidder` to the account calling the function (line 68), and the `highestBid` to their bid, the value that was sent with the call (line 69). + +Finally, we emit the `Bid` event (line 71). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we create in our "Solidity NFT Course" Learneth course. + +2. Mint yourself an NFT with the tokenId 0. + +3. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +4. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for `tokenId`. This will allow the contract to transfer the token to be auctioned. + +5. Call the `start` function of your auction contract. If you call the `started` function now, it should return `true`. If you call the `highestBid` function it should return 1. + +6. Set the value that you can attach to transactions to 3 Wei and call the `bid` function of the auction contract. If you call the `highestBid` function it should now return 3. diff --git a/locales/ja/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md b/locales/ja/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md new file mode 100644 index 000000000..e324a5c6e --- /dev/null +++ b/locales/ja/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md @@ -0,0 +1,45 @@ +In this section, we will finish the contract, create a function to withdraw the bids that an account has made, and create a function to end the auction. + +### Withdraw + +We create a local variable `bal` (balance) that stores the total value of bids that the function caller has made (line 75) since their last withdrawal. We can assign this value to `bal` by accessing the bids mapping using the address of the function caller as the key. + +Next, we set the value of the address of the function caller to 0 in the bids mapping because they will withdraw the total value of their bids (line 76). + +Now we transfer that amount of ETH from the contract to the function caller and emit the `Withdraw` event (line 79). + +### End + +Before the function caller can execute this function and end the auction, we need to check if certain conditions are met. The auction needs to have started (line 83), the end date of the auction needs to have been reached (line 84), and the auction must not have ended already (line 85). + +Once the auction has ended, we set the state variable `ended` to `true` (line 87). + +We check if anybody participated in the auction and bid on the NFT (line 88). + +If there was a bid, we transfer the NFT from the contract to the highest bidder (line 89) and transfer the ETH that was sent from the highest bidder to the contract, now to the address of the auctioneer, the seller of the NFT (line 90). + +If nobody bids on the NFT, we send the NFT back to the auctioneer (line 92). + +Finally, we emit the `End` event (line 95). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we created in our Learneth "Solidity NFT Course". + +2. Mint yourself an NFT with the tokenId 0. + +3. For testing purposes, change the value that is assigned to the `endAt` state variable (line 54) from `7 days` to `5 minutes`. + +4. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +5. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for the `tokenId`. + +6. Call the `start` function of your auction contract. + +7. Bid 2 Ether using account 1, and 3 Ether using account 2. If you call the `highestBidder` function, it should now return the address of account 2. + +8. Call the `withdraw` function with account 1. In the balance of account 1, you should see the 2 Ether minus some transaction fees. + +9. After 5 minutes have passed, call the `end` function. Then, call the `ended` function which should return `true`. + +In the NFT contract, if you call the `ownerOf` function with the tokenId 0, it should return the address of account 2. If you look at the balance of account 1 it should have increased by 3 Ether minus some transaction fees. diff --git a/locales/ja/ERC721Auction/config.yml b/locales/ja/ERC721Auction/config.yml new file mode 100644 index 000000000..0783a37a1 --- /dev/null +++ b/locales/ja/ERC721Auction/config.yml @@ -0,0 +1,19 @@ +--- +id: er721Auction +name: NFT Auction Contract +summary: Learn how to write an ERC721 (NFT) auction contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: Contract Setup + path: auction-contract-setup + - + name: Start and Bid Functions + path: auction-start-bid + - + name: Withdraw and End Functions + path: auction-withdraw-end diff --git a/locales/ja/Interoperability/1_Intro/intro.md b/locales/ja/Interoperability/1_Intro/intro.md new file mode 100644 index 000000000..ab26f4f6d --- /dev/null +++ b/locales/ja/Interoperability/1_Intro/intro.md @@ -0,0 +1,5 @@ +As the web3 world grows, there will be more blockchains. Unless the chains can communicate with one another, the ecosystem will become increasingly fragmented. + +The Axelar network enables protocols to have cross-chain functionality between any two blockchains. + +Building a protocol that is interoperable between ecosystems is essential for growth. diff --git a/locales/ja/Interoperability/2_Gateway/gateway.md b/locales/ja/Interoperability/2_Gateway/gateway.md new file mode 100644 index 000000000..dc752d3eb --- /dev/null +++ b/locales/ja/Interoperability/2_Gateway/gateway.md @@ -0,0 +1,25 @@ +The Axelar Gateway is the entrypoint for your smart contract into the Axelar ecosystem. Once you have triggered the appropriate function on the Gateway, your transaction will begin its interchain journey from your source chain across the Axelar network to the destination chain. Each chain that is connected to Axelar has a deployed gateway contract for you to interact with. + +The following are the two more relevant functions you will need to be familiar with. + +## callContract() + +This function triggers an interchain transaction with a message from the source to the destination chain. It takes three relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent + +The first two parameters are quite intuitive. They consist of both the name of the chain you want this transaction to go to and the address on that chain you want to end execute at. The final parameter is the payload. This payload represents a general message that is sent to the destination chain. The message can be used in many different ways on the destination chain. For example, you can send data to be used as a parameter in another function on the destination chain, you can send a function signature as a message that will then get executed on a destination chain, and much more. + +## callContractWithToken() + +This function triggers an interchain with a message and a fungible token from the source to the destination chain. It takes five relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent +4. `symbol`: The symbol of the token being sent +5. `amount`: The amount of that token that is being sent + +The first three parameters here are the same as in `callContract()`. The final two parameters are relevant to the token that is being sent along with the message. These are the symbol of the token and the amount of the token that is being sent. diff --git a/locales/ja/Interoperability/3_GasService/GasService.md b/locales/ja/Interoperability/3_GasService/GasService.md new file mode 100644 index 000000000..4ed0afbbf --- /dev/null +++ b/locales/ja/Interoperability/3_GasService/GasService.md @@ -0,0 +1,29 @@ +The Axelar Gas Service is an extremely useful tool made available to pay gas for an interchain transaction. It allows you to pay for the cost of a transaction in the token of the source chain, making for a much easier end user (and developer) experience. If for example the source chain is Ethereum and the destination chain is Polygon then the gas service will receive the complete payment for the transaction in ETH and no matic is needed from the caller to pay for the execution on the Polygon destination chain. + +The following are the two more relevant functions you will need to be familiar with in regards to the Gas Service. + +## payNativeGasForContractCall() + +This function allows you to pay for the entirety of an interchain transaction in the native token of the source chain. It takes five relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +The parameters overlap with the parameters required by the `callContract()` function in the Gateway contract. The two parameters not discussed in the Gateway section are `sender` and `refundAddress`. The sender is the address paying for the transaction and the refund address is the address that will receive any surplus funds sent to the gas service. + +## payNativeGasForContractCallWithToken() + +This function allows you to pay for the entirety of an interchain transaction (that includes a token transfer) in the native token of the source chain. It takes seven relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `symbol`: The symbol of the token that was sent +6. `amount`: The amount of the token that was sent +7. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +This function is nearly identical to the first top one the main difference being that it is used for message + token transfer transactions as opposed to just interchain message transactions (aka GMP Transactions). As a result the GasService needs to also know the `symbol` and `amount` of the token that is being sent. diff --git a/locales/ja/Interoperability/4_Executable/executable.md b/locales/ja/Interoperability/4_Executable/executable.md new file mode 100644 index 000000000..1f72c6be4 --- /dev/null +++ b/locales/ja/Interoperability/4_Executable/executable.md @@ -0,0 +1,27 @@ +The Axelar executable contains relevant helper functions that will be automatically executed on the destination chain in correspondence to the relevant inbound transaction from the source chain. + +The following are the relevant functions you will need to use from Axelar Executable + +## \_execute() + +This function handles the execution on the destination chain. It takes the following four parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent + +The `sourceChain` and `sourceAddress` are key parameters which you receive out of the box that can be used for verifying authenticity of messages on the destination chain. The payload (as discussed in the gateway section) is the message that was sent from the source chain to be used on your destination chain. The `commandId` will not be used during the rest of this module. + +## \_executeWithToken() + +This function handles the execution on the destination chain for a message being sent with a fungible token. It takes six relevant parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent +5. `tokenSymbol`: The symbol of the token being sent +6. `amount`: The amount of that token that is being sent + +The first four parameters are identical to that of the `_execute()` function. The final two parameters of `tokenSymbol` and `amount` are in reference to the token that is being sent along with the message. It allows you on the destination chain to interact with the token accordingly, for example transferring it to another receiving address. The `commandId` will not be used during the rest of this module. diff --git a/locales/ja/Interoperability/5_InterchainMessage/interchainMessage.md b/locales/ja/Interoperability/5_InterchainMessage/interchainMessage.md new file mode 100644 index 000000000..029f642ce --- /dev/null +++ b/locales/ja/Interoperability/5_InterchainMessage/interchainMessage.md @@ -0,0 +1,53 @@ +In this section we will create a contract that will send a "hello world" message between two blockchains. + +## Constructor + +The first thing you will need to create is the `constructor` for the function. This will allow you to set the `Gateway` and `Gas Service` contracts we discussed in the previous sections. + +When deploying the contract you will pass in the address of the `Gateway` and `GasService` for Ethereum Sepolia those addresses are `0xe432150cce91c13a887f7D836923d5597adD8E31` for the Gateway and `0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6` for the Gas Service. + +For the full list of relevant Axelar addresses see here + +## Send Interchain Message + +Now that the constructor has set the relevant Axelar addresses needed to trigger an interchain transaction you can move on to the `setRemoteValue()`, which will trigger this transaction. + +This function takes three parameters: + +1. `_destinationChain`: The chain which the transaction is going to +2. `_destinationAddress`: The address on the destination chain the transaction will execute at +3. `_message`: The message being passed to the destination chain + +First, you have a `require` statement which ensures that the `msg.value` contains a value. This `msg.value` will be used to pay the `GasService`. If no funds were sent, then the transaction should be reverted as the transaction cannot execute on the Axelar blockchain and destination chain without any gas. + +Next, you encode the `_message` that was passed in. Notice that the `_message` is set as a `string` type. Axelar expects this message to be submitted as a `bytes` type so to convert the `string` to `bytes` you simply pass it through `abi.encode()`. + +Now, with your message encoded you can begin to interact with the `GasService` and the `Gateway` + +To pay for the entire interchain transaction you will trigger the function `payNativeGasForContractCall`, which is defined in the `GasService`. + +This function needs the parameters explained earlier in the GasService section. The `sender` for this transaction will be this contract, which is `address(this)`. The `destinationChain` and `destinationAddress` can simply be passed in from this functions parameters, the `payload` is the encoded \_message we wrote earlier. Finally, you need to specify what the refund address is, this can be the address that triggers this function, which you get by writing `msg.sender`. + +Once you trigger this function you will have successfully sent a transaction from the source chain via Axelar to the destination chain! But there is still one final step that needs to be complete. + +### Receive Message on Destination Chain + +On the destination chain the inbound interchain transaction needs to be picked up and handled by the `AxelarExecutable`'s `_execute()` function. + +The `_execute()` function is defined in the `AxelarExecutable` contract so when defining this function you must remember to include the `override` keyword. + +This function takes three parameters. + +1. `_sourceChain`: The blockchain which the transaction has originated from +2. `_sourceAddress`: The address on the source chain which the transaction has been sent from +3. `_payload`: The message that has been sent from the source chain + +The first thing that needs to be done in this contract is to get access to your `message` that was sent. Recall, before sending the message it was sent through `abi.encode()` to convert the message from type `string` to type `bytes`. To convert your message back from type `bytes` to type `string` simply pass the `_payload` to the function `abi.decode()` and specify that you want the `_payload` decoded to type `string`. This will return the message as a string. + +Now that you have your message as a type string you can set the `sourceChain` and `sourceAddress` storage variables as `_sourceChain` and `_sourceAddress` to have an easy reference to the data that was passed in. You can also emit the `Executed` event with the `sourceAddress` and `message` event that you just decoded. + +Great! At this point you are now handling the interchain transaction on the destination chain. + +To interact with this contract make sure you deploy it on at least two blockchains so that you can call `setRemoteValue()` from the one chain and then have the `_execute()` function automatically triggered on another chain. You will be able to query the `sourceChain` and `sourceAddress` variables on the destination chain to ensure that the interchain execution worked correctly. + +To view the full step by step of the interchain transaction checkout the Axelarscan (testnet) block explorer. diff --git a/locales/ja/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md b/locales/ja/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md new file mode 100644 index 000000000..11915eb32 --- /dev/null +++ b/locales/ja/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md @@ -0,0 +1,39 @@ +At this point we have gone over an example of how to send a general message between one blockchain to another. Now, let's implement a contract that sends a message and a token from one blockchain to another. + +## Overview + +This contract should seem largely familiar. Much like the previous section the `constructor` receives the `Gateway` and `Gas Service` addresses. + +It then has a function that will be called from the source chain called `sendToMany` that takes in parameters similar to the previous section. + +1. `_destinationChain`: The chain the transaction is sending to +2. `_destinationAddress`: The address on the destination chain your transaction is sending to +3. `_destinationAddresses`: The message that you will be sending along with your token transfer. In this example the message is a list of receiving addresses for the token transfer. +4. `_symbol`: The symbol of the token address being sent +5. `_amount`: The amount of the token being sent + +In the function we already have the `require` statement implemented to ensure gas is sent + +We also have the basic ERC20 functionality to send the token from the calling wallet to this smart contract. The contract also calls the `approve` function to allow the Gateway to eventually transfer funds on its behalf. + +Finally, the `_executeWithToken()` function is also implemented out of the box. + +It makes use of the following params: + +1. `_payload`: The incoming message from the source chain +2. `_tokenSymbol`: The symbol of the token that was sent from the source chain +3. `_amount`: The amount of the token that was sent from the source chain + +Now with these params that were passed in, the `_execute()` function can send the tokens that were sent to the appropriate receivers. + +## Challenge + +Your challenge here is to finish off the `sendToMany()` function using the Axelar Gateway and Gas Service to trigger an interchain transaction. + +In the end you should be able to deploy this contract on two testnets, trigger the `sendToMany()` function and see the live transaction on Axelarscan (testnet) block explorer. + +### Testing Notes + +Note 1: The recommended ERC20 to use is `aUSDC` a wrapped version of the USDC token that can be obtained from the discord faucet bot. When triggering the `sendToMany()` function simply pass in the symbol `aUSDC` to the fourth param. + +Note2: When triggering the `sendToMany()` function you must remember to `approve` your contract to spend `aUSDC` tokens on your behalf, otherwise `transferFrom()` on line49 will throw an error. diff --git a/locales/ja/Interoperability/7_FurtherReading/furtherReading.md b/locales/ja/Interoperability/7_FurtherReading/furtherReading.md new file mode 100644 index 000000000..a601d7ac7 --- /dev/null +++ b/locales/ja/Interoperability/7_FurtherReading/furtherReading.md @@ -0,0 +1,11 @@ +Congratulations on making it to the end of the interoperability module! 🎉🎉 + +To continue your learning journey of interoperability with Axelar. There are many useful resources available. + +- For documentation 📚 + +- For more technical examples 💻 + +- For live coding demos 📹 + +- For the developer blog 📝 diff --git a/locales/ja/Interoperability/README.md b/locales/ja/Interoperability/README.md new file mode 100644 index 000000000..a43fc5dd5 --- /dev/null +++ b/locales/ja/Interoperability/README.md @@ -0,0 +1,3 @@ +## Interoperability Between Blockchains + +Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. diff --git a/locales/ja/Interoperability/config.yml b/locales/ja/Interoperability/config.yml new file mode 100644 index 000000000..39f1be7ed --- /dev/null +++ b/locales/ja/Interoperability/config.yml @@ -0,0 +1,31 @@ +--- +id: interopCourse +name: Multichain Protocols with Axelar +summary: Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. +level: 2 +tags: + - Solidity + - Interoperability + - Axelar +steps: + - + name: An Intro to Axelar + path: 1_Intro + - + name: Axelar Gateway + path: 2_Gateway + - + name: Axelar Gas Service + path: 3_GasService + - + name: Axelar Executable + path: 4_Executable + - + name: Interchain Messages + path: 5_InterchainMessage + - + name: Interchain Token Transfers + path: 6_InterchainTokenTransfer + - + name: Further Reading + path: 7_FurtherReading diff --git a/locales/ja/Multisig-Tutorial/1-multisig-introduction/introduction.md b/locales/ja/Multisig-Tutorial/1-multisig-introduction/introduction.md new file mode 100644 index 000000000..3e9f18938 --- /dev/null +++ b/locales/ja/Multisig-Tutorial/1-multisig-introduction/introduction.md @@ -0,0 +1,41 @@ +Welcome to the Multisignature Wallet course! In this section, we'll explore the fundamentals of Multisignature (Multisig) wallets and we'll go through a multisig wallet contract. + +## What is a Multisignature Wallet? + +A multisignature (multisig) wallet is a type of digital wallet that requires multiple keys to authorize a cryptocurrency transaction. + +Imagine a multisig wallet as a secure vault with multiple locks. To open the vault, each keyholder must open their individual lock. This setup ensures that no single person can access the vault's contents without the others' consent. + +## How Does a Multisig Wallet Work? + +In a multisig setup, each transaction must receive a predetermined number of approvals from a set group of individuals. For instance, in a 3-of-5 wallet configuration, there are five authorized addresses, but a transaction only goes through when at least three of them give their approval. When a transaction is initiated, it's presented as a **proposal** to the group. Each member who agrees to the transaction uses their private key to digitally sign it. + +These **digital signatures** are unique and are generated based on the combination of the transaction data and the private key. + +When the required number of signatures is reached, the transaction is broadcasted to the blockchain for execution. + +## Why Use a Multisig Wallet? + +Multisig wallets are crucial for enhanced security in cryptocurrency transactions. They mitigate the risk of theft or loss of a single key. In business, they're used to ensure that funds can't be moved without consensus among stakeholders. For instance, in a company managing cryptocurrency assets, a multisig wallet might require the CFO, CEO, and a board member to all approve significant transactions, protecting against internal fraud or external hacks. + +## Conclusion + +In this section, we learned that a multisig wallet requires multiple keys to authorize a proposed cryptocurrency transaction and that a multisigs mitigates the risk of theft or loss of a single key. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is a Multisignature Wallet? + +1. A digital wallet that requires a single signature for transactions. +2. A digital wallet that requires multiple signatures for transactions. +3. A physical wallet used for storing cryptocurrency. +4. A wallet that can only hold multiple types of cryptocurrencies. + +### 2) How does a Multisignature Wallet enhance security? + +1. By requiring a single private key for transactions. +2. By distributing transaction approval across multiple owners. +3. By storing transaction data on-chain. +4. None of the above. + +Feel free to take your time and answer the questions above. Once you're ready, we'll move on to exploring the Multisig smart contract and understanding its structure. diff --git a/locales/ja/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md b/locales/ja/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md new file mode 100644 index 000000000..17b0a924f --- /dev/null +++ b/locales/ja/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md @@ -0,0 +1,60 @@ +In this section, we'll explore the **initialization process** of the Multisig smart contract. We'll examine the constructor function and review how it sets up the initial state of the contract. + +## Note + +From this section on in this tutorial, we will be building up a multisig contract. In subsequent sections, the contract will become increasingly complete. + +## Overview + +In this section, the contract consists of events, state variables, modifiers, and functions. **Events** provide transparency by logging specified activities on the blockchain, while **modifiers** ensure that only authorized users can execute certain functions. + +## State Variables + +In Line 4, we have the MultisigWallet contract itself. At the beginning of the contract, we have three state variables. + +1. **`owners`:** An array containing the addresses of all owners of the multi-signature wallet (Line 5). +2. **`isOwner`:** A mapping indicating whether an address is an owner (Line 6). +3. **`numConfirmationsRequired`:** The number of confirmations required for a transaction (Line 7). + +The setup of array and mapping allows us to easily retrieve the list of owners and verify whether an address is an owner. + +## Modifiers + +Next, we have a modifier called `onlyOwner` (Line 9). Modifiers in Solidity are special keywords that can be used to amend the behavior of functions. In our case, the `onlyOwner` modifier ensures that only owners can execute a function. It does this by checking whether the address of the **caller** is an owner. + +## Constructor Function + +The `constructor` function (Line 14) is executed only once during the deployment of the contract. It initializes essential parameters, in this case, the list of owners and the required number of confirmations (Line 14). + +On lines 15 and 16, we have two `require` statements to ensure that the inputs are valid. In this case, we require that there must be at least one owner and that the number of required confirmations must be greater than zero and less than or equal to the number of owners. + +The constructor then initializes the contract state by verifying that is not address(0) (Line 25) and that the owner is unique (Line 26). Then it adds a key/ value pair to the isOwner mapping (Line 28), and then it populates the `owners` array with the provided owner addresses (Line 29). + +Finally, it sets the `numConfirmationsRequired` variable with the specified value (Line 32). + +## getOwners Function + +The `getOwners` function (Line 36) allows users to retrieve the list of owners of the multi-signature wallet. It returns the `owners` array (Line 37). + +## getNumConfirmationsRequired Function + +The `getNumConfirmationsRequired` function (Line 41) allows users to retrieve the number of confirmations required for a transaction. It returns the `numConfirmationsRequired` variable (Line 42). + +## Conclusion + +In this section, we explored the initialization process of the Multisig smart contract. We examined the constructor function and understood how it sets up the initial state of the contract. + +## ⭐️ Assignment: Deploy a Multisig Wallet + +Deploy a Multisig contract with three owners and require two confirmations for transaction execution. + +1. Compile contractInitialization.sol +2. Go to Deploy & Run Transactions in Remix. +3. Expand the "Deploy" section. +4. Under "_OWNERS", enter three an array of three addresses. +5. Under "_NUM_CONFIRMATIONS_REQUIRED", enter the number of confirmations required for a transaction. + +**Hints:** + +- You can get addresses from the "ACCOUNTS" dropdown menu. +- The array of addresses should be in the format: ["0x123...", "0x456...", "0x789..."]. diff --git a/locales/ja/Multisig-Tutorial/3-multisig-deposits/deposits.md b/locales/ja/Multisig-Tutorial/3-multisig-deposits/deposits.md new file mode 100644 index 000000000..a8a14213b --- /dev/null +++ b/locales/ja/Multisig-Tutorial/3-multisig-deposits/deposits.md @@ -0,0 +1,34 @@ +In this section, we'll explore the `receive` function and the associated Deposit event. We'll examine how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## Deposit Event + +On line, 9 we have the Deposit event. The Deposit event is emitted whenever Ether is deposited into the multi-signature wallet. It includes three parameters: + +1. `sender`: The address that sent the Ether. +2. `amount`: The amount of Ether deposited. +3. `balance`: The updated balance of the contract after the deposit. + +We can use the Deposit event to track the flow of Ether into the multi-signature wallet and maybe trigger other actions based on the event. + +## receive Function + +On line 43, we have the `receive` function. The `receive` function is a special function that is executed whenever Ether is sent to the contract. + +The `receive` function is marked as `external` and `payable`. The `external` modifier means that the function can only be called from outside the contract. The `payable` modifier means that the function can receive Ether. + +The `receive` function emits the Deposit event (Line 44) with the address of the sender, the amount of Ether sent, and the updated balance of the contract. It doesn't return anything. + +To receive Ether, a contract must have a `receive`, `fallback`, or a function with the `payable` modifier. If none of these are present, the contract will reject any Ether sent to it. + +## Conclusion + +In this section, we explored the `receive` function and the associated Deposit event. We examined how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## ⭐️ Assignment: Deposit Ether + +Deposit 2 Ether into the Multisig contract. + +1. Deploy the Multisig contract as in the previous assignment. +2. Enter a Value of 2 Ether in the Value field and select Ether in the dropdown menu. +3. At the bottom of your deployed contract in the "Low level interactions" section, click on the "Transact" button. +4. On top of your deployed contract, it should now say "Balance: 2 Ether". diff --git a/locales/ja/Multisig-Tutorial/4-multisig-transactions/transactions.md b/locales/ja/Multisig-Tutorial/4-multisig-transactions/transactions.md new file mode 100644 index 000000000..f62fd48a0 --- /dev/null +++ b/locales/ja/Multisig-Tutorial/4-multisig-transactions/transactions.md @@ -0,0 +1,73 @@ +In this section, we'll explore the process of submitting and confirming transactions. + +## Modifiers + +We have new modifiers in this iteration of the contract. Let's examine them one by one. + +1. **`txExists` modifier:** (Line 13) ensures that the transaction exists. It does this by checking whether the transaction index is less than the length of the `transactions` array. We'll go into more about in this modifier later in this section. +2. **`notExecuted` modifier:** (Line 18) ensures that the transaction has not been executed. It does this by checking whether the `executed` variable of the transaction is false. +3. **`notConfirmed` modifier:** (Line 23) ensures that the transaction has not been confirmed by the caller. It does this by checking whether the `isConfirmed` mapping of the transaction index and the caller's address is false. + +## Transaction Struct + +On line 28, we have a struct called `Transaction`. We store the struct members: `to`, `value`, `data`, `executed`, and `numConfirmations` in individual variables. + +## Mapping of Confirmations + +On line 37, we have a mapping called `isConfirmed`. This mapping is used to keep track of the confirmations of each transaction. It maps the transaction's index to a mapping of an owner addresse to a boolean value. The boolean value indicates whether this owner has confirmed the transaction. + +## Transactions Array + +On line 39, we have an array called `transactions`. The array is used to store all the transactions submitted to the multi-signature wallet. + +## Events + +We have four new events in this iteration of the contract: + +1. **`SubmitTransaction` event:** emitted whenever a transaction is submitted to the multi-signature wallet. +2. **`ConfirmTransaction` event:** emitted whenever a transaction is confirmed by an owner. +3. **`RevokeConfirmation` event:** emitted whenever a transaction confirmation is revoked by an owner. +4. **`ExecuteTransaction` event:** emitted whenever a transaction is executed. + +## submitTransaction Function + +The `submitTransaction` function (Line 78) allows users to submit a transaction to the multi-sig wallet. It takes three parameters: `to`, `value`, and `data`. The `to` parameter is the address of the recipient of the transaction. The `value` parameter is the amount of Ether to be sent. The `data` parameter is the data to be sent to the recipient. Only owners can submit transactions. + +On line, 85 we create a new transaction struct and push it to the `transactions` array and emit the `SubmitTransaction` event. The `txIndex` variable is used to keep track of the transaction index. + +## confirmTransaction Function + +The `confirmTransaction` function (Line 98) allows users to confirm a transaction. It takes one parameter: `txIndex`. +It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. The `onlyOwner` modifier ensures that only owners can confirm transactions. The `txExists` modifier ensures that the transaction exists. The `notExecuted` modifier ensures that the transaction has not been executed. + +On line 101, we store the transaction in a local variable called `transaction`. We then increment the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to true. Finally, we emit the `ConfirmTransaction` event. + +## executeTransaction Function + +The `executeTransaction` function (Line 108) allows users to execute a transaction. On line 113, we require that the number of confirmations of the transaction is greater than or equal to the required number of confirmations. We then set the `executed` variable of the transaction to true. Finally, send the funds using the `call` function. This is the `call` of the recipient address with the value and data of the transaction. If the transaction is successful, we emit the `ExecuteTransaction` event. + +## getTransactionCount Function + +The `getTransactionCount` function (Line 132) allows users to retrieve the number of transactions in the multi-signature wallet. It returns the length of the `transactions` array. + +## getTransaction Function + +The `getTransaction` function (Line 136) allows users to retrieve a transaction. It returns the transaction struct members that we explored earlier in this section. + +## Conclusion + +In this section, we explored the process of submitting, confirming, and executing transactions. We examined the `submitTransaction`, `confirmTransaction`, and `executeTransaction` functions and understood how they work together to allow multiple users to submit and confirm transactions. + +## ⭐️ Assignment: Make a Transaction + +Submit, confirm, and execute a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. Deploy the Multisig contract as in the previous assignment. Make sure that the required number of confirmations is 2. +2. Fund the multisig from any address by sending 4 Ether as you did in the previous assignment. +3. Try sending 2 Ether to the first account in the "ACCOUNTS" dropdown menu. Once you have submitted this transaction (with submitTransaction), click on `getTransactionCount` and should see one transaction or you can click on `getTransaction`, insert 0 as the transaction index and see the transaction you just submitted. +4. Now you can click on `confirmTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. +5. Switch to the second owner account and confirm the transaction again. If you click on `getTransaction` again, you should see that the transaction has been confirmed twice. +6. The last step is to execute the transaction. Click on `executeTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been executed. You can also check the balance of the first account in the "ACCOUNTS" dropdown menu. It should now be 2 Ether higher and the balance of the multi-signature wallet should be 2 Ether lower. + +**Hint:** +If you submit a transaction make sure that the value is in Wei and that the _data field is correctly filled in. E.g. it could look like this: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 2000000000000000000, 0x" for 2 Ether. diff --git a/locales/ja/Multisig-Tutorial/5-multisig-revoke/revoke.md b/locales/ja/Multisig-Tutorial/5-multisig-revoke/revoke.md new file mode 100644 index 000000000..1bf085343 --- /dev/null +++ b/locales/ja/Multisig-Tutorial/5-multisig-revoke/revoke.md @@ -0,0 +1,30 @@ +In this section, we'll explore the process of revoking confirmations. This process is necessary when an owner changes their mind about a transaction and wants to stop it from being executed. This section will be pretty straightforward. + +## revokeConfirmation Event + +On line 14, we have added the `RevokeConfirmation` event. This event is emitted whenever a transaction confirmation is revoked by an owner. + +## revokeConfirmation Function + +On line 129, we have added the `revokeConfirmation` function. It allows users to revoke a transaction confirmation. + +`revokeConfirmation` takes one parameter: `txIndex`. It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. + +On line 134, we require that the transaction has been confirmed by the caller. This ensures that an owner who has confirmed the transaction can only revoke their own confirmation. +We then decrement the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to false. Finally, we emit the `RevokeConfirmation` event. + +## Conclusion + +In this section, we explored the process of revoking confirmations. We examined the `revokeConfirmation` function and understood how it works to allow users to revoke confirmations. + +## ⭐️ Assignment: Revoke a Confirmation + +Confirm and revoke a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. As in the previous assignment, deploy the Multisig contract, send the contract some Ether, and then submit a transaction to the first account in the "ACCOUNTS" dropdown menu with a value of 2 Ether. +2. Confirm the transaction twice as in the previous assignment. +3. Revoke the transaction by clicking on `revokeConfirmation` and inserting 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. + +## Final Conclusion + +In this tutorial, we explored the process of creating a multi-signature wallet. We learned how to initialize the contract, deposit Ether, submit, confirm, and revoke transactions. We also learned how to execute transactions and retrieve information about the multi-signature wallet. diff --git a/locales/ja/Multisig-Tutorial/README.md b/locales/ja/Multisig-Tutorial/README.md new file mode 100644 index 000000000..ae5997802 --- /dev/null +++ b/locales/ja/Multisig-Tutorial/README.md @@ -0,0 +1,5 @@ +## MultiSig Wallet + +Learn how to write a MultiSig Wallet smart contract on Ethereum. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ja/Multisig-Tutorial/config.yml b/locales/ja/Multisig-Tutorial/config.yml new file mode 100644 index 000000000..067de0fb9 --- /dev/null +++ b/locales/ja/Multisig-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: multisigCourse +name: Multisig Wallet +summary: Learn how to create and interact with a multisig wallet. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - Multisig +steps: + - + name: 1. Introduction + path: 1-multisig-introduction + - + name: 2. Initialize the Contract + path: 2-multisig-initialization + - + name: 3. Deposits + path: 3-multisig-deposits + - + name: 4. Transactions + path: 4-multisig-transactions + - + name: 5. Revoking Confirmations + path: 5-multisig-revoke diff --git a/locales/ja/NFTTokenCourse/README.md b/locales/ja/NFTTokenCourse/README.md new file mode 100644 index 000000000..c3d2a183a --- /dev/null +++ b/locales/ja/NFTTokenCourse/README.md @@ -0,0 +1,5 @@ +## Solidity NFT Course + +Learn how to create your own NFTs (non-fungible tokens). + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ja/NFTTokenCourse/config.yml b/locales/ja/NFTTokenCourse/config.yml new file mode 100644 index 000000000..af82db834 --- /dev/null +++ b/locales/ja/NFTTokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: nftTokenCourse +name: Solidity NFT Course +summary: Learn how to create your own NFT tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc721-interface + - + name: 3. Metadata Interface + path: erc721-interface-metadata + - + name: 4. Token Creation + path: erc721-token-creation + - + name: 5. Metadata IPFS + path: erc721-metadata-ipfs + - + name: 6. Deploy to Testnet + path: erc721-deploy-testnet-opensea diff --git a/locales/ja/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md b/locales/ja/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md new file mode 100644 index 000000000..40576500c --- /dev/null +++ b/locales/ja/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md @@ -0,0 +1,50 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to the Rinkeby testnet of the Ethereum blockchain, mint an NFT, and look at it on the NFT marketplace OpenSea. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token for Rinkeby + +In order to make transactions on the testnet, we need Ethereum testnet tokens. + +**2.1** Switch your Metamask from "Ethereum Mainnetwork" to "Rinkeby Test Network". + +**2.2** Go to https://faucet.paradigm.xyz/, enter the address of your account and claim testnet ETH. +You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Contract Deployment + +**3.1** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It should then ask you to connect your account, which you should confirm. Then you should see the Rinkeby network badge under "Injected Web3". + +**3.2** Deploy your token contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. + +### 4. Mint an NFT + +**4.1** Expand your contract in the IDE so you can see the buttons for the functions. + +**4.2** Expand the input fields next to the safeMint button. Enter the Ethereum address of the account that is connected to Remix in the “to:” input field. Enter “0” in the input field "tokenID:". Click on transact. + +**4.3** In Metamask click on assets, then click on the “Import tokens” link, and paste the address of your contract in the input field. You can set decimals to 0. + +You should now see the name of the symbol of your token contract (e.g. GEO) in your “Assets” view in Metamask. You should have one of these tokens. + +### 5. See your NFT on OpenSea + +OpenSea is one of the most popular online marketplace for NFTs. OpenSea also provides a version where you can see assets on the testnet, under https://testnets.opensea.io/ + +**5.1** Go to https://testnets.opensea.io/login. + +**5.2** Connect with your Metamask wallet. You should be redirected to your account https://testnets.opensea.io/account view on OpenSea, where you should be able to see your NFT. You should see the image of your NFT; when you click on it, you should see the name, description, and under properties, also the attributes that you created. + +If you successfully completed this course and are familiar with the basics of Solidity development, we encourage you to continue your learning journey by learning how to create your own NFT auction contract from the Learneth resources. diff --git a/locales/ja/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md b/locales/ja/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md new file mode 100644 index 000000000..a43162feb --- /dev/null +++ b/locales/ja/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md @@ -0,0 +1,44 @@ +The metadata extension is optional. It allows us to add additional information to our ERC721 tokens. We can specify a name, a symbol, and an URI (Uniform Resource Identifier) that can point to a file where we can add even more information in the form of a JSON. + +## ERC721 Metadata Functions + +### name + +The function `name` (line 16) returns the name of the token collection. A token collection means all tokens created with your ERC721 token contract implementation. Every token in this collection will have this name, regardless of their tokenId. + +### symbol + +The function `symbol` (line 21) returns the symbol of the token collection. + +### tokenURI + +The function `tokenURI` (line 26) returns the URI for the token with the id `tokenId`. In this case it’s not the URI of the whole collection but of an individual token in the collection. + +## ERC721 Metadata JSON Schema + +The file that the tokenURI points to should conform to the Metadata JSON Schema as it is specified in the EIP-721. + +``` +{ + "title": "Asset Metadata", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Identifies the asset to which this NFT represents" + }, + "description": { + "type": "string", + "description": "Describes the asset to which this NFT represents" + }, + "image": { + "type": "string", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." + } + } +} +``` + +The root element must be of the type object. This root object should have properties with the keys: name, description, and image that should be all of the type string. + +The ERC721 standard is pretty flexible, the tokenURI does not need to point to a JSON document and the JSON does not need to have all properties and often has additional properties. diff --git a/locales/ja/NFTTokenCourse/erc721-interface/erc721Interface.md b/locales/ja/NFTTokenCourse/erc721-interface/erc721Interface.md new file mode 100644 index 000000000..468e8e640 --- /dev/null +++ b/locales/ja/NFTTokenCourse/erc721-interface/erc721Interface.md @@ -0,0 +1,100 @@ +ERC721 is a standard for token contracts that manage non-fungible tokens (NFTs) on the Ethereum blockchain. + +Each non-fungible token is unique and not interchangeable. NFTs can have different properties, behavior, or rights. Non-fungible tokens are used to represent ownership of unique digital and physical assets like art, collectibles, or real estate. + +If you want to know more about the ERC721 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +The ERC721 standard is more complex than the ERC20 standard and it features optional extensions. ERC721 compliant contracts must, at a minimum, implement the ERC721 and ERC165 interfaces, which we will look at in this section. + +This interface (line 11) is part of the open-source contract library provided by OpenZeppelin. + +## Basic IERC721 Functions + +Contracts compliant with the ERC721 standard have to implement the following functions: + +### balanceOf + +The function `balanceOf` (line 30) returns the amount of tokens owned by the account with the address `owner`. + +### ownerOf + +The function `ownerOf` (line 39) returns the address `owner` of the account that holds the token with the id `tokenId`. + +### safeTransferFrom + +The function `safeTransferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +The function `safeTransferFrom` (line 137) is almost identical to the function `safeTransferFrom` (line 55) .The only difference is that this function has a non-empty payload `data`. + +A smart contract must implement the ERC721TokenReceiver Interface if it is to receive a transfer. This will ensure that the contract can handle ERC721 token transfers and prevent the tokens from being locked in a contract that can’t. + +### transferFrom + +The function `transferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +**It is recommended to use safeTransferFrom instead of transferFrom whenever possible.** +The `transferFrom` function is not secure because it doesn’t check if the smart contract that is the recipient of the transfer has implemented the ERC721TokenReceiver interface and is capable of handling ERC721 tokens. + +## Advanced IERC721 Functions + +### approve + +The function `approve` (line 94) gives the account with the address `to` the permission to manage the token with the id `tokenId` on behalf of the account calling the function. + +### getApproved + +The function `getApproved` (line 103) returns the address of the account (return var `operator`) that is approved to manage the token with the id `tokenId`. + +### setApprovalForAll + +The function `setApprovalForAll` (line 115) sets the permission (`_approved`) for the account with the specified address (input param - `operator`) to manage all tokens of the account calling the function. + +### isApprovedForAll + +The function `getApproved` (line 103) returns the boolean true if the account with the address `operator` is approved to manage all tokens of the account with the address `owner`. + +## IERC721 Events + +ERC721 contracts must also emit the following events: + +### Transfer + +The `Transfer` event (line 15) must be emitted when the token with the id `tokenId` is transferred from the account with the address `from` to the account with the address `to`. + +### Approval + +The `Approval` event (line 20) must be emitted when the account with the address `owner` approves the account with the address `spender` to manage the token with the id `tokenId` on its behalf. + +### ApprovalForAll + +The `ApprovalForAll` event (line 25) must be emitted when the account with the address `owner` gives or removes the permission (`_approved`) of the account with the address `operator` to manage all its tokens. + +## IERC165 + +In addition to the ERC721 interface, ERC721 compliant contracts must also implement the ERC165 interface. + +With the implementation of the ERC165 interface, contracts can declare the support of specific interfaces. A contract that wants to interact with another contract can then query if the other contract supports this interface before making a transaction e.g. sending tokens to it that they might not support. + +Our IERC721 interface here imports (line 6) and inherits (line 11) from the IERC165 interface. + +This is how OpenZeppelins implementation of the ERC165 interface looks like: + +``` +interface IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +For example, the ERC165 identifier for the ERC721 interface as specified in the EIP721 is “0x80ac58cd”. Learn how to calculate an interface identifier and more about the ERC165 in its improvement proposal. + +## Other interfaces + +The IERC721TokenReceiver interface must be implemented to accept safe transfers. + +There are two optional extensions for ERC721 contracts specified in the EIP721: + +IERC721Enumerable enables a contract to publish its full list of tokens and make them discoverable. + +IERC721Metadata enables a contract to associate additional information to a token. We will have a more detailed look into this in the next section. diff --git a/locales/ja/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md b/locales/ja/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md new file mode 100644 index 000000000..27876b068 --- /dev/null +++ b/locales/ja/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md @@ -0,0 +1,101 @@ +In this section, we will create our metadata and store it in a decentralized way. + +IPFS ( InterPlanetary File System) is a peer-to-peer network for storing files in a distributed way. Pinata.cloud is a pinning service that allows users to easily host files on the IPFS network. + +We want to host our images and the JSON files with their metadata on IPFS. + +### Create Image Folder + +In this example, we will create metadata for three tokens. As you can see below, we create three images that we stored in a folder. + +``` +geo-img +├── geo_1.png +├── geo_2.png +├── geo_3.png +``` + +### Register on Pinata + +Now, we want to host these images somewhere so we can point to them in the metadata of our tokens. Let's do it in a decentralized way and use Pinata to host them on IPFS. + +First you need an account on Pinata. Go to Pinata.cloud and create an account. On Pinata you can upload up to 1 GB of data for free. + +Once you have signed up, you should be in the Pin Manager view. + +Pin Manager Pinata + +### Upload Images to IPFS + +Click on the upload button and upload the folder with your images. +Once you've uploaded your folder, you should see the name of your folder and the CID (content identifier) associated with it. If the content in the folder changes, the CID will also change. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P + +You can access a specific image by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png + +### Create JSON files + +We create another folder where we store three JSON files. + +``` +geo-json +├── 0 +├── 1 +├── 2 +``` + +Inside the JSON files, create the metadata for the tokens, like name, description, and image. +For the image URL, we are going to use the URL of our images on IPFS. You can add additional data if you like; in this example, we added some unique attributes for each token. + +This is how the JSON for the first token could look: + +``` +{ + "name": "Geometry#0", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png +", + "attributes": [ + { "trait_type": "background", "value": "cyan" }, + { "trait_type": "color", "value": "red" }, + { "trait_type": "shape", "value": "circle" } + ] +} +``` + +This is how the JSON for the second token could look: + +``` +{ + "name": "Geometry#1", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_2.png", + "attributes": [ + { "trait_type": "background", "value": "magenta" }, + { "trait_type": "color", "value": "green" }, + { "trait_type": "shape", "value": "square" } + ] +} +``` + +As shown above, the folder in this example is called "geo-json". Inside this folder, we have three JSON files. +The first JSON file is called "0", the second JSON file is called "1", and the third JSON file is called "2". + +Make sure that your JSON files don't have a file ending and are named like their corresponding tokenIds. +In the pin manager on pinata.cloud, click on the upload button and upload the folder with your JSON files. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. +For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp +This will become our baseURI. + +You can access a specific JSON file then by just adding a slash and the tokenId by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/0 + +In the contract, replace the baseURI with your own baseURI. In this example, the baseURI consists of the URL +"https://ipfs.io/ipfs/", the CID containing the JSON files, and a slash at the end "/". + +An individual tokenURI will now be created for each token by adding the tokenId to the baseURI — exactly what we did manually in the example above to access the JSON file. diff --git a/locales/ja/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md b/locales/ja/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md new file mode 100644 index 000000000..891fe00a7 --- /dev/null +++ b/locales/ja/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md @@ -0,0 +1,35 @@ +In this contract, we use an ERC721 token contract implementation from OpenZeppelin (line 4). + +Have a look at their implementation of a ERC721 contract. Apart from the functionality specified in the ERC721 standard, the contract provides additional functions which we will see in a bit. + +## myToken + +We create our own contract called MyToken (line 7), which inherits (line 7) the functionality from the OpenZepplin `ERC721` token contract implementation and `Ownable` that we imported (line 4). If you don't remember the Ownable contract module, have a look at the ERC20 extensions section. + +This ERC721 implementation makes use of the IERC721Metadata extension that is specified in the EIP. Our contract inherits the functions `name()` and `symbol()` +and has a constructor that allows their values to be set during the deployment of the contract (line 8). +In this case, we are going to use the default values. We name our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +### Base URI + +With an ERC721 contract, we are able to mint various tokens, each with its own tokenId. As we saw in the IERC721Metadata interface, each token can have its own `tokenURI`, which typically points to a JSON file to store metadata like name, description, and image link. +If a contract mints multiple tokens, ERC721 implementations often use the same URI as a base (`baseURI`) for all tokens and only differentiate them by adding their unique `tokenId` at the end via concatenation. In the next part, we will see what this looks like in practice. + +In this example, we are storing our data on IPFS — more on that in the next section. Our baseURI is https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/ (line 11). +Through concatenation the tokenURI for the token with the id 0 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/0 , the tokenURI for the token with the id 1 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/1, and so on. + +When using IPFS and you run into "504 Gateway Time-out" errors, you might have to wait and retry until the data is available. + +### safeMint + +With the safeMint function (line 14) we enable the owner to create new tokens with a dedicated token id after contract deployment. +The safeMint function is part of the ERC721 implementation of OpenZeppelin and lets us safely mint a token with the id `tokenId` to the account with the address `to`. For access control, we use the `onlyOwner` modifier from the Ownable access control contract module that we imported (line 5). + +In the next section, we will see how we can create and host the metadata for our NFTs. + +## ⭐️ Assignment + +1. Rename your contract to `Geometry`. +2. Rename your token to `Geometry`. +3. Change the symbol of your token to `GEO`. +4. Change the `_baseURI` to https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/. diff --git a/locales/ja/NFTTokenCourse/introduction/introduction.md b/locales/ja/NFTTokenCourse/introduction/introduction.md new file mode 100644 index 000000000..13beea567 --- /dev/null +++ b/locales/ja/NFTTokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with NFTs, tokens created with the ERC721 token standard. + +If you want to learn more about fungible tokens and the ERC20 token standard, have a look at the Learneth ERC20 Token Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain-based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/ja/OpcodesInTheDebugger/1_intro/step.md b/locales/ja/OpcodesInTheDebugger/1_intro/step.md new file mode 100644 index 000000000..c1d9a2448 --- /dev/null +++ b/locales/ja/OpcodesInTheDebugger/1_intro/step.md @@ -0,0 +1,5 @@ +This workshop aims to give a better understanding about how a contract get deployed. +`SimpleStore` is a very basic contract. +It has a very simple constructor - which just uses the first parameter `_o` and saves it to `s`. + +Using the debugger, we'll try to see, what the opcode `CODECOPY` does. diff --git a/locales/ja/OpcodesInTheDebugger/2_memory/step.md b/locales/ja/OpcodesInTheDebugger/2_memory/step.md new file mode 100644 index 000000000..577169a5e --- /dev/null +++ b/locales/ja/OpcodesInTheDebugger/2_memory/step.md @@ -0,0 +1,8 @@ +Before we start, just quick reminder: + +The runtime of the EVM has several kinds of memory: + +- `calldata`: This is the input value given to the transaction. +- `stack`: Basically, this is a list of values, each value is limited in size (32 bytes). +- `memory`: Memory is used when the **type** of value getting stored is more complex like an array or a mapping. This memory is **temporary** and is **released** at the end of the execution. +- `storage`: This is a mapping, each value stored is **persisted** and saved on chain. diff --git a/locales/ja/OpcodesInTheDebugger/3_codecopy/step.md b/locales/ja/OpcodesInTheDebugger/3_codecopy/step.md new file mode 100644 index 000000000..b0c9f7d52 --- /dev/null +++ b/locales/ja/OpcodesInTheDebugger/3_codecopy/step.md @@ -0,0 +1,7 @@ +CODECOPY is one of the many opcodes run by the EVM. Check out the complete list of opcodes at https://ethervm.io/ . + +CODECOPY takes the **running code** (or part of it) and to copies it from the `calldata` to the `memory`. + +The solidity implementation is: **codecopy(t, f, s)** - copy **s** bytes from code at position **f** to memory at position **t**. + +Every contract deployment uses **CODECOPY**. diff --git a/locales/ja/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md b/locales/ja/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md new file mode 100644 index 000000000..63950051d --- /dev/null +++ b/locales/ja/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md @@ -0,0 +1,11 @@ +Let's go back to our contract. +Please make sure the `solidity compiler` and `Deploy & Run Transactions` are activated. + +Alternatively, you can click on `Solidity` from the `Home Page` **Environments** section. + +- Compile the contract from the `solidity compiler`. +- Go to the `Deploy & Run Transactions` and make sure `SimpleStore` is selected contract. +- In the textbox to the right of `Deploy`, input a positive integer. +- Click on `Deploy`. + +In the next step, we'll watch the deployment in the debugger. diff --git a/locales/ja/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md b/locales/ja/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md new file mode 100644 index 000000000..3ef3cd146 --- /dev/null +++ b/locales/ja/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md @@ -0,0 +1,7 @@ +From the Remix terminal, identify the transaction that deployed the contract and click `Debug` + +In the gutter of the editor, put a breakpoint on the line `s = _o`, and click on `Jump to the next Breakpoint` (bottom right button). + +Click on `Step into`, to move along the opcodes until you reach `SSTORE`. + +`SSTORE` is the opcode for storing the value `_o` in the storage. Let's continue further to the `CODECOPY`. diff --git a/locales/ja/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md b/locales/ja/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md new file mode 100644 index 000000000..1480728e6 --- /dev/null +++ b/locales/ja/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md @@ -0,0 +1,57 @@ +The goal here is to store the code in the blockchain. The EVM needs to tell the client (geth, parity) which what part of the **Call Data** to store. In this step, we are saving the contract MINUS its constructor (because that gets inplmented only 1 time) and MINUS the input parameter does not need to be stored. + +`CODECOPY` is the first step: it copies the bytecode to memory, then the ethereum client will be able to consume it. MUNCH! + +But wait... before the client can **MUNCH** bytecode, it needs an instruction - an opcode to tell it to MUNCH. `RETURN` is this opcode! + +As stated in the general spec, at the end of the contract creation, the client (geth, parity) takes the targeted value by the opcode `RETURN` and **persists** it by making it part of the deployed bytecode. + +Once you are in the `CODECOPY`, look at the top 3 items in the **Stack**: + +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x0000000000000000000000000000000000000000000000000000000000000055` +`2: 0x000000000000000000000000000000000000000000000000000000000000003e` + +_In your Stack - `1` & `2` may be slightly different. The difference may be due to a different compiler version._ + +**These are the parameters for `CODECOPY`.** + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +`0` is the offset where the copied code should be placed in the **memory**. In this example, ( all zeros) the code is copied to the beginning of the memory. (**t**) +`1` is the offset in **calldata** where to copy from (**f**) +`2` number of bytes to copy - (**s**) + +After `CODECOPY` is executed, (click the _step into_ button) the copied code should be: +`0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c63430005110032` in memory. **I'll refer to this value as (X)**. + +Let's look at the debugger's **Memory** panel. +The 0x number I gave above is not what you will see in the **Memory** panel -what you will see is this: +0x0: 6080604052600080fdfea265627a7a72 ????R??????ebzzr +0x10: 31582029bb0975555a15a155e2cf28e0 1X ?? uUZ??U???? +0x20: 25c8d492f0613bfb5cbf96399f6dbd4e ?????a?????9?m?N +0x30: a6fc9164736f6c634300051100320000 ???dsolcC????2?? +0x40: 00000000000000000000000000000000 ???????????????? +0x50: 000000000000000000000000000000a0 ??????????????? +0x60: 00000000000000000000000000000000 ???????????????? +0x70: 00000000000000000000000000000000 ???????????????? +0x80: 00000000000000000000000000000000 ???????????????? +0x90: 00000000000000000000000000000002 ???????????????? + +The `0x0`, `0x10`, etc is the position. The next number is the bytecode for that position. This is followed by question marks and seemingly random letters & numbers. This is **Remix**'s attempt to convert this into a string. + +So if we glue the first four sections of bytecode together, we'll get: +**0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e0a6fc9164736f6c63430005110032** The last section - `0x90` has 2 which is what I input for the constructors parameter. + +The input data from the **Call Data** panel is: +`0x6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c634300051100320000000000000000000000000000000000000000000000000000000000000002` +**I'll refer to this value as (Y).** + +This shows us that `(X)` is a subset of the original calldata `(Y)`: + +`(X)` is calldata without the input parameter `0000000000000000000000000000000000000000000000000000000000000002` (we don't need to store this) +and without the constructor code `6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe` which should be executed only 1 time. + +So `CODECOPY` extracts the bytecode from the calldata and copies it to the memory. + +Let's move to the next step. diff --git a/locales/ja/OpcodesInTheDebugger/7_returnAndStore/step.md b/locales/ja/OpcodesInTheDebugger/7_returnAndStore/step.md new file mode 100644 index 000000000..b375a24fb --- /dev/null +++ b/locales/ja/OpcodesInTheDebugger/7_returnAndStore/step.md @@ -0,0 +1,18 @@ +# The Opcode RETURN + +At the end of the last chapter we had moved to one step after **CODECOPY** to see what happened in the memory. + +Now that CODECOPY has been executed, we are on the opcode `PUSH1 00`. + +`PUSH1 00` prepares the stack for the `RETURN` opcode. +`RETURN` is the last part of this process. It is where the code is returned to the client. + +We push `00` to the stack because this is the offset position of the contract bytecode in memory. + +Now we can call the all important `RETURN` opcode. + +The **stack inspector** shows: +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x000000000000000000000000000000000000000000000000000000000000003e` + +Which is to say it returns to the client the bytecode starting `0x00` with length `0x3e`. diff --git a/locales/ja/OpcodesInTheDebugger/8_findTheOffset/step.md b/locales/ja/OpcodesInTheDebugger/8_findTheOffset/step.md new file mode 100644 index 000000000..6b1ddc5cf --- /dev/null +++ b/locales/ja/OpcodesInTheDebugger/8_findTheOffset/step.md @@ -0,0 +1,18 @@ +# Find the offset ;) + +And now for a slightly different example: + +- Compile notSimpleStore.sol +- Deploy the contract `notSoSimpleStore` +- Make sure you have a successful deployment - if not check that you used **the correct input type** in the constructor. +- Go to the Debugger by clicking the **debug** button at the (successful) creation transaction. +- Find the value of the parameter of `CODECOPY` which represents the offset in calldata where to copy from. + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +If you look in the **Stack**, you should see that the 2nd element is: +0x0000000000000000000000000000000000000000000000000000000000000083 + +And this is the **f** of the input params of codecopy. + +### Hope you picked up a thing or 2 about how opcodes work! diff --git a/locales/ja/OpcodesInTheDebugger/config.yml b/locales/ja/OpcodesInTheDebugger/config.yml new file mode 100644 index 000000000..74a1bf3a1 --- /dev/null +++ b/locales/ja/OpcodesInTheDebugger/config.yml @@ -0,0 +1,10 @@ +--- +id: opcodesdebug +name: Opcodes in the Debugger +summary: Using the Debugger, we'll check out what the CODECOPY opcode does and how it is used by the EVM during contract creation. +level: 3 +tags: + - Remix + - Debugging + - EVM + - Opcodes diff --git a/locales/ja/ProxyContract/1_Why/step1.md b/locales/ja/ProxyContract/1_Why/step1.md new file mode 100644 index 000000000..03c4d1675 --- /dev/null +++ b/locales/ja/ProxyContract/1_Why/step1.md @@ -0,0 +1,27 @@ +# プロキシコントラクト(別名: ディスパッチャー) + +## 目的 + +**ライブラリ開発**で主に使用されている有用なパターンです。 + +このパターンは、次の場面で役立ちます。 + +- **デプロイ時にガス代を節約** + ガス代が高いことの理由は、実行において多大なガス代がかかることを抑制し、最適化されたコードを奨励するためです。 + +- プロキシコントラクトは、デプロイにおける冗長性を減らすことができるので、同じコントラクトで多数のインスタンスをデプロイすることが必要な時に便利です。 + +- **ブロックチェーンでコードの繰り返しを避ける** + 負荷の高い計算は、すべてのノードで実行する必要があるため、高価になります。また、ネットワークにも遅延を発生させます。 + +- **アップグレーダブル(バージョン化)コントラクトの開発** + コントラクトをデプロイすると、イミュータブルになります。 異なるコントラクトにコードを再設計することで、同じストレージを保ちながら、ロジックのアップグレードを可能にします。 + +## ガス代の例 + +作成時において、コントラクトのコードを保存するのにかかるコストは次のようになります。 + +- 200 \* max_byte_code_length gas +- 200 \* 24576 = 49152004915200 \* 10 gwei = 49152000 gwei = 0.049152 ether = 9 EUR + +max_byte_code_lengthについての情報は、 https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md をご覧ください。 diff --git a/locales/ja/ProxyContract/2_How/step2.md b/locales/ja/ProxyContract/2_How/step2.md new file mode 100644 index 000000000..d80b6557c --- /dev/null +++ b/locales/ja/ProxyContract/2_How/step2.md @@ -0,0 +1,13 @@ +# How it works? + +**EIP-7 DelegateCall** opcode allows a separate execution in another contract while maintaining the original execution context. + +All **message calls** from the user go through a **Proxy contract**. + +The **Proxy contract** then will redirect them to the **Logic contract**. + +And when you need to **upgrade** the logic, you'll **just** deploy that - **HOWEVER** - the implementation of Proxy will remain the same. + +You'll only need to update the address of Logic contract in Proxy. + +The Proxy Contract uses **Delegate calls** and **Solidity assembly** because without it, it's impossible to return any value from **delegatecall**. diff --git a/locales/ja/ProxyContract/3_Delegatecall/step3.md b/locales/ja/ProxyContract/3_Delegatecall/step3.md new file mode 100644 index 000000000..8693e5567 --- /dev/null +++ b/locales/ja/ProxyContract/3_Delegatecall/step3.md @@ -0,0 +1,9 @@ +# Delegate call + +It's a special variant of a **message call**, which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract so **msg.sender** and **msg.value** do not change their values. + +This means that a contract can dynamically load code from a different address at runtime. + +The storage, the current address and balance still refer to the calling contract, only the code is taken from the called address. + +So when a **Proxy** delegates calls to the Logic contract, every storage modification will impact the storage of Logic contract. diff --git a/locales/ja/ProxyContract/4_Generic_proxy_example/step4.md b/locales/ja/ProxyContract/4_Generic_proxy_example/step4.md new file mode 100644 index 000000000..d20fdd16d --- /dev/null +++ b/locales/ja/ProxyContract/4_Generic_proxy_example/step4.md @@ -0,0 +1,15 @@ +# A Basic Generic Proxy Example + +In the associated solidity file, **step4.sol**, there are 2 contracts - **ProxyContract** and **LogicContract**. + +To use this system, we first deploy the LogicContract. + +And then when we go to deploy the ProxyContract, we pass the LogicContract's address as an argument of the ProxyContract's constructor. + +The ProxyContract is deployed only once. + +The code of LogicContract will be called at the line 20. It will be forwarded with delegate call while keeping the context of LogicContract. + +In case we need to change the logic we would deploy a new LogicContract and set the address of it with setLogicContractAddress setter function. + +_Note: The LogicContract we have here does not use the storage. Once you need to use the storage the implementation becomes a bit more complicated because those contracts share the context._ diff --git a/locales/ja/ProxyContract/5_Test/step5.md b/locales/ja/ProxyContract/5_Test/step5.md new file mode 100644 index 000000000..120a15e13 --- /dev/null +++ b/locales/ja/ProxyContract/5_Test/step5.md @@ -0,0 +1,6 @@ +# Let's test what we've learned + +- Write a contract named "LogicContract" which implements a public function named "getNumber" which returns 10 +- Write a proxy contract named "ProxyContract". This ProxyContract should take an address of LogicContract as a first parameter. + +Good Luck! diff --git a/locales/ja/ProxyContract/6_Storage_Problem/step6.md b/locales/ja/ProxyContract/6_Storage_Problem/step6.md new file mode 100644 index 000000000..d2b804284 --- /dev/null +++ b/locales/ja/ProxyContract/6_Storage_Problem/step6.md @@ -0,0 +1,13 @@ +# What if we have state variables? + +Things are more complicated once we need to deal with state variables. State variable are saved to **storage**. + +`storage`: is a mapping; each value stored there is persisted and saved on chain. + +_Note: Statically-sized state variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position 0. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible. For contracts that use inheritance, the ordering of state variables is determined by the C3-linearized order of contracts starting with the most base-ward contract_ + +Once we execute **delegate call**, the storage of both contracts get **"merged"** into a single messy state. + +We have to "tell" ProxyContract what the **state** of the **Logic contract** looks like. + +The easiest way to do this is to create a separate contract - in this example - named **StorageContract** which will represent the **state** and which proxyContract will inherit from. diff --git a/locales/ja/ProxyContract/7_links/step7.md b/locales/ja/ProxyContract/7_links/step7.md new file mode 100644 index 000000000..c2784c3cc --- /dev/null +++ b/locales/ja/ProxyContract/7_links/step7.md @@ -0,0 +1,19 @@ +# Check out some links for more info + +- ERC DelegateProxy + https://github.com/ethereum/EIPs/pull/897 + +- The joint post by Zeppelin Solutions and Aragon. + https://blog.openzeppelin.com/proxy-libraries-in-solidity-79fbe4b970fd/ + +- Proxy Patterns by OpenZeppelin + https://blog.openzeppelin.com/proxy-patterns/ + +- The most mature implementation of Proxy pattern is The Unstructure Storage pattern that is released as part of ZeppelinOS + https://blog.openzeppelin.com/upgradeability-using-unstructured-storage/ + +- Great blog post by Jack Tanner + https://blog.indorse.io/ethereum-upgradeable-smart-contract-strategies-456350d0557c + +- Upgradeable Ethereum Smart Contracts + https://medium.com/@daonomic/upgradeable-ethereum-smart-contracts-d036cb373d6 diff --git a/locales/ja/ProxyContract/README.md b/locales/ja/ProxyContract/README.md new file mode 100644 index 000000000..6a5364c94 --- /dev/null +++ b/locales/ja/ProxyContract/README.md @@ -0,0 +1,3 @@ +## Learn the Proxy Pattern + +Save gas & make upgradable contracts diff --git a/locales/ja/ProxyContract/config.yml b/locales/ja/ProxyContract/config.yml new file mode 100644 index 000000000..e36e640b8 --- /dev/null +++ b/locales/ja/ProxyContract/config.yml @@ -0,0 +1,9 @@ +--- +id: proxycontract +name: All about Proxy Contracts +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 3 +tags: + - Remix + - Solidity + - Code Patterns diff --git a/locales/ja/README.md b/locales/ja/README.md new file mode 100644 index 000000000..cb799bd20 --- /dev/null +++ b/locales/ja/README.md @@ -0,0 +1,36 @@ +# This is a repo of tutorials for the Remix's LearnEth Plugin + +### To use these tutorials: + +**1. Open Remix** + +https://remix.ethereum.org + +**2. In the plugin manager activate LEARNETH** + +**3. Go to the Learneth plugin and these tutorials will load by default** + +**4. You may need to sign into Github especially during an in-person workshop** + +Github will block too many requests from the same location, unless you are signed into Github and have input your token. Generally, this is only an issue during in person workshops, when there can be many requests from the same location. + +To input your Github token: + +``` +- In one browser window - go to https://remix.ethereum.org and go to the settings tab +- In another browser window go to: + +https://github.com/settings/tokens + +and create a new token and save it in Remix in the you just opened on the settings tab. +``` + +--- + +### Write your own tutorials for LEARNETH: + +See this site for instructions: + +https://remix-learneth-plugin.readthedocs.io/en/latest/index.html#creating-tutorials + +--- diff --git a/locales/ja/Recorder/1_Usecases/1_usecases.md b/locales/ja/Recorder/1_Usecases/1_usecases.md new file mode 100644 index 000000000..0c624393c --- /dev/null +++ b/locales/ja/Recorder/1_Usecases/1_usecases.md @@ -0,0 +1,7 @@ +1. You want to show someone what happens when you do a number of transactions with a contract and you don't want to explain each step - you just want to get them to the last step. + + - To show someone a problem in their code. + + - In a class, to get the students to a certain place and have them start working from there. + +2. You want to start your development in the JavascriptVM because it is quick and then to switch to another testnet - but you don't want to manually repeat all the tedious clicking for each different network. diff --git a/locales/ja/Recorder/2_Record/README.md b/locales/ja/Recorder/2_Record/README.md new file mode 100644 index 000000000..41d214277 --- /dev/null +++ b/locales/ja/Recorder/2_Record/README.md @@ -0,0 +1,32 @@ +# Setting up a tedious series of steps + +## Following this could get tedious but that's the point. + +We are going to: + +- Deploy a voting contract where there are 3 proposals input in the constructor. +- Give voting privileges to 2 additional address (so we have a total of 3 voting addresses). +- Have one address vote for proposal 1 (0-based index) and the other two vote for proposal 2. + +1. Take the 3_Ballot.sol from the sample solidity files and compile it. Then go to the **Deploy & Run** Module. + +2. Select the **JavaScript VM** Environment. + +3. In the constructor's parameter - put in **["0x5031000000000000000000000000000000000000000000000000000000000000", "0x5032000000000000000000000000000000000000000000000000000000000000", "0x5033000000000000000000000000000000000000000000000000000000000000"]** Then click the **Deploy** button. + +4. Open up the deployed contract. + +5. In the **vote** function put in 2. This means that you as the msg.sender & chairperson are voting for proposal at position 2, which is the last proposal in our list. + +6. Now you need to give other addresses the right to vote. Select another address in the **account** pulldown and copy it and then **go back to the 1st address**. Paste the copy address into the textbox next to the giveRightToVote function. And again, select another address and copy it and **then go back to the 1st address** again and paste it into giveRightToVote. + +7. Now you have 3 addresses with the right to vote. + +8. Switch to one of the addresses that you gave the right to vote and vote for proposal **1**. (Put **1** in the textbox next to the vote function). And then switch to the other address and vote for proposal **2** with that one. + +9. Open up the **Transactions recorded** section of the module - by clicking on the caret. Click the hard disk icon in the **Transactions recorded** section to save your steps. + ![recorder](https://github.com/ethereum/remix-workshops/blob/master/Recorder/2_Record/images/recorder.png?raw=true "recorder") + +10. You will get a modal window that tells you it wants to save a file called **scenario.json**. Click OK. + +11. Click on the function **winningProposal** to confirm that the final proposal won - which is the proposal at position 2 in the array. **0: uint256: winningProposal_ 2** diff --git a/locales/ja/Recorder/3_Editing_a_Senario/README.md b/locales/ja/Recorder/3_Editing_a_Senario/README.md new file mode 100644 index 000000000..d23dfb95c --- /dev/null +++ b/locales/ja/Recorder/3_Editing_a_Senario/README.md @@ -0,0 +1,54 @@ +# Editing a scenario + +Here's the first few lines of the scenario that I recorded. The addresses on my machine will be different from your's. + +``` +{ + "accounts": { + "account{0}": "0xca35b7d915458ef540ade6068dfe2f44e8fa733c", + "account{4}": "0xdd870fa1b7c4700f2bd7f44238821c26f7392148", + "account{3}": "0x583031d1113ad414f02576bd6afabfb302140225" + } +``` + +So if you wanted to play this scenario in another testnet, you'd need to change these addresses to address that you have test ETH on so that you could pay for the transactions. But other than swapping out the addresses, you can quickly run this on other nets. + +And you might change the parameters for the functions. + +For example here is a bit of the scenario.json a bit further down where proposal 2 was voted for by one of the addresses: + +``` +{ + "timestamp": 1566428184043, + "record": { + "value": "0", + "parameters": [ + "2" + ], + "to": "created{1566428035436}", + "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", + "name": "vote", + "inputs": "(uint8)", + "type": "function", + "from": "account{4}" + } + }, +``` + +Let's edit this so that another proposal wins in the playback. + +Change the **parameters** array which now is: + +``` +"parameters": [ + "2" + ] +``` + +to: + +``` +"parameters": [ + "1" + ] +``` diff --git a/locales/ja/Recorder/4_Play/README.md b/locales/ja/Recorder/4_Play/README.md new file mode 100644 index 000000000..196664550 --- /dev/null +++ b/locales/ja/Recorder/4_Play/README.md @@ -0,0 +1,8 @@ +# Playing a scenario + +1. Click the play icon to the right of the floppy disk icon to play the steps you did. + +2. You'll see another instance of the contract deployed. Open it up. + +3. Click the winningProposal function and you should see now that proposal 1 won. + It should print out: **0: uint256: winningProposal_ 1** diff --git a/locales/ja/Recorder/README.md b/locales/ja/Recorder/README.md new file mode 100644 index 000000000..94d928383 --- /dev/null +++ b/locales/ja/Recorder/README.md @@ -0,0 +1,3 @@ +## Get yourself Remixing! + +The recorder is used for recording a set of transactions in the Deploy & Run module, editing their parameters and then playing them back in another context. It really is the remix of Remix! diff --git a/locales/ja/Recorder/config.yml b/locales/ja/Recorder/config.yml new file mode 100644 index 000000000..b8980e042 --- /dev/null +++ b/locales/ja/Recorder/config.yml @@ -0,0 +1,7 @@ +--- +id: recorder +name: Recorder +summary: Save a set of actions and replay and replay and replay +level: 2 +tags: + - Remix diff --git a/locales/ja/SolidityBeginnerCourse/README.md b/locales/ja/SolidityBeginnerCourse/README.md new file mode 100644 index 000000000..ae0b6d882 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Course + +Learn the most important Solidity beginner concepts interactively, based on the popular https://solidity-by-example.org/ contracts. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ja/SolidityBeginnerCourse/basic-syntax/basicSyntax.md b/locales/ja/SolidityBeginnerCourse/basic-syntax/basicSyntax.md new file mode 100644 index 000000000..e9f77871e --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/basic-syntax/basicSyntax.md @@ -0,0 +1,26 @@ +In this section, we will create our first _smart contract_. This contract only consists of a string that holds the value "Hello World!". + +In the first line, we should specify the license that we want to use. You can find a comprehensive list of licenses here: https://spdx.org/licenses/. + +Using the `pragma` keyword (line 3), we specify the Solidity version we want the compiler to use. In this case, it should be greater than or equal to `0.8.3` but less than 0.9.0. + +We define a contract with the keyword `contract` and give it a name, in this case, `HelloWorld` (line 5). + +Inside our contract, we define a _state variable_ `greet` that holds the string `"Hello World!"` (line 6). + +Solidity is a _statically typed_ language, which means that you need to specify the type of the variable when you declare it. In this case, `greet` is a `string`. + +We also define the _visibility_ of the variable, which specifies from where you can access it. In this case, it's a `public` variable that you can access from inside and outside the contract. + +Don't worry if you didn't understand some concepts like _visibility_, _data types_, or _state variables_. We will look into them in the following sections. + +To help you understand the code, we will link in all following sections to video tutorials from the creator of the Solidity by Example contracts. + +Watch a video tutorial on Basic Syntax. + +## ⭐️ Assignment + +1. Delete the HelloWorld contract and its content. +2. Create a new contract named "MyContract". +3. The contract should have a public state variable called "name" of the type string. +4. Assign the value "Alice" to your new variable. diff --git a/locales/ja/SolidityBeginnerCourse/config.yml b/locales/ja/SolidityBeginnerCourse/config.yml new file mode 100644 index 000000000..a729093d8 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/config.yml @@ -0,0 +1,65 @@ +--- +id: soliditybeginner +name: Solidity Beginner Course +summary: Solidity Beginner Course based on the popular https://solidity-by-example.org/ contracts. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Basic Syntax + path: basic-syntax + - + name: 3. Primitive Data Types + path: primitive-data-types + - + name: 4. Variables + path: variables + - + name: 5.1 Functions - Reading and Writing to a State Variable + path: functions-reading-and-writing + - + name: 5.2 Functions - View and Pure + path: functions-view-and-pure + - + name: 5.3 Functions - Modifiers and Constructors + path: functions-modifiers-and-constructors + - + name: 5.4 Functions - Inputs and Outputs + path: functions-inputs-and-outputs + - + name: 6. Visibility + path: visibility + - + name: 7.1 Control Flow - If/Else + path: control-flow-if-else + - + name: 7.2 Control Flow - Loops + path: control-flow-loops + - + name: 8.1 Data Structures - Arrays + path: data-structures-arrays + - + name: 8.2 Data Structures - Mappings + path: data-structures-mappings + - + name: 8.3 Data Structures - Structs + path: data-structures-structs + - + name: 8.4 Data Structures - Enums + path: data-structures-enums + - + name: 9. Data Locations + path: data-locations + - + name: 10.1 Transactions - Ether and Wei + path: transactions-ether-and-wei + - + name: 10.2 Transactions - Gas and Gas Price + path: transactions-gas-and-gas-price + - + name: 10.3 Transactions - Sending Ether + path: transactions-sending-ether diff --git a/locales/ja/SolidityBeginnerCourse/control-flow-if-else/ifElse.md b/locales/ja/SolidityBeginnerCourse/control-flow-if-else/ifElse.md new file mode 100644 index 000000000..634e27689 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/control-flow-if-else/ifElse.md @@ -0,0 +1,33 @@ +Solidity supports different control flow statements that determine which parts of the contract will be executed. The conditional _If/Else statement_ enables contracts to make decisions depending on whether boolean conditions are either `true` or `false`. + +Solidity differentiates between three different If/Else statements: `if`, `else`, and `else if`. + +### if + +The `if` statement is the most basic statement that allows the contract to perform an action based on a boolean expression. + +In this contract’s `foo` function (line 5) the if statement (line 6) checks if `x` is smaller than `10`. If the statement is true, the function returns `0`. + +### else + +The `else` statement enables our contract to perform an action if conditions are not met. + +In this contract, the `foo` function uses the `else` statement (line 10) to return `2` if none of the other conditions are met. + +### else if + +With the `else if` statement we can combine several conditions. + +If the first condition (line 6) of the foo function is not met, but the condition of the `else if` statement (line 8) becomes true, the function returns `1`. + +Watch a video tutorial on the If/Else statement. + +## ⭐️ Assignment + +Create a new function called `evenCheck` in the `IfElse` contract: + +- That takes in a `uint` as an argument. +- The function returns `true` if the argument is even, and `false` if the argument is odd. +- Use a ternery operator to return the result of the `evenCheck` function. + +Tip: The modulo (%) operator produces the remainder of an integer division. diff --git a/locales/ja/SolidityBeginnerCourse/control-flow-loops/loops.md b/locales/ja/SolidityBeginnerCourse/control-flow-loops/loops.md new file mode 100644 index 000000000..ffaa30650 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/control-flow-loops/loops.md @@ -0,0 +1,32 @@ +Solidity supports iterative control flow statements that allow contracts to execute code repeatedly. + +Solidity differentiates between three types of loops: `for`, `while`, and `do while` loops. + +### for + +Generally, `for` loops (line 7) are great if you know how many times you want to execute a certain block of code. In solidity, you should specify this amount to avoid transactions running out of gas and failing if the amount of iterations is too high. + +### while + +If you don’t know how many times you want to execute the code but want to break the loop based on a condition, you can use a `while` loop (line 20). +Loops are seldom used in Solidity since transactions might run out of gas and fail if there is no limit to the number of iterations that can occur. + +### do while + +The `do while` loop is a special kind of while loop where you can ensure the code is executed at least once, before checking on the condition. + +### continue + +The `continue` statement is used to skip the remaining code block and start the next iteration of the loop. In this contract, the `continue` statement (line 10) will prevent the second if statement (line 12) from being executed. + +### break + +The `break` statement is used to exit a loop. In this contract, the break statement (line 14) will cause the for loop to be terminated after the sixth iteration. + +Watch a video tutorial on Loop statements. + +## ⭐️ Assignment + +1. Create a public `uint` state variable called count in the `Loop` contract. +2. At the end of the for loop, increment the count variable by 1. +3. Try to get the count variable to be equal to 9, but make sure you don’t edit the `break` statement. diff --git a/locales/ja/SolidityBeginnerCourse/data-locations/dataLocations.md b/locales/ja/SolidityBeginnerCourse/data-locations/dataLocations.md new file mode 100644 index 000000000..881bf8ffc --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/data-locations/dataLocations.md @@ -0,0 +1,54 @@ +The values of variables in Solidity can be stored in different data locations: _memory_, _storage_, and _calldata_. + +As we have discussed before, variables of the value type store an independent copy of a value, while variables of the reference type (array, struct, mapping) only store the location (reference) of the value. + +If we use a reference type in a function, we have to specify in which data location their values are stored. The price for the execution of the function is influenced by the data location; creating copies from reference types costs gas. + +### Storage + +Values stored in _storage_ are stored permanently on the blockchain and, therefore, are expensive to use. + +In this contract, the state variables `arr`, `map`, and `myStructs` (lines 5, 6, and 10) are stored in storage. State variables are always stored in storage. + +### Memory + +Values stored in _memory_ are only stored temporarily and are not on the blockchain. They only exist during the execution of an external function and are discarded afterward. They are cheaper to use than values stored in _storage_. + +In this contract, the local variable `myMemstruct` (line 19), as well as the parameter `_arr` (line 31), are stored in memory. Function parameters need to have the data location _memory_ or _calldata_. + +### Calldata + +_Calldata_ stores function arguments. Like _memory_, _calldata_ is only stored temporarily during the execution of an external function. In contrast to values stored in _memory_, values stored in _calldata_ can not be changed. Calldata is the cheapest data location to use. + +In this contract, the parameter `_arr` (line 35) has the data location _calldata_. If we wanted to assign a new value to the first element of the array `_arr`, we could do that in the `function g` (line 31) but not in the `function h` (line 35). This is because `_arr` in `function g `has the data location _memory_ and _function h_ has the data location `calldata`. + +## Assignments + +### Memory to memory + +Assignments from _memory_ to _memory_ create references instead of copies. If you change the value in one variable, the value of all other variables that reference the same data will be changed. + +If we were to create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myMemStruct` (line 19), any change to `myMemStruct2` would also change the value of `myMemStruct`. + +### Storage to local storage + +Assignments from _storage_ to _local storage_ also create references, not copies. + +If we change the value of the local variable `myStruct` (line 17), the value of our state variable `myStructs` (line 10) changes as well. + +## Storage and memory/calldata + +Assignments between _storage_ and _memory_ (or _calldata_) create independent copies, not references. + +If we were to create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myStruct`, changes in `myMemStruct3` would not affect the values stored in the mapping `myStructs` (line 10). + +As we said in the beginning, when creating contracts we have to be mindful of gas costs. Therefore, we need to use data locations that require the lowest amount of gas possible. + +## ⭐️ Assignment + +1. Change the value of the `myStruct` member `foo`, inside the `function f`, to 4. +2. Create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` and assign it the value of `myMemStruct`. Change the value of the `myMemStruct2` member `foo` to 1. +3. Create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` and assign it the value of `myStruct`. Change the value of the `myMemStruct3` member `foo` to 3. +4. Let the function f return `myStruct`, `myMemStruct2`, and `myMemStruct3`. + +Tip: Make sure to create the correct return types for the function `f`. diff --git a/locales/ja/SolidityBeginnerCourse/data-structures-arrays/arrays.md b/locales/ja/SolidityBeginnerCourse/data-structures-arrays/arrays.md new file mode 100644 index 000000000..19af3de49 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/data-structures-arrays/arrays.md @@ -0,0 +1,44 @@ +In the next sections, we will look into the data structures that we can use to organize and store our data in Solidity. + +_Arrays_, _mappings_ and _structs_ are all _reference types_. Unlike _value types_ (e.g. _booleans_ or _integers_) reference types don't store their value directly. Instead, they store the location where the value is being stored. Multiple reference type variables could reference the same location, and a change in one variable would affect the others, therefore they need to be handled carefully. + +In Solidity, an array stores an ordered list of values of the same type that are indexed numerically. + +There are two types of arrays, compile-time _fixed-size_ and _dynamic arrays_. For fixed-size arrays, we need to declare the size of the array before it is compiled. The size of dynamic arrays can be changed after the contract has been compiled. + +### Declaring arrays + +We declare a fixed-size array by providing its type, array size (as an integer in square brackets), visibility, and name (line 9). + +We declare a dynamic array in the same manner. However, we don’t provide an array size and leave the brackets empty (line 6). + +### Initializing arrays + +We can initialize the elements of an array all at once (line 7), or initiate new elements one by one (arr[0] = 1;). If we declare an array, we automatically initialize its elements with the default value 0 (line 9). + +### Accessing array elements + +We access elements inside an array by providing the name of the array and the index in brackets (line 12). + +### Adding array elements + +Using the `push()` member function, we add an element to the end of a dynamic array (line 25). + +### Removing array elements + +Using the `pop()` member function, we delete the last element of a dynamic array (line 31). + +We can use the `delete` operator to remove an element with a specific index from an array (line 42). +When we remove an element with the `delete` operator all other elements stay the same, which means that the length of the array will stay the same. This will create a gap in our array. +If the order of the array is not important, then we can move the last element of the array to the place of the deleted element (line 46), or use a mapping. A mapping might be a better choice if we plan to remove elements in our data structure. + +### Array length + +Using the length member, we can read the number of elements that are stored in an array (line 35). + +Watch a video tutorial on Arrays. + +## ⭐️ Assignment + +1. Initialize a public fixed-sized array called `arr3` with the values 0, 1, 2. Make the size as small as possible. +2. Change the `getArr()` function to return the value of `arr3`. diff --git a/locales/ja/SolidityBeginnerCourse/data-structures-enums/enums.md b/locales/ja/SolidityBeginnerCourse/data-structures-enums/enums.md new file mode 100644 index 000000000..40411db67 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/data-structures-enums/enums.md @@ -0,0 +1,33 @@ +In Solidity _enums_ are custom data types consisting of a limited set of constant values. We use enums when our variables should only get assigned a value from a predefined set of values. + +In this contract, the state variable `status` can get assigned a value from the limited set of provided values of the enum `Status` representing the various states of a shipping status. + +### Defining enums + +We define an enum with the enum keyword, followed by the name of the custom type we want to create (line 6). Inside the curly braces, we define all available members of the enum. + +### Initializing an enum variable + +We can initialize a new variable of an enum type by providing the name of the enum, the visibility, and the name of the variable (line 16). Upon its initialization, the variable will be assigned the value of the first member of the enum, in this case, Pending (line 7). + +Even though enum members are named when you define them, they are stored as unsigned integers, not strings. They are numbered in the order that they were defined, the first member starting at 0. The initial value of status, in this case, is 0. + +### Accessing an enum value + +To access the enum value of a variable, we simply need to provide the name of the variable that is storing the value (line 25). + +### Updating an enum value + +We can update the enum value of a variable by assigning it the `uint` representing the enum member (line 30). Shipped would be 1 in this example. Another way to update the value is using the dot operator by providing the name of the enum and its member (line 35). + +### Removing an enum value + +We can use the delete operator to delete the enum value of the variable, which means as for arrays and mappings, to set the default value to 0. + +Watch a video tutorial on Enums. + +## ⭐️ Assignment + +1. Define an enum type called `Size` with the members `S`, `M`, and `L`. +2. Initialize the variable `sizes` of the enum type `Size`. +3. Create a getter function `getSize()` that returns the value of the variable `sizes`. diff --git a/locales/ja/SolidityBeginnerCourse/data-structures-mappings/mappings.md b/locales/ja/SolidityBeginnerCourse/data-structures-mappings/mappings.md new file mode 100644 index 000000000..72fc4acb4 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/data-structures-mappings/mappings.md @@ -0,0 +1,37 @@ +In Solidity, _mappings_ are a collection of key types and corresponding value type pairs. + +The biggest difference between a mapping and an array is that you can't iterate over mappings. If we don't know a key we won't be able to access its value. If we need to know all of our data or iterate over it, we should use an array. + +If we want to retrieve a value based on a known key we can use a mapping (e.g. addresses are often used as keys). Looking up values with a mapping is easier and cheaper than iterating over arrays. If arrays become too large, the gas cost of iterating over it could become too high and cause the transaction to fail. + +We could also store the keys of a mapping in an array that we can iterate over. + +### Creating mappings + +Mappings are declared with the syntax `mapping(KeyType => ValueType) VariableName`. +The key type can be any built-in value type or any contract, but not a reference type. The value type can be of any type. + +In this contract, we are creating the public mapping `myMap` (line 6) that associates the key type `address` with the value type `uint`. + +### Accessing values + +The syntax for interacting with key-value pairs of mappings is similar to that of arrays. +To find the value associated with a specific key, we provide the name of the mapping and the key in brackets (line 11). + +In contrast to arrays, we won't get an error if we try to access the value of a key whose value has not been set yet. When we create a mapping, every possible key is mapped to the default value 0. + +### Setting values + +We set a new value for a key by providing the mapping’s name and key in brackets and assigning it a new value (line 16). + +### Removing values + +We can use the delete operator to delete a value associated with a key, which will set it to the default value of 0. As we have seen in the arrays section. + +Watch a video tutorial on Mappings. + +## ⭐️ Assignment + +1. Create a public mapping `balances` that associates the key type `address` with the value type `uint`. +2. Change the functions `get` and `remove` to work with the mapping balances. +3. Change the function `set` to create a new entry to the balances mapping, where the key is the address of the parameter and the value is the balance associated with the address of the parameter. diff --git a/locales/ja/SolidityBeginnerCourse/data-structures-structs/structs.md b/locales/ja/SolidityBeginnerCourse/data-structures-structs/structs.md new file mode 100644 index 000000000..fba0d93b0 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/data-structures-structs/structs.md @@ -0,0 +1,29 @@ +In Solidity, we can define custom data types in the form of _structs_. Structs are a collection of variables that can consist of different data types. + +### Defining structs + +We define a struct using the `struct` keyword and a name (line 5). Inside curly braces, we can define our struct’s members, which consist of the variable names and their data types. + +### Initializing structs + +There are different ways to initialize a struct. + +Positional parameters: We can provide the name of the struct and the values of its members as parameters in parentheses (line 16). + +Key-value mapping: We provide the name of the struct and the keys and values as a mapping inside curly braces (line 19). + +Initialize and update a struct: We initialize an empty struct first and then update its member by assigning it a new value (line 23). + +### Accessing structs + +To access a member of a struct we can use the dot operator (line 33). + +### Updating structs + +To update a structs’ member we also use the dot operator and assign it a new value (lines 39 and 45). + +Watch a video tutorial on Structs. + +## ⭐️ Assignment + +Create a function `remove` that takes a `uint` as a parameter and deletes a struct member with the given index in the `todos` mapping. diff --git a/locales/ja/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md b/locales/ja/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md new file mode 100644 index 000000000..d0e628f6b --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md @@ -0,0 +1,37 @@ +In this section, we will learn more about the inputs and outputs of functions. + +### Multiple named Outputs + +Functions can return multiple values that can be named and assigned to their name. + +The `returnMany` function (line 6) shows how to return multiple values. +You will often return multiple values. It could be a function that collects outputs of various functions and returns them in a single function call for example. + +The `named` function (line 19) shows how to name return values. +Naming return values helps with the readability of your contracts. Named return values make it easier to keep track of the values and the order in which they are returned. You can also assign values to a name. + +The `assigned` function (line 33) shows how to assign values to a name. +When you assign values to a name you can omit (leave out) the return statement and return them individually. + +### Deconstructing Assignments + +You can use deconstructing assignments to unpack values into distinct variables. + +The `destructingAssigments` function (line 49) assigns the values of the `returnMany` function to the new local variables `i`, `b`, and `j` (line 60). + +### Input and Output restrictions + +There are a few restrictions and best practices for the input and output parameters of contract functions. + +"_[Mappings] cannot be used as parameters or return parameters of contract functions that are publicly visible._" +From the Solidity documentation. + +Arrays can be used as parameters, as shown in the function `arrayInput` (line 71). Arrays can also be used as return parameters as shown in the function `arrayOutput` (line 76). + +You have to be cautious with arrays of arbitrary size because of their gas consumption. While a function using very large arrays as inputs might fail when the gas costs are too high, a function using a smaller array might still be able to execute. + +Watch a video tutorial on Function Outputs. + +## ⭐️ Assignment + +Create a new function called `returnTwo` that returns the values `-2` and `true` without using a return statement. diff --git a/locales/ja/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md b/locales/ja/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md new file mode 100644 index 000000000..d707a987b --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md @@ -0,0 +1,39 @@ +In this section, we will learn how to modify the behavior of a function and how to run contract initialization code. + +### Function Modifier + +_Function Modifiers_ are used to change the behavior of a function. For example, they often check for a condition prior to executing a function to restrict access or validate inputs. + +This first part of this contract is about changing ownership of a contract. Ownership in this contract is expressed by the value of the state variable `owner` that is of the type `address` (line 7). + +The function `changeOwner` (line 33) can change this ownership. It takes an input parameter of the type `address` and assigns its value to the state variable `owner`. + +However, this function cannot simply be executed under all conditions; it has two modifiers, `onlyOwner` and `validAddress`. + +Let's look at `onlyOwner` first (line 18). +Function modifiers are defined with the `modifier` keyword and a unique name; they can also have parameters. + +The underscore `_` (line 23) is used inside modifiers to represent the rest of the code that will be executed in the body of the modified function. +The code you place before the underscore in the modifier will be executed before the code in the body of the modified function. The code after the underscore will be executed after the code in the body of the modified function. + +In this case, the `require` function (line 19) checks if the address executing the contract is the same as the value stored in the variable `owner`. If it is, the rest of the code will be executed, otherwise it will throw an error. + +You can learn more about `assert` and `require` in the Solidity documentation, they are used to check for conditions and throw errors if they are not met. + +The `validAddress` modifier (line 28) has a parameter of type `address` and checks if the provided address is valid. If it is, it continues to execute the code. + +### Constructor + +A constructor function is executed upon the creation of a contract. You can use it to run contract initialization code. The constructor can have parameters and is especially useful when you don't know certain initialization values before the deployment of the contract. + +You declare a constructor using the `constructor` keyword. The constructor in this contract (line 11) sets the initial value of the owner variable upon the creation of the contract. + +Watch a video tutorial on Function Modifiers. + +## ⭐️ Assignment + +1. Create a new function, `increaseX` in the contract. The function should take an input parameter of type `uint` and increase the value of the variable `x` by the value of the input parameter. +2. Make sure that x can only be increased. +3. The body of the function `increaseX` should be empty. + +Tip: Use modifiers. diff --git a/locales/ja/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md b/locales/ja/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md new file mode 100644 index 000000000..3670c03e2 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md @@ -0,0 +1,23 @@ +This section will give a short introduction to functions and teach you how to use them to read from and write to a state variable. + +As in other languages, we use functions in Solidity to create modular, reusable code. However, Solidity functions have some particularities. + +Solidity functions can be split into two types: + +1. Functions that modify the state of the blockchain, like writing to a state variable. In this contract, the `set` function (line 9) changes the state variable `num`. +2. Functions that don't modify the state of the blockchain. These functions are marked `view` or `pure`. For example, in this contract, the `get` function (line 14) marked `view` that only returns `num` does not change the state. + +To define a function, use the `function` keyword followed by a unique name. + +If the function takes inputs like our `set` function (line 9), you must specify the parameter types and names. A common convention is to use an underscore as a prefix for the parameter name to distinguish them from state variables. + +You can then set the visibility of a function and declare them `view` or `pure` as we do for the `get` function if they don't modify the state. Our `get` function also returns values, so we have to specify the return types. In this case, it's a `uint` since the state variable `num` that the function returns is a `uint`. + +We will explore the particularities of Solidity functions in more detail in the following sections. + +Watch a video tutorial on Functions. + +## ⭐️ Assignment + +1. Create a public state variable called `b` that is of type `bool` and initialize it to `true`. +2. Create a public function called `get_b` that returns the value of `b`. diff --git a/locales/ja/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md b/locales/ja/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md new file mode 100644 index 000000000..b846c7d99 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md @@ -0,0 +1,44 @@ +This section will look into the types of functions that don't modify the state of the blockchain: _view_ and _pure_ functions. + +### View Functions + +_View functions_ promise to not modify the state. + +"The following statements are considered modifying the state: + +1. Writing to state variables. +2. Emitting events. +3. Creating other contracts. +4. Using selfdestruct. +5. Sending Ether via calls. +6. Calling any function not marked view or pure. +7. Using low-level calls. +8. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a view function using the keyword `view`. In this contract, `addToX` (line 8) is a view function. This function takes the parameter `y` and returns the sum of the parameter and the state variable `x`. It reads `x` but does not modify it. + +### Pure functions + +_Pure functions_ promise to neither modify nor to read the state. + +"In addition to the list of state modifying statements explained above, the following are considered reading from the state: + +1. Reading from state variables. +2. Accessing `address(this).balance` or `
.balance`. +3. Accessing any of the members of block, tx, msg (with the exception of `msg.sig` and `msg.data`). +4. Calling any function not marked pure. +5. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a pure function using the keyword `pure`. In this contract, `add` (line 13) is a pure function. This function takes the parameters `i` and `j`, and returns the sum of them. It neither reads nor modifies the state variable `x`. + +In Solidity development, you need to optimise your code for saving computation cost (gas cost). Declaring functions view and pure can save gas cost and make the code more readable and easier to maintain. Pure functions don't have any side effects and will always return the same result if you pass the same arguments. + +Watch a video tutorial on View and Pure Functions. + +## ⭐️ Assignment + +Create a function called `addToX2` that takes the parameter `y` and updates the state variable `x` with the sum of the parameter and the state variable `x`. diff --git a/locales/ja/SolidityBeginnerCourse/introduction/introduction.md b/locales/ja/SolidityBeginnerCourse/introduction/introduction.md new file mode 100644 index 000000000..cc821a46a --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/introduction/introduction.md @@ -0,0 +1,32 @@ +Welcome to this interactive Solidity course for beginners. + +In this first section, we will give you a short preview of the concepts we will cover in this course, look at an example smart contract, and show you how you can interact with this contract in the Remix IDE. + +This contract is a counter contract that has the functionality to increase, decrease, and return the state of a counter variable. + +If we look at the top of the contract, we can see some information about the contract like the license (line 1), the Solidity version (line 2), as well as the keyword `contract` and it's name, `Counter` (line 4). We will cover these concepts in the next section about the **Basic Syntax**. + +With `uint public count` (line 5) we declare a state variable of the type `uint` with the visibility `public`. We will cover these concepts in our sections about **Variables**, **Primitive Data Types**, and **Visibility**. + +We then create a `get` function (line 8) that is defined with the `view` keyword and returns a `uint` type. Specifically, it returns the `count` variable. This contract has two more functions, an `inc` (line 13) and `dec` (line 18) function that increases or decreases our count variable. +We will talk about these concepts in our sections about **Functions - Reading and Writing to a State Variable** and **Functions - View and pure**. + +## Compile and Deploy through Remix + +**GIF** Interacting with the contract: Compile and deploy contract + +1. We can compile your `Counter` contract in the "Solidity compiler" module of the Remix IDE. + +2. In the "Deploy & run transactions" module, we select our contract "Counter" in the contract input field and click on the "Deploy" button. + +3. We expand the token contract functions in the IDE, and test its `get`, `inc`, and `dec` functions. + +## ⭐️ Assignment + +Throughout this course, we will give you assignments to test and consolidate your newly acquired knowledge. + +Your first assignment is to: + +1. Compile this contract. +2. Deploy it to the Remix VM. +3. Interact with your contract. diff --git a/locales/ja/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md b/locales/ja/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md new file mode 100644 index 000000000..9ea6b8626 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md @@ -0,0 +1,33 @@ +In this section, we will show you Solidity’s primitive data types, how to declare them, and their characteristics. + +### bool + +You can declare data a boolean type by using the keyword ‘bool’. Booleans can either have the value `true` or `false`. + +### uint + +We use the keywords `uint` and `uint8` to `uint256` to declare an _unsigned integer type_ (they don’t have a sign, unlike -12, for example). Uints are integers that are positive or zero and range from 8 bits to 256 bits. The type `uint` is the same as `uint256`. + +### int + +We use the keywords `int` and `int8` to `int256` to declare an integer type. Integers can be positive, negative, or zero and range from 8 bits to 256 bits. The type `int` is the same as `int256`. + +### address + +Variables of the type `address` hold a 20-byte value, which is the size of an Ethereum address. There is also a special kind of Ethereum address, `address payable`, which can receive ether from the contract. + +All these data types have default values, as shown in the contract (line 29). + +You can learn more about these data types as well as _Fixed Point Numbers_, _Byte Arrays_, _Strings_, and more in the Solidity documentation. + +Later in the course, we will look at data structures like **Mappings**, **Arrays**, **Enums**, and **Structs**. + +Watch a video tutorial on Primitive Data Types. + +## ⭐️ Assignment + +1. Create a new variable `newAddr` that is a `public` `address` and give it a value that is not the same as the available variable `addr`. +2. Create a `public` variable called `neg` that is a negative number, decide upon the type. +3. Create a new variable, `newU` that has the smallest `uint` size type and the smallest `uint` value and is `public`. + +Tip: Look at the other address in the contract or search the internet for an Ethereum address. diff --git a/locales/ja/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md b/locales/ja/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md new file mode 100644 index 000000000..57208c555 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md @@ -0,0 +1,26 @@ +_Ether_ (ETH) is a cryptocurrency. _Ether_ is also used to pay fees for using the Ethereum network, like making transactions in the form of sending _Ether_ to an address or interacting with an Ethereum application. + +### Ether Units + +To specify a unit of _Ether_, we can add the suffixes `wei`, `gwei`, or `ether` to a literal number. + +#### `wei` + +_Wei_ is the smallest subunit of _Ether_, named after the cryptographer [Wei Dai](https://en.wikipedia.org/wiki/Wei_Dai). _Ether_ numbers without a suffix are treated as `wei` (line 7). + +#### `gwei` + +One `gwei` (giga-wei) is equal to 1,000,000,000 (10^9) `wei`. + +#### `ether` + +One `ether` is equal to 1,000,000,000,000,000,000 (10^18) `wei` (line 11). + +Watch a video tutorial on Ether and Wei. + +## ⭐️ Assignment + +1. Create a `public` `uint` called `oneGWei` and set it to 1 `gwei`. +2. Create a `public` `bool` called `isOneGWei` and set it to the result of a comparison operation between 1 gwei and 10^9. + +Tip: Look at how this is written for `gwei` and `ether` in the contract. diff --git a/locales/ja/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md b/locales/ja/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md new file mode 100644 index 000000000..bbc25575c --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md @@ -0,0 +1,29 @@ +As we have seen in the previous section, executing code via transactions on the Ethereum Network costs transaction fees in the form of Ether. The amount of fees that have to be paid to execute a transaction depends on the amount of _gas_ that the execution of the transaction costs. + +### Gas + +_Gas_ is the unit that measures the amount of computational effort that is required to execute a specific operation on the Ethereum network. + +### Gas price + +The _gas_ that fuels Ethereum is sometimes compared to the gas that fuels a car. The amount of gas your car consumes is mostly the same, but the price you pay for gas depends on the market. + +Similarly, the amount of _gas_ that a transaction requires is always the same for the same computational work that is associated with it. However the price that the sender of the transaction is willing to pay for the _gas_ is up to them. Transactions with higher _gas prices_ are going through faster; transactions with very low _gas prices_ might not go through at all. + +When sending a transaction, the sender has to pay the _gas_ fee (gas_price \* gas) upon execution of the transaction. If _gas_ is left over after the execution is completed, the sender gets refunded. + +_Gas_ prices are denoted in gwei. + +### Gas limit + +When sending a transaction, the sender specifies the maximum amount of gas that they are willing to pay for. If they set the limit too low, their transaction can run out of _gas_ before being completed, reverting any changes being made. In this case, the _gas_ was consumed and can’t be refunded. + +Learn more about _gas_ on ethereum.org. + +Watch a video tutorial on Gas and Gas Price. + +## ⭐️ Assignment + +Create a new `public` state variable in the `Gas` contract called `cost` of the type `uint`. Store the value of the gas cost for deploying the contract in the new variable, including the cost for the value you are storing. + +Tip: You can check in the Remix terminal the details of a transaction, including the gas cost. You can also use the Remix plugin _Gas Profiler_ to check for the gas cost of transactions. diff --git a/locales/ja/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md b/locales/ja/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md new file mode 100644 index 000000000..58fb4c5a6 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md @@ -0,0 +1,86 @@ +In this section, we will learn how a contract can send and receive Ether. + +### Sending Ether + +We have three different options to transfer Ether: `transfer()`, `send()` and `call()`. + +#### **transfer** + +`
.transfer(uint256 amount)` + +- `transfer()` throws an exception on failure +- Forwards a fixed 2300 gas stipend + +An example of `transfer()` can be seen in the `SendEther` contract (line 35). +**`Transfer()` is not recommended to be used anymore.** + +#### **send** + +`
.send(uint256 amount) returns (bool)` + +- `send()` returns false on failure +- Forwards a fixed 2300 gas stipend + +An example of `send()` can be seen in the `SendEther` contract (line 41). +**`Send()` is not recommended to be used anymore.** + +#### **call** + +`
.call(bytes memory) returns (bool, bytes memory)` + +- `call()` returns false on failure +- Forwards the maximum amount of gas, but this is adjustable + +An example of `call()` can be seen in the `SendEther` contract (line 48). +`Call()` is currently recommended if you are transfering Ether. + +The reason `transfer()` and `send()` were introduced was to guard against _reentry attacks_ by limiting the forwarded gas to 2300, which would be insufficient to make a reentrant call that can modify storage. + +As we discussed in the last section, each operation on Ethereum has a specific cost associated with it. Certain operations have become more cost intensive over time, so the gas costs associated with them are also raised. When gas costs for operations are subject to change it is not good to use a hardcoded gas amount like transfer(), and send() do. + +That’s why `call()` instead of `transfer()` is now recommended to send Ether. + +Learn more about the subject in this Consensys blog post. + +### Reentrancy attack + +A _reentrancy attack_ occurs when a function makes an external call to an untrusted contract and the attacker uses the contract to make recursive calls back to the original function before it finishes its execution. Through this method, the attacker can drain funds and manipulate data in unintended ways. + +To guard against a _reentrancy attack_, all state changes should be made before calling an external contract. This is also called the Checks-Effects-Interactions pattern. + +Another way to prevent reentrancy is to use a _Reentrancy Guard_ that checks for such calls and rejects them. You can see an example of this in the contract in our modifier section or a more gas-efficient version on Open Zepplin. + +### Receiving Ether + +If we want to enable a contract to receive Ether without a function being called, we need to create a `receive` function (line 22) or a `fallback` function (line 25); otherwise, the Ether will be rejected, and the contract will throw an exception. + +The `receive` function is executed on calls with empty calldata (e.g. plain Ether transfers via send() or transfer()), while the fallback function is executed on calls with calldata. If no receive function exists but a fallback function does, calls with empty calldata will also use the fallback function. + +### Payable function modifier + +The `payable` function modifier allows a function to receive Ether. + +The `receive` function (line 22) needs to be `payable`. If you delete the `payable` modifier you will get an error from the compiler. If you delete the `payable` modifier from the `fallback` function (line 25) it will compile, but it won’t be able to receive Ether. +The functions `sendViaTransfer`, `sendViaSend`, and `sendViaCall` (lines 33, 38, and 45) also need to be `payable` in order to receive Ether. + +### Payable address + +Solidity makes a distinction between two different flavors of the address data type: address and address payable. + +`address`: Holds a 20-byte value. +`address payable`: Holds a 20-byte value and can receive Ether via its members: transfer and send. + +If you change the parameter type for the functions `sendViaTransfer` and `sendViaSend` (line 33 and 38) from `payable address` to `address`, you won’t be able to use `transfer()` (line 35) or `send()` (line 41). + +Watch a video tutorial on Sending Ether. + +## ⭐️ Assignment + +Build a charity contract that receives Ether that can be withdrawn by a beneficiary. + +1. Create a contract called `Charity`. +2. Add a public state variable called `owner` of the type address. +3. Create a donate function that is public and payable without any parameters or function code. +4. Create a withdraw function that is public and sends the total balance of the contract to the `owner` address. + +Tip: Test your contract by deploying it from one account and then sending Ether to it from another account. Then execute the withdraw function. diff --git a/locales/ja/SolidityBeginnerCourse/variables/variables.md b/locales/ja/SolidityBeginnerCourse/variables/variables.md new file mode 100644 index 000000000..dfb35b382 --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/variables/variables.md @@ -0,0 +1,29 @@ +There are three different types of variables in Solidity: _State Variables_, _Local Variables_, and _Global Variables_. + +## 1. State Variables + +_State Variables_ are stored in the contract _storage_ and thereby on the blockchain. They are declared inside the contract but outside the function. +This contract has two state variables, the string `text`(line 6) and the uint `num` (line 7). + +## 2. Local Variables + +_Local Variables_ are stored in the _memory_ and their values are only accessible within the function they are defined in. Local Variables are not stored on the blockchain. +In this contract, the uint `i` (line 11) is a local variable. + +## 3. Global Variables + +_Global Variables_, also called _Special Variables_, exist in the global namespace. They don't need to be declared but can be accessed from within your contract. +Global Variables are used to retrieve information about the blockchain, particular addresses, contracts, and transactions. + +In this example, we use `block.timestamp` (line 14) to get a Unix timestamp of when the current block was generated and `msg.sender` (line 15) to get the caller of the contract function’s address. + +A list of all Global Variables is available in the Solidity documentation. + +Watch video tutorials on State Variables, Local Variables, and Global Variables. + +## ⭐️ Assignment + +1. Create a new public state variable called `blockNumber`. +2. Inside the function `doSomething()`, assign the value of the current block number to the state variable `blockNumber`. + +Tip: Look into the global variables section of the Solidity documentation to find out how to read the current block number. diff --git a/locales/ja/SolidityBeginnerCourse/visibility/visibility.md b/locales/ja/SolidityBeginnerCourse/visibility/visibility.md new file mode 100644 index 000000000..79e4307bf --- /dev/null +++ b/locales/ja/SolidityBeginnerCourse/visibility/visibility.md @@ -0,0 +1,37 @@ +The `visibility` specifier is used to control who has access to functions and state variables. + +There are four types of visibilities: `external`, `public`, `internal`, and `private`. + +They regulate if functions and state variables can be called from inside the contract, from contracts that derive from the contract (child contracts), or from other contracts and transactions. + +### private + +- Can be called from inside the contract + +### internal + +- Can be called from inside the contract +- Can be called from a child contract + +### public + +- Can be called from inside the contract +- Can be called from a child contract +- Can be called from other contracts or transactions + +### external + +- Can be called from other contracts or transactions +- State variables can not be `external` + +In this example, we have two contracts, the `Base` contract (line 4) and the `Child` contract (line 55) which inherits the functions and state variables from the `Base` contract. + +When you uncomment the `testPrivateFunc` (lines 58-60) you get an error because the child contract doesn’t have access to the private function `privateFunc` from the `Base` contract. + +If you compile and deploy the two contracts, you will not be able to call the functions `privateFunc` and `internalFunc` directly. You will only be able to call them via `testPrivateFunc` and `testInternalFunc`. + +Watch a video tutorial on Visibility. + +## ⭐️ Assignment + +Create a new function in the `Child` contract called `testInternalVar` that returns the values of all state variables from the `Base` contract that are possible to return. diff --git a/locales/ja/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md b/locales/ja/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md new file mode 100644 index 000000000..801d8c582 --- /dev/null +++ b/locales/ja/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md @@ -0,0 +1,47 @@ +In this tutorial, we'll explore the Uniswap V3 Swap contract to learn about how single-hop and multi-hop swaps work. + +But first, some Uniswap fundamentals. + +## What is Uniswap? + +Uniswap is a decentralized cryptocurrency exchange. It allows users to exchange tokens without the need for a centralized intermediary. Uniswap is a key player in the decentralized finance (DeFi) space. + +## How does Uniswap work? + +Instead of using an order book like a traditional centralized exchange, Uniswap uses an automated market maker (AMM) model. In Uniswap, the AMM is a smart contract that holds reserves of tokens (Liquidity Pool). Users can trade between tokens in the Liquidity Pool. The price of each token is determined by the ratio of the reserves. + +### Step-by-step example of a Uniswap trade + +1. Alice wants to trade 1 ETH for DAI. +2. Alice sends 1 ETH to the Uniswap smart contract. +3. The Uniswap smart contract calculates the amount of DAI that Alice should receive based on the current exchange rate. +4. The Uniswap smart contract sends the DAI to Alice. +5. The Uniswap smart contract adds the 1 ETH to its reserves. +6. The Uniswap smart contract recalculates the exchange rate based on the new reserves. + +The tokens in the Liquidity Pool are provided by Liquidity Providers. When a Liquidity Provider deposits tokens into a Liquidity Pool, they receive Liquidity Provider Tokens in return. Liquidity Provider Tokens represent a user's share of a Liquidity Pool. + +Users of Uniswap pay a fee for each trade. The fee is paid to the Liquidity Providers in the form of additional Liquidity Provider Tokens. + +## Uniswap Swap Contract + +The Uniswap Swap contract allows users to swap tokens using Uniswap V3. It can do single-hop swaps, which allow users to exchange one token for another directly. It can also do multi-hop swaps, which means that users can exchange one token for another by routing through multiple tokens. Routing in this context means that the swap contract will exchange the token for another token, then exchange that token for another token, and so on until it reaches the desired token. + +## Conclusion + +In this section, we learned about Uniswap, how it works, and how we are going to use it to swap tokens. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is Uniswap? + +1. A centralized exchange protocol. +2. A decentralized exchange protocol that uses an order book. +3. A decentralized exchange protocol that uses an automated market maker (AMM) model. +4. A decentralized exchange protocol that uses an order book and an automated market maker (AMM) model. + +### 2) How does Uniswap determine the price of a token? + +1. The price of a token is determined by the ratio of the reserves. +2. The price of a token is determined by the ratio of the reserves and the number of trades. +3. The price of a token is determined by the ratio of the reserves and the number of Liquidity Providers. diff --git a/locales/ja/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md b/locales/ja/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md new file mode 100644 index 000000000..e5cc248f5 --- /dev/null +++ b/locales/ja/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md @@ -0,0 +1,41 @@ +The entire UniswapSwapExamples contract will only be presented in section 5 of this tutorial. Before then, we'll build up blocks of code. + +This section explores the `ISwapRouter` interface, which defines the functions that can be called on the Uniswap Swap contract. + +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. +Multi-hop swaps allow users to exchange one token for another by routing through multiple tokens. + +Interfaces in Solidity specify functions that must be included in a contract that inherits them. They are useful for declaring what functions be supported and allow for easier integration and interaction between different contracts. + +Structs are used to define custom data types. + +## ISwapRouter Interface + +The ISwapRouter interface defines the functions that can be called on the Uniswap Swap contract. We will need to use this interface to interact with the Uniswap Swap contract and execute swaps. + +On line 5, we define a constant variable called `router` that is of type `ISwapRouter`. We set the value of this variable to the interface instance of a smart contract that is deployed at the address `0xE592427A0AEce92De3Edee1F18E0157C05861564`. This is the address of the Uniswap V3 Swap contract on the Ethereum mainnet. + +On line 9, we define an interface called `ISwapRouter`. This interface defines two functions: `exactInputSingle` and `exactInput`. + +## exactInputSingle + +On line 25, we define a struct called `ExactInputSingleParams`. This struct defines the parameters that are required for our exactInputSingle function on line 21, which will execute a single-hop swap. The struct has the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 fee`**: The fee associated with the swap. +- **`address recipient`**: The address that will receive the output token. +- **`uint deadline`**: A timestamp by which the transaction must be processed, for time-limiting the swap. +- **`uint amountIn`**: The amount of the input token being sent. +- **`uint amountOutMinimum`**: The minimum amount of the output token that the sender is willing to accept, to protect against unfavorable price movements. +- **`uint160 sqrtPriceLimitX96`**: A limit on the price, represented in a specific format, to prevent the swap from occurring at unfavorable prices. + +## exactInput + +On line 25, we define a struct called `ExactInputParams`. This struct defines the parameters that are required for our `exactInput` function on line 33. This function will execute a multi-hop swap. The struct has the following parameters: + +- **`bytes path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address recipient`**: The address receiving the output tokens. +- **`uint deadline`**: Similar to above, a timestamp by which the transaction must be processed. +- **`uint amountIn`**: The amount of the input token. +- **`uint amountOutMinimum`**: The minimum amount of the output token the sender expects to receive. diff --git a/locales/ja/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md b/locales/ja/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md new file mode 100644 index 000000000..f4d70c445 --- /dev/null +++ b/locales/ja/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md @@ -0,0 +1,36 @@ +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. In this section, we will learn how to use the Uniswap V3 Swap contract to execute single-hop swaps. + +## Function Parameters + +On line 8, we define a function called `swapExactInputSingleHop`. This function executes a single-hop swap. It takes the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 poolFee`**: The fee associated with the swap. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +## Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 14. +Then, we approve the Uniswap Swap contract to spend the input token on our behalf, line 15. + +On line 17, we create an instance of the `ExactInputSingleParams` struct. This struct contains the parameters that are required for our `exactInputSingle` function on line 45, which will execute the single-hop swap. We repeat `ISwapRouter.ExactInputSingleParams` two times on that line because we are making an instance of a struct that is defined in an interface. + +## Parameters of the ExactInputSingleParams Struct + +We set the parameters of the struct as follows: + +- **`tokenIn`**: We set this to the `tokenIn` parameter of our function. +- **`tokenOut`**: We set this to the `tokenOut` parameter of our function. +- **`fee`**: We set this to the `poolFee` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. +- **`sqrtPriceLimitX96`**: We set this to 0 because we do not want to specify a limit on the price. + +## Executing the Single-hop Swap + +On line 29, we assign the output of the `exactInputSingle` function to the `amountOut` variable. This function executes the single-hop swap and returns the amount of the output token that was received. diff --git a/locales/ja/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md b/locales/ja/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md new file mode 100644 index 000000000..7883b4718 --- /dev/null +++ b/locales/ja/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md @@ -0,0 +1,30 @@ +In this section, we'll delve into the `swapExactInputMultiHop` function in the `UniswapV3SwapExamples` contract. This function enables more complex token swaps by allowing users to specify a custom path through multiple liquidity pools. + +If for example, a user wants to swap token A for token D, but there is no direct liquidity pool for A and D, the user can specify a path through multiple tokens. For example, the user can swap A for B, then B for C, and finally C for D. This is of course automatically done by the Uniswap V3 Swap contract. + +### Parameters and Return Value + +On line 32, we define a function called `swapExactInputMultiHop`. This function executes a multi-hop swap. It takes the following parameters: + +- **`bytes calldata path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address tokenIn`**: The address of the token being sent. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +### Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 38. +Then, we approve the Uniswap Swap router to spend the input token on our behalf, line 41. + +On line 43, we create an instance of the `ExactInputParams` struct, line 73. This struct contains the parameters that are required for our `exactInput` function on line 81, which will execute the multi-hop swap. + +We set the parameters of the struct as follows: + +- **`path`**: We set this to the `path` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. + +On line 53, we execute the multi-hop swap by calling the `exactInput` function. This function returns the amount of the output token that was received. diff --git a/locales/ja/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md b/locales/ja/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md new file mode 100644 index 000000000..b3cec34e9 --- /dev/null +++ b/locales/ja/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md @@ -0,0 +1,52 @@ +In this section, we'll explore the `IERC20` interface, a standard interface for interacting with ERC-20 tokens and the `IWETH` interface, a standard interface for interacting with wrapped Ether (WETH). Understanding these interfaces is crucial as it is used in the Uniswap V3 Swap contract to handle token transfers and approvals. + +You can find a "Solidity ERC20 Token Course" for beginners in LearnEth to understand the ERC20 token standard in more detail. + +## IERC20 Interface + +On line 80, we define the `IERC20` interface. This interface defines a standard set of functions that ERC-20 tokens must implement. Let's examine the key functions within this interface: + +### 1. totalSupply + +On line 81, we define the `totalSupply` function. This function returns the total supply of the token. + +### 2. balanceOf + +On line 83, we define the `balanceOf` function. This function returns the balance of the specified address. + +### 3. transfer + +On line 85, we define the `transfer` function. This function transfers tokens from the sender to the specified recipient. + +### 4. allowance + +On line 87, we define the `allowance` function. This function returns the amount of tokens that the spender is allowed to spend on behalf of the owner. + +### 5. approve + +On line 89, we define the `approve` function. When called, this function approves a spender to spend the specified amount of tokens on behalf of the sender. + +### 6. transferFrom + +On line 91, we define the `transferFrom` function. This function transfers tokens from the specified sender to the recipient. The function can only be called by the spender if the spender is allowed to spend the specified amount of tokens on behalf of the sender. + +### 7. Events + +On lines 102-103, we define the `Transfer` and `Approval` events. These events are emitted when the `transfer` and `approve` functions are called, respectively. + +## IWETH Interface + +On line 106, we define the `IWETH` interface. This interface extends the `IERC20` interface and defines two additional functions: + +### 1. deposit + +On line 107, we define the `deposit` function. This function deposits ETH into the contract and returns the equivalent amount of WETH. This function is used to wrap ETH into WETH. +We need to wrap ETH into WETH because the Uniswap V3 Swap contract only supports ERC-20 tokens. + +### 2. withdraw + +On line 109, we define the `withdraw` function. This function withdraws the specified amount of WETH from the contract and returns the equivalent amount of ETH. This function is used to unwrap WETH into ETH. + +## Conclusion + +In this tutorial, we explored the Uniswap V3 Swap contract. To get a full sense of how Uniswap works, try making some swaps on the Uniswap DApp and go to the Uniswap docs. diff --git a/locales/ja/Uniswap-Tutorial/README.md b/locales/ja/Uniswap-Tutorial/README.md new file mode 100644 index 000000000..cf66c5582 --- /dev/null +++ b/locales/ja/Uniswap-Tutorial/README.md @@ -0,0 +1,5 @@ +# Uniswap Swap Course + +Review the code of the Uniswap V3 Swap contract for performing token swaps. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ja/Uniswap-Tutorial/config.yml b/locales/ja/Uniswap-Tutorial/config.yml new file mode 100644 index 000000000..f49f02abc --- /dev/null +++ b/locales/ja/Uniswap-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: uniswapSwapCourse +name: Uniswap Swap Course +summary: Go through the Solidity code of the Uniswap V3 Swap contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - Uniswap +steps: + - + name: 1. Introduction + path: 1-introduction-to-uniswap + - + name: 2. Routers, Interfaces, and Structs + path: 2-router-interfaces-and-structs + - + name: 3. Single Hop Swaps + path: 3-single-hop-swaps + - + name: 4. Multi-Hop Swaps + path: 4-multi-hop-swaps + - + name: 5. Erc20 and Weth Interfaces + path: 5-erc20-weth-interfaces diff --git a/locales/ja/Web3Client/1_Using_Web3/Running_a_script.md b/locales/ja/Web3Client/1_Using_Web3/Running_a_script.md new file mode 100644 index 000000000..3b7b23332 --- /dev/null +++ b/locales/ja/Web3Client/1_Using_Web3/Running_a_script.md @@ -0,0 +1,24 @@ +## Querying the Blockchain + +In this tutorial, we'll run a script that queries the blockchain using a JavaScript library. + +This means that instead of using the Remix GUI or a block explorer like Etherscan, we'll use a script in the editor and will run it from the terminal. + +The JS libraries that are used the most for interacting with the blockchain are web3.js & ethers.js. + +Let's begin with a simple web3.js example, queryBlockNum.js. + +The script's call to web3.js is wrapped in a self-executing async function that contains a try/catch block. + +We'll query the current blocknumber with: +`let blockNumber = await web3.eth.getBlockNumber()` + +Note that the object `web3` is injected by Remix. For more info on web3.js, check their docs, https://web3js.readthedocs.io. + +To use web3.js or ethers.js, you need to select the **Injected Web3** or **Web3 Provider** environment in the **Deploy & Run** module. Scripts don't currently work with the JSVM. **If you try, you'll get an error.** + +So for this example choose **Injected Web3** in the Deploy & Run module and have Metamask installed. + +From the terminal, execute `remix.execute()`. This command will execute the current JavaScript file with the line `let blockNumber = await web3.eth.getBlockNumber()`. + +In the console, you should see the current block number of the chain that metamask is connected to. diff --git a/locales/ja/Web3Client/2_Querying_a_Contract/queryContract.md b/locales/ja/Web3Client/2_Querying_a_Contract/queryContract.md new file mode 100644 index 000000000..461c98244 --- /dev/null +++ b/locales/ja/Web3Client/2_Querying_a_Contract/queryContract.md @@ -0,0 +1,23 @@ +Now that we know how to query simple data, let's try a more complex query. + +This is a contract deployed to the mainnet - at this address: https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code + +We are going to query the contract to find the name of it's token. + +The **name** variable is a state variable of the contract. + +To access this **mainnet** contract, we need to do some setup. + +1. Switch to the mainnet in metamask. +2. You'll probably need to refresh Remix. +3. As a result of the refresh, you may need to reload this tutorial too. +4. Go to Deploy & Run and switch to **Injected Web3**. + +**Using Web3** +In the script, queryContract.js, we need to instantiate a new instance of web3.eth.Contract object. For this we need to grab the contract's ABI and its address. The source code & ABI is available in etherscan because the contract's developer intentionally published it. + +In etherscan, we can see that its name is **TetherToken**. Scrolling down to the TetherToken contract in the source code section of etherscan, we can see the state variables for the contract - the first of which is named **name**. + +There are a few syntactic hoops to jump through to return the value of the state variable. + +- To call the autogenerated getter function of the public state variable, you need to both treat the variable as a function (by adding parentheses) and also to tack on a call(). diff --git a/locales/ja/Web3Client/README.md b/locales/ja/Web3Client/README.md new file mode 100644 index 000000000..a319f312f --- /dev/null +++ b/locales/ja/Web3Client/README.md @@ -0,0 +1 @@ +This workshop is about using the web3.js to interact with a contract and more generally to the blockchain. diff --git a/locales/ja/Web3Client/config.yml b/locales/ja/Web3Client/config.yml new file mode 100644 index 000000000..07cb1760c --- /dev/null +++ b/locales/ja/Web3Client/config.yml @@ -0,0 +1,9 @@ +--- +id: useofweb3js +name: Basic use of web3.js +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 2 +tags: + - JS + - Remix + - Web3 diff --git a/locales/ko/Basics/README.md b/locales/ko/Basics/README.md new file mode 100644 index 000000000..6b065b830 --- /dev/null +++ b/locales/ko/Basics/README.md @@ -0,0 +1,3 @@ +## Loading, Compiling, Deploying + +This beginner level tutorial introduces Remix's interface and concepts used in Ethereum. diff --git a/locales/ko/Basics/config.yml b/locales/ko/Basics/config.yml new file mode 100644 index 000000000..8c160b545 --- /dev/null +++ b/locales/ko/Basics/config.yml @@ -0,0 +1,26 @@ +--- +id: basics +name: Basics of Remix +summary: A typical workflow in Remix +level: 1 +tags: + - Remix +steps: + - + name: Intro to the Interface + path: interface_introduction + - + name: Intro to Workspaces + path: workspaces + - + name: Loading & Compiling + path: load_and_compile + - + name: Deploying to the Remix VM + path: deploy_to_the_remixvm + - + name: Interacting with Functions + path: interacting + - + name: Deploying to Public Networks + path: deploy_injected diff --git a/locales/ko/Basics/deploy_injected/README.md b/locales/ko/Basics/deploy_injected/README.md new file mode 100644 index 000000000..172396527 --- /dev/null +++ b/locales/ko/Basics/deploy_injected/README.md @@ -0,0 +1,21 @@ +1. If you don't have a browser wallet like **MetaMask** download and install one now. + +2. Click the MetaMask icon in your browser. Sign in and choose the Ephemery test network. You might need to update your wallet's settings so that you can see **test networks**. Alternatively, you can go to Remix's Deploy & Run transation module and in the ENVIRONMENT section select Ephemery. + +3. Getting test ETH for public test networks is often annoying. Ephemery is a public network that is refreshed monthly, so getting test ETH should be painless. Here is a link to some Ephemery faucets. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/testnet.png) + +Sepolia is another popular testnet that is not refreshed, so deployments will persist, but Sepolia faucets are more difficult to use. + +In your browser wallet make sure that you have NOT selected mainnet or any network that will cost real ETH. In the Deploy & Run module, below the Environment select box, you'll see a badge with the network's ID and for popular chains, its name. In the case below its Sepolia. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/sepolia.png) + +5. Make sure you see the 2_Owner.sol as a choice in the **CONTRACT** select box, then click the **Deploy** button. + +If the **CONTRACT** select box is empty, you'll need to compile 2_Owner again by making 2_Owner.sol the active file in the **editor** and then go to the **Solidity Compiler** to compile it. + +6. After you hit the `Deploy` button, you'll see the browser wallet popup asking you to pay for the transactions. If you have the appropriate kind of ETH for this chain, approve this transaction. Check the printout in the terminal. Once the block is validated, the **deployed instance** will appear at the bottom of Deploy & Run + +And with that you have finished this tutorial. You now have experience with opening, compiling, deploying and interacting with Smart Contracts in Remix IDE. diff --git a/locales/ko/Basics/deploy_to_the_remixvm/README.md b/locales/ko/Basics/deploy_to_the_remixvm/README.md new file mode 100644 index 000000000..8035d631b --- /dev/null +++ b/locales/ko/Basics/deploy_to_the_remixvm/README.md @@ -0,0 +1,15 @@ +In the previous chapter, we compiled a contract - which is to say the Solidity code has been transformed into little chunks of Ethereum Virtual Machine (EVM) bytecode. + +Now we will put that code on a test blockchain. + +1. Click the Deploy and Run icon ![deploy & run icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_to_the_remixvm/images/run.png "deploy & run icon"). + +2. Select one of the **Remix VM**s from the **Environment** pulldown. + +3. Click the Deploy button (or the transact button in the expanded view). + +4. You have deployed your compiled contract to the Remix VM - a simulated blockchain that is running inside of your browser window. The Remix VM is simple, fast test chain. It is not that realistic because you don't need to approve each transaction. + +5. Check the terminal to see detail of this deployment transaction. + +You can also use Remix to deploy to other public EVM chains. To do this, you'll need to connect to a different **Environment** - like Injected Provider. The Injected Provider connects Remix to browser wallet (like MetaMask or similar). We'll try deploying to a public network at the end of this tutorial. But before we get there, we'll cover how to interact with a deployed contract's functions. diff --git a/locales/ko/Basics/interacting/README.md b/locales/ko/Basics/interacting/README.md new file mode 100644 index 000000000..59ef44200 --- /dev/null +++ b/locales/ko/Basics/interacting/README.md @@ -0,0 +1,19 @@ +## Accessing functions in a deployed contract + +1. When a contract has been successfully deployed, it will appear at the bottom of the Deploy and Run plugin. Open up the contract by clicking the caret - so the caret points down. + ![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/instance.png "deployed contract") + +2. There are 2 functions in this contract. To input the parameters individually, clicking the caret to the right of changeOwner (outlined in red below). In the expanded view, each parameter has its own input box. + +![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/deployed_open2.png "deployed contract") + +If this contract had imported other contracts, then the functions of the imported contracts would also be visible here. At some point, try playing with An ERC20 contract to see all its many functions. + +3. Functions with blue buttons are either **pure** or **view** functions. This means that they are just reading a property or are returning a value. In other words, they aren't saving anything - so they are FREE (they don’t cost gas). Functions with other colors - usually orange (depending on the Remix theme) cost gas because they are saving information. They are creating a **transaction**. + +4. 2_Owner.sol does not have a **payable** function. If it did, the button's color would be red. Payable functions allow you to send Ether to the function. To send ETH with a payable function, you put the amount you want to send in the **value** field towards the top of the Deploy & Run module. + +5. In the Remix VM, you don't need to approve a transaction. When using a more realistic test environment or when using the mainnet - you will need to approve the transactions for them to go through. Approving a transaction costs gas. + +6. Choosing a public network is not done in Remix but in your Browser Wallet. There is a plug icon to the right of the Environment title that links to chainlist.org where you can get the specs of the chain you want to interact with. + ![chainlist](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/chainlist.png "chainlist") diff --git a/locales/ko/Basics/interface_introduction/README.md b/locales/ko/Basics/interface_introduction/README.md new file mode 100644 index 000000000..76c953fbd --- /dev/null +++ b/locales/ko/Basics/interface_introduction/README.md @@ -0,0 +1,15 @@ +## Remix is composed of four panels. + +![Remix layout](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/a-layout1c.png "Remix layout") + +- Most plugins appear in the **Side Panel**. +- Editing code happens in tabs in the **Main Panel**. +- The results of transactions and other actions are visible in the **Terminal**. +- Switching between plugins happens in the **Icons Panel**. +- To make a panel larger, drag its border. + +Try clicking the **Solidity Compiler** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/solidity-icon.png) in the **Icons Panel**. Then click the **Deploy & Run** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/deploy-run.png). Then come back to **LearnEth** by clicking this icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/learneth.png). + +In the **Main Panel** of Remix, make sure you see the **Home** tab. The **Home** tab has lots of useful links. To navigate there, either click the **Home** tab in the **Main Panel** or click the Remix icon ![Remix icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/remix-logo.png "Remix icon") on the top of the icon panel. + +- See all the plugins in the **Plugin Manager**. Click this icon ![plugin manager](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/plugin1.png "Plugin Manager icon") in the lower left corner Remix. diff --git a/locales/ko/Basics/load_and_compile/README.md b/locales/ko/Basics/load_and_compile/README.md new file mode 100644 index 000000000..a666d5d13 --- /dev/null +++ b/locales/ko/Basics/load_and_compile/README.md @@ -0,0 +1,20 @@ +Let's load a file from the File Explorer into the Editor. + +1. In the icon panel, click ![file explorer icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/files1.png "file explorer icon") , the File Explorer's icon. + +2. Make sure you are in the **default_workspace**. + +![default workspace](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/default_workspace_open.png) + +3. Open the contracts folder and click on **2_Owner.sol** in the contracts folder. Click it. The file will appear in a tab in the main panel. + +4. In the icon panel, click the **Solidity Compiler** ![solidity compiler icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/solidity1.png "solidity compiler icon"). The Solidity compiler should now be in the side panel. + +5. Click the compile button. + ![compile 2\_owner](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/compile2owner.png "compile 2_Owner") + +6. Compiling can also be triggered by hitting **CTRL + S**. + +The spinner will turn while the file is compiling. + +**Note:** The spinner also turns when the compiler itself is loading. To choose a **different version of Solidity**, go to the select box at the top of the plugin. diff --git a/locales/ko/Basics/workspaces/README.md b/locales/ko/Basics/workspaces/README.md new file mode 100644 index 000000000..97a47d283 --- /dev/null +++ b/locales/ko/Basics/workspaces/README.md @@ -0,0 +1,23 @@ +## Workspaces help organize your separate projects. + +If this is your first time to Remix, a Workspace named **default_workspace** is loaded in the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/default_workspace.png) + +The **default_workspace** has three Solidity (.sol) files in the contracts folder. Remix has a number of other templates. When you load a template, it goes into a Workspace. To go between Workspaces, use the select box at the top of the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/select-box.png) + +But Workspaces are not only for templates. When cloning a repo into Remix, the files will be put into a Workspace. + +Let's create a new Workspace + +1. At the top of the File Explorer, click the hamburger icon (the 3 horizontal lines). Read through the commands and tools in this menu. + +2. Select **+ Create** (the first choice). + +3. In the modal the comes up, choose one of the templates. + +![hamburger](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/workspaces/images/popup.png) + +Notice that in this popup menu, you can clone a repo. Managing a Git repo happens in the DGit plugin. You can also create Github actions with the three workflow choices in the popup menu. diff --git a/locales/ko/CircomHashChecker/README.md b/locales/ko/CircomHashChecker/README.md new file mode 100644 index 000000000..20391a668 --- /dev/null +++ b/locales/ko/CircomHashChecker/README.md @@ -0,0 +1,14 @@ +Hash Checker Tutorial + +This tutorial guides you through creating and understanding a Hash Checker circuit using Remix-IDE. You'll learn how to generate the circuit using a template, explore the code, perform a trusted setup, generate proofs, and verify them. This tutorial is suitable for beginners familiar with Circom and Zero-Knowledge Proofs. + +Prerequisites + +``` +Basic understanding of Zero-Knowledge Proofs and Circom. +Familiarity with Remix-IDE. +``` + +Estimated Time + +Approximately 1-2 hours. diff --git a/locales/ko/CircomHashChecker/config.yml b/locales/ko/CircomHashChecker/config.yml new file mode 100644 index 000000000..2c2aae80a --- /dev/null +++ b/locales/ko/CircomHashChecker/config.yml @@ -0,0 +1,35 @@ +id: circom-hash-checker +name: Hash Checker Tutorial +summary: A tutorial on creating and understanding a Hash Checker circuit using Remix-IDE templates, including trusted setup and proof generation. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction to the Hash Checker Circuit + path: step-1 + - + name: Generating the Hash Checker Template in Remix-IDE + path: step-2 + - + name: Exploring calculate_hash.circom + path: step-3 + - + name: Compiling the Circuit + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Compute Witness + path: step-6 + - + name: Generate Proof + path: step-7 + - + name: Exploring the Trusted Setup Script (Optional) + path: step-8 + - + name: Exploring the Proof Generation Script (Optional) + path: step-9 diff --git a/locales/ko/CircomHashChecker/step-1/README.md b/locales/ko/CircomHashChecker/step-1/README.md new file mode 100644 index 000000000..be922e93b --- /dev/null +++ b/locales/ko/CircomHashChecker/step-1/README.md @@ -0,0 +1,8 @@ +In this tutorial, we'll explore the **Hash Checker** circuit, a zero-knowledge proof (ZKP) application using Circom and Remix-IDE. The Hash Checker circuit allows you to prove knowledge of certain inputs that hash to a given value without revealing the inputs themselves. + +### What You'll Learn + +- How to generate a Hash Checker circuit using Remix-IDE's workspace templates. +- Understanding the Circom code for hashing and checking hashes. +- Performing a trusted setup using Groth16. +- Generating zero-knowledge proofs. diff --git a/locales/ko/CircomHashChecker/step-2/README.md b/locales/ko/CircomHashChecker/step-2/README.md new file mode 100644 index 000000000..bc827019e --- /dev/null +++ b/locales/ko/CircomHashChecker/step-2/README.md @@ -0,0 +1,37 @@ +Follow these steps to create the Hash Checker workspace in Remix-IDE. + +### Step 1: Access the Workspace Templates + +1. In the **File Explorer** sidebar, click on the **hamburger menu icon** (three horizontal lines). + + hamburger-menu + +2. Select **"Create Using Template"** from the dropdown. + + create-using-template + +### Step 2: Find the Hash Checker Template + +1. In the main panel, scroll down to the **"Circom ZKP"** section. + + create-zkp-section + +2. Locate the **"Hash Checker"** item. + +### Step 3: Create the Workspace + +1. Click on the **"Create"** button on the Hash Checker item. + + create-hash-checker + +2. In the modal pop-up, provide a **workspace name** (e.g., `hash-checker-workspace`). + + workspace-name-modal + +3. Click **"OK"** to create the template. + +### Result + +- The workspace is created with the necessary files and directories. + + workspace-name-modal diff --git a/locales/ko/CircomHashChecker/step-3/README.md b/locales/ko/CircomHashChecker/step-3/README.md new file mode 100644 index 000000000..b3ac14050 --- /dev/null +++ b/locales/ko/CircomHashChecker/step-3/README.md @@ -0,0 +1,32 @@ +## Exploring `calculate_hash.circom` + +Navigate to the `circuits` directory and open `calculate_hash.circom`. This file contains the Circom code for the Hash Checker circuit. + +### Code Breakdown + +#### Pragma and Includes: + +- `pragma circom 2.0.0;` specifies the Circom version. +- `include "circomlib/circuits/poseidon.circom";` fetch and includes the Poseidon hash function from [CircomLib](https://github.com/iden3/circomlib). + +#### `CalculateHash` Template: + +- Defines inputs `value1`, `value2`, `value3`, `value4`. +- Uses the `Poseidon` hash function to compute a hash of these values.\ +- Outputs `out`, which is the hash. + +#### `HashChecker` Template: + +- Inputs are the same values plus a `hash`. +- Instantiates `CalculateHash` as `calculateSecret`. +- Computes `calculatedHash`. +- Uses `assert(hash == calculatedHash);` to ensure the provided hash matches the calculated hash. + +#### Main Component: + +- `component main {public [hash]} = HashChecker();` +- Specifies that `hash` is a `public` input, while the values are `private`. + +### Purpose + +The circuit allows someone to prove they know `value1`, `value2`, `value3`, and `value4` that hash to a specific `hash` without revealing the values themselves. diff --git a/locales/ko/CircomHashChecker/step-4/README.md b/locales/ko/CircomHashChecker/step-4/README.md new file mode 100644 index 000000000..537c6a241 --- /dev/null +++ b/locales/ko/CircomHashChecker/step-4/README.md @@ -0,0 +1,32 @@ +## Compiling the Circuit + +### Selecting the Compiler Version + +1. Go to the **Circuit Compiler** plugin in the sidebar. +2. Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +### Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +### Compiling the Circuit + +1. Click on the **Compile** button. +2. Wait for the compilation to complete. A success badge will appear if compilation is successful. + +compilation-success + +### Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/ko/CircomHashChecker/step-5/README.md b/locales/ko/CircomHashChecker/step-5/README.md new file mode 100644 index 000000000..c3ea8509b --- /dev/null +++ b/locales/ko/CircomHashChecker/step-5/README.md @@ -0,0 +1,25 @@ +## Performing a Trusted Setup + +1. **Access the Setup and Exports Section**: + +- After successful compilation, the **Setup and Exports** section becomes available in the plugin. + +2. **Select Proving Scheme**: + +- Choose **Groth16** from the **Proving Scheme** dropdown. + +3. **Select Power of Tau File**: + +- Choose the appropriate **Power of Tau** file from the dropdown. If unsure, use the default option. + +4. **Export Verification Key and Contract** (optional): + +- Enable **Export Verification Key** to save the verification key to the File Explorer. +- Enable **Export Verifier Contract** to save the Solidity contract for on-chain verification. + +trusted-setup + +5. **Run the Trusted Setup**: + +- Click on the **Run Setup** button. +- Wait for the process to complete. This may take some time depending on the circuit complexity. diff --git a/locales/ko/CircomHashChecker/step-6/README.md b/locales/ko/CircomHashChecker/step-6/README.md new file mode 100644 index 000000000..03b848f81 --- /dev/null +++ b/locales/ko/CircomHashChecker/step-6/README.md @@ -0,0 +1,28 @@ +## Compute Witness + +1. **Access the Compute Witness Section**: + - After the trusted setup, the **Compute Witness** section becomes available. + +2. **Input Values**: + - You'll see input fields for `value1`, `value2`, `value3`, `value4`, and `hash`. + - Enter values for each input. For example: + - `value1`: `1234` + - `value2`: `2` + - `value3`: `3` + - `value4`: `4` + +3. **Calculate the Hash**: + + - Compute the Poseidon hash of the four values using an external tool or library compatible with the Poseidon hash function. + - For the values above, here is the computed Poseidon hash `16382790289988537028417564277589554649233048801038362947503054340165041751802`. + - Enter the calculated `hash` value in the `hash` input field. + + compute-witness + +4. **Compute the Witness**: + + - Click on the **Compute Witness** button. + - Wait for the process to complete. A success badge will appear if the witness is computed successfully. + - If successful, you'll see `calculate_hash.wtn` created in the `.bin` directory in the file explorer. + + witness-computed diff --git a/locales/ko/CircomHashChecker/step-7/README.md b/locales/ko/CircomHashChecker/step-7/README.md new file mode 100644 index 000000000..e6ae80fea --- /dev/null +++ b/locales/ko/CircomHashChecker/step-7/README.md @@ -0,0 +1,21 @@ +## Generate Proof + +1. **Access the Generate Proof Section**: + - After computing the witness, expand the **Generate Proof** section. + +2. **Configure Proof Generation**: + - **Export Verifier Calldata**: Enable this option if you plan to verify the proof on-chain. + +3. **Generate the Proof**: + + - Click on the **Generate Proof** button. + - Wait for the proof generation to complete. + + generate-proof + +4. **View the Proof**: + + - The proof data will be displayed in the File Explorer. + - **Congratulations!** You've successfully compiled the `Hash Checker` circuit, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + + generate-proof diff --git a/locales/ko/CircomHashChecker/step-8/README.md b/locales/ko/CircomHashChecker/step-8/README.md new file mode 100644 index 000000000..e489a8cab --- /dev/null +++ b/locales/ko/CircomHashChecker/step-8/README.md @@ -0,0 +1,34 @@ +## Understanding `groth16_trusted_setup.ts` + +Navigate to `scripts/groth16/groth16_trusted_setup.ts`. This script performs the trusted setup necessary for generating proofs. + +### Code Breakdown + +#### Circuit Compilation: + +- Uses `remix.call('circuit-compiler', 'generateR1cs', ...)` to generate `R1CS` (Rank-1 Constraint System) from the circuit. + +#### Trusted Setup Steps: + +- `snarkjs.zKey.newZKey`: Initializes the proving key (`zkey_0`). +- `snarkjs.zKey.contribute`: Adds contributions to the proving key (`zkey_1`). +- `snarkjs.zKey.beacon`: Finalizes the proving key (`zkey_final`). + +#### Verification: + +- `snarkjs.zKey.verifyFromR1cs`: Verifies the proving key against the `R1CS` and initial parameters. + +#### Exporting Keys: + +- Exports the verification key to `scripts/groth16/zk/keys/verification_key.json`. +- Exports the final proving key (`scripts/groth16/zk/keys/zkey_final.txt`). + +### Purpose + +- Performs the trusted setup required for the `Groth16` proving system. +- Generates the necessary keys for proof generation and verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"setup done."` logged in the terminal. diff --git a/locales/ko/CircomHashChecker/step-9/README.md b/locales/ko/CircomHashChecker/step-9/README.md new file mode 100644 index 000000000..653d5ced1 --- /dev/null +++ b/locales/ko/CircomHashChecker/step-9/README.md @@ -0,0 +1,37 @@ +## Understanding `groth16_zkproof.ts` + +Navigate to `scripts/groth16/groth16_zkproof.ts`. This script generates the zero-knowledge proof and prepares it for verification. + +### Code Overview + +#### Loading Files: + +- Reads the R1CS and WASM files generated from the circuit. +- Loads the final proving key (`zkey_final`) and verification key (`vKey`). + +#### Defining Inputs: + +- Sets the private values (`value1`, `value2`, `value3`, `value4`). +- Computes the `hash` using Poseidon from [CircomLib](https://github.com/iden3/circomlib). + +#### Witness Calculation and Proof Generation: + +- Calculates the witness (`wtns`). +- Checks the witness against the `R1CS`. +- Generates the proof using `Groth16`. +- Verifies the proof. + +#### Exporting Verifier Contract and Inputs: + +- Generates a Solidity verifier contract. +- Exports the proof inputs to `input.json`. + +### Purpose + +- Generates a zero-knowledge proof that the prover knows values hashing to a specific hash. +- Prepares the verifier contract and inputs for on-chain verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"zk proof validity"` logged in the terminal. diff --git a/locales/ko/CircomIntro/README.md b/locales/ko/CircomIntro/README.md new file mode 100644 index 000000000..c58b2daec --- /dev/null +++ b/locales/ko/CircomIntro/README.md @@ -0,0 +1,21 @@ +Intro to Circom + +This is an introduction to Circom. You'll learn how to write, compile, and test arithmetic circuits in Circom. We'll go over how to do this within Remix-IDE. + +Tutorial Overview + +``` +Step 1: Introduction +Step 2: Setting Up Remix-IDE and Installing the Circuit-Compiler Plugin +Step 3: Writing Your First Circom Circuit +Step 4: Compiling the Circuit Using the Plugin +Step 5: Performing a Trusted Setup +Step 6: Computing the Witness +Step 7: Generating the Proof +``` + +Prerequisites: + +``` +Basic understanding of cryptography and zero-knowledge proofs is helpful but not required. +``` diff --git a/locales/ko/CircomIntro/config.yml b/locales/ko/CircomIntro/config.yml new file mode 100644 index 000000000..d6dfdca46 --- /dev/null +++ b/locales/ko/CircomIntro/config.yml @@ -0,0 +1,29 @@ +id: circom-intro +name: Intro to Circom +summary: A intro to using Circom for creating arithmetic circuits. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction + path: step-1 + - + name: Installing the Circuit-Compiler + path: step-2 + - + name: Writing Your First Circom Circuit + path: step-3 + - + name: Compiling the Circuit Using the Plugin + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Computing the Witness + path: step-6 + - + name: Generating the Proof + path: step-7 diff --git a/locales/ko/CircomIntro/step-1/README.md b/locales/ko/CircomIntro/step-1/README.md new file mode 100644 index 000000000..0766ce6f4 --- /dev/null +++ b/locales/ko/CircomIntro/step-1/README.md @@ -0,0 +1,13 @@ +Welcome to this beginner-level tutorial on Circom using Remix. In this tutorial, you'll learn the basics of Circom, a domain-specific language used for creating arithmetic circuits. + +**What is Circom?** + +Circom is a language designed for writing arithmetic circuits that can be used in zero-knowledge proofs, particularly zk-SNARKs. It allows developers to define complex mathematical circuits that can prove knowledge of certain data without revealing it. + +**Why Use Remix-IDE for Circom?** + +- **Ease of Use:** Remix-IDE provides a user-friendly interface that simplifies the development process. +- **Integrated Tools:** With plugins like `circuit-compiler`, you can compile Circom code, perform trusted setups, compute witnesses, and generate proofs all within the same environment. +- **No Installation Required:** As a web-based IDE, you can start coding immediately without setting up a local development environment. + +In the next steps, we'll guide you through setting up Remix-IDE for Circom development and help you write your first circuit. diff --git a/locales/ko/CircomIntro/step-2/README.md b/locales/ko/CircomIntro/step-2/README.md new file mode 100644 index 000000000..4b228c298 --- /dev/null +++ b/locales/ko/CircomIntro/step-2/README.md @@ -0,0 +1,25 @@ +In this step, we'll set up Remix for Circom development by activating the `Circom ZKP compiler` plugin. + +## Activating the Circom ZKP compiler + +1. At the bottom of the icon panel on the left of the screen, click on the **Plugin Manager** (the plug icon). + 2.In the search bar, type **Circom**. +2. Find the **Circuit Compiler** plugin in the list and click on the **Activate** button. +3. The plugin will now appear in your sidebar. + +install-plugin + +## The Circom Compiler Interface + +- **Compiler Version Dropdown:** Select the Circom compiler version you wish to use. +- **Auto Compile Checkbox:** Enable this to automatically compile your circuit whenever you make changes. +- **Hide Warnings Checkbox:** Enable this to suppress compiler warnings. +- **Advanced Configuration:** Click to expand options for selecting the prime field (e.g., BN128, BLS12381). + +compiler-interface + +With the plugin installed, you're now ready to start writing Circom code in Remix-IDE. + +**Note:** Make sure your internet connection is stable, as Remix-IDE is a web-based tool. + +In the next step, we'll write our first Circom circuit. diff --git a/locales/ko/CircomIntro/step-3/README.md b/locales/ko/CircomIntro/step-3/README.md new file mode 100644 index 000000000..6424668f6 --- /dev/null +++ b/locales/ko/CircomIntro/step-3/README.md @@ -0,0 +1,38 @@ +Let's write a simple Circom circuit. + +## Creating a New Circuit File + +1. In the **File Explorer** on the left sidebar, click on the **Create New File** icon. +2. Name your file `multiplier.circom` and press **Enter**. + +create-new-file + +## Writing the Circuit + +Open `multiplier.circom` and add the following code: + +```circom +pragma circom 2.0.0; + +template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; +} + +component main = Multiplier(); +``` + +## Explanation: + +- template `Multiplier()`: Defines a new circuit template called Multiplier. +- `signal input a;` and `signal input b;`: Declare input signals a and b. +- `signal output c;`: Declare an output signal c. +- `c <== a * b;`: Constrain c to be the product of a and b. +- `component main = Multiplier();`: Instantiates the Multiplier circuit as main, which is required for the compiler. + +### NB: + +Signals are values in a cryptographic circuit that are strictly determined by the circuit's equations and constraints. Think of a signal as a value that must follow specific mathematical rules defined by the circuit—once set, it can't be changed arbitrarily. In regular programming, variables are flexible and can be updated or reassigned as needed, whereas, signals can't be altered freely. diff --git a/locales/ko/CircomIntro/step-4/README.md b/locales/ko/CircomIntro/step-4/README.md new file mode 100644 index 000000000..ad3f2a089 --- /dev/null +++ b/locales/ko/CircomIntro/step-4/README.md @@ -0,0 +1,34 @@ +With your `multiplier.circom` circuit ready, let's compile it using the Circuit Compiler plugin. + +## Selecting the Compiler Version + +Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +## Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +## Compiling the Circuit + +1. Click on the **Compile** button. +2. The compiler will process your circuit. +3. If successful, you'll see a compilation success message. + +compilation-success + +**Note:** If there are any errors, they will be displayed in the console. Check your code for typos or syntax errors. + +## Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/ko/CircomIntro/step-5/README.md b/locales/ko/CircomIntro/step-5/README.md new file mode 100644 index 000000000..8e8496bbd --- /dev/null +++ b/locales/ko/CircomIntro/step-5/README.md @@ -0,0 +1,26 @@ +After compiling your circuit, you need to perform a trusted setup to generate proving and verification keys. + +## Understanding Trusted Setup + +- **Trusted Setup:** A process required for zk-SNARKs to generate the necessary parameters for proof generation and verification. +- You can choose between different protocols like **Groth16** and **Plonk**. + +## Performing the Trusted Setup + +1. In the **Setup and Exports** section, select the **Proving Scheme**: + - Choose between **Groth16** or **Plonk**. We'll use **Groth16** for this tutorial. + +2. Choose the appropriate **Power of Tau** file from the dropdown. This file is necessary for the trusted setup. + - If unsure, select the default option. + +3. Click on the **Setup** button to start the trusted setup process. + +4. You can enable **Export Verification Key** to get the verification parameters. + +5. You can enable **Export Verification Contract** if you intend to verify proofs on-chain. + +trusted-setup + +**Note:** The trusted setup may take some time, depending on the complexity of your circuit. + +In the next step, we'll compute the witness for our circuit. diff --git a/locales/ko/CircomIntro/step-6/README.md b/locales/ko/CircomIntro/step-6/README.md new file mode 100644 index 000000000..e13d33d32 --- /dev/null +++ b/locales/ko/CircomIntro/step-6/README.md @@ -0,0 +1,27 @@ +With the trusted setup complete, you can now compute the witness for your circuit based on specific inputs. + +## What is a Witness? + +- A **Witness** is a set of values that satisfy all the constraints of your circuit. It includes all the intermediate numbers and results that satisfy the circuit's rules. The witness is used in zero-knowledge proofs to demonstrate that you know a valid solution to the problem without actually showing the solution itself. This allows others to verify that you did everything correctly while keeping your specific numbers and calculations private. +- It is essential for generating a proof. + +## Inputting Values + +1. In the **Compute Witness** section, you'll see input fields dynamically generated based on your circuit's inputs. +2. Enter values for `a` and `b`. For example: + - `a = 3` + - `b = 4` + +compute-witness + +## Computing the Witness + +1. After entering the inputs, click on the **Compute Witness** button. +2. The plugin will compute the witness based on your inputs. +3. If successful, you'll see `multiplier.wtn` created in the `.bin` directory in the file explorer. + +witness-computed + +**Note:** If there are any errors, ensure that your inputs are valid and satisfy the circuit's constraints. + +In the next step, we'll generate a proof using the computed witness. diff --git a/locales/ko/CircomIntro/step-7/README.md b/locales/ko/CircomIntro/step-7/README.md new file mode 100644 index 000000000..f5cf332a9 --- /dev/null +++ b/locales/ko/CircomIntro/step-7/README.md @@ -0,0 +1,31 @@ +With the witness computed, the final step is to generate a proof that can be verified by others. + +## Generating the Proof + +1. In the **Generate Proof** section, you have the option to **Export Verifier Calldata**. + - Enable the **Export Verifier Calldata** checkbox if you plan to verify the proof on-chain. +2. Click on the **Generate Proof** button. + +generate-proof + +## Understanding the Output + +- After generating the proof, the plugin will display the proof data. +- If you enabled **Export Verifier Calldata**, it will also provide the calldata needed for on-chain verification. + +proof-generated + +## Next Steps + +- **Verification:** You can use the verification key or contract exported earlier to verify the proof. +- **On-Chain Verification:** If you're familiar with smart contracts, you can deploy the verification contract and use the calldata to perform on-chain verification. + +**Congratulations!** You've successfully written a Circom circuit, compiled it, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + +## Additional Resources + +- [Circom Documentation](https://docs.circom.io/) +- [Remix-IDE Documentation](https://remix-ide.readthedocs.io/) +- [Zero-Knowledge Proofs Explained](https://zkproof.org/) + +Feel free to experiment with more complex circuits and explore the capabilities of Circom and Remix-IDE further. diff --git a/locales/ko/DeployWithLibraries/1_Writing_a_Library/step1.md b/locales/ko/DeployWithLibraries/1_Writing_a_Library/step1.md new file mode 100644 index 000000000..1ad984835 --- /dev/null +++ b/locales/ko/DeployWithLibraries/1_Writing_a_Library/step1.md @@ -0,0 +1,17 @@ +A libraries looks like a **contract** but use the keyword `library` + +A library typically is a collection of useful functions sitting out there on the blockchain that any contract can use. Because the library is already deployed, it saves the deployment costs of the many contracts that use it. + +In the following contract: + +- Make a library with the name `LibraryForTest`. + +It is possible to put a library in same file with another contract. So put the library below the contract. + +This library should have a method called `getFromLib` method which returns `3`. + +- Update the `get` method in the `test` contract to use the `LibraryForTest` library. The function `get` should return the value it receives from `getFromLib`. + +--------- + +You can find more info about libraries in this section of the Solidity Docs. diff --git a/locales/ko/DeployWithLibraries/2_Generate_Metadata/step2.md b/locales/ko/DeployWithLibraries/2_Generate_Metadata/step2.md new file mode 100644 index 000000000..218c86ff9 --- /dev/null +++ b/locales/ko/DeployWithLibraries/2_Generate_Metadata/step2.md @@ -0,0 +1,38 @@ +## Deploying Library + +The **library** from the previous chapter was in the same file as the **contract**. However, they won't be deployed together and will have different addresses. + +In order to use a library, the calling contract must have the library's **address**. + +But the library's address is not directly specified in the solidity code. The calling contract's compiled bytecode contains a **placeholder** where library's **addresses** will go. + +At deployment of the **calling contract**, Remix will look in the contract's **metadata** for the library's address and will update the placeholder with the address. + +So before deploying a contract that calls a library, you need to generate the contract's metadata (AKA its **build artifact**) and then you need to input the library's address into the metadata file. + +A contract's metadata is generated at **compile time**. + +Let's setup Remix to generate the **metadata file**. + +- Go to the settings module by clicking on the settings ![settings](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/settings.png "Settings") icon in the icon panel. + +![settings module](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_settings.png "Settings Module") + +- And check the first option `Generate contract metadata`. + +# Compile and generate metadata (JSON) file. + +1. Open the Solidity Compiler ![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +2. Compile `2_contractSimpleLibrary.sol`. + +3. Switch to the File Explorer ![File Explorer](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_file_explorer.png "File Explorer") + +4. Navigate to the newly create JSON files. + - It should be in the folder: + +**browser/.learneth/DeployWithLibraries/2_Generate_Metadata/artifacts/** + +5. Select the newly created JSON file created from the contract. It has the **same name** as the contract `sample` but with the extension **json**: `sample.json` (don't select the library's metadata `contractSimpleLibrary.json`). + +In the next step we'll make some adjustments to the metadata file. diff --git a/locales/ko/DeployWithLibraries/3_Edit_Metadata/step3.md b/locales/ko/DeployWithLibraries/3_Edit_Metadata/step3.md new file mode 100644 index 000000000..1555d645d --- /dev/null +++ b/locales/ko/DeployWithLibraries/3_Edit_Metadata/step3.md @@ -0,0 +1,12 @@ +The `Deploy` property in `sampleContract.json` contains everything you need for telling Remix IDE the address of the library for a specific network. + +- `
` contains the address of the library that is already deployed. You have to specify this address for each network. +- `autoDeployLib` is a boolean and tells Remix IDE if it should autodeploy the library before deploying the contract. + +Basically if `autoDeployLib` is **true**, the `
` will not be used and Remix will automatically deploy the library before deploying the contract. + +For the purpose of this demo - we are mimicking a situation where the library has already been deployed because this is a more common situation. + +So set `autoDeploy` to **false**, for the `VM:-` entry. + +Move to next Step. diff --git a/locales/ko/DeployWithLibraries/4_Linking_and_Deploying/step4.md b/locales/ko/DeployWithLibraries/4_Linking_and_Deploying/step4.md new file mode 100644 index 000000000..ad5f52e2d --- /dev/null +++ b/locales/ko/DeployWithLibraries/4_Linking_and_Deploying/step4.md @@ -0,0 +1,25 @@ +Switch to the `Deploy & Run` module +![Run transaction](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/remix_runtransaction.png "Run Transaction") + +- Select the Remix VM Environment and select the `sampleContract` contract in the list of compiled contracts. + +- Click on `Deploy` + +The terminal should output something like `creation of sample errored:
is not a valid address. Please check the provided address is valid.` +That is expected: **We have set `autoDeployLib` to false, so Remix expects to have an address and not just `
`** + +So we need deploy the library to get its address. + +- Select the library `aLib` in the list of compiled contract and hit `deploy` + + ![Choose aLib](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/contract_alib.png "Choose aLib") + +- Click the clipboard icon to copy the address of the library. + + ![Copy lib1](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/alib_copy.png "Copy") + +- Paste it into the **contract sample's** metadata JSON. + +- Reselect the `sampleContract` contract in the `Run transaction` module and hit deploy. + +- Deploy should now be successful. diff --git a/locales/ko/DeployWithLibraries/5_Under_The_Hood/step5.md b/locales/ko/DeployWithLibraries/5_Under_The_Hood/step5.md new file mode 100644 index 000000000..860b48b24 --- /dev/null +++ b/locales/ko/DeployWithLibraries/5_Under_The_Hood/step5.md @@ -0,0 +1,30 @@ +Switch to the `Solidity compiler` module +![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +- Select the `sampleContract` contract in the list of compiled contracts. +- click on `ByteCode`, it should copy the following to the clipboard: + +``` +{ + "linkReferences": { + "browser/contractSimpleLibrary.sol": { + "lib1": [ + { + "length": 20, + "start": 115 + } + ] + } + }, + "object": "608060405234801561001057600080fd5b5060f68061001f6000396000f3fe6080604052600436106039576000357c0100000000000000000000000000000000000000000000000000000000900480636d4ce63c14603e575b600080fd5b348015604957600080fd5b5060506052565b005b73__$d42d70ba92b626965f4c69b39148e37a33$__63fea24e5f6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801560b157600080fd5b505af415801560c4573d6000803e3d6000fd5b5050505056fea165627a7a7230582068c9a3a9a5cbfd26cfdab2534abfc926912d9b89eaa14e36c8248b7e7eb0ab090029", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xF6 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x39 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x3E JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x50 PUSH1 0x52 JUMP JUMPDEST STOP JUMPDEST PUSH20 0x0 PUSH4 0xFEA24E5F PUSH1 0x40 MLOAD DUP2 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH1 0xB1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS DELEGATECALL ISZERO DUP1 ISZERO PUSH1 0xC4 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 PUSH9 0xC9A3A9A5CBFD26CFDA 0xb2 MSTORE8 0x4a 0xbf 0xc9 0x26 SWAP2 0x2d SWAP12 DUP10 0xea LOG1 0x4e CALLDATASIZE 0xc8 0x24 DUP12 PUSH31 0x7EB0AB09002900000000000000000000000000000000000000000000000000 ", + "sourceMap": "63:85:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63:85:0;;;;;;;" +} +``` + +This is basically what the compiler is returning: + +- `linkReferences` describes what are the libraries used by the contract. +- `object` is the compiled contract (bytecode). This is what gets deployed and saved onto the blockchain. In this example, the value `__$d42d70ba92b626965f4c69b39148e37a33$__` inside the bytecode is just a placeholder for the library address. In your case, the placeholder will be between `__$` and `$__`. + +The metadata JSON from Remix IDE tells Remix to replace the placeholder with the given address. diff --git a/locales/ko/DeployWithLibraries/README.md b/locales/ko/DeployWithLibraries/README.md new file mode 100644 index 000000000..fb31b1264 --- /dev/null +++ b/locales/ko/DeployWithLibraries/README.md @@ -0,0 +1,3 @@ +**Libraries** are deployed contracts that do not store state and are used by other contracts to decrease their size and thus their deployment costs. + +Learn to work with **Libraries** in Remix - you won't need to whisper. diff --git a/locales/ko/DeployWithLibraries/config.yml b/locales/ko/DeployWithLibraries/config.yml new file mode 100644 index 000000000..0816e2346 --- /dev/null +++ b/locales/ko/DeployWithLibraries/config.yml @@ -0,0 +1,8 @@ +--- +id: deploylibraries +name: Deploy with Libraries +summary: Write, Deploy and link a Library to a Contract +level: 3 +tags: + - Remix + - Solidity diff --git a/locales/ko/ERC20TokenCourse/README.md b/locales/ko/ERC20TokenCourse/README.md new file mode 100644 index 000000000..25a6ccf95 --- /dev/null +++ b/locales/ko/ERC20TokenCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Token Course + +Learn to understand and create ERC20 tokens. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ko/ERC20TokenCourse/config.yml b/locales/ko/ERC20TokenCourse/config.yml new file mode 100644 index 000000000..8c12a5213 --- /dev/null +++ b/locales/ko/ERC20TokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: tokenCourse +name: Solidity ERC20 Token Course +summary: Learn how to create your own ERC20 tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - ERC20 +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc20-interface + - + name: 3. Token Creation + path: erc20-token-creation + - + name: 4. Interaction + path: erc20-interaction + - + name: 5. Testnet Deployment + path: erc20-testnet-deployment + - + name: 6. Extensions + path: erc20-extensions diff --git a/locales/ko/ERC20TokenCourse/erc20-extensions/erc20extensions.md b/locales/ko/ERC20TokenCourse/erc20-extensions/erc20extensions.md new file mode 100644 index 000000000..b3649fbba --- /dev/null +++ b/locales/ko/ERC20TokenCourse/erc20-extensions/erc20extensions.md @@ -0,0 +1,33 @@ +The ERC20 standard only describes the required and optional functionality that your contract needs, but you can add additional functionality. + +In this section, we added the functionality to burn and mint tokens, as well as the ability to pause the contract, by using OpenZeppelin extensions. + +Of course, you can write your own ERC20 token contract implementation or extensions and import them into your contract. But OpenZeppelin contracts have been audited by security experts and are a great way to add desired functionality. + +### Mintable + +The mint function allows the creator of the contract to mint (create) additional tokens after the contract has been deployed (line 22). As input parameters, the function needs the address that the tokens will be minted to, and the amount of tokens that should be minted. + +We don't have to import `mint()` from another contract since the mint function is already part of the ERC20 contract implementation of OpenZeppelin. We import `Ownable` (line 7) which is a contract module that provides a basic access control mechanism that allows an owner to have exclusive access to specific functions. In this contract, we add the inherited `onlyOwner` modifier to the `mint` function (line 22) and restrict access to this function to the "owner". + +The contract will inherit additional functions like owner(), transferOwnership() and renounceOwnership() to manage access, from the Ownable contract. + +### Burnable + +By importing the "ERC20Burnable" (line 5) and inheriting its functions (line 9) our contract allows token holders to destroy their tokens as well as the tokens in their allowance. +For more information, have a look at the ERC20Burnable contract. + +### Pausable + +With the "Pausable" contract module (line 6 and 9) the owner is able to pause (line 14) and unpause (line 18) the contract. In the pause state, tokens can't be transferred, which can be helpful in emergency scenarios. +For more information, have a look at the Pausable contract. + +Have a look at the OpenZeppelins Contract Wizard, which allows you to easily add additional functionality. + +If you successfully completed this course, try the Learneth NFT Course as the next step in your journey. + +## ⭐️ Assignment + +1. Try to mint tokens to an account after deployment. Call `totalSupply()` and `balanceOf()` to confirm the correct execution. +2. Burn tokens and then call `totalSupply()` and `balanceOf()` to confirm the correct execution. +3. Test the pause function by pausing the contract using the owner account and trying to make a transfer with a second account. The transaction should not be able to be executed and will throw the exception: "Pausable: paused". diff --git a/locales/ko/ERC20TokenCourse/erc20-interaction/er20interaction.md b/locales/ko/ERC20TokenCourse/erc20-interaction/er20interaction.md new file mode 100644 index 000000000..5c082b248 --- /dev/null +++ b/locales/ko/ERC20TokenCourse/erc20-interaction/er20interaction.md @@ -0,0 +1,87 @@ +In this section, we will deploy a contract in our browser and test its functionality. + +### 1. Deploy the contract + +**1.1** Compile your EduCoin contract in the "Solidity compiler" module of the Remix IDE. + +**1.2** In the "Deploy & run transactions" module, select your contract "EduCoin" in the contract input field and click on the "Deploy" button. Always make sure to select the correct contract in the contract selector input field. + +**GIF** Compile and deploy: Compile and deploy contract + +### 2. Test the functions + +Expand the token contract functions in the IDE. + +#### 2.1 Decimals + +Click on the "decimals" button to call the decimals() function. +It should return "18". + +#### 2.2 Name + +Click on the "name" button to call the name() function. +It should return "EduCoin". + +#### 2.3 Symbol + +Click on the "symbol" button to call the symbol() function. +It should return "EDC". + +#### 2.4 Total supply + +Click on the "totalSupply" button to call the totalSupply() function. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test decimals, name, symbol, and totalSupply functions: Test transfer function + +#### 2.5 Balance of + +**2.5.1** Go to the "ACCOUNT" section in the sidebar and copy the displayed address by using the copy icon next to it. + +**2.5.2** Paste the address in the input field next to the "balanceOf" function button and click on the button. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test balanceOf function: Test transfer function + +#### 2.6 Transfer + +We will transfer EduCoin from one account to a second account. + +**2.6.1** Go to the "ACCOUNT" section in the sidebar and click on the displayed address. This should open a dropdown. Select the second address displayed and copy its address (account 2). + +**2.6.2** Open the dropdown and select the first account again (account 1), because this is the account that we want to use to make the transfer. + +**2.6.3** Paste the address in the input field next to the "transfer" function button, input the number 500000000000000000000, and click on the button. + +**2.6.4** If you check the balances for account 1 and account 2, they should both return the amount 500000000000000000000. + +**GIF** Test transfer function: Test transfer function + +#### 2.7 Approve + +We will now allow account 1 to spend tokens on behalf of account 2. + +**2.7.1** Go to the "Account" section, copy the address of account 1, then set it to account 2 again. + +**2.7.2** In the approve function, enter the address of account 1 as the input for spender and set the amount to 250000000000000000000. + +**GIF** Test approve function: Test approve function + +#### 2.8 Allowance + +Next to the "allowance" button enter the address of account 2 as the owner and account 1 as the spender; click on the button. +It should return 1000000000000000000000. + +**GIF** Test allowance function: Test allowance function + +#### 2.9 TransferFrom + +Now account 1 will transfer 250000000000000000000 tokens from account 2 to its own account. + +**2.9.1** Select account 1 in the "ACCOUNT" section. + +**2.9.2** Next to the "transferFrom" button enter the address of account 2 as the sender and account 1 as the recipient, enter 250000000000000000000 as the amount and click on the button. + +**2.9.3** Check the balances of accounts 2 and 1, they should return 250000000000000000000 and 750000000000000000000. + +**GIF** Test transferFrom function: Test transferFrom function diff --git a/locales/ko/ERC20TokenCourse/erc20-interface/erc20interface.md b/locales/ko/ERC20TokenCourse/erc20-interface/erc20interface.md new file mode 100644 index 000000000..5c4e8137c --- /dev/null +++ b/locales/ko/ERC20TokenCourse/erc20-interface/erc20interface.md @@ -0,0 +1,76 @@ +ERC20 (Ethereum Request for Comments 20) is a standard for token contracts that manages fungible tokens on the Ethereum blockchain. + +Fungible tokens are all equal to each other and have the same value, behavior, and rights. Fungible tokens are often used as a medium of exchange, like the currencies ETH or BTC. However, they can also have other use cases like voting rights or reputation. + +If you want to know more about the ERC20 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +To get an overview of the required functionality of an ERC20 token contract, we will look at an interface that interacts with an ERC20 contract. +This interface (line 9) is part of the open-source contract library provided by OpenZeppelin. + +## ERC20 Functions + +Contracts compliant with the ERC20 standard must implement the following six functions: + +### totalSupply + +The function `totalSupply` (line 13) returns the total amount of tokens available. + +### balanceOf + +The function `balanceOf` (line 18) returns the amount of tokens owned by the account with the address `account`. + +### transfer + +The function `transfer` (line 27) transfers `amount` of tokens to the address `recipient`. +This function **must** emit (produce) a `Transfer` event (see below) and **should** throw an exception when the sender doesn't have enough tokens to make the transfer. + +### approve + +The function `approve` (line 52) creates an allowance for the address `spender` to transfer `amount` of tokens on behalf of the account calling the function. + +### allowance + +The function `allowance` (line 36) returns the amount of tokens that the address `spender` is allowed to spend on behalf of the account with the address `owner`. + +### transferFrom + +The function `transferFrom` (line 63) transfers `amount` of tokens on behalf of the address `sender` to the address `recipient`. +This function **must** emit a `Transfer` event. + +## ERC20 Events + +ERC20 contracts must also emit two events: + +### Transfer + +The `Transfer` (line 71) event must be emitted when `value` amount of tokens are transferred from the account with the address `indexed from` to `indexed to`. The parameters `from` and `to` are `indexed` allowing us to search for these events using the indexed parameters as filters. + +### Approval + +The `Approval` (line 77) event must be emitted when the account `indexed owner` approves the account `indexed spender` to transfer `value` amount of tokens on its behalf. + +## ERC20 Optional functions + +In addition to the mandatory functions and events, there are also three optional functions specified in the ERC20 standard that are not implemented in this interface: + +### name + +`function name() external view returns (string);` + +Returns the name of the token. + +### symbol + +`function symbol() external view returns (string);` + +Returns the symbol of the token. + +### decimals + +`function decimals() external view returns (uint8);` + +Returns the number of decimal places the token uses. + +You may want to use decimals to make your token divisible into arbitrary amounts like 1.5 ETH when displayed. The EVM (Ethereum virtual machine) only supports integer numbers. That's why the ERC20 standard suggests to implement the decimal functionality that specifies how many decimal places a token has. 18 decimal places is the industry standard. diff --git a/locales/ko/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md b/locales/ko/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md new file mode 100644 index 000000000..94b513922 --- /dev/null +++ b/locales/ko/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md @@ -0,0 +1,41 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to a testnet of the Ethereum blockchain. This testnet behaves very similarly to the real blockchain (mainnet), but does not require real ETH to pay for transactions. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token + +In order to make transactions on the testnet we need Ethereum testnet tokens, which you can receive from something called a _faucet_. + +**2.1** Switch your Metamask network by clicking on the "Ethereum Mainnetwork" drop down and selecting "Ropsten Test Network". If you don’t see any test networks, click on the "Show/hide" link and enable "Show test networks" in the settings. + +**2.2** Go to https://faucet.ropsten.be/, enter the address of your account, and claim testnet ETH. You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Deployment + +Make sure the EduCoin contract is compiled. + +**3.1.** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It will ask you to connect your account which you should confirm. + +**3.2** Deploy the EduCoin contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. Copy the contract address. + +**3.4** In Metamask, click on assets, then click on the "Import tokens" link, and paste the address of your contract in the input field. + +You should now see a balance of 1000 EDC in your wallet. + +### 4. Make a transaction + +**4.1** Click on the identicon (visual representation of your address) in the Metamask wallet and create a second account (Account 2). + +**4.2** Copy the address of Account 2. + +**4.3** Switch to the first account (Account 1) and send 250 EDC to Account 2. Check the balances of Account 1 and Account 2. You might need to add the token address again for Account 2 to import the tokens and you will need testeth if you want to make a transaction with this account. + +You can also see your account balances if you look at the contract in Remix and call the `balanceOf` function using the addresses of Account 1 and Account 2. diff --git a/locales/ko/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md b/locales/ko/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md new file mode 100644 index 000000000..49b71abdd --- /dev/null +++ b/locales/ko/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md @@ -0,0 +1,18 @@ +A token standard tells us what functionality the contract needs to comply with it. How this functionality is implemented is up to the developers. In this contract, we will use an ERC20 token contract implementation from OpenZeppelin (line 4). In this case, we import version 4.4.0 of the OpenZeppelin contracts. + +Have a look at their nicely documented ERC20 contract to have a better understanding of how an implementation might look. Apart from the functionality specified in the ERC20 standard, this contract provides additional functionality. + +We will create our own contract called MyToken (line 6), which inherits the functionality from the OpenZepplin ERC20 token contract implementation that we imported (line 4). + +This contract implements the optional functions `name()` and `symbol()` of the ERC20 Token standard and has a constructor where their values can be set during the deployment of the contract (line 7). +In this case, we are going to use the default values. We will call our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +Next, we make use of the inherited `_mint` function (line 8) that allows us to create tokens upon deployment of the contract. Inside the parameters, we specify the address of the account that receives the tokens and the amount of tokens that are created. +In this case, the account that deploys the contract will receive the tokens and we set the amount to 1000000 to the power of `decimals()`. The optional function `decimals()` of the ERC20 token standard is implemented and set to the default value of 18. This will create 1000000 tokens that will have 18 decimal places. + +## ⭐️ Assignment + +1. Rename your contract to `EduCoin`. +2. Rename your token to `EduCoin`. +3. Change the symbol of your token to `EDC`. +4. Change the amount of tokens that will be minted from 1000000 to 1000. diff --git a/locales/ko/ERC20TokenCourse/introduction/introduction.md b/locales/ko/ERC20TokenCourse/introduction/introduction.md new file mode 100644 index 000000000..4eaf7583c --- /dev/null +++ b/locales/ko/ERC20TokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with the ERC20 token standard in the following sections. + +If you want to learn more about NFTs and the ERC721 token standard, have a look at the Learneth NFT Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/ko/ERC721Auction/README.md b/locales/ko/ERC721Auction/README.md new file mode 100644 index 000000000..325e4d60e --- /dev/null +++ b/locales/ko/ERC721Auction/README.md @@ -0,0 +1,5 @@ +## NFT Auction Contract + +Learn how to write an ERC721 (NFT) auction contract. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ko/ERC721Auction/auction-contract-setup/auctionContractSetup.md b/locales/ko/ERC721Auction/auction-contract-setup/auctionContractSetup.md new file mode 100644 index 000000000..945f0f803 --- /dev/null +++ b/locales/ko/ERC721Auction/auction-contract-setup/auctionContractSetup.md @@ -0,0 +1,46 @@ +In this contract tutorial, we will learn how to create an ERC721 (NFT) auction contract. +We recommend to you, to do the Learneth "Solidity NFT Course" before starting this tutorial. + +In the following sections, we will create a contract that will enable a seller to auction an NFT to the highest bidder. This contract was created by the Solidity by Example project. In this first section, we will create an interface, the necessary state variables, and the constructor. + +### Interface + +We create the interface (line 5) for the ERC721 token since our contract will need to interact with it. We will need the `safeTransferFrom` (line 5), and` transferFrom` (line 11) methods. + +### EnglishAuction + +We create the four events `Start`, `Bid`, `Withdraw`, `End` (line 19-22) so we can log important interactions. + +Next, we will create the state variables that store all the necessary information about our auction on-chain. + +We create two state variables for the NFT we want to auction. In the variable `nft` (line 24) we store a representation of the NFT contract, that will allow us to call its functions by combining the interface IERC721 and the address of the NFT contract. +In `nftId` (line 25), we store the specific token id in our NFT contract that will be auctioned. + +Next, we need a variable to store the address of the person that is auctioning off the NFT, the `seller` (line 27). +We want our NFT contract to send the seller the proceeds of the auction when it is finished, that’s why use `address payable`. + +We create a state variable `endAt` (line 28) where we will store the end date of the auction. +We also create the two booleans, `started` (line 29) and `ended` (line 30), that keep track of whether the auction has started or ended. + +We create a variable `highestBidder` (line 32) where we will store the address of the highest bidder. We will send the highest bidder the NFT once the auction has ended. + +Finally, we need a uint `highestBid` (line 33) to store the highest bid and a mapping `bids` (line 34), where we can store the total value of bids that an account has made before withdrawing; more on this in the next section. + +### Constructor + +When the auctioneer deploys the contract, they need to provide a few arguments: +the address of the contract of the NFT they want to auction `_nft` (line 37), the token id of the NFT they want to auction `_nftId` (line 38), and a starting price that must be overbid to place the first bid in the auction,`_startingBid` (line 39). + +Once deployed, the state variables `nft` (line 41), `nftId` (line 42), `highestBid` (line 45) will be assigned the values from the arguments. The address of the `seller` that deployed the contract will be automatically read out via msg.sender and stored in the state variable `seller` (line 44). + +In the next section, we will enable the auctioneer to start the auction and bidders to place their bids. + +## ⭐️ Assignment + +We will use the assignment part of the following sections to give you instructions on testing your contract in the Remix VM environment of Remix. + +1. Deploy an NFT contract. You can use the NFT contract that we created in our "3.3 ERC721 - Token Creation" section. + +2. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +3. After deploying your contract, test if contract functions like `nft`, `nftId`, and `started` work as expected. diff --git a/locales/ko/ERC721Auction/auction-start-bid/auctionContractStartBid.md b/locales/ko/ERC721Auction/auction-start-bid/auctionContractStartBid.md new file mode 100644 index 000000000..c2b944e0c --- /dev/null +++ b/locales/ko/ERC721Auction/auction-start-bid/auctionContractStartBid.md @@ -0,0 +1,42 @@ +In this section, we will create a function to start the auction and a function to bid on the NFT. + +### Start + +We use some control structures to check if necessary conditions are met before we let the seller start the auction. + +First, we check if the auction has already started (line 49). If it has started and our state variable `started` returns `true` we exit the function and throw an exception. + +The second condition we check for is whether the seller is executing the function (line 50). We have already created a function to store the seller's address when they deploy the contract in the `seller` state variable and can now check if the account executing the start function is the seller. If not we throw an exception. + +Next, we want to transfer the NFT that is up for auction from the seller to the contract (line 52). +We set the state variable `started` to `true` (line 53), and create an end date for the auction (line 54). In this case, it will be seven days from when the start function has been called. We can use a suffix like `days` after a literal number to specify units of time. If you want to learn more about time units have a look at the solidity documentation. + +Finally, we will emit our `Start()` event (line 56). + +### Bid + +Before the function caller can make a bid, we need to be sure that certain conditions are met. The auction needs to have started (line 60), the auction can not have ended (line 61) and the bid (the value attached to the call) needs to be higher than the current highest bid (line 62). + +Now we want to store the bid of the current highest bidder before we make a new bid. +First, we check if there is a bidder (line 64). If this function call is the first bid then the next line would be irrelevant. +In our mapping `bids` (line 34) we map the key, the `address` of the bidder, to the value, a `uint` that represents the total amount of ETH a bidder has bid in the auction before withdrawing. +If there is a bidder, we add the last bid (`highestBid`) of the `highestBidder` to the total value of the bids they have made (line 65) before withdrawing. +We store the bids because we want to enable the bidder to withdraw the ETH they used to make bids if they are no longer the highest bidder. + +Next, we set the `highestBidder` to the account calling the function (line 68), and the `highestBid` to their bid, the value that was sent with the call (line 69). + +Finally, we emit the `Bid` event (line 71). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we create in our "Solidity NFT Course" Learneth course. + +2. Mint yourself an NFT with the tokenId 0. + +3. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +4. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for `tokenId`. This will allow the contract to transfer the token to be auctioned. + +5. Call the `start` function of your auction contract. If you call the `started` function now, it should return `true`. If you call the `highestBid` function it should return 1. + +6. Set the value that you can attach to transactions to 3 Wei and call the `bid` function of the auction contract. If you call the `highestBid` function it should now return 3. diff --git a/locales/ko/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md b/locales/ko/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md new file mode 100644 index 000000000..e324a5c6e --- /dev/null +++ b/locales/ko/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md @@ -0,0 +1,45 @@ +In this section, we will finish the contract, create a function to withdraw the bids that an account has made, and create a function to end the auction. + +### Withdraw + +We create a local variable `bal` (balance) that stores the total value of bids that the function caller has made (line 75) since their last withdrawal. We can assign this value to `bal` by accessing the bids mapping using the address of the function caller as the key. + +Next, we set the value of the address of the function caller to 0 in the bids mapping because they will withdraw the total value of their bids (line 76). + +Now we transfer that amount of ETH from the contract to the function caller and emit the `Withdraw` event (line 79). + +### End + +Before the function caller can execute this function and end the auction, we need to check if certain conditions are met. The auction needs to have started (line 83), the end date of the auction needs to have been reached (line 84), and the auction must not have ended already (line 85). + +Once the auction has ended, we set the state variable `ended` to `true` (line 87). + +We check if anybody participated in the auction and bid on the NFT (line 88). + +If there was a bid, we transfer the NFT from the contract to the highest bidder (line 89) and transfer the ETH that was sent from the highest bidder to the contract, now to the address of the auctioneer, the seller of the NFT (line 90). + +If nobody bids on the NFT, we send the NFT back to the auctioneer (line 92). + +Finally, we emit the `End` event (line 95). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we created in our Learneth "Solidity NFT Course". + +2. Mint yourself an NFT with the tokenId 0. + +3. For testing purposes, change the value that is assigned to the `endAt` state variable (line 54) from `7 days` to `5 minutes`. + +4. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +5. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for the `tokenId`. + +6. Call the `start` function of your auction contract. + +7. Bid 2 Ether using account 1, and 3 Ether using account 2. If you call the `highestBidder` function, it should now return the address of account 2. + +8. Call the `withdraw` function with account 1. In the balance of account 1, you should see the 2 Ether minus some transaction fees. + +9. After 5 minutes have passed, call the `end` function. Then, call the `ended` function which should return `true`. + +In the NFT contract, if you call the `ownerOf` function with the tokenId 0, it should return the address of account 2. If you look at the balance of account 1 it should have increased by 3 Ether minus some transaction fees. diff --git a/locales/ko/ERC721Auction/config.yml b/locales/ko/ERC721Auction/config.yml new file mode 100644 index 000000000..0783a37a1 --- /dev/null +++ b/locales/ko/ERC721Auction/config.yml @@ -0,0 +1,19 @@ +--- +id: er721Auction +name: NFT Auction Contract +summary: Learn how to write an ERC721 (NFT) auction contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: Contract Setup + path: auction-contract-setup + - + name: Start and Bid Functions + path: auction-start-bid + - + name: Withdraw and End Functions + path: auction-withdraw-end diff --git a/locales/ko/Interoperability/1_Intro/intro.md b/locales/ko/Interoperability/1_Intro/intro.md new file mode 100644 index 000000000..ab26f4f6d --- /dev/null +++ b/locales/ko/Interoperability/1_Intro/intro.md @@ -0,0 +1,5 @@ +As the web3 world grows, there will be more blockchains. Unless the chains can communicate with one another, the ecosystem will become increasingly fragmented. + +The Axelar network enables protocols to have cross-chain functionality between any two blockchains. + +Building a protocol that is interoperable between ecosystems is essential for growth. diff --git a/locales/ko/Interoperability/2_Gateway/gateway.md b/locales/ko/Interoperability/2_Gateway/gateway.md new file mode 100644 index 000000000..dc752d3eb --- /dev/null +++ b/locales/ko/Interoperability/2_Gateway/gateway.md @@ -0,0 +1,25 @@ +The Axelar Gateway is the entrypoint for your smart contract into the Axelar ecosystem. Once you have triggered the appropriate function on the Gateway, your transaction will begin its interchain journey from your source chain across the Axelar network to the destination chain. Each chain that is connected to Axelar has a deployed gateway contract for you to interact with. + +The following are the two more relevant functions you will need to be familiar with. + +## callContract() + +This function triggers an interchain transaction with a message from the source to the destination chain. It takes three relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent + +The first two parameters are quite intuitive. They consist of both the name of the chain you want this transaction to go to and the address on that chain you want to end execute at. The final parameter is the payload. This payload represents a general message that is sent to the destination chain. The message can be used in many different ways on the destination chain. For example, you can send data to be used as a parameter in another function on the destination chain, you can send a function signature as a message that will then get executed on a destination chain, and much more. + +## callContractWithToken() + +This function triggers an interchain with a message and a fungible token from the source to the destination chain. It takes five relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent +4. `symbol`: The symbol of the token being sent +5. `amount`: The amount of that token that is being sent + +The first three parameters here are the same as in `callContract()`. The final two parameters are relevant to the token that is being sent along with the message. These are the symbol of the token and the amount of the token that is being sent. diff --git a/locales/ko/Interoperability/3_GasService/GasService.md b/locales/ko/Interoperability/3_GasService/GasService.md new file mode 100644 index 000000000..4ed0afbbf --- /dev/null +++ b/locales/ko/Interoperability/3_GasService/GasService.md @@ -0,0 +1,29 @@ +The Axelar Gas Service is an extremely useful tool made available to pay gas for an interchain transaction. It allows you to pay for the cost of a transaction in the token of the source chain, making for a much easier end user (and developer) experience. If for example the source chain is Ethereum and the destination chain is Polygon then the gas service will receive the complete payment for the transaction in ETH and no matic is needed from the caller to pay for the execution on the Polygon destination chain. + +The following are the two more relevant functions you will need to be familiar with in regards to the Gas Service. + +## payNativeGasForContractCall() + +This function allows you to pay for the entirety of an interchain transaction in the native token of the source chain. It takes five relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +The parameters overlap with the parameters required by the `callContract()` function in the Gateway contract. The two parameters not discussed in the Gateway section are `sender` and `refundAddress`. The sender is the address paying for the transaction and the refund address is the address that will receive any surplus funds sent to the gas service. + +## payNativeGasForContractCallWithToken() + +This function allows you to pay for the entirety of an interchain transaction (that includes a token transfer) in the native token of the source chain. It takes seven relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `symbol`: The symbol of the token that was sent +6. `amount`: The amount of the token that was sent +7. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +This function is nearly identical to the first top one the main difference being that it is used for message + token transfer transactions as opposed to just interchain message transactions (aka GMP Transactions). As a result the GasService needs to also know the `symbol` and `amount` of the token that is being sent. diff --git a/locales/ko/Interoperability/4_Executable/executable.md b/locales/ko/Interoperability/4_Executable/executable.md new file mode 100644 index 000000000..1f72c6be4 --- /dev/null +++ b/locales/ko/Interoperability/4_Executable/executable.md @@ -0,0 +1,27 @@ +The Axelar executable contains relevant helper functions that will be automatically executed on the destination chain in correspondence to the relevant inbound transaction from the source chain. + +The following are the relevant functions you will need to use from Axelar Executable + +## \_execute() + +This function handles the execution on the destination chain. It takes the following four parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent + +The `sourceChain` and `sourceAddress` are key parameters which you receive out of the box that can be used for verifying authenticity of messages on the destination chain. The payload (as discussed in the gateway section) is the message that was sent from the source chain to be used on your destination chain. The `commandId` will not be used during the rest of this module. + +## \_executeWithToken() + +This function handles the execution on the destination chain for a message being sent with a fungible token. It takes six relevant parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent +5. `tokenSymbol`: The symbol of the token being sent +6. `amount`: The amount of that token that is being sent + +The first four parameters are identical to that of the `_execute()` function. The final two parameters of `tokenSymbol` and `amount` are in reference to the token that is being sent along with the message. It allows you on the destination chain to interact with the token accordingly, for example transferring it to another receiving address. The `commandId` will not be used during the rest of this module. diff --git a/locales/ko/Interoperability/5_InterchainMessage/interchainMessage.md b/locales/ko/Interoperability/5_InterchainMessage/interchainMessage.md new file mode 100644 index 000000000..029f642ce --- /dev/null +++ b/locales/ko/Interoperability/5_InterchainMessage/interchainMessage.md @@ -0,0 +1,53 @@ +In this section we will create a contract that will send a "hello world" message between two blockchains. + +## Constructor + +The first thing you will need to create is the `constructor` for the function. This will allow you to set the `Gateway` and `Gas Service` contracts we discussed in the previous sections. + +When deploying the contract you will pass in the address of the `Gateway` and `GasService` for Ethereum Sepolia those addresses are `0xe432150cce91c13a887f7D836923d5597adD8E31` for the Gateway and `0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6` for the Gas Service. + +For the full list of relevant Axelar addresses see here + +## Send Interchain Message + +Now that the constructor has set the relevant Axelar addresses needed to trigger an interchain transaction you can move on to the `setRemoteValue()`, which will trigger this transaction. + +This function takes three parameters: + +1. `_destinationChain`: The chain which the transaction is going to +2. `_destinationAddress`: The address on the destination chain the transaction will execute at +3. `_message`: The message being passed to the destination chain + +First, you have a `require` statement which ensures that the `msg.value` contains a value. This `msg.value` will be used to pay the `GasService`. If no funds were sent, then the transaction should be reverted as the transaction cannot execute on the Axelar blockchain and destination chain without any gas. + +Next, you encode the `_message` that was passed in. Notice that the `_message` is set as a `string` type. Axelar expects this message to be submitted as a `bytes` type so to convert the `string` to `bytes` you simply pass it through `abi.encode()`. + +Now, with your message encoded you can begin to interact with the `GasService` and the `Gateway` + +To pay for the entire interchain transaction you will trigger the function `payNativeGasForContractCall`, which is defined in the `GasService`. + +This function needs the parameters explained earlier in the GasService section. The `sender` for this transaction will be this contract, which is `address(this)`. The `destinationChain` and `destinationAddress` can simply be passed in from this functions parameters, the `payload` is the encoded \_message we wrote earlier. Finally, you need to specify what the refund address is, this can be the address that triggers this function, which you get by writing `msg.sender`. + +Once you trigger this function you will have successfully sent a transaction from the source chain via Axelar to the destination chain! But there is still one final step that needs to be complete. + +### Receive Message on Destination Chain + +On the destination chain the inbound interchain transaction needs to be picked up and handled by the `AxelarExecutable`'s `_execute()` function. + +The `_execute()` function is defined in the `AxelarExecutable` contract so when defining this function you must remember to include the `override` keyword. + +This function takes three parameters. + +1. `_sourceChain`: The blockchain which the transaction has originated from +2. `_sourceAddress`: The address on the source chain which the transaction has been sent from +3. `_payload`: The message that has been sent from the source chain + +The first thing that needs to be done in this contract is to get access to your `message` that was sent. Recall, before sending the message it was sent through `abi.encode()` to convert the message from type `string` to type `bytes`. To convert your message back from type `bytes` to type `string` simply pass the `_payload` to the function `abi.decode()` and specify that you want the `_payload` decoded to type `string`. This will return the message as a string. + +Now that you have your message as a type string you can set the `sourceChain` and `sourceAddress` storage variables as `_sourceChain` and `_sourceAddress` to have an easy reference to the data that was passed in. You can also emit the `Executed` event with the `sourceAddress` and `message` event that you just decoded. + +Great! At this point you are now handling the interchain transaction on the destination chain. + +To interact with this contract make sure you deploy it on at least two blockchains so that you can call `setRemoteValue()` from the one chain and then have the `_execute()` function automatically triggered on another chain. You will be able to query the `sourceChain` and `sourceAddress` variables on the destination chain to ensure that the interchain execution worked correctly. + +To view the full step by step of the interchain transaction checkout the Axelarscan (testnet) block explorer. diff --git a/locales/ko/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md b/locales/ko/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md new file mode 100644 index 000000000..11915eb32 --- /dev/null +++ b/locales/ko/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md @@ -0,0 +1,39 @@ +At this point we have gone over an example of how to send a general message between one blockchain to another. Now, let's implement a contract that sends a message and a token from one blockchain to another. + +## Overview + +This contract should seem largely familiar. Much like the previous section the `constructor` receives the `Gateway` and `Gas Service` addresses. + +It then has a function that will be called from the source chain called `sendToMany` that takes in parameters similar to the previous section. + +1. `_destinationChain`: The chain the transaction is sending to +2. `_destinationAddress`: The address on the destination chain your transaction is sending to +3. `_destinationAddresses`: The message that you will be sending along with your token transfer. In this example the message is a list of receiving addresses for the token transfer. +4. `_symbol`: The symbol of the token address being sent +5. `_amount`: The amount of the token being sent + +In the function we already have the `require` statement implemented to ensure gas is sent + +We also have the basic ERC20 functionality to send the token from the calling wallet to this smart contract. The contract also calls the `approve` function to allow the Gateway to eventually transfer funds on its behalf. + +Finally, the `_executeWithToken()` function is also implemented out of the box. + +It makes use of the following params: + +1. `_payload`: The incoming message from the source chain +2. `_tokenSymbol`: The symbol of the token that was sent from the source chain +3. `_amount`: The amount of the token that was sent from the source chain + +Now with these params that were passed in, the `_execute()` function can send the tokens that were sent to the appropriate receivers. + +## Challenge + +Your challenge here is to finish off the `sendToMany()` function using the Axelar Gateway and Gas Service to trigger an interchain transaction. + +In the end you should be able to deploy this contract on two testnets, trigger the `sendToMany()` function and see the live transaction on Axelarscan (testnet) block explorer. + +### Testing Notes + +Note 1: The recommended ERC20 to use is `aUSDC` a wrapped version of the USDC token that can be obtained from the discord faucet bot. When triggering the `sendToMany()` function simply pass in the symbol `aUSDC` to the fourth param. + +Note2: When triggering the `sendToMany()` function you must remember to `approve` your contract to spend `aUSDC` tokens on your behalf, otherwise `transferFrom()` on line49 will throw an error. diff --git a/locales/ko/Interoperability/7_FurtherReading/furtherReading.md b/locales/ko/Interoperability/7_FurtherReading/furtherReading.md new file mode 100644 index 000000000..a601d7ac7 --- /dev/null +++ b/locales/ko/Interoperability/7_FurtherReading/furtherReading.md @@ -0,0 +1,11 @@ +Congratulations on making it to the end of the interoperability module! 🎉🎉 + +To continue your learning journey of interoperability with Axelar. There are many useful resources available. + +- For documentation 📚 + +- For more technical examples 💻 + +- For live coding demos 📹 + +- For the developer blog 📝 diff --git a/locales/ko/Interoperability/README.md b/locales/ko/Interoperability/README.md new file mode 100644 index 000000000..a43fc5dd5 --- /dev/null +++ b/locales/ko/Interoperability/README.md @@ -0,0 +1,3 @@ +## Interoperability Between Blockchains + +Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. diff --git a/locales/ko/Interoperability/config.yml b/locales/ko/Interoperability/config.yml new file mode 100644 index 000000000..39f1be7ed --- /dev/null +++ b/locales/ko/Interoperability/config.yml @@ -0,0 +1,31 @@ +--- +id: interopCourse +name: Multichain Protocols with Axelar +summary: Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. +level: 2 +tags: + - Solidity + - Interoperability + - Axelar +steps: + - + name: An Intro to Axelar + path: 1_Intro + - + name: Axelar Gateway + path: 2_Gateway + - + name: Axelar Gas Service + path: 3_GasService + - + name: Axelar Executable + path: 4_Executable + - + name: Interchain Messages + path: 5_InterchainMessage + - + name: Interchain Token Transfers + path: 6_InterchainTokenTransfer + - + name: Further Reading + path: 7_FurtherReading diff --git a/locales/ko/Multisig-Tutorial/1-multisig-introduction/introduction.md b/locales/ko/Multisig-Tutorial/1-multisig-introduction/introduction.md new file mode 100644 index 000000000..3e9f18938 --- /dev/null +++ b/locales/ko/Multisig-Tutorial/1-multisig-introduction/introduction.md @@ -0,0 +1,41 @@ +Welcome to the Multisignature Wallet course! In this section, we'll explore the fundamentals of Multisignature (Multisig) wallets and we'll go through a multisig wallet contract. + +## What is a Multisignature Wallet? + +A multisignature (multisig) wallet is a type of digital wallet that requires multiple keys to authorize a cryptocurrency transaction. + +Imagine a multisig wallet as a secure vault with multiple locks. To open the vault, each keyholder must open their individual lock. This setup ensures that no single person can access the vault's contents without the others' consent. + +## How Does a Multisig Wallet Work? + +In a multisig setup, each transaction must receive a predetermined number of approvals from a set group of individuals. For instance, in a 3-of-5 wallet configuration, there are five authorized addresses, but a transaction only goes through when at least three of them give their approval. When a transaction is initiated, it's presented as a **proposal** to the group. Each member who agrees to the transaction uses their private key to digitally sign it. + +These **digital signatures** are unique and are generated based on the combination of the transaction data and the private key. + +When the required number of signatures is reached, the transaction is broadcasted to the blockchain for execution. + +## Why Use a Multisig Wallet? + +Multisig wallets are crucial for enhanced security in cryptocurrency transactions. They mitigate the risk of theft or loss of a single key. In business, they're used to ensure that funds can't be moved without consensus among stakeholders. For instance, in a company managing cryptocurrency assets, a multisig wallet might require the CFO, CEO, and a board member to all approve significant transactions, protecting against internal fraud or external hacks. + +## Conclusion + +In this section, we learned that a multisig wallet requires multiple keys to authorize a proposed cryptocurrency transaction and that a multisigs mitigates the risk of theft or loss of a single key. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is a Multisignature Wallet? + +1. A digital wallet that requires a single signature for transactions. +2. A digital wallet that requires multiple signatures for transactions. +3. A physical wallet used for storing cryptocurrency. +4. A wallet that can only hold multiple types of cryptocurrencies. + +### 2) How does a Multisignature Wallet enhance security? + +1. By requiring a single private key for transactions. +2. By distributing transaction approval across multiple owners. +3. By storing transaction data on-chain. +4. None of the above. + +Feel free to take your time and answer the questions above. Once you're ready, we'll move on to exploring the Multisig smart contract and understanding its structure. diff --git a/locales/ko/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md b/locales/ko/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md new file mode 100644 index 000000000..17b0a924f --- /dev/null +++ b/locales/ko/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md @@ -0,0 +1,60 @@ +In this section, we'll explore the **initialization process** of the Multisig smart contract. We'll examine the constructor function and review how it sets up the initial state of the contract. + +## Note + +From this section on in this tutorial, we will be building up a multisig contract. In subsequent sections, the contract will become increasingly complete. + +## Overview + +In this section, the contract consists of events, state variables, modifiers, and functions. **Events** provide transparency by logging specified activities on the blockchain, while **modifiers** ensure that only authorized users can execute certain functions. + +## State Variables + +In Line 4, we have the MultisigWallet contract itself. At the beginning of the contract, we have three state variables. + +1. **`owners`:** An array containing the addresses of all owners of the multi-signature wallet (Line 5). +2. **`isOwner`:** A mapping indicating whether an address is an owner (Line 6). +3. **`numConfirmationsRequired`:** The number of confirmations required for a transaction (Line 7). + +The setup of array and mapping allows us to easily retrieve the list of owners and verify whether an address is an owner. + +## Modifiers + +Next, we have a modifier called `onlyOwner` (Line 9). Modifiers in Solidity are special keywords that can be used to amend the behavior of functions. In our case, the `onlyOwner` modifier ensures that only owners can execute a function. It does this by checking whether the address of the **caller** is an owner. + +## Constructor Function + +The `constructor` function (Line 14) is executed only once during the deployment of the contract. It initializes essential parameters, in this case, the list of owners and the required number of confirmations (Line 14). + +On lines 15 and 16, we have two `require` statements to ensure that the inputs are valid. In this case, we require that there must be at least one owner and that the number of required confirmations must be greater than zero and less than or equal to the number of owners. + +The constructor then initializes the contract state by verifying that is not address(0) (Line 25) and that the owner is unique (Line 26). Then it adds a key/ value pair to the isOwner mapping (Line 28), and then it populates the `owners` array with the provided owner addresses (Line 29). + +Finally, it sets the `numConfirmationsRequired` variable with the specified value (Line 32). + +## getOwners Function + +The `getOwners` function (Line 36) allows users to retrieve the list of owners of the multi-signature wallet. It returns the `owners` array (Line 37). + +## getNumConfirmationsRequired Function + +The `getNumConfirmationsRequired` function (Line 41) allows users to retrieve the number of confirmations required for a transaction. It returns the `numConfirmationsRequired` variable (Line 42). + +## Conclusion + +In this section, we explored the initialization process of the Multisig smart contract. We examined the constructor function and understood how it sets up the initial state of the contract. + +## ⭐️ Assignment: Deploy a Multisig Wallet + +Deploy a Multisig contract with three owners and require two confirmations for transaction execution. + +1. Compile contractInitialization.sol +2. Go to Deploy & Run Transactions in Remix. +3. Expand the "Deploy" section. +4. Under "_OWNERS", enter three an array of three addresses. +5. Under "_NUM_CONFIRMATIONS_REQUIRED", enter the number of confirmations required for a transaction. + +**Hints:** + +- You can get addresses from the "ACCOUNTS" dropdown menu. +- The array of addresses should be in the format: ["0x123...", "0x456...", "0x789..."]. diff --git a/locales/ko/Multisig-Tutorial/3-multisig-deposits/deposits.md b/locales/ko/Multisig-Tutorial/3-multisig-deposits/deposits.md new file mode 100644 index 000000000..a8a14213b --- /dev/null +++ b/locales/ko/Multisig-Tutorial/3-multisig-deposits/deposits.md @@ -0,0 +1,34 @@ +In this section, we'll explore the `receive` function and the associated Deposit event. We'll examine how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## Deposit Event + +On line, 9 we have the Deposit event. The Deposit event is emitted whenever Ether is deposited into the multi-signature wallet. It includes three parameters: + +1. `sender`: The address that sent the Ether. +2. `amount`: The amount of Ether deposited. +3. `balance`: The updated balance of the contract after the deposit. + +We can use the Deposit event to track the flow of Ether into the multi-signature wallet and maybe trigger other actions based on the event. + +## receive Function + +On line 43, we have the `receive` function. The `receive` function is a special function that is executed whenever Ether is sent to the contract. + +The `receive` function is marked as `external` and `payable`. The `external` modifier means that the function can only be called from outside the contract. The `payable` modifier means that the function can receive Ether. + +The `receive` function emits the Deposit event (Line 44) with the address of the sender, the amount of Ether sent, and the updated balance of the contract. It doesn't return anything. + +To receive Ether, a contract must have a `receive`, `fallback`, or a function with the `payable` modifier. If none of these are present, the contract will reject any Ether sent to it. + +## Conclusion + +In this section, we explored the `receive` function and the associated Deposit event. We examined how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## ⭐️ Assignment: Deposit Ether + +Deposit 2 Ether into the Multisig contract. + +1. Deploy the Multisig contract as in the previous assignment. +2. Enter a Value of 2 Ether in the Value field and select Ether in the dropdown menu. +3. At the bottom of your deployed contract in the "Low level interactions" section, click on the "Transact" button. +4. On top of your deployed contract, it should now say "Balance: 2 Ether". diff --git a/locales/ko/Multisig-Tutorial/4-multisig-transactions/transactions.md b/locales/ko/Multisig-Tutorial/4-multisig-transactions/transactions.md new file mode 100644 index 000000000..f62fd48a0 --- /dev/null +++ b/locales/ko/Multisig-Tutorial/4-multisig-transactions/transactions.md @@ -0,0 +1,73 @@ +In this section, we'll explore the process of submitting and confirming transactions. + +## Modifiers + +We have new modifiers in this iteration of the contract. Let's examine them one by one. + +1. **`txExists` modifier:** (Line 13) ensures that the transaction exists. It does this by checking whether the transaction index is less than the length of the `transactions` array. We'll go into more about in this modifier later in this section. +2. **`notExecuted` modifier:** (Line 18) ensures that the transaction has not been executed. It does this by checking whether the `executed` variable of the transaction is false. +3. **`notConfirmed` modifier:** (Line 23) ensures that the transaction has not been confirmed by the caller. It does this by checking whether the `isConfirmed` mapping of the transaction index and the caller's address is false. + +## Transaction Struct + +On line 28, we have a struct called `Transaction`. We store the struct members: `to`, `value`, `data`, `executed`, and `numConfirmations` in individual variables. + +## Mapping of Confirmations + +On line 37, we have a mapping called `isConfirmed`. This mapping is used to keep track of the confirmations of each transaction. It maps the transaction's index to a mapping of an owner addresse to a boolean value. The boolean value indicates whether this owner has confirmed the transaction. + +## Transactions Array + +On line 39, we have an array called `transactions`. The array is used to store all the transactions submitted to the multi-signature wallet. + +## Events + +We have four new events in this iteration of the contract: + +1. **`SubmitTransaction` event:** emitted whenever a transaction is submitted to the multi-signature wallet. +2. **`ConfirmTransaction` event:** emitted whenever a transaction is confirmed by an owner. +3. **`RevokeConfirmation` event:** emitted whenever a transaction confirmation is revoked by an owner. +4. **`ExecuteTransaction` event:** emitted whenever a transaction is executed. + +## submitTransaction Function + +The `submitTransaction` function (Line 78) allows users to submit a transaction to the multi-sig wallet. It takes three parameters: `to`, `value`, and `data`. The `to` parameter is the address of the recipient of the transaction. The `value` parameter is the amount of Ether to be sent. The `data` parameter is the data to be sent to the recipient. Only owners can submit transactions. + +On line, 85 we create a new transaction struct and push it to the `transactions` array and emit the `SubmitTransaction` event. The `txIndex` variable is used to keep track of the transaction index. + +## confirmTransaction Function + +The `confirmTransaction` function (Line 98) allows users to confirm a transaction. It takes one parameter: `txIndex`. +It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. The `onlyOwner` modifier ensures that only owners can confirm transactions. The `txExists` modifier ensures that the transaction exists. The `notExecuted` modifier ensures that the transaction has not been executed. + +On line 101, we store the transaction in a local variable called `transaction`. We then increment the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to true. Finally, we emit the `ConfirmTransaction` event. + +## executeTransaction Function + +The `executeTransaction` function (Line 108) allows users to execute a transaction. On line 113, we require that the number of confirmations of the transaction is greater than or equal to the required number of confirmations. We then set the `executed` variable of the transaction to true. Finally, send the funds using the `call` function. This is the `call` of the recipient address with the value and data of the transaction. If the transaction is successful, we emit the `ExecuteTransaction` event. + +## getTransactionCount Function + +The `getTransactionCount` function (Line 132) allows users to retrieve the number of transactions in the multi-signature wallet. It returns the length of the `transactions` array. + +## getTransaction Function + +The `getTransaction` function (Line 136) allows users to retrieve a transaction. It returns the transaction struct members that we explored earlier in this section. + +## Conclusion + +In this section, we explored the process of submitting, confirming, and executing transactions. We examined the `submitTransaction`, `confirmTransaction`, and `executeTransaction` functions and understood how they work together to allow multiple users to submit and confirm transactions. + +## ⭐️ Assignment: Make a Transaction + +Submit, confirm, and execute a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. Deploy the Multisig contract as in the previous assignment. Make sure that the required number of confirmations is 2. +2. Fund the multisig from any address by sending 4 Ether as you did in the previous assignment. +3. Try sending 2 Ether to the first account in the "ACCOUNTS" dropdown menu. Once you have submitted this transaction (with submitTransaction), click on `getTransactionCount` and should see one transaction or you can click on `getTransaction`, insert 0 as the transaction index and see the transaction you just submitted. +4. Now you can click on `confirmTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. +5. Switch to the second owner account and confirm the transaction again. If you click on `getTransaction` again, you should see that the transaction has been confirmed twice. +6. The last step is to execute the transaction. Click on `executeTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been executed. You can also check the balance of the first account in the "ACCOUNTS" dropdown menu. It should now be 2 Ether higher and the balance of the multi-signature wallet should be 2 Ether lower. + +**Hint:** +If you submit a transaction make sure that the value is in Wei and that the _data field is correctly filled in. E.g. it could look like this: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 2000000000000000000, 0x" for 2 Ether. diff --git a/locales/ko/Multisig-Tutorial/5-multisig-revoke/revoke.md b/locales/ko/Multisig-Tutorial/5-multisig-revoke/revoke.md new file mode 100644 index 000000000..1bf085343 --- /dev/null +++ b/locales/ko/Multisig-Tutorial/5-multisig-revoke/revoke.md @@ -0,0 +1,30 @@ +In this section, we'll explore the process of revoking confirmations. This process is necessary when an owner changes their mind about a transaction and wants to stop it from being executed. This section will be pretty straightforward. + +## revokeConfirmation Event + +On line 14, we have added the `RevokeConfirmation` event. This event is emitted whenever a transaction confirmation is revoked by an owner. + +## revokeConfirmation Function + +On line 129, we have added the `revokeConfirmation` function. It allows users to revoke a transaction confirmation. + +`revokeConfirmation` takes one parameter: `txIndex`. It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. + +On line 134, we require that the transaction has been confirmed by the caller. This ensures that an owner who has confirmed the transaction can only revoke their own confirmation. +We then decrement the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to false. Finally, we emit the `RevokeConfirmation` event. + +## Conclusion + +In this section, we explored the process of revoking confirmations. We examined the `revokeConfirmation` function and understood how it works to allow users to revoke confirmations. + +## ⭐️ Assignment: Revoke a Confirmation + +Confirm and revoke a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. As in the previous assignment, deploy the Multisig contract, send the contract some Ether, and then submit a transaction to the first account in the "ACCOUNTS" dropdown menu with a value of 2 Ether. +2. Confirm the transaction twice as in the previous assignment. +3. Revoke the transaction by clicking on `revokeConfirmation` and inserting 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. + +## Final Conclusion + +In this tutorial, we explored the process of creating a multi-signature wallet. We learned how to initialize the contract, deposit Ether, submit, confirm, and revoke transactions. We also learned how to execute transactions and retrieve information about the multi-signature wallet. diff --git a/locales/ko/Multisig-Tutorial/README.md b/locales/ko/Multisig-Tutorial/README.md new file mode 100644 index 000000000..ae5997802 --- /dev/null +++ b/locales/ko/Multisig-Tutorial/README.md @@ -0,0 +1,5 @@ +## MultiSig Wallet + +Learn how to write a MultiSig Wallet smart contract on Ethereum. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ko/Multisig-Tutorial/config.yml b/locales/ko/Multisig-Tutorial/config.yml new file mode 100644 index 000000000..067de0fb9 --- /dev/null +++ b/locales/ko/Multisig-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: multisigCourse +name: Multisig Wallet +summary: Learn how to create and interact with a multisig wallet. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - Multisig +steps: + - + name: 1. Introduction + path: 1-multisig-introduction + - + name: 2. Initialize the Contract + path: 2-multisig-initialization + - + name: 3. Deposits + path: 3-multisig-deposits + - + name: 4. Transactions + path: 4-multisig-transactions + - + name: 5. Revoking Confirmations + path: 5-multisig-revoke diff --git a/locales/ko/NFTTokenCourse/README.md b/locales/ko/NFTTokenCourse/README.md new file mode 100644 index 000000000..c3d2a183a --- /dev/null +++ b/locales/ko/NFTTokenCourse/README.md @@ -0,0 +1,5 @@ +## Solidity NFT Course + +Learn how to create your own NFTs (non-fungible tokens). + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ko/NFTTokenCourse/config.yml b/locales/ko/NFTTokenCourse/config.yml new file mode 100644 index 000000000..af82db834 --- /dev/null +++ b/locales/ko/NFTTokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: nftTokenCourse +name: Solidity NFT Course +summary: Learn how to create your own NFT tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc721-interface + - + name: 3. Metadata Interface + path: erc721-interface-metadata + - + name: 4. Token Creation + path: erc721-token-creation + - + name: 5. Metadata IPFS + path: erc721-metadata-ipfs + - + name: 6. Deploy to Testnet + path: erc721-deploy-testnet-opensea diff --git a/locales/ko/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md b/locales/ko/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md new file mode 100644 index 000000000..40576500c --- /dev/null +++ b/locales/ko/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md @@ -0,0 +1,50 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to the Rinkeby testnet of the Ethereum blockchain, mint an NFT, and look at it on the NFT marketplace OpenSea. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token for Rinkeby + +In order to make transactions on the testnet, we need Ethereum testnet tokens. + +**2.1** Switch your Metamask from "Ethereum Mainnetwork" to "Rinkeby Test Network". + +**2.2** Go to https://faucet.paradigm.xyz/, enter the address of your account and claim testnet ETH. +You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Contract Deployment + +**3.1** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It should then ask you to connect your account, which you should confirm. Then you should see the Rinkeby network badge under "Injected Web3". + +**3.2** Deploy your token contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. + +### 4. Mint an NFT + +**4.1** Expand your contract in the IDE so you can see the buttons for the functions. + +**4.2** Expand the input fields next to the safeMint button. Enter the Ethereum address of the account that is connected to Remix in the “to:” input field. Enter “0” in the input field "tokenID:". Click on transact. + +**4.3** In Metamask click on assets, then click on the “Import tokens” link, and paste the address of your contract in the input field. You can set decimals to 0. + +You should now see the name of the symbol of your token contract (e.g. GEO) in your “Assets” view in Metamask. You should have one of these tokens. + +### 5. See your NFT on OpenSea + +OpenSea is one of the most popular online marketplace for NFTs. OpenSea also provides a version where you can see assets on the testnet, under https://testnets.opensea.io/ + +**5.1** Go to https://testnets.opensea.io/login. + +**5.2** Connect with your Metamask wallet. You should be redirected to your account https://testnets.opensea.io/account view on OpenSea, where you should be able to see your NFT. You should see the image of your NFT; when you click on it, you should see the name, description, and under properties, also the attributes that you created. + +If you successfully completed this course and are familiar with the basics of Solidity development, we encourage you to continue your learning journey by learning how to create your own NFT auction contract from the Learneth resources. diff --git a/locales/ko/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md b/locales/ko/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md new file mode 100644 index 000000000..a43162feb --- /dev/null +++ b/locales/ko/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md @@ -0,0 +1,44 @@ +The metadata extension is optional. It allows us to add additional information to our ERC721 tokens. We can specify a name, a symbol, and an URI (Uniform Resource Identifier) that can point to a file where we can add even more information in the form of a JSON. + +## ERC721 Metadata Functions + +### name + +The function `name` (line 16) returns the name of the token collection. A token collection means all tokens created with your ERC721 token contract implementation. Every token in this collection will have this name, regardless of their tokenId. + +### symbol + +The function `symbol` (line 21) returns the symbol of the token collection. + +### tokenURI + +The function `tokenURI` (line 26) returns the URI for the token with the id `tokenId`. In this case it’s not the URI of the whole collection but of an individual token in the collection. + +## ERC721 Metadata JSON Schema + +The file that the tokenURI points to should conform to the Metadata JSON Schema as it is specified in the EIP-721. + +``` +{ + "title": "Asset Metadata", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Identifies the asset to which this NFT represents" + }, + "description": { + "type": "string", + "description": "Describes the asset to which this NFT represents" + }, + "image": { + "type": "string", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." + } + } +} +``` + +The root element must be of the type object. This root object should have properties with the keys: name, description, and image that should be all of the type string. + +The ERC721 standard is pretty flexible, the tokenURI does not need to point to a JSON document and the JSON does not need to have all properties and often has additional properties. diff --git a/locales/ko/NFTTokenCourse/erc721-interface/erc721Interface.md b/locales/ko/NFTTokenCourse/erc721-interface/erc721Interface.md new file mode 100644 index 000000000..468e8e640 --- /dev/null +++ b/locales/ko/NFTTokenCourse/erc721-interface/erc721Interface.md @@ -0,0 +1,100 @@ +ERC721 is a standard for token contracts that manage non-fungible tokens (NFTs) on the Ethereum blockchain. + +Each non-fungible token is unique and not interchangeable. NFTs can have different properties, behavior, or rights. Non-fungible tokens are used to represent ownership of unique digital and physical assets like art, collectibles, or real estate. + +If you want to know more about the ERC721 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +The ERC721 standard is more complex than the ERC20 standard and it features optional extensions. ERC721 compliant contracts must, at a minimum, implement the ERC721 and ERC165 interfaces, which we will look at in this section. + +This interface (line 11) is part of the open-source contract library provided by OpenZeppelin. + +## Basic IERC721 Functions + +Contracts compliant with the ERC721 standard have to implement the following functions: + +### balanceOf + +The function `balanceOf` (line 30) returns the amount of tokens owned by the account with the address `owner`. + +### ownerOf + +The function `ownerOf` (line 39) returns the address `owner` of the account that holds the token with the id `tokenId`. + +### safeTransferFrom + +The function `safeTransferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +The function `safeTransferFrom` (line 137) is almost identical to the function `safeTransferFrom` (line 55) .The only difference is that this function has a non-empty payload `data`. + +A smart contract must implement the ERC721TokenReceiver Interface if it is to receive a transfer. This will ensure that the contract can handle ERC721 token transfers and prevent the tokens from being locked in a contract that can’t. + +### transferFrom + +The function `transferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +**It is recommended to use safeTransferFrom instead of transferFrom whenever possible.** +The `transferFrom` function is not secure because it doesn’t check if the smart contract that is the recipient of the transfer has implemented the ERC721TokenReceiver interface and is capable of handling ERC721 tokens. + +## Advanced IERC721 Functions + +### approve + +The function `approve` (line 94) gives the account with the address `to` the permission to manage the token with the id `tokenId` on behalf of the account calling the function. + +### getApproved + +The function `getApproved` (line 103) returns the address of the account (return var `operator`) that is approved to manage the token with the id `tokenId`. + +### setApprovalForAll + +The function `setApprovalForAll` (line 115) sets the permission (`_approved`) for the account with the specified address (input param - `operator`) to manage all tokens of the account calling the function. + +### isApprovedForAll + +The function `getApproved` (line 103) returns the boolean true if the account with the address `operator` is approved to manage all tokens of the account with the address `owner`. + +## IERC721 Events + +ERC721 contracts must also emit the following events: + +### Transfer + +The `Transfer` event (line 15) must be emitted when the token with the id `tokenId` is transferred from the account with the address `from` to the account with the address `to`. + +### Approval + +The `Approval` event (line 20) must be emitted when the account with the address `owner` approves the account with the address `spender` to manage the token with the id `tokenId` on its behalf. + +### ApprovalForAll + +The `ApprovalForAll` event (line 25) must be emitted when the account with the address `owner` gives or removes the permission (`_approved`) of the account with the address `operator` to manage all its tokens. + +## IERC165 + +In addition to the ERC721 interface, ERC721 compliant contracts must also implement the ERC165 interface. + +With the implementation of the ERC165 interface, contracts can declare the support of specific interfaces. A contract that wants to interact with another contract can then query if the other contract supports this interface before making a transaction e.g. sending tokens to it that they might not support. + +Our IERC721 interface here imports (line 6) and inherits (line 11) from the IERC165 interface. + +This is how OpenZeppelins implementation of the ERC165 interface looks like: + +``` +interface IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +For example, the ERC165 identifier for the ERC721 interface as specified in the EIP721 is “0x80ac58cd”. Learn how to calculate an interface identifier and more about the ERC165 in its improvement proposal. + +## Other interfaces + +The IERC721TokenReceiver interface must be implemented to accept safe transfers. + +There are two optional extensions for ERC721 contracts specified in the EIP721: + +IERC721Enumerable enables a contract to publish its full list of tokens and make them discoverable. + +IERC721Metadata enables a contract to associate additional information to a token. We will have a more detailed look into this in the next section. diff --git a/locales/ko/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md b/locales/ko/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md new file mode 100644 index 000000000..27876b068 --- /dev/null +++ b/locales/ko/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md @@ -0,0 +1,101 @@ +In this section, we will create our metadata and store it in a decentralized way. + +IPFS ( InterPlanetary File System) is a peer-to-peer network for storing files in a distributed way. Pinata.cloud is a pinning service that allows users to easily host files on the IPFS network. + +We want to host our images and the JSON files with their metadata on IPFS. + +### Create Image Folder + +In this example, we will create metadata for three tokens. As you can see below, we create three images that we stored in a folder. + +``` +geo-img +├── geo_1.png +├── geo_2.png +├── geo_3.png +``` + +### Register on Pinata + +Now, we want to host these images somewhere so we can point to them in the metadata of our tokens. Let's do it in a decentralized way and use Pinata to host them on IPFS. + +First you need an account on Pinata. Go to Pinata.cloud and create an account. On Pinata you can upload up to 1 GB of data for free. + +Once you have signed up, you should be in the Pin Manager view. + +Pin Manager Pinata + +### Upload Images to IPFS + +Click on the upload button and upload the folder with your images. +Once you've uploaded your folder, you should see the name of your folder and the CID (content identifier) associated with it. If the content in the folder changes, the CID will also change. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P + +You can access a specific image by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png + +### Create JSON files + +We create another folder where we store three JSON files. + +``` +geo-json +├── 0 +├── 1 +├── 2 +``` + +Inside the JSON files, create the metadata for the tokens, like name, description, and image. +For the image URL, we are going to use the URL of our images on IPFS. You can add additional data if you like; in this example, we added some unique attributes for each token. + +This is how the JSON for the first token could look: + +``` +{ + "name": "Geometry#0", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png +", + "attributes": [ + { "trait_type": "background", "value": "cyan" }, + { "trait_type": "color", "value": "red" }, + { "trait_type": "shape", "value": "circle" } + ] +} +``` + +This is how the JSON for the second token could look: + +``` +{ + "name": "Geometry#1", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_2.png", + "attributes": [ + { "trait_type": "background", "value": "magenta" }, + { "trait_type": "color", "value": "green" }, + { "trait_type": "shape", "value": "square" } + ] +} +``` + +As shown above, the folder in this example is called "geo-json". Inside this folder, we have three JSON files. +The first JSON file is called "0", the second JSON file is called "1", and the third JSON file is called "2". + +Make sure that your JSON files don't have a file ending and are named like their corresponding tokenIds. +In the pin manager on pinata.cloud, click on the upload button and upload the folder with your JSON files. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. +For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp +This will become our baseURI. + +You can access a specific JSON file then by just adding a slash and the tokenId by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/0 + +In the contract, replace the baseURI with your own baseURI. In this example, the baseURI consists of the URL +"https://ipfs.io/ipfs/", the CID containing the JSON files, and a slash at the end "/". + +An individual tokenURI will now be created for each token by adding the tokenId to the baseURI — exactly what we did manually in the example above to access the JSON file. diff --git a/locales/ko/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md b/locales/ko/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md new file mode 100644 index 000000000..891fe00a7 --- /dev/null +++ b/locales/ko/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md @@ -0,0 +1,35 @@ +In this contract, we use an ERC721 token contract implementation from OpenZeppelin (line 4). + +Have a look at their implementation of a ERC721 contract. Apart from the functionality specified in the ERC721 standard, the contract provides additional functions which we will see in a bit. + +## myToken + +We create our own contract called MyToken (line 7), which inherits (line 7) the functionality from the OpenZepplin `ERC721` token contract implementation and `Ownable` that we imported (line 4). If you don't remember the Ownable contract module, have a look at the ERC20 extensions section. + +This ERC721 implementation makes use of the IERC721Metadata extension that is specified in the EIP. Our contract inherits the functions `name()` and `symbol()` +and has a constructor that allows their values to be set during the deployment of the contract (line 8). +In this case, we are going to use the default values. We name our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +### Base URI + +With an ERC721 contract, we are able to mint various tokens, each with its own tokenId. As we saw in the IERC721Metadata interface, each token can have its own `tokenURI`, which typically points to a JSON file to store metadata like name, description, and image link. +If a contract mints multiple tokens, ERC721 implementations often use the same URI as a base (`baseURI`) for all tokens and only differentiate them by adding their unique `tokenId` at the end via concatenation. In the next part, we will see what this looks like in practice. + +In this example, we are storing our data on IPFS — more on that in the next section. Our baseURI is https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/ (line 11). +Through concatenation the tokenURI for the token with the id 0 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/0 , the tokenURI for the token with the id 1 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/1, and so on. + +When using IPFS and you run into "504 Gateway Time-out" errors, you might have to wait and retry until the data is available. + +### safeMint + +With the safeMint function (line 14) we enable the owner to create new tokens with a dedicated token id after contract deployment. +The safeMint function is part of the ERC721 implementation of OpenZeppelin and lets us safely mint a token with the id `tokenId` to the account with the address `to`. For access control, we use the `onlyOwner` modifier from the Ownable access control contract module that we imported (line 5). + +In the next section, we will see how we can create and host the metadata for our NFTs. + +## ⭐️ Assignment + +1. Rename your contract to `Geometry`. +2. Rename your token to `Geometry`. +3. Change the symbol of your token to `GEO`. +4. Change the `_baseURI` to https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/. diff --git a/locales/ko/NFTTokenCourse/introduction/introduction.md b/locales/ko/NFTTokenCourse/introduction/introduction.md new file mode 100644 index 000000000..13beea567 --- /dev/null +++ b/locales/ko/NFTTokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with NFTs, tokens created with the ERC721 token standard. + +If you want to learn more about fungible tokens and the ERC20 token standard, have a look at the Learneth ERC20 Token Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain-based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/ko/OpcodesInTheDebugger/1_intro/step.md b/locales/ko/OpcodesInTheDebugger/1_intro/step.md new file mode 100644 index 000000000..c1d9a2448 --- /dev/null +++ b/locales/ko/OpcodesInTheDebugger/1_intro/step.md @@ -0,0 +1,5 @@ +This workshop aims to give a better understanding about how a contract get deployed. +`SimpleStore` is a very basic contract. +It has a very simple constructor - which just uses the first parameter `_o` and saves it to `s`. + +Using the debugger, we'll try to see, what the opcode `CODECOPY` does. diff --git a/locales/ko/OpcodesInTheDebugger/2_memory/step.md b/locales/ko/OpcodesInTheDebugger/2_memory/step.md new file mode 100644 index 000000000..577169a5e --- /dev/null +++ b/locales/ko/OpcodesInTheDebugger/2_memory/step.md @@ -0,0 +1,8 @@ +Before we start, just quick reminder: + +The runtime of the EVM has several kinds of memory: + +- `calldata`: This is the input value given to the transaction. +- `stack`: Basically, this is a list of values, each value is limited in size (32 bytes). +- `memory`: Memory is used when the **type** of value getting stored is more complex like an array or a mapping. This memory is **temporary** and is **released** at the end of the execution. +- `storage`: This is a mapping, each value stored is **persisted** and saved on chain. diff --git a/locales/ko/OpcodesInTheDebugger/3_codecopy/step.md b/locales/ko/OpcodesInTheDebugger/3_codecopy/step.md new file mode 100644 index 000000000..b0c9f7d52 --- /dev/null +++ b/locales/ko/OpcodesInTheDebugger/3_codecopy/step.md @@ -0,0 +1,7 @@ +CODECOPY is one of the many opcodes run by the EVM. Check out the complete list of opcodes at https://ethervm.io/ . + +CODECOPY takes the **running code** (or part of it) and to copies it from the `calldata` to the `memory`. + +The solidity implementation is: **codecopy(t, f, s)** - copy **s** bytes from code at position **f** to memory at position **t**. + +Every contract deployment uses **CODECOPY**. diff --git a/locales/ko/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md b/locales/ko/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md new file mode 100644 index 000000000..63950051d --- /dev/null +++ b/locales/ko/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md @@ -0,0 +1,11 @@ +Let's go back to our contract. +Please make sure the `solidity compiler` and `Deploy & Run Transactions` are activated. + +Alternatively, you can click on `Solidity` from the `Home Page` **Environments** section. + +- Compile the contract from the `solidity compiler`. +- Go to the `Deploy & Run Transactions` and make sure `SimpleStore` is selected contract. +- In the textbox to the right of `Deploy`, input a positive integer. +- Click on `Deploy`. + +In the next step, we'll watch the deployment in the debugger. diff --git a/locales/ko/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md b/locales/ko/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md new file mode 100644 index 000000000..3ef3cd146 --- /dev/null +++ b/locales/ko/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md @@ -0,0 +1,7 @@ +From the Remix terminal, identify the transaction that deployed the contract and click `Debug` + +In the gutter of the editor, put a breakpoint on the line `s = _o`, and click on `Jump to the next Breakpoint` (bottom right button). + +Click on `Step into`, to move along the opcodes until you reach `SSTORE`. + +`SSTORE` is the opcode for storing the value `_o` in the storage. Let's continue further to the `CODECOPY`. diff --git a/locales/ko/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md b/locales/ko/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md new file mode 100644 index 000000000..1480728e6 --- /dev/null +++ b/locales/ko/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md @@ -0,0 +1,57 @@ +The goal here is to store the code in the blockchain. The EVM needs to tell the client (geth, parity) which what part of the **Call Data** to store. In this step, we are saving the contract MINUS its constructor (because that gets inplmented only 1 time) and MINUS the input parameter does not need to be stored. + +`CODECOPY` is the first step: it copies the bytecode to memory, then the ethereum client will be able to consume it. MUNCH! + +But wait... before the client can **MUNCH** bytecode, it needs an instruction - an opcode to tell it to MUNCH. `RETURN` is this opcode! + +As stated in the general spec, at the end of the contract creation, the client (geth, parity) takes the targeted value by the opcode `RETURN` and **persists** it by making it part of the deployed bytecode. + +Once you are in the `CODECOPY`, look at the top 3 items in the **Stack**: + +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x0000000000000000000000000000000000000000000000000000000000000055` +`2: 0x000000000000000000000000000000000000000000000000000000000000003e` + +_In your Stack - `1` & `2` may be slightly different. The difference may be due to a different compiler version._ + +**These are the parameters for `CODECOPY`.** + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +`0` is the offset where the copied code should be placed in the **memory**. In this example, ( all zeros) the code is copied to the beginning of the memory. (**t**) +`1` is the offset in **calldata** where to copy from (**f**) +`2` number of bytes to copy - (**s**) + +After `CODECOPY` is executed, (click the _step into_ button) the copied code should be: +`0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c63430005110032` in memory. **I'll refer to this value as (X)**. + +Let's look at the debugger's **Memory** panel. +The 0x number I gave above is not what you will see in the **Memory** panel -what you will see is this: +0x0: 6080604052600080fdfea265627a7a72 ????R??????ebzzr +0x10: 31582029bb0975555a15a155e2cf28e0 1X ?? uUZ??U???? +0x20: 25c8d492f0613bfb5cbf96399f6dbd4e ?????a?????9?m?N +0x30: a6fc9164736f6c634300051100320000 ???dsolcC????2?? +0x40: 00000000000000000000000000000000 ???????????????? +0x50: 000000000000000000000000000000a0 ??????????????? +0x60: 00000000000000000000000000000000 ???????????????? +0x70: 00000000000000000000000000000000 ???????????????? +0x80: 00000000000000000000000000000000 ???????????????? +0x90: 00000000000000000000000000000002 ???????????????? + +The `0x0`, `0x10`, etc is the position. The next number is the bytecode for that position. This is followed by question marks and seemingly random letters & numbers. This is **Remix**'s attempt to convert this into a string. + +So if we glue the first four sections of bytecode together, we'll get: +**0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e0a6fc9164736f6c63430005110032** The last section - `0x90` has 2 which is what I input for the constructors parameter. + +The input data from the **Call Data** panel is: +`0x6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c634300051100320000000000000000000000000000000000000000000000000000000000000002` +**I'll refer to this value as (Y).** + +This shows us that `(X)` is a subset of the original calldata `(Y)`: + +`(X)` is calldata without the input parameter `0000000000000000000000000000000000000000000000000000000000000002` (we don't need to store this) +and without the constructor code `6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe` which should be executed only 1 time. + +So `CODECOPY` extracts the bytecode from the calldata and copies it to the memory. + +Let's move to the next step. diff --git a/locales/ko/OpcodesInTheDebugger/7_returnAndStore/step.md b/locales/ko/OpcodesInTheDebugger/7_returnAndStore/step.md new file mode 100644 index 000000000..b375a24fb --- /dev/null +++ b/locales/ko/OpcodesInTheDebugger/7_returnAndStore/step.md @@ -0,0 +1,18 @@ +# The Opcode RETURN + +At the end of the last chapter we had moved to one step after **CODECOPY** to see what happened in the memory. + +Now that CODECOPY has been executed, we are on the opcode `PUSH1 00`. + +`PUSH1 00` prepares the stack for the `RETURN` opcode. +`RETURN` is the last part of this process. It is where the code is returned to the client. + +We push `00` to the stack because this is the offset position of the contract bytecode in memory. + +Now we can call the all important `RETURN` opcode. + +The **stack inspector** shows: +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x000000000000000000000000000000000000000000000000000000000000003e` + +Which is to say it returns to the client the bytecode starting `0x00` with length `0x3e`. diff --git a/locales/ko/OpcodesInTheDebugger/8_findTheOffset/step.md b/locales/ko/OpcodesInTheDebugger/8_findTheOffset/step.md new file mode 100644 index 000000000..6b1ddc5cf --- /dev/null +++ b/locales/ko/OpcodesInTheDebugger/8_findTheOffset/step.md @@ -0,0 +1,18 @@ +# Find the offset ;) + +And now for a slightly different example: + +- Compile notSimpleStore.sol +- Deploy the contract `notSoSimpleStore` +- Make sure you have a successful deployment - if not check that you used **the correct input type** in the constructor. +- Go to the Debugger by clicking the **debug** button at the (successful) creation transaction. +- Find the value of the parameter of `CODECOPY` which represents the offset in calldata where to copy from. + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +If you look in the **Stack**, you should see that the 2nd element is: +0x0000000000000000000000000000000000000000000000000000000000000083 + +And this is the **f** of the input params of codecopy. + +### Hope you picked up a thing or 2 about how opcodes work! diff --git a/locales/ko/OpcodesInTheDebugger/config.yml b/locales/ko/OpcodesInTheDebugger/config.yml new file mode 100644 index 000000000..74a1bf3a1 --- /dev/null +++ b/locales/ko/OpcodesInTheDebugger/config.yml @@ -0,0 +1,10 @@ +--- +id: opcodesdebug +name: Opcodes in the Debugger +summary: Using the Debugger, we'll check out what the CODECOPY opcode does and how it is used by the EVM during contract creation. +level: 3 +tags: + - Remix + - Debugging + - EVM + - Opcodes diff --git a/locales/ko/ProxyContract/1_Why/step1.md b/locales/ko/ProxyContract/1_Why/step1.md new file mode 100644 index 000000000..b4a38aaeb --- /dev/null +++ b/locales/ko/ProxyContract/1_Why/step1.md @@ -0,0 +1,27 @@ +# Proxy Contract AKA the Dispatcher + +## Why? + +This is a great pattern that is used mainly in **library development**. + +It helps in the following ways: + +- **Save gas cost at deployment time** + The purpose of a high gas cost is to discourage the operations that cost a lot for their execution and to encourage optimized code. + +- Proxy contracts are useful when a lot of instances of the same contract need to be deployed because they reduce the duplications in the deployment. + +- **Avoid code repetition in the blockchain.** + Heavy computations are expensive because every node will need to perform them, this is of course slowing the network. + +- **Develop upgradable(versioned) contracts** + When the contract is deployed, it’s immutable. By re-designing the code into different contracts, it is possible to allow logic upgrades while keeping the storage the same. + +## Example of gas cost + +Storing contract code at creation time can cost up to: + +- 200 \* max_byte_code_length gas +- 200 \* 24576 = 49152004915200 \* 10 gwei = 49152000 gwei = 0.049152 ether = 9 EUR + +see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md for more info on max_byte_code_length. diff --git a/locales/ko/ProxyContract/2_How/step2.md b/locales/ko/ProxyContract/2_How/step2.md new file mode 100644 index 000000000..d80b6557c --- /dev/null +++ b/locales/ko/ProxyContract/2_How/step2.md @@ -0,0 +1,13 @@ +# How it works? + +**EIP-7 DelegateCall** opcode allows a separate execution in another contract while maintaining the original execution context. + +All **message calls** from the user go through a **Proxy contract**. + +The **Proxy contract** then will redirect them to the **Logic contract**. + +And when you need to **upgrade** the logic, you'll **just** deploy that - **HOWEVER** - the implementation of Proxy will remain the same. + +You'll only need to update the address of Logic contract in Proxy. + +The Proxy Contract uses **Delegate calls** and **Solidity assembly** because without it, it's impossible to return any value from **delegatecall**. diff --git a/locales/ko/ProxyContract/3_Delegatecall/step3.md b/locales/ko/ProxyContract/3_Delegatecall/step3.md new file mode 100644 index 000000000..8693e5567 --- /dev/null +++ b/locales/ko/ProxyContract/3_Delegatecall/step3.md @@ -0,0 +1,9 @@ +# Delegate call + +It's a special variant of a **message call**, which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract so **msg.sender** and **msg.value** do not change their values. + +This means that a contract can dynamically load code from a different address at runtime. + +The storage, the current address and balance still refer to the calling contract, only the code is taken from the called address. + +So when a **Proxy** delegates calls to the Logic contract, every storage modification will impact the storage of Logic contract. diff --git a/locales/ko/ProxyContract/4_Generic_proxy_example/step4.md b/locales/ko/ProxyContract/4_Generic_proxy_example/step4.md new file mode 100644 index 000000000..d20fdd16d --- /dev/null +++ b/locales/ko/ProxyContract/4_Generic_proxy_example/step4.md @@ -0,0 +1,15 @@ +# A Basic Generic Proxy Example + +In the associated solidity file, **step4.sol**, there are 2 contracts - **ProxyContract** and **LogicContract**. + +To use this system, we first deploy the LogicContract. + +And then when we go to deploy the ProxyContract, we pass the LogicContract's address as an argument of the ProxyContract's constructor. + +The ProxyContract is deployed only once. + +The code of LogicContract will be called at the line 20. It will be forwarded with delegate call while keeping the context of LogicContract. + +In case we need to change the logic we would deploy a new LogicContract and set the address of it with setLogicContractAddress setter function. + +_Note: The LogicContract we have here does not use the storage. Once you need to use the storage the implementation becomes a bit more complicated because those contracts share the context._ diff --git a/locales/ko/ProxyContract/5_Test/step5.md b/locales/ko/ProxyContract/5_Test/step5.md new file mode 100644 index 000000000..120a15e13 --- /dev/null +++ b/locales/ko/ProxyContract/5_Test/step5.md @@ -0,0 +1,6 @@ +# Let's test what we've learned + +- Write a contract named "LogicContract" which implements a public function named "getNumber" which returns 10 +- Write a proxy contract named "ProxyContract". This ProxyContract should take an address of LogicContract as a first parameter. + +Good Luck! diff --git a/locales/ko/ProxyContract/6_Storage_Problem/step6.md b/locales/ko/ProxyContract/6_Storage_Problem/step6.md new file mode 100644 index 000000000..d2b804284 --- /dev/null +++ b/locales/ko/ProxyContract/6_Storage_Problem/step6.md @@ -0,0 +1,13 @@ +# What if we have state variables? + +Things are more complicated once we need to deal with state variables. State variable are saved to **storage**. + +`storage`: is a mapping; each value stored there is persisted and saved on chain. + +_Note: Statically-sized state variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position 0. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible. For contracts that use inheritance, the ordering of state variables is determined by the C3-linearized order of contracts starting with the most base-ward contract_ + +Once we execute **delegate call**, the storage of both contracts get **"merged"** into a single messy state. + +We have to "tell" ProxyContract what the **state** of the **Logic contract** looks like. + +The easiest way to do this is to create a separate contract - in this example - named **StorageContract** which will represent the **state** and which proxyContract will inherit from. diff --git a/locales/ko/ProxyContract/7_links/step7.md b/locales/ko/ProxyContract/7_links/step7.md new file mode 100644 index 000000000..c2784c3cc --- /dev/null +++ b/locales/ko/ProxyContract/7_links/step7.md @@ -0,0 +1,19 @@ +# Check out some links for more info + +- ERC DelegateProxy + https://github.com/ethereum/EIPs/pull/897 + +- The joint post by Zeppelin Solutions and Aragon. + https://blog.openzeppelin.com/proxy-libraries-in-solidity-79fbe4b970fd/ + +- Proxy Patterns by OpenZeppelin + https://blog.openzeppelin.com/proxy-patterns/ + +- The most mature implementation of Proxy pattern is The Unstructure Storage pattern that is released as part of ZeppelinOS + https://blog.openzeppelin.com/upgradeability-using-unstructured-storage/ + +- Great blog post by Jack Tanner + https://blog.indorse.io/ethereum-upgradeable-smart-contract-strategies-456350d0557c + +- Upgradeable Ethereum Smart Contracts + https://medium.com/@daonomic/upgradeable-ethereum-smart-contracts-d036cb373d6 diff --git a/locales/ko/ProxyContract/README.md b/locales/ko/ProxyContract/README.md new file mode 100644 index 000000000..6a5364c94 --- /dev/null +++ b/locales/ko/ProxyContract/README.md @@ -0,0 +1,3 @@ +## Learn the Proxy Pattern + +Save gas & make upgradable contracts diff --git a/locales/ko/ProxyContract/config.yml b/locales/ko/ProxyContract/config.yml new file mode 100644 index 000000000..e36e640b8 --- /dev/null +++ b/locales/ko/ProxyContract/config.yml @@ -0,0 +1,9 @@ +--- +id: proxycontract +name: All about Proxy Contracts +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 3 +tags: + - Remix + - Solidity + - Code Patterns diff --git a/locales/ko/README.md b/locales/ko/README.md new file mode 100644 index 000000000..cb799bd20 --- /dev/null +++ b/locales/ko/README.md @@ -0,0 +1,36 @@ +# This is a repo of tutorials for the Remix's LearnEth Plugin + +### To use these tutorials: + +**1. Open Remix** + +https://remix.ethereum.org + +**2. In the plugin manager activate LEARNETH** + +**3. Go to the Learneth plugin and these tutorials will load by default** + +**4. You may need to sign into Github especially during an in-person workshop** + +Github will block too many requests from the same location, unless you are signed into Github and have input your token. Generally, this is only an issue during in person workshops, when there can be many requests from the same location. + +To input your Github token: + +``` +- In one browser window - go to https://remix.ethereum.org and go to the settings tab +- In another browser window go to: + +https://github.com/settings/tokens + +and create a new token and save it in Remix in the you just opened on the settings tab. +``` + +--- + +### Write your own tutorials for LEARNETH: + +See this site for instructions: + +https://remix-learneth-plugin.readthedocs.io/en/latest/index.html#creating-tutorials + +--- diff --git a/locales/ko/Recorder/1_Usecases/1_usecases.md b/locales/ko/Recorder/1_Usecases/1_usecases.md new file mode 100644 index 000000000..0c624393c --- /dev/null +++ b/locales/ko/Recorder/1_Usecases/1_usecases.md @@ -0,0 +1,7 @@ +1. You want to show someone what happens when you do a number of transactions with a contract and you don't want to explain each step - you just want to get them to the last step. + + - To show someone a problem in their code. + + - In a class, to get the students to a certain place and have them start working from there. + +2. You want to start your development in the JavascriptVM because it is quick and then to switch to another testnet - but you don't want to manually repeat all the tedious clicking for each different network. diff --git a/locales/ko/Recorder/2_Record/README.md b/locales/ko/Recorder/2_Record/README.md new file mode 100644 index 000000000..41d214277 --- /dev/null +++ b/locales/ko/Recorder/2_Record/README.md @@ -0,0 +1,32 @@ +# Setting up a tedious series of steps + +## Following this could get tedious but that's the point. + +We are going to: + +- Deploy a voting contract where there are 3 proposals input in the constructor. +- Give voting privileges to 2 additional address (so we have a total of 3 voting addresses). +- Have one address vote for proposal 1 (0-based index) and the other two vote for proposal 2. + +1. Take the 3_Ballot.sol from the sample solidity files and compile it. Then go to the **Deploy & Run** Module. + +2. Select the **JavaScript VM** Environment. + +3. In the constructor's parameter - put in **["0x5031000000000000000000000000000000000000000000000000000000000000", "0x5032000000000000000000000000000000000000000000000000000000000000", "0x5033000000000000000000000000000000000000000000000000000000000000"]** Then click the **Deploy** button. + +4. Open up the deployed contract. + +5. In the **vote** function put in 2. This means that you as the msg.sender & chairperson are voting for proposal at position 2, which is the last proposal in our list. + +6. Now you need to give other addresses the right to vote. Select another address in the **account** pulldown and copy it and then **go back to the 1st address**. Paste the copy address into the textbox next to the giveRightToVote function. And again, select another address and copy it and **then go back to the 1st address** again and paste it into giveRightToVote. + +7. Now you have 3 addresses with the right to vote. + +8. Switch to one of the addresses that you gave the right to vote and vote for proposal **1**. (Put **1** in the textbox next to the vote function). And then switch to the other address and vote for proposal **2** with that one. + +9. Open up the **Transactions recorded** section of the module - by clicking on the caret. Click the hard disk icon in the **Transactions recorded** section to save your steps. + ![recorder](https://github.com/ethereum/remix-workshops/blob/master/Recorder/2_Record/images/recorder.png?raw=true "recorder") + +10. You will get a modal window that tells you it wants to save a file called **scenario.json**. Click OK. + +11. Click on the function **winningProposal** to confirm that the final proposal won - which is the proposal at position 2 in the array. **0: uint256: winningProposal_ 2** diff --git a/locales/ko/Recorder/3_Editing_a_Senario/README.md b/locales/ko/Recorder/3_Editing_a_Senario/README.md new file mode 100644 index 000000000..d23dfb95c --- /dev/null +++ b/locales/ko/Recorder/3_Editing_a_Senario/README.md @@ -0,0 +1,54 @@ +# Editing a scenario + +Here's the first few lines of the scenario that I recorded. The addresses on my machine will be different from your's. + +``` +{ + "accounts": { + "account{0}": "0xca35b7d915458ef540ade6068dfe2f44e8fa733c", + "account{4}": "0xdd870fa1b7c4700f2bd7f44238821c26f7392148", + "account{3}": "0x583031d1113ad414f02576bd6afabfb302140225" + } +``` + +So if you wanted to play this scenario in another testnet, you'd need to change these addresses to address that you have test ETH on so that you could pay for the transactions. But other than swapping out the addresses, you can quickly run this on other nets. + +And you might change the parameters for the functions. + +For example here is a bit of the scenario.json a bit further down where proposal 2 was voted for by one of the addresses: + +``` +{ + "timestamp": 1566428184043, + "record": { + "value": "0", + "parameters": [ + "2" + ], + "to": "created{1566428035436}", + "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", + "name": "vote", + "inputs": "(uint8)", + "type": "function", + "from": "account{4}" + } + }, +``` + +Let's edit this so that another proposal wins in the playback. + +Change the **parameters** array which now is: + +``` +"parameters": [ + "2" + ] +``` + +to: + +``` +"parameters": [ + "1" + ] +``` diff --git a/locales/ko/Recorder/4_Play/README.md b/locales/ko/Recorder/4_Play/README.md new file mode 100644 index 000000000..196664550 --- /dev/null +++ b/locales/ko/Recorder/4_Play/README.md @@ -0,0 +1,8 @@ +# Playing a scenario + +1. Click the play icon to the right of the floppy disk icon to play the steps you did. + +2. You'll see another instance of the contract deployed. Open it up. + +3. Click the winningProposal function and you should see now that proposal 1 won. + It should print out: **0: uint256: winningProposal_ 1** diff --git a/locales/ko/Recorder/README.md b/locales/ko/Recorder/README.md new file mode 100644 index 000000000..94d928383 --- /dev/null +++ b/locales/ko/Recorder/README.md @@ -0,0 +1,3 @@ +## Get yourself Remixing! + +The recorder is used for recording a set of transactions in the Deploy & Run module, editing their parameters and then playing them back in another context. It really is the remix of Remix! diff --git a/locales/ko/Recorder/config.yml b/locales/ko/Recorder/config.yml new file mode 100644 index 000000000..b8980e042 --- /dev/null +++ b/locales/ko/Recorder/config.yml @@ -0,0 +1,7 @@ +--- +id: recorder +name: Recorder +summary: Save a set of actions and replay and replay and replay +level: 2 +tags: + - Remix diff --git a/locales/ko/SolidityBeginnerCourse/README.md b/locales/ko/SolidityBeginnerCourse/README.md new file mode 100644 index 000000000..ae0b6d882 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Course + +Learn the most important Solidity beginner concepts interactively, based on the popular https://solidity-by-example.org/ contracts. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ko/SolidityBeginnerCourse/basic-syntax/basicSyntax.md b/locales/ko/SolidityBeginnerCourse/basic-syntax/basicSyntax.md new file mode 100644 index 000000000..e9f77871e --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/basic-syntax/basicSyntax.md @@ -0,0 +1,26 @@ +In this section, we will create our first _smart contract_. This contract only consists of a string that holds the value "Hello World!". + +In the first line, we should specify the license that we want to use. You can find a comprehensive list of licenses here: https://spdx.org/licenses/. + +Using the `pragma` keyword (line 3), we specify the Solidity version we want the compiler to use. In this case, it should be greater than or equal to `0.8.3` but less than 0.9.0. + +We define a contract with the keyword `contract` and give it a name, in this case, `HelloWorld` (line 5). + +Inside our contract, we define a _state variable_ `greet` that holds the string `"Hello World!"` (line 6). + +Solidity is a _statically typed_ language, which means that you need to specify the type of the variable when you declare it. In this case, `greet` is a `string`. + +We also define the _visibility_ of the variable, which specifies from where you can access it. In this case, it's a `public` variable that you can access from inside and outside the contract. + +Don't worry if you didn't understand some concepts like _visibility_, _data types_, or _state variables_. We will look into them in the following sections. + +To help you understand the code, we will link in all following sections to video tutorials from the creator of the Solidity by Example contracts. + +Watch a video tutorial on Basic Syntax. + +## ⭐️ Assignment + +1. Delete the HelloWorld contract and its content. +2. Create a new contract named "MyContract". +3. The contract should have a public state variable called "name" of the type string. +4. Assign the value "Alice" to your new variable. diff --git a/locales/ko/SolidityBeginnerCourse/config.yml b/locales/ko/SolidityBeginnerCourse/config.yml new file mode 100644 index 000000000..a729093d8 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/config.yml @@ -0,0 +1,65 @@ +--- +id: soliditybeginner +name: Solidity Beginner Course +summary: Solidity Beginner Course based on the popular https://solidity-by-example.org/ contracts. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Basic Syntax + path: basic-syntax + - + name: 3. Primitive Data Types + path: primitive-data-types + - + name: 4. Variables + path: variables + - + name: 5.1 Functions - Reading and Writing to a State Variable + path: functions-reading-and-writing + - + name: 5.2 Functions - View and Pure + path: functions-view-and-pure + - + name: 5.3 Functions - Modifiers and Constructors + path: functions-modifiers-and-constructors + - + name: 5.4 Functions - Inputs and Outputs + path: functions-inputs-and-outputs + - + name: 6. Visibility + path: visibility + - + name: 7.1 Control Flow - If/Else + path: control-flow-if-else + - + name: 7.2 Control Flow - Loops + path: control-flow-loops + - + name: 8.1 Data Structures - Arrays + path: data-structures-arrays + - + name: 8.2 Data Structures - Mappings + path: data-structures-mappings + - + name: 8.3 Data Structures - Structs + path: data-structures-structs + - + name: 8.4 Data Structures - Enums + path: data-structures-enums + - + name: 9. Data Locations + path: data-locations + - + name: 10.1 Transactions - Ether and Wei + path: transactions-ether-and-wei + - + name: 10.2 Transactions - Gas and Gas Price + path: transactions-gas-and-gas-price + - + name: 10.3 Transactions - Sending Ether + path: transactions-sending-ether diff --git a/locales/ko/SolidityBeginnerCourse/control-flow-if-else/ifElse.md b/locales/ko/SolidityBeginnerCourse/control-flow-if-else/ifElse.md new file mode 100644 index 000000000..634e27689 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/control-flow-if-else/ifElse.md @@ -0,0 +1,33 @@ +Solidity supports different control flow statements that determine which parts of the contract will be executed. The conditional _If/Else statement_ enables contracts to make decisions depending on whether boolean conditions are either `true` or `false`. + +Solidity differentiates between three different If/Else statements: `if`, `else`, and `else if`. + +### if + +The `if` statement is the most basic statement that allows the contract to perform an action based on a boolean expression. + +In this contract’s `foo` function (line 5) the if statement (line 6) checks if `x` is smaller than `10`. If the statement is true, the function returns `0`. + +### else + +The `else` statement enables our contract to perform an action if conditions are not met. + +In this contract, the `foo` function uses the `else` statement (line 10) to return `2` if none of the other conditions are met. + +### else if + +With the `else if` statement we can combine several conditions. + +If the first condition (line 6) of the foo function is not met, but the condition of the `else if` statement (line 8) becomes true, the function returns `1`. + +Watch a video tutorial on the If/Else statement. + +## ⭐️ Assignment + +Create a new function called `evenCheck` in the `IfElse` contract: + +- That takes in a `uint` as an argument. +- The function returns `true` if the argument is even, and `false` if the argument is odd. +- Use a ternery operator to return the result of the `evenCheck` function. + +Tip: The modulo (%) operator produces the remainder of an integer division. diff --git a/locales/ko/SolidityBeginnerCourse/control-flow-loops/loops.md b/locales/ko/SolidityBeginnerCourse/control-flow-loops/loops.md new file mode 100644 index 000000000..ffaa30650 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/control-flow-loops/loops.md @@ -0,0 +1,32 @@ +Solidity supports iterative control flow statements that allow contracts to execute code repeatedly. + +Solidity differentiates between three types of loops: `for`, `while`, and `do while` loops. + +### for + +Generally, `for` loops (line 7) are great if you know how many times you want to execute a certain block of code. In solidity, you should specify this amount to avoid transactions running out of gas and failing if the amount of iterations is too high. + +### while + +If you don’t know how many times you want to execute the code but want to break the loop based on a condition, you can use a `while` loop (line 20). +Loops are seldom used in Solidity since transactions might run out of gas and fail if there is no limit to the number of iterations that can occur. + +### do while + +The `do while` loop is a special kind of while loop where you can ensure the code is executed at least once, before checking on the condition. + +### continue + +The `continue` statement is used to skip the remaining code block and start the next iteration of the loop. In this contract, the `continue` statement (line 10) will prevent the second if statement (line 12) from being executed. + +### break + +The `break` statement is used to exit a loop. In this contract, the break statement (line 14) will cause the for loop to be terminated after the sixth iteration. + +Watch a video tutorial on Loop statements. + +## ⭐️ Assignment + +1. Create a public `uint` state variable called count in the `Loop` contract. +2. At the end of the for loop, increment the count variable by 1. +3. Try to get the count variable to be equal to 9, but make sure you don’t edit the `break` statement. diff --git a/locales/ko/SolidityBeginnerCourse/data-locations/dataLocations.md b/locales/ko/SolidityBeginnerCourse/data-locations/dataLocations.md new file mode 100644 index 000000000..881bf8ffc --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/data-locations/dataLocations.md @@ -0,0 +1,54 @@ +The values of variables in Solidity can be stored in different data locations: _memory_, _storage_, and _calldata_. + +As we have discussed before, variables of the value type store an independent copy of a value, while variables of the reference type (array, struct, mapping) only store the location (reference) of the value. + +If we use a reference type in a function, we have to specify in which data location their values are stored. The price for the execution of the function is influenced by the data location; creating copies from reference types costs gas. + +### Storage + +Values stored in _storage_ are stored permanently on the blockchain and, therefore, are expensive to use. + +In this contract, the state variables `arr`, `map`, and `myStructs` (lines 5, 6, and 10) are stored in storage. State variables are always stored in storage. + +### Memory + +Values stored in _memory_ are only stored temporarily and are not on the blockchain. They only exist during the execution of an external function and are discarded afterward. They are cheaper to use than values stored in _storage_. + +In this contract, the local variable `myMemstruct` (line 19), as well as the parameter `_arr` (line 31), are stored in memory. Function parameters need to have the data location _memory_ or _calldata_. + +### Calldata + +_Calldata_ stores function arguments. Like _memory_, _calldata_ is only stored temporarily during the execution of an external function. In contrast to values stored in _memory_, values stored in _calldata_ can not be changed. Calldata is the cheapest data location to use. + +In this contract, the parameter `_arr` (line 35) has the data location _calldata_. If we wanted to assign a new value to the first element of the array `_arr`, we could do that in the `function g` (line 31) but not in the `function h` (line 35). This is because `_arr` in `function g `has the data location _memory_ and _function h_ has the data location `calldata`. + +## Assignments + +### Memory to memory + +Assignments from _memory_ to _memory_ create references instead of copies. If you change the value in one variable, the value of all other variables that reference the same data will be changed. + +If we were to create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myMemStruct` (line 19), any change to `myMemStruct2` would also change the value of `myMemStruct`. + +### Storage to local storage + +Assignments from _storage_ to _local storage_ also create references, not copies. + +If we change the value of the local variable `myStruct` (line 17), the value of our state variable `myStructs` (line 10) changes as well. + +## Storage and memory/calldata + +Assignments between _storage_ and _memory_ (or _calldata_) create independent copies, not references. + +If we were to create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myStruct`, changes in `myMemStruct3` would not affect the values stored in the mapping `myStructs` (line 10). + +As we said in the beginning, when creating contracts we have to be mindful of gas costs. Therefore, we need to use data locations that require the lowest amount of gas possible. + +## ⭐️ Assignment + +1. Change the value of the `myStruct` member `foo`, inside the `function f`, to 4. +2. Create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` and assign it the value of `myMemStruct`. Change the value of the `myMemStruct2` member `foo` to 1. +3. Create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` and assign it the value of `myStruct`. Change the value of the `myMemStruct3` member `foo` to 3. +4. Let the function f return `myStruct`, `myMemStruct2`, and `myMemStruct3`. + +Tip: Make sure to create the correct return types for the function `f`. diff --git a/locales/ko/SolidityBeginnerCourse/data-structures-arrays/arrays.md b/locales/ko/SolidityBeginnerCourse/data-structures-arrays/arrays.md new file mode 100644 index 000000000..19af3de49 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/data-structures-arrays/arrays.md @@ -0,0 +1,44 @@ +In the next sections, we will look into the data structures that we can use to organize and store our data in Solidity. + +_Arrays_, _mappings_ and _structs_ are all _reference types_. Unlike _value types_ (e.g. _booleans_ or _integers_) reference types don't store their value directly. Instead, they store the location where the value is being stored. Multiple reference type variables could reference the same location, and a change in one variable would affect the others, therefore they need to be handled carefully. + +In Solidity, an array stores an ordered list of values of the same type that are indexed numerically. + +There are two types of arrays, compile-time _fixed-size_ and _dynamic arrays_. For fixed-size arrays, we need to declare the size of the array before it is compiled. The size of dynamic arrays can be changed after the contract has been compiled. + +### Declaring arrays + +We declare a fixed-size array by providing its type, array size (as an integer in square brackets), visibility, and name (line 9). + +We declare a dynamic array in the same manner. However, we don’t provide an array size and leave the brackets empty (line 6). + +### Initializing arrays + +We can initialize the elements of an array all at once (line 7), or initiate new elements one by one (arr[0] = 1;). If we declare an array, we automatically initialize its elements with the default value 0 (line 9). + +### Accessing array elements + +We access elements inside an array by providing the name of the array and the index in brackets (line 12). + +### Adding array elements + +Using the `push()` member function, we add an element to the end of a dynamic array (line 25). + +### Removing array elements + +Using the `pop()` member function, we delete the last element of a dynamic array (line 31). + +We can use the `delete` operator to remove an element with a specific index from an array (line 42). +When we remove an element with the `delete` operator all other elements stay the same, which means that the length of the array will stay the same. This will create a gap in our array. +If the order of the array is not important, then we can move the last element of the array to the place of the deleted element (line 46), or use a mapping. A mapping might be a better choice if we plan to remove elements in our data structure. + +### Array length + +Using the length member, we can read the number of elements that are stored in an array (line 35). + +Watch a video tutorial on Arrays. + +## ⭐️ Assignment + +1. Initialize a public fixed-sized array called `arr3` with the values 0, 1, 2. Make the size as small as possible. +2. Change the `getArr()` function to return the value of `arr3`. diff --git a/locales/ko/SolidityBeginnerCourse/data-structures-enums/enums.md b/locales/ko/SolidityBeginnerCourse/data-structures-enums/enums.md new file mode 100644 index 000000000..40411db67 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/data-structures-enums/enums.md @@ -0,0 +1,33 @@ +In Solidity _enums_ are custom data types consisting of a limited set of constant values. We use enums when our variables should only get assigned a value from a predefined set of values. + +In this contract, the state variable `status` can get assigned a value from the limited set of provided values of the enum `Status` representing the various states of a shipping status. + +### Defining enums + +We define an enum with the enum keyword, followed by the name of the custom type we want to create (line 6). Inside the curly braces, we define all available members of the enum. + +### Initializing an enum variable + +We can initialize a new variable of an enum type by providing the name of the enum, the visibility, and the name of the variable (line 16). Upon its initialization, the variable will be assigned the value of the first member of the enum, in this case, Pending (line 7). + +Even though enum members are named when you define them, they are stored as unsigned integers, not strings. They are numbered in the order that they were defined, the first member starting at 0. The initial value of status, in this case, is 0. + +### Accessing an enum value + +To access the enum value of a variable, we simply need to provide the name of the variable that is storing the value (line 25). + +### Updating an enum value + +We can update the enum value of a variable by assigning it the `uint` representing the enum member (line 30). Shipped would be 1 in this example. Another way to update the value is using the dot operator by providing the name of the enum and its member (line 35). + +### Removing an enum value + +We can use the delete operator to delete the enum value of the variable, which means as for arrays and mappings, to set the default value to 0. + +Watch a video tutorial on Enums. + +## ⭐️ Assignment + +1. Define an enum type called `Size` with the members `S`, `M`, and `L`. +2. Initialize the variable `sizes` of the enum type `Size`. +3. Create a getter function `getSize()` that returns the value of the variable `sizes`. diff --git a/locales/ko/SolidityBeginnerCourse/data-structures-mappings/mappings.md b/locales/ko/SolidityBeginnerCourse/data-structures-mappings/mappings.md new file mode 100644 index 000000000..72fc4acb4 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/data-structures-mappings/mappings.md @@ -0,0 +1,37 @@ +In Solidity, _mappings_ are a collection of key types and corresponding value type pairs. + +The biggest difference between a mapping and an array is that you can't iterate over mappings. If we don't know a key we won't be able to access its value. If we need to know all of our data or iterate over it, we should use an array. + +If we want to retrieve a value based on a known key we can use a mapping (e.g. addresses are often used as keys). Looking up values with a mapping is easier and cheaper than iterating over arrays. If arrays become too large, the gas cost of iterating over it could become too high and cause the transaction to fail. + +We could also store the keys of a mapping in an array that we can iterate over. + +### Creating mappings + +Mappings are declared with the syntax `mapping(KeyType => ValueType) VariableName`. +The key type can be any built-in value type or any contract, but not a reference type. The value type can be of any type. + +In this contract, we are creating the public mapping `myMap` (line 6) that associates the key type `address` with the value type `uint`. + +### Accessing values + +The syntax for interacting with key-value pairs of mappings is similar to that of arrays. +To find the value associated with a specific key, we provide the name of the mapping and the key in brackets (line 11). + +In contrast to arrays, we won't get an error if we try to access the value of a key whose value has not been set yet. When we create a mapping, every possible key is mapped to the default value 0. + +### Setting values + +We set a new value for a key by providing the mapping’s name and key in brackets and assigning it a new value (line 16). + +### Removing values + +We can use the delete operator to delete a value associated with a key, which will set it to the default value of 0. As we have seen in the arrays section. + +Watch a video tutorial on Mappings. + +## ⭐️ Assignment + +1. Create a public mapping `balances` that associates the key type `address` with the value type `uint`. +2. Change the functions `get` and `remove` to work with the mapping balances. +3. Change the function `set` to create a new entry to the balances mapping, where the key is the address of the parameter and the value is the balance associated with the address of the parameter. diff --git a/locales/ko/SolidityBeginnerCourse/data-structures-structs/structs.md b/locales/ko/SolidityBeginnerCourse/data-structures-structs/structs.md new file mode 100644 index 000000000..fba0d93b0 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/data-structures-structs/structs.md @@ -0,0 +1,29 @@ +In Solidity, we can define custom data types in the form of _structs_. Structs are a collection of variables that can consist of different data types. + +### Defining structs + +We define a struct using the `struct` keyword and a name (line 5). Inside curly braces, we can define our struct’s members, which consist of the variable names and their data types. + +### Initializing structs + +There are different ways to initialize a struct. + +Positional parameters: We can provide the name of the struct and the values of its members as parameters in parentheses (line 16). + +Key-value mapping: We provide the name of the struct and the keys and values as a mapping inside curly braces (line 19). + +Initialize and update a struct: We initialize an empty struct first and then update its member by assigning it a new value (line 23). + +### Accessing structs + +To access a member of a struct we can use the dot operator (line 33). + +### Updating structs + +To update a structs’ member we also use the dot operator and assign it a new value (lines 39 and 45). + +Watch a video tutorial on Structs. + +## ⭐️ Assignment + +Create a function `remove` that takes a `uint` as a parameter and deletes a struct member with the given index in the `todos` mapping. diff --git a/locales/ko/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md b/locales/ko/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md new file mode 100644 index 000000000..d0e628f6b --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md @@ -0,0 +1,37 @@ +In this section, we will learn more about the inputs and outputs of functions. + +### Multiple named Outputs + +Functions can return multiple values that can be named and assigned to their name. + +The `returnMany` function (line 6) shows how to return multiple values. +You will often return multiple values. It could be a function that collects outputs of various functions and returns them in a single function call for example. + +The `named` function (line 19) shows how to name return values. +Naming return values helps with the readability of your contracts. Named return values make it easier to keep track of the values and the order in which they are returned. You can also assign values to a name. + +The `assigned` function (line 33) shows how to assign values to a name. +When you assign values to a name you can omit (leave out) the return statement and return them individually. + +### Deconstructing Assignments + +You can use deconstructing assignments to unpack values into distinct variables. + +The `destructingAssigments` function (line 49) assigns the values of the `returnMany` function to the new local variables `i`, `b`, and `j` (line 60). + +### Input and Output restrictions + +There are a few restrictions and best practices for the input and output parameters of contract functions. + +"_[Mappings] cannot be used as parameters or return parameters of contract functions that are publicly visible._" +From the Solidity documentation. + +Arrays can be used as parameters, as shown in the function `arrayInput` (line 71). Arrays can also be used as return parameters as shown in the function `arrayOutput` (line 76). + +You have to be cautious with arrays of arbitrary size because of their gas consumption. While a function using very large arrays as inputs might fail when the gas costs are too high, a function using a smaller array might still be able to execute. + +Watch a video tutorial on Function Outputs. + +## ⭐️ Assignment + +Create a new function called `returnTwo` that returns the values `-2` and `true` without using a return statement. diff --git a/locales/ko/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md b/locales/ko/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md new file mode 100644 index 000000000..d707a987b --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md @@ -0,0 +1,39 @@ +In this section, we will learn how to modify the behavior of a function and how to run contract initialization code. + +### Function Modifier + +_Function Modifiers_ are used to change the behavior of a function. For example, they often check for a condition prior to executing a function to restrict access or validate inputs. + +This first part of this contract is about changing ownership of a contract. Ownership in this contract is expressed by the value of the state variable `owner` that is of the type `address` (line 7). + +The function `changeOwner` (line 33) can change this ownership. It takes an input parameter of the type `address` and assigns its value to the state variable `owner`. + +However, this function cannot simply be executed under all conditions; it has two modifiers, `onlyOwner` and `validAddress`. + +Let's look at `onlyOwner` first (line 18). +Function modifiers are defined with the `modifier` keyword and a unique name; they can also have parameters. + +The underscore `_` (line 23) is used inside modifiers to represent the rest of the code that will be executed in the body of the modified function. +The code you place before the underscore in the modifier will be executed before the code in the body of the modified function. The code after the underscore will be executed after the code in the body of the modified function. + +In this case, the `require` function (line 19) checks if the address executing the contract is the same as the value stored in the variable `owner`. If it is, the rest of the code will be executed, otherwise it will throw an error. + +You can learn more about `assert` and `require` in the Solidity documentation, they are used to check for conditions and throw errors if they are not met. + +The `validAddress` modifier (line 28) has a parameter of type `address` and checks if the provided address is valid. If it is, it continues to execute the code. + +### Constructor + +A constructor function is executed upon the creation of a contract. You can use it to run contract initialization code. The constructor can have parameters and is especially useful when you don't know certain initialization values before the deployment of the contract. + +You declare a constructor using the `constructor` keyword. The constructor in this contract (line 11) sets the initial value of the owner variable upon the creation of the contract. + +Watch a video tutorial on Function Modifiers. + +## ⭐️ Assignment + +1. Create a new function, `increaseX` in the contract. The function should take an input parameter of type `uint` and increase the value of the variable `x` by the value of the input parameter. +2. Make sure that x can only be increased. +3. The body of the function `increaseX` should be empty. + +Tip: Use modifiers. diff --git a/locales/ko/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md b/locales/ko/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md new file mode 100644 index 000000000..3670c03e2 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md @@ -0,0 +1,23 @@ +This section will give a short introduction to functions and teach you how to use them to read from and write to a state variable. + +As in other languages, we use functions in Solidity to create modular, reusable code. However, Solidity functions have some particularities. + +Solidity functions can be split into two types: + +1. Functions that modify the state of the blockchain, like writing to a state variable. In this contract, the `set` function (line 9) changes the state variable `num`. +2. Functions that don't modify the state of the blockchain. These functions are marked `view` or `pure`. For example, in this contract, the `get` function (line 14) marked `view` that only returns `num` does not change the state. + +To define a function, use the `function` keyword followed by a unique name. + +If the function takes inputs like our `set` function (line 9), you must specify the parameter types and names. A common convention is to use an underscore as a prefix for the parameter name to distinguish them from state variables. + +You can then set the visibility of a function and declare them `view` or `pure` as we do for the `get` function if they don't modify the state. Our `get` function also returns values, so we have to specify the return types. In this case, it's a `uint` since the state variable `num` that the function returns is a `uint`. + +We will explore the particularities of Solidity functions in more detail in the following sections. + +Watch a video tutorial on Functions. + +## ⭐️ Assignment + +1. Create a public state variable called `b` that is of type `bool` and initialize it to `true`. +2. Create a public function called `get_b` that returns the value of `b`. diff --git a/locales/ko/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md b/locales/ko/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md new file mode 100644 index 000000000..b846c7d99 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md @@ -0,0 +1,44 @@ +This section will look into the types of functions that don't modify the state of the blockchain: _view_ and _pure_ functions. + +### View Functions + +_View functions_ promise to not modify the state. + +"The following statements are considered modifying the state: + +1. Writing to state variables. +2. Emitting events. +3. Creating other contracts. +4. Using selfdestruct. +5. Sending Ether via calls. +6. Calling any function not marked view or pure. +7. Using low-level calls. +8. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a view function using the keyword `view`. In this contract, `addToX` (line 8) is a view function. This function takes the parameter `y` and returns the sum of the parameter and the state variable `x`. It reads `x` but does not modify it. + +### Pure functions + +_Pure functions_ promise to neither modify nor to read the state. + +"In addition to the list of state modifying statements explained above, the following are considered reading from the state: + +1. Reading from state variables. +2. Accessing `address(this).balance` or `
.balance`. +3. Accessing any of the members of block, tx, msg (with the exception of `msg.sig` and `msg.data`). +4. Calling any function not marked pure. +5. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a pure function using the keyword `pure`. In this contract, `add` (line 13) is a pure function. This function takes the parameters `i` and `j`, and returns the sum of them. It neither reads nor modifies the state variable `x`. + +In Solidity development, you need to optimise your code for saving computation cost (gas cost). Declaring functions view and pure can save gas cost and make the code more readable and easier to maintain. Pure functions don't have any side effects and will always return the same result if you pass the same arguments. + +Watch a video tutorial on View and Pure Functions. + +## ⭐️ Assignment + +Create a function called `addToX2` that takes the parameter `y` and updates the state variable `x` with the sum of the parameter and the state variable `x`. diff --git a/locales/ko/SolidityBeginnerCourse/introduction/introduction.md b/locales/ko/SolidityBeginnerCourse/introduction/introduction.md new file mode 100644 index 000000000..cc821a46a --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/introduction/introduction.md @@ -0,0 +1,32 @@ +Welcome to this interactive Solidity course for beginners. + +In this first section, we will give you a short preview of the concepts we will cover in this course, look at an example smart contract, and show you how you can interact with this contract in the Remix IDE. + +This contract is a counter contract that has the functionality to increase, decrease, and return the state of a counter variable. + +If we look at the top of the contract, we can see some information about the contract like the license (line 1), the Solidity version (line 2), as well as the keyword `contract` and it's name, `Counter` (line 4). We will cover these concepts in the next section about the **Basic Syntax**. + +With `uint public count` (line 5) we declare a state variable of the type `uint` with the visibility `public`. We will cover these concepts in our sections about **Variables**, **Primitive Data Types**, and **Visibility**. + +We then create a `get` function (line 8) that is defined with the `view` keyword and returns a `uint` type. Specifically, it returns the `count` variable. This contract has two more functions, an `inc` (line 13) and `dec` (line 18) function that increases or decreases our count variable. +We will talk about these concepts in our sections about **Functions - Reading and Writing to a State Variable** and **Functions - View and pure**. + +## Compile and Deploy through Remix + +**GIF** Interacting with the contract: Compile and deploy contract + +1. We can compile your `Counter` contract in the "Solidity compiler" module of the Remix IDE. + +2. In the "Deploy & run transactions" module, we select our contract "Counter" in the contract input field and click on the "Deploy" button. + +3. We expand the token contract functions in the IDE, and test its `get`, `inc`, and `dec` functions. + +## ⭐️ Assignment + +Throughout this course, we will give you assignments to test and consolidate your newly acquired knowledge. + +Your first assignment is to: + +1. Compile this contract. +2. Deploy it to the Remix VM. +3. Interact with your contract. diff --git a/locales/ko/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md b/locales/ko/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md new file mode 100644 index 000000000..9ea6b8626 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md @@ -0,0 +1,33 @@ +In this section, we will show you Solidity’s primitive data types, how to declare them, and their characteristics. + +### bool + +You can declare data a boolean type by using the keyword ‘bool’. Booleans can either have the value `true` or `false`. + +### uint + +We use the keywords `uint` and `uint8` to `uint256` to declare an _unsigned integer type_ (they don’t have a sign, unlike -12, for example). Uints are integers that are positive or zero and range from 8 bits to 256 bits. The type `uint` is the same as `uint256`. + +### int + +We use the keywords `int` and `int8` to `int256` to declare an integer type. Integers can be positive, negative, or zero and range from 8 bits to 256 bits. The type `int` is the same as `int256`. + +### address + +Variables of the type `address` hold a 20-byte value, which is the size of an Ethereum address. There is also a special kind of Ethereum address, `address payable`, which can receive ether from the contract. + +All these data types have default values, as shown in the contract (line 29). + +You can learn more about these data types as well as _Fixed Point Numbers_, _Byte Arrays_, _Strings_, and more in the Solidity documentation. + +Later in the course, we will look at data structures like **Mappings**, **Arrays**, **Enums**, and **Structs**. + +Watch a video tutorial on Primitive Data Types. + +## ⭐️ Assignment + +1. Create a new variable `newAddr` that is a `public` `address` and give it a value that is not the same as the available variable `addr`. +2. Create a `public` variable called `neg` that is a negative number, decide upon the type. +3. Create a new variable, `newU` that has the smallest `uint` size type and the smallest `uint` value and is `public`. + +Tip: Look at the other address in the contract or search the internet for an Ethereum address. diff --git a/locales/ko/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md b/locales/ko/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md new file mode 100644 index 000000000..57208c555 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md @@ -0,0 +1,26 @@ +_Ether_ (ETH) is a cryptocurrency. _Ether_ is also used to pay fees for using the Ethereum network, like making transactions in the form of sending _Ether_ to an address or interacting with an Ethereum application. + +### Ether Units + +To specify a unit of _Ether_, we can add the suffixes `wei`, `gwei`, or `ether` to a literal number. + +#### `wei` + +_Wei_ is the smallest subunit of _Ether_, named after the cryptographer [Wei Dai](https://en.wikipedia.org/wiki/Wei_Dai). _Ether_ numbers without a suffix are treated as `wei` (line 7). + +#### `gwei` + +One `gwei` (giga-wei) is equal to 1,000,000,000 (10^9) `wei`. + +#### `ether` + +One `ether` is equal to 1,000,000,000,000,000,000 (10^18) `wei` (line 11). + +Watch a video tutorial on Ether and Wei. + +## ⭐️ Assignment + +1. Create a `public` `uint` called `oneGWei` and set it to 1 `gwei`. +2. Create a `public` `bool` called `isOneGWei` and set it to the result of a comparison operation between 1 gwei and 10^9. + +Tip: Look at how this is written for `gwei` and `ether` in the contract. diff --git a/locales/ko/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md b/locales/ko/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md new file mode 100644 index 000000000..bbc25575c --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md @@ -0,0 +1,29 @@ +As we have seen in the previous section, executing code via transactions on the Ethereum Network costs transaction fees in the form of Ether. The amount of fees that have to be paid to execute a transaction depends on the amount of _gas_ that the execution of the transaction costs. + +### Gas + +_Gas_ is the unit that measures the amount of computational effort that is required to execute a specific operation on the Ethereum network. + +### Gas price + +The _gas_ that fuels Ethereum is sometimes compared to the gas that fuels a car. The amount of gas your car consumes is mostly the same, but the price you pay for gas depends on the market. + +Similarly, the amount of _gas_ that a transaction requires is always the same for the same computational work that is associated with it. However the price that the sender of the transaction is willing to pay for the _gas_ is up to them. Transactions with higher _gas prices_ are going through faster; transactions with very low _gas prices_ might not go through at all. + +When sending a transaction, the sender has to pay the _gas_ fee (gas_price \* gas) upon execution of the transaction. If _gas_ is left over after the execution is completed, the sender gets refunded. + +_Gas_ prices are denoted in gwei. + +### Gas limit + +When sending a transaction, the sender specifies the maximum amount of gas that they are willing to pay for. If they set the limit too low, their transaction can run out of _gas_ before being completed, reverting any changes being made. In this case, the _gas_ was consumed and can’t be refunded. + +Learn more about _gas_ on ethereum.org. + +Watch a video tutorial on Gas and Gas Price. + +## ⭐️ Assignment + +Create a new `public` state variable in the `Gas` contract called `cost` of the type `uint`. Store the value of the gas cost for deploying the contract in the new variable, including the cost for the value you are storing. + +Tip: You can check in the Remix terminal the details of a transaction, including the gas cost. You can also use the Remix plugin _Gas Profiler_ to check for the gas cost of transactions. diff --git a/locales/ko/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md b/locales/ko/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md new file mode 100644 index 000000000..58fb4c5a6 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md @@ -0,0 +1,86 @@ +In this section, we will learn how a contract can send and receive Ether. + +### Sending Ether + +We have three different options to transfer Ether: `transfer()`, `send()` and `call()`. + +#### **transfer** + +`
.transfer(uint256 amount)` + +- `transfer()` throws an exception on failure +- Forwards a fixed 2300 gas stipend + +An example of `transfer()` can be seen in the `SendEther` contract (line 35). +**`Transfer()` is not recommended to be used anymore.** + +#### **send** + +`
.send(uint256 amount) returns (bool)` + +- `send()` returns false on failure +- Forwards a fixed 2300 gas stipend + +An example of `send()` can be seen in the `SendEther` contract (line 41). +**`Send()` is not recommended to be used anymore.** + +#### **call** + +`
.call(bytes memory) returns (bool, bytes memory)` + +- `call()` returns false on failure +- Forwards the maximum amount of gas, but this is adjustable + +An example of `call()` can be seen in the `SendEther` contract (line 48). +`Call()` is currently recommended if you are transfering Ether. + +The reason `transfer()` and `send()` were introduced was to guard against _reentry attacks_ by limiting the forwarded gas to 2300, which would be insufficient to make a reentrant call that can modify storage. + +As we discussed in the last section, each operation on Ethereum has a specific cost associated with it. Certain operations have become more cost intensive over time, so the gas costs associated with them are also raised. When gas costs for operations are subject to change it is not good to use a hardcoded gas amount like transfer(), and send() do. + +That’s why `call()` instead of `transfer()` is now recommended to send Ether. + +Learn more about the subject in this Consensys blog post. + +### Reentrancy attack + +A _reentrancy attack_ occurs when a function makes an external call to an untrusted contract and the attacker uses the contract to make recursive calls back to the original function before it finishes its execution. Through this method, the attacker can drain funds and manipulate data in unintended ways. + +To guard against a _reentrancy attack_, all state changes should be made before calling an external contract. This is also called the Checks-Effects-Interactions pattern. + +Another way to prevent reentrancy is to use a _Reentrancy Guard_ that checks for such calls and rejects them. You can see an example of this in the contract in our modifier section or a more gas-efficient version on Open Zepplin. + +### Receiving Ether + +If we want to enable a contract to receive Ether without a function being called, we need to create a `receive` function (line 22) or a `fallback` function (line 25); otherwise, the Ether will be rejected, and the contract will throw an exception. + +The `receive` function is executed on calls with empty calldata (e.g. plain Ether transfers via send() or transfer()), while the fallback function is executed on calls with calldata. If no receive function exists but a fallback function does, calls with empty calldata will also use the fallback function. + +### Payable function modifier + +The `payable` function modifier allows a function to receive Ether. + +The `receive` function (line 22) needs to be `payable`. If you delete the `payable` modifier you will get an error from the compiler. If you delete the `payable` modifier from the `fallback` function (line 25) it will compile, but it won’t be able to receive Ether. +The functions `sendViaTransfer`, `sendViaSend`, and `sendViaCall` (lines 33, 38, and 45) also need to be `payable` in order to receive Ether. + +### Payable address + +Solidity makes a distinction between two different flavors of the address data type: address and address payable. + +`address`: Holds a 20-byte value. +`address payable`: Holds a 20-byte value and can receive Ether via its members: transfer and send. + +If you change the parameter type for the functions `sendViaTransfer` and `sendViaSend` (line 33 and 38) from `payable address` to `address`, you won’t be able to use `transfer()` (line 35) or `send()` (line 41). + +Watch a video tutorial on Sending Ether. + +## ⭐️ Assignment + +Build a charity contract that receives Ether that can be withdrawn by a beneficiary. + +1. Create a contract called `Charity`. +2. Add a public state variable called `owner` of the type address. +3. Create a donate function that is public and payable without any parameters or function code. +4. Create a withdraw function that is public and sends the total balance of the contract to the `owner` address. + +Tip: Test your contract by deploying it from one account and then sending Ether to it from another account. Then execute the withdraw function. diff --git a/locales/ko/SolidityBeginnerCourse/variables/variables.md b/locales/ko/SolidityBeginnerCourse/variables/variables.md new file mode 100644 index 000000000..dfb35b382 --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/variables/variables.md @@ -0,0 +1,29 @@ +There are three different types of variables in Solidity: _State Variables_, _Local Variables_, and _Global Variables_. + +## 1. State Variables + +_State Variables_ are stored in the contract _storage_ and thereby on the blockchain. They are declared inside the contract but outside the function. +This contract has two state variables, the string `text`(line 6) and the uint `num` (line 7). + +## 2. Local Variables + +_Local Variables_ are stored in the _memory_ and their values are only accessible within the function they are defined in. Local Variables are not stored on the blockchain. +In this contract, the uint `i` (line 11) is a local variable. + +## 3. Global Variables + +_Global Variables_, also called _Special Variables_, exist in the global namespace. They don't need to be declared but can be accessed from within your contract. +Global Variables are used to retrieve information about the blockchain, particular addresses, contracts, and transactions. + +In this example, we use `block.timestamp` (line 14) to get a Unix timestamp of when the current block was generated and `msg.sender` (line 15) to get the caller of the contract function’s address. + +A list of all Global Variables is available in the Solidity documentation. + +Watch video tutorials on State Variables, Local Variables, and Global Variables. + +## ⭐️ Assignment + +1. Create a new public state variable called `blockNumber`. +2. Inside the function `doSomething()`, assign the value of the current block number to the state variable `blockNumber`. + +Tip: Look into the global variables section of the Solidity documentation to find out how to read the current block number. diff --git a/locales/ko/SolidityBeginnerCourse/visibility/visibility.md b/locales/ko/SolidityBeginnerCourse/visibility/visibility.md new file mode 100644 index 000000000..79e4307bf --- /dev/null +++ b/locales/ko/SolidityBeginnerCourse/visibility/visibility.md @@ -0,0 +1,37 @@ +The `visibility` specifier is used to control who has access to functions and state variables. + +There are four types of visibilities: `external`, `public`, `internal`, and `private`. + +They regulate if functions and state variables can be called from inside the contract, from contracts that derive from the contract (child contracts), or from other contracts and transactions. + +### private + +- Can be called from inside the contract + +### internal + +- Can be called from inside the contract +- Can be called from a child contract + +### public + +- Can be called from inside the contract +- Can be called from a child contract +- Can be called from other contracts or transactions + +### external + +- Can be called from other contracts or transactions +- State variables can not be `external` + +In this example, we have two contracts, the `Base` contract (line 4) and the `Child` contract (line 55) which inherits the functions and state variables from the `Base` contract. + +When you uncomment the `testPrivateFunc` (lines 58-60) you get an error because the child contract doesn’t have access to the private function `privateFunc` from the `Base` contract. + +If you compile and deploy the two contracts, you will not be able to call the functions `privateFunc` and `internalFunc` directly. You will only be able to call them via `testPrivateFunc` and `testInternalFunc`. + +Watch a video tutorial on Visibility. + +## ⭐️ Assignment + +Create a new function in the `Child` contract called `testInternalVar` that returns the values of all state variables from the `Base` contract that are possible to return. diff --git a/locales/ko/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md b/locales/ko/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md new file mode 100644 index 000000000..801d8c582 --- /dev/null +++ b/locales/ko/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md @@ -0,0 +1,47 @@ +In this tutorial, we'll explore the Uniswap V3 Swap contract to learn about how single-hop and multi-hop swaps work. + +But first, some Uniswap fundamentals. + +## What is Uniswap? + +Uniswap is a decentralized cryptocurrency exchange. It allows users to exchange tokens without the need for a centralized intermediary. Uniswap is a key player in the decentralized finance (DeFi) space. + +## How does Uniswap work? + +Instead of using an order book like a traditional centralized exchange, Uniswap uses an automated market maker (AMM) model. In Uniswap, the AMM is a smart contract that holds reserves of tokens (Liquidity Pool). Users can trade between tokens in the Liquidity Pool. The price of each token is determined by the ratio of the reserves. + +### Step-by-step example of a Uniswap trade + +1. Alice wants to trade 1 ETH for DAI. +2. Alice sends 1 ETH to the Uniswap smart contract. +3. The Uniswap smart contract calculates the amount of DAI that Alice should receive based on the current exchange rate. +4. The Uniswap smart contract sends the DAI to Alice. +5. The Uniswap smart contract adds the 1 ETH to its reserves. +6. The Uniswap smart contract recalculates the exchange rate based on the new reserves. + +The tokens in the Liquidity Pool are provided by Liquidity Providers. When a Liquidity Provider deposits tokens into a Liquidity Pool, they receive Liquidity Provider Tokens in return. Liquidity Provider Tokens represent a user's share of a Liquidity Pool. + +Users of Uniswap pay a fee for each trade. The fee is paid to the Liquidity Providers in the form of additional Liquidity Provider Tokens. + +## Uniswap Swap Contract + +The Uniswap Swap contract allows users to swap tokens using Uniswap V3. It can do single-hop swaps, which allow users to exchange one token for another directly. It can also do multi-hop swaps, which means that users can exchange one token for another by routing through multiple tokens. Routing in this context means that the swap contract will exchange the token for another token, then exchange that token for another token, and so on until it reaches the desired token. + +## Conclusion + +In this section, we learned about Uniswap, how it works, and how we are going to use it to swap tokens. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is Uniswap? + +1. A centralized exchange protocol. +2. A decentralized exchange protocol that uses an order book. +3. A decentralized exchange protocol that uses an automated market maker (AMM) model. +4. A decentralized exchange protocol that uses an order book and an automated market maker (AMM) model. + +### 2) How does Uniswap determine the price of a token? + +1. The price of a token is determined by the ratio of the reserves. +2. The price of a token is determined by the ratio of the reserves and the number of trades. +3. The price of a token is determined by the ratio of the reserves and the number of Liquidity Providers. diff --git a/locales/ko/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md b/locales/ko/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md new file mode 100644 index 000000000..e5cc248f5 --- /dev/null +++ b/locales/ko/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md @@ -0,0 +1,41 @@ +The entire UniswapSwapExamples contract will only be presented in section 5 of this tutorial. Before then, we'll build up blocks of code. + +This section explores the `ISwapRouter` interface, which defines the functions that can be called on the Uniswap Swap contract. + +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. +Multi-hop swaps allow users to exchange one token for another by routing through multiple tokens. + +Interfaces in Solidity specify functions that must be included in a contract that inherits them. They are useful for declaring what functions be supported and allow for easier integration and interaction between different contracts. + +Structs are used to define custom data types. + +## ISwapRouter Interface + +The ISwapRouter interface defines the functions that can be called on the Uniswap Swap contract. We will need to use this interface to interact with the Uniswap Swap contract and execute swaps. + +On line 5, we define a constant variable called `router` that is of type `ISwapRouter`. We set the value of this variable to the interface instance of a smart contract that is deployed at the address `0xE592427A0AEce92De3Edee1F18E0157C05861564`. This is the address of the Uniswap V3 Swap contract on the Ethereum mainnet. + +On line 9, we define an interface called `ISwapRouter`. This interface defines two functions: `exactInputSingle` and `exactInput`. + +## exactInputSingle + +On line 25, we define a struct called `ExactInputSingleParams`. This struct defines the parameters that are required for our exactInputSingle function on line 21, which will execute a single-hop swap. The struct has the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 fee`**: The fee associated with the swap. +- **`address recipient`**: The address that will receive the output token. +- **`uint deadline`**: A timestamp by which the transaction must be processed, for time-limiting the swap. +- **`uint amountIn`**: The amount of the input token being sent. +- **`uint amountOutMinimum`**: The minimum amount of the output token that the sender is willing to accept, to protect against unfavorable price movements. +- **`uint160 sqrtPriceLimitX96`**: A limit on the price, represented in a specific format, to prevent the swap from occurring at unfavorable prices. + +## exactInput + +On line 25, we define a struct called `ExactInputParams`. This struct defines the parameters that are required for our `exactInput` function on line 33. This function will execute a multi-hop swap. The struct has the following parameters: + +- **`bytes path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address recipient`**: The address receiving the output tokens. +- **`uint deadline`**: Similar to above, a timestamp by which the transaction must be processed. +- **`uint amountIn`**: The amount of the input token. +- **`uint amountOutMinimum`**: The minimum amount of the output token the sender expects to receive. diff --git a/locales/ko/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md b/locales/ko/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md new file mode 100644 index 000000000..f4d70c445 --- /dev/null +++ b/locales/ko/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md @@ -0,0 +1,36 @@ +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. In this section, we will learn how to use the Uniswap V3 Swap contract to execute single-hop swaps. + +## Function Parameters + +On line 8, we define a function called `swapExactInputSingleHop`. This function executes a single-hop swap. It takes the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 poolFee`**: The fee associated with the swap. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +## Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 14. +Then, we approve the Uniswap Swap contract to spend the input token on our behalf, line 15. + +On line 17, we create an instance of the `ExactInputSingleParams` struct. This struct contains the parameters that are required for our `exactInputSingle` function on line 45, which will execute the single-hop swap. We repeat `ISwapRouter.ExactInputSingleParams` two times on that line because we are making an instance of a struct that is defined in an interface. + +## Parameters of the ExactInputSingleParams Struct + +We set the parameters of the struct as follows: + +- **`tokenIn`**: We set this to the `tokenIn` parameter of our function. +- **`tokenOut`**: We set this to the `tokenOut` parameter of our function. +- **`fee`**: We set this to the `poolFee` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. +- **`sqrtPriceLimitX96`**: We set this to 0 because we do not want to specify a limit on the price. + +## Executing the Single-hop Swap + +On line 29, we assign the output of the `exactInputSingle` function to the `amountOut` variable. This function executes the single-hop swap and returns the amount of the output token that was received. diff --git a/locales/ko/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md b/locales/ko/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md new file mode 100644 index 000000000..7883b4718 --- /dev/null +++ b/locales/ko/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md @@ -0,0 +1,30 @@ +In this section, we'll delve into the `swapExactInputMultiHop` function in the `UniswapV3SwapExamples` contract. This function enables more complex token swaps by allowing users to specify a custom path through multiple liquidity pools. + +If for example, a user wants to swap token A for token D, but there is no direct liquidity pool for A and D, the user can specify a path through multiple tokens. For example, the user can swap A for B, then B for C, and finally C for D. This is of course automatically done by the Uniswap V3 Swap contract. + +### Parameters and Return Value + +On line 32, we define a function called `swapExactInputMultiHop`. This function executes a multi-hop swap. It takes the following parameters: + +- **`bytes calldata path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address tokenIn`**: The address of the token being sent. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +### Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 38. +Then, we approve the Uniswap Swap router to spend the input token on our behalf, line 41. + +On line 43, we create an instance of the `ExactInputParams` struct, line 73. This struct contains the parameters that are required for our `exactInput` function on line 81, which will execute the multi-hop swap. + +We set the parameters of the struct as follows: + +- **`path`**: We set this to the `path` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. + +On line 53, we execute the multi-hop swap by calling the `exactInput` function. This function returns the amount of the output token that was received. diff --git a/locales/ko/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md b/locales/ko/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md new file mode 100644 index 000000000..b3cec34e9 --- /dev/null +++ b/locales/ko/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md @@ -0,0 +1,52 @@ +In this section, we'll explore the `IERC20` interface, a standard interface for interacting with ERC-20 tokens and the `IWETH` interface, a standard interface for interacting with wrapped Ether (WETH). Understanding these interfaces is crucial as it is used in the Uniswap V3 Swap contract to handle token transfers and approvals. + +You can find a "Solidity ERC20 Token Course" for beginners in LearnEth to understand the ERC20 token standard in more detail. + +## IERC20 Interface + +On line 80, we define the `IERC20` interface. This interface defines a standard set of functions that ERC-20 tokens must implement. Let's examine the key functions within this interface: + +### 1. totalSupply + +On line 81, we define the `totalSupply` function. This function returns the total supply of the token. + +### 2. balanceOf + +On line 83, we define the `balanceOf` function. This function returns the balance of the specified address. + +### 3. transfer + +On line 85, we define the `transfer` function. This function transfers tokens from the sender to the specified recipient. + +### 4. allowance + +On line 87, we define the `allowance` function. This function returns the amount of tokens that the spender is allowed to spend on behalf of the owner. + +### 5. approve + +On line 89, we define the `approve` function. When called, this function approves a spender to spend the specified amount of tokens on behalf of the sender. + +### 6. transferFrom + +On line 91, we define the `transferFrom` function. This function transfers tokens from the specified sender to the recipient. The function can only be called by the spender if the spender is allowed to spend the specified amount of tokens on behalf of the sender. + +### 7. Events + +On lines 102-103, we define the `Transfer` and `Approval` events. These events are emitted when the `transfer` and `approve` functions are called, respectively. + +## IWETH Interface + +On line 106, we define the `IWETH` interface. This interface extends the `IERC20` interface and defines two additional functions: + +### 1. deposit + +On line 107, we define the `deposit` function. This function deposits ETH into the contract and returns the equivalent amount of WETH. This function is used to wrap ETH into WETH. +We need to wrap ETH into WETH because the Uniswap V3 Swap contract only supports ERC-20 tokens. + +### 2. withdraw + +On line 109, we define the `withdraw` function. This function withdraws the specified amount of WETH from the contract and returns the equivalent amount of ETH. This function is used to unwrap WETH into ETH. + +## Conclusion + +In this tutorial, we explored the Uniswap V3 Swap contract. To get a full sense of how Uniswap works, try making some swaps on the Uniswap DApp and go to the Uniswap docs. diff --git a/locales/ko/Uniswap-Tutorial/README.md b/locales/ko/Uniswap-Tutorial/README.md new file mode 100644 index 000000000..cf66c5582 --- /dev/null +++ b/locales/ko/Uniswap-Tutorial/README.md @@ -0,0 +1,5 @@ +# Uniswap Swap Course + +Review the code of the Uniswap V3 Swap contract for performing token swaps. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ko/Uniswap-Tutorial/config.yml b/locales/ko/Uniswap-Tutorial/config.yml new file mode 100644 index 000000000..f49f02abc --- /dev/null +++ b/locales/ko/Uniswap-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: uniswapSwapCourse +name: Uniswap Swap Course +summary: Go through the Solidity code of the Uniswap V3 Swap contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - Uniswap +steps: + - + name: 1. Introduction + path: 1-introduction-to-uniswap + - + name: 2. Routers, Interfaces, and Structs + path: 2-router-interfaces-and-structs + - + name: 3. Single Hop Swaps + path: 3-single-hop-swaps + - + name: 4. Multi-Hop Swaps + path: 4-multi-hop-swaps + - + name: 5. Erc20 and Weth Interfaces + path: 5-erc20-weth-interfaces diff --git a/locales/ko/Web3Client/1_Using_Web3/Running_a_script.md b/locales/ko/Web3Client/1_Using_Web3/Running_a_script.md new file mode 100644 index 000000000..3b7b23332 --- /dev/null +++ b/locales/ko/Web3Client/1_Using_Web3/Running_a_script.md @@ -0,0 +1,24 @@ +## Querying the Blockchain + +In this tutorial, we'll run a script that queries the blockchain using a JavaScript library. + +This means that instead of using the Remix GUI or a block explorer like Etherscan, we'll use a script in the editor and will run it from the terminal. + +The JS libraries that are used the most for interacting with the blockchain are web3.js & ethers.js. + +Let's begin with a simple web3.js example, queryBlockNum.js. + +The script's call to web3.js is wrapped in a self-executing async function that contains a try/catch block. + +We'll query the current blocknumber with: +`let blockNumber = await web3.eth.getBlockNumber()` + +Note that the object `web3` is injected by Remix. For more info on web3.js, check their docs, https://web3js.readthedocs.io. + +To use web3.js or ethers.js, you need to select the **Injected Web3** or **Web3 Provider** environment in the **Deploy & Run** module. Scripts don't currently work with the JSVM. **If you try, you'll get an error.** + +So for this example choose **Injected Web3** in the Deploy & Run module and have Metamask installed. + +From the terminal, execute `remix.execute()`. This command will execute the current JavaScript file with the line `let blockNumber = await web3.eth.getBlockNumber()`. + +In the console, you should see the current block number of the chain that metamask is connected to. diff --git a/locales/ko/Web3Client/2_Querying_a_Contract/queryContract.md b/locales/ko/Web3Client/2_Querying_a_Contract/queryContract.md new file mode 100644 index 000000000..461c98244 --- /dev/null +++ b/locales/ko/Web3Client/2_Querying_a_Contract/queryContract.md @@ -0,0 +1,23 @@ +Now that we know how to query simple data, let's try a more complex query. + +This is a contract deployed to the mainnet - at this address: https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code + +We are going to query the contract to find the name of it's token. + +The **name** variable is a state variable of the contract. + +To access this **mainnet** contract, we need to do some setup. + +1. Switch to the mainnet in metamask. +2. You'll probably need to refresh Remix. +3. As a result of the refresh, you may need to reload this tutorial too. +4. Go to Deploy & Run and switch to **Injected Web3**. + +**Using Web3** +In the script, queryContract.js, we need to instantiate a new instance of web3.eth.Contract object. For this we need to grab the contract's ABI and its address. The source code & ABI is available in etherscan because the contract's developer intentionally published it. + +In etherscan, we can see that its name is **TetherToken**. Scrolling down to the TetherToken contract in the source code section of etherscan, we can see the state variables for the contract - the first of which is named **name**. + +There are a few syntactic hoops to jump through to return the value of the state variable. + +- To call the autogenerated getter function of the public state variable, you need to both treat the variable as a function (by adding parentheses) and also to tack on a call(). diff --git a/locales/ko/Web3Client/README.md b/locales/ko/Web3Client/README.md new file mode 100644 index 000000000..a319f312f --- /dev/null +++ b/locales/ko/Web3Client/README.md @@ -0,0 +1 @@ +This workshop is about using the web3.js to interact with a contract and more generally to the blockchain. diff --git a/locales/ko/Web3Client/config.yml b/locales/ko/Web3Client/config.yml new file mode 100644 index 000000000..07cb1760c --- /dev/null +++ b/locales/ko/Web3Client/config.yml @@ -0,0 +1,9 @@ +--- +id: useofweb3js +name: Basic use of web3.js +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 2 +tags: + - JS + - Remix + - Web3 diff --git a/locales/pt/Basics/README.md b/locales/pt/Basics/README.md new file mode 100644 index 000000000..6b065b830 --- /dev/null +++ b/locales/pt/Basics/README.md @@ -0,0 +1,3 @@ +## Loading, Compiling, Deploying + +This beginner level tutorial introduces Remix's interface and concepts used in Ethereum. diff --git a/locales/pt/Basics/config.yml b/locales/pt/Basics/config.yml new file mode 100644 index 000000000..8c160b545 --- /dev/null +++ b/locales/pt/Basics/config.yml @@ -0,0 +1,26 @@ +--- +id: basics +name: Basics of Remix +summary: A typical workflow in Remix +level: 1 +tags: + - Remix +steps: + - + name: Intro to the Interface + path: interface_introduction + - + name: Intro to Workspaces + path: workspaces + - + name: Loading & Compiling + path: load_and_compile + - + name: Deploying to the Remix VM + path: deploy_to_the_remixvm + - + name: Interacting with Functions + path: interacting + - + name: Deploying to Public Networks + path: deploy_injected diff --git a/locales/pt/Basics/deploy_injected/README.md b/locales/pt/Basics/deploy_injected/README.md new file mode 100644 index 000000000..172396527 --- /dev/null +++ b/locales/pt/Basics/deploy_injected/README.md @@ -0,0 +1,21 @@ +1. If you don't have a browser wallet like **MetaMask** download and install one now. + +2. Click the MetaMask icon in your browser. Sign in and choose the Ephemery test network. You might need to update your wallet's settings so that you can see **test networks**. Alternatively, you can go to Remix's Deploy & Run transation module and in the ENVIRONMENT section select Ephemery. + +3. Getting test ETH for public test networks is often annoying. Ephemery is a public network that is refreshed monthly, so getting test ETH should be painless. Here is a link to some Ephemery faucets. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/testnet.png) + +Sepolia is another popular testnet that is not refreshed, so deployments will persist, but Sepolia faucets are more difficult to use. + +In your browser wallet make sure that you have NOT selected mainnet or any network that will cost real ETH. In the Deploy & Run module, below the Environment select box, you'll see a badge with the network's ID and for popular chains, its name. In the case below its Sepolia. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/sepolia.png) + +5. Make sure you see the 2_Owner.sol as a choice in the **CONTRACT** select box, then click the **Deploy** button. + +If the **CONTRACT** select box is empty, you'll need to compile 2_Owner again by making 2_Owner.sol the active file in the **editor** and then go to the **Solidity Compiler** to compile it. + +6. After you hit the `Deploy` button, you'll see the browser wallet popup asking you to pay for the transactions. If you have the appropriate kind of ETH for this chain, approve this transaction. Check the printout in the terminal. Once the block is validated, the **deployed instance** will appear at the bottom of Deploy & Run + +And with that you have finished this tutorial. You now have experience with opening, compiling, deploying and interacting with Smart Contracts in Remix IDE. diff --git a/locales/pt/Basics/deploy_to_the_remixvm/README.md b/locales/pt/Basics/deploy_to_the_remixvm/README.md new file mode 100644 index 000000000..8035d631b --- /dev/null +++ b/locales/pt/Basics/deploy_to_the_remixvm/README.md @@ -0,0 +1,15 @@ +In the previous chapter, we compiled a contract - which is to say the Solidity code has been transformed into little chunks of Ethereum Virtual Machine (EVM) bytecode. + +Now we will put that code on a test blockchain. + +1. Click the Deploy and Run icon ![deploy & run icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_to_the_remixvm/images/run.png "deploy & run icon"). + +2. Select one of the **Remix VM**s from the **Environment** pulldown. + +3. Click the Deploy button (or the transact button in the expanded view). + +4. You have deployed your compiled contract to the Remix VM - a simulated blockchain that is running inside of your browser window. The Remix VM is simple, fast test chain. It is not that realistic because you don't need to approve each transaction. + +5. Check the terminal to see detail of this deployment transaction. + +You can also use Remix to deploy to other public EVM chains. To do this, you'll need to connect to a different **Environment** - like Injected Provider. The Injected Provider connects Remix to browser wallet (like MetaMask or similar). We'll try deploying to a public network at the end of this tutorial. But before we get there, we'll cover how to interact with a deployed contract's functions. diff --git a/locales/pt/Basics/interacting/README.md b/locales/pt/Basics/interacting/README.md new file mode 100644 index 000000000..59ef44200 --- /dev/null +++ b/locales/pt/Basics/interacting/README.md @@ -0,0 +1,19 @@ +## Accessing functions in a deployed contract + +1. When a contract has been successfully deployed, it will appear at the bottom of the Deploy and Run plugin. Open up the contract by clicking the caret - so the caret points down. + ![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/instance.png "deployed contract") + +2. There are 2 functions in this contract. To input the parameters individually, clicking the caret to the right of changeOwner (outlined in red below). In the expanded view, each parameter has its own input box. + +![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/deployed_open2.png "deployed contract") + +If this contract had imported other contracts, then the functions of the imported contracts would also be visible here. At some point, try playing with An ERC20 contract to see all its many functions. + +3. Functions with blue buttons are either **pure** or **view** functions. This means that they are just reading a property or are returning a value. In other words, they aren't saving anything - so they are FREE (they don’t cost gas). Functions with other colors - usually orange (depending on the Remix theme) cost gas because they are saving information. They are creating a **transaction**. + +4. 2_Owner.sol does not have a **payable** function. If it did, the button's color would be red. Payable functions allow you to send Ether to the function. To send ETH with a payable function, you put the amount you want to send in the **value** field towards the top of the Deploy & Run module. + +5. In the Remix VM, you don't need to approve a transaction. When using a more realistic test environment or when using the mainnet - you will need to approve the transactions for them to go through. Approving a transaction costs gas. + +6. Choosing a public network is not done in Remix but in your Browser Wallet. There is a plug icon to the right of the Environment title that links to chainlist.org where you can get the specs of the chain you want to interact with. + ![chainlist](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/chainlist.png "chainlist") diff --git a/locales/pt/Basics/interface_introduction/README.md b/locales/pt/Basics/interface_introduction/README.md new file mode 100644 index 000000000..76c953fbd --- /dev/null +++ b/locales/pt/Basics/interface_introduction/README.md @@ -0,0 +1,15 @@ +## Remix is composed of four panels. + +![Remix layout](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/a-layout1c.png "Remix layout") + +- Most plugins appear in the **Side Panel**. +- Editing code happens in tabs in the **Main Panel**. +- The results of transactions and other actions are visible in the **Terminal**. +- Switching between plugins happens in the **Icons Panel**. +- To make a panel larger, drag its border. + +Try clicking the **Solidity Compiler** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/solidity-icon.png) in the **Icons Panel**. Then click the **Deploy & Run** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/deploy-run.png). Then come back to **LearnEth** by clicking this icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/learneth.png). + +In the **Main Panel** of Remix, make sure you see the **Home** tab. The **Home** tab has lots of useful links. To navigate there, either click the **Home** tab in the **Main Panel** or click the Remix icon ![Remix icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/remix-logo.png "Remix icon") on the top of the icon panel. + +- See all the plugins in the **Plugin Manager**. Click this icon ![plugin manager](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/plugin1.png "Plugin Manager icon") in the lower left corner Remix. diff --git a/locales/pt/Basics/load_and_compile/README.md b/locales/pt/Basics/load_and_compile/README.md new file mode 100644 index 000000000..a666d5d13 --- /dev/null +++ b/locales/pt/Basics/load_and_compile/README.md @@ -0,0 +1,20 @@ +Let's load a file from the File Explorer into the Editor. + +1. In the icon panel, click ![file explorer icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/files1.png "file explorer icon") , the File Explorer's icon. + +2. Make sure you are in the **default_workspace**. + +![default workspace](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/default_workspace_open.png) + +3. Open the contracts folder and click on **2_Owner.sol** in the contracts folder. Click it. The file will appear in a tab in the main panel. + +4. In the icon panel, click the **Solidity Compiler** ![solidity compiler icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/solidity1.png "solidity compiler icon"). The Solidity compiler should now be in the side panel. + +5. Click the compile button. + ![compile 2\_owner](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/compile2owner.png "compile 2_Owner") + +6. Compiling can also be triggered by hitting **CTRL + S**. + +The spinner will turn while the file is compiling. + +**Note:** The spinner also turns when the compiler itself is loading. To choose a **different version of Solidity**, go to the select box at the top of the plugin. diff --git a/locales/pt/Basics/workspaces/README.md b/locales/pt/Basics/workspaces/README.md new file mode 100644 index 000000000..97a47d283 --- /dev/null +++ b/locales/pt/Basics/workspaces/README.md @@ -0,0 +1,23 @@ +## Workspaces help organize your separate projects. + +If this is your first time to Remix, a Workspace named **default_workspace** is loaded in the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/default_workspace.png) + +The **default_workspace** has three Solidity (.sol) files in the contracts folder. Remix has a number of other templates. When you load a template, it goes into a Workspace. To go between Workspaces, use the select box at the top of the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/select-box.png) + +But Workspaces are not only for templates. When cloning a repo into Remix, the files will be put into a Workspace. + +Let's create a new Workspace + +1. At the top of the File Explorer, click the hamburger icon (the 3 horizontal lines). Read through the commands and tools in this menu. + +2. Select **+ Create** (the first choice). + +3. In the modal the comes up, choose one of the templates. + +![hamburger](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/workspaces/images/popup.png) + +Notice that in this popup menu, you can clone a repo. Managing a Git repo happens in the DGit plugin. You can also create Github actions with the three workflow choices in the popup menu. diff --git a/locales/pt/CircomHashChecker/README.md b/locales/pt/CircomHashChecker/README.md new file mode 100644 index 000000000..20391a668 --- /dev/null +++ b/locales/pt/CircomHashChecker/README.md @@ -0,0 +1,14 @@ +Hash Checker Tutorial + +This tutorial guides you through creating and understanding a Hash Checker circuit using Remix-IDE. You'll learn how to generate the circuit using a template, explore the code, perform a trusted setup, generate proofs, and verify them. This tutorial is suitable for beginners familiar with Circom and Zero-Knowledge Proofs. + +Prerequisites + +``` +Basic understanding of Zero-Knowledge Proofs and Circom. +Familiarity with Remix-IDE. +``` + +Estimated Time + +Approximately 1-2 hours. diff --git a/locales/pt/CircomHashChecker/config.yml b/locales/pt/CircomHashChecker/config.yml new file mode 100644 index 000000000..2c2aae80a --- /dev/null +++ b/locales/pt/CircomHashChecker/config.yml @@ -0,0 +1,35 @@ +id: circom-hash-checker +name: Hash Checker Tutorial +summary: A tutorial on creating and understanding a Hash Checker circuit using Remix-IDE templates, including trusted setup and proof generation. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction to the Hash Checker Circuit + path: step-1 + - + name: Generating the Hash Checker Template in Remix-IDE + path: step-2 + - + name: Exploring calculate_hash.circom + path: step-3 + - + name: Compiling the Circuit + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Compute Witness + path: step-6 + - + name: Generate Proof + path: step-7 + - + name: Exploring the Trusted Setup Script (Optional) + path: step-8 + - + name: Exploring the Proof Generation Script (Optional) + path: step-9 diff --git a/locales/pt/CircomHashChecker/step-1/README.md b/locales/pt/CircomHashChecker/step-1/README.md new file mode 100644 index 000000000..be922e93b --- /dev/null +++ b/locales/pt/CircomHashChecker/step-1/README.md @@ -0,0 +1,8 @@ +In this tutorial, we'll explore the **Hash Checker** circuit, a zero-knowledge proof (ZKP) application using Circom and Remix-IDE. The Hash Checker circuit allows you to prove knowledge of certain inputs that hash to a given value without revealing the inputs themselves. + +### What You'll Learn + +- How to generate a Hash Checker circuit using Remix-IDE's workspace templates. +- Understanding the Circom code for hashing and checking hashes. +- Performing a trusted setup using Groth16. +- Generating zero-knowledge proofs. diff --git a/locales/pt/CircomHashChecker/step-2/README.md b/locales/pt/CircomHashChecker/step-2/README.md new file mode 100644 index 000000000..bc827019e --- /dev/null +++ b/locales/pt/CircomHashChecker/step-2/README.md @@ -0,0 +1,37 @@ +Follow these steps to create the Hash Checker workspace in Remix-IDE. + +### Step 1: Access the Workspace Templates + +1. In the **File Explorer** sidebar, click on the **hamburger menu icon** (three horizontal lines). + + hamburger-menu + +2. Select **"Create Using Template"** from the dropdown. + + create-using-template + +### Step 2: Find the Hash Checker Template + +1. In the main panel, scroll down to the **"Circom ZKP"** section. + + create-zkp-section + +2. Locate the **"Hash Checker"** item. + +### Step 3: Create the Workspace + +1. Click on the **"Create"** button on the Hash Checker item. + + create-hash-checker + +2. In the modal pop-up, provide a **workspace name** (e.g., `hash-checker-workspace`). + + workspace-name-modal + +3. Click **"OK"** to create the template. + +### Result + +- The workspace is created with the necessary files and directories. + + workspace-name-modal diff --git a/locales/pt/CircomHashChecker/step-3/README.md b/locales/pt/CircomHashChecker/step-3/README.md new file mode 100644 index 000000000..b3ac14050 --- /dev/null +++ b/locales/pt/CircomHashChecker/step-3/README.md @@ -0,0 +1,32 @@ +## Exploring `calculate_hash.circom` + +Navigate to the `circuits` directory and open `calculate_hash.circom`. This file contains the Circom code for the Hash Checker circuit. + +### Code Breakdown + +#### Pragma and Includes: + +- `pragma circom 2.0.0;` specifies the Circom version. +- `include "circomlib/circuits/poseidon.circom";` fetch and includes the Poseidon hash function from [CircomLib](https://github.com/iden3/circomlib). + +#### `CalculateHash` Template: + +- Defines inputs `value1`, `value2`, `value3`, `value4`. +- Uses the `Poseidon` hash function to compute a hash of these values.\ +- Outputs `out`, which is the hash. + +#### `HashChecker` Template: + +- Inputs are the same values plus a `hash`. +- Instantiates `CalculateHash` as `calculateSecret`. +- Computes `calculatedHash`. +- Uses `assert(hash == calculatedHash);` to ensure the provided hash matches the calculated hash. + +#### Main Component: + +- `component main {public [hash]} = HashChecker();` +- Specifies that `hash` is a `public` input, while the values are `private`. + +### Purpose + +The circuit allows someone to prove they know `value1`, `value2`, `value3`, and `value4` that hash to a specific `hash` without revealing the values themselves. diff --git a/locales/pt/CircomHashChecker/step-4/README.md b/locales/pt/CircomHashChecker/step-4/README.md new file mode 100644 index 000000000..537c6a241 --- /dev/null +++ b/locales/pt/CircomHashChecker/step-4/README.md @@ -0,0 +1,32 @@ +## Compiling the Circuit + +### Selecting the Compiler Version + +1. Go to the **Circuit Compiler** plugin in the sidebar. +2. Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +### Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +### Compiling the Circuit + +1. Click on the **Compile** button. +2. Wait for the compilation to complete. A success badge will appear if compilation is successful. + +compilation-success + +### Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/pt/CircomHashChecker/step-5/README.md b/locales/pt/CircomHashChecker/step-5/README.md new file mode 100644 index 000000000..c3ea8509b --- /dev/null +++ b/locales/pt/CircomHashChecker/step-5/README.md @@ -0,0 +1,25 @@ +## Performing a Trusted Setup + +1. **Access the Setup and Exports Section**: + +- After successful compilation, the **Setup and Exports** section becomes available in the plugin. + +2. **Select Proving Scheme**: + +- Choose **Groth16** from the **Proving Scheme** dropdown. + +3. **Select Power of Tau File**: + +- Choose the appropriate **Power of Tau** file from the dropdown. If unsure, use the default option. + +4. **Export Verification Key and Contract** (optional): + +- Enable **Export Verification Key** to save the verification key to the File Explorer. +- Enable **Export Verifier Contract** to save the Solidity contract for on-chain verification. + +trusted-setup + +5. **Run the Trusted Setup**: + +- Click on the **Run Setup** button. +- Wait for the process to complete. This may take some time depending on the circuit complexity. diff --git a/locales/pt/CircomHashChecker/step-6/README.md b/locales/pt/CircomHashChecker/step-6/README.md new file mode 100644 index 000000000..03b848f81 --- /dev/null +++ b/locales/pt/CircomHashChecker/step-6/README.md @@ -0,0 +1,28 @@ +## Compute Witness + +1. **Access the Compute Witness Section**: + - After the trusted setup, the **Compute Witness** section becomes available. + +2. **Input Values**: + - You'll see input fields for `value1`, `value2`, `value3`, `value4`, and `hash`. + - Enter values for each input. For example: + - `value1`: `1234` + - `value2`: `2` + - `value3`: `3` + - `value4`: `4` + +3. **Calculate the Hash**: + + - Compute the Poseidon hash of the four values using an external tool or library compatible with the Poseidon hash function. + - For the values above, here is the computed Poseidon hash `16382790289988537028417564277589554649233048801038362947503054340165041751802`. + - Enter the calculated `hash` value in the `hash` input field. + + compute-witness + +4. **Compute the Witness**: + + - Click on the **Compute Witness** button. + - Wait for the process to complete. A success badge will appear if the witness is computed successfully. + - If successful, you'll see `calculate_hash.wtn` created in the `.bin` directory in the file explorer. + + witness-computed diff --git a/locales/pt/CircomHashChecker/step-7/README.md b/locales/pt/CircomHashChecker/step-7/README.md new file mode 100644 index 000000000..e6ae80fea --- /dev/null +++ b/locales/pt/CircomHashChecker/step-7/README.md @@ -0,0 +1,21 @@ +## Generate Proof + +1. **Access the Generate Proof Section**: + - After computing the witness, expand the **Generate Proof** section. + +2. **Configure Proof Generation**: + - **Export Verifier Calldata**: Enable this option if you plan to verify the proof on-chain. + +3. **Generate the Proof**: + + - Click on the **Generate Proof** button. + - Wait for the proof generation to complete. + + generate-proof + +4. **View the Proof**: + + - The proof data will be displayed in the File Explorer. + - **Congratulations!** You've successfully compiled the `Hash Checker` circuit, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + + generate-proof diff --git a/locales/pt/CircomHashChecker/step-8/README.md b/locales/pt/CircomHashChecker/step-8/README.md new file mode 100644 index 000000000..e489a8cab --- /dev/null +++ b/locales/pt/CircomHashChecker/step-8/README.md @@ -0,0 +1,34 @@ +## Understanding `groth16_trusted_setup.ts` + +Navigate to `scripts/groth16/groth16_trusted_setup.ts`. This script performs the trusted setup necessary for generating proofs. + +### Code Breakdown + +#### Circuit Compilation: + +- Uses `remix.call('circuit-compiler', 'generateR1cs', ...)` to generate `R1CS` (Rank-1 Constraint System) from the circuit. + +#### Trusted Setup Steps: + +- `snarkjs.zKey.newZKey`: Initializes the proving key (`zkey_0`). +- `snarkjs.zKey.contribute`: Adds contributions to the proving key (`zkey_1`). +- `snarkjs.zKey.beacon`: Finalizes the proving key (`zkey_final`). + +#### Verification: + +- `snarkjs.zKey.verifyFromR1cs`: Verifies the proving key against the `R1CS` and initial parameters. + +#### Exporting Keys: + +- Exports the verification key to `scripts/groth16/zk/keys/verification_key.json`. +- Exports the final proving key (`scripts/groth16/zk/keys/zkey_final.txt`). + +### Purpose + +- Performs the trusted setup required for the `Groth16` proving system. +- Generates the necessary keys for proof generation and verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"setup done."` logged in the terminal. diff --git a/locales/pt/CircomHashChecker/step-9/README.md b/locales/pt/CircomHashChecker/step-9/README.md new file mode 100644 index 000000000..653d5ced1 --- /dev/null +++ b/locales/pt/CircomHashChecker/step-9/README.md @@ -0,0 +1,37 @@ +## Understanding `groth16_zkproof.ts` + +Navigate to `scripts/groth16/groth16_zkproof.ts`. This script generates the zero-knowledge proof and prepares it for verification. + +### Code Overview + +#### Loading Files: + +- Reads the R1CS and WASM files generated from the circuit. +- Loads the final proving key (`zkey_final`) and verification key (`vKey`). + +#### Defining Inputs: + +- Sets the private values (`value1`, `value2`, `value3`, `value4`). +- Computes the `hash` using Poseidon from [CircomLib](https://github.com/iden3/circomlib). + +#### Witness Calculation and Proof Generation: + +- Calculates the witness (`wtns`). +- Checks the witness against the `R1CS`. +- Generates the proof using `Groth16`. +- Verifies the proof. + +#### Exporting Verifier Contract and Inputs: + +- Generates a Solidity verifier contract. +- Exports the proof inputs to `input.json`. + +### Purpose + +- Generates a zero-knowledge proof that the prover knows values hashing to a specific hash. +- Prepares the verifier contract and inputs for on-chain verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"zk proof validity"` logged in the terminal. diff --git a/locales/pt/CircomIntro/README.md b/locales/pt/CircomIntro/README.md new file mode 100644 index 000000000..c58b2daec --- /dev/null +++ b/locales/pt/CircomIntro/README.md @@ -0,0 +1,21 @@ +Intro to Circom + +This is an introduction to Circom. You'll learn how to write, compile, and test arithmetic circuits in Circom. We'll go over how to do this within Remix-IDE. + +Tutorial Overview + +``` +Step 1: Introduction +Step 2: Setting Up Remix-IDE and Installing the Circuit-Compiler Plugin +Step 3: Writing Your First Circom Circuit +Step 4: Compiling the Circuit Using the Plugin +Step 5: Performing a Trusted Setup +Step 6: Computing the Witness +Step 7: Generating the Proof +``` + +Prerequisites: + +``` +Basic understanding of cryptography and zero-knowledge proofs is helpful but not required. +``` diff --git a/locales/pt/CircomIntro/config.yml b/locales/pt/CircomIntro/config.yml new file mode 100644 index 000000000..d6dfdca46 --- /dev/null +++ b/locales/pt/CircomIntro/config.yml @@ -0,0 +1,29 @@ +id: circom-intro +name: Intro to Circom +summary: A intro to using Circom for creating arithmetic circuits. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction + path: step-1 + - + name: Installing the Circuit-Compiler + path: step-2 + - + name: Writing Your First Circom Circuit + path: step-3 + - + name: Compiling the Circuit Using the Plugin + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Computing the Witness + path: step-6 + - + name: Generating the Proof + path: step-7 diff --git a/locales/pt/CircomIntro/step-1/README.md b/locales/pt/CircomIntro/step-1/README.md new file mode 100644 index 000000000..0766ce6f4 --- /dev/null +++ b/locales/pt/CircomIntro/step-1/README.md @@ -0,0 +1,13 @@ +Welcome to this beginner-level tutorial on Circom using Remix. In this tutorial, you'll learn the basics of Circom, a domain-specific language used for creating arithmetic circuits. + +**What is Circom?** + +Circom is a language designed for writing arithmetic circuits that can be used in zero-knowledge proofs, particularly zk-SNARKs. It allows developers to define complex mathematical circuits that can prove knowledge of certain data without revealing it. + +**Why Use Remix-IDE for Circom?** + +- **Ease of Use:** Remix-IDE provides a user-friendly interface that simplifies the development process. +- **Integrated Tools:** With plugins like `circuit-compiler`, you can compile Circom code, perform trusted setups, compute witnesses, and generate proofs all within the same environment. +- **No Installation Required:** As a web-based IDE, you can start coding immediately without setting up a local development environment. + +In the next steps, we'll guide you through setting up Remix-IDE for Circom development and help you write your first circuit. diff --git a/locales/pt/CircomIntro/step-2/README.md b/locales/pt/CircomIntro/step-2/README.md new file mode 100644 index 000000000..4b228c298 --- /dev/null +++ b/locales/pt/CircomIntro/step-2/README.md @@ -0,0 +1,25 @@ +In this step, we'll set up Remix for Circom development by activating the `Circom ZKP compiler` plugin. + +## Activating the Circom ZKP compiler + +1. At the bottom of the icon panel on the left of the screen, click on the **Plugin Manager** (the plug icon). + 2.In the search bar, type **Circom**. +2. Find the **Circuit Compiler** plugin in the list and click on the **Activate** button. +3. The plugin will now appear in your sidebar. + +install-plugin + +## The Circom Compiler Interface + +- **Compiler Version Dropdown:** Select the Circom compiler version you wish to use. +- **Auto Compile Checkbox:** Enable this to automatically compile your circuit whenever you make changes. +- **Hide Warnings Checkbox:** Enable this to suppress compiler warnings. +- **Advanced Configuration:** Click to expand options for selecting the prime field (e.g., BN128, BLS12381). + +compiler-interface + +With the plugin installed, you're now ready to start writing Circom code in Remix-IDE. + +**Note:** Make sure your internet connection is stable, as Remix-IDE is a web-based tool. + +In the next step, we'll write our first Circom circuit. diff --git a/locales/pt/CircomIntro/step-3/README.md b/locales/pt/CircomIntro/step-3/README.md new file mode 100644 index 000000000..6424668f6 --- /dev/null +++ b/locales/pt/CircomIntro/step-3/README.md @@ -0,0 +1,38 @@ +Let's write a simple Circom circuit. + +## Creating a New Circuit File + +1. In the **File Explorer** on the left sidebar, click on the **Create New File** icon. +2. Name your file `multiplier.circom` and press **Enter**. + +create-new-file + +## Writing the Circuit + +Open `multiplier.circom` and add the following code: + +```circom +pragma circom 2.0.0; + +template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; +} + +component main = Multiplier(); +``` + +## Explanation: + +- template `Multiplier()`: Defines a new circuit template called Multiplier. +- `signal input a;` and `signal input b;`: Declare input signals a and b. +- `signal output c;`: Declare an output signal c. +- `c <== a * b;`: Constrain c to be the product of a and b. +- `component main = Multiplier();`: Instantiates the Multiplier circuit as main, which is required for the compiler. + +### NB: + +Signals are values in a cryptographic circuit that are strictly determined by the circuit's equations and constraints. Think of a signal as a value that must follow specific mathematical rules defined by the circuit—once set, it can't be changed arbitrarily. In regular programming, variables are flexible and can be updated or reassigned as needed, whereas, signals can't be altered freely. diff --git a/locales/pt/CircomIntro/step-4/README.md b/locales/pt/CircomIntro/step-4/README.md new file mode 100644 index 000000000..ad3f2a089 --- /dev/null +++ b/locales/pt/CircomIntro/step-4/README.md @@ -0,0 +1,34 @@ +With your `multiplier.circom` circuit ready, let's compile it using the Circuit Compiler plugin. + +## Selecting the Compiler Version + +Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +## Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +## Compiling the Circuit + +1. Click on the **Compile** button. +2. The compiler will process your circuit. +3. If successful, you'll see a compilation success message. + +compilation-success + +**Note:** If there are any errors, they will be displayed in the console. Check your code for typos or syntax errors. + +## Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/pt/CircomIntro/step-5/README.md b/locales/pt/CircomIntro/step-5/README.md new file mode 100644 index 000000000..8e8496bbd --- /dev/null +++ b/locales/pt/CircomIntro/step-5/README.md @@ -0,0 +1,26 @@ +After compiling your circuit, you need to perform a trusted setup to generate proving and verification keys. + +## Understanding Trusted Setup + +- **Trusted Setup:** A process required for zk-SNARKs to generate the necessary parameters for proof generation and verification. +- You can choose between different protocols like **Groth16** and **Plonk**. + +## Performing the Trusted Setup + +1. In the **Setup and Exports** section, select the **Proving Scheme**: + - Choose between **Groth16** or **Plonk**. We'll use **Groth16** for this tutorial. + +2. Choose the appropriate **Power of Tau** file from the dropdown. This file is necessary for the trusted setup. + - If unsure, select the default option. + +3. Click on the **Setup** button to start the trusted setup process. + +4. You can enable **Export Verification Key** to get the verification parameters. + +5. You can enable **Export Verification Contract** if you intend to verify proofs on-chain. + +trusted-setup + +**Note:** The trusted setup may take some time, depending on the complexity of your circuit. + +In the next step, we'll compute the witness for our circuit. diff --git a/locales/pt/CircomIntro/step-6/README.md b/locales/pt/CircomIntro/step-6/README.md new file mode 100644 index 000000000..e13d33d32 --- /dev/null +++ b/locales/pt/CircomIntro/step-6/README.md @@ -0,0 +1,27 @@ +With the trusted setup complete, you can now compute the witness for your circuit based on specific inputs. + +## What is a Witness? + +- A **Witness** is a set of values that satisfy all the constraints of your circuit. It includes all the intermediate numbers and results that satisfy the circuit's rules. The witness is used in zero-knowledge proofs to demonstrate that you know a valid solution to the problem without actually showing the solution itself. This allows others to verify that you did everything correctly while keeping your specific numbers and calculations private. +- It is essential for generating a proof. + +## Inputting Values + +1. In the **Compute Witness** section, you'll see input fields dynamically generated based on your circuit's inputs. +2. Enter values for `a` and `b`. For example: + - `a = 3` + - `b = 4` + +compute-witness + +## Computing the Witness + +1. After entering the inputs, click on the **Compute Witness** button. +2. The plugin will compute the witness based on your inputs. +3. If successful, you'll see `multiplier.wtn` created in the `.bin` directory in the file explorer. + +witness-computed + +**Note:** If there are any errors, ensure that your inputs are valid and satisfy the circuit's constraints. + +In the next step, we'll generate a proof using the computed witness. diff --git a/locales/pt/CircomIntro/step-7/README.md b/locales/pt/CircomIntro/step-7/README.md new file mode 100644 index 000000000..f5cf332a9 --- /dev/null +++ b/locales/pt/CircomIntro/step-7/README.md @@ -0,0 +1,31 @@ +With the witness computed, the final step is to generate a proof that can be verified by others. + +## Generating the Proof + +1. In the **Generate Proof** section, you have the option to **Export Verifier Calldata**. + - Enable the **Export Verifier Calldata** checkbox if you plan to verify the proof on-chain. +2. Click on the **Generate Proof** button. + +generate-proof + +## Understanding the Output + +- After generating the proof, the plugin will display the proof data. +- If you enabled **Export Verifier Calldata**, it will also provide the calldata needed for on-chain verification. + +proof-generated + +## Next Steps + +- **Verification:** You can use the verification key or contract exported earlier to verify the proof. +- **On-Chain Verification:** If you're familiar with smart contracts, you can deploy the verification contract and use the calldata to perform on-chain verification. + +**Congratulations!** You've successfully written a Circom circuit, compiled it, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + +## Additional Resources + +- [Circom Documentation](https://docs.circom.io/) +- [Remix-IDE Documentation](https://remix-ide.readthedocs.io/) +- [Zero-Knowledge Proofs Explained](https://zkproof.org/) + +Feel free to experiment with more complex circuits and explore the capabilities of Circom and Remix-IDE further. diff --git a/locales/pt/DeployWithLibraries/1_Writing_a_Library/step1.md b/locales/pt/DeployWithLibraries/1_Writing_a_Library/step1.md new file mode 100644 index 000000000..1ad984835 --- /dev/null +++ b/locales/pt/DeployWithLibraries/1_Writing_a_Library/step1.md @@ -0,0 +1,17 @@ +A libraries looks like a **contract** but use the keyword `library` + +A library typically is a collection of useful functions sitting out there on the blockchain that any contract can use. Because the library is already deployed, it saves the deployment costs of the many contracts that use it. + +In the following contract: + +- Make a library with the name `LibraryForTest`. + +It is possible to put a library in same file with another contract. So put the library below the contract. + +This library should have a method called `getFromLib` method which returns `3`. + +- Update the `get` method in the `test` contract to use the `LibraryForTest` library. The function `get` should return the value it receives from `getFromLib`. + +--------- + +You can find more info about libraries in this section of the Solidity Docs. diff --git a/locales/pt/DeployWithLibraries/2_Generate_Metadata/step2.md b/locales/pt/DeployWithLibraries/2_Generate_Metadata/step2.md new file mode 100644 index 000000000..218c86ff9 --- /dev/null +++ b/locales/pt/DeployWithLibraries/2_Generate_Metadata/step2.md @@ -0,0 +1,38 @@ +## Deploying Library + +The **library** from the previous chapter was in the same file as the **contract**. However, they won't be deployed together and will have different addresses. + +In order to use a library, the calling contract must have the library's **address**. + +But the library's address is not directly specified in the solidity code. The calling contract's compiled bytecode contains a **placeholder** where library's **addresses** will go. + +At deployment of the **calling contract**, Remix will look in the contract's **metadata** for the library's address and will update the placeholder with the address. + +So before deploying a contract that calls a library, you need to generate the contract's metadata (AKA its **build artifact**) and then you need to input the library's address into the metadata file. + +A contract's metadata is generated at **compile time**. + +Let's setup Remix to generate the **metadata file**. + +- Go to the settings module by clicking on the settings ![settings](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/settings.png "Settings") icon in the icon panel. + +![settings module](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_settings.png "Settings Module") + +- And check the first option `Generate contract metadata`. + +# Compile and generate metadata (JSON) file. + +1. Open the Solidity Compiler ![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +2. Compile `2_contractSimpleLibrary.sol`. + +3. Switch to the File Explorer ![File Explorer](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_file_explorer.png "File Explorer") + +4. Navigate to the newly create JSON files. + - It should be in the folder: + +**browser/.learneth/DeployWithLibraries/2_Generate_Metadata/artifacts/** + +5. Select the newly created JSON file created from the contract. It has the **same name** as the contract `sample` but with the extension **json**: `sample.json` (don't select the library's metadata `contractSimpleLibrary.json`). + +In the next step we'll make some adjustments to the metadata file. diff --git a/locales/pt/DeployWithLibraries/3_Edit_Metadata/step3.md b/locales/pt/DeployWithLibraries/3_Edit_Metadata/step3.md new file mode 100644 index 000000000..1555d645d --- /dev/null +++ b/locales/pt/DeployWithLibraries/3_Edit_Metadata/step3.md @@ -0,0 +1,12 @@ +The `Deploy` property in `sampleContract.json` contains everything you need for telling Remix IDE the address of the library for a specific network. + +- `
` contains the address of the library that is already deployed. You have to specify this address for each network. +- `autoDeployLib` is a boolean and tells Remix IDE if it should autodeploy the library before deploying the contract. + +Basically if `autoDeployLib` is **true**, the `
` will not be used and Remix will automatically deploy the library before deploying the contract. + +For the purpose of this demo - we are mimicking a situation where the library has already been deployed because this is a more common situation. + +So set `autoDeploy` to **false**, for the `VM:-` entry. + +Move to next Step. diff --git a/locales/pt/DeployWithLibraries/4_Linking_and_Deploying/step4.md b/locales/pt/DeployWithLibraries/4_Linking_and_Deploying/step4.md new file mode 100644 index 000000000..ad5f52e2d --- /dev/null +++ b/locales/pt/DeployWithLibraries/4_Linking_and_Deploying/step4.md @@ -0,0 +1,25 @@ +Switch to the `Deploy & Run` module +![Run transaction](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/remix_runtransaction.png "Run Transaction") + +- Select the Remix VM Environment and select the `sampleContract` contract in the list of compiled contracts. + +- Click on `Deploy` + +The terminal should output something like `creation of sample errored:
is not a valid address. Please check the provided address is valid.` +That is expected: **We have set `autoDeployLib` to false, so Remix expects to have an address and not just `
`** + +So we need deploy the library to get its address. + +- Select the library `aLib` in the list of compiled contract and hit `deploy` + + ![Choose aLib](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/contract_alib.png "Choose aLib") + +- Click the clipboard icon to copy the address of the library. + + ![Copy lib1](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/alib_copy.png "Copy") + +- Paste it into the **contract sample's** metadata JSON. + +- Reselect the `sampleContract` contract in the `Run transaction` module and hit deploy. + +- Deploy should now be successful. diff --git a/locales/pt/DeployWithLibraries/5_Under_The_Hood/step5.md b/locales/pt/DeployWithLibraries/5_Under_The_Hood/step5.md new file mode 100644 index 000000000..860b48b24 --- /dev/null +++ b/locales/pt/DeployWithLibraries/5_Under_The_Hood/step5.md @@ -0,0 +1,30 @@ +Switch to the `Solidity compiler` module +![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +- Select the `sampleContract` contract in the list of compiled contracts. +- click on `ByteCode`, it should copy the following to the clipboard: + +``` +{ + "linkReferences": { + "browser/contractSimpleLibrary.sol": { + "lib1": [ + { + "length": 20, + "start": 115 + } + ] + } + }, + "object": "608060405234801561001057600080fd5b5060f68061001f6000396000f3fe6080604052600436106039576000357c0100000000000000000000000000000000000000000000000000000000900480636d4ce63c14603e575b600080fd5b348015604957600080fd5b5060506052565b005b73__$d42d70ba92b626965f4c69b39148e37a33$__63fea24e5f6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801560b157600080fd5b505af415801560c4573d6000803e3d6000fd5b5050505056fea165627a7a7230582068c9a3a9a5cbfd26cfdab2534abfc926912d9b89eaa14e36c8248b7e7eb0ab090029", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xF6 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x39 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x3E JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x50 PUSH1 0x52 JUMP JUMPDEST STOP JUMPDEST PUSH20 0x0 PUSH4 0xFEA24E5F PUSH1 0x40 MLOAD DUP2 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH1 0xB1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS DELEGATECALL ISZERO DUP1 ISZERO PUSH1 0xC4 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 PUSH9 0xC9A3A9A5CBFD26CFDA 0xb2 MSTORE8 0x4a 0xbf 0xc9 0x26 SWAP2 0x2d SWAP12 DUP10 0xea LOG1 0x4e CALLDATASIZE 0xc8 0x24 DUP12 PUSH31 0x7EB0AB09002900000000000000000000000000000000000000000000000000 ", + "sourceMap": "63:85:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63:85:0;;;;;;;" +} +``` + +This is basically what the compiler is returning: + +- `linkReferences` describes what are the libraries used by the contract. +- `object` is the compiled contract (bytecode). This is what gets deployed and saved onto the blockchain. In this example, the value `__$d42d70ba92b626965f4c69b39148e37a33$__` inside the bytecode is just a placeholder for the library address. In your case, the placeholder will be between `__$` and `$__`. + +The metadata JSON from Remix IDE tells Remix to replace the placeholder with the given address. diff --git a/locales/pt/DeployWithLibraries/README.md b/locales/pt/DeployWithLibraries/README.md new file mode 100644 index 000000000..fb31b1264 --- /dev/null +++ b/locales/pt/DeployWithLibraries/README.md @@ -0,0 +1,3 @@ +**Libraries** are deployed contracts that do not store state and are used by other contracts to decrease their size and thus their deployment costs. + +Learn to work with **Libraries** in Remix - you won't need to whisper. diff --git a/locales/pt/DeployWithLibraries/config.yml b/locales/pt/DeployWithLibraries/config.yml new file mode 100644 index 000000000..0816e2346 --- /dev/null +++ b/locales/pt/DeployWithLibraries/config.yml @@ -0,0 +1,8 @@ +--- +id: deploylibraries +name: Deploy with Libraries +summary: Write, Deploy and link a Library to a Contract +level: 3 +tags: + - Remix + - Solidity diff --git a/locales/pt/ERC20TokenCourse/README.md b/locales/pt/ERC20TokenCourse/README.md new file mode 100644 index 000000000..25a6ccf95 --- /dev/null +++ b/locales/pt/ERC20TokenCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Token Course + +Learn to understand and create ERC20 tokens. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/pt/ERC20TokenCourse/config.yml b/locales/pt/ERC20TokenCourse/config.yml new file mode 100644 index 000000000..8c12a5213 --- /dev/null +++ b/locales/pt/ERC20TokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: tokenCourse +name: Solidity ERC20 Token Course +summary: Learn how to create your own ERC20 tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - ERC20 +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc20-interface + - + name: 3. Token Creation + path: erc20-token-creation + - + name: 4. Interaction + path: erc20-interaction + - + name: 5. Testnet Deployment + path: erc20-testnet-deployment + - + name: 6. Extensions + path: erc20-extensions diff --git a/locales/pt/ERC20TokenCourse/erc20-extensions/erc20extensions.md b/locales/pt/ERC20TokenCourse/erc20-extensions/erc20extensions.md new file mode 100644 index 000000000..b3649fbba --- /dev/null +++ b/locales/pt/ERC20TokenCourse/erc20-extensions/erc20extensions.md @@ -0,0 +1,33 @@ +The ERC20 standard only describes the required and optional functionality that your contract needs, but you can add additional functionality. + +In this section, we added the functionality to burn and mint tokens, as well as the ability to pause the contract, by using OpenZeppelin extensions. + +Of course, you can write your own ERC20 token contract implementation or extensions and import them into your contract. But OpenZeppelin contracts have been audited by security experts and are a great way to add desired functionality. + +### Mintable + +The mint function allows the creator of the contract to mint (create) additional tokens after the contract has been deployed (line 22). As input parameters, the function needs the address that the tokens will be minted to, and the amount of tokens that should be minted. + +We don't have to import `mint()` from another contract since the mint function is already part of the ERC20 contract implementation of OpenZeppelin. We import `Ownable` (line 7) which is a contract module that provides a basic access control mechanism that allows an owner to have exclusive access to specific functions. In this contract, we add the inherited `onlyOwner` modifier to the `mint` function (line 22) and restrict access to this function to the "owner". + +The contract will inherit additional functions like owner(), transferOwnership() and renounceOwnership() to manage access, from the Ownable contract. + +### Burnable + +By importing the "ERC20Burnable" (line 5) and inheriting its functions (line 9) our contract allows token holders to destroy their tokens as well as the tokens in their allowance. +For more information, have a look at the ERC20Burnable contract. + +### Pausable + +With the "Pausable" contract module (line 6 and 9) the owner is able to pause (line 14) and unpause (line 18) the contract. In the pause state, tokens can't be transferred, which can be helpful in emergency scenarios. +For more information, have a look at the Pausable contract. + +Have a look at the OpenZeppelins Contract Wizard, which allows you to easily add additional functionality. + +If you successfully completed this course, try the Learneth NFT Course as the next step in your journey. + +## ⭐️ Assignment + +1. Try to mint tokens to an account after deployment. Call `totalSupply()` and `balanceOf()` to confirm the correct execution. +2. Burn tokens and then call `totalSupply()` and `balanceOf()` to confirm the correct execution. +3. Test the pause function by pausing the contract using the owner account and trying to make a transfer with a second account. The transaction should not be able to be executed and will throw the exception: "Pausable: paused". diff --git a/locales/pt/ERC20TokenCourse/erc20-interaction/er20interaction.md b/locales/pt/ERC20TokenCourse/erc20-interaction/er20interaction.md new file mode 100644 index 000000000..5c082b248 --- /dev/null +++ b/locales/pt/ERC20TokenCourse/erc20-interaction/er20interaction.md @@ -0,0 +1,87 @@ +In this section, we will deploy a contract in our browser and test its functionality. + +### 1. Deploy the contract + +**1.1** Compile your EduCoin contract in the "Solidity compiler" module of the Remix IDE. + +**1.2** In the "Deploy & run transactions" module, select your contract "EduCoin" in the contract input field and click on the "Deploy" button. Always make sure to select the correct contract in the contract selector input field. + +**GIF** Compile and deploy: Compile and deploy contract + +### 2. Test the functions + +Expand the token contract functions in the IDE. + +#### 2.1 Decimals + +Click on the "decimals" button to call the decimals() function. +It should return "18". + +#### 2.2 Name + +Click on the "name" button to call the name() function. +It should return "EduCoin". + +#### 2.3 Symbol + +Click on the "symbol" button to call the symbol() function. +It should return "EDC". + +#### 2.4 Total supply + +Click on the "totalSupply" button to call the totalSupply() function. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test decimals, name, symbol, and totalSupply functions: Test transfer function + +#### 2.5 Balance of + +**2.5.1** Go to the "ACCOUNT" section in the sidebar and copy the displayed address by using the copy icon next to it. + +**2.5.2** Paste the address in the input field next to the "balanceOf" function button and click on the button. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test balanceOf function: Test transfer function + +#### 2.6 Transfer + +We will transfer EduCoin from one account to a second account. + +**2.6.1** Go to the "ACCOUNT" section in the sidebar and click on the displayed address. This should open a dropdown. Select the second address displayed and copy its address (account 2). + +**2.6.2** Open the dropdown and select the first account again (account 1), because this is the account that we want to use to make the transfer. + +**2.6.3** Paste the address in the input field next to the "transfer" function button, input the number 500000000000000000000, and click on the button. + +**2.6.4** If you check the balances for account 1 and account 2, they should both return the amount 500000000000000000000. + +**GIF** Test transfer function: Test transfer function + +#### 2.7 Approve + +We will now allow account 1 to spend tokens on behalf of account 2. + +**2.7.1** Go to the "Account" section, copy the address of account 1, then set it to account 2 again. + +**2.7.2** In the approve function, enter the address of account 1 as the input for spender and set the amount to 250000000000000000000. + +**GIF** Test approve function: Test approve function + +#### 2.8 Allowance + +Next to the "allowance" button enter the address of account 2 as the owner and account 1 as the spender; click on the button. +It should return 1000000000000000000000. + +**GIF** Test allowance function: Test allowance function + +#### 2.9 TransferFrom + +Now account 1 will transfer 250000000000000000000 tokens from account 2 to its own account. + +**2.9.1** Select account 1 in the "ACCOUNT" section. + +**2.9.2** Next to the "transferFrom" button enter the address of account 2 as the sender and account 1 as the recipient, enter 250000000000000000000 as the amount and click on the button. + +**2.9.3** Check the balances of accounts 2 and 1, they should return 250000000000000000000 and 750000000000000000000. + +**GIF** Test transferFrom function: Test transferFrom function diff --git a/locales/pt/ERC20TokenCourse/erc20-interface/erc20interface.md b/locales/pt/ERC20TokenCourse/erc20-interface/erc20interface.md new file mode 100644 index 000000000..5c4e8137c --- /dev/null +++ b/locales/pt/ERC20TokenCourse/erc20-interface/erc20interface.md @@ -0,0 +1,76 @@ +ERC20 (Ethereum Request for Comments 20) is a standard for token contracts that manages fungible tokens on the Ethereum blockchain. + +Fungible tokens are all equal to each other and have the same value, behavior, and rights. Fungible tokens are often used as a medium of exchange, like the currencies ETH or BTC. However, they can also have other use cases like voting rights or reputation. + +If you want to know more about the ERC20 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +To get an overview of the required functionality of an ERC20 token contract, we will look at an interface that interacts with an ERC20 contract. +This interface (line 9) is part of the open-source contract library provided by OpenZeppelin. + +## ERC20 Functions + +Contracts compliant with the ERC20 standard must implement the following six functions: + +### totalSupply + +The function `totalSupply` (line 13) returns the total amount of tokens available. + +### balanceOf + +The function `balanceOf` (line 18) returns the amount of tokens owned by the account with the address `account`. + +### transfer + +The function `transfer` (line 27) transfers `amount` of tokens to the address `recipient`. +This function **must** emit (produce) a `Transfer` event (see below) and **should** throw an exception when the sender doesn't have enough tokens to make the transfer. + +### approve + +The function `approve` (line 52) creates an allowance for the address `spender` to transfer `amount` of tokens on behalf of the account calling the function. + +### allowance + +The function `allowance` (line 36) returns the amount of tokens that the address `spender` is allowed to spend on behalf of the account with the address `owner`. + +### transferFrom + +The function `transferFrom` (line 63) transfers `amount` of tokens on behalf of the address `sender` to the address `recipient`. +This function **must** emit a `Transfer` event. + +## ERC20 Events + +ERC20 contracts must also emit two events: + +### Transfer + +The `Transfer` (line 71) event must be emitted when `value` amount of tokens are transferred from the account with the address `indexed from` to `indexed to`. The parameters `from` and `to` are `indexed` allowing us to search for these events using the indexed parameters as filters. + +### Approval + +The `Approval` (line 77) event must be emitted when the account `indexed owner` approves the account `indexed spender` to transfer `value` amount of tokens on its behalf. + +## ERC20 Optional functions + +In addition to the mandatory functions and events, there are also three optional functions specified in the ERC20 standard that are not implemented in this interface: + +### name + +`function name() external view returns (string);` + +Returns the name of the token. + +### symbol + +`function symbol() external view returns (string);` + +Returns the symbol of the token. + +### decimals + +`function decimals() external view returns (uint8);` + +Returns the number of decimal places the token uses. + +You may want to use decimals to make your token divisible into arbitrary amounts like 1.5 ETH when displayed. The EVM (Ethereum virtual machine) only supports integer numbers. That's why the ERC20 standard suggests to implement the decimal functionality that specifies how many decimal places a token has. 18 decimal places is the industry standard. diff --git a/locales/pt/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md b/locales/pt/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md new file mode 100644 index 000000000..94b513922 --- /dev/null +++ b/locales/pt/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md @@ -0,0 +1,41 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to a testnet of the Ethereum blockchain. This testnet behaves very similarly to the real blockchain (mainnet), but does not require real ETH to pay for transactions. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token + +In order to make transactions on the testnet we need Ethereum testnet tokens, which you can receive from something called a _faucet_. + +**2.1** Switch your Metamask network by clicking on the "Ethereum Mainnetwork" drop down and selecting "Ropsten Test Network". If you don’t see any test networks, click on the "Show/hide" link and enable "Show test networks" in the settings. + +**2.2** Go to https://faucet.ropsten.be/, enter the address of your account, and claim testnet ETH. You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Deployment + +Make sure the EduCoin contract is compiled. + +**3.1.** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It will ask you to connect your account which you should confirm. + +**3.2** Deploy the EduCoin contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. Copy the contract address. + +**3.4** In Metamask, click on assets, then click on the "Import tokens" link, and paste the address of your contract in the input field. + +You should now see a balance of 1000 EDC in your wallet. + +### 4. Make a transaction + +**4.1** Click on the identicon (visual representation of your address) in the Metamask wallet and create a second account (Account 2). + +**4.2** Copy the address of Account 2. + +**4.3** Switch to the first account (Account 1) and send 250 EDC to Account 2. Check the balances of Account 1 and Account 2. You might need to add the token address again for Account 2 to import the tokens and you will need testeth if you want to make a transaction with this account. + +You can also see your account balances if you look at the contract in Remix and call the `balanceOf` function using the addresses of Account 1 and Account 2. diff --git a/locales/pt/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md b/locales/pt/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md new file mode 100644 index 000000000..49b71abdd --- /dev/null +++ b/locales/pt/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md @@ -0,0 +1,18 @@ +A token standard tells us what functionality the contract needs to comply with it. How this functionality is implemented is up to the developers. In this contract, we will use an ERC20 token contract implementation from OpenZeppelin (line 4). In this case, we import version 4.4.0 of the OpenZeppelin contracts. + +Have a look at their nicely documented ERC20 contract to have a better understanding of how an implementation might look. Apart from the functionality specified in the ERC20 standard, this contract provides additional functionality. + +We will create our own contract called MyToken (line 6), which inherits the functionality from the OpenZepplin ERC20 token contract implementation that we imported (line 4). + +This contract implements the optional functions `name()` and `symbol()` of the ERC20 Token standard and has a constructor where their values can be set during the deployment of the contract (line 7). +In this case, we are going to use the default values. We will call our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +Next, we make use of the inherited `_mint` function (line 8) that allows us to create tokens upon deployment of the contract. Inside the parameters, we specify the address of the account that receives the tokens and the amount of tokens that are created. +In this case, the account that deploys the contract will receive the tokens and we set the amount to 1000000 to the power of `decimals()`. The optional function `decimals()` of the ERC20 token standard is implemented and set to the default value of 18. This will create 1000000 tokens that will have 18 decimal places. + +## ⭐️ Assignment + +1. Rename your contract to `EduCoin`. +2. Rename your token to `EduCoin`. +3. Change the symbol of your token to `EDC`. +4. Change the amount of tokens that will be minted from 1000000 to 1000. diff --git a/locales/pt/ERC20TokenCourse/introduction/introduction.md b/locales/pt/ERC20TokenCourse/introduction/introduction.md new file mode 100644 index 000000000..4eaf7583c --- /dev/null +++ b/locales/pt/ERC20TokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with the ERC20 token standard in the following sections. + +If you want to learn more about NFTs and the ERC721 token standard, have a look at the Learneth NFT Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/pt/ERC721Auction/README.md b/locales/pt/ERC721Auction/README.md new file mode 100644 index 000000000..325e4d60e --- /dev/null +++ b/locales/pt/ERC721Auction/README.md @@ -0,0 +1,5 @@ +## NFT Auction Contract + +Learn how to write an ERC721 (NFT) auction contract. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/pt/ERC721Auction/auction-contract-setup/auctionContractSetup.md b/locales/pt/ERC721Auction/auction-contract-setup/auctionContractSetup.md new file mode 100644 index 000000000..945f0f803 --- /dev/null +++ b/locales/pt/ERC721Auction/auction-contract-setup/auctionContractSetup.md @@ -0,0 +1,46 @@ +In this contract tutorial, we will learn how to create an ERC721 (NFT) auction contract. +We recommend to you, to do the Learneth "Solidity NFT Course" before starting this tutorial. + +In the following sections, we will create a contract that will enable a seller to auction an NFT to the highest bidder. This contract was created by the Solidity by Example project. In this first section, we will create an interface, the necessary state variables, and the constructor. + +### Interface + +We create the interface (line 5) for the ERC721 token since our contract will need to interact with it. We will need the `safeTransferFrom` (line 5), and` transferFrom` (line 11) methods. + +### EnglishAuction + +We create the four events `Start`, `Bid`, `Withdraw`, `End` (line 19-22) so we can log important interactions. + +Next, we will create the state variables that store all the necessary information about our auction on-chain. + +We create two state variables for the NFT we want to auction. In the variable `nft` (line 24) we store a representation of the NFT contract, that will allow us to call its functions by combining the interface IERC721 and the address of the NFT contract. +In `nftId` (line 25), we store the specific token id in our NFT contract that will be auctioned. + +Next, we need a variable to store the address of the person that is auctioning off the NFT, the `seller` (line 27). +We want our NFT contract to send the seller the proceeds of the auction when it is finished, that’s why use `address payable`. + +We create a state variable `endAt` (line 28) where we will store the end date of the auction. +We also create the two booleans, `started` (line 29) and `ended` (line 30), that keep track of whether the auction has started or ended. + +We create a variable `highestBidder` (line 32) where we will store the address of the highest bidder. We will send the highest bidder the NFT once the auction has ended. + +Finally, we need a uint `highestBid` (line 33) to store the highest bid and a mapping `bids` (line 34), where we can store the total value of bids that an account has made before withdrawing; more on this in the next section. + +### Constructor + +When the auctioneer deploys the contract, they need to provide a few arguments: +the address of the contract of the NFT they want to auction `_nft` (line 37), the token id of the NFT they want to auction `_nftId` (line 38), and a starting price that must be overbid to place the first bid in the auction,`_startingBid` (line 39). + +Once deployed, the state variables `nft` (line 41), `nftId` (line 42), `highestBid` (line 45) will be assigned the values from the arguments. The address of the `seller` that deployed the contract will be automatically read out via msg.sender and stored in the state variable `seller` (line 44). + +In the next section, we will enable the auctioneer to start the auction and bidders to place their bids. + +## ⭐️ Assignment + +We will use the assignment part of the following sections to give you instructions on testing your contract in the Remix VM environment of Remix. + +1. Deploy an NFT contract. You can use the NFT contract that we created in our "3.3 ERC721 - Token Creation" section. + +2. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +3. After deploying your contract, test if contract functions like `nft`, `nftId`, and `started` work as expected. diff --git a/locales/pt/ERC721Auction/auction-start-bid/auctionContractStartBid.md b/locales/pt/ERC721Auction/auction-start-bid/auctionContractStartBid.md new file mode 100644 index 000000000..c2b944e0c --- /dev/null +++ b/locales/pt/ERC721Auction/auction-start-bid/auctionContractStartBid.md @@ -0,0 +1,42 @@ +In this section, we will create a function to start the auction and a function to bid on the NFT. + +### Start + +We use some control structures to check if necessary conditions are met before we let the seller start the auction. + +First, we check if the auction has already started (line 49). If it has started and our state variable `started` returns `true` we exit the function and throw an exception. + +The second condition we check for is whether the seller is executing the function (line 50). We have already created a function to store the seller's address when they deploy the contract in the `seller` state variable and can now check if the account executing the start function is the seller. If not we throw an exception. + +Next, we want to transfer the NFT that is up for auction from the seller to the contract (line 52). +We set the state variable `started` to `true` (line 53), and create an end date for the auction (line 54). In this case, it will be seven days from when the start function has been called. We can use a suffix like `days` after a literal number to specify units of time. If you want to learn more about time units have a look at the solidity documentation. + +Finally, we will emit our `Start()` event (line 56). + +### Bid + +Before the function caller can make a bid, we need to be sure that certain conditions are met. The auction needs to have started (line 60), the auction can not have ended (line 61) and the bid (the value attached to the call) needs to be higher than the current highest bid (line 62). + +Now we want to store the bid of the current highest bidder before we make a new bid. +First, we check if there is a bidder (line 64). If this function call is the first bid then the next line would be irrelevant. +In our mapping `bids` (line 34) we map the key, the `address` of the bidder, to the value, a `uint` that represents the total amount of ETH a bidder has bid in the auction before withdrawing. +If there is a bidder, we add the last bid (`highestBid`) of the `highestBidder` to the total value of the bids they have made (line 65) before withdrawing. +We store the bids because we want to enable the bidder to withdraw the ETH they used to make bids if they are no longer the highest bidder. + +Next, we set the `highestBidder` to the account calling the function (line 68), and the `highestBid` to their bid, the value that was sent with the call (line 69). + +Finally, we emit the `Bid` event (line 71). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we create in our "Solidity NFT Course" Learneth course. + +2. Mint yourself an NFT with the tokenId 0. + +3. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +4. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for `tokenId`. This will allow the contract to transfer the token to be auctioned. + +5. Call the `start` function of your auction contract. If you call the `started` function now, it should return `true`. If you call the `highestBid` function it should return 1. + +6. Set the value that you can attach to transactions to 3 Wei and call the `bid` function of the auction contract. If you call the `highestBid` function it should now return 3. diff --git a/locales/pt/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md b/locales/pt/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md new file mode 100644 index 000000000..e324a5c6e --- /dev/null +++ b/locales/pt/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md @@ -0,0 +1,45 @@ +In this section, we will finish the contract, create a function to withdraw the bids that an account has made, and create a function to end the auction. + +### Withdraw + +We create a local variable `bal` (balance) that stores the total value of bids that the function caller has made (line 75) since their last withdrawal. We can assign this value to `bal` by accessing the bids mapping using the address of the function caller as the key. + +Next, we set the value of the address of the function caller to 0 in the bids mapping because they will withdraw the total value of their bids (line 76). + +Now we transfer that amount of ETH from the contract to the function caller and emit the `Withdraw` event (line 79). + +### End + +Before the function caller can execute this function and end the auction, we need to check if certain conditions are met. The auction needs to have started (line 83), the end date of the auction needs to have been reached (line 84), and the auction must not have ended already (line 85). + +Once the auction has ended, we set the state variable `ended` to `true` (line 87). + +We check if anybody participated in the auction and bid on the NFT (line 88). + +If there was a bid, we transfer the NFT from the contract to the highest bidder (line 89) and transfer the ETH that was sent from the highest bidder to the contract, now to the address of the auctioneer, the seller of the NFT (line 90). + +If nobody bids on the NFT, we send the NFT back to the auctioneer (line 92). + +Finally, we emit the `End` event (line 95). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we created in our Learneth "Solidity NFT Course". + +2. Mint yourself an NFT with the tokenId 0. + +3. For testing purposes, change the value that is assigned to the `endAt` state variable (line 54) from `7 days` to `5 minutes`. + +4. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +5. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for the `tokenId`. + +6. Call the `start` function of your auction contract. + +7. Bid 2 Ether using account 1, and 3 Ether using account 2. If you call the `highestBidder` function, it should now return the address of account 2. + +8. Call the `withdraw` function with account 1. In the balance of account 1, you should see the 2 Ether minus some transaction fees. + +9. After 5 minutes have passed, call the `end` function. Then, call the `ended` function which should return `true`. + +In the NFT contract, if you call the `ownerOf` function with the tokenId 0, it should return the address of account 2. If you look at the balance of account 1 it should have increased by 3 Ether minus some transaction fees. diff --git a/locales/pt/ERC721Auction/config.yml b/locales/pt/ERC721Auction/config.yml new file mode 100644 index 000000000..0783a37a1 --- /dev/null +++ b/locales/pt/ERC721Auction/config.yml @@ -0,0 +1,19 @@ +--- +id: er721Auction +name: NFT Auction Contract +summary: Learn how to write an ERC721 (NFT) auction contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: Contract Setup + path: auction-contract-setup + - + name: Start and Bid Functions + path: auction-start-bid + - + name: Withdraw and End Functions + path: auction-withdraw-end diff --git a/locales/pt/Interoperability/1_Intro/intro.md b/locales/pt/Interoperability/1_Intro/intro.md new file mode 100644 index 000000000..ab26f4f6d --- /dev/null +++ b/locales/pt/Interoperability/1_Intro/intro.md @@ -0,0 +1,5 @@ +As the web3 world grows, there will be more blockchains. Unless the chains can communicate with one another, the ecosystem will become increasingly fragmented. + +The Axelar network enables protocols to have cross-chain functionality between any two blockchains. + +Building a protocol that is interoperable between ecosystems is essential for growth. diff --git a/locales/pt/Interoperability/2_Gateway/gateway.md b/locales/pt/Interoperability/2_Gateway/gateway.md new file mode 100644 index 000000000..dc752d3eb --- /dev/null +++ b/locales/pt/Interoperability/2_Gateway/gateway.md @@ -0,0 +1,25 @@ +The Axelar Gateway is the entrypoint for your smart contract into the Axelar ecosystem. Once you have triggered the appropriate function on the Gateway, your transaction will begin its interchain journey from your source chain across the Axelar network to the destination chain. Each chain that is connected to Axelar has a deployed gateway contract for you to interact with. + +The following are the two more relevant functions you will need to be familiar with. + +## callContract() + +This function triggers an interchain transaction with a message from the source to the destination chain. It takes three relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent + +The first two parameters are quite intuitive. They consist of both the name of the chain you want this transaction to go to and the address on that chain you want to end execute at. The final parameter is the payload. This payload represents a general message that is sent to the destination chain. The message can be used in many different ways on the destination chain. For example, you can send data to be used as a parameter in another function on the destination chain, you can send a function signature as a message that will then get executed on a destination chain, and much more. + +## callContractWithToken() + +This function triggers an interchain with a message and a fungible token from the source to the destination chain. It takes five relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent +4. `symbol`: The symbol of the token being sent +5. `amount`: The amount of that token that is being sent + +The first three parameters here are the same as in `callContract()`. The final two parameters are relevant to the token that is being sent along with the message. These are the symbol of the token and the amount of the token that is being sent. diff --git a/locales/pt/Interoperability/3_GasService/GasService.md b/locales/pt/Interoperability/3_GasService/GasService.md new file mode 100644 index 000000000..4ed0afbbf --- /dev/null +++ b/locales/pt/Interoperability/3_GasService/GasService.md @@ -0,0 +1,29 @@ +The Axelar Gas Service is an extremely useful tool made available to pay gas for an interchain transaction. It allows you to pay for the cost of a transaction in the token of the source chain, making for a much easier end user (and developer) experience. If for example the source chain is Ethereum and the destination chain is Polygon then the gas service will receive the complete payment for the transaction in ETH and no matic is needed from the caller to pay for the execution on the Polygon destination chain. + +The following are the two more relevant functions you will need to be familiar with in regards to the Gas Service. + +## payNativeGasForContractCall() + +This function allows you to pay for the entirety of an interchain transaction in the native token of the source chain. It takes five relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +The parameters overlap with the parameters required by the `callContract()` function in the Gateway contract. The two parameters not discussed in the Gateway section are `sender` and `refundAddress`. The sender is the address paying for the transaction and the refund address is the address that will receive any surplus funds sent to the gas service. + +## payNativeGasForContractCallWithToken() + +This function allows you to pay for the entirety of an interchain transaction (that includes a token transfer) in the native token of the source chain. It takes seven relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `symbol`: The symbol of the token that was sent +6. `amount`: The amount of the token that was sent +7. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +This function is nearly identical to the first top one the main difference being that it is used for message + token transfer transactions as opposed to just interchain message transactions (aka GMP Transactions). As a result the GasService needs to also know the `symbol` and `amount` of the token that is being sent. diff --git a/locales/pt/Interoperability/4_Executable/executable.md b/locales/pt/Interoperability/4_Executable/executable.md new file mode 100644 index 000000000..1f72c6be4 --- /dev/null +++ b/locales/pt/Interoperability/4_Executable/executable.md @@ -0,0 +1,27 @@ +The Axelar executable contains relevant helper functions that will be automatically executed on the destination chain in correspondence to the relevant inbound transaction from the source chain. + +The following are the relevant functions you will need to use from Axelar Executable + +## \_execute() + +This function handles the execution on the destination chain. It takes the following four parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent + +The `sourceChain` and `sourceAddress` are key parameters which you receive out of the box that can be used for verifying authenticity of messages on the destination chain. The payload (as discussed in the gateway section) is the message that was sent from the source chain to be used on your destination chain. The `commandId` will not be used during the rest of this module. + +## \_executeWithToken() + +This function handles the execution on the destination chain for a message being sent with a fungible token. It takes six relevant parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent +5. `tokenSymbol`: The symbol of the token being sent +6. `amount`: The amount of that token that is being sent + +The first four parameters are identical to that of the `_execute()` function. The final two parameters of `tokenSymbol` and `amount` are in reference to the token that is being sent along with the message. It allows you on the destination chain to interact with the token accordingly, for example transferring it to another receiving address. The `commandId` will not be used during the rest of this module. diff --git a/locales/pt/Interoperability/5_InterchainMessage/interchainMessage.md b/locales/pt/Interoperability/5_InterchainMessage/interchainMessage.md new file mode 100644 index 000000000..029f642ce --- /dev/null +++ b/locales/pt/Interoperability/5_InterchainMessage/interchainMessage.md @@ -0,0 +1,53 @@ +In this section we will create a contract that will send a "hello world" message between two blockchains. + +## Constructor + +The first thing you will need to create is the `constructor` for the function. This will allow you to set the `Gateway` and `Gas Service` contracts we discussed in the previous sections. + +When deploying the contract you will pass in the address of the `Gateway` and `GasService` for Ethereum Sepolia those addresses are `0xe432150cce91c13a887f7D836923d5597adD8E31` for the Gateway and `0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6` for the Gas Service. + +For the full list of relevant Axelar addresses see here + +## Send Interchain Message + +Now that the constructor has set the relevant Axelar addresses needed to trigger an interchain transaction you can move on to the `setRemoteValue()`, which will trigger this transaction. + +This function takes three parameters: + +1. `_destinationChain`: The chain which the transaction is going to +2. `_destinationAddress`: The address on the destination chain the transaction will execute at +3. `_message`: The message being passed to the destination chain + +First, you have a `require` statement which ensures that the `msg.value` contains a value. This `msg.value` will be used to pay the `GasService`. If no funds were sent, then the transaction should be reverted as the transaction cannot execute on the Axelar blockchain and destination chain without any gas. + +Next, you encode the `_message` that was passed in. Notice that the `_message` is set as a `string` type. Axelar expects this message to be submitted as a `bytes` type so to convert the `string` to `bytes` you simply pass it through `abi.encode()`. + +Now, with your message encoded you can begin to interact with the `GasService` and the `Gateway` + +To pay for the entire interchain transaction you will trigger the function `payNativeGasForContractCall`, which is defined in the `GasService`. + +This function needs the parameters explained earlier in the GasService section. The `sender` for this transaction will be this contract, which is `address(this)`. The `destinationChain` and `destinationAddress` can simply be passed in from this functions parameters, the `payload` is the encoded \_message we wrote earlier. Finally, you need to specify what the refund address is, this can be the address that triggers this function, which you get by writing `msg.sender`. + +Once you trigger this function you will have successfully sent a transaction from the source chain via Axelar to the destination chain! But there is still one final step that needs to be complete. + +### Receive Message on Destination Chain + +On the destination chain the inbound interchain transaction needs to be picked up and handled by the `AxelarExecutable`'s `_execute()` function. + +The `_execute()` function is defined in the `AxelarExecutable` contract so when defining this function you must remember to include the `override` keyword. + +This function takes three parameters. + +1. `_sourceChain`: The blockchain which the transaction has originated from +2. `_sourceAddress`: The address on the source chain which the transaction has been sent from +3. `_payload`: The message that has been sent from the source chain + +The first thing that needs to be done in this contract is to get access to your `message` that was sent. Recall, before sending the message it was sent through `abi.encode()` to convert the message from type `string` to type `bytes`. To convert your message back from type `bytes` to type `string` simply pass the `_payload` to the function `abi.decode()` and specify that you want the `_payload` decoded to type `string`. This will return the message as a string. + +Now that you have your message as a type string you can set the `sourceChain` and `sourceAddress` storage variables as `_sourceChain` and `_sourceAddress` to have an easy reference to the data that was passed in. You can also emit the `Executed` event with the `sourceAddress` and `message` event that you just decoded. + +Great! At this point you are now handling the interchain transaction on the destination chain. + +To interact with this contract make sure you deploy it on at least two blockchains so that you can call `setRemoteValue()` from the one chain and then have the `_execute()` function automatically triggered on another chain. You will be able to query the `sourceChain` and `sourceAddress` variables on the destination chain to ensure that the interchain execution worked correctly. + +To view the full step by step of the interchain transaction checkout the Axelarscan (testnet) block explorer. diff --git a/locales/pt/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md b/locales/pt/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md new file mode 100644 index 000000000..11915eb32 --- /dev/null +++ b/locales/pt/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md @@ -0,0 +1,39 @@ +At this point we have gone over an example of how to send a general message between one blockchain to another. Now, let's implement a contract that sends a message and a token from one blockchain to another. + +## Overview + +This contract should seem largely familiar. Much like the previous section the `constructor` receives the `Gateway` and `Gas Service` addresses. + +It then has a function that will be called from the source chain called `sendToMany` that takes in parameters similar to the previous section. + +1. `_destinationChain`: The chain the transaction is sending to +2. `_destinationAddress`: The address on the destination chain your transaction is sending to +3. `_destinationAddresses`: The message that you will be sending along with your token transfer. In this example the message is a list of receiving addresses for the token transfer. +4. `_symbol`: The symbol of the token address being sent +5. `_amount`: The amount of the token being sent + +In the function we already have the `require` statement implemented to ensure gas is sent + +We also have the basic ERC20 functionality to send the token from the calling wallet to this smart contract. The contract also calls the `approve` function to allow the Gateway to eventually transfer funds on its behalf. + +Finally, the `_executeWithToken()` function is also implemented out of the box. + +It makes use of the following params: + +1. `_payload`: The incoming message from the source chain +2. `_tokenSymbol`: The symbol of the token that was sent from the source chain +3. `_amount`: The amount of the token that was sent from the source chain + +Now with these params that were passed in, the `_execute()` function can send the tokens that were sent to the appropriate receivers. + +## Challenge + +Your challenge here is to finish off the `sendToMany()` function using the Axelar Gateway and Gas Service to trigger an interchain transaction. + +In the end you should be able to deploy this contract on two testnets, trigger the `sendToMany()` function and see the live transaction on Axelarscan (testnet) block explorer. + +### Testing Notes + +Note 1: The recommended ERC20 to use is `aUSDC` a wrapped version of the USDC token that can be obtained from the discord faucet bot. When triggering the `sendToMany()` function simply pass in the symbol `aUSDC` to the fourth param. + +Note2: When triggering the `sendToMany()` function you must remember to `approve` your contract to spend `aUSDC` tokens on your behalf, otherwise `transferFrom()` on line49 will throw an error. diff --git a/locales/pt/Interoperability/7_FurtherReading/furtherReading.md b/locales/pt/Interoperability/7_FurtherReading/furtherReading.md new file mode 100644 index 000000000..a601d7ac7 --- /dev/null +++ b/locales/pt/Interoperability/7_FurtherReading/furtherReading.md @@ -0,0 +1,11 @@ +Congratulations on making it to the end of the interoperability module! 🎉🎉 + +To continue your learning journey of interoperability with Axelar. There are many useful resources available. + +- For documentation 📚 + +- For more technical examples 💻 + +- For live coding demos 📹 + +- For the developer blog 📝 diff --git a/locales/pt/Interoperability/README.md b/locales/pt/Interoperability/README.md new file mode 100644 index 000000000..a43fc5dd5 --- /dev/null +++ b/locales/pt/Interoperability/README.md @@ -0,0 +1,3 @@ +## Interoperability Between Blockchains + +Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. diff --git a/locales/pt/Interoperability/config.yml b/locales/pt/Interoperability/config.yml new file mode 100644 index 000000000..39f1be7ed --- /dev/null +++ b/locales/pt/Interoperability/config.yml @@ -0,0 +1,31 @@ +--- +id: interopCourse +name: Multichain Protocols with Axelar +summary: Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. +level: 2 +tags: + - Solidity + - Interoperability + - Axelar +steps: + - + name: An Intro to Axelar + path: 1_Intro + - + name: Axelar Gateway + path: 2_Gateway + - + name: Axelar Gas Service + path: 3_GasService + - + name: Axelar Executable + path: 4_Executable + - + name: Interchain Messages + path: 5_InterchainMessage + - + name: Interchain Token Transfers + path: 6_InterchainTokenTransfer + - + name: Further Reading + path: 7_FurtherReading diff --git a/locales/pt/Multisig-Tutorial/1-multisig-introduction/introduction.md b/locales/pt/Multisig-Tutorial/1-multisig-introduction/introduction.md new file mode 100644 index 000000000..3e9f18938 --- /dev/null +++ b/locales/pt/Multisig-Tutorial/1-multisig-introduction/introduction.md @@ -0,0 +1,41 @@ +Welcome to the Multisignature Wallet course! In this section, we'll explore the fundamentals of Multisignature (Multisig) wallets and we'll go through a multisig wallet contract. + +## What is a Multisignature Wallet? + +A multisignature (multisig) wallet is a type of digital wallet that requires multiple keys to authorize a cryptocurrency transaction. + +Imagine a multisig wallet as a secure vault with multiple locks. To open the vault, each keyholder must open their individual lock. This setup ensures that no single person can access the vault's contents without the others' consent. + +## How Does a Multisig Wallet Work? + +In a multisig setup, each transaction must receive a predetermined number of approvals from a set group of individuals. For instance, in a 3-of-5 wallet configuration, there are five authorized addresses, but a transaction only goes through when at least three of them give their approval. When a transaction is initiated, it's presented as a **proposal** to the group. Each member who agrees to the transaction uses their private key to digitally sign it. + +These **digital signatures** are unique and are generated based on the combination of the transaction data and the private key. + +When the required number of signatures is reached, the transaction is broadcasted to the blockchain for execution. + +## Why Use a Multisig Wallet? + +Multisig wallets are crucial for enhanced security in cryptocurrency transactions. They mitigate the risk of theft or loss of a single key. In business, they're used to ensure that funds can't be moved without consensus among stakeholders. For instance, in a company managing cryptocurrency assets, a multisig wallet might require the CFO, CEO, and a board member to all approve significant transactions, protecting against internal fraud or external hacks. + +## Conclusion + +In this section, we learned that a multisig wallet requires multiple keys to authorize a proposed cryptocurrency transaction and that a multisigs mitigates the risk of theft or loss of a single key. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is a Multisignature Wallet? + +1. A digital wallet that requires a single signature for transactions. +2. A digital wallet that requires multiple signatures for transactions. +3. A physical wallet used for storing cryptocurrency. +4. A wallet that can only hold multiple types of cryptocurrencies. + +### 2) How does a Multisignature Wallet enhance security? + +1. By requiring a single private key for transactions. +2. By distributing transaction approval across multiple owners. +3. By storing transaction data on-chain. +4. None of the above. + +Feel free to take your time and answer the questions above. Once you're ready, we'll move on to exploring the Multisig smart contract and understanding its structure. diff --git a/locales/pt/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md b/locales/pt/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md new file mode 100644 index 000000000..17b0a924f --- /dev/null +++ b/locales/pt/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md @@ -0,0 +1,60 @@ +In this section, we'll explore the **initialization process** of the Multisig smart contract. We'll examine the constructor function and review how it sets up the initial state of the contract. + +## Note + +From this section on in this tutorial, we will be building up a multisig contract. In subsequent sections, the contract will become increasingly complete. + +## Overview + +In this section, the contract consists of events, state variables, modifiers, and functions. **Events** provide transparency by logging specified activities on the blockchain, while **modifiers** ensure that only authorized users can execute certain functions. + +## State Variables + +In Line 4, we have the MultisigWallet contract itself. At the beginning of the contract, we have three state variables. + +1. **`owners`:** An array containing the addresses of all owners of the multi-signature wallet (Line 5). +2. **`isOwner`:** A mapping indicating whether an address is an owner (Line 6). +3. **`numConfirmationsRequired`:** The number of confirmations required for a transaction (Line 7). + +The setup of array and mapping allows us to easily retrieve the list of owners and verify whether an address is an owner. + +## Modifiers + +Next, we have a modifier called `onlyOwner` (Line 9). Modifiers in Solidity are special keywords that can be used to amend the behavior of functions. In our case, the `onlyOwner` modifier ensures that only owners can execute a function. It does this by checking whether the address of the **caller** is an owner. + +## Constructor Function + +The `constructor` function (Line 14) is executed only once during the deployment of the contract. It initializes essential parameters, in this case, the list of owners and the required number of confirmations (Line 14). + +On lines 15 and 16, we have two `require` statements to ensure that the inputs are valid. In this case, we require that there must be at least one owner and that the number of required confirmations must be greater than zero and less than or equal to the number of owners. + +The constructor then initializes the contract state by verifying that is not address(0) (Line 25) and that the owner is unique (Line 26). Then it adds a key/ value pair to the isOwner mapping (Line 28), and then it populates the `owners` array with the provided owner addresses (Line 29). + +Finally, it sets the `numConfirmationsRequired` variable with the specified value (Line 32). + +## getOwners Function + +The `getOwners` function (Line 36) allows users to retrieve the list of owners of the multi-signature wallet. It returns the `owners` array (Line 37). + +## getNumConfirmationsRequired Function + +The `getNumConfirmationsRequired` function (Line 41) allows users to retrieve the number of confirmations required for a transaction. It returns the `numConfirmationsRequired` variable (Line 42). + +## Conclusion + +In this section, we explored the initialization process of the Multisig smart contract. We examined the constructor function and understood how it sets up the initial state of the contract. + +## ⭐️ Assignment: Deploy a Multisig Wallet + +Deploy a Multisig contract with three owners and require two confirmations for transaction execution. + +1. Compile contractInitialization.sol +2. Go to Deploy & Run Transactions in Remix. +3. Expand the "Deploy" section. +4. Under "_OWNERS", enter three an array of three addresses. +5. Under "_NUM_CONFIRMATIONS_REQUIRED", enter the number of confirmations required for a transaction. + +**Hints:** + +- You can get addresses from the "ACCOUNTS" dropdown menu. +- The array of addresses should be in the format: ["0x123...", "0x456...", "0x789..."]. diff --git a/locales/pt/Multisig-Tutorial/3-multisig-deposits/deposits.md b/locales/pt/Multisig-Tutorial/3-multisig-deposits/deposits.md new file mode 100644 index 000000000..a8a14213b --- /dev/null +++ b/locales/pt/Multisig-Tutorial/3-multisig-deposits/deposits.md @@ -0,0 +1,34 @@ +In this section, we'll explore the `receive` function and the associated Deposit event. We'll examine how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## Deposit Event + +On line, 9 we have the Deposit event. The Deposit event is emitted whenever Ether is deposited into the multi-signature wallet. It includes three parameters: + +1. `sender`: The address that sent the Ether. +2. `amount`: The amount of Ether deposited. +3. `balance`: The updated balance of the contract after the deposit. + +We can use the Deposit event to track the flow of Ether into the multi-signature wallet and maybe trigger other actions based on the event. + +## receive Function + +On line 43, we have the `receive` function. The `receive` function is a special function that is executed whenever Ether is sent to the contract. + +The `receive` function is marked as `external` and `payable`. The `external` modifier means that the function can only be called from outside the contract. The `payable` modifier means that the function can receive Ether. + +The `receive` function emits the Deposit event (Line 44) with the address of the sender, the amount of Ether sent, and the updated balance of the contract. It doesn't return anything. + +To receive Ether, a contract must have a `receive`, `fallback`, or a function with the `payable` modifier. If none of these are present, the contract will reject any Ether sent to it. + +## Conclusion + +In this section, we explored the `receive` function and the associated Deposit event. We examined how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## ⭐️ Assignment: Deposit Ether + +Deposit 2 Ether into the Multisig contract. + +1. Deploy the Multisig contract as in the previous assignment. +2. Enter a Value of 2 Ether in the Value field and select Ether in the dropdown menu. +3. At the bottom of your deployed contract in the "Low level interactions" section, click on the "Transact" button. +4. On top of your deployed contract, it should now say "Balance: 2 Ether". diff --git a/locales/pt/Multisig-Tutorial/4-multisig-transactions/transactions.md b/locales/pt/Multisig-Tutorial/4-multisig-transactions/transactions.md new file mode 100644 index 000000000..f62fd48a0 --- /dev/null +++ b/locales/pt/Multisig-Tutorial/4-multisig-transactions/transactions.md @@ -0,0 +1,73 @@ +In this section, we'll explore the process of submitting and confirming transactions. + +## Modifiers + +We have new modifiers in this iteration of the contract. Let's examine them one by one. + +1. **`txExists` modifier:** (Line 13) ensures that the transaction exists. It does this by checking whether the transaction index is less than the length of the `transactions` array. We'll go into more about in this modifier later in this section. +2. **`notExecuted` modifier:** (Line 18) ensures that the transaction has not been executed. It does this by checking whether the `executed` variable of the transaction is false. +3. **`notConfirmed` modifier:** (Line 23) ensures that the transaction has not been confirmed by the caller. It does this by checking whether the `isConfirmed` mapping of the transaction index and the caller's address is false. + +## Transaction Struct + +On line 28, we have a struct called `Transaction`. We store the struct members: `to`, `value`, `data`, `executed`, and `numConfirmations` in individual variables. + +## Mapping of Confirmations + +On line 37, we have a mapping called `isConfirmed`. This mapping is used to keep track of the confirmations of each transaction. It maps the transaction's index to a mapping of an owner addresse to a boolean value. The boolean value indicates whether this owner has confirmed the transaction. + +## Transactions Array + +On line 39, we have an array called `transactions`. The array is used to store all the transactions submitted to the multi-signature wallet. + +## Events + +We have four new events in this iteration of the contract: + +1. **`SubmitTransaction` event:** emitted whenever a transaction is submitted to the multi-signature wallet. +2. **`ConfirmTransaction` event:** emitted whenever a transaction is confirmed by an owner. +3. **`RevokeConfirmation` event:** emitted whenever a transaction confirmation is revoked by an owner. +4. **`ExecuteTransaction` event:** emitted whenever a transaction is executed. + +## submitTransaction Function + +The `submitTransaction` function (Line 78) allows users to submit a transaction to the multi-sig wallet. It takes three parameters: `to`, `value`, and `data`. The `to` parameter is the address of the recipient of the transaction. The `value` parameter is the amount of Ether to be sent. The `data` parameter is the data to be sent to the recipient. Only owners can submit transactions. + +On line, 85 we create a new transaction struct and push it to the `transactions` array and emit the `SubmitTransaction` event. The `txIndex` variable is used to keep track of the transaction index. + +## confirmTransaction Function + +The `confirmTransaction` function (Line 98) allows users to confirm a transaction. It takes one parameter: `txIndex`. +It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. The `onlyOwner` modifier ensures that only owners can confirm transactions. The `txExists` modifier ensures that the transaction exists. The `notExecuted` modifier ensures that the transaction has not been executed. + +On line 101, we store the transaction in a local variable called `transaction`. We then increment the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to true. Finally, we emit the `ConfirmTransaction` event. + +## executeTransaction Function + +The `executeTransaction` function (Line 108) allows users to execute a transaction. On line 113, we require that the number of confirmations of the transaction is greater than or equal to the required number of confirmations. We then set the `executed` variable of the transaction to true. Finally, send the funds using the `call` function. This is the `call` of the recipient address with the value and data of the transaction. If the transaction is successful, we emit the `ExecuteTransaction` event. + +## getTransactionCount Function + +The `getTransactionCount` function (Line 132) allows users to retrieve the number of transactions in the multi-signature wallet. It returns the length of the `transactions` array. + +## getTransaction Function + +The `getTransaction` function (Line 136) allows users to retrieve a transaction. It returns the transaction struct members that we explored earlier in this section. + +## Conclusion + +In this section, we explored the process of submitting, confirming, and executing transactions. We examined the `submitTransaction`, `confirmTransaction`, and `executeTransaction` functions and understood how they work together to allow multiple users to submit and confirm transactions. + +## ⭐️ Assignment: Make a Transaction + +Submit, confirm, and execute a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. Deploy the Multisig contract as in the previous assignment. Make sure that the required number of confirmations is 2. +2. Fund the multisig from any address by sending 4 Ether as you did in the previous assignment. +3. Try sending 2 Ether to the first account in the "ACCOUNTS" dropdown menu. Once you have submitted this transaction (with submitTransaction), click on `getTransactionCount` and should see one transaction or you can click on `getTransaction`, insert 0 as the transaction index and see the transaction you just submitted. +4. Now you can click on `confirmTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. +5. Switch to the second owner account and confirm the transaction again. If you click on `getTransaction` again, you should see that the transaction has been confirmed twice. +6. The last step is to execute the transaction. Click on `executeTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been executed. You can also check the balance of the first account in the "ACCOUNTS" dropdown menu. It should now be 2 Ether higher and the balance of the multi-signature wallet should be 2 Ether lower. + +**Hint:** +If you submit a transaction make sure that the value is in Wei and that the _data field is correctly filled in. E.g. it could look like this: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 2000000000000000000, 0x" for 2 Ether. diff --git a/locales/pt/Multisig-Tutorial/5-multisig-revoke/revoke.md b/locales/pt/Multisig-Tutorial/5-multisig-revoke/revoke.md new file mode 100644 index 000000000..1bf085343 --- /dev/null +++ b/locales/pt/Multisig-Tutorial/5-multisig-revoke/revoke.md @@ -0,0 +1,30 @@ +In this section, we'll explore the process of revoking confirmations. This process is necessary when an owner changes their mind about a transaction and wants to stop it from being executed. This section will be pretty straightforward. + +## revokeConfirmation Event + +On line 14, we have added the `RevokeConfirmation` event. This event is emitted whenever a transaction confirmation is revoked by an owner. + +## revokeConfirmation Function + +On line 129, we have added the `revokeConfirmation` function. It allows users to revoke a transaction confirmation. + +`revokeConfirmation` takes one parameter: `txIndex`. It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. + +On line 134, we require that the transaction has been confirmed by the caller. This ensures that an owner who has confirmed the transaction can only revoke their own confirmation. +We then decrement the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to false. Finally, we emit the `RevokeConfirmation` event. + +## Conclusion + +In this section, we explored the process of revoking confirmations. We examined the `revokeConfirmation` function and understood how it works to allow users to revoke confirmations. + +## ⭐️ Assignment: Revoke a Confirmation + +Confirm and revoke a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. As in the previous assignment, deploy the Multisig contract, send the contract some Ether, and then submit a transaction to the first account in the "ACCOUNTS" dropdown menu with a value of 2 Ether. +2. Confirm the transaction twice as in the previous assignment. +3. Revoke the transaction by clicking on `revokeConfirmation` and inserting 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. + +## Final Conclusion + +In this tutorial, we explored the process of creating a multi-signature wallet. We learned how to initialize the contract, deposit Ether, submit, confirm, and revoke transactions. We also learned how to execute transactions and retrieve information about the multi-signature wallet. diff --git a/locales/pt/Multisig-Tutorial/README.md b/locales/pt/Multisig-Tutorial/README.md new file mode 100644 index 000000000..ae5997802 --- /dev/null +++ b/locales/pt/Multisig-Tutorial/README.md @@ -0,0 +1,5 @@ +## MultiSig Wallet + +Learn how to write a MultiSig Wallet smart contract on Ethereum. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/pt/Multisig-Tutorial/config.yml b/locales/pt/Multisig-Tutorial/config.yml new file mode 100644 index 000000000..067de0fb9 --- /dev/null +++ b/locales/pt/Multisig-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: multisigCourse +name: Multisig Wallet +summary: Learn how to create and interact with a multisig wallet. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - Multisig +steps: + - + name: 1. Introduction + path: 1-multisig-introduction + - + name: 2. Initialize the Contract + path: 2-multisig-initialization + - + name: 3. Deposits + path: 3-multisig-deposits + - + name: 4. Transactions + path: 4-multisig-transactions + - + name: 5. Revoking Confirmations + path: 5-multisig-revoke diff --git a/locales/pt/NFTTokenCourse/README.md b/locales/pt/NFTTokenCourse/README.md new file mode 100644 index 000000000..c3d2a183a --- /dev/null +++ b/locales/pt/NFTTokenCourse/README.md @@ -0,0 +1,5 @@ +## Solidity NFT Course + +Learn how to create your own NFTs (non-fungible tokens). + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/pt/NFTTokenCourse/config.yml b/locales/pt/NFTTokenCourse/config.yml new file mode 100644 index 000000000..af82db834 --- /dev/null +++ b/locales/pt/NFTTokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: nftTokenCourse +name: Solidity NFT Course +summary: Learn how to create your own NFT tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc721-interface + - + name: 3. Metadata Interface + path: erc721-interface-metadata + - + name: 4. Token Creation + path: erc721-token-creation + - + name: 5. Metadata IPFS + path: erc721-metadata-ipfs + - + name: 6. Deploy to Testnet + path: erc721-deploy-testnet-opensea diff --git a/locales/pt/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md b/locales/pt/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md new file mode 100644 index 000000000..40576500c --- /dev/null +++ b/locales/pt/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md @@ -0,0 +1,50 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to the Rinkeby testnet of the Ethereum blockchain, mint an NFT, and look at it on the NFT marketplace OpenSea. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token for Rinkeby + +In order to make transactions on the testnet, we need Ethereum testnet tokens. + +**2.1** Switch your Metamask from "Ethereum Mainnetwork" to "Rinkeby Test Network". + +**2.2** Go to https://faucet.paradigm.xyz/, enter the address of your account and claim testnet ETH. +You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Contract Deployment + +**3.1** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It should then ask you to connect your account, which you should confirm. Then you should see the Rinkeby network badge under "Injected Web3". + +**3.2** Deploy your token contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. + +### 4. Mint an NFT + +**4.1** Expand your contract in the IDE so you can see the buttons for the functions. + +**4.2** Expand the input fields next to the safeMint button. Enter the Ethereum address of the account that is connected to Remix in the “to:” input field. Enter “0” in the input field "tokenID:". Click on transact. + +**4.3** In Metamask click on assets, then click on the “Import tokens” link, and paste the address of your contract in the input field. You can set decimals to 0. + +You should now see the name of the symbol of your token contract (e.g. GEO) in your “Assets” view in Metamask. You should have one of these tokens. + +### 5. See your NFT on OpenSea + +OpenSea is one of the most popular online marketplace for NFTs. OpenSea also provides a version where you can see assets on the testnet, under https://testnets.opensea.io/ + +**5.1** Go to https://testnets.opensea.io/login. + +**5.2** Connect with your Metamask wallet. You should be redirected to your account https://testnets.opensea.io/account view on OpenSea, where you should be able to see your NFT. You should see the image of your NFT; when you click on it, you should see the name, description, and under properties, also the attributes that you created. + +If you successfully completed this course and are familiar with the basics of Solidity development, we encourage you to continue your learning journey by learning how to create your own NFT auction contract from the Learneth resources. diff --git a/locales/pt/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md b/locales/pt/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md new file mode 100644 index 000000000..a43162feb --- /dev/null +++ b/locales/pt/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md @@ -0,0 +1,44 @@ +The metadata extension is optional. It allows us to add additional information to our ERC721 tokens. We can specify a name, a symbol, and an URI (Uniform Resource Identifier) that can point to a file where we can add even more information in the form of a JSON. + +## ERC721 Metadata Functions + +### name + +The function `name` (line 16) returns the name of the token collection. A token collection means all tokens created with your ERC721 token contract implementation. Every token in this collection will have this name, regardless of their tokenId. + +### symbol + +The function `symbol` (line 21) returns the symbol of the token collection. + +### tokenURI + +The function `tokenURI` (line 26) returns the URI for the token with the id `tokenId`. In this case it’s not the URI of the whole collection but of an individual token in the collection. + +## ERC721 Metadata JSON Schema + +The file that the tokenURI points to should conform to the Metadata JSON Schema as it is specified in the EIP-721. + +``` +{ + "title": "Asset Metadata", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Identifies the asset to which this NFT represents" + }, + "description": { + "type": "string", + "description": "Describes the asset to which this NFT represents" + }, + "image": { + "type": "string", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." + } + } +} +``` + +The root element must be of the type object. This root object should have properties with the keys: name, description, and image that should be all of the type string. + +The ERC721 standard is pretty flexible, the tokenURI does not need to point to a JSON document and the JSON does not need to have all properties and often has additional properties. diff --git a/locales/pt/NFTTokenCourse/erc721-interface/erc721Interface.md b/locales/pt/NFTTokenCourse/erc721-interface/erc721Interface.md new file mode 100644 index 000000000..468e8e640 --- /dev/null +++ b/locales/pt/NFTTokenCourse/erc721-interface/erc721Interface.md @@ -0,0 +1,100 @@ +ERC721 is a standard for token contracts that manage non-fungible tokens (NFTs) on the Ethereum blockchain. + +Each non-fungible token is unique and not interchangeable. NFTs can have different properties, behavior, or rights. Non-fungible tokens are used to represent ownership of unique digital and physical assets like art, collectibles, or real estate. + +If you want to know more about the ERC721 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +The ERC721 standard is more complex than the ERC20 standard and it features optional extensions. ERC721 compliant contracts must, at a minimum, implement the ERC721 and ERC165 interfaces, which we will look at in this section. + +This interface (line 11) is part of the open-source contract library provided by OpenZeppelin. + +## Basic IERC721 Functions + +Contracts compliant with the ERC721 standard have to implement the following functions: + +### balanceOf + +The function `balanceOf` (line 30) returns the amount of tokens owned by the account with the address `owner`. + +### ownerOf + +The function `ownerOf` (line 39) returns the address `owner` of the account that holds the token with the id `tokenId`. + +### safeTransferFrom + +The function `safeTransferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +The function `safeTransferFrom` (line 137) is almost identical to the function `safeTransferFrom` (line 55) .The only difference is that this function has a non-empty payload `data`. + +A smart contract must implement the ERC721TokenReceiver Interface if it is to receive a transfer. This will ensure that the contract can handle ERC721 token transfers and prevent the tokens from being locked in a contract that can’t. + +### transferFrom + +The function `transferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +**It is recommended to use safeTransferFrom instead of transferFrom whenever possible.** +The `transferFrom` function is not secure because it doesn’t check if the smart contract that is the recipient of the transfer has implemented the ERC721TokenReceiver interface and is capable of handling ERC721 tokens. + +## Advanced IERC721 Functions + +### approve + +The function `approve` (line 94) gives the account with the address `to` the permission to manage the token with the id `tokenId` on behalf of the account calling the function. + +### getApproved + +The function `getApproved` (line 103) returns the address of the account (return var `operator`) that is approved to manage the token with the id `tokenId`. + +### setApprovalForAll + +The function `setApprovalForAll` (line 115) sets the permission (`_approved`) for the account with the specified address (input param - `operator`) to manage all tokens of the account calling the function. + +### isApprovedForAll + +The function `getApproved` (line 103) returns the boolean true if the account with the address `operator` is approved to manage all tokens of the account with the address `owner`. + +## IERC721 Events + +ERC721 contracts must also emit the following events: + +### Transfer + +The `Transfer` event (line 15) must be emitted when the token with the id `tokenId` is transferred from the account with the address `from` to the account with the address `to`. + +### Approval + +The `Approval` event (line 20) must be emitted when the account with the address `owner` approves the account with the address `spender` to manage the token with the id `tokenId` on its behalf. + +### ApprovalForAll + +The `ApprovalForAll` event (line 25) must be emitted when the account with the address `owner` gives or removes the permission (`_approved`) of the account with the address `operator` to manage all its tokens. + +## IERC165 + +In addition to the ERC721 interface, ERC721 compliant contracts must also implement the ERC165 interface. + +With the implementation of the ERC165 interface, contracts can declare the support of specific interfaces. A contract that wants to interact with another contract can then query if the other contract supports this interface before making a transaction e.g. sending tokens to it that they might not support. + +Our IERC721 interface here imports (line 6) and inherits (line 11) from the IERC165 interface. + +This is how OpenZeppelins implementation of the ERC165 interface looks like: + +``` +interface IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +For example, the ERC165 identifier for the ERC721 interface as specified in the EIP721 is “0x80ac58cd”. Learn how to calculate an interface identifier and more about the ERC165 in its improvement proposal. + +## Other interfaces + +The IERC721TokenReceiver interface must be implemented to accept safe transfers. + +There are two optional extensions for ERC721 contracts specified in the EIP721: + +IERC721Enumerable enables a contract to publish its full list of tokens and make them discoverable. + +IERC721Metadata enables a contract to associate additional information to a token. We will have a more detailed look into this in the next section. diff --git a/locales/pt/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md b/locales/pt/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md new file mode 100644 index 000000000..27876b068 --- /dev/null +++ b/locales/pt/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md @@ -0,0 +1,101 @@ +In this section, we will create our metadata and store it in a decentralized way. + +IPFS ( InterPlanetary File System) is a peer-to-peer network for storing files in a distributed way. Pinata.cloud is a pinning service that allows users to easily host files on the IPFS network. + +We want to host our images and the JSON files with their metadata on IPFS. + +### Create Image Folder + +In this example, we will create metadata for three tokens. As you can see below, we create three images that we stored in a folder. + +``` +geo-img +├── geo_1.png +├── geo_2.png +├── geo_3.png +``` + +### Register on Pinata + +Now, we want to host these images somewhere so we can point to them in the metadata of our tokens. Let's do it in a decentralized way and use Pinata to host them on IPFS. + +First you need an account on Pinata. Go to Pinata.cloud and create an account. On Pinata you can upload up to 1 GB of data for free. + +Once you have signed up, you should be in the Pin Manager view. + +Pin Manager Pinata + +### Upload Images to IPFS + +Click on the upload button and upload the folder with your images. +Once you've uploaded your folder, you should see the name of your folder and the CID (content identifier) associated with it. If the content in the folder changes, the CID will also change. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P + +You can access a specific image by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png + +### Create JSON files + +We create another folder where we store three JSON files. + +``` +geo-json +├── 0 +├── 1 +├── 2 +``` + +Inside the JSON files, create the metadata for the tokens, like name, description, and image. +For the image URL, we are going to use the URL of our images on IPFS. You can add additional data if you like; in this example, we added some unique attributes for each token. + +This is how the JSON for the first token could look: + +``` +{ + "name": "Geometry#0", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png +", + "attributes": [ + { "trait_type": "background", "value": "cyan" }, + { "trait_type": "color", "value": "red" }, + { "trait_type": "shape", "value": "circle" } + ] +} +``` + +This is how the JSON for the second token could look: + +``` +{ + "name": "Geometry#1", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_2.png", + "attributes": [ + { "trait_type": "background", "value": "magenta" }, + { "trait_type": "color", "value": "green" }, + { "trait_type": "shape", "value": "square" } + ] +} +``` + +As shown above, the folder in this example is called "geo-json". Inside this folder, we have three JSON files. +The first JSON file is called "0", the second JSON file is called "1", and the third JSON file is called "2". + +Make sure that your JSON files don't have a file ending and are named like their corresponding tokenIds. +In the pin manager on pinata.cloud, click on the upload button and upload the folder with your JSON files. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. +For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp +This will become our baseURI. + +You can access a specific JSON file then by just adding a slash and the tokenId by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/0 + +In the contract, replace the baseURI with your own baseURI. In this example, the baseURI consists of the URL +"https://ipfs.io/ipfs/", the CID containing the JSON files, and a slash at the end "/". + +An individual tokenURI will now be created for each token by adding the tokenId to the baseURI — exactly what we did manually in the example above to access the JSON file. diff --git a/locales/pt/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md b/locales/pt/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md new file mode 100644 index 000000000..891fe00a7 --- /dev/null +++ b/locales/pt/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md @@ -0,0 +1,35 @@ +In this contract, we use an ERC721 token contract implementation from OpenZeppelin (line 4). + +Have a look at their implementation of a ERC721 contract. Apart from the functionality specified in the ERC721 standard, the contract provides additional functions which we will see in a bit. + +## myToken + +We create our own contract called MyToken (line 7), which inherits (line 7) the functionality from the OpenZepplin `ERC721` token contract implementation and `Ownable` that we imported (line 4). If you don't remember the Ownable contract module, have a look at the ERC20 extensions section. + +This ERC721 implementation makes use of the IERC721Metadata extension that is specified in the EIP. Our contract inherits the functions `name()` and `symbol()` +and has a constructor that allows their values to be set during the deployment of the contract (line 8). +In this case, we are going to use the default values. We name our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +### Base URI + +With an ERC721 contract, we are able to mint various tokens, each with its own tokenId. As we saw in the IERC721Metadata interface, each token can have its own `tokenURI`, which typically points to a JSON file to store metadata like name, description, and image link. +If a contract mints multiple tokens, ERC721 implementations often use the same URI as a base (`baseURI`) for all tokens and only differentiate them by adding their unique `tokenId` at the end via concatenation. In the next part, we will see what this looks like in practice. + +In this example, we are storing our data on IPFS — more on that in the next section. Our baseURI is https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/ (line 11). +Through concatenation the tokenURI for the token with the id 0 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/0 , the tokenURI for the token with the id 1 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/1, and so on. + +When using IPFS and you run into "504 Gateway Time-out" errors, you might have to wait and retry until the data is available. + +### safeMint + +With the safeMint function (line 14) we enable the owner to create new tokens with a dedicated token id after contract deployment. +The safeMint function is part of the ERC721 implementation of OpenZeppelin and lets us safely mint a token with the id `tokenId` to the account with the address `to`. For access control, we use the `onlyOwner` modifier from the Ownable access control contract module that we imported (line 5). + +In the next section, we will see how we can create and host the metadata for our NFTs. + +## ⭐️ Assignment + +1. Rename your contract to `Geometry`. +2. Rename your token to `Geometry`. +3. Change the symbol of your token to `GEO`. +4. Change the `_baseURI` to https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/. diff --git a/locales/pt/NFTTokenCourse/introduction/introduction.md b/locales/pt/NFTTokenCourse/introduction/introduction.md new file mode 100644 index 000000000..13beea567 --- /dev/null +++ b/locales/pt/NFTTokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with NFTs, tokens created with the ERC721 token standard. + +If you want to learn more about fungible tokens and the ERC20 token standard, have a look at the Learneth ERC20 Token Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain-based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/pt/OpcodesInTheDebugger/1_intro/step.md b/locales/pt/OpcodesInTheDebugger/1_intro/step.md new file mode 100644 index 000000000..c1d9a2448 --- /dev/null +++ b/locales/pt/OpcodesInTheDebugger/1_intro/step.md @@ -0,0 +1,5 @@ +This workshop aims to give a better understanding about how a contract get deployed. +`SimpleStore` is a very basic contract. +It has a very simple constructor - which just uses the first parameter `_o` and saves it to `s`. + +Using the debugger, we'll try to see, what the opcode `CODECOPY` does. diff --git a/locales/pt/OpcodesInTheDebugger/2_memory/step.md b/locales/pt/OpcodesInTheDebugger/2_memory/step.md new file mode 100644 index 000000000..577169a5e --- /dev/null +++ b/locales/pt/OpcodesInTheDebugger/2_memory/step.md @@ -0,0 +1,8 @@ +Before we start, just quick reminder: + +The runtime of the EVM has several kinds of memory: + +- `calldata`: This is the input value given to the transaction. +- `stack`: Basically, this is a list of values, each value is limited in size (32 bytes). +- `memory`: Memory is used when the **type** of value getting stored is more complex like an array or a mapping. This memory is **temporary** and is **released** at the end of the execution. +- `storage`: This is a mapping, each value stored is **persisted** and saved on chain. diff --git a/locales/pt/OpcodesInTheDebugger/3_codecopy/step.md b/locales/pt/OpcodesInTheDebugger/3_codecopy/step.md new file mode 100644 index 000000000..b0c9f7d52 --- /dev/null +++ b/locales/pt/OpcodesInTheDebugger/3_codecopy/step.md @@ -0,0 +1,7 @@ +CODECOPY is one of the many opcodes run by the EVM. Check out the complete list of opcodes at https://ethervm.io/ . + +CODECOPY takes the **running code** (or part of it) and to copies it from the `calldata` to the `memory`. + +The solidity implementation is: **codecopy(t, f, s)** - copy **s** bytes from code at position **f** to memory at position **t**. + +Every contract deployment uses **CODECOPY**. diff --git a/locales/pt/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md b/locales/pt/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md new file mode 100644 index 000000000..63950051d --- /dev/null +++ b/locales/pt/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md @@ -0,0 +1,11 @@ +Let's go back to our contract. +Please make sure the `solidity compiler` and `Deploy & Run Transactions` are activated. + +Alternatively, you can click on `Solidity` from the `Home Page` **Environments** section. + +- Compile the contract from the `solidity compiler`. +- Go to the `Deploy & Run Transactions` and make sure `SimpleStore` is selected contract. +- In the textbox to the right of `Deploy`, input a positive integer. +- Click on `Deploy`. + +In the next step, we'll watch the deployment in the debugger. diff --git a/locales/pt/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md b/locales/pt/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md new file mode 100644 index 000000000..3ef3cd146 --- /dev/null +++ b/locales/pt/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md @@ -0,0 +1,7 @@ +From the Remix terminal, identify the transaction that deployed the contract and click `Debug` + +In the gutter of the editor, put a breakpoint on the line `s = _o`, and click on `Jump to the next Breakpoint` (bottom right button). + +Click on `Step into`, to move along the opcodes until you reach `SSTORE`. + +`SSTORE` is the opcode for storing the value `_o` in the storage. Let's continue further to the `CODECOPY`. diff --git a/locales/pt/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md b/locales/pt/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md new file mode 100644 index 000000000..1480728e6 --- /dev/null +++ b/locales/pt/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md @@ -0,0 +1,57 @@ +The goal here is to store the code in the blockchain. The EVM needs to tell the client (geth, parity) which what part of the **Call Data** to store. In this step, we are saving the contract MINUS its constructor (because that gets inplmented only 1 time) and MINUS the input parameter does not need to be stored. + +`CODECOPY` is the first step: it copies the bytecode to memory, then the ethereum client will be able to consume it. MUNCH! + +But wait... before the client can **MUNCH** bytecode, it needs an instruction - an opcode to tell it to MUNCH. `RETURN` is this opcode! + +As stated in the general spec, at the end of the contract creation, the client (geth, parity) takes the targeted value by the opcode `RETURN` and **persists** it by making it part of the deployed bytecode. + +Once you are in the `CODECOPY`, look at the top 3 items in the **Stack**: + +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x0000000000000000000000000000000000000000000000000000000000000055` +`2: 0x000000000000000000000000000000000000000000000000000000000000003e` + +_In your Stack - `1` & `2` may be slightly different. The difference may be due to a different compiler version._ + +**These are the parameters for `CODECOPY`.** + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +`0` is the offset where the copied code should be placed in the **memory**. In this example, ( all zeros) the code is copied to the beginning of the memory. (**t**) +`1` is the offset in **calldata** where to copy from (**f**) +`2` number of bytes to copy - (**s**) + +After `CODECOPY` is executed, (click the _step into_ button) the copied code should be: +`0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c63430005110032` in memory. **I'll refer to this value as (X)**. + +Let's look at the debugger's **Memory** panel. +The 0x number I gave above is not what you will see in the **Memory** panel -what you will see is this: +0x0: 6080604052600080fdfea265627a7a72 ????R??????ebzzr +0x10: 31582029bb0975555a15a155e2cf28e0 1X ?? uUZ??U???? +0x20: 25c8d492f0613bfb5cbf96399f6dbd4e ?????a?????9?m?N +0x30: a6fc9164736f6c634300051100320000 ???dsolcC????2?? +0x40: 00000000000000000000000000000000 ???????????????? +0x50: 000000000000000000000000000000a0 ??????????????? +0x60: 00000000000000000000000000000000 ???????????????? +0x70: 00000000000000000000000000000000 ???????????????? +0x80: 00000000000000000000000000000000 ???????????????? +0x90: 00000000000000000000000000000002 ???????????????? + +The `0x0`, `0x10`, etc is the position. The next number is the bytecode for that position. This is followed by question marks and seemingly random letters & numbers. This is **Remix**'s attempt to convert this into a string. + +So if we glue the first four sections of bytecode together, we'll get: +**0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e0a6fc9164736f6c63430005110032** The last section - `0x90` has 2 which is what I input for the constructors parameter. + +The input data from the **Call Data** panel is: +`0x6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c634300051100320000000000000000000000000000000000000000000000000000000000000002` +**I'll refer to this value as (Y).** + +This shows us that `(X)` is a subset of the original calldata `(Y)`: + +`(X)` is calldata without the input parameter `0000000000000000000000000000000000000000000000000000000000000002` (we don't need to store this) +and without the constructor code `6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe` which should be executed only 1 time. + +So `CODECOPY` extracts the bytecode from the calldata and copies it to the memory. + +Let's move to the next step. diff --git a/locales/pt/OpcodesInTheDebugger/7_returnAndStore/step.md b/locales/pt/OpcodesInTheDebugger/7_returnAndStore/step.md new file mode 100644 index 000000000..b375a24fb --- /dev/null +++ b/locales/pt/OpcodesInTheDebugger/7_returnAndStore/step.md @@ -0,0 +1,18 @@ +# The Opcode RETURN + +At the end of the last chapter we had moved to one step after **CODECOPY** to see what happened in the memory. + +Now that CODECOPY has been executed, we are on the opcode `PUSH1 00`. + +`PUSH1 00` prepares the stack for the `RETURN` opcode. +`RETURN` is the last part of this process. It is where the code is returned to the client. + +We push `00` to the stack because this is the offset position of the contract bytecode in memory. + +Now we can call the all important `RETURN` opcode. + +The **stack inspector** shows: +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x000000000000000000000000000000000000000000000000000000000000003e` + +Which is to say it returns to the client the bytecode starting `0x00` with length `0x3e`. diff --git a/locales/pt/OpcodesInTheDebugger/8_findTheOffset/step.md b/locales/pt/OpcodesInTheDebugger/8_findTheOffset/step.md new file mode 100644 index 000000000..6b1ddc5cf --- /dev/null +++ b/locales/pt/OpcodesInTheDebugger/8_findTheOffset/step.md @@ -0,0 +1,18 @@ +# Find the offset ;) + +And now for a slightly different example: + +- Compile notSimpleStore.sol +- Deploy the contract `notSoSimpleStore` +- Make sure you have a successful deployment - if not check that you used **the correct input type** in the constructor. +- Go to the Debugger by clicking the **debug** button at the (successful) creation transaction. +- Find the value of the parameter of `CODECOPY` which represents the offset in calldata where to copy from. + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +If you look in the **Stack**, you should see that the 2nd element is: +0x0000000000000000000000000000000000000000000000000000000000000083 + +And this is the **f** of the input params of codecopy. + +### Hope you picked up a thing or 2 about how opcodes work! diff --git a/locales/pt/OpcodesInTheDebugger/config.yml b/locales/pt/OpcodesInTheDebugger/config.yml new file mode 100644 index 000000000..74a1bf3a1 --- /dev/null +++ b/locales/pt/OpcodesInTheDebugger/config.yml @@ -0,0 +1,10 @@ +--- +id: opcodesdebug +name: Opcodes in the Debugger +summary: Using the Debugger, we'll check out what the CODECOPY opcode does and how it is used by the EVM during contract creation. +level: 3 +tags: + - Remix + - Debugging + - EVM + - Opcodes diff --git a/locales/pt/ProxyContract/1_Why/step1.md b/locales/pt/ProxyContract/1_Why/step1.md new file mode 100644 index 000000000..b4a38aaeb --- /dev/null +++ b/locales/pt/ProxyContract/1_Why/step1.md @@ -0,0 +1,27 @@ +# Proxy Contract AKA the Dispatcher + +## Why? + +This is a great pattern that is used mainly in **library development**. + +It helps in the following ways: + +- **Save gas cost at deployment time** + The purpose of a high gas cost is to discourage the operations that cost a lot for their execution and to encourage optimized code. + +- Proxy contracts are useful when a lot of instances of the same contract need to be deployed because they reduce the duplications in the deployment. + +- **Avoid code repetition in the blockchain.** + Heavy computations are expensive because every node will need to perform them, this is of course slowing the network. + +- **Develop upgradable(versioned) contracts** + When the contract is deployed, it’s immutable. By re-designing the code into different contracts, it is possible to allow logic upgrades while keeping the storage the same. + +## Example of gas cost + +Storing contract code at creation time can cost up to: + +- 200 \* max_byte_code_length gas +- 200 \* 24576 = 49152004915200 \* 10 gwei = 49152000 gwei = 0.049152 ether = 9 EUR + +see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md for more info on max_byte_code_length. diff --git a/locales/pt/ProxyContract/2_How/step2.md b/locales/pt/ProxyContract/2_How/step2.md new file mode 100644 index 000000000..d80b6557c --- /dev/null +++ b/locales/pt/ProxyContract/2_How/step2.md @@ -0,0 +1,13 @@ +# How it works? + +**EIP-7 DelegateCall** opcode allows a separate execution in another contract while maintaining the original execution context. + +All **message calls** from the user go through a **Proxy contract**. + +The **Proxy contract** then will redirect them to the **Logic contract**. + +And when you need to **upgrade** the logic, you'll **just** deploy that - **HOWEVER** - the implementation of Proxy will remain the same. + +You'll only need to update the address of Logic contract in Proxy. + +The Proxy Contract uses **Delegate calls** and **Solidity assembly** because without it, it's impossible to return any value from **delegatecall**. diff --git a/locales/pt/ProxyContract/3_Delegatecall/step3.md b/locales/pt/ProxyContract/3_Delegatecall/step3.md new file mode 100644 index 000000000..8693e5567 --- /dev/null +++ b/locales/pt/ProxyContract/3_Delegatecall/step3.md @@ -0,0 +1,9 @@ +# Delegate call + +It's a special variant of a **message call**, which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract so **msg.sender** and **msg.value** do not change their values. + +This means that a contract can dynamically load code from a different address at runtime. + +The storage, the current address and balance still refer to the calling contract, only the code is taken from the called address. + +So when a **Proxy** delegates calls to the Logic contract, every storage modification will impact the storage of Logic contract. diff --git a/locales/pt/ProxyContract/4_Generic_proxy_example/step4.md b/locales/pt/ProxyContract/4_Generic_proxy_example/step4.md new file mode 100644 index 000000000..d20fdd16d --- /dev/null +++ b/locales/pt/ProxyContract/4_Generic_proxy_example/step4.md @@ -0,0 +1,15 @@ +# A Basic Generic Proxy Example + +In the associated solidity file, **step4.sol**, there are 2 contracts - **ProxyContract** and **LogicContract**. + +To use this system, we first deploy the LogicContract. + +And then when we go to deploy the ProxyContract, we pass the LogicContract's address as an argument of the ProxyContract's constructor. + +The ProxyContract is deployed only once. + +The code of LogicContract will be called at the line 20. It will be forwarded with delegate call while keeping the context of LogicContract. + +In case we need to change the logic we would deploy a new LogicContract and set the address of it with setLogicContractAddress setter function. + +_Note: The LogicContract we have here does not use the storage. Once you need to use the storage the implementation becomes a bit more complicated because those contracts share the context._ diff --git a/locales/pt/ProxyContract/5_Test/step5.md b/locales/pt/ProxyContract/5_Test/step5.md new file mode 100644 index 000000000..120a15e13 --- /dev/null +++ b/locales/pt/ProxyContract/5_Test/step5.md @@ -0,0 +1,6 @@ +# Let's test what we've learned + +- Write a contract named "LogicContract" which implements a public function named "getNumber" which returns 10 +- Write a proxy contract named "ProxyContract". This ProxyContract should take an address of LogicContract as a first parameter. + +Good Luck! diff --git a/locales/pt/ProxyContract/6_Storage_Problem/step6.md b/locales/pt/ProxyContract/6_Storage_Problem/step6.md new file mode 100644 index 000000000..d2b804284 --- /dev/null +++ b/locales/pt/ProxyContract/6_Storage_Problem/step6.md @@ -0,0 +1,13 @@ +# What if we have state variables? + +Things are more complicated once we need to deal with state variables. State variable are saved to **storage**. + +`storage`: is a mapping; each value stored there is persisted and saved on chain. + +_Note: Statically-sized state variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position 0. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible. For contracts that use inheritance, the ordering of state variables is determined by the C3-linearized order of contracts starting with the most base-ward contract_ + +Once we execute **delegate call**, the storage of both contracts get **"merged"** into a single messy state. + +We have to "tell" ProxyContract what the **state** of the **Logic contract** looks like. + +The easiest way to do this is to create a separate contract - in this example - named **StorageContract** which will represent the **state** and which proxyContract will inherit from. diff --git a/locales/pt/ProxyContract/7_links/step7.md b/locales/pt/ProxyContract/7_links/step7.md new file mode 100644 index 000000000..c2784c3cc --- /dev/null +++ b/locales/pt/ProxyContract/7_links/step7.md @@ -0,0 +1,19 @@ +# Check out some links for more info + +- ERC DelegateProxy + https://github.com/ethereum/EIPs/pull/897 + +- The joint post by Zeppelin Solutions and Aragon. + https://blog.openzeppelin.com/proxy-libraries-in-solidity-79fbe4b970fd/ + +- Proxy Patterns by OpenZeppelin + https://blog.openzeppelin.com/proxy-patterns/ + +- The most mature implementation of Proxy pattern is The Unstructure Storage pattern that is released as part of ZeppelinOS + https://blog.openzeppelin.com/upgradeability-using-unstructured-storage/ + +- Great blog post by Jack Tanner + https://blog.indorse.io/ethereum-upgradeable-smart-contract-strategies-456350d0557c + +- Upgradeable Ethereum Smart Contracts + https://medium.com/@daonomic/upgradeable-ethereum-smart-contracts-d036cb373d6 diff --git a/locales/pt/ProxyContract/README.md b/locales/pt/ProxyContract/README.md new file mode 100644 index 000000000..6a5364c94 --- /dev/null +++ b/locales/pt/ProxyContract/README.md @@ -0,0 +1,3 @@ +## Learn the Proxy Pattern + +Save gas & make upgradable contracts diff --git a/locales/pt/ProxyContract/config.yml b/locales/pt/ProxyContract/config.yml new file mode 100644 index 000000000..e36e640b8 --- /dev/null +++ b/locales/pt/ProxyContract/config.yml @@ -0,0 +1,9 @@ +--- +id: proxycontract +name: All about Proxy Contracts +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 3 +tags: + - Remix + - Solidity + - Code Patterns diff --git a/locales/pt/README.md b/locales/pt/README.md new file mode 100644 index 000000000..cb799bd20 --- /dev/null +++ b/locales/pt/README.md @@ -0,0 +1,36 @@ +# This is a repo of tutorials for the Remix's LearnEth Plugin + +### To use these tutorials: + +**1. Open Remix** + +https://remix.ethereum.org + +**2. In the plugin manager activate LEARNETH** + +**3. Go to the Learneth plugin and these tutorials will load by default** + +**4. You may need to sign into Github especially during an in-person workshop** + +Github will block too many requests from the same location, unless you are signed into Github and have input your token. Generally, this is only an issue during in person workshops, when there can be many requests from the same location. + +To input your Github token: + +``` +- In one browser window - go to https://remix.ethereum.org and go to the settings tab +- In another browser window go to: + +https://github.com/settings/tokens + +and create a new token and save it in Remix in the you just opened on the settings tab. +``` + +--- + +### Write your own tutorials for LEARNETH: + +See this site for instructions: + +https://remix-learneth-plugin.readthedocs.io/en/latest/index.html#creating-tutorials + +--- diff --git a/locales/pt/Recorder/1_Usecases/1_usecases.md b/locales/pt/Recorder/1_Usecases/1_usecases.md new file mode 100644 index 000000000..0c624393c --- /dev/null +++ b/locales/pt/Recorder/1_Usecases/1_usecases.md @@ -0,0 +1,7 @@ +1. You want to show someone what happens when you do a number of transactions with a contract and you don't want to explain each step - you just want to get them to the last step. + + - To show someone a problem in their code. + + - In a class, to get the students to a certain place and have them start working from there. + +2. You want to start your development in the JavascriptVM because it is quick and then to switch to another testnet - but you don't want to manually repeat all the tedious clicking for each different network. diff --git a/locales/pt/Recorder/2_Record/README.md b/locales/pt/Recorder/2_Record/README.md new file mode 100644 index 000000000..41d214277 --- /dev/null +++ b/locales/pt/Recorder/2_Record/README.md @@ -0,0 +1,32 @@ +# Setting up a tedious series of steps + +## Following this could get tedious but that's the point. + +We are going to: + +- Deploy a voting contract where there are 3 proposals input in the constructor. +- Give voting privileges to 2 additional address (so we have a total of 3 voting addresses). +- Have one address vote for proposal 1 (0-based index) and the other two vote for proposal 2. + +1. Take the 3_Ballot.sol from the sample solidity files and compile it. Then go to the **Deploy & Run** Module. + +2. Select the **JavaScript VM** Environment. + +3. In the constructor's parameter - put in **["0x5031000000000000000000000000000000000000000000000000000000000000", "0x5032000000000000000000000000000000000000000000000000000000000000", "0x5033000000000000000000000000000000000000000000000000000000000000"]** Then click the **Deploy** button. + +4. Open up the deployed contract. + +5. In the **vote** function put in 2. This means that you as the msg.sender & chairperson are voting for proposal at position 2, which is the last proposal in our list. + +6. Now you need to give other addresses the right to vote. Select another address in the **account** pulldown and copy it and then **go back to the 1st address**. Paste the copy address into the textbox next to the giveRightToVote function. And again, select another address and copy it and **then go back to the 1st address** again and paste it into giveRightToVote. + +7. Now you have 3 addresses with the right to vote. + +8. Switch to one of the addresses that you gave the right to vote and vote for proposal **1**. (Put **1** in the textbox next to the vote function). And then switch to the other address and vote for proposal **2** with that one. + +9. Open up the **Transactions recorded** section of the module - by clicking on the caret. Click the hard disk icon in the **Transactions recorded** section to save your steps. + ![recorder](https://github.com/ethereum/remix-workshops/blob/master/Recorder/2_Record/images/recorder.png?raw=true "recorder") + +10. You will get a modal window that tells you it wants to save a file called **scenario.json**. Click OK. + +11. Click on the function **winningProposal** to confirm that the final proposal won - which is the proposal at position 2 in the array. **0: uint256: winningProposal_ 2** diff --git a/locales/pt/Recorder/3_Editing_a_Senario/README.md b/locales/pt/Recorder/3_Editing_a_Senario/README.md new file mode 100644 index 000000000..d23dfb95c --- /dev/null +++ b/locales/pt/Recorder/3_Editing_a_Senario/README.md @@ -0,0 +1,54 @@ +# Editing a scenario + +Here's the first few lines of the scenario that I recorded. The addresses on my machine will be different from your's. + +``` +{ + "accounts": { + "account{0}": "0xca35b7d915458ef540ade6068dfe2f44e8fa733c", + "account{4}": "0xdd870fa1b7c4700f2bd7f44238821c26f7392148", + "account{3}": "0x583031d1113ad414f02576bd6afabfb302140225" + } +``` + +So if you wanted to play this scenario in another testnet, you'd need to change these addresses to address that you have test ETH on so that you could pay for the transactions. But other than swapping out the addresses, you can quickly run this on other nets. + +And you might change the parameters for the functions. + +For example here is a bit of the scenario.json a bit further down where proposal 2 was voted for by one of the addresses: + +``` +{ + "timestamp": 1566428184043, + "record": { + "value": "0", + "parameters": [ + "2" + ], + "to": "created{1566428035436}", + "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", + "name": "vote", + "inputs": "(uint8)", + "type": "function", + "from": "account{4}" + } + }, +``` + +Let's edit this so that another proposal wins in the playback. + +Change the **parameters** array which now is: + +``` +"parameters": [ + "2" + ] +``` + +to: + +``` +"parameters": [ + "1" + ] +``` diff --git a/locales/pt/Recorder/4_Play/README.md b/locales/pt/Recorder/4_Play/README.md new file mode 100644 index 000000000..196664550 --- /dev/null +++ b/locales/pt/Recorder/4_Play/README.md @@ -0,0 +1,8 @@ +# Playing a scenario + +1. Click the play icon to the right of the floppy disk icon to play the steps you did. + +2. You'll see another instance of the contract deployed. Open it up. + +3. Click the winningProposal function and you should see now that proposal 1 won. + It should print out: **0: uint256: winningProposal_ 1** diff --git a/locales/pt/Recorder/README.md b/locales/pt/Recorder/README.md new file mode 100644 index 000000000..94d928383 --- /dev/null +++ b/locales/pt/Recorder/README.md @@ -0,0 +1,3 @@ +## Get yourself Remixing! + +The recorder is used for recording a set of transactions in the Deploy & Run module, editing their parameters and then playing them back in another context. It really is the remix of Remix! diff --git a/locales/pt/Recorder/config.yml b/locales/pt/Recorder/config.yml new file mode 100644 index 000000000..b8980e042 --- /dev/null +++ b/locales/pt/Recorder/config.yml @@ -0,0 +1,7 @@ +--- +id: recorder +name: Recorder +summary: Save a set of actions and replay and replay and replay +level: 2 +tags: + - Remix diff --git a/locales/pt/SolidityBeginnerCourse/README.md b/locales/pt/SolidityBeginnerCourse/README.md new file mode 100644 index 000000000..ae0b6d882 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Course + +Learn the most important Solidity beginner concepts interactively, based on the popular https://solidity-by-example.org/ contracts. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/pt/SolidityBeginnerCourse/basic-syntax/basicSyntax.md b/locales/pt/SolidityBeginnerCourse/basic-syntax/basicSyntax.md new file mode 100644 index 000000000..e9f77871e --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/basic-syntax/basicSyntax.md @@ -0,0 +1,26 @@ +In this section, we will create our first _smart contract_. This contract only consists of a string that holds the value "Hello World!". + +In the first line, we should specify the license that we want to use. You can find a comprehensive list of licenses here: https://spdx.org/licenses/. + +Using the `pragma` keyword (line 3), we specify the Solidity version we want the compiler to use. In this case, it should be greater than or equal to `0.8.3` but less than 0.9.0. + +We define a contract with the keyword `contract` and give it a name, in this case, `HelloWorld` (line 5). + +Inside our contract, we define a _state variable_ `greet` that holds the string `"Hello World!"` (line 6). + +Solidity is a _statically typed_ language, which means that you need to specify the type of the variable when you declare it. In this case, `greet` is a `string`. + +We also define the _visibility_ of the variable, which specifies from where you can access it. In this case, it's a `public` variable that you can access from inside and outside the contract. + +Don't worry if you didn't understand some concepts like _visibility_, _data types_, or _state variables_. We will look into them in the following sections. + +To help you understand the code, we will link in all following sections to video tutorials from the creator of the Solidity by Example contracts. + +Watch a video tutorial on Basic Syntax. + +## ⭐️ Assignment + +1. Delete the HelloWorld contract and its content. +2. Create a new contract named "MyContract". +3. The contract should have a public state variable called "name" of the type string. +4. Assign the value "Alice" to your new variable. diff --git a/locales/pt/SolidityBeginnerCourse/config.yml b/locales/pt/SolidityBeginnerCourse/config.yml new file mode 100644 index 000000000..a729093d8 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/config.yml @@ -0,0 +1,65 @@ +--- +id: soliditybeginner +name: Solidity Beginner Course +summary: Solidity Beginner Course based on the popular https://solidity-by-example.org/ contracts. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Basic Syntax + path: basic-syntax + - + name: 3. Primitive Data Types + path: primitive-data-types + - + name: 4. Variables + path: variables + - + name: 5.1 Functions - Reading and Writing to a State Variable + path: functions-reading-and-writing + - + name: 5.2 Functions - View and Pure + path: functions-view-and-pure + - + name: 5.3 Functions - Modifiers and Constructors + path: functions-modifiers-and-constructors + - + name: 5.4 Functions - Inputs and Outputs + path: functions-inputs-and-outputs + - + name: 6. Visibility + path: visibility + - + name: 7.1 Control Flow - If/Else + path: control-flow-if-else + - + name: 7.2 Control Flow - Loops + path: control-flow-loops + - + name: 8.1 Data Structures - Arrays + path: data-structures-arrays + - + name: 8.2 Data Structures - Mappings + path: data-structures-mappings + - + name: 8.3 Data Structures - Structs + path: data-structures-structs + - + name: 8.4 Data Structures - Enums + path: data-structures-enums + - + name: 9. Data Locations + path: data-locations + - + name: 10.1 Transactions - Ether and Wei + path: transactions-ether-and-wei + - + name: 10.2 Transactions - Gas and Gas Price + path: transactions-gas-and-gas-price + - + name: 10.3 Transactions - Sending Ether + path: transactions-sending-ether diff --git a/locales/pt/SolidityBeginnerCourse/control-flow-if-else/ifElse.md b/locales/pt/SolidityBeginnerCourse/control-flow-if-else/ifElse.md new file mode 100644 index 000000000..634e27689 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/control-flow-if-else/ifElse.md @@ -0,0 +1,33 @@ +Solidity supports different control flow statements that determine which parts of the contract will be executed. The conditional _If/Else statement_ enables contracts to make decisions depending on whether boolean conditions are either `true` or `false`. + +Solidity differentiates between three different If/Else statements: `if`, `else`, and `else if`. + +### if + +The `if` statement is the most basic statement that allows the contract to perform an action based on a boolean expression. + +In this contract’s `foo` function (line 5) the if statement (line 6) checks if `x` is smaller than `10`. If the statement is true, the function returns `0`. + +### else + +The `else` statement enables our contract to perform an action if conditions are not met. + +In this contract, the `foo` function uses the `else` statement (line 10) to return `2` if none of the other conditions are met. + +### else if + +With the `else if` statement we can combine several conditions. + +If the first condition (line 6) of the foo function is not met, but the condition of the `else if` statement (line 8) becomes true, the function returns `1`. + +Watch a video tutorial on the If/Else statement. + +## ⭐️ Assignment + +Create a new function called `evenCheck` in the `IfElse` contract: + +- That takes in a `uint` as an argument. +- The function returns `true` if the argument is even, and `false` if the argument is odd. +- Use a ternery operator to return the result of the `evenCheck` function. + +Tip: The modulo (%) operator produces the remainder of an integer division. diff --git a/locales/pt/SolidityBeginnerCourse/control-flow-loops/loops.md b/locales/pt/SolidityBeginnerCourse/control-flow-loops/loops.md new file mode 100644 index 000000000..ffaa30650 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/control-flow-loops/loops.md @@ -0,0 +1,32 @@ +Solidity supports iterative control flow statements that allow contracts to execute code repeatedly. + +Solidity differentiates between three types of loops: `for`, `while`, and `do while` loops. + +### for + +Generally, `for` loops (line 7) are great if you know how many times you want to execute a certain block of code. In solidity, you should specify this amount to avoid transactions running out of gas and failing if the amount of iterations is too high. + +### while + +If you don’t know how many times you want to execute the code but want to break the loop based on a condition, you can use a `while` loop (line 20). +Loops are seldom used in Solidity since transactions might run out of gas and fail if there is no limit to the number of iterations that can occur. + +### do while + +The `do while` loop is a special kind of while loop where you can ensure the code is executed at least once, before checking on the condition. + +### continue + +The `continue` statement is used to skip the remaining code block and start the next iteration of the loop. In this contract, the `continue` statement (line 10) will prevent the second if statement (line 12) from being executed. + +### break + +The `break` statement is used to exit a loop. In this contract, the break statement (line 14) will cause the for loop to be terminated after the sixth iteration. + +Watch a video tutorial on Loop statements. + +## ⭐️ Assignment + +1. Create a public `uint` state variable called count in the `Loop` contract. +2. At the end of the for loop, increment the count variable by 1. +3. Try to get the count variable to be equal to 9, but make sure you don’t edit the `break` statement. diff --git a/locales/pt/SolidityBeginnerCourse/data-locations/dataLocations.md b/locales/pt/SolidityBeginnerCourse/data-locations/dataLocations.md new file mode 100644 index 000000000..881bf8ffc --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/data-locations/dataLocations.md @@ -0,0 +1,54 @@ +The values of variables in Solidity can be stored in different data locations: _memory_, _storage_, and _calldata_. + +As we have discussed before, variables of the value type store an independent copy of a value, while variables of the reference type (array, struct, mapping) only store the location (reference) of the value. + +If we use a reference type in a function, we have to specify in which data location their values are stored. The price for the execution of the function is influenced by the data location; creating copies from reference types costs gas. + +### Storage + +Values stored in _storage_ are stored permanently on the blockchain and, therefore, are expensive to use. + +In this contract, the state variables `arr`, `map`, and `myStructs` (lines 5, 6, and 10) are stored in storage. State variables are always stored in storage. + +### Memory + +Values stored in _memory_ are only stored temporarily and are not on the blockchain. They only exist during the execution of an external function and are discarded afterward. They are cheaper to use than values stored in _storage_. + +In this contract, the local variable `myMemstruct` (line 19), as well as the parameter `_arr` (line 31), are stored in memory. Function parameters need to have the data location _memory_ or _calldata_. + +### Calldata + +_Calldata_ stores function arguments. Like _memory_, _calldata_ is only stored temporarily during the execution of an external function. In contrast to values stored in _memory_, values stored in _calldata_ can not be changed. Calldata is the cheapest data location to use. + +In this contract, the parameter `_arr` (line 35) has the data location _calldata_. If we wanted to assign a new value to the first element of the array `_arr`, we could do that in the `function g` (line 31) but not in the `function h` (line 35). This is because `_arr` in `function g `has the data location _memory_ and _function h_ has the data location `calldata`. + +## Assignments + +### Memory to memory + +Assignments from _memory_ to _memory_ create references instead of copies. If you change the value in one variable, the value of all other variables that reference the same data will be changed. + +If we were to create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myMemStruct` (line 19), any change to `myMemStruct2` would also change the value of `myMemStruct`. + +### Storage to local storage + +Assignments from _storage_ to _local storage_ also create references, not copies. + +If we change the value of the local variable `myStruct` (line 17), the value of our state variable `myStructs` (line 10) changes as well. + +## Storage and memory/calldata + +Assignments between _storage_ and _memory_ (or _calldata_) create independent copies, not references. + +If we were to create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myStruct`, changes in `myMemStruct3` would not affect the values stored in the mapping `myStructs` (line 10). + +As we said in the beginning, when creating contracts we have to be mindful of gas costs. Therefore, we need to use data locations that require the lowest amount of gas possible. + +## ⭐️ Assignment + +1. Change the value of the `myStruct` member `foo`, inside the `function f`, to 4. +2. Create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` and assign it the value of `myMemStruct`. Change the value of the `myMemStruct2` member `foo` to 1. +3. Create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` and assign it the value of `myStruct`. Change the value of the `myMemStruct3` member `foo` to 3. +4. Let the function f return `myStruct`, `myMemStruct2`, and `myMemStruct3`. + +Tip: Make sure to create the correct return types for the function `f`. diff --git a/locales/pt/SolidityBeginnerCourse/data-structures-arrays/arrays.md b/locales/pt/SolidityBeginnerCourse/data-structures-arrays/arrays.md new file mode 100644 index 000000000..19af3de49 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/data-structures-arrays/arrays.md @@ -0,0 +1,44 @@ +In the next sections, we will look into the data structures that we can use to organize and store our data in Solidity. + +_Arrays_, _mappings_ and _structs_ are all _reference types_. Unlike _value types_ (e.g. _booleans_ or _integers_) reference types don't store their value directly. Instead, they store the location where the value is being stored. Multiple reference type variables could reference the same location, and a change in one variable would affect the others, therefore they need to be handled carefully. + +In Solidity, an array stores an ordered list of values of the same type that are indexed numerically. + +There are two types of arrays, compile-time _fixed-size_ and _dynamic arrays_. For fixed-size arrays, we need to declare the size of the array before it is compiled. The size of dynamic arrays can be changed after the contract has been compiled. + +### Declaring arrays + +We declare a fixed-size array by providing its type, array size (as an integer in square brackets), visibility, and name (line 9). + +We declare a dynamic array in the same manner. However, we don’t provide an array size and leave the brackets empty (line 6). + +### Initializing arrays + +We can initialize the elements of an array all at once (line 7), or initiate new elements one by one (arr[0] = 1;). If we declare an array, we automatically initialize its elements with the default value 0 (line 9). + +### Accessing array elements + +We access elements inside an array by providing the name of the array and the index in brackets (line 12). + +### Adding array elements + +Using the `push()` member function, we add an element to the end of a dynamic array (line 25). + +### Removing array elements + +Using the `pop()` member function, we delete the last element of a dynamic array (line 31). + +We can use the `delete` operator to remove an element with a specific index from an array (line 42). +When we remove an element with the `delete` operator all other elements stay the same, which means that the length of the array will stay the same. This will create a gap in our array. +If the order of the array is not important, then we can move the last element of the array to the place of the deleted element (line 46), or use a mapping. A mapping might be a better choice if we plan to remove elements in our data structure. + +### Array length + +Using the length member, we can read the number of elements that are stored in an array (line 35). + +Watch a video tutorial on Arrays. + +## ⭐️ Assignment + +1. Initialize a public fixed-sized array called `arr3` with the values 0, 1, 2. Make the size as small as possible. +2. Change the `getArr()` function to return the value of `arr3`. diff --git a/locales/pt/SolidityBeginnerCourse/data-structures-enums/enums.md b/locales/pt/SolidityBeginnerCourse/data-structures-enums/enums.md new file mode 100644 index 000000000..40411db67 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/data-structures-enums/enums.md @@ -0,0 +1,33 @@ +In Solidity _enums_ are custom data types consisting of a limited set of constant values. We use enums when our variables should only get assigned a value from a predefined set of values. + +In this contract, the state variable `status` can get assigned a value from the limited set of provided values of the enum `Status` representing the various states of a shipping status. + +### Defining enums + +We define an enum with the enum keyword, followed by the name of the custom type we want to create (line 6). Inside the curly braces, we define all available members of the enum. + +### Initializing an enum variable + +We can initialize a new variable of an enum type by providing the name of the enum, the visibility, and the name of the variable (line 16). Upon its initialization, the variable will be assigned the value of the first member of the enum, in this case, Pending (line 7). + +Even though enum members are named when you define them, they are stored as unsigned integers, not strings. They are numbered in the order that they were defined, the first member starting at 0. The initial value of status, in this case, is 0. + +### Accessing an enum value + +To access the enum value of a variable, we simply need to provide the name of the variable that is storing the value (line 25). + +### Updating an enum value + +We can update the enum value of a variable by assigning it the `uint` representing the enum member (line 30). Shipped would be 1 in this example. Another way to update the value is using the dot operator by providing the name of the enum and its member (line 35). + +### Removing an enum value + +We can use the delete operator to delete the enum value of the variable, which means as for arrays and mappings, to set the default value to 0. + +Watch a video tutorial on Enums. + +## ⭐️ Assignment + +1. Define an enum type called `Size` with the members `S`, `M`, and `L`. +2. Initialize the variable `sizes` of the enum type `Size`. +3. Create a getter function `getSize()` that returns the value of the variable `sizes`. diff --git a/locales/pt/SolidityBeginnerCourse/data-structures-mappings/mappings.md b/locales/pt/SolidityBeginnerCourse/data-structures-mappings/mappings.md new file mode 100644 index 000000000..72fc4acb4 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/data-structures-mappings/mappings.md @@ -0,0 +1,37 @@ +In Solidity, _mappings_ are a collection of key types and corresponding value type pairs. + +The biggest difference between a mapping and an array is that you can't iterate over mappings. If we don't know a key we won't be able to access its value. If we need to know all of our data or iterate over it, we should use an array. + +If we want to retrieve a value based on a known key we can use a mapping (e.g. addresses are often used as keys). Looking up values with a mapping is easier and cheaper than iterating over arrays. If arrays become too large, the gas cost of iterating over it could become too high and cause the transaction to fail. + +We could also store the keys of a mapping in an array that we can iterate over. + +### Creating mappings + +Mappings are declared with the syntax `mapping(KeyType => ValueType) VariableName`. +The key type can be any built-in value type or any contract, but not a reference type. The value type can be of any type. + +In this contract, we are creating the public mapping `myMap` (line 6) that associates the key type `address` with the value type `uint`. + +### Accessing values + +The syntax for interacting with key-value pairs of mappings is similar to that of arrays. +To find the value associated with a specific key, we provide the name of the mapping and the key in brackets (line 11). + +In contrast to arrays, we won't get an error if we try to access the value of a key whose value has not been set yet. When we create a mapping, every possible key is mapped to the default value 0. + +### Setting values + +We set a new value for a key by providing the mapping’s name and key in brackets and assigning it a new value (line 16). + +### Removing values + +We can use the delete operator to delete a value associated with a key, which will set it to the default value of 0. As we have seen in the arrays section. + +Watch a video tutorial on Mappings. + +## ⭐️ Assignment + +1. Create a public mapping `balances` that associates the key type `address` with the value type `uint`. +2. Change the functions `get` and `remove` to work with the mapping balances. +3. Change the function `set` to create a new entry to the balances mapping, where the key is the address of the parameter and the value is the balance associated with the address of the parameter. diff --git a/locales/pt/SolidityBeginnerCourse/data-structures-structs/structs.md b/locales/pt/SolidityBeginnerCourse/data-structures-structs/structs.md new file mode 100644 index 000000000..fba0d93b0 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/data-structures-structs/structs.md @@ -0,0 +1,29 @@ +In Solidity, we can define custom data types in the form of _structs_. Structs are a collection of variables that can consist of different data types. + +### Defining structs + +We define a struct using the `struct` keyword and a name (line 5). Inside curly braces, we can define our struct’s members, which consist of the variable names and their data types. + +### Initializing structs + +There are different ways to initialize a struct. + +Positional parameters: We can provide the name of the struct and the values of its members as parameters in parentheses (line 16). + +Key-value mapping: We provide the name of the struct and the keys and values as a mapping inside curly braces (line 19). + +Initialize and update a struct: We initialize an empty struct first and then update its member by assigning it a new value (line 23). + +### Accessing structs + +To access a member of a struct we can use the dot operator (line 33). + +### Updating structs + +To update a structs’ member we also use the dot operator and assign it a new value (lines 39 and 45). + +Watch a video tutorial on Structs. + +## ⭐️ Assignment + +Create a function `remove` that takes a `uint` as a parameter and deletes a struct member with the given index in the `todos` mapping. diff --git a/locales/pt/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md b/locales/pt/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md new file mode 100644 index 000000000..d0e628f6b --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md @@ -0,0 +1,37 @@ +In this section, we will learn more about the inputs and outputs of functions. + +### Multiple named Outputs + +Functions can return multiple values that can be named and assigned to their name. + +The `returnMany` function (line 6) shows how to return multiple values. +You will often return multiple values. It could be a function that collects outputs of various functions and returns them in a single function call for example. + +The `named` function (line 19) shows how to name return values. +Naming return values helps with the readability of your contracts. Named return values make it easier to keep track of the values and the order in which they are returned. You can also assign values to a name. + +The `assigned` function (line 33) shows how to assign values to a name. +When you assign values to a name you can omit (leave out) the return statement and return them individually. + +### Deconstructing Assignments + +You can use deconstructing assignments to unpack values into distinct variables. + +The `destructingAssigments` function (line 49) assigns the values of the `returnMany` function to the new local variables `i`, `b`, and `j` (line 60). + +### Input and Output restrictions + +There are a few restrictions and best practices for the input and output parameters of contract functions. + +"_[Mappings] cannot be used as parameters or return parameters of contract functions that are publicly visible._" +From the Solidity documentation. + +Arrays can be used as parameters, as shown in the function `arrayInput` (line 71). Arrays can also be used as return parameters as shown in the function `arrayOutput` (line 76). + +You have to be cautious with arrays of arbitrary size because of their gas consumption. While a function using very large arrays as inputs might fail when the gas costs are too high, a function using a smaller array might still be able to execute. + +Watch a video tutorial on Function Outputs. + +## ⭐️ Assignment + +Create a new function called `returnTwo` that returns the values `-2` and `true` without using a return statement. diff --git a/locales/pt/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md b/locales/pt/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md new file mode 100644 index 000000000..d707a987b --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md @@ -0,0 +1,39 @@ +In this section, we will learn how to modify the behavior of a function and how to run contract initialization code. + +### Function Modifier + +_Function Modifiers_ are used to change the behavior of a function. For example, they often check for a condition prior to executing a function to restrict access or validate inputs. + +This first part of this contract is about changing ownership of a contract. Ownership in this contract is expressed by the value of the state variable `owner` that is of the type `address` (line 7). + +The function `changeOwner` (line 33) can change this ownership. It takes an input parameter of the type `address` and assigns its value to the state variable `owner`. + +However, this function cannot simply be executed under all conditions; it has two modifiers, `onlyOwner` and `validAddress`. + +Let's look at `onlyOwner` first (line 18). +Function modifiers are defined with the `modifier` keyword and a unique name; they can also have parameters. + +The underscore `_` (line 23) is used inside modifiers to represent the rest of the code that will be executed in the body of the modified function. +The code you place before the underscore in the modifier will be executed before the code in the body of the modified function. The code after the underscore will be executed after the code in the body of the modified function. + +In this case, the `require` function (line 19) checks if the address executing the contract is the same as the value stored in the variable `owner`. If it is, the rest of the code will be executed, otherwise it will throw an error. + +You can learn more about `assert` and `require` in the Solidity documentation, they are used to check for conditions and throw errors if they are not met. + +The `validAddress` modifier (line 28) has a parameter of type `address` and checks if the provided address is valid. If it is, it continues to execute the code. + +### Constructor + +A constructor function is executed upon the creation of a contract. You can use it to run contract initialization code. The constructor can have parameters and is especially useful when you don't know certain initialization values before the deployment of the contract. + +You declare a constructor using the `constructor` keyword. The constructor in this contract (line 11) sets the initial value of the owner variable upon the creation of the contract. + +Watch a video tutorial on Function Modifiers. + +## ⭐️ Assignment + +1. Create a new function, `increaseX` in the contract. The function should take an input parameter of type `uint` and increase the value of the variable `x` by the value of the input parameter. +2. Make sure that x can only be increased. +3. The body of the function `increaseX` should be empty. + +Tip: Use modifiers. diff --git a/locales/pt/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md b/locales/pt/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md new file mode 100644 index 000000000..3670c03e2 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md @@ -0,0 +1,23 @@ +This section will give a short introduction to functions and teach you how to use them to read from and write to a state variable. + +As in other languages, we use functions in Solidity to create modular, reusable code. However, Solidity functions have some particularities. + +Solidity functions can be split into two types: + +1. Functions that modify the state of the blockchain, like writing to a state variable. In this contract, the `set` function (line 9) changes the state variable `num`. +2. Functions that don't modify the state of the blockchain. These functions are marked `view` or `pure`. For example, in this contract, the `get` function (line 14) marked `view` that only returns `num` does not change the state. + +To define a function, use the `function` keyword followed by a unique name. + +If the function takes inputs like our `set` function (line 9), you must specify the parameter types and names. A common convention is to use an underscore as a prefix for the parameter name to distinguish them from state variables. + +You can then set the visibility of a function and declare them `view` or `pure` as we do for the `get` function if they don't modify the state. Our `get` function also returns values, so we have to specify the return types. In this case, it's a `uint` since the state variable `num` that the function returns is a `uint`. + +We will explore the particularities of Solidity functions in more detail in the following sections. + +Watch a video tutorial on Functions. + +## ⭐️ Assignment + +1. Create a public state variable called `b` that is of type `bool` and initialize it to `true`. +2. Create a public function called `get_b` that returns the value of `b`. diff --git a/locales/pt/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md b/locales/pt/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md new file mode 100644 index 000000000..b846c7d99 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md @@ -0,0 +1,44 @@ +This section will look into the types of functions that don't modify the state of the blockchain: _view_ and _pure_ functions. + +### View Functions + +_View functions_ promise to not modify the state. + +"The following statements are considered modifying the state: + +1. Writing to state variables. +2. Emitting events. +3. Creating other contracts. +4. Using selfdestruct. +5. Sending Ether via calls. +6. Calling any function not marked view or pure. +7. Using low-level calls. +8. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a view function using the keyword `view`. In this contract, `addToX` (line 8) is a view function. This function takes the parameter `y` and returns the sum of the parameter and the state variable `x`. It reads `x` but does not modify it. + +### Pure functions + +_Pure functions_ promise to neither modify nor to read the state. + +"In addition to the list of state modifying statements explained above, the following are considered reading from the state: + +1. Reading from state variables. +2. Accessing `address(this).balance` or `
.balance`. +3. Accessing any of the members of block, tx, msg (with the exception of `msg.sig` and `msg.data`). +4. Calling any function not marked pure. +5. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a pure function using the keyword `pure`. In this contract, `add` (line 13) is a pure function. This function takes the parameters `i` and `j`, and returns the sum of them. It neither reads nor modifies the state variable `x`. + +In Solidity development, you need to optimise your code for saving computation cost (gas cost). Declaring functions view and pure can save gas cost and make the code more readable and easier to maintain. Pure functions don't have any side effects and will always return the same result if you pass the same arguments. + +Watch a video tutorial on View and Pure Functions. + +## ⭐️ Assignment + +Create a function called `addToX2` that takes the parameter `y` and updates the state variable `x` with the sum of the parameter and the state variable `x`. diff --git a/locales/pt/SolidityBeginnerCourse/introduction/introduction.md b/locales/pt/SolidityBeginnerCourse/introduction/introduction.md new file mode 100644 index 000000000..cc821a46a --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/introduction/introduction.md @@ -0,0 +1,32 @@ +Welcome to this interactive Solidity course for beginners. + +In this first section, we will give you a short preview of the concepts we will cover in this course, look at an example smart contract, and show you how you can interact with this contract in the Remix IDE. + +This contract is a counter contract that has the functionality to increase, decrease, and return the state of a counter variable. + +If we look at the top of the contract, we can see some information about the contract like the license (line 1), the Solidity version (line 2), as well as the keyword `contract` and it's name, `Counter` (line 4). We will cover these concepts in the next section about the **Basic Syntax**. + +With `uint public count` (line 5) we declare a state variable of the type `uint` with the visibility `public`. We will cover these concepts in our sections about **Variables**, **Primitive Data Types**, and **Visibility**. + +We then create a `get` function (line 8) that is defined with the `view` keyword and returns a `uint` type. Specifically, it returns the `count` variable. This contract has two more functions, an `inc` (line 13) and `dec` (line 18) function that increases or decreases our count variable. +We will talk about these concepts in our sections about **Functions - Reading and Writing to a State Variable** and **Functions - View and pure**. + +## Compile and Deploy through Remix + +**GIF** Interacting with the contract: Compile and deploy contract + +1. We can compile your `Counter` contract in the "Solidity compiler" module of the Remix IDE. + +2. In the "Deploy & run transactions" module, we select our contract "Counter" in the contract input field and click on the "Deploy" button. + +3. We expand the token contract functions in the IDE, and test its `get`, `inc`, and `dec` functions. + +## ⭐️ Assignment + +Throughout this course, we will give you assignments to test and consolidate your newly acquired knowledge. + +Your first assignment is to: + +1. Compile this contract. +2. Deploy it to the Remix VM. +3. Interact with your contract. diff --git a/locales/pt/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md b/locales/pt/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md new file mode 100644 index 000000000..9ea6b8626 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md @@ -0,0 +1,33 @@ +In this section, we will show you Solidity’s primitive data types, how to declare them, and their characteristics. + +### bool + +You can declare data a boolean type by using the keyword ‘bool’. Booleans can either have the value `true` or `false`. + +### uint + +We use the keywords `uint` and `uint8` to `uint256` to declare an _unsigned integer type_ (they don’t have a sign, unlike -12, for example). Uints are integers that are positive or zero and range from 8 bits to 256 bits. The type `uint` is the same as `uint256`. + +### int + +We use the keywords `int` and `int8` to `int256` to declare an integer type. Integers can be positive, negative, or zero and range from 8 bits to 256 bits. The type `int` is the same as `int256`. + +### address + +Variables of the type `address` hold a 20-byte value, which is the size of an Ethereum address. There is also a special kind of Ethereum address, `address payable`, which can receive ether from the contract. + +All these data types have default values, as shown in the contract (line 29). + +You can learn more about these data types as well as _Fixed Point Numbers_, _Byte Arrays_, _Strings_, and more in the Solidity documentation. + +Later in the course, we will look at data structures like **Mappings**, **Arrays**, **Enums**, and **Structs**. + +Watch a video tutorial on Primitive Data Types. + +## ⭐️ Assignment + +1. Create a new variable `newAddr` that is a `public` `address` and give it a value that is not the same as the available variable `addr`. +2. Create a `public` variable called `neg` that is a negative number, decide upon the type. +3. Create a new variable, `newU` that has the smallest `uint` size type and the smallest `uint` value and is `public`. + +Tip: Look at the other address in the contract or search the internet for an Ethereum address. diff --git a/locales/pt/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md b/locales/pt/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md new file mode 100644 index 000000000..57208c555 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md @@ -0,0 +1,26 @@ +_Ether_ (ETH) is a cryptocurrency. _Ether_ is also used to pay fees for using the Ethereum network, like making transactions in the form of sending _Ether_ to an address or interacting with an Ethereum application. + +### Ether Units + +To specify a unit of _Ether_, we can add the suffixes `wei`, `gwei`, or `ether` to a literal number. + +#### `wei` + +_Wei_ is the smallest subunit of _Ether_, named after the cryptographer [Wei Dai](https://en.wikipedia.org/wiki/Wei_Dai). _Ether_ numbers without a suffix are treated as `wei` (line 7). + +#### `gwei` + +One `gwei` (giga-wei) is equal to 1,000,000,000 (10^9) `wei`. + +#### `ether` + +One `ether` is equal to 1,000,000,000,000,000,000 (10^18) `wei` (line 11). + +Watch a video tutorial on Ether and Wei. + +## ⭐️ Assignment + +1. Create a `public` `uint` called `oneGWei` and set it to 1 `gwei`. +2. Create a `public` `bool` called `isOneGWei` and set it to the result of a comparison operation between 1 gwei and 10^9. + +Tip: Look at how this is written for `gwei` and `ether` in the contract. diff --git a/locales/pt/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md b/locales/pt/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md new file mode 100644 index 000000000..bbc25575c --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md @@ -0,0 +1,29 @@ +As we have seen in the previous section, executing code via transactions on the Ethereum Network costs transaction fees in the form of Ether. The amount of fees that have to be paid to execute a transaction depends on the amount of _gas_ that the execution of the transaction costs. + +### Gas + +_Gas_ is the unit that measures the amount of computational effort that is required to execute a specific operation on the Ethereum network. + +### Gas price + +The _gas_ that fuels Ethereum is sometimes compared to the gas that fuels a car. The amount of gas your car consumes is mostly the same, but the price you pay for gas depends on the market. + +Similarly, the amount of _gas_ that a transaction requires is always the same for the same computational work that is associated with it. However the price that the sender of the transaction is willing to pay for the _gas_ is up to them. Transactions with higher _gas prices_ are going through faster; transactions with very low _gas prices_ might not go through at all. + +When sending a transaction, the sender has to pay the _gas_ fee (gas_price \* gas) upon execution of the transaction. If _gas_ is left over after the execution is completed, the sender gets refunded. + +_Gas_ prices are denoted in gwei. + +### Gas limit + +When sending a transaction, the sender specifies the maximum amount of gas that they are willing to pay for. If they set the limit too low, their transaction can run out of _gas_ before being completed, reverting any changes being made. In this case, the _gas_ was consumed and can’t be refunded. + +Learn more about _gas_ on ethereum.org. + +Watch a video tutorial on Gas and Gas Price. + +## ⭐️ Assignment + +Create a new `public` state variable in the `Gas` contract called `cost` of the type `uint`. Store the value of the gas cost for deploying the contract in the new variable, including the cost for the value you are storing. + +Tip: You can check in the Remix terminal the details of a transaction, including the gas cost. You can also use the Remix plugin _Gas Profiler_ to check for the gas cost of transactions. diff --git a/locales/pt/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md b/locales/pt/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md new file mode 100644 index 000000000..58fb4c5a6 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md @@ -0,0 +1,86 @@ +In this section, we will learn how a contract can send and receive Ether. + +### Sending Ether + +We have three different options to transfer Ether: `transfer()`, `send()` and `call()`. + +#### **transfer** + +`
.transfer(uint256 amount)` + +- `transfer()` throws an exception on failure +- Forwards a fixed 2300 gas stipend + +An example of `transfer()` can be seen in the `SendEther` contract (line 35). +**`Transfer()` is not recommended to be used anymore.** + +#### **send** + +`
.send(uint256 amount) returns (bool)` + +- `send()` returns false on failure +- Forwards a fixed 2300 gas stipend + +An example of `send()` can be seen in the `SendEther` contract (line 41). +**`Send()` is not recommended to be used anymore.** + +#### **call** + +`
.call(bytes memory) returns (bool, bytes memory)` + +- `call()` returns false on failure +- Forwards the maximum amount of gas, but this is adjustable + +An example of `call()` can be seen in the `SendEther` contract (line 48). +`Call()` is currently recommended if you are transfering Ether. + +The reason `transfer()` and `send()` were introduced was to guard against _reentry attacks_ by limiting the forwarded gas to 2300, which would be insufficient to make a reentrant call that can modify storage. + +As we discussed in the last section, each operation on Ethereum has a specific cost associated with it. Certain operations have become more cost intensive over time, so the gas costs associated with them are also raised. When gas costs for operations are subject to change it is not good to use a hardcoded gas amount like transfer(), and send() do. + +That’s why `call()` instead of `transfer()` is now recommended to send Ether. + +Learn more about the subject in this Consensys blog post. + +### Reentrancy attack + +A _reentrancy attack_ occurs when a function makes an external call to an untrusted contract and the attacker uses the contract to make recursive calls back to the original function before it finishes its execution. Through this method, the attacker can drain funds and manipulate data in unintended ways. + +To guard against a _reentrancy attack_, all state changes should be made before calling an external contract. This is also called the Checks-Effects-Interactions pattern. + +Another way to prevent reentrancy is to use a _Reentrancy Guard_ that checks for such calls and rejects them. You can see an example of this in the contract in our modifier section or a more gas-efficient version on Open Zepplin. + +### Receiving Ether + +If we want to enable a contract to receive Ether without a function being called, we need to create a `receive` function (line 22) or a `fallback` function (line 25); otherwise, the Ether will be rejected, and the contract will throw an exception. + +The `receive` function is executed on calls with empty calldata (e.g. plain Ether transfers via send() or transfer()), while the fallback function is executed on calls with calldata. If no receive function exists but a fallback function does, calls with empty calldata will also use the fallback function. + +### Payable function modifier + +The `payable` function modifier allows a function to receive Ether. + +The `receive` function (line 22) needs to be `payable`. If you delete the `payable` modifier you will get an error from the compiler. If you delete the `payable` modifier from the `fallback` function (line 25) it will compile, but it won’t be able to receive Ether. +The functions `sendViaTransfer`, `sendViaSend`, and `sendViaCall` (lines 33, 38, and 45) also need to be `payable` in order to receive Ether. + +### Payable address + +Solidity makes a distinction between two different flavors of the address data type: address and address payable. + +`address`: Holds a 20-byte value. +`address payable`: Holds a 20-byte value and can receive Ether via its members: transfer and send. + +If you change the parameter type for the functions `sendViaTransfer` and `sendViaSend` (line 33 and 38) from `payable address` to `address`, you won’t be able to use `transfer()` (line 35) or `send()` (line 41). + +Watch a video tutorial on Sending Ether. + +## ⭐️ Assignment + +Build a charity contract that receives Ether that can be withdrawn by a beneficiary. + +1. Create a contract called `Charity`. +2. Add a public state variable called `owner` of the type address. +3. Create a donate function that is public and payable without any parameters or function code. +4. Create a withdraw function that is public and sends the total balance of the contract to the `owner` address. + +Tip: Test your contract by deploying it from one account and then sending Ether to it from another account. Then execute the withdraw function. diff --git a/locales/pt/SolidityBeginnerCourse/variables/variables.md b/locales/pt/SolidityBeginnerCourse/variables/variables.md new file mode 100644 index 000000000..dfb35b382 --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/variables/variables.md @@ -0,0 +1,29 @@ +There are three different types of variables in Solidity: _State Variables_, _Local Variables_, and _Global Variables_. + +## 1. State Variables + +_State Variables_ are stored in the contract _storage_ and thereby on the blockchain. They are declared inside the contract but outside the function. +This contract has two state variables, the string `text`(line 6) and the uint `num` (line 7). + +## 2. Local Variables + +_Local Variables_ are stored in the _memory_ and their values are only accessible within the function they are defined in. Local Variables are not stored on the blockchain. +In this contract, the uint `i` (line 11) is a local variable. + +## 3. Global Variables + +_Global Variables_, also called _Special Variables_, exist in the global namespace. They don't need to be declared but can be accessed from within your contract. +Global Variables are used to retrieve information about the blockchain, particular addresses, contracts, and transactions. + +In this example, we use `block.timestamp` (line 14) to get a Unix timestamp of when the current block was generated and `msg.sender` (line 15) to get the caller of the contract function’s address. + +A list of all Global Variables is available in the Solidity documentation. + +Watch video tutorials on State Variables, Local Variables, and Global Variables. + +## ⭐️ Assignment + +1. Create a new public state variable called `blockNumber`. +2. Inside the function `doSomething()`, assign the value of the current block number to the state variable `blockNumber`. + +Tip: Look into the global variables section of the Solidity documentation to find out how to read the current block number. diff --git a/locales/pt/SolidityBeginnerCourse/visibility/visibility.md b/locales/pt/SolidityBeginnerCourse/visibility/visibility.md new file mode 100644 index 000000000..79e4307bf --- /dev/null +++ b/locales/pt/SolidityBeginnerCourse/visibility/visibility.md @@ -0,0 +1,37 @@ +The `visibility` specifier is used to control who has access to functions and state variables. + +There are four types of visibilities: `external`, `public`, `internal`, and `private`. + +They regulate if functions and state variables can be called from inside the contract, from contracts that derive from the contract (child contracts), or from other contracts and transactions. + +### private + +- Can be called from inside the contract + +### internal + +- Can be called from inside the contract +- Can be called from a child contract + +### public + +- Can be called from inside the contract +- Can be called from a child contract +- Can be called from other contracts or transactions + +### external + +- Can be called from other contracts or transactions +- State variables can not be `external` + +In this example, we have two contracts, the `Base` contract (line 4) and the `Child` contract (line 55) which inherits the functions and state variables from the `Base` contract. + +When you uncomment the `testPrivateFunc` (lines 58-60) you get an error because the child contract doesn’t have access to the private function `privateFunc` from the `Base` contract. + +If you compile and deploy the two contracts, you will not be able to call the functions `privateFunc` and `internalFunc` directly. You will only be able to call them via `testPrivateFunc` and `testInternalFunc`. + +Watch a video tutorial on Visibility. + +## ⭐️ Assignment + +Create a new function in the `Child` contract called `testInternalVar` that returns the values of all state variables from the `Base` contract that are possible to return. diff --git a/locales/pt/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md b/locales/pt/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md new file mode 100644 index 000000000..801d8c582 --- /dev/null +++ b/locales/pt/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md @@ -0,0 +1,47 @@ +In this tutorial, we'll explore the Uniswap V3 Swap contract to learn about how single-hop and multi-hop swaps work. + +But first, some Uniswap fundamentals. + +## What is Uniswap? + +Uniswap is a decentralized cryptocurrency exchange. It allows users to exchange tokens without the need for a centralized intermediary. Uniswap is a key player in the decentralized finance (DeFi) space. + +## How does Uniswap work? + +Instead of using an order book like a traditional centralized exchange, Uniswap uses an automated market maker (AMM) model. In Uniswap, the AMM is a smart contract that holds reserves of tokens (Liquidity Pool). Users can trade between tokens in the Liquidity Pool. The price of each token is determined by the ratio of the reserves. + +### Step-by-step example of a Uniswap trade + +1. Alice wants to trade 1 ETH for DAI. +2. Alice sends 1 ETH to the Uniswap smart contract. +3. The Uniswap smart contract calculates the amount of DAI that Alice should receive based on the current exchange rate. +4. The Uniswap smart contract sends the DAI to Alice. +5. The Uniswap smart contract adds the 1 ETH to its reserves. +6. The Uniswap smart contract recalculates the exchange rate based on the new reserves. + +The tokens in the Liquidity Pool are provided by Liquidity Providers. When a Liquidity Provider deposits tokens into a Liquidity Pool, they receive Liquidity Provider Tokens in return. Liquidity Provider Tokens represent a user's share of a Liquidity Pool. + +Users of Uniswap pay a fee for each trade. The fee is paid to the Liquidity Providers in the form of additional Liquidity Provider Tokens. + +## Uniswap Swap Contract + +The Uniswap Swap contract allows users to swap tokens using Uniswap V3. It can do single-hop swaps, which allow users to exchange one token for another directly. It can also do multi-hop swaps, which means that users can exchange one token for another by routing through multiple tokens. Routing in this context means that the swap contract will exchange the token for another token, then exchange that token for another token, and so on until it reaches the desired token. + +## Conclusion + +In this section, we learned about Uniswap, how it works, and how we are going to use it to swap tokens. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is Uniswap? + +1. A centralized exchange protocol. +2. A decentralized exchange protocol that uses an order book. +3. A decentralized exchange protocol that uses an automated market maker (AMM) model. +4. A decentralized exchange protocol that uses an order book and an automated market maker (AMM) model. + +### 2) How does Uniswap determine the price of a token? + +1. The price of a token is determined by the ratio of the reserves. +2. The price of a token is determined by the ratio of the reserves and the number of trades. +3. The price of a token is determined by the ratio of the reserves and the number of Liquidity Providers. diff --git a/locales/pt/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md b/locales/pt/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md new file mode 100644 index 000000000..e5cc248f5 --- /dev/null +++ b/locales/pt/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md @@ -0,0 +1,41 @@ +The entire UniswapSwapExamples contract will only be presented in section 5 of this tutorial. Before then, we'll build up blocks of code. + +This section explores the `ISwapRouter` interface, which defines the functions that can be called on the Uniswap Swap contract. + +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. +Multi-hop swaps allow users to exchange one token for another by routing through multiple tokens. + +Interfaces in Solidity specify functions that must be included in a contract that inherits them. They are useful for declaring what functions be supported and allow for easier integration and interaction between different contracts. + +Structs are used to define custom data types. + +## ISwapRouter Interface + +The ISwapRouter interface defines the functions that can be called on the Uniswap Swap contract. We will need to use this interface to interact with the Uniswap Swap contract and execute swaps. + +On line 5, we define a constant variable called `router` that is of type `ISwapRouter`. We set the value of this variable to the interface instance of a smart contract that is deployed at the address `0xE592427A0AEce92De3Edee1F18E0157C05861564`. This is the address of the Uniswap V3 Swap contract on the Ethereum mainnet. + +On line 9, we define an interface called `ISwapRouter`. This interface defines two functions: `exactInputSingle` and `exactInput`. + +## exactInputSingle + +On line 25, we define a struct called `ExactInputSingleParams`. This struct defines the parameters that are required for our exactInputSingle function on line 21, which will execute a single-hop swap. The struct has the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 fee`**: The fee associated with the swap. +- **`address recipient`**: The address that will receive the output token. +- **`uint deadline`**: A timestamp by which the transaction must be processed, for time-limiting the swap. +- **`uint amountIn`**: The amount of the input token being sent. +- **`uint amountOutMinimum`**: The minimum amount of the output token that the sender is willing to accept, to protect against unfavorable price movements. +- **`uint160 sqrtPriceLimitX96`**: A limit on the price, represented in a specific format, to prevent the swap from occurring at unfavorable prices. + +## exactInput + +On line 25, we define a struct called `ExactInputParams`. This struct defines the parameters that are required for our `exactInput` function on line 33. This function will execute a multi-hop swap. The struct has the following parameters: + +- **`bytes path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address recipient`**: The address receiving the output tokens. +- **`uint deadline`**: Similar to above, a timestamp by which the transaction must be processed. +- **`uint amountIn`**: The amount of the input token. +- **`uint amountOutMinimum`**: The minimum amount of the output token the sender expects to receive. diff --git a/locales/pt/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md b/locales/pt/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md new file mode 100644 index 000000000..f4d70c445 --- /dev/null +++ b/locales/pt/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md @@ -0,0 +1,36 @@ +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. In this section, we will learn how to use the Uniswap V3 Swap contract to execute single-hop swaps. + +## Function Parameters + +On line 8, we define a function called `swapExactInputSingleHop`. This function executes a single-hop swap. It takes the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 poolFee`**: The fee associated with the swap. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +## Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 14. +Then, we approve the Uniswap Swap contract to spend the input token on our behalf, line 15. + +On line 17, we create an instance of the `ExactInputSingleParams` struct. This struct contains the parameters that are required for our `exactInputSingle` function on line 45, which will execute the single-hop swap. We repeat `ISwapRouter.ExactInputSingleParams` two times on that line because we are making an instance of a struct that is defined in an interface. + +## Parameters of the ExactInputSingleParams Struct + +We set the parameters of the struct as follows: + +- **`tokenIn`**: We set this to the `tokenIn` parameter of our function. +- **`tokenOut`**: We set this to the `tokenOut` parameter of our function. +- **`fee`**: We set this to the `poolFee` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. +- **`sqrtPriceLimitX96`**: We set this to 0 because we do not want to specify a limit on the price. + +## Executing the Single-hop Swap + +On line 29, we assign the output of the `exactInputSingle` function to the `amountOut` variable. This function executes the single-hop swap and returns the amount of the output token that was received. diff --git a/locales/pt/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md b/locales/pt/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md new file mode 100644 index 000000000..7883b4718 --- /dev/null +++ b/locales/pt/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md @@ -0,0 +1,30 @@ +In this section, we'll delve into the `swapExactInputMultiHop` function in the `UniswapV3SwapExamples` contract. This function enables more complex token swaps by allowing users to specify a custom path through multiple liquidity pools. + +If for example, a user wants to swap token A for token D, but there is no direct liquidity pool for A and D, the user can specify a path through multiple tokens. For example, the user can swap A for B, then B for C, and finally C for D. This is of course automatically done by the Uniswap V3 Swap contract. + +### Parameters and Return Value + +On line 32, we define a function called `swapExactInputMultiHop`. This function executes a multi-hop swap. It takes the following parameters: + +- **`bytes calldata path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address tokenIn`**: The address of the token being sent. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +### Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 38. +Then, we approve the Uniswap Swap router to spend the input token on our behalf, line 41. + +On line 43, we create an instance of the `ExactInputParams` struct, line 73. This struct contains the parameters that are required for our `exactInput` function on line 81, which will execute the multi-hop swap. + +We set the parameters of the struct as follows: + +- **`path`**: We set this to the `path` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. + +On line 53, we execute the multi-hop swap by calling the `exactInput` function. This function returns the amount of the output token that was received. diff --git a/locales/pt/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md b/locales/pt/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md new file mode 100644 index 000000000..b3cec34e9 --- /dev/null +++ b/locales/pt/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md @@ -0,0 +1,52 @@ +In this section, we'll explore the `IERC20` interface, a standard interface for interacting with ERC-20 tokens and the `IWETH` interface, a standard interface for interacting with wrapped Ether (WETH). Understanding these interfaces is crucial as it is used in the Uniswap V3 Swap contract to handle token transfers and approvals. + +You can find a "Solidity ERC20 Token Course" for beginners in LearnEth to understand the ERC20 token standard in more detail. + +## IERC20 Interface + +On line 80, we define the `IERC20` interface. This interface defines a standard set of functions that ERC-20 tokens must implement. Let's examine the key functions within this interface: + +### 1. totalSupply + +On line 81, we define the `totalSupply` function. This function returns the total supply of the token. + +### 2. balanceOf + +On line 83, we define the `balanceOf` function. This function returns the balance of the specified address. + +### 3. transfer + +On line 85, we define the `transfer` function. This function transfers tokens from the sender to the specified recipient. + +### 4. allowance + +On line 87, we define the `allowance` function. This function returns the amount of tokens that the spender is allowed to spend on behalf of the owner. + +### 5. approve + +On line 89, we define the `approve` function. When called, this function approves a spender to spend the specified amount of tokens on behalf of the sender. + +### 6. transferFrom + +On line 91, we define the `transferFrom` function. This function transfers tokens from the specified sender to the recipient. The function can only be called by the spender if the spender is allowed to spend the specified amount of tokens on behalf of the sender. + +### 7. Events + +On lines 102-103, we define the `Transfer` and `Approval` events. These events are emitted when the `transfer` and `approve` functions are called, respectively. + +## IWETH Interface + +On line 106, we define the `IWETH` interface. This interface extends the `IERC20` interface and defines two additional functions: + +### 1. deposit + +On line 107, we define the `deposit` function. This function deposits ETH into the contract and returns the equivalent amount of WETH. This function is used to wrap ETH into WETH. +We need to wrap ETH into WETH because the Uniswap V3 Swap contract only supports ERC-20 tokens. + +### 2. withdraw + +On line 109, we define the `withdraw` function. This function withdraws the specified amount of WETH from the contract and returns the equivalent amount of ETH. This function is used to unwrap WETH into ETH. + +## Conclusion + +In this tutorial, we explored the Uniswap V3 Swap contract. To get a full sense of how Uniswap works, try making some swaps on the Uniswap DApp and go to the Uniswap docs. diff --git a/locales/pt/Uniswap-Tutorial/README.md b/locales/pt/Uniswap-Tutorial/README.md new file mode 100644 index 000000000..cf66c5582 --- /dev/null +++ b/locales/pt/Uniswap-Tutorial/README.md @@ -0,0 +1,5 @@ +# Uniswap Swap Course + +Review the code of the Uniswap V3 Swap contract for performing token swaps. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/pt/Uniswap-Tutorial/config.yml b/locales/pt/Uniswap-Tutorial/config.yml new file mode 100644 index 000000000..f49f02abc --- /dev/null +++ b/locales/pt/Uniswap-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: uniswapSwapCourse +name: Uniswap Swap Course +summary: Go through the Solidity code of the Uniswap V3 Swap contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - Uniswap +steps: + - + name: 1. Introduction + path: 1-introduction-to-uniswap + - + name: 2. Routers, Interfaces, and Structs + path: 2-router-interfaces-and-structs + - + name: 3. Single Hop Swaps + path: 3-single-hop-swaps + - + name: 4. Multi-Hop Swaps + path: 4-multi-hop-swaps + - + name: 5. Erc20 and Weth Interfaces + path: 5-erc20-weth-interfaces diff --git a/locales/pt/Web3Client/1_Using_Web3/Running_a_script.md b/locales/pt/Web3Client/1_Using_Web3/Running_a_script.md new file mode 100644 index 000000000..3b7b23332 --- /dev/null +++ b/locales/pt/Web3Client/1_Using_Web3/Running_a_script.md @@ -0,0 +1,24 @@ +## Querying the Blockchain + +In this tutorial, we'll run a script that queries the blockchain using a JavaScript library. + +This means that instead of using the Remix GUI or a block explorer like Etherscan, we'll use a script in the editor and will run it from the terminal. + +The JS libraries that are used the most for interacting with the blockchain are web3.js & ethers.js. + +Let's begin with a simple web3.js example, queryBlockNum.js. + +The script's call to web3.js is wrapped in a self-executing async function that contains a try/catch block. + +We'll query the current blocknumber with: +`let blockNumber = await web3.eth.getBlockNumber()` + +Note that the object `web3` is injected by Remix. For more info on web3.js, check their docs, https://web3js.readthedocs.io. + +To use web3.js or ethers.js, you need to select the **Injected Web3** or **Web3 Provider** environment in the **Deploy & Run** module. Scripts don't currently work with the JSVM. **If you try, you'll get an error.** + +So for this example choose **Injected Web3** in the Deploy & Run module and have Metamask installed. + +From the terminal, execute `remix.execute()`. This command will execute the current JavaScript file with the line `let blockNumber = await web3.eth.getBlockNumber()`. + +In the console, you should see the current block number of the chain that metamask is connected to. diff --git a/locales/pt/Web3Client/2_Querying_a_Contract/queryContract.md b/locales/pt/Web3Client/2_Querying_a_Contract/queryContract.md new file mode 100644 index 000000000..461c98244 --- /dev/null +++ b/locales/pt/Web3Client/2_Querying_a_Contract/queryContract.md @@ -0,0 +1,23 @@ +Now that we know how to query simple data, let's try a more complex query. + +This is a contract deployed to the mainnet - at this address: https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code + +We are going to query the contract to find the name of it's token. + +The **name** variable is a state variable of the contract. + +To access this **mainnet** contract, we need to do some setup. + +1. Switch to the mainnet in metamask. +2. You'll probably need to refresh Remix. +3. As a result of the refresh, you may need to reload this tutorial too. +4. Go to Deploy & Run and switch to **Injected Web3**. + +**Using Web3** +In the script, queryContract.js, we need to instantiate a new instance of web3.eth.Contract object. For this we need to grab the contract's ABI and its address. The source code & ABI is available in etherscan because the contract's developer intentionally published it. + +In etherscan, we can see that its name is **TetherToken**. Scrolling down to the TetherToken contract in the source code section of etherscan, we can see the state variables for the contract - the first of which is named **name**. + +There are a few syntactic hoops to jump through to return the value of the state variable. + +- To call the autogenerated getter function of the public state variable, you need to both treat the variable as a function (by adding parentheses) and also to tack on a call(). diff --git a/locales/pt/Web3Client/README.md b/locales/pt/Web3Client/README.md new file mode 100644 index 000000000..a319f312f --- /dev/null +++ b/locales/pt/Web3Client/README.md @@ -0,0 +1 @@ +This workshop is about using the web3.js to interact with a contract and more generally to the blockchain. diff --git a/locales/pt/Web3Client/config.yml b/locales/pt/Web3Client/config.yml new file mode 100644 index 000000000..07cb1760c --- /dev/null +++ b/locales/pt/Web3Client/config.yml @@ -0,0 +1,9 @@ +--- +id: useofweb3js +name: Basic use of web3.js +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 2 +tags: + - JS + - Remix + - Web3 diff --git a/locales/ru/Basics/README.md b/locales/ru/Basics/README.md new file mode 100644 index 000000000..1d5ced54f --- /dev/null +++ b/locales/ru/Basics/README.md @@ -0,0 +1,3 @@ +## Загрузка, компиляция, деплой + +This beginner level tutorial introduces Remix's interface and concepts used in Ethereum. diff --git a/locales/ru/Basics/config.yml b/locales/ru/Basics/config.yml new file mode 100644 index 000000000..8c160b545 --- /dev/null +++ b/locales/ru/Basics/config.yml @@ -0,0 +1,26 @@ +--- +id: basics +name: Basics of Remix +summary: A typical workflow in Remix +level: 1 +tags: + - Remix +steps: + - + name: Intro to the Interface + path: interface_introduction + - + name: Intro to Workspaces + path: workspaces + - + name: Loading & Compiling + path: load_and_compile + - + name: Deploying to the Remix VM + path: deploy_to_the_remixvm + - + name: Interacting with Functions + path: interacting + - + name: Deploying to Public Networks + path: deploy_injected diff --git a/locales/ru/Basics/deploy_injected/README.md b/locales/ru/Basics/deploy_injected/README.md new file mode 100644 index 000000000..172396527 --- /dev/null +++ b/locales/ru/Basics/deploy_injected/README.md @@ -0,0 +1,21 @@ +1. If you don't have a browser wallet like **MetaMask** download and install one now. + +2. Click the MetaMask icon in your browser. Sign in and choose the Ephemery test network. You might need to update your wallet's settings so that you can see **test networks**. Alternatively, you can go to Remix's Deploy & Run transation module and in the ENVIRONMENT section select Ephemery. + +3. Getting test ETH for public test networks is often annoying. Ephemery is a public network that is refreshed monthly, so getting test ETH should be painless. Here is a link to some Ephemery faucets. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/testnet.png) + +Sepolia is another popular testnet that is not refreshed, so deployments will persist, but Sepolia faucets are more difficult to use. + +In your browser wallet make sure that you have NOT selected mainnet or any network that will cost real ETH. In the Deploy & Run module, below the Environment select box, you'll see a badge with the network's ID and for popular chains, its name. In the case below its Sepolia. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/sepolia.png) + +5. Make sure you see the 2_Owner.sol as a choice in the **CONTRACT** select box, then click the **Deploy** button. + +If the **CONTRACT** select box is empty, you'll need to compile 2_Owner again by making 2_Owner.sol the active file in the **editor** and then go to the **Solidity Compiler** to compile it. + +6. After you hit the `Deploy` button, you'll see the browser wallet popup asking you to pay for the transactions. If you have the appropriate kind of ETH for this chain, approve this transaction. Check the printout in the terminal. Once the block is validated, the **deployed instance** will appear at the bottom of Deploy & Run + +And with that you have finished this tutorial. You now have experience with opening, compiling, deploying and interacting with Smart Contracts in Remix IDE. diff --git a/locales/ru/Basics/deploy_to_the_remixvm/README.md b/locales/ru/Basics/deploy_to_the_remixvm/README.md new file mode 100644 index 000000000..8035d631b --- /dev/null +++ b/locales/ru/Basics/deploy_to_the_remixvm/README.md @@ -0,0 +1,15 @@ +In the previous chapter, we compiled a contract - which is to say the Solidity code has been transformed into little chunks of Ethereum Virtual Machine (EVM) bytecode. + +Now we will put that code on a test blockchain. + +1. Click the Deploy and Run icon ![deploy & run icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_to_the_remixvm/images/run.png "deploy & run icon"). + +2. Select one of the **Remix VM**s from the **Environment** pulldown. + +3. Click the Deploy button (or the transact button in the expanded view). + +4. You have deployed your compiled contract to the Remix VM - a simulated blockchain that is running inside of your browser window. The Remix VM is simple, fast test chain. It is not that realistic because you don't need to approve each transaction. + +5. Check the terminal to see detail of this deployment transaction. + +You can also use Remix to deploy to other public EVM chains. To do this, you'll need to connect to a different **Environment** - like Injected Provider. The Injected Provider connects Remix to browser wallet (like MetaMask or similar). We'll try deploying to a public network at the end of this tutorial. But before we get there, we'll cover how to interact with a deployed contract's functions. diff --git a/locales/ru/Basics/interacting/README.md b/locales/ru/Basics/interacting/README.md new file mode 100644 index 000000000..59ef44200 --- /dev/null +++ b/locales/ru/Basics/interacting/README.md @@ -0,0 +1,19 @@ +## Accessing functions in a deployed contract + +1. When a contract has been successfully deployed, it will appear at the bottom of the Deploy and Run plugin. Open up the contract by clicking the caret - so the caret points down. + ![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/instance.png "deployed contract") + +2. There are 2 functions in this contract. To input the parameters individually, clicking the caret to the right of changeOwner (outlined in red below). In the expanded view, each parameter has its own input box. + +![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/deployed_open2.png "deployed contract") + +If this contract had imported other contracts, then the functions of the imported contracts would also be visible here. At some point, try playing with An ERC20 contract to see all its many functions. + +3. Functions with blue buttons are either **pure** or **view** functions. This means that they are just reading a property or are returning a value. In other words, they aren't saving anything - so they are FREE (they don’t cost gas). Functions with other colors - usually orange (depending on the Remix theme) cost gas because they are saving information. They are creating a **transaction**. + +4. 2_Owner.sol does not have a **payable** function. If it did, the button's color would be red. Payable functions allow you to send Ether to the function. To send ETH with a payable function, you put the amount you want to send in the **value** field towards the top of the Deploy & Run module. + +5. In the Remix VM, you don't need to approve a transaction. When using a more realistic test environment or when using the mainnet - you will need to approve the transactions for them to go through. Approving a transaction costs gas. + +6. Choosing a public network is not done in Remix but in your Browser Wallet. There is a plug icon to the right of the Environment title that links to chainlist.org where you can get the specs of the chain you want to interact with. + ![chainlist](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/chainlist.png "chainlist") diff --git a/locales/ru/Basics/interface_introduction/README.md b/locales/ru/Basics/interface_introduction/README.md new file mode 100644 index 000000000..76c953fbd --- /dev/null +++ b/locales/ru/Basics/interface_introduction/README.md @@ -0,0 +1,15 @@ +## Remix is composed of four panels. + +![Remix layout](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/a-layout1c.png "Remix layout") + +- Most plugins appear in the **Side Panel**. +- Editing code happens in tabs in the **Main Panel**. +- The results of transactions and other actions are visible in the **Terminal**. +- Switching between plugins happens in the **Icons Panel**. +- To make a panel larger, drag its border. + +Try clicking the **Solidity Compiler** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/solidity-icon.png) in the **Icons Panel**. Then click the **Deploy & Run** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/deploy-run.png). Then come back to **LearnEth** by clicking this icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/learneth.png). + +In the **Main Panel** of Remix, make sure you see the **Home** tab. The **Home** tab has lots of useful links. To navigate there, either click the **Home** tab in the **Main Panel** or click the Remix icon ![Remix icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/remix-logo.png "Remix icon") on the top of the icon panel. + +- See all the plugins in the **Plugin Manager**. Click this icon ![plugin manager](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/plugin1.png "Plugin Manager icon") in the lower left corner Remix. diff --git a/locales/ru/Basics/load_and_compile/README.md b/locales/ru/Basics/load_and_compile/README.md new file mode 100644 index 000000000..a666d5d13 --- /dev/null +++ b/locales/ru/Basics/load_and_compile/README.md @@ -0,0 +1,20 @@ +Let's load a file from the File Explorer into the Editor. + +1. In the icon panel, click ![file explorer icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/files1.png "file explorer icon") , the File Explorer's icon. + +2. Make sure you are in the **default_workspace**. + +![default workspace](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/default_workspace_open.png) + +3. Open the contracts folder and click on **2_Owner.sol** in the contracts folder. Click it. The file will appear in a tab in the main panel. + +4. In the icon panel, click the **Solidity Compiler** ![solidity compiler icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/solidity1.png "solidity compiler icon"). The Solidity compiler should now be in the side panel. + +5. Click the compile button. + ![compile 2\_owner](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/compile2owner.png "compile 2_Owner") + +6. Compiling can also be triggered by hitting **CTRL + S**. + +The spinner will turn while the file is compiling. + +**Note:** The spinner also turns when the compiler itself is loading. To choose a **different version of Solidity**, go to the select box at the top of the plugin. diff --git a/locales/ru/Basics/workspaces/README.md b/locales/ru/Basics/workspaces/README.md new file mode 100644 index 000000000..97a47d283 --- /dev/null +++ b/locales/ru/Basics/workspaces/README.md @@ -0,0 +1,23 @@ +## Workspaces help organize your separate projects. + +If this is your first time to Remix, a Workspace named **default_workspace** is loaded in the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/default_workspace.png) + +The **default_workspace** has three Solidity (.sol) files in the contracts folder. Remix has a number of other templates. When you load a template, it goes into a Workspace. To go between Workspaces, use the select box at the top of the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/select-box.png) + +But Workspaces are not only for templates. When cloning a repo into Remix, the files will be put into a Workspace. + +Let's create a new Workspace + +1. At the top of the File Explorer, click the hamburger icon (the 3 horizontal lines). Read through the commands and tools in this menu. + +2. Select **+ Create** (the first choice). + +3. In the modal the comes up, choose one of the templates. + +![hamburger](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/workspaces/images/popup.png) + +Notice that in this popup menu, you can clone a repo. Managing a Git repo happens in the DGit plugin. You can also create Github actions with the three workflow choices in the popup menu. diff --git a/locales/ru/CircomHashChecker/README.md b/locales/ru/CircomHashChecker/README.md new file mode 100644 index 000000000..20391a668 --- /dev/null +++ b/locales/ru/CircomHashChecker/README.md @@ -0,0 +1,14 @@ +Hash Checker Tutorial + +This tutorial guides you through creating and understanding a Hash Checker circuit using Remix-IDE. You'll learn how to generate the circuit using a template, explore the code, perform a trusted setup, generate proofs, and verify them. This tutorial is suitable for beginners familiar with Circom and Zero-Knowledge Proofs. + +Prerequisites + +``` +Basic understanding of Zero-Knowledge Proofs and Circom. +Familiarity with Remix-IDE. +``` + +Estimated Time + +Approximately 1-2 hours. diff --git a/locales/ru/CircomHashChecker/config.yml b/locales/ru/CircomHashChecker/config.yml new file mode 100644 index 000000000..2c2aae80a --- /dev/null +++ b/locales/ru/CircomHashChecker/config.yml @@ -0,0 +1,35 @@ +id: circom-hash-checker +name: Hash Checker Tutorial +summary: A tutorial on creating and understanding a Hash Checker circuit using Remix-IDE templates, including trusted setup and proof generation. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction to the Hash Checker Circuit + path: step-1 + - + name: Generating the Hash Checker Template in Remix-IDE + path: step-2 + - + name: Exploring calculate_hash.circom + path: step-3 + - + name: Compiling the Circuit + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Compute Witness + path: step-6 + - + name: Generate Proof + path: step-7 + - + name: Exploring the Trusted Setup Script (Optional) + path: step-8 + - + name: Exploring the Proof Generation Script (Optional) + path: step-9 diff --git a/locales/ru/CircomHashChecker/step-1/README.md b/locales/ru/CircomHashChecker/step-1/README.md new file mode 100644 index 000000000..be922e93b --- /dev/null +++ b/locales/ru/CircomHashChecker/step-1/README.md @@ -0,0 +1,8 @@ +In this tutorial, we'll explore the **Hash Checker** circuit, a zero-knowledge proof (ZKP) application using Circom and Remix-IDE. The Hash Checker circuit allows you to prove knowledge of certain inputs that hash to a given value without revealing the inputs themselves. + +### What You'll Learn + +- How to generate a Hash Checker circuit using Remix-IDE's workspace templates. +- Understanding the Circom code for hashing and checking hashes. +- Performing a trusted setup using Groth16. +- Generating zero-knowledge proofs. diff --git a/locales/ru/CircomHashChecker/step-2/README.md b/locales/ru/CircomHashChecker/step-2/README.md new file mode 100644 index 000000000..bc827019e --- /dev/null +++ b/locales/ru/CircomHashChecker/step-2/README.md @@ -0,0 +1,37 @@ +Follow these steps to create the Hash Checker workspace in Remix-IDE. + +### Step 1: Access the Workspace Templates + +1. In the **File Explorer** sidebar, click on the **hamburger menu icon** (three horizontal lines). + + hamburger-menu + +2. Select **"Create Using Template"** from the dropdown. + + create-using-template + +### Step 2: Find the Hash Checker Template + +1. In the main panel, scroll down to the **"Circom ZKP"** section. + + create-zkp-section + +2. Locate the **"Hash Checker"** item. + +### Step 3: Create the Workspace + +1. Click on the **"Create"** button on the Hash Checker item. + + create-hash-checker + +2. In the modal pop-up, provide a **workspace name** (e.g., `hash-checker-workspace`). + + workspace-name-modal + +3. Click **"OK"** to create the template. + +### Result + +- The workspace is created with the necessary files and directories. + + workspace-name-modal diff --git a/locales/ru/CircomHashChecker/step-3/README.md b/locales/ru/CircomHashChecker/step-3/README.md new file mode 100644 index 000000000..b3ac14050 --- /dev/null +++ b/locales/ru/CircomHashChecker/step-3/README.md @@ -0,0 +1,32 @@ +## Exploring `calculate_hash.circom` + +Navigate to the `circuits` directory and open `calculate_hash.circom`. This file contains the Circom code for the Hash Checker circuit. + +### Code Breakdown + +#### Pragma and Includes: + +- `pragma circom 2.0.0;` specifies the Circom version. +- `include "circomlib/circuits/poseidon.circom";` fetch and includes the Poseidon hash function from [CircomLib](https://github.com/iden3/circomlib). + +#### `CalculateHash` Template: + +- Defines inputs `value1`, `value2`, `value3`, `value4`. +- Uses the `Poseidon` hash function to compute a hash of these values.\ +- Outputs `out`, which is the hash. + +#### `HashChecker` Template: + +- Inputs are the same values plus a `hash`. +- Instantiates `CalculateHash` as `calculateSecret`. +- Computes `calculatedHash`. +- Uses `assert(hash == calculatedHash);` to ensure the provided hash matches the calculated hash. + +#### Main Component: + +- `component main {public [hash]} = HashChecker();` +- Specifies that `hash` is a `public` input, while the values are `private`. + +### Purpose + +The circuit allows someone to prove they know `value1`, `value2`, `value3`, and `value4` that hash to a specific `hash` without revealing the values themselves. diff --git a/locales/ru/CircomHashChecker/step-4/README.md b/locales/ru/CircomHashChecker/step-4/README.md new file mode 100644 index 000000000..537c6a241 --- /dev/null +++ b/locales/ru/CircomHashChecker/step-4/README.md @@ -0,0 +1,32 @@ +## Compiling the Circuit + +### Selecting the Compiler Version + +1. Go to the **Circuit Compiler** plugin in the sidebar. +2. Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +### Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +### Compiling the Circuit + +1. Click on the **Compile** button. +2. Wait for the compilation to complete. A success badge will appear if compilation is successful. + +compilation-success + +### Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/ru/CircomHashChecker/step-5/README.md b/locales/ru/CircomHashChecker/step-5/README.md new file mode 100644 index 000000000..c3ea8509b --- /dev/null +++ b/locales/ru/CircomHashChecker/step-5/README.md @@ -0,0 +1,25 @@ +## Performing a Trusted Setup + +1. **Access the Setup and Exports Section**: + +- After successful compilation, the **Setup and Exports** section becomes available in the plugin. + +2. **Select Proving Scheme**: + +- Choose **Groth16** from the **Proving Scheme** dropdown. + +3. **Select Power of Tau File**: + +- Choose the appropriate **Power of Tau** file from the dropdown. If unsure, use the default option. + +4. **Export Verification Key and Contract** (optional): + +- Enable **Export Verification Key** to save the verification key to the File Explorer. +- Enable **Export Verifier Contract** to save the Solidity contract for on-chain verification. + +trusted-setup + +5. **Run the Trusted Setup**: + +- Click on the **Run Setup** button. +- Wait for the process to complete. This may take some time depending on the circuit complexity. diff --git a/locales/ru/CircomHashChecker/step-6/README.md b/locales/ru/CircomHashChecker/step-6/README.md new file mode 100644 index 000000000..03b848f81 --- /dev/null +++ b/locales/ru/CircomHashChecker/step-6/README.md @@ -0,0 +1,28 @@ +## Compute Witness + +1. **Access the Compute Witness Section**: + - After the trusted setup, the **Compute Witness** section becomes available. + +2. **Input Values**: + - You'll see input fields for `value1`, `value2`, `value3`, `value4`, and `hash`. + - Enter values for each input. For example: + - `value1`: `1234` + - `value2`: `2` + - `value3`: `3` + - `value4`: `4` + +3. **Calculate the Hash**: + + - Compute the Poseidon hash of the four values using an external tool or library compatible with the Poseidon hash function. + - For the values above, here is the computed Poseidon hash `16382790289988537028417564277589554649233048801038362947503054340165041751802`. + - Enter the calculated `hash` value in the `hash` input field. + + compute-witness + +4. **Compute the Witness**: + + - Click on the **Compute Witness** button. + - Wait for the process to complete. A success badge will appear if the witness is computed successfully. + - If successful, you'll see `calculate_hash.wtn` created in the `.bin` directory in the file explorer. + + witness-computed diff --git a/locales/ru/CircomHashChecker/step-7/README.md b/locales/ru/CircomHashChecker/step-7/README.md new file mode 100644 index 000000000..e6ae80fea --- /dev/null +++ b/locales/ru/CircomHashChecker/step-7/README.md @@ -0,0 +1,21 @@ +## Generate Proof + +1. **Access the Generate Proof Section**: + - After computing the witness, expand the **Generate Proof** section. + +2. **Configure Proof Generation**: + - **Export Verifier Calldata**: Enable this option if you plan to verify the proof on-chain. + +3. **Generate the Proof**: + + - Click on the **Generate Proof** button. + - Wait for the proof generation to complete. + + generate-proof + +4. **View the Proof**: + + - The proof data will be displayed in the File Explorer. + - **Congratulations!** You've successfully compiled the `Hash Checker` circuit, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + + generate-proof diff --git a/locales/ru/CircomHashChecker/step-8/README.md b/locales/ru/CircomHashChecker/step-8/README.md new file mode 100644 index 000000000..e489a8cab --- /dev/null +++ b/locales/ru/CircomHashChecker/step-8/README.md @@ -0,0 +1,34 @@ +## Understanding `groth16_trusted_setup.ts` + +Navigate to `scripts/groth16/groth16_trusted_setup.ts`. This script performs the trusted setup necessary for generating proofs. + +### Code Breakdown + +#### Circuit Compilation: + +- Uses `remix.call('circuit-compiler', 'generateR1cs', ...)` to generate `R1CS` (Rank-1 Constraint System) from the circuit. + +#### Trusted Setup Steps: + +- `snarkjs.zKey.newZKey`: Initializes the proving key (`zkey_0`). +- `snarkjs.zKey.contribute`: Adds contributions to the proving key (`zkey_1`). +- `snarkjs.zKey.beacon`: Finalizes the proving key (`zkey_final`). + +#### Verification: + +- `snarkjs.zKey.verifyFromR1cs`: Verifies the proving key against the `R1CS` and initial parameters. + +#### Exporting Keys: + +- Exports the verification key to `scripts/groth16/zk/keys/verification_key.json`. +- Exports the final proving key (`scripts/groth16/zk/keys/zkey_final.txt`). + +### Purpose + +- Performs the trusted setup required for the `Groth16` proving system. +- Generates the necessary keys for proof generation and verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"setup done."` logged in the terminal. diff --git a/locales/ru/CircomHashChecker/step-9/README.md b/locales/ru/CircomHashChecker/step-9/README.md new file mode 100644 index 000000000..653d5ced1 --- /dev/null +++ b/locales/ru/CircomHashChecker/step-9/README.md @@ -0,0 +1,37 @@ +## Understanding `groth16_zkproof.ts` + +Navigate to `scripts/groth16/groth16_zkproof.ts`. This script generates the zero-knowledge proof and prepares it for verification. + +### Code Overview + +#### Loading Files: + +- Reads the R1CS and WASM files generated from the circuit. +- Loads the final proving key (`zkey_final`) and verification key (`vKey`). + +#### Defining Inputs: + +- Sets the private values (`value1`, `value2`, `value3`, `value4`). +- Computes the `hash` using Poseidon from [CircomLib](https://github.com/iden3/circomlib). + +#### Witness Calculation and Proof Generation: + +- Calculates the witness (`wtns`). +- Checks the witness against the `R1CS`. +- Generates the proof using `Groth16`. +- Verifies the proof. + +#### Exporting Verifier Contract and Inputs: + +- Generates a Solidity verifier contract. +- Exports the proof inputs to `input.json`. + +### Purpose + +- Generates a zero-knowledge proof that the prover knows values hashing to a specific hash. +- Prepares the verifier contract and inputs for on-chain verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"zk proof validity"` logged in the terminal. diff --git a/locales/ru/CircomIntro/README.md b/locales/ru/CircomIntro/README.md new file mode 100644 index 000000000..c58b2daec --- /dev/null +++ b/locales/ru/CircomIntro/README.md @@ -0,0 +1,21 @@ +Intro to Circom + +This is an introduction to Circom. You'll learn how to write, compile, and test arithmetic circuits in Circom. We'll go over how to do this within Remix-IDE. + +Tutorial Overview + +``` +Step 1: Introduction +Step 2: Setting Up Remix-IDE and Installing the Circuit-Compiler Plugin +Step 3: Writing Your First Circom Circuit +Step 4: Compiling the Circuit Using the Plugin +Step 5: Performing a Trusted Setup +Step 6: Computing the Witness +Step 7: Generating the Proof +``` + +Prerequisites: + +``` +Basic understanding of cryptography and zero-knowledge proofs is helpful but not required. +``` diff --git a/locales/ru/CircomIntro/config.yml b/locales/ru/CircomIntro/config.yml new file mode 100644 index 000000000..d6dfdca46 --- /dev/null +++ b/locales/ru/CircomIntro/config.yml @@ -0,0 +1,29 @@ +id: circom-intro +name: Intro to Circom +summary: A intro to using Circom for creating arithmetic circuits. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction + path: step-1 + - + name: Installing the Circuit-Compiler + path: step-2 + - + name: Writing Your First Circom Circuit + path: step-3 + - + name: Compiling the Circuit Using the Plugin + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Computing the Witness + path: step-6 + - + name: Generating the Proof + path: step-7 diff --git a/locales/ru/CircomIntro/step-1/README.md b/locales/ru/CircomIntro/step-1/README.md new file mode 100644 index 000000000..0766ce6f4 --- /dev/null +++ b/locales/ru/CircomIntro/step-1/README.md @@ -0,0 +1,13 @@ +Welcome to this beginner-level tutorial on Circom using Remix. In this tutorial, you'll learn the basics of Circom, a domain-specific language used for creating arithmetic circuits. + +**What is Circom?** + +Circom is a language designed for writing arithmetic circuits that can be used in zero-knowledge proofs, particularly zk-SNARKs. It allows developers to define complex mathematical circuits that can prove knowledge of certain data without revealing it. + +**Why Use Remix-IDE for Circom?** + +- **Ease of Use:** Remix-IDE provides a user-friendly interface that simplifies the development process. +- **Integrated Tools:** With plugins like `circuit-compiler`, you can compile Circom code, perform trusted setups, compute witnesses, and generate proofs all within the same environment. +- **No Installation Required:** As a web-based IDE, you can start coding immediately without setting up a local development environment. + +In the next steps, we'll guide you through setting up Remix-IDE for Circom development and help you write your first circuit. diff --git a/locales/ru/CircomIntro/step-2/README.md b/locales/ru/CircomIntro/step-2/README.md new file mode 100644 index 000000000..4b228c298 --- /dev/null +++ b/locales/ru/CircomIntro/step-2/README.md @@ -0,0 +1,25 @@ +In this step, we'll set up Remix for Circom development by activating the `Circom ZKP compiler` plugin. + +## Activating the Circom ZKP compiler + +1. At the bottom of the icon panel on the left of the screen, click on the **Plugin Manager** (the plug icon). + 2.In the search bar, type **Circom**. +2. Find the **Circuit Compiler** plugin in the list and click on the **Activate** button. +3. The plugin will now appear in your sidebar. + +install-plugin + +## The Circom Compiler Interface + +- **Compiler Version Dropdown:** Select the Circom compiler version you wish to use. +- **Auto Compile Checkbox:** Enable this to automatically compile your circuit whenever you make changes. +- **Hide Warnings Checkbox:** Enable this to suppress compiler warnings. +- **Advanced Configuration:** Click to expand options for selecting the prime field (e.g., BN128, BLS12381). + +compiler-interface + +With the plugin installed, you're now ready to start writing Circom code in Remix-IDE. + +**Note:** Make sure your internet connection is stable, as Remix-IDE is a web-based tool. + +In the next step, we'll write our first Circom circuit. diff --git a/locales/ru/CircomIntro/step-3/README.md b/locales/ru/CircomIntro/step-3/README.md new file mode 100644 index 000000000..6424668f6 --- /dev/null +++ b/locales/ru/CircomIntro/step-3/README.md @@ -0,0 +1,38 @@ +Let's write a simple Circom circuit. + +## Creating a New Circuit File + +1. In the **File Explorer** on the left sidebar, click on the **Create New File** icon. +2. Name your file `multiplier.circom` and press **Enter**. + +create-new-file + +## Writing the Circuit + +Open `multiplier.circom` and add the following code: + +```circom +pragma circom 2.0.0; + +template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; +} + +component main = Multiplier(); +``` + +## Explanation: + +- template `Multiplier()`: Defines a new circuit template called Multiplier. +- `signal input a;` and `signal input b;`: Declare input signals a and b. +- `signal output c;`: Declare an output signal c. +- `c <== a * b;`: Constrain c to be the product of a and b. +- `component main = Multiplier();`: Instantiates the Multiplier circuit as main, which is required for the compiler. + +### NB: + +Signals are values in a cryptographic circuit that are strictly determined by the circuit's equations and constraints. Think of a signal as a value that must follow specific mathematical rules defined by the circuit—once set, it can't be changed arbitrarily. In regular programming, variables are flexible and can be updated or reassigned as needed, whereas, signals can't be altered freely. diff --git a/locales/ru/CircomIntro/step-4/README.md b/locales/ru/CircomIntro/step-4/README.md new file mode 100644 index 000000000..ad3f2a089 --- /dev/null +++ b/locales/ru/CircomIntro/step-4/README.md @@ -0,0 +1,34 @@ +With your `multiplier.circom` circuit ready, let's compile it using the Circuit Compiler plugin. + +## Selecting the Compiler Version + +Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +## Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +## Compiling the Circuit + +1. Click on the **Compile** button. +2. The compiler will process your circuit. +3. If successful, you'll see a compilation success message. + +compilation-success + +**Note:** If there are any errors, they will be displayed in the console. Check your code for typos or syntax errors. + +## Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/ru/CircomIntro/step-5/README.md b/locales/ru/CircomIntro/step-5/README.md new file mode 100644 index 000000000..8e8496bbd --- /dev/null +++ b/locales/ru/CircomIntro/step-5/README.md @@ -0,0 +1,26 @@ +After compiling your circuit, you need to perform a trusted setup to generate proving and verification keys. + +## Understanding Trusted Setup + +- **Trusted Setup:** A process required for zk-SNARKs to generate the necessary parameters for proof generation and verification. +- You can choose between different protocols like **Groth16** and **Plonk**. + +## Performing the Trusted Setup + +1. In the **Setup and Exports** section, select the **Proving Scheme**: + - Choose between **Groth16** or **Plonk**. We'll use **Groth16** for this tutorial. + +2. Choose the appropriate **Power of Tau** file from the dropdown. This file is necessary for the trusted setup. + - If unsure, select the default option. + +3. Click on the **Setup** button to start the trusted setup process. + +4. You can enable **Export Verification Key** to get the verification parameters. + +5. You can enable **Export Verification Contract** if you intend to verify proofs on-chain. + +trusted-setup + +**Note:** The trusted setup may take some time, depending on the complexity of your circuit. + +In the next step, we'll compute the witness for our circuit. diff --git a/locales/ru/CircomIntro/step-6/README.md b/locales/ru/CircomIntro/step-6/README.md new file mode 100644 index 000000000..e13d33d32 --- /dev/null +++ b/locales/ru/CircomIntro/step-6/README.md @@ -0,0 +1,27 @@ +With the trusted setup complete, you can now compute the witness for your circuit based on specific inputs. + +## What is a Witness? + +- A **Witness** is a set of values that satisfy all the constraints of your circuit. It includes all the intermediate numbers and results that satisfy the circuit's rules. The witness is used in zero-knowledge proofs to demonstrate that you know a valid solution to the problem without actually showing the solution itself. This allows others to verify that you did everything correctly while keeping your specific numbers and calculations private. +- It is essential for generating a proof. + +## Inputting Values + +1. In the **Compute Witness** section, you'll see input fields dynamically generated based on your circuit's inputs. +2. Enter values for `a` and `b`. For example: + - `a = 3` + - `b = 4` + +compute-witness + +## Computing the Witness + +1. After entering the inputs, click on the **Compute Witness** button. +2. The plugin will compute the witness based on your inputs. +3. If successful, you'll see `multiplier.wtn` created in the `.bin` directory in the file explorer. + +witness-computed + +**Note:** If there are any errors, ensure that your inputs are valid and satisfy the circuit's constraints. + +In the next step, we'll generate a proof using the computed witness. diff --git a/locales/ru/CircomIntro/step-7/README.md b/locales/ru/CircomIntro/step-7/README.md new file mode 100644 index 000000000..f5cf332a9 --- /dev/null +++ b/locales/ru/CircomIntro/step-7/README.md @@ -0,0 +1,31 @@ +With the witness computed, the final step is to generate a proof that can be verified by others. + +## Generating the Proof + +1. In the **Generate Proof** section, you have the option to **Export Verifier Calldata**. + - Enable the **Export Verifier Calldata** checkbox if you plan to verify the proof on-chain. +2. Click on the **Generate Proof** button. + +generate-proof + +## Understanding the Output + +- After generating the proof, the plugin will display the proof data. +- If you enabled **Export Verifier Calldata**, it will also provide the calldata needed for on-chain verification. + +proof-generated + +## Next Steps + +- **Verification:** You can use the verification key or contract exported earlier to verify the proof. +- **On-Chain Verification:** If you're familiar with smart contracts, you can deploy the verification contract and use the calldata to perform on-chain verification. + +**Congratulations!** You've successfully written a Circom circuit, compiled it, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + +## Additional Resources + +- [Circom Documentation](https://docs.circom.io/) +- [Remix-IDE Documentation](https://remix-ide.readthedocs.io/) +- [Zero-Knowledge Proofs Explained](https://zkproof.org/) + +Feel free to experiment with more complex circuits and explore the capabilities of Circom and Remix-IDE further. diff --git a/locales/ru/DeployWithLibraries/1_Writing_a_Library/step1.md b/locales/ru/DeployWithLibraries/1_Writing_a_Library/step1.md new file mode 100644 index 000000000..1ad984835 --- /dev/null +++ b/locales/ru/DeployWithLibraries/1_Writing_a_Library/step1.md @@ -0,0 +1,17 @@ +A libraries looks like a **contract** but use the keyword `library` + +A library typically is a collection of useful functions sitting out there on the blockchain that any contract can use. Because the library is already deployed, it saves the deployment costs of the many contracts that use it. + +In the following contract: + +- Make a library with the name `LibraryForTest`. + +It is possible to put a library in same file with another contract. So put the library below the contract. + +This library should have a method called `getFromLib` method which returns `3`. + +- Update the `get` method in the `test` contract to use the `LibraryForTest` library. The function `get` should return the value it receives from `getFromLib`. + +--------- + +You can find more info about libraries in this section of the Solidity Docs. diff --git a/locales/ru/DeployWithLibraries/2_Generate_Metadata/step2.md b/locales/ru/DeployWithLibraries/2_Generate_Metadata/step2.md new file mode 100644 index 000000000..218c86ff9 --- /dev/null +++ b/locales/ru/DeployWithLibraries/2_Generate_Metadata/step2.md @@ -0,0 +1,38 @@ +## Deploying Library + +The **library** from the previous chapter was in the same file as the **contract**. However, they won't be deployed together and will have different addresses. + +In order to use a library, the calling contract must have the library's **address**. + +But the library's address is not directly specified in the solidity code. The calling contract's compiled bytecode contains a **placeholder** where library's **addresses** will go. + +At deployment of the **calling contract**, Remix will look in the contract's **metadata** for the library's address and will update the placeholder with the address. + +So before deploying a contract that calls a library, you need to generate the contract's metadata (AKA its **build artifact**) and then you need to input the library's address into the metadata file. + +A contract's metadata is generated at **compile time**. + +Let's setup Remix to generate the **metadata file**. + +- Go to the settings module by clicking on the settings ![settings](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/settings.png "Settings") icon in the icon panel. + +![settings module](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_settings.png "Settings Module") + +- And check the first option `Generate contract metadata`. + +# Compile and generate metadata (JSON) file. + +1. Open the Solidity Compiler ![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +2. Compile `2_contractSimpleLibrary.sol`. + +3. Switch to the File Explorer ![File Explorer](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_file_explorer.png "File Explorer") + +4. Navigate to the newly create JSON files. + - It should be in the folder: + +**browser/.learneth/DeployWithLibraries/2_Generate_Metadata/artifacts/** + +5. Select the newly created JSON file created from the contract. It has the **same name** as the contract `sample` but with the extension **json**: `sample.json` (don't select the library's metadata `contractSimpleLibrary.json`). + +In the next step we'll make some adjustments to the metadata file. diff --git a/locales/ru/DeployWithLibraries/3_Edit_Metadata/step3.md b/locales/ru/DeployWithLibraries/3_Edit_Metadata/step3.md new file mode 100644 index 000000000..1555d645d --- /dev/null +++ b/locales/ru/DeployWithLibraries/3_Edit_Metadata/step3.md @@ -0,0 +1,12 @@ +The `Deploy` property in `sampleContract.json` contains everything you need for telling Remix IDE the address of the library for a specific network. + +- `
` contains the address of the library that is already deployed. You have to specify this address for each network. +- `autoDeployLib` is a boolean and tells Remix IDE if it should autodeploy the library before deploying the contract. + +Basically if `autoDeployLib` is **true**, the `
` will not be used and Remix will automatically deploy the library before deploying the contract. + +For the purpose of this demo - we are mimicking a situation where the library has already been deployed because this is a more common situation. + +So set `autoDeploy` to **false**, for the `VM:-` entry. + +Move to next Step. diff --git a/locales/ru/DeployWithLibraries/4_Linking_and_Deploying/step4.md b/locales/ru/DeployWithLibraries/4_Linking_and_Deploying/step4.md new file mode 100644 index 000000000..ad5f52e2d --- /dev/null +++ b/locales/ru/DeployWithLibraries/4_Linking_and_Deploying/step4.md @@ -0,0 +1,25 @@ +Switch to the `Deploy & Run` module +![Run transaction](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/remix_runtransaction.png "Run Transaction") + +- Select the Remix VM Environment and select the `sampleContract` contract in the list of compiled contracts. + +- Click on `Deploy` + +The terminal should output something like `creation of sample errored:
is not a valid address. Please check the provided address is valid.` +That is expected: **We have set `autoDeployLib` to false, so Remix expects to have an address and not just `
`** + +So we need deploy the library to get its address. + +- Select the library `aLib` in the list of compiled contract and hit `deploy` + + ![Choose aLib](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/contract_alib.png "Choose aLib") + +- Click the clipboard icon to copy the address of the library. + + ![Copy lib1](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/alib_copy.png "Copy") + +- Paste it into the **contract sample's** metadata JSON. + +- Reselect the `sampleContract` contract in the `Run transaction` module and hit deploy. + +- Deploy should now be successful. diff --git a/locales/ru/DeployWithLibraries/5_Under_The_Hood/step5.md b/locales/ru/DeployWithLibraries/5_Under_The_Hood/step5.md new file mode 100644 index 000000000..860b48b24 --- /dev/null +++ b/locales/ru/DeployWithLibraries/5_Under_The_Hood/step5.md @@ -0,0 +1,30 @@ +Switch to the `Solidity compiler` module +![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +- Select the `sampleContract` contract in the list of compiled contracts. +- click on `ByteCode`, it should copy the following to the clipboard: + +``` +{ + "linkReferences": { + "browser/contractSimpleLibrary.sol": { + "lib1": [ + { + "length": 20, + "start": 115 + } + ] + } + }, + "object": "608060405234801561001057600080fd5b5060f68061001f6000396000f3fe6080604052600436106039576000357c0100000000000000000000000000000000000000000000000000000000900480636d4ce63c14603e575b600080fd5b348015604957600080fd5b5060506052565b005b73__$d42d70ba92b626965f4c69b39148e37a33$__63fea24e5f6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801560b157600080fd5b505af415801560c4573d6000803e3d6000fd5b5050505056fea165627a7a7230582068c9a3a9a5cbfd26cfdab2534abfc926912d9b89eaa14e36c8248b7e7eb0ab090029", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xF6 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x39 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x3E JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x50 PUSH1 0x52 JUMP JUMPDEST STOP JUMPDEST PUSH20 0x0 PUSH4 0xFEA24E5F PUSH1 0x40 MLOAD DUP2 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH1 0xB1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS DELEGATECALL ISZERO DUP1 ISZERO PUSH1 0xC4 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 PUSH9 0xC9A3A9A5CBFD26CFDA 0xb2 MSTORE8 0x4a 0xbf 0xc9 0x26 SWAP2 0x2d SWAP12 DUP10 0xea LOG1 0x4e CALLDATASIZE 0xc8 0x24 DUP12 PUSH31 0x7EB0AB09002900000000000000000000000000000000000000000000000000 ", + "sourceMap": "63:85:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63:85:0;;;;;;;" +} +``` + +This is basically what the compiler is returning: + +- `linkReferences` describes what are the libraries used by the contract. +- `object` is the compiled contract (bytecode). This is what gets deployed and saved onto the blockchain. In this example, the value `__$d42d70ba92b626965f4c69b39148e37a33$__` inside the bytecode is just a placeholder for the library address. In your case, the placeholder will be between `__$` and `$__`. + +The metadata JSON from Remix IDE tells Remix to replace the placeholder with the given address. diff --git a/locales/ru/DeployWithLibraries/README.md b/locales/ru/DeployWithLibraries/README.md new file mode 100644 index 000000000..fb31b1264 --- /dev/null +++ b/locales/ru/DeployWithLibraries/README.md @@ -0,0 +1,3 @@ +**Libraries** are deployed contracts that do not store state and are used by other contracts to decrease their size and thus their deployment costs. + +Learn to work with **Libraries** in Remix - you won't need to whisper. diff --git a/locales/ru/DeployWithLibraries/config.yml b/locales/ru/DeployWithLibraries/config.yml new file mode 100644 index 000000000..0816e2346 --- /dev/null +++ b/locales/ru/DeployWithLibraries/config.yml @@ -0,0 +1,8 @@ +--- +id: deploylibraries +name: Deploy with Libraries +summary: Write, Deploy and link a Library to a Contract +level: 3 +tags: + - Remix + - Solidity diff --git a/locales/ru/ERC20TokenCourse/README.md b/locales/ru/ERC20TokenCourse/README.md new file mode 100644 index 000000000..25a6ccf95 --- /dev/null +++ b/locales/ru/ERC20TokenCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Token Course + +Learn to understand and create ERC20 tokens. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ru/ERC20TokenCourse/config.yml b/locales/ru/ERC20TokenCourse/config.yml new file mode 100644 index 000000000..8c12a5213 --- /dev/null +++ b/locales/ru/ERC20TokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: tokenCourse +name: Solidity ERC20 Token Course +summary: Learn how to create your own ERC20 tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - ERC20 +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc20-interface + - + name: 3. Token Creation + path: erc20-token-creation + - + name: 4. Interaction + path: erc20-interaction + - + name: 5. Testnet Deployment + path: erc20-testnet-deployment + - + name: 6. Extensions + path: erc20-extensions diff --git a/locales/ru/ERC20TokenCourse/erc20-extensions/erc20extensions.md b/locales/ru/ERC20TokenCourse/erc20-extensions/erc20extensions.md new file mode 100644 index 000000000..b3649fbba --- /dev/null +++ b/locales/ru/ERC20TokenCourse/erc20-extensions/erc20extensions.md @@ -0,0 +1,33 @@ +The ERC20 standard only describes the required and optional functionality that your contract needs, but you can add additional functionality. + +In this section, we added the functionality to burn and mint tokens, as well as the ability to pause the contract, by using OpenZeppelin extensions. + +Of course, you can write your own ERC20 token contract implementation or extensions and import them into your contract. But OpenZeppelin contracts have been audited by security experts and are a great way to add desired functionality. + +### Mintable + +The mint function allows the creator of the contract to mint (create) additional tokens after the contract has been deployed (line 22). As input parameters, the function needs the address that the tokens will be minted to, and the amount of tokens that should be minted. + +We don't have to import `mint()` from another contract since the mint function is already part of the ERC20 contract implementation of OpenZeppelin. We import `Ownable` (line 7) which is a contract module that provides a basic access control mechanism that allows an owner to have exclusive access to specific functions. In this contract, we add the inherited `onlyOwner` modifier to the `mint` function (line 22) and restrict access to this function to the "owner". + +The contract will inherit additional functions like owner(), transferOwnership() and renounceOwnership() to manage access, from the Ownable contract. + +### Burnable + +By importing the "ERC20Burnable" (line 5) and inheriting its functions (line 9) our contract allows token holders to destroy their tokens as well as the tokens in their allowance. +For more information, have a look at the ERC20Burnable contract. + +### Pausable + +With the "Pausable" contract module (line 6 and 9) the owner is able to pause (line 14) and unpause (line 18) the contract. In the pause state, tokens can't be transferred, which can be helpful in emergency scenarios. +For more information, have a look at the Pausable contract. + +Have a look at the OpenZeppelins Contract Wizard, which allows you to easily add additional functionality. + +If you successfully completed this course, try the Learneth NFT Course as the next step in your journey. + +## ⭐️ Assignment + +1. Try to mint tokens to an account after deployment. Call `totalSupply()` and `balanceOf()` to confirm the correct execution. +2. Burn tokens and then call `totalSupply()` and `balanceOf()` to confirm the correct execution. +3. Test the pause function by pausing the contract using the owner account and trying to make a transfer with a second account. The transaction should not be able to be executed and will throw the exception: "Pausable: paused". diff --git a/locales/ru/ERC20TokenCourse/erc20-interaction/er20interaction.md b/locales/ru/ERC20TokenCourse/erc20-interaction/er20interaction.md new file mode 100644 index 000000000..5c082b248 --- /dev/null +++ b/locales/ru/ERC20TokenCourse/erc20-interaction/er20interaction.md @@ -0,0 +1,87 @@ +In this section, we will deploy a contract in our browser and test its functionality. + +### 1. Deploy the contract + +**1.1** Compile your EduCoin contract in the "Solidity compiler" module of the Remix IDE. + +**1.2** In the "Deploy & run transactions" module, select your contract "EduCoin" in the contract input field and click on the "Deploy" button. Always make sure to select the correct contract in the contract selector input field. + +**GIF** Compile and deploy: Compile and deploy contract + +### 2. Test the functions + +Expand the token contract functions in the IDE. + +#### 2.1 Decimals + +Click on the "decimals" button to call the decimals() function. +It should return "18". + +#### 2.2 Name + +Click on the "name" button to call the name() function. +It should return "EduCoin". + +#### 2.3 Symbol + +Click on the "symbol" button to call the symbol() function. +It should return "EDC". + +#### 2.4 Total supply + +Click on the "totalSupply" button to call the totalSupply() function. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test decimals, name, symbol, and totalSupply functions: Test transfer function + +#### 2.5 Balance of + +**2.5.1** Go to the "ACCOUNT" section in the sidebar and copy the displayed address by using the copy icon next to it. + +**2.5.2** Paste the address in the input field next to the "balanceOf" function button and click on the button. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test balanceOf function: Test transfer function + +#### 2.6 Transfer + +We will transfer EduCoin from one account to a second account. + +**2.6.1** Go to the "ACCOUNT" section in the sidebar and click on the displayed address. This should open a dropdown. Select the second address displayed and copy its address (account 2). + +**2.6.2** Open the dropdown and select the first account again (account 1), because this is the account that we want to use to make the transfer. + +**2.6.3** Paste the address in the input field next to the "transfer" function button, input the number 500000000000000000000, and click on the button. + +**2.6.4** If you check the balances for account 1 and account 2, they should both return the amount 500000000000000000000. + +**GIF** Test transfer function: Test transfer function + +#### 2.7 Approve + +We will now allow account 1 to spend tokens on behalf of account 2. + +**2.7.1** Go to the "Account" section, copy the address of account 1, then set it to account 2 again. + +**2.7.2** In the approve function, enter the address of account 1 as the input for spender and set the amount to 250000000000000000000. + +**GIF** Test approve function: Test approve function + +#### 2.8 Allowance + +Next to the "allowance" button enter the address of account 2 as the owner and account 1 as the spender; click on the button. +It should return 1000000000000000000000. + +**GIF** Test allowance function: Test allowance function + +#### 2.9 TransferFrom + +Now account 1 will transfer 250000000000000000000 tokens from account 2 to its own account. + +**2.9.1** Select account 1 in the "ACCOUNT" section. + +**2.9.2** Next to the "transferFrom" button enter the address of account 2 as the sender and account 1 as the recipient, enter 250000000000000000000 as the amount and click on the button. + +**2.9.3** Check the balances of accounts 2 and 1, they should return 250000000000000000000 and 750000000000000000000. + +**GIF** Test transferFrom function: Test transferFrom function diff --git a/locales/ru/ERC20TokenCourse/erc20-interface/erc20interface.md b/locales/ru/ERC20TokenCourse/erc20-interface/erc20interface.md new file mode 100644 index 000000000..5c4e8137c --- /dev/null +++ b/locales/ru/ERC20TokenCourse/erc20-interface/erc20interface.md @@ -0,0 +1,76 @@ +ERC20 (Ethereum Request for Comments 20) is a standard for token contracts that manages fungible tokens on the Ethereum blockchain. + +Fungible tokens are all equal to each other and have the same value, behavior, and rights. Fungible tokens are often used as a medium of exchange, like the currencies ETH or BTC. However, they can also have other use cases like voting rights or reputation. + +If you want to know more about the ERC20 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +To get an overview of the required functionality of an ERC20 token contract, we will look at an interface that interacts with an ERC20 contract. +This interface (line 9) is part of the open-source contract library provided by OpenZeppelin. + +## ERC20 Functions + +Contracts compliant with the ERC20 standard must implement the following six functions: + +### totalSupply + +The function `totalSupply` (line 13) returns the total amount of tokens available. + +### balanceOf + +The function `balanceOf` (line 18) returns the amount of tokens owned by the account with the address `account`. + +### transfer + +The function `transfer` (line 27) transfers `amount` of tokens to the address `recipient`. +This function **must** emit (produce) a `Transfer` event (see below) and **should** throw an exception when the sender doesn't have enough tokens to make the transfer. + +### approve + +The function `approve` (line 52) creates an allowance for the address `spender` to transfer `amount` of tokens on behalf of the account calling the function. + +### allowance + +The function `allowance` (line 36) returns the amount of tokens that the address `spender` is allowed to spend on behalf of the account with the address `owner`. + +### transferFrom + +The function `transferFrom` (line 63) transfers `amount` of tokens on behalf of the address `sender` to the address `recipient`. +This function **must** emit a `Transfer` event. + +## ERC20 Events + +ERC20 contracts must also emit two events: + +### Transfer + +The `Transfer` (line 71) event must be emitted when `value` amount of tokens are transferred from the account with the address `indexed from` to `indexed to`. The parameters `from` and `to` are `indexed` allowing us to search for these events using the indexed parameters as filters. + +### Approval + +The `Approval` (line 77) event must be emitted when the account `indexed owner` approves the account `indexed spender` to transfer `value` amount of tokens on its behalf. + +## ERC20 Optional functions + +In addition to the mandatory functions and events, there are also three optional functions specified in the ERC20 standard that are not implemented in this interface: + +### name + +`function name() external view returns (string);` + +Returns the name of the token. + +### symbol + +`function symbol() external view returns (string);` + +Returns the symbol of the token. + +### decimals + +`function decimals() external view returns (uint8);` + +Returns the number of decimal places the token uses. + +You may want to use decimals to make your token divisible into arbitrary amounts like 1.5 ETH when displayed. The EVM (Ethereum virtual machine) only supports integer numbers. That's why the ERC20 standard suggests to implement the decimal functionality that specifies how many decimal places a token has. 18 decimal places is the industry standard. diff --git a/locales/ru/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md b/locales/ru/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md new file mode 100644 index 000000000..94b513922 --- /dev/null +++ b/locales/ru/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md @@ -0,0 +1,41 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to a testnet of the Ethereum blockchain. This testnet behaves very similarly to the real blockchain (mainnet), but does not require real ETH to pay for transactions. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token + +In order to make transactions on the testnet we need Ethereum testnet tokens, which you can receive from something called a _faucet_. + +**2.1** Switch your Metamask network by clicking on the "Ethereum Mainnetwork" drop down and selecting "Ropsten Test Network". If you don’t see any test networks, click on the "Show/hide" link and enable "Show test networks" in the settings. + +**2.2** Go to https://faucet.ropsten.be/, enter the address of your account, and claim testnet ETH. You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Deployment + +Make sure the EduCoin contract is compiled. + +**3.1.** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It will ask you to connect your account which you should confirm. + +**3.2** Deploy the EduCoin contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. Copy the contract address. + +**3.4** In Metamask, click on assets, then click on the "Import tokens" link, and paste the address of your contract in the input field. + +You should now see a balance of 1000 EDC in your wallet. + +### 4. Make a transaction + +**4.1** Click on the identicon (visual representation of your address) in the Metamask wallet and create a second account (Account 2). + +**4.2** Copy the address of Account 2. + +**4.3** Switch to the first account (Account 1) and send 250 EDC to Account 2. Check the balances of Account 1 and Account 2. You might need to add the token address again for Account 2 to import the tokens and you will need testeth if you want to make a transaction with this account. + +You can also see your account balances if you look at the contract in Remix and call the `balanceOf` function using the addresses of Account 1 and Account 2. diff --git a/locales/ru/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md b/locales/ru/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md new file mode 100644 index 000000000..49b71abdd --- /dev/null +++ b/locales/ru/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md @@ -0,0 +1,18 @@ +A token standard tells us what functionality the contract needs to comply with it. How this functionality is implemented is up to the developers. In this contract, we will use an ERC20 token contract implementation from OpenZeppelin (line 4). In this case, we import version 4.4.0 of the OpenZeppelin contracts. + +Have a look at their nicely documented ERC20 contract to have a better understanding of how an implementation might look. Apart from the functionality specified in the ERC20 standard, this contract provides additional functionality. + +We will create our own contract called MyToken (line 6), which inherits the functionality from the OpenZepplin ERC20 token contract implementation that we imported (line 4). + +This contract implements the optional functions `name()` and `symbol()` of the ERC20 Token standard and has a constructor where their values can be set during the deployment of the contract (line 7). +In this case, we are going to use the default values. We will call our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +Next, we make use of the inherited `_mint` function (line 8) that allows us to create tokens upon deployment of the contract. Inside the parameters, we specify the address of the account that receives the tokens and the amount of tokens that are created. +In this case, the account that deploys the contract will receive the tokens and we set the amount to 1000000 to the power of `decimals()`. The optional function `decimals()` of the ERC20 token standard is implemented and set to the default value of 18. This will create 1000000 tokens that will have 18 decimal places. + +## ⭐️ Assignment + +1. Rename your contract to `EduCoin`. +2. Rename your token to `EduCoin`. +3. Change the symbol of your token to `EDC`. +4. Change the amount of tokens that will be minted from 1000000 to 1000. diff --git a/locales/ru/ERC20TokenCourse/introduction/introduction.md b/locales/ru/ERC20TokenCourse/introduction/introduction.md new file mode 100644 index 000000000..4eaf7583c --- /dev/null +++ b/locales/ru/ERC20TokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with the ERC20 token standard in the following sections. + +If you want to learn more about NFTs and the ERC721 token standard, have a look at the Learneth NFT Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/ru/ERC721Auction/README.md b/locales/ru/ERC721Auction/README.md new file mode 100644 index 000000000..325e4d60e --- /dev/null +++ b/locales/ru/ERC721Auction/README.md @@ -0,0 +1,5 @@ +## NFT Auction Contract + +Learn how to write an ERC721 (NFT) auction contract. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ru/ERC721Auction/auction-contract-setup/auctionContractSetup.md b/locales/ru/ERC721Auction/auction-contract-setup/auctionContractSetup.md new file mode 100644 index 000000000..945f0f803 --- /dev/null +++ b/locales/ru/ERC721Auction/auction-contract-setup/auctionContractSetup.md @@ -0,0 +1,46 @@ +In this contract tutorial, we will learn how to create an ERC721 (NFT) auction contract. +We recommend to you, to do the Learneth "Solidity NFT Course" before starting this tutorial. + +In the following sections, we will create a contract that will enable a seller to auction an NFT to the highest bidder. This contract was created by the Solidity by Example project. In this first section, we will create an interface, the necessary state variables, and the constructor. + +### Interface + +We create the interface (line 5) for the ERC721 token since our contract will need to interact with it. We will need the `safeTransferFrom` (line 5), and` transferFrom` (line 11) methods. + +### EnglishAuction + +We create the four events `Start`, `Bid`, `Withdraw`, `End` (line 19-22) so we can log important interactions. + +Next, we will create the state variables that store all the necessary information about our auction on-chain. + +We create two state variables for the NFT we want to auction. In the variable `nft` (line 24) we store a representation of the NFT contract, that will allow us to call its functions by combining the interface IERC721 and the address of the NFT contract. +In `nftId` (line 25), we store the specific token id in our NFT contract that will be auctioned. + +Next, we need a variable to store the address of the person that is auctioning off the NFT, the `seller` (line 27). +We want our NFT contract to send the seller the proceeds of the auction when it is finished, that’s why use `address payable`. + +We create a state variable `endAt` (line 28) where we will store the end date of the auction. +We also create the two booleans, `started` (line 29) and `ended` (line 30), that keep track of whether the auction has started or ended. + +We create a variable `highestBidder` (line 32) where we will store the address of the highest bidder. We will send the highest bidder the NFT once the auction has ended. + +Finally, we need a uint `highestBid` (line 33) to store the highest bid and a mapping `bids` (line 34), where we can store the total value of bids that an account has made before withdrawing; more on this in the next section. + +### Constructor + +When the auctioneer deploys the contract, they need to provide a few arguments: +the address of the contract of the NFT they want to auction `_nft` (line 37), the token id of the NFT they want to auction `_nftId` (line 38), and a starting price that must be overbid to place the first bid in the auction,`_startingBid` (line 39). + +Once deployed, the state variables `nft` (line 41), `nftId` (line 42), `highestBid` (line 45) will be assigned the values from the arguments. The address of the `seller` that deployed the contract will be automatically read out via msg.sender and stored in the state variable `seller` (line 44). + +In the next section, we will enable the auctioneer to start the auction and bidders to place their bids. + +## ⭐️ Assignment + +We will use the assignment part of the following sections to give you instructions on testing your contract in the Remix VM environment of Remix. + +1. Deploy an NFT contract. You can use the NFT contract that we created in our "3.3 ERC721 - Token Creation" section. + +2. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +3. After deploying your contract, test if contract functions like `nft`, `nftId`, and `started` work as expected. diff --git a/locales/ru/ERC721Auction/auction-start-bid/auctionContractStartBid.md b/locales/ru/ERC721Auction/auction-start-bid/auctionContractStartBid.md new file mode 100644 index 000000000..c2b944e0c --- /dev/null +++ b/locales/ru/ERC721Auction/auction-start-bid/auctionContractStartBid.md @@ -0,0 +1,42 @@ +In this section, we will create a function to start the auction and a function to bid on the NFT. + +### Start + +We use some control structures to check if necessary conditions are met before we let the seller start the auction. + +First, we check if the auction has already started (line 49). If it has started and our state variable `started` returns `true` we exit the function and throw an exception. + +The second condition we check for is whether the seller is executing the function (line 50). We have already created a function to store the seller's address when they deploy the contract in the `seller` state variable and can now check if the account executing the start function is the seller. If not we throw an exception. + +Next, we want to transfer the NFT that is up for auction from the seller to the contract (line 52). +We set the state variable `started` to `true` (line 53), and create an end date for the auction (line 54). In this case, it will be seven days from when the start function has been called. We can use a suffix like `days` after a literal number to specify units of time. If you want to learn more about time units have a look at the solidity documentation. + +Finally, we will emit our `Start()` event (line 56). + +### Bid + +Before the function caller can make a bid, we need to be sure that certain conditions are met. The auction needs to have started (line 60), the auction can not have ended (line 61) and the bid (the value attached to the call) needs to be higher than the current highest bid (line 62). + +Now we want to store the bid of the current highest bidder before we make a new bid. +First, we check if there is a bidder (line 64). If this function call is the first bid then the next line would be irrelevant. +In our mapping `bids` (line 34) we map the key, the `address` of the bidder, to the value, a `uint` that represents the total amount of ETH a bidder has bid in the auction before withdrawing. +If there is a bidder, we add the last bid (`highestBid`) of the `highestBidder` to the total value of the bids they have made (line 65) before withdrawing. +We store the bids because we want to enable the bidder to withdraw the ETH they used to make bids if they are no longer the highest bidder. + +Next, we set the `highestBidder` to the account calling the function (line 68), and the `highestBid` to their bid, the value that was sent with the call (line 69). + +Finally, we emit the `Bid` event (line 71). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we create in our "Solidity NFT Course" Learneth course. + +2. Mint yourself an NFT with the tokenId 0. + +3. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +4. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for `tokenId`. This will allow the contract to transfer the token to be auctioned. + +5. Call the `start` function of your auction contract. If you call the `started` function now, it should return `true`. If you call the `highestBid` function it should return 1. + +6. Set the value that you can attach to transactions to 3 Wei and call the `bid` function of the auction contract. If you call the `highestBid` function it should now return 3. diff --git a/locales/ru/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md b/locales/ru/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md new file mode 100644 index 000000000..e324a5c6e --- /dev/null +++ b/locales/ru/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md @@ -0,0 +1,45 @@ +In this section, we will finish the contract, create a function to withdraw the bids that an account has made, and create a function to end the auction. + +### Withdraw + +We create a local variable `bal` (balance) that stores the total value of bids that the function caller has made (line 75) since their last withdrawal. We can assign this value to `bal` by accessing the bids mapping using the address of the function caller as the key. + +Next, we set the value of the address of the function caller to 0 in the bids mapping because they will withdraw the total value of their bids (line 76). + +Now we transfer that amount of ETH from the contract to the function caller and emit the `Withdraw` event (line 79). + +### End + +Before the function caller can execute this function and end the auction, we need to check if certain conditions are met. The auction needs to have started (line 83), the end date of the auction needs to have been reached (line 84), and the auction must not have ended already (line 85). + +Once the auction has ended, we set the state variable `ended` to `true` (line 87). + +We check if anybody participated in the auction and bid on the NFT (line 88). + +If there was a bid, we transfer the NFT from the contract to the highest bidder (line 89) and transfer the ETH that was sent from the highest bidder to the contract, now to the address of the auctioneer, the seller of the NFT (line 90). + +If nobody bids on the NFT, we send the NFT back to the auctioneer (line 92). + +Finally, we emit the `End` event (line 95). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we created in our Learneth "Solidity NFT Course". + +2. Mint yourself an NFT with the tokenId 0. + +3. For testing purposes, change the value that is assigned to the `endAt` state variable (line 54) from `7 days` to `5 minutes`. + +4. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +5. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for the `tokenId`. + +6. Call the `start` function of your auction contract. + +7. Bid 2 Ether using account 1, and 3 Ether using account 2. If you call the `highestBidder` function, it should now return the address of account 2. + +8. Call the `withdraw` function with account 1. In the balance of account 1, you should see the 2 Ether minus some transaction fees. + +9. After 5 minutes have passed, call the `end` function. Then, call the `ended` function which should return `true`. + +In the NFT contract, if you call the `ownerOf` function with the tokenId 0, it should return the address of account 2. If you look at the balance of account 1 it should have increased by 3 Ether minus some transaction fees. diff --git a/locales/ru/ERC721Auction/config.yml b/locales/ru/ERC721Auction/config.yml new file mode 100644 index 000000000..0783a37a1 --- /dev/null +++ b/locales/ru/ERC721Auction/config.yml @@ -0,0 +1,19 @@ +--- +id: er721Auction +name: NFT Auction Contract +summary: Learn how to write an ERC721 (NFT) auction contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: Contract Setup + path: auction-contract-setup + - + name: Start and Bid Functions + path: auction-start-bid + - + name: Withdraw and End Functions + path: auction-withdraw-end diff --git a/locales/ru/Interoperability/1_Intro/intro.md b/locales/ru/Interoperability/1_Intro/intro.md new file mode 100644 index 000000000..ab26f4f6d --- /dev/null +++ b/locales/ru/Interoperability/1_Intro/intro.md @@ -0,0 +1,5 @@ +As the web3 world grows, there will be more blockchains. Unless the chains can communicate with one another, the ecosystem will become increasingly fragmented. + +The Axelar network enables protocols to have cross-chain functionality between any two blockchains. + +Building a protocol that is interoperable between ecosystems is essential for growth. diff --git a/locales/ru/Interoperability/2_Gateway/gateway.md b/locales/ru/Interoperability/2_Gateway/gateway.md new file mode 100644 index 000000000..dc752d3eb --- /dev/null +++ b/locales/ru/Interoperability/2_Gateway/gateway.md @@ -0,0 +1,25 @@ +The Axelar Gateway is the entrypoint for your smart contract into the Axelar ecosystem. Once you have triggered the appropriate function on the Gateway, your transaction will begin its interchain journey from your source chain across the Axelar network to the destination chain. Each chain that is connected to Axelar has a deployed gateway contract for you to interact with. + +The following are the two more relevant functions you will need to be familiar with. + +## callContract() + +This function triggers an interchain transaction with a message from the source to the destination chain. It takes three relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent + +The first two parameters are quite intuitive. They consist of both the name of the chain you want this transaction to go to and the address on that chain you want to end execute at. The final parameter is the payload. This payload represents a general message that is sent to the destination chain. The message can be used in many different ways on the destination chain. For example, you can send data to be used as a parameter in another function on the destination chain, you can send a function signature as a message that will then get executed on a destination chain, and much more. + +## callContractWithToken() + +This function triggers an interchain with a message and a fungible token from the source to the destination chain. It takes five relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent +4. `symbol`: The symbol of the token being sent +5. `amount`: The amount of that token that is being sent + +The first three parameters here are the same as in `callContract()`. The final two parameters are relevant to the token that is being sent along with the message. These are the symbol of the token and the amount of the token that is being sent. diff --git a/locales/ru/Interoperability/3_GasService/GasService.md b/locales/ru/Interoperability/3_GasService/GasService.md new file mode 100644 index 000000000..4ed0afbbf --- /dev/null +++ b/locales/ru/Interoperability/3_GasService/GasService.md @@ -0,0 +1,29 @@ +The Axelar Gas Service is an extremely useful tool made available to pay gas for an interchain transaction. It allows you to pay for the cost of a transaction in the token of the source chain, making for a much easier end user (and developer) experience. If for example the source chain is Ethereum and the destination chain is Polygon then the gas service will receive the complete payment for the transaction in ETH and no matic is needed from the caller to pay for the execution on the Polygon destination chain. + +The following are the two more relevant functions you will need to be familiar with in regards to the Gas Service. + +## payNativeGasForContractCall() + +This function allows you to pay for the entirety of an interchain transaction in the native token of the source chain. It takes five relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +The parameters overlap with the parameters required by the `callContract()` function in the Gateway contract. The two parameters not discussed in the Gateway section are `sender` and `refundAddress`. The sender is the address paying for the transaction and the refund address is the address that will receive any surplus funds sent to the gas service. + +## payNativeGasForContractCallWithToken() + +This function allows you to pay for the entirety of an interchain transaction (that includes a token transfer) in the native token of the source chain. It takes seven relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `symbol`: The symbol of the token that was sent +6. `amount`: The amount of the token that was sent +7. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +This function is nearly identical to the first top one the main difference being that it is used for message + token transfer transactions as opposed to just interchain message transactions (aka GMP Transactions). As a result the GasService needs to also know the `symbol` and `amount` of the token that is being sent. diff --git a/locales/ru/Interoperability/4_Executable/executable.md b/locales/ru/Interoperability/4_Executable/executable.md new file mode 100644 index 000000000..1f72c6be4 --- /dev/null +++ b/locales/ru/Interoperability/4_Executable/executable.md @@ -0,0 +1,27 @@ +The Axelar executable contains relevant helper functions that will be automatically executed on the destination chain in correspondence to the relevant inbound transaction from the source chain. + +The following are the relevant functions you will need to use from Axelar Executable + +## \_execute() + +This function handles the execution on the destination chain. It takes the following four parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent + +The `sourceChain` and `sourceAddress` are key parameters which you receive out of the box that can be used for verifying authenticity of messages on the destination chain. The payload (as discussed in the gateway section) is the message that was sent from the source chain to be used on your destination chain. The `commandId` will not be used during the rest of this module. + +## \_executeWithToken() + +This function handles the execution on the destination chain for a message being sent with a fungible token. It takes six relevant parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent +5. `tokenSymbol`: The symbol of the token being sent +6. `amount`: The amount of that token that is being sent + +The first four parameters are identical to that of the `_execute()` function. The final two parameters of `tokenSymbol` and `amount` are in reference to the token that is being sent along with the message. It allows you on the destination chain to interact with the token accordingly, for example transferring it to another receiving address. The `commandId` will not be used during the rest of this module. diff --git a/locales/ru/Interoperability/5_InterchainMessage/interchainMessage.md b/locales/ru/Interoperability/5_InterchainMessage/interchainMessage.md new file mode 100644 index 000000000..029f642ce --- /dev/null +++ b/locales/ru/Interoperability/5_InterchainMessage/interchainMessage.md @@ -0,0 +1,53 @@ +In this section we will create a contract that will send a "hello world" message between two blockchains. + +## Constructor + +The first thing you will need to create is the `constructor` for the function. This will allow you to set the `Gateway` and `Gas Service` contracts we discussed in the previous sections. + +When deploying the contract you will pass in the address of the `Gateway` and `GasService` for Ethereum Sepolia those addresses are `0xe432150cce91c13a887f7D836923d5597adD8E31` for the Gateway and `0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6` for the Gas Service. + +For the full list of relevant Axelar addresses see here + +## Send Interchain Message + +Now that the constructor has set the relevant Axelar addresses needed to trigger an interchain transaction you can move on to the `setRemoteValue()`, which will trigger this transaction. + +This function takes three parameters: + +1. `_destinationChain`: The chain which the transaction is going to +2. `_destinationAddress`: The address on the destination chain the transaction will execute at +3. `_message`: The message being passed to the destination chain + +First, you have a `require` statement which ensures that the `msg.value` contains a value. This `msg.value` will be used to pay the `GasService`. If no funds were sent, then the transaction should be reverted as the transaction cannot execute on the Axelar blockchain and destination chain without any gas. + +Next, you encode the `_message` that was passed in. Notice that the `_message` is set as a `string` type. Axelar expects this message to be submitted as a `bytes` type so to convert the `string` to `bytes` you simply pass it through `abi.encode()`. + +Now, with your message encoded you can begin to interact with the `GasService` and the `Gateway` + +To pay for the entire interchain transaction you will trigger the function `payNativeGasForContractCall`, which is defined in the `GasService`. + +This function needs the parameters explained earlier in the GasService section. The `sender` for this transaction will be this contract, which is `address(this)`. The `destinationChain` and `destinationAddress` can simply be passed in from this functions parameters, the `payload` is the encoded \_message we wrote earlier. Finally, you need to specify what the refund address is, this can be the address that triggers this function, which you get by writing `msg.sender`. + +Once you trigger this function you will have successfully sent a transaction from the source chain via Axelar to the destination chain! But there is still one final step that needs to be complete. + +### Receive Message on Destination Chain + +On the destination chain the inbound interchain transaction needs to be picked up and handled by the `AxelarExecutable`'s `_execute()` function. + +The `_execute()` function is defined in the `AxelarExecutable` contract so when defining this function you must remember to include the `override` keyword. + +This function takes three parameters. + +1. `_sourceChain`: The blockchain which the transaction has originated from +2. `_sourceAddress`: The address on the source chain which the transaction has been sent from +3. `_payload`: The message that has been sent from the source chain + +The first thing that needs to be done in this contract is to get access to your `message` that was sent. Recall, before sending the message it was sent through `abi.encode()` to convert the message from type `string` to type `bytes`. To convert your message back from type `bytes` to type `string` simply pass the `_payload` to the function `abi.decode()` and specify that you want the `_payload` decoded to type `string`. This will return the message as a string. + +Now that you have your message as a type string you can set the `sourceChain` and `sourceAddress` storage variables as `_sourceChain` and `_sourceAddress` to have an easy reference to the data that was passed in. You can also emit the `Executed` event with the `sourceAddress` and `message` event that you just decoded. + +Great! At this point you are now handling the interchain transaction on the destination chain. + +To interact with this contract make sure you deploy it on at least two blockchains so that you can call `setRemoteValue()` from the one chain and then have the `_execute()` function automatically triggered on another chain. You will be able to query the `sourceChain` and `sourceAddress` variables on the destination chain to ensure that the interchain execution worked correctly. + +To view the full step by step of the interchain transaction checkout the Axelarscan (testnet) block explorer. diff --git a/locales/ru/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md b/locales/ru/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md new file mode 100644 index 000000000..11915eb32 --- /dev/null +++ b/locales/ru/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md @@ -0,0 +1,39 @@ +At this point we have gone over an example of how to send a general message between one blockchain to another. Now, let's implement a contract that sends a message and a token from one blockchain to another. + +## Overview + +This contract should seem largely familiar. Much like the previous section the `constructor` receives the `Gateway` and `Gas Service` addresses. + +It then has a function that will be called from the source chain called `sendToMany` that takes in parameters similar to the previous section. + +1. `_destinationChain`: The chain the transaction is sending to +2. `_destinationAddress`: The address on the destination chain your transaction is sending to +3. `_destinationAddresses`: The message that you will be sending along with your token transfer. In this example the message is a list of receiving addresses for the token transfer. +4. `_symbol`: The symbol of the token address being sent +5. `_amount`: The amount of the token being sent + +In the function we already have the `require` statement implemented to ensure gas is sent + +We also have the basic ERC20 functionality to send the token from the calling wallet to this smart contract. The contract also calls the `approve` function to allow the Gateway to eventually transfer funds on its behalf. + +Finally, the `_executeWithToken()` function is also implemented out of the box. + +It makes use of the following params: + +1. `_payload`: The incoming message from the source chain +2. `_tokenSymbol`: The symbol of the token that was sent from the source chain +3. `_amount`: The amount of the token that was sent from the source chain + +Now with these params that were passed in, the `_execute()` function can send the tokens that were sent to the appropriate receivers. + +## Challenge + +Your challenge here is to finish off the `sendToMany()` function using the Axelar Gateway and Gas Service to trigger an interchain transaction. + +In the end you should be able to deploy this contract on two testnets, trigger the `sendToMany()` function and see the live transaction on Axelarscan (testnet) block explorer. + +### Testing Notes + +Note 1: The recommended ERC20 to use is `aUSDC` a wrapped version of the USDC token that can be obtained from the discord faucet bot. When triggering the `sendToMany()` function simply pass in the symbol `aUSDC` to the fourth param. + +Note2: When triggering the `sendToMany()` function you must remember to `approve` your contract to spend `aUSDC` tokens on your behalf, otherwise `transferFrom()` on line49 will throw an error. diff --git a/locales/ru/Interoperability/7_FurtherReading/furtherReading.md b/locales/ru/Interoperability/7_FurtherReading/furtherReading.md new file mode 100644 index 000000000..a601d7ac7 --- /dev/null +++ b/locales/ru/Interoperability/7_FurtherReading/furtherReading.md @@ -0,0 +1,11 @@ +Congratulations on making it to the end of the interoperability module! 🎉🎉 + +To continue your learning journey of interoperability with Axelar. There are many useful resources available. + +- For documentation 📚 + +- For more technical examples 💻 + +- For live coding demos 📹 + +- For the developer blog 📝 diff --git a/locales/ru/Interoperability/README.md b/locales/ru/Interoperability/README.md new file mode 100644 index 000000000..a43fc5dd5 --- /dev/null +++ b/locales/ru/Interoperability/README.md @@ -0,0 +1,3 @@ +## Interoperability Between Blockchains + +Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. diff --git a/locales/ru/Interoperability/config.yml b/locales/ru/Interoperability/config.yml new file mode 100644 index 000000000..39f1be7ed --- /dev/null +++ b/locales/ru/Interoperability/config.yml @@ -0,0 +1,31 @@ +--- +id: interopCourse +name: Multichain Protocols with Axelar +summary: Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. +level: 2 +tags: + - Solidity + - Interoperability + - Axelar +steps: + - + name: An Intro to Axelar + path: 1_Intro + - + name: Axelar Gateway + path: 2_Gateway + - + name: Axelar Gas Service + path: 3_GasService + - + name: Axelar Executable + path: 4_Executable + - + name: Interchain Messages + path: 5_InterchainMessage + - + name: Interchain Token Transfers + path: 6_InterchainTokenTransfer + - + name: Further Reading + path: 7_FurtherReading diff --git a/locales/ru/Multisig-Tutorial/1-multisig-introduction/introduction.md b/locales/ru/Multisig-Tutorial/1-multisig-introduction/introduction.md new file mode 100644 index 000000000..3e9f18938 --- /dev/null +++ b/locales/ru/Multisig-Tutorial/1-multisig-introduction/introduction.md @@ -0,0 +1,41 @@ +Welcome to the Multisignature Wallet course! In this section, we'll explore the fundamentals of Multisignature (Multisig) wallets and we'll go through a multisig wallet contract. + +## What is a Multisignature Wallet? + +A multisignature (multisig) wallet is a type of digital wallet that requires multiple keys to authorize a cryptocurrency transaction. + +Imagine a multisig wallet as a secure vault with multiple locks. To open the vault, each keyholder must open their individual lock. This setup ensures that no single person can access the vault's contents without the others' consent. + +## How Does a Multisig Wallet Work? + +In a multisig setup, each transaction must receive a predetermined number of approvals from a set group of individuals. For instance, in a 3-of-5 wallet configuration, there are five authorized addresses, but a transaction only goes through when at least three of them give their approval. When a transaction is initiated, it's presented as a **proposal** to the group. Each member who agrees to the transaction uses their private key to digitally sign it. + +These **digital signatures** are unique and are generated based on the combination of the transaction data and the private key. + +When the required number of signatures is reached, the transaction is broadcasted to the blockchain for execution. + +## Why Use a Multisig Wallet? + +Multisig wallets are crucial for enhanced security in cryptocurrency transactions. They mitigate the risk of theft or loss of a single key. In business, they're used to ensure that funds can't be moved without consensus among stakeholders. For instance, in a company managing cryptocurrency assets, a multisig wallet might require the CFO, CEO, and a board member to all approve significant transactions, protecting against internal fraud or external hacks. + +## Conclusion + +In this section, we learned that a multisig wallet requires multiple keys to authorize a proposed cryptocurrency transaction and that a multisigs mitigates the risk of theft or loss of a single key. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is a Multisignature Wallet? + +1. A digital wallet that requires a single signature for transactions. +2. A digital wallet that requires multiple signatures for transactions. +3. A physical wallet used for storing cryptocurrency. +4. A wallet that can only hold multiple types of cryptocurrencies. + +### 2) How does a Multisignature Wallet enhance security? + +1. By requiring a single private key for transactions. +2. By distributing transaction approval across multiple owners. +3. By storing transaction data on-chain. +4. None of the above. + +Feel free to take your time and answer the questions above. Once you're ready, we'll move on to exploring the Multisig smart contract and understanding its structure. diff --git a/locales/ru/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md b/locales/ru/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md new file mode 100644 index 000000000..17b0a924f --- /dev/null +++ b/locales/ru/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md @@ -0,0 +1,60 @@ +In this section, we'll explore the **initialization process** of the Multisig smart contract. We'll examine the constructor function and review how it sets up the initial state of the contract. + +## Note + +From this section on in this tutorial, we will be building up a multisig contract. In subsequent sections, the contract will become increasingly complete. + +## Overview + +In this section, the contract consists of events, state variables, modifiers, and functions. **Events** provide transparency by logging specified activities on the blockchain, while **modifiers** ensure that only authorized users can execute certain functions. + +## State Variables + +In Line 4, we have the MultisigWallet contract itself. At the beginning of the contract, we have three state variables. + +1. **`owners`:** An array containing the addresses of all owners of the multi-signature wallet (Line 5). +2. **`isOwner`:** A mapping indicating whether an address is an owner (Line 6). +3. **`numConfirmationsRequired`:** The number of confirmations required for a transaction (Line 7). + +The setup of array and mapping allows us to easily retrieve the list of owners and verify whether an address is an owner. + +## Modifiers + +Next, we have a modifier called `onlyOwner` (Line 9). Modifiers in Solidity are special keywords that can be used to amend the behavior of functions. In our case, the `onlyOwner` modifier ensures that only owners can execute a function. It does this by checking whether the address of the **caller** is an owner. + +## Constructor Function + +The `constructor` function (Line 14) is executed only once during the deployment of the contract. It initializes essential parameters, in this case, the list of owners and the required number of confirmations (Line 14). + +On lines 15 and 16, we have two `require` statements to ensure that the inputs are valid. In this case, we require that there must be at least one owner and that the number of required confirmations must be greater than zero and less than or equal to the number of owners. + +The constructor then initializes the contract state by verifying that is not address(0) (Line 25) and that the owner is unique (Line 26). Then it adds a key/ value pair to the isOwner mapping (Line 28), and then it populates the `owners` array with the provided owner addresses (Line 29). + +Finally, it sets the `numConfirmationsRequired` variable with the specified value (Line 32). + +## getOwners Function + +The `getOwners` function (Line 36) allows users to retrieve the list of owners of the multi-signature wallet. It returns the `owners` array (Line 37). + +## getNumConfirmationsRequired Function + +The `getNumConfirmationsRequired` function (Line 41) allows users to retrieve the number of confirmations required for a transaction. It returns the `numConfirmationsRequired` variable (Line 42). + +## Conclusion + +In this section, we explored the initialization process of the Multisig smart contract. We examined the constructor function and understood how it sets up the initial state of the contract. + +## ⭐️ Assignment: Deploy a Multisig Wallet + +Deploy a Multisig contract with three owners and require two confirmations for transaction execution. + +1. Compile contractInitialization.sol +2. Go to Deploy & Run Transactions in Remix. +3. Expand the "Deploy" section. +4. Under "_OWNERS", enter three an array of three addresses. +5. Under "_NUM_CONFIRMATIONS_REQUIRED", enter the number of confirmations required for a transaction. + +**Hints:** + +- You can get addresses from the "ACCOUNTS" dropdown menu. +- The array of addresses should be in the format: ["0x123...", "0x456...", "0x789..."]. diff --git a/locales/ru/Multisig-Tutorial/3-multisig-deposits/deposits.md b/locales/ru/Multisig-Tutorial/3-multisig-deposits/deposits.md new file mode 100644 index 000000000..a8a14213b --- /dev/null +++ b/locales/ru/Multisig-Tutorial/3-multisig-deposits/deposits.md @@ -0,0 +1,34 @@ +In this section, we'll explore the `receive` function and the associated Deposit event. We'll examine how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## Deposit Event + +On line, 9 we have the Deposit event. The Deposit event is emitted whenever Ether is deposited into the multi-signature wallet. It includes three parameters: + +1. `sender`: The address that sent the Ether. +2. `amount`: The amount of Ether deposited. +3. `balance`: The updated balance of the contract after the deposit. + +We can use the Deposit event to track the flow of Ether into the multi-signature wallet and maybe trigger other actions based on the event. + +## receive Function + +On line 43, we have the `receive` function. The `receive` function is a special function that is executed whenever Ether is sent to the contract. + +The `receive` function is marked as `external` and `payable`. The `external` modifier means that the function can only be called from outside the contract. The `payable` modifier means that the function can receive Ether. + +The `receive` function emits the Deposit event (Line 44) with the address of the sender, the amount of Ether sent, and the updated balance of the contract. It doesn't return anything. + +To receive Ether, a contract must have a `receive`, `fallback`, or a function with the `payable` modifier. If none of these are present, the contract will reject any Ether sent to it. + +## Conclusion + +In this section, we explored the `receive` function and the associated Deposit event. We examined how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## ⭐️ Assignment: Deposit Ether + +Deposit 2 Ether into the Multisig contract. + +1. Deploy the Multisig contract as in the previous assignment. +2. Enter a Value of 2 Ether in the Value field and select Ether in the dropdown menu. +3. At the bottom of your deployed contract in the "Low level interactions" section, click on the "Transact" button. +4. On top of your deployed contract, it should now say "Balance: 2 Ether". diff --git a/locales/ru/Multisig-Tutorial/4-multisig-transactions/transactions.md b/locales/ru/Multisig-Tutorial/4-multisig-transactions/transactions.md new file mode 100644 index 000000000..f62fd48a0 --- /dev/null +++ b/locales/ru/Multisig-Tutorial/4-multisig-transactions/transactions.md @@ -0,0 +1,73 @@ +In this section, we'll explore the process of submitting and confirming transactions. + +## Modifiers + +We have new modifiers in this iteration of the contract. Let's examine them one by one. + +1. **`txExists` modifier:** (Line 13) ensures that the transaction exists. It does this by checking whether the transaction index is less than the length of the `transactions` array. We'll go into more about in this modifier later in this section. +2. **`notExecuted` modifier:** (Line 18) ensures that the transaction has not been executed. It does this by checking whether the `executed` variable of the transaction is false. +3. **`notConfirmed` modifier:** (Line 23) ensures that the transaction has not been confirmed by the caller. It does this by checking whether the `isConfirmed` mapping of the transaction index and the caller's address is false. + +## Transaction Struct + +On line 28, we have a struct called `Transaction`. We store the struct members: `to`, `value`, `data`, `executed`, and `numConfirmations` in individual variables. + +## Mapping of Confirmations + +On line 37, we have a mapping called `isConfirmed`. This mapping is used to keep track of the confirmations of each transaction. It maps the transaction's index to a mapping of an owner addresse to a boolean value. The boolean value indicates whether this owner has confirmed the transaction. + +## Transactions Array + +On line 39, we have an array called `transactions`. The array is used to store all the transactions submitted to the multi-signature wallet. + +## Events + +We have four new events in this iteration of the contract: + +1. **`SubmitTransaction` event:** emitted whenever a transaction is submitted to the multi-signature wallet. +2. **`ConfirmTransaction` event:** emitted whenever a transaction is confirmed by an owner. +3. **`RevokeConfirmation` event:** emitted whenever a transaction confirmation is revoked by an owner. +4. **`ExecuteTransaction` event:** emitted whenever a transaction is executed. + +## submitTransaction Function + +The `submitTransaction` function (Line 78) allows users to submit a transaction to the multi-sig wallet. It takes three parameters: `to`, `value`, and `data`. The `to` parameter is the address of the recipient of the transaction. The `value` parameter is the amount of Ether to be sent. The `data` parameter is the data to be sent to the recipient. Only owners can submit transactions. + +On line, 85 we create a new transaction struct and push it to the `transactions` array and emit the `SubmitTransaction` event. The `txIndex` variable is used to keep track of the transaction index. + +## confirmTransaction Function + +The `confirmTransaction` function (Line 98) allows users to confirm a transaction. It takes one parameter: `txIndex`. +It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. The `onlyOwner` modifier ensures that only owners can confirm transactions. The `txExists` modifier ensures that the transaction exists. The `notExecuted` modifier ensures that the transaction has not been executed. + +On line 101, we store the transaction in a local variable called `transaction`. We then increment the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to true. Finally, we emit the `ConfirmTransaction` event. + +## executeTransaction Function + +The `executeTransaction` function (Line 108) allows users to execute a transaction. On line 113, we require that the number of confirmations of the transaction is greater than or equal to the required number of confirmations. We then set the `executed` variable of the transaction to true. Finally, send the funds using the `call` function. This is the `call` of the recipient address with the value and data of the transaction. If the transaction is successful, we emit the `ExecuteTransaction` event. + +## getTransactionCount Function + +The `getTransactionCount` function (Line 132) allows users to retrieve the number of transactions in the multi-signature wallet. It returns the length of the `transactions` array. + +## getTransaction Function + +The `getTransaction` function (Line 136) allows users to retrieve a transaction. It returns the transaction struct members that we explored earlier in this section. + +## Conclusion + +In this section, we explored the process of submitting, confirming, and executing transactions. We examined the `submitTransaction`, `confirmTransaction`, and `executeTransaction` functions and understood how they work together to allow multiple users to submit and confirm transactions. + +## ⭐️ Assignment: Make a Transaction + +Submit, confirm, and execute a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. Deploy the Multisig contract as in the previous assignment. Make sure that the required number of confirmations is 2. +2. Fund the multisig from any address by sending 4 Ether as you did in the previous assignment. +3. Try sending 2 Ether to the first account in the "ACCOUNTS" dropdown menu. Once you have submitted this transaction (with submitTransaction), click on `getTransactionCount` and should see one transaction or you can click on `getTransaction`, insert 0 as the transaction index and see the transaction you just submitted. +4. Now you can click on `confirmTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. +5. Switch to the second owner account and confirm the transaction again. If you click on `getTransaction` again, you should see that the transaction has been confirmed twice. +6. The last step is to execute the transaction. Click on `executeTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been executed. You can also check the balance of the first account in the "ACCOUNTS" dropdown menu. It should now be 2 Ether higher and the balance of the multi-signature wallet should be 2 Ether lower. + +**Hint:** +If you submit a transaction make sure that the value is in Wei and that the _data field is correctly filled in. E.g. it could look like this: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 2000000000000000000, 0x" for 2 Ether. diff --git a/locales/ru/Multisig-Tutorial/5-multisig-revoke/revoke.md b/locales/ru/Multisig-Tutorial/5-multisig-revoke/revoke.md new file mode 100644 index 000000000..1bf085343 --- /dev/null +++ b/locales/ru/Multisig-Tutorial/5-multisig-revoke/revoke.md @@ -0,0 +1,30 @@ +In this section, we'll explore the process of revoking confirmations. This process is necessary when an owner changes their mind about a transaction and wants to stop it from being executed. This section will be pretty straightforward. + +## revokeConfirmation Event + +On line 14, we have added the `RevokeConfirmation` event. This event is emitted whenever a transaction confirmation is revoked by an owner. + +## revokeConfirmation Function + +On line 129, we have added the `revokeConfirmation` function. It allows users to revoke a transaction confirmation. + +`revokeConfirmation` takes one parameter: `txIndex`. It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. + +On line 134, we require that the transaction has been confirmed by the caller. This ensures that an owner who has confirmed the transaction can only revoke their own confirmation. +We then decrement the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to false. Finally, we emit the `RevokeConfirmation` event. + +## Conclusion + +In this section, we explored the process of revoking confirmations. We examined the `revokeConfirmation` function and understood how it works to allow users to revoke confirmations. + +## ⭐️ Assignment: Revoke a Confirmation + +Confirm and revoke a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. As in the previous assignment, deploy the Multisig contract, send the contract some Ether, and then submit a transaction to the first account in the "ACCOUNTS" dropdown menu with a value of 2 Ether. +2. Confirm the transaction twice as in the previous assignment. +3. Revoke the transaction by clicking on `revokeConfirmation` and inserting 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. + +## Final Conclusion + +In this tutorial, we explored the process of creating a multi-signature wallet. We learned how to initialize the contract, deposit Ether, submit, confirm, and revoke transactions. We also learned how to execute transactions and retrieve information about the multi-signature wallet. diff --git a/locales/ru/Multisig-Tutorial/README.md b/locales/ru/Multisig-Tutorial/README.md new file mode 100644 index 000000000..ae5997802 --- /dev/null +++ b/locales/ru/Multisig-Tutorial/README.md @@ -0,0 +1,5 @@ +## MultiSig Wallet + +Learn how to write a MultiSig Wallet smart contract on Ethereum. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ru/Multisig-Tutorial/config.yml b/locales/ru/Multisig-Tutorial/config.yml new file mode 100644 index 000000000..067de0fb9 --- /dev/null +++ b/locales/ru/Multisig-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: multisigCourse +name: Multisig Wallet +summary: Learn how to create and interact with a multisig wallet. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - Multisig +steps: + - + name: 1. Introduction + path: 1-multisig-introduction + - + name: 2. Initialize the Contract + path: 2-multisig-initialization + - + name: 3. Deposits + path: 3-multisig-deposits + - + name: 4. Transactions + path: 4-multisig-transactions + - + name: 5. Revoking Confirmations + path: 5-multisig-revoke diff --git a/locales/ru/NFTTokenCourse/README.md b/locales/ru/NFTTokenCourse/README.md new file mode 100644 index 000000000..c3d2a183a --- /dev/null +++ b/locales/ru/NFTTokenCourse/README.md @@ -0,0 +1,5 @@ +## Solidity NFT Course + +Learn how to create your own NFTs (non-fungible tokens). + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ru/NFTTokenCourse/config.yml b/locales/ru/NFTTokenCourse/config.yml new file mode 100644 index 000000000..af82db834 --- /dev/null +++ b/locales/ru/NFTTokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: nftTokenCourse +name: Solidity NFT Course +summary: Learn how to create your own NFT tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc721-interface + - + name: 3. Metadata Interface + path: erc721-interface-metadata + - + name: 4. Token Creation + path: erc721-token-creation + - + name: 5. Metadata IPFS + path: erc721-metadata-ipfs + - + name: 6. Deploy to Testnet + path: erc721-deploy-testnet-opensea diff --git a/locales/ru/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md b/locales/ru/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md new file mode 100644 index 000000000..40576500c --- /dev/null +++ b/locales/ru/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md @@ -0,0 +1,50 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to the Rinkeby testnet of the Ethereum blockchain, mint an NFT, and look at it on the NFT marketplace OpenSea. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token for Rinkeby + +In order to make transactions on the testnet, we need Ethereum testnet tokens. + +**2.1** Switch your Metamask from "Ethereum Mainnetwork" to "Rinkeby Test Network". + +**2.2** Go to https://faucet.paradigm.xyz/, enter the address of your account and claim testnet ETH. +You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Contract Deployment + +**3.1** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It should then ask you to connect your account, which you should confirm. Then you should see the Rinkeby network badge under "Injected Web3". + +**3.2** Deploy your token contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. + +### 4. Mint an NFT + +**4.1** Expand your contract in the IDE so you can see the buttons for the functions. + +**4.2** Expand the input fields next to the safeMint button. Enter the Ethereum address of the account that is connected to Remix in the “to:” input field. Enter “0” in the input field "tokenID:". Click on transact. + +**4.3** In Metamask click on assets, then click on the “Import tokens” link, and paste the address of your contract in the input field. You can set decimals to 0. + +You should now see the name of the symbol of your token contract (e.g. GEO) in your “Assets” view in Metamask. You should have one of these tokens. + +### 5. See your NFT on OpenSea + +OpenSea is one of the most popular online marketplace for NFTs. OpenSea also provides a version where you can see assets on the testnet, under https://testnets.opensea.io/ + +**5.1** Go to https://testnets.opensea.io/login. + +**5.2** Connect with your Metamask wallet. You should be redirected to your account https://testnets.opensea.io/account view on OpenSea, where you should be able to see your NFT. You should see the image of your NFT; when you click on it, you should see the name, description, and under properties, also the attributes that you created. + +If you successfully completed this course and are familiar with the basics of Solidity development, we encourage you to continue your learning journey by learning how to create your own NFT auction contract from the Learneth resources. diff --git a/locales/ru/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md b/locales/ru/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md new file mode 100644 index 000000000..a43162feb --- /dev/null +++ b/locales/ru/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md @@ -0,0 +1,44 @@ +The metadata extension is optional. It allows us to add additional information to our ERC721 tokens. We can specify a name, a symbol, and an URI (Uniform Resource Identifier) that can point to a file where we can add even more information in the form of a JSON. + +## ERC721 Metadata Functions + +### name + +The function `name` (line 16) returns the name of the token collection. A token collection means all tokens created with your ERC721 token contract implementation. Every token in this collection will have this name, regardless of their tokenId. + +### symbol + +The function `symbol` (line 21) returns the symbol of the token collection. + +### tokenURI + +The function `tokenURI` (line 26) returns the URI for the token with the id `tokenId`. In this case it’s not the URI of the whole collection but of an individual token in the collection. + +## ERC721 Metadata JSON Schema + +The file that the tokenURI points to should conform to the Metadata JSON Schema as it is specified in the EIP-721. + +``` +{ + "title": "Asset Metadata", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Identifies the asset to which this NFT represents" + }, + "description": { + "type": "string", + "description": "Describes the asset to which this NFT represents" + }, + "image": { + "type": "string", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." + } + } +} +``` + +The root element must be of the type object. This root object should have properties with the keys: name, description, and image that should be all of the type string. + +The ERC721 standard is pretty flexible, the tokenURI does not need to point to a JSON document and the JSON does not need to have all properties and often has additional properties. diff --git a/locales/ru/NFTTokenCourse/erc721-interface/erc721Interface.md b/locales/ru/NFTTokenCourse/erc721-interface/erc721Interface.md new file mode 100644 index 000000000..468e8e640 --- /dev/null +++ b/locales/ru/NFTTokenCourse/erc721-interface/erc721Interface.md @@ -0,0 +1,100 @@ +ERC721 is a standard for token contracts that manage non-fungible tokens (NFTs) on the Ethereum blockchain. + +Each non-fungible token is unique and not interchangeable. NFTs can have different properties, behavior, or rights. Non-fungible tokens are used to represent ownership of unique digital and physical assets like art, collectibles, or real estate. + +If you want to know more about the ERC721 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +The ERC721 standard is more complex than the ERC20 standard and it features optional extensions. ERC721 compliant contracts must, at a minimum, implement the ERC721 and ERC165 interfaces, which we will look at in this section. + +This interface (line 11) is part of the open-source contract library provided by OpenZeppelin. + +## Basic IERC721 Functions + +Contracts compliant with the ERC721 standard have to implement the following functions: + +### balanceOf + +The function `balanceOf` (line 30) returns the amount of tokens owned by the account with the address `owner`. + +### ownerOf + +The function `ownerOf` (line 39) returns the address `owner` of the account that holds the token with the id `tokenId`. + +### safeTransferFrom + +The function `safeTransferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +The function `safeTransferFrom` (line 137) is almost identical to the function `safeTransferFrom` (line 55) .The only difference is that this function has a non-empty payload `data`. + +A smart contract must implement the ERC721TokenReceiver Interface if it is to receive a transfer. This will ensure that the contract can handle ERC721 token transfers and prevent the tokens from being locked in a contract that can’t. + +### transferFrom + +The function `transferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +**It is recommended to use safeTransferFrom instead of transferFrom whenever possible.** +The `transferFrom` function is not secure because it doesn’t check if the smart contract that is the recipient of the transfer has implemented the ERC721TokenReceiver interface and is capable of handling ERC721 tokens. + +## Advanced IERC721 Functions + +### approve + +The function `approve` (line 94) gives the account with the address `to` the permission to manage the token with the id `tokenId` on behalf of the account calling the function. + +### getApproved + +The function `getApproved` (line 103) returns the address of the account (return var `operator`) that is approved to manage the token with the id `tokenId`. + +### setApprovalForAll + +The function `setApprovalForAll` (line 115) sets the permission (`_approved`) for the account with the specified address (input param - `operator`) to manage all tokens of the account calling the function. + +### isApprovedForAll + +The function `getApproved` (line 103) returns the boolean true if the account with the address `operator` is approved to manage all tokens of the account with the address `owner`. + +## IERC721 Events + +ERC721 contracts must also emit the following events: + +### Transfer + +The `Transfer` event (line 15) must be emitted when the token with the id `tokenId` is transferred from the account with the address `from` to the account with the address `to`. + +### Approval + +The `Approval` event (line 20) must be emitted when the account with the address `owner` approves the account with the address `spender` to manage the token with the id `tokenId` on its behalf. + +### ApprovalForAll + +The `ApprovalForAll` event (line 25) must be emitted when the account with the address `owner` gives or removes the permission (`_approved`) of the account with the address `operator` to manage all its tokens. + +## IERC165 + +In addition to the ERC721 interface, ERC721 compliant contracts must also implement the ERC165 interface. + +With the implementation of the ERC165 interface, contracts can declare the support of specific interfaces. A contract that wants to interact with another contract can then query if the other contract supports this interface before making a transaction e.g. sending tokens to it that they might not support. + +Our IERC721 interface here imports (line 6) and inherits (line 11) from the IERC165 interface. + +This is how OpenZeppelins implementation of the ERC165 interface looks like: + +``` +interface IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +For example, the ERC165 identifier for the ERC721 interface as specified in the EIP721 is “0x80ac58cd”. Learn how to calculate an interface identifier and more about the ERC165 in its improvement proposal. + +## Other interfaces + +The IERC721TokenReceiver interface must be implemented to accept safe transfers. + +There are two optional extensions for ERC721 contracts specified in the EIP721: + +IERC721Enumerable enables a contract to publish its full list of tokens and make them discoverable. + +IERC721Metadata enables a contract to associate additional information to a token. We will have a more detailed look into this in the next section. diff --git a/locales/ru/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md b/locales/ru/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md new file mode 100644 index 000000000..27876b068 --- /dev/null +++ b/locales/ru/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md @@ -0,0 +1,101 @@ +In this section, we will create our metadata and store it in a decentralized way. + +IPFS ( InterPlanetary File System) is a peer-to-peer network for storing files in a distributed way. Pinata.cloud is a pinning service that allows users to easily host files on the IPFS network. + +We want to host our images and the JSON files with their metadata on IPFS. + +### Create Image Folder + +In this example, we will create metadata for three tokens. As you can see below, we create three images that we stored in a folder. + +``` +geo-img +├── geo_1.png +├── geo_2.png +├── geo_3.png +``` + +### Register on Pinata + +Now, we want to host these images somewhere so we can point to them in the metadata of our tokens. Let's do it in a decentralized way and use Pinata to host them on IPFS. + +First you need an account on Pinata. Go to Pinata.cloud and create an account. On Pinata you can upload up to 1 GB of data for free. + +Once you have signed up, you should be in the Pin Manager view. + +Pin Manager Pinata + +### Upload Images to IPFS + +Click on the upload button and upload the folder with your images. +Once you've uploaded your folder, you should see the name of your folder and the CID (content identifier) associated with it. If the content in the folder changes, the CID will also change. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P + +You can access a specific image by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png + +### Create JSON files + +We create another folder where we store three JSON files. + +``` +geo-json +├── 0 +├── 1 +├── 2 +``` + +Inside the JSON files, create the metadata for the tokens, like name, description, and image. +For the image URL, we are going to use the URL of our images on IPFS. You can add additional data if you like; in this example, we added some unique attributes for each token. + +This is how the JSON for the first token could look: + +``` +{ + "name": "Geometry#0", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png +", + "attributes": [ + { "trait_type": "background", "value": "cyan" }, + { "trait_type": "color", "value": "red" }, + { "trait_type": "shape", "value": "circle" } + ] +} +``` + +This is how the JSON for the second token could look: + +``` +{ + "name": "Geometry#1", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_2.png", + "attributes": [ + { "trait_type": "background", "value": "magenta" }, + { "trait_type": "color", "value": "green" }, + { "trait_type": "shape", "value": "square" } + ] +} +``` + +As shown above, the folder in this example is called "geo-json". Inside this folder, we have three JSON files. +The first JSON file is called "0", the second JSON file is called "1", and the third JSON file is called "2". + +Make sure that your JSON files don't have a file ending and are named like their corresponding tokenIds. +In the pin manager on pinata.cloud, click on the upload button and upload the folder with your JSON files. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. +For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp +This will become our baseURI. + +You can access a specific JSON file then by just adding a slash and the tokenId by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/0 + +In the contract, replace the baseURI with your own baseURI. In this example, the baseURI consists of the URL +"https://ipfs.io/ipfs/", the CID containing the JSON files, and a slash at the end "/". + +An individual tokenURI will now be created for each token by adding the tokenId to the baseURI — exactly what we did manually in the example above to access the JSON file. diff --git a/locales/ru/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md b/locales/ru/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md new file mode 100644 index 000000000..891fe00a7 --- /dev/null +++ b/locales/ru/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md @@ -0,0 +1,35 @@ +In this contract, we use an ERC721 token contract implementation from OpenZeppelin (line 4). + +Have a look at their implementation of a ERC721 contract. Apart from the functionality specified in the ERC721 standard, the contract provides additional functions which we will see in a bit. + +## myToken + +We create our own contract called MyToken (line 7), which inherits (line 7) the functionality from the OpenZepplin `ERC721` token contract implementation and `Ownable` that we imported (line 4). If you don't remember the Ownable contract module, have a look at the ERC20 extensions section. + +This ERC721 implementation makes use of the IERC721Metadata extension that is specified in the EIP. Our contract inherits the functions `name()` and `symbol()` +and has a constructor that allows their values to be set during the deployment of the contract (line 8). +In this case, we are going to use the default values. We name our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +### Base URI + +With an ERC721 contract, we are able to mint various tokens, each with its own tokenId. As we saw in the IERC721Metadata interface, each token can have its own `tokenURI`, which typically points to a JSON file to store metadata like name, description, and image link. +If a contract mints multiple tokens, ERC721 implementations often use the same URI as a base (`baseURI`) for all tokens and only differentiate them by adding their unique `tokenId` at the end via concatenation. In the next part, we will see what this looks like in practice. + +In this example, we are storing our data on IPFS — more on that in the next section. Our baseURI is https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/ (line 11). +Through concatenation the tokenURI for the token with the id 0 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/0 , the tokenURI for the token with the id 1 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/1, and so on. + +When using IPFS and you run into "504 Gateway Time-out" errors, you might have to wait and retry until the data is available. + +### safeMint + +With the safeMint function (line 14) we enable the owner to create new tokens with a dedicated token id after contract deployment. +The safeMint function is part of the ERC721 implementation of OpenZeppelin and lets us safely mint a token with the id `tokenId` to the account with the address `to`. For access control, we use the `onlyOwner` modifier from the Ownable access control contract module that we imported (line 5). + +In the next section, we will see how we can create and host the metadata for our NFTs. + +## ⭐️ Assignment + +1. Rename your contract to `Geometry`. +2. Rename your token to `Geometry`. +3. Change the symbol of your token to `GEO`. +4. Change the `_baseURI` to https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/. diff --git a/locales/ru/NFTTokenCourse/introduction/introduction.md b/locales/ru/NFTTokenCourse/introduction/introduction.md new file mode 100644 index 000000000..13beea567 --- /dev/null +++ b/locales/ru/NFTTokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with NFTs, tokens created with the ERC721 token standard. + +If you want to learn more about fungible tokens and the ERC20 token standard, have a look at the Learneth ERC20 Token Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain-based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/ru/OpcodesInTheDebugger/1_intro/step.md b/locales/ru/OpcodesInTheDebugger/1_intro/step.md new file mode 100644 index 000000000..c1d9a2448 --- /dev/null +++ b/locales/ru/OpcodesInTheDebugger/1_intro/step.md @@ -0,0 +1,5 @@ +This workshop aims to give a better understanding about how a contract get deployed. +`SimpleStore` is a very basic contract. +It has a very simple constructor - which just uses the first parameter `_o` and saves it to `s`. + +Using the debugger, we'll try to see, what the opcode `CODECOPY` does. diff --git a/locales/ru/OpcodesInTheDebugger/2_memory/step.md b/locales/ru/OpcodesInTheDebugger/2_memory/step.md new file mode 100644 index 000000000..577169a5e --- /dev/null +++ b/locales/ru/OpcodesInTheDebugger/2_memory/step.md @@ -0,0 +1,8 @@ +Before we start, just quick reminder: + +The runtime of the EVM has several kinds of memory: + +- `calldata`: This is the input value given to the transaction. +- `stack`: Basically, this is a list of values, each value is limited in size (32 bytes). +- `memory`: Memory is used when the **type** of value getting stored is more complex like an array or a mapping. This memory is **temporary** and is **released** at the end of the execution. +- `storage`: This is a mapping, each value stored is **persisted** and saved on chain. diff --git a/locales/ru/OpcodesInTheDebugger/3_codecopy/step.md b/locales/ru/OpcodesInTheDebugger/3_codecopy/step.md new file mode 100644 index 000000000..b0c9f7d52 --- /dev/null +++ b/locales/ru/OpcodesInTheDebugger/3_codecopy/step.md @@ -0,0 +1,7 @@ +CODECOPY is one of the many opcodes run by the EVM. Check out the complete list of opcodes at https://ethervm.io/ . + +CODECOPY takes the **running code** (or part of it) and to copies it from the `calldata` to the `memory`. + +The solidity implementation is: **codecopy(t, f, s)** - copy **s** bytes from code at position **f** to memory at position **t**. + +Every contract deployment uses **CODECOPY**. diff --git a/locales/ru/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md b/locales/ru/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md new file mode 100644 index 000000000..63950051d --- /dev/null +++ b/locales/ru/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md @@ -0,0 +1,11 @@ +Let's go back to our contract. +Please make sure the `solidity compiler` and `Deploy & Run Transactions` are activated. + +Alternatively, you can click on `Solidity` from the `Home Page` **Environments** section. + +- Compile the contract from the `solidity compiler`. +- Go to the `Deploy & Run Transactions` and make sure `SimpleStore` is selected contract. +- In the textbox to the right of `Deploy`, input a positive integer. +- Click on `Deploy`. + +In the next step, we'll watch the deployment in the debugger. diff --git a/locales/ru/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md b/locales/ru/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md new file mode 100644 index 000000000..3ef3cd146 --- /dev/null +++ b/locales/ru/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md @@ -0,0 +1,7 @@ +From the Remix terminal, identify the transaction that deployed the contract and click `Debug` + +In the gutter of the editor, put a breakpoint on the line `s = _o`, and click on `Jump to the next Breakpoint` (bottom right button). + +Click on `Step into`, to move along the opcodes until you reach `SSTORE`. + +`SSTORE` is the opcode for storing the value `_o` in the storage. Let's continue further to the `CODECOPY`. diff --git a/locales/ru/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md b/locales/ru/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md new file mode 100644 index 000000000..1480728e6 --- /dev/null +++ b/locales/ru/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md @@ -0,0 +1,57 @@ +The goal here is to store the code in the blockchain. The EVM needs to tell the client (geth, parity) which what part of the **Call Data** to store. In this step, we are saving the contract MINUS its constructor (because that gets inplmented only 1 time) and MINUS the input parameter does not need to be stored. + +`CODECOPY` is the first step: it copies the bytecode to memory, then the ethereum client will be able to consume it. MUNCH! + +But wait... before the client can **MUNCH** bytecode, it needs an instruction - an opcode to tell it to MUNCH. `RETURN` is this opcode! + +As stated in the general spec, at the end of the contract creation, the client (geth, parity) takes the targeted value by the opcode `RETURN` and **persists** it by making it part of the deployed bytecode. + +Once you are in the `CODECOPY`, look at the top 3 items in the **Stack**: + +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x0000000000000000000000000000000000000000000000000000000000000055` +`2: 0x000000000000000000000000000000000000000000000000000000000000003e` + +_In your Stack - `1` & `2` may be slightly different. The difference may be due to a different compiler version._ + +**These are the parameters for `CODECOPY`.** + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +`0` is the offset where the copied code should be placed in the **memory**. In this example, ( all zeros) the code is copied to the beginning of the memory. (**t**) +`1` is the offset in **calldata** where to copy from (**f**) +`2` number of bytes to copy - (**s**) + +After `CODECOPY` is executed, (click the _step into_ button) the copied code should be: +`0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c63430005110032` in memory. **I'll refer to this value as (X)**. + +Let's look at the debugger's **Memory** panel. +The 0x number I gave above is not what you will see in the **Memory** panel -what you will see is this: +0x0: 6080604052600080fdfea265627a7a72 ????R??????ebzzr +0x10: 31582029bb0975555a15a155e2cf28e0 1X ?? uUZ??U???? +0x20: 25c8d492f0613bfb5cbf96399f6dbd4e ?????a?????9?m?N +0x30: a6fc9164736f6c634300051100320000 ???dsolcC????2?? +0x40: 00000000000000000000000000000000 ???????????????? +0x50: 000000000000000000000000000000a0 ??????????????? +0x60: 00000000000000000000000000000000 ???????????????? +0x70: 00000000000000000000000000000000 ???????????????? +0x80: 00000000000000000000000000000000 ???????????????? +0x90: 00000000000000000000000000000002 ???????????????? + +The `0x0`, `0x10`, etc is the position. The next number is the bytecode for that position. This is followed by question marks and seemingly random letters & numbers. This is **Remix**'s attempt to convert this into a string. + +So if we glue the first four sections of bytecode together, we'll get: +**0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e0a6fc9164736f6c63430005110032** The last section - `0x90` has 2 which is what I input for the constructors parameter. + +The input data from the **Call Data** panel is: +`0x6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c634300051100320000000000000000000000000000000000000000000000000000000000000002` +**I'll refer to this value as (Y).** + +This shows us that `(X)` is a subset of the original calldata `(Y)`: + +`(X)` is calldata without the input parameter `0000000000000000000000000000000000000000000000000000000000000002` (we don't need to store this) +and without the constructor code `6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe` which should be executed only 1 time. + +So `CODECOPY` extracts the bytecode from the calldata and copies it to the memory. + +Let's move to the next step. diff --git a/locales/ru/OpcodesInTheDebugger/7_returnAndStore/step.md b/locales/ru/OpcodesInTheDebugger/7_returnAndStore/step.md new file mode 100644 index 000000000..b375a24fb --- /dev/null +++ b/locales/ru/OpcodesInTheDebugger/7_returnAndStore/step.md @@ -0,0 +1,18 @@ +# The Opcode RETURN + +At the end of the last chapter we had moved to one step after **CODECOPY** to see what happened in the memory. + +Now that CODECOPY has been executed, we are on the opcode `PUSH1 00`. + +`PUSH1 00` prepares the stack for the `RETURN` opcode. +`RETURN` is the last part of this process. It is where the code is returned to the client. + +We push `00` to the stack because this is the offset position of the contract bytecode in memory. + +Now we can call the all important `RETURN` opcode. + +The **stack inspector** shows: +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x000000000000000000000000000000000000000000000000000000000000003e` + +Which is to say it returns to the client the bytecode starting `0x00` with length `0x3e`. diff --git a/locales/ru/OpcodesInTheDebugger/8_findTheOffset/step.md b/locales/ru/OpcodesInTheDebugger/8_findTheOffset/step.md new file mode 100644 index 000000000..6b1ddc5cf --- /dev/null +++ b/locales/ru/OpcodesInTheDebugger/8_findTheOffset/step.md @@ -0,0 +1,18 @@ +# Find the offset ;) + +And now for a slightly different example: + +- Compile notSimpleStore.sol +- Deploy the contract `notSoSimpleStore` +- Make sure you have a successful deployment - if not check that you used **the correct input type** in the constructor. +- Go to the Debugger by clicking the **debug** button at the (successful) creation transaction. +- Find the value of the parameter of `CODECOPY` which represents the offset in calldata where to copy from. + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +If you look in the **Stack**, you should see that the 2nd element is: +0x0000000000000000000000000000000000000000000000000000000000000083 + +And this is the **f** of the input params of codecopy. + +### Hope you picked up a thing or 2 about how opcodes work! diff --git a/locales/ru/OpcodesInTheDebugger/config.yml b/locales/ru/OpcodesInTheDebugger/config.yml new file mode 100644 index 000000000..74a1bf3a1 --- /dev/null +++ b/locales/ru/OpcodesInTheDebugger/config.yml @@ -0,0 +1,10 @@ +--- +id: opcodesdebug +name: Opcodes in the Debugger +summary: Using the Debugger, we'll check out what the CODECOPY opcode does and how it is used by the EVM during contract creation. +level: 3 +tags: + - Remix + - Debugging + - EVM + - Opcodes diff --git a/locales/ru/ProxyContract/1_Why/step1.md b/locales/ru/ProxyContract/1_Why/step1.md new file mode 100644 index 000000000..b4a38aaeb --- /dev/null +++ b/locales/ru/ProxyContract/1_Why/step1.md @@ -0,0 +1,27 @@ +# Proxy Contract AKA the Dispatcher + +## Why? + +This is a great pattern that is used mainly in **library development**. + +It helps in the following ways: + +- **Save gas cost at deployment time** + The purpose of a high gas cost is to discourage the operations that cost a lot for their execution and to encourage optimized code. + +- Proxy contracts are useful when a lot of instances of the same contract need to be deployed because they reduce the duplications in the deployment. + +- **Avoid code repetition in the blockchain.** + Heavy computations are expensive because every node will need to perform them, this is of course slowing the network. + +- **Develop upgradable(versioned) contracts** + When the contract is deployed, it’s immutable. By re-designing the code into different contracts, it is possible to allow logic upgrades while keeping the storage the same. + +## Example of gas cost + +Storing contract code at creation time can cost up to: + +- 200 \* max_byte_code_length gas +- 200 \* 24576 = 49152004915200 \* 10 gwei = 49152000 gwei = 0.049152 ether = 9 EUR + +see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md for more info on max_byte_code_length. diff --git a/locales/ru/ProxyContract/2_How/step2.md b/locales/ru/ProxyContract/2_How/step2.md new file mode 100644 index 000000000..d80b6557c --- /dev/null +++ b/locales/ru/ProxyContract/2_How/step2.md @@ -0,0 +1,13 @@ +# How it works? + +**EIP-7 DelegateCall** opcode allows a separate execution in another contract while maintaining the original execution context. + +All **message calls** from the user go through a **Proxy contract**. + +The **Proxy contract** then will redirect them to the **Logic contract**. + +And when you need to **upgrade** the logic, you'll **just** deploy that - **HOWEVER** - the implementation of Proxy will remain the same. + +You'll only need to update the address of Logic contract in Proxy. + +The Proxy Contract uses **Delegate calls** and **Solidity assembly** because without it, it's impossible to return any value from **delegatecall**. diff --git a/locales/ru/ProxyContract/3_Delegatecall/step3.md b/locales/ru/ProxyContract/3_Delegatecall/step3.md new file mode 100644 index 000000000..8693e5567 --- /dev/null +++ b/locales/ru/ProxyContract/3_Delegatecall/step3.md @@ -0,0 +1,9 @@ +# Delegate call + +It's a special variant of a **message call**, which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract so **msg.sender** and **msg.value** do not change their values. + +This means that a contract can dynamically load code from a different address at runtime. + +The storage, the current address and balance still refer to the calling contract, only the code is taken from the called address. + +So when a **Proxy** delegates calls to the Logic contract, every storage modification will impact the storage of Logic contract. diff --git a/locales/ru/ProxyContract/4_Generic_proxy_example/step4.md b/locales/ru/ProxyContract/4_Generic_proxy_example/step4.md new file mode 100644 index 000000000..d20fdd16d --- /dev/null +++ b/locales/ru/ProxyContract/4_Generic_proxy_example/step4.md @@ -0,0 +1,15 @@ +# A Basic Generic Proxy Example + +In the associated solidity file, **step4.sol**, there are 2 contracts - **ProxyContract** and **LogicContract**. + +To use this system, we first deploy the LogicContract. + +And then when we go to deploy the ProxyContract, we pass the LogicContract's address as an argument of the ProxyContract's constructor. + +The ProxyContract is deployed only once. + +The code of LogicContract will be called at the line 20. It will be forwarded with delegate call while keeping the context of LogicContract. + +In case we need to change the logic we would deploy a new LogicContract and set the address of it with setLogicContractAddress setter function. + +_Note: The LogicContract we have here does not use the storage. Once you need to use the storage the implementation becomes a bit more complicated because those contracts share the context._ diff --git a/locales/ru/ProxyContract/5_Test/step5.md b/locales/ru/ProxyContract/5_Test/step5.md new file mode 100644 index 000000000..120a15e13 --- /dev/null +++ b/locales/ru/ProxyContract/5_Test/step5.md @@ -0,0 +1,6 @@ +# Let's test what we've learned + +- Write a contract named "LogicContract" which implements a public function named "getNumber" which returns 10 +- Write a proxy contract named "ProxyContract". This ProxyContract should take an address of LogicContract as a first parameter. + +Good Luck! diff --git a/locales/ru/ProxyContract/6_Storage_Problem/step6.md b/locales/ru/ProxyContract/6_Storage_Problem/step6.md new file mode 100644 index 000000000..d2b804284 --- /dev/null +++ b/locales/ru/ProxyContract/6_Storage_Problem/step6.md @@ -0,0 +1,13 @@ +# What if we have state variables? + +Things are more complicated once we need to deal with state variables. State variable are saved to **storage**. + +`storage`: is a mapping; each value stored there is persisted and saved on chain. + +_Note: Statically-sized state variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position 0. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible. For contracts that use inheritance, the ordering of state variables is determined by the C3-linearized order of contracts starting with the most base-ward contract_ + +Once we execute **delegate call**, the storage of both contracts get **"merged"** into a single messy state. + +We have to "tell" ProxyContract what the **state** of the **Logic contract** looks like. + +The easiest way to do this is to create a separate contract - in this example - named **StorageContract** which will represent the **state** and which proxyContract will inherit from. diff --git a/locales/ru/ProxyContract/7_links/step7.md b/locales/ru/ProxyContract/7_links/step7.md new file mode 100644 index 000000000..c2784c3cc --- /dev/null +++ b/locales/ru/ProxyContract/7_links/step7.md @@ -0,0 +1,19 @@ +# Check out some links for more info + +- ERC DelegateProxy + https://github.com/ethereum/EIPs/pull/897 + +- The joint post by Zeppelin Solutions and Aragon. + https://blog.openzeppelin.com/proxy-libraries-in-solidity-79fbe4b970fd/ + +- Proxy Patterns by OpenZeppelin + https://blog.openzeppelin.com/proxy-patterns/ + +- The most mature implementation of Proxy pattern is The Unstructure Storage pattern that is released as part of ZeppelinOS + https://blog.openzeppelin.com/upgradeability-using-unstructured-storage/ + +- Great blog post by Jack Tanner + https://blog.indorse.io/ethereum-upgradeable-smart-contract-strategies-456350d0557c + +- Upgradeable Ethereum Smart Contracts + https://medium.com/@daonomic/upgradeable-ethereum-smart-contracts-d036cb373d6 diff --git a/locales/ru/ProxyContract/README.md b/locales/ru/ProxyContract/README.md new file mode 100644 index 000000000..6a5364c94 --- /dev/null +++ b/locales/ru/ProxyContract/README.md @@ -0,0 +1,3 @@ +## Learn the Proxy Pattern + +Save gas & make upgradable contracts diff --git a/locales/ru/ProxyContract/config.yml b/locales/ru/ProxyContract/config.yml new file mode 100644 index 000000000..e36e640b8 --- /dev/null +++ b/locales/ru/ProxyContract/config.yml @@ -0,0 +1,9 @@ +--- +id: proxycontract +name: All about Proxy Contracts +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 3 +tags: + - Remix + - Solidity + - Code Patterns diff --git a/locales/ru/README.md b/locales/ru/README.md new file mode 100644 index 000000000..cb799bd20 --- /dev/null +++ b/locales/ru/README.md @@ -0,0 +1,36 @@ +# This is a repo of tutorials for the Remix's LearnEth Plugin + +### To use these tutorials: + +**1. Open Remix** + +https://remix.ethereum.org + +**2. In the plugin manager activate LEARNETH** + +**3. Go to the Learneth plugin and these tutorials will load by default** + +**4. You may need to sign into Github especially during an in-person workshop** + +Github will block too many requests from the same location, unless you are signed into Github and have input your token. Generally, this is only an issue during in person workshops, when there can be many requests from the same location. + +To input your Github token: + +``` +- In one browser window - go to https://remix.ethereum.org and go to the settings tab +- In another browser window go to: + +https://github.com/settings/tokens + +and create a new token and save it in Remix in the you just opened on the settings tab. +``` + +--- + +### Write your own tutorials for LEARNETH: + +See this site for instructions: + +https://remix-learneth-plugin.readthedocs.io/en/latest/index.html#creating-tutorials + +--- diff --git a/locales/ru/Recorder/1_Usecases/1_usecases.md b/locales/ru/Recorder/1_Usecases/1_usecases.md new file mode 100644 index 000000000..0c624393c --- /dev/null +++ b/locales/ru/Recorder/1_Usecases/1_usecases.md @@ -0,0 +1,7 @@ +1. You want to show someone what happens when you do a number of transactions with a contract and you don't want to explain each step - you just want to get them to the last step. + + - To show someone a problem in their code. + + - In a class, to get the students to a certain place and have them start working from there. + +2. You want to start your development in the JavascriptVM because it is quick and then to switch to another testnet - but you don't want to manually repeat all the tedious clicking for each different network. diff --git a/locales/ru/Recorder/2_Record/README.md b/locales/ru/Recorder/2_Record/README.md new file mode 100644 index 000000000..41d214277 --- /dev/null +++ b/locales/ru/Recorder/2_Record/README.md @@ -0,0 +1,32 @@ +# Setting up a tedious series of steps + +## Following this could get tedious but that's the point. + +We are going to: + +- Deploy a voting contract where there are 3 proposals input in the constructor. +- Give voting privileges to 2 additional address (so we have a total of 3 voting addresses). +- Have one address vote for proposal 1 (0-based index) and the other two vote for proposal 2. + +1. Take the 3_Ballot.sol from the sample solidity files and compile it. Then go to the **Deploy & Run** Module. + +2. Select the **JavaScript VM** Environment. + +3. In the constructor's parameter - put in **["0x5031000000000000000000000000000000000000000000000000000000000000", "0x5032000000000000000000000000000000000000000000000000000000000000", "0x5033000000000000000000000000000000000000000000000000000000000000"]** Then click the **Deploy** button. + +4. Open up the deployed contract. + +5. In the **vote** function put in 2. This means that you as the msg.sender & chairperson are voting for proposal at position 2, which is the last proposal in our list. + +6. Now you need to give other addresses the right to vote. Select another address in the **account** pulldown and copy it and then **go back to the 1st address**. Paste the copy address into the textbox next to the giveRightToVote function. And again, select another address and copy it and **then go back to the 1st address** again and paste it into giveRightToVote. + +7. Now you have 3 addresses with the right to vote. + +8. Switch to one of the addresses that you gave the right to vote and vote for proposal **1**. (Put **1** in the textbox next to the vote function). And then switch to the other address and vote for proposal **2** with that one. + +9. Open up the **Transactions recorded** section of the module - by clicking on the caret. Click the hard disk icon in the **Transactions recorded** section to save your steps. + ![recorder](https://github.com/ethereum/remix-workshops/blob/master/Recorder/2_Record/images/recorder.png?raw=true "recorder") + +10. You will get a modal window that tells you it wants to save a file called **scenario.json**. Click OK. + +11. Click on the function **winningProposal** to confirm that the final proposal won - which is the proposal at position 2 in the array. **0: uint256: winningProposal_ 2** diff --git a/locales/ru/Recorder/3_Editing_a_Senario/README.md b/locales/ru/Recorder/3_Editing_a_Senario/README.md new file mode 100644 index 000000000..d23dfb95c --- /dev/null +++ b/locales/ru/Recorder/3_Editing_a_Senario/README.md @@ -0,0 +1,54 @@ +# Editing a scenario + +Here's the first few lines of the scenario that I recorded. The addresses on my machine will be different from your's. + +``` +{ + "accounts": { + "account{0}": "0xca35b7d915458ef540ade6068dfe2f44e8fa733c", + "account{4}": "0xdd870fa1b7c4700f2bd7f44238821c26f7392148", + "account{3}": "0x583031d1113ad414f02576bd6afabfb302140225" + } +``` + +So if you wanted to play this scenario in another testnet, you'd need to change these addresses to address that you have test ETH on so that you could pay for the transactions. But other than swapping out the addresses, you can quickly run this on other nets. + +And you might change the parameters for the functions. + +For example here is a bit of the scenario.json a bit further down where proposal 2 was voted for by one of the addresses: + +``` +{ + "timestamp": 1566428184043, + "record": { + "value": "0", + "parameters": [ + "2" + ], + "to": "created{1566428035436}", + "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", + "name": "vote", + "inputs": "(uint8)", + "type": "function", + "from": "account{4}" + } + }, +``` + +Let's edit this so that another proposal wins in the playback. + +Change the **parameters** array which now is: + +``` +"parameters": [ + "2" + ] +``` + +to: + +``` +"parameters": [ + "1" + ] +``` diff --git a/locales/ru/Recorder/4_Play/README.md b/locales/ru/Recorder/4_Play/README.md new file mode 100644 index 000000000..196664550 --- /dev/null +++ b/locales/ru/Recorder/4_Play/README.md @@ -0,0 +1,8 @@ +# Playing a scenario + +1. Click the play icon to the right of the floppy disk icon to play the steps you did. + +2. You'll see another instance of the contract deployed. Open it up. + +3. Click the winningProposal function and you should see now that proposal 1 won. + It should print out: **0: uint256: winningProposal_ 1** diff --git a/locales/ru/Recorder/README.md b/locales/ru/Recorder/README.md new file mode 100644 index 000000000..94d928383 --- /dev/null +++ b/locales/ru/Recorder/README.md @@ -0,0 +1,3 @@ +## Get yourself Remixing! + +The recorder is used for recording a set of transactions in the Deploy & Run module, editing their parameters and then playing them back in another context. It really is the remix of Remix! diff --git a/locales/ru/Recorder/config.yml b/locales/ru/Recorder/config.yml new file mode 100644 index 000000000..b8980e042 --- /dev/null +++ b/locales/ru/Recorder/config.yml @@ -0,0 +1,7 @@ +--- +id: recorder +name: Recorder +summary: Save a set of actions and replay and replay and replay +level: 2 +tags: + - Remix diff --git a/locales/ru/SolidityBeginnerCourse/README.md b/locales/ru/SolidityBeginnerCourse/README.md new file mode 100644 index 000000000..ae0b6d882 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Course + +Learn the most important Solidity beginner concepts interactively, based on the popular https://solidity-by-example.org/ contracts. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ru/SolidityBeginnerCourse/basic-syntax/basicSyntax.md b/locales/ru/SolidityBeginnerCourse/basic-syntax/basicSyntax.md new file mode 100644 index 000000000..e9f77871e --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/basic-syntax/basicSyntax.md @@ -0,0 +1,26 @@ +In this section, we will create our first _smart contract_. This contract only consists of a string that holds the value "Hello World!". + +In the first line, we should specify the license that we want to use. You can find a comprehensive list of licenses here: https://spdx.org/licenses/. + +Using the `pragma` keyword (line 3), we specify the Solidity version we want the compiler to use. In this case, it should be greater than or equal to `0.8.3` but less than 0.9.0. + +We define a contract with the keyword `contract` and give it a name, in this case, `HelloWorld` (line 5). + +Inside our contract, we define a _state variable_ `greet` that holds the string `"Hello World!"` (line 6). + +Solidity is a _statically typed_ language, which means that you need to specify the type of the variable when you declare it. In this case, `greet` is a `string`. + +We also define the _visibility_ of the variable, which specifies from where you can access it. In this case, it's a `public` variable that you can access from inside and outside the contract. + +Don't worry if you didn't understand some concepts like _visibility_, _data types_, or _state variables_. We will look into them in the following sections. + +To help you understand the code, we will link in all following sections to video tutorials from the creator of the Solidity by Example contracts. + +Watch a video tutorial on Basic Syntax. + +## ⭐️ Assignment + +1. Delete the HelloWorld contract and its content. +2. Create a new contract named "MyContract". +3. The contract should have a public state variable called "name" of the type string. +4. Assign the value "Alice" to your new variable. diff --git a/locales/ru/SolidityBeginnerCourse/config.yml b/locales/ru/SolidityBeginnerCourse/config.yml new file mode 100644 index 000000000..a729093d8 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/config.yml @@ -0,0 +1,65 @@ +--- +id: soliditybeginner +name: Solidity Beginner Course +summary: Solidity Beginner Course based on the popular https://solidity-by-example.org/ contracts. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Basic Syntax + path: basic-syntax + - + name: 3. Primitive Data Types + path: primitive-data-types + - + name: 4. Variables + path: variables + - + name: 5.1 Functions - Reading and Writing to a State Variable + path: functions-reading-and-writing + - + name: 5.2 Functions - View and Pure + path: functions-view-and-pure + - + name: 5.3 Functions - Modifiers and Constructors + path: functions-modifiers-and-constructors + - + name: 5.4 Functions - Inputs and Outputs + path: functions-inputs-and-outputs + - + name: 6. Visibility + path: visibility + - + name: 7.1 Control Flow - If/Else + path: control-flow-if-else + - + name: 7.2 Control Flow - Loops + path: control-flow-loops + - + name: 8.1 Data Structures - Arrays + path: data-structures-arrays + - + name: 8.2 Data Structures - Mappings + path: data-structures-mappings + - + name: 8.3 Data Structures - Structs + path: data-structures-structs + - + name: 8.4 Data Structures - Enums + path: data-structures-enums + - + name: 9. Data Locations + path: data-locations + - + name: 10.1 Transactions - Ether and Wei + path: transactions-ether-and-wei + - + name: 10.2 Transactions - Gas and Gas Price + path: transactions-gas-and-gas-price + - + name: 10.3 Transactions - Sending Ether + path: transactions-sending-ether diff --git a/locales/ru/SolidityBeginnerCourse/control-flow-if-else/ifElse.md b/locales/ru/SolidityBeginnerCourse/control-flow-if-else/ifElse.md new file mode 100644 index 000000000..634e27689 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/control-flow-if-else/ifElse.md @@ -0,0 +1,33 @@ +Solidity supports different control flow statements that determine which parts of the contract will be executed. The conditional _If/Else statement_ enables contracts to make decisions depending on whether boolean conditions are either `true` or `false`. + +Solidity differentiates between three different If/Else statements: `if`, `else`, and `else if`. + +### if + +The `if` statement is the most basic statement that allows the contract to perform an action based on a boolean expression. + +In this contract’s `foo` function (line 5) the if statement (line 6) checks if `x` is smaller than `10`. If the statement is true, the function returns `0`. + +### else + +The `else` statement enables our contract to perform an action if conditions are not met. + +In this contract, the `foo` function uses the `else` statement (line 10) to return `2` if none of the other conditions are met. + +### else if + +With the `else if` statement we can combine several conditions. + +If the first condition (line 6) of the foo function is not met, but the condition of the `else if` statement (line 8) becomes true, the function returns `1`. + +Watch a video tutorial on the If/Else statement. + +## ⭐️ Assignment + +Create a new function called `evenCheck` in the `IfElse` contract: + +- That takes in a `uint` as an argument. +- The function returns `true` if the argument is even, and `false` if the argument is odd. +- Use a ternery operator to return the result of the `evenCheck` function. + +Tip: The modulo (%) operator produces the remainder of an integer division. diff --git a/locales/ru/SolidityBeginnerCourse/control-flow-loops/loops.md b/locales/ru/SolidityBeginnerCourse/control-flow-loops/loops.md new file mode 100644 index 000000000..ffaa30650 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/control-flow-loops/loops.md @@ -0,0 +1,32 @@ +Solidity supports iterative control flow statements that allow contracts to execute code repeatedly. + +Solidity differentiates between three types of loops: `for`, `while`, and `do while` loops. + +### for + +Generally, `for` loops (line 7) are great if you know how many times you want to execute a certain block of code. In solidity, you should specify this amount to avoid transactions running out of gas and failing if the amount of iterations is too high. + +### while + +If you don’t know how many times you want to execute the code but want to break the loop based on a condition, you can use a `while` loop (line 20). +Loops are seldom used in Solidity since transactions might run out of gas and fail if there is no limit to the number of iterations that can occur. + +### do while + +The `do while` loop is a special kind of while loop where you can ensure the code is executed at least once, before checking on the condition. + +### continue + +The `continue` statement is used to skip the remaining code block and start the next iteration of the loop. In this contract, the `continue` statement (line 10) will prevent the second if statement (line 12) from being executed. + +### break + +The `break` statement is used to exit a loop. In this contract, the break statement (line 14) will cause the for loop to be terminated after the sixth iteration. + +Watch a video tutorial on Loop statements. + +## ⭐️ Assignment + +1. Create a public `uint` state variable called count in the `Loop` contract. +2. At the end of the for loop, increment the count variable by 1. +3. Try to get the count variable to be equal to 9, but make sure you don’t edit the `break` statement. diff --git a/locales/ru/SolidityBeginnerCourse/data-locations/dataLocations.md b/locales/ru/SolidityBeginnerCourse/data-locations/dataLocations.md new file mode 100644 index 000000000..881bf8ffc --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/data-locations/dataLocations.md @@ -0,0 +1,54 @@ +The values of variables in Solidity can be stored in different data locations: _memory_, _storage_, and _calldata_. + +As we have discussed before, variables of the value type store an independent copy of a value, while variables of the reference type (array, struct, mapping) only store the location (reference) of the value. + +If we use a reference type in a function, we have to specify in which data location their values are stored. The price for the execution of the function is influenced by the data location; creating copies from reference types costs gas. + +### Storage + +Values stored in _storage_ are stored permanently on the blockchain and, therefore, are expensive to use. + +In this contract, the state variables `arr`, `map`, and `myStructs` (lines 5, 6, and 10) are stored in storage. State variables are always stored in storage. + +### Memory + +Values stored in _memory_ are only stored temporarily and are not on the blockchain. They only exist during the execution of an external function and are discarded afterward. They are cheaper to use than values stored in _storage_. + +In this contract, the local variable `myMemstruct` (line 19), as well as the parameter `_arr` (line 31), are stored in memory. Function parameters need to have the data location _memory_ or _calldata_. + +### Calldata + +_Calldata_ stores function arguments. Like _memory_, _calldata_ is only stored temporarily during the execution of an external function. In contrast to values stored in _memory_, values stored in _calldata_ can not be changed. Calldata is the cheapest data location to use. + +In this contract, the parameter `_arr` (line 35) has the data location _calldata_. If we wanted to assign a new value to the first element of the array `_arr`, we could do that in the `function g` (line 31) but not in the `function h` (line 35). This is because `_arr` in `function g `has the data location _memory_ and _function h_ has the data location `calldata`. + +## Assignments + +### Memory to memory + +Assignments from _memory_ to _memory_ create references instead of copies. If you change the value in one variable, the value of all other variables that reference the same data will be changed. + +If we were to create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myMemStruct` (line 19), any change to `myMemStruct2` would also change the value of `myMemStruct`. + +### Storage to local storage + +Assignments from _storage_ to _local storage_ also create references, not copies. + +If we change the value of the local variable `myStruct` (line 17), the value of our state variable `myStructs` (line 10) changes as well. + +## Storage and memory/calldata + +Assignments between _storage_ and _memory_ (or _calldata_) create independent copies, not references. + +If we were to create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myStruct`, changes in `myMemStruct3` would not affect the values stored in the mapping `myStructs` (line 10). + +As we said in the beginning, when creating contracts we have to be mindful of gas costs. Therefore, we need to use data locations that require the lowest amount of gas possible. + +## ⭐️ Assignment + +1. Change the value of the `myStruct` member `foo`, inside the `function f`, to 4. +2. Create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` and assign it the value of `myMemStruct`. Change the value of the `myMemStruct2` member `foo` to 1. +3. Create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` and assign it the value of `myStruct`. Change the value of the `myMemStruct3` member `foo` to 3. +4. Let the function f return `myStruct`, `myMemStruct2`, and `myMemStruct3`. + +Tip: Make sure to create the correct return types for the function `f`. diff --git a/locales/ru/SolidityBeginnerCourse/data-structures-arrays/arrays.md b/locales/ru/SolidityBeginnerCourse/data-structures-arrays/arrays.md new file mode 100644 index 000000000..19af3de49 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/data-structures-arrays/arrays.md @@ -0,0 +1,44 @@ +In the next sections, we will look into the data structures that we can use to organize and store our data in Solidity. + +_Arrays_, _mappings_ and _structs_ are all _reference types_. Unlike _value types_ (e.g. _booleans_ or _integers_) reference types don't store their value directly. Instead, they store the location where the value is being stored. Multiple reference type variables could reference the same location, and a change in one variable would affect the others, therefore they need to be handled carefully. + +In Solidity, an array stores an ordered list of values of the same type that are indexed numerically. + +There are two types of arrays, compile-time _fixed-size_ and _dynamic arrays_. For fixed-size arrays, we need to declare the size of the array before it is compiled. The size of dynamic arrays can be changed after the contract has been compiled. + +### Declaring arrays + +We declare a fixed-size array by providing its type, array size (as an integer in square brackets), visibility, and name (line 9). + +We declare a dynamic array in the same manner. However, we don’t provide an array size and leave the brackets empty (line 6). + +### Initializing arrays + +We can initialize the elements of an array all at once (line 7), or initiate new elements one by one (arr[0] = 1;). If we declare an array, we automatically initialize its elements with the default value 0 (line 9). + +### Accessing array elements + +We access elements inside an array by providing the name of the array and the index in brackets (line 12). + +### Adding array elements + +Using the `push()` member function, we add an element to the end of a dynamic array (line 25). + +### Removing array elements + +Using the `pop()` member function, we delete the last element of a dynamic array (line 31). + +We can use the `delete` operator to remove an element with a specific index from an array (line 42). +When we remove an element with the `delete` operator all other elements stay the same, which means that the length of the array will stay the same. This will create a gap in our array. +If the order of the array is not important, then we can move the last element of the array to the place of the deleted element (line 46), or use a mapping. A mapping might be a better choice if we plan to remove elements in our data structure. + +### Array length + +Using the length member, we can read the number of elements that are stored in an array (line 35). + +Watch a video tutorial on Arrays. + +## ⭐️ Assignment + +1. Initialize a public fixed-sized array called `arr3` with the values 0, 1, 2. Make the size as small as possible. +2. Change the `getArr()` function to return the value of `arr3`. diff --git a/locales/ru/SolidityBeginnerCourse/data-structures-enums/enums.md b/locales/ru/SolidityBeginnerCourse/data-structures-enums/enums.md new file mode 100644 index 000000000..40411db67 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/data-structures-enums/enums.md @@ -0,0 +1,33 @@ +In Solidity _enums_ are custom data types consisting of a limited set of constant values. We use enums when our variables should only get assigned a value from a predefined set of values. + +In this contract, the state variable `status` can get assigned a value from the limited set of provided values of the enum `Status` representing the various states of a shipping status. + +### Defining enums + +We define an enum with the enum keyword, followed by the name of the custom type we want to create (line 6). Inside the curly braces, we define all available members of the enum. + +### Initializing an enum variable + +We can initialize a new variable of an enum type by providing the name of the enum, the visibility, and the name of the variable (line 16). Upon its initialization, the variable will be assigned the value of the first member of the enum, in this case, Pending (line 7). + +Even though enum members are named when you define them, they are stored as unsigned integers, not strings. They are numbered in the order that they were defined, the first member starting at 0. The initial value of status, in this case, is 0. + +### Accessing an enum value + +To access the enum value of a variable, we simply need to provide the name of the variable that is storing the value (line 25). + +### Updating an enum value + +We can update the enum value of a variable by assigning it the `uint` representing the enum member (line 30). Shipped would be 1 in this example. Another way to update the value is using the dot operator by providing the name of the enum and its member (line 35). + +### Removing an enum value + +We can use the delete operator to delete the enum value of the variable, which means as for arrays and mappings, to set the default value to 0. + +Watch a video tutorial on Enums. + +## ⭐️ Assignment + +1. Define an enum type called `Size` with the members `S`, `M`, and `L`. +2. Initialize the variable `sizes` of the enum type `Size`. +3. Create a getter function `getSize()` that returns the value of the variable `sizes`. diff --git a/locales/ru/SolidityBeginnerCourse/data-structures-mappings/mappings.md b/locales/ru/SolidityBeginnerCourse/data-structures-mappings/mappings.md new file mode 100644 index 000000000..72fc4acb4 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/data-structures-mappings/mappings.md @@ -0,0 +1,37 @@ +In Solidity, _mappings_ are a collection of key types and corresponding value type pairs. + +The biggest difference between a mapping and an array is that you can't iterate over mappings. If we don't know a key we won't be able to access its value. If we need to know all of our data or iterate over it, we should use an array. + +If we want to retrieve a value based on a known key we can use a mapping (e.g. addresses are often used as keys). Looking up values with a mapping is easier and cheaper than iterating over arrays. If arrays become too large, the gas cost of iterating over it could become too high and cause the transaction to fail. + +We could also store the keys of a mapping in an array that we can iterate over. + +### Creating mappings + +Mappings are declared with the syntax `mapping(KeyType => ValueType) VariableName`. +The key type can be any built-in value type or any contract, but not a reference type. The value type can be of any type. + +In this contract, we are creating the public mapping `myMap` (line 6) that associates the key type `address` with the value type `uint`. + +### Accessing values + +The syntax for interacting with key-value pairs of mappings is similar to that of arrays. +To find the value associated with a specific key, we provide the name of the mapping and the key in brackets (line 11). + +In contrast to arrays, we won't get an error if we try to access the value of a key whose value has not been set yet. When we create a mapping, every possible key is mapped to the default value 0. + +### Setting values + +We set a new value for a key by providing the mapping’s name and key in brackets and assigning it a new value (line 16). + +### Removing values + +We can use the delete operator to delete a value associated with a key, which will set it to the default value of 0. As we have seen in the arrays section. + +Watch a video tutorial on Mappings. + +## ⭐️ Assignment + +1. Create a public mapping `balances` that associates the key type `address` with the value type `uint`. +2. Change the functions `get` and `remove` to work with the mapping balances. +3. Change the function `set` to create a new entry to the balances mapping, where the key is the address of the parameter and the value is the balance associated with the address of the parameter. diff --git a/locales/ru/SolidityBeginnerCourse/data-structures-structs/structs.md b/locales/ru/SolidityBeginnerCourse/data-structures-structs/structs.md new file mode 100644 index 000000000..fba0d93b0 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/data-structures-structs/structs.md @@ -0,0 +1,29 @@ +In Solidity, we can define custom data types in the form of _structs_. Structs are a collection of variables that can consist of different data types. + +### Defining structs + +We define a struct using the `struct` keyword and a name (line 5). Inside curly braces, we can define our struct’s members, which consist of the variable names and their data types. + +### Initializing structs + +There are different ways to initialize a struct. + +Positional parameters: We can provide the name of the struct and the values of its members as parameters in parentheses (line 16). + +Key-value mapping: We provide the name of the struct and the keys and values as a mapping inside curly braces (line 19). + +Initialize and update a struct: We initialize an empty struct first and then update its member by assigning it a new value (line 23). + +### Accessing structs + +To access a member of a struct we can use the dot operator (line 33). + +### Updating structs + +To update a structs’ member we also use the dot operator and assign it a new value (lines 39 and 45). + +Watch a video tutorial on Structs. + +## ⭐️ Assignment + +Create a function `remove` that takes a `uint` as a parameter and deletes a struct member with the given index in the `todos` mapping. diff --git a/locales/ru/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md b/locales/ru/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md new file mode 100644 index 000000000..d0e628f6b --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md @@ -0,0 +1,37 @@ +In this section, we will learn more about the inputs and outputs of functions. + +### Multiple named Outputs + +Functions can return multiple values that can be named and assigned to their name. + +The `returnMany` function (line 6) shows how to return multiple values. +You will often return multiple values. It could be a function that collects outputs of various functions and returns them in a single function call for example. + +The `named` function (line 19) shows how to name return values. +Naming return values helps with the readability of your contracts. Named return values make it easier to keep track of the values and the order in which they are returned. You can also assign values to a name. + +The `assigned` function (line 33) shows how to assign values to a name. +When you assign values to a name you can omit (leave out) the return statement and return them individually. + +### Deconstructing Assignments + +You can use deconstructing assignments to unpack values into distinct variables. + +The `destructingAssigments` function (line 49) assigns the values of the `returnMany` function to the new local variables `i`, `b`, and `j` (line 60). + +### Input and Output restrictions + +There are a few restrictions and best practices for the input and output parameters of contract functions. + +"_[Mappings] cannot be used as parameters or return parameters of contract functions that are publicly visible._" +From the Solidity documentation. + +Arrays can be used as parameters, as shown in the function `arrayInput` (line 71). Arrays can also be used as return parameters as shown in the function `arrayOutput` (line 76). + +You have to be cautious with arrays of arbitrary size because of their gas consumption. While a function using very large arrays as inputs might fail when the gas costs are too high, a function using a smaller array might still be able to execute. + +Watch a video tutorial on Function Outputs. + +## ⭐️ Assignment + +Create a new function called `returnTwo` that returns the values `-2` and `true` without using a return statement. diff --git a/locales/ru/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md b/locales/ru/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md new file mode 100644 index 000000000..d707a987b --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md @@ -0,0 +1,39 @@ +In this section, we will learn how to modify the behavior of a function and how to run contract initialization code. + +### Function Modifier + +_Function Modifiers_ are used to change the behavior of a function. For example, they often check for a condition prior to executing a function to restrict access or validate inputs. + +This first part of this contract is about changing ownership of a contract. Ownership in this contract is expressed by the value of the state variable `owner` that is of the type `address` (line 7). + +The function `changeOwner` (line 33) can change this ownership. It takes an input parameter of the type `address` and assigns its value to the state variable `owner`. + +However, this function cannot simply be executed under all conditions; it has two modifiers, `onlyOwner` and `validAddress`. + +Let's look at `onlyOwner` first (line 18). +Function modifiers are defined with the `modifier` keyword and a unique name; they can also have parameters. + +The underscore `_` (line 23) is used inside modifiers to represent the rest of the code that will be executed in the body of the modified function. +The code you place before the underscore in the modifier will be executed before the code in the body of the modified function. The code after the underscore will be executed after the code in the body of the modified function. + +In this case, the `require` function (line 19) checks if the address executing the contract is the same as the value stored in the variable `owner`. If it is, the rest of the code will be executed, otherwise it will throw an error. + +You can learn more about `assert` and `require` in the Solidity documentation, they are used to check for conditions and throw errors if they are not met. + +The `validAddress` modifier (line 28) has a parameter of type `address` and checks if the provided address is valid. If it is, it continues to execute the code. + +### Constructor + +A constructor function is executed upon the creation of a contract. You can use it to run contract initialization code. The constructor can have parameters and is especially useful when you don't know certain initialization values before the deployment of the contract. + +You declare a constructor using the `constructor` keyword. The constructor in this contract (line 11) sets the initial value of the owner variable upon the creation of the contract. + +Watch a video tutorial on Function Modifiers. + +## ⭐️ Assignment + +1. Create a new function, `increaseX` in the contract. The function should take an input parameter of type `uint` and increase the value of the variable `x` by the value of the input parameter. +2. Make sure that x can only be increased. +3. The body of the function `increaseX` should be empty. + +Tip: Use modifiers. diff --git a/locales/ru/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md b/locales/ru/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md new file mode 100644 index 000000000..3670c03e2 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md @@ -0,0 +1,23 @@ +This section will give a short introduction to functions and teach you how to use them to read from and write to a state variable. + +As in other languages, we use functions in Solidity to create modular, reusable code. However, Solidity functions have some particularities. + +Solidity functions can be split into two types: + +1. Functions that modify the state of the blockchain, like writing to a state variable. In this contract, the `set` function (line 9) changes the state variable `num`. +2. Functions that don't modify the state of the blockchain. These functions are marked `view` or `pure`. For example, in this contract, the `get` function (line 14) marked `view` that only returns `num` does not change the state. + +To define a function, use the `function` keyword followed by a unique name. + +If the function takes inputs like our `set` function (line 9), you must specify the parameter types and names. A common convention is to use an underscore as a prefix for the parameter name to distinguish them from state variables. + +You can then set the visibility of a function and declare them `view` or `pure` as we do for the `get` function if they don't modify the state. Our `get` function also returns values, so we have to specify the return types. In this case, it's a `uint` since the state variable `num` that the function returns is a `uint`. + +We will explore the particularities of Solidity functions in more detail in the following sections. + +Watch a video tutorial on Functions. + +## ⭐️ Assignment + +1. Create a public state variable called `b` that is of type `bool` and initialize it to `true`. +2. Create a public function called `get_b` that returns the value of `b`. diff --git a/locales/ru/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md b/locales/ru/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md new file mode 100644 index 000000000..b846c7d99 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md @@ -0,0 +1,44 @@ +This section will look into the types of functions that don't modify the state of the blockchain: _view_ and _pure_ functions. + +### View Functions + +_View functions_ promise to not modify the state. + +"The following statements are considered modifying the state: + +1. Writing to state variables. +2. Emitting events. +3. Creating other contracts. +4. Using selfdestruct. +5. Sending Ether via calls. +6. Calling any function not marked view or pure. +7. Using low-level calls. +8. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a view function using the keyword `view`. In this contract, `addToX` (line 8) is a view function. This function takes the parameter `y` and returns the sum of the parameter and the state variable `x`. It reads `x` but does not modify it. + +### Pure functions + +_Pure functions_ promise to neither modify nor to read the state. + +"In addition to the list of state modifying statements explained above, the following are considered reading from the state: + +1. Reading from state variables. +2. Accessing `address(this).balance` or `
.balance`. +3. Accessing any of the members of block, tx, msg (with the exception of `msg.sig` and `msg.data`). +4. Calling any function not marked pure. +5. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a pure function using the keyword `pure`. In this contract, `add` (line 13) is a pure function. This function takes the parameters `i` and `j`, and returns the sum of them. It neither reads nor modifies the state variable `x`. + +In Solidity development, you need to optimise your code for saving computation cost (gas cost). Declaring functions view and pure can save gas cost and make the code more readable and easier to maintain. Pure functions don't have any side effects and will always return the same result if you pass the same arguments. + +Watch a video tutorial on View and Pure Functions. + +## ⭐️ Assignment + +Create a function called `addToX2` that takes the parameter `y` and updates the state variable `x` with the sum of the parameter and the state variable `x`. diff --git a/locales/ru/SolidityBeginnerCourse/introduction/introduction.md b/locales/ru/SolidityBeginnerCourse/introduction/introduction.md new file mode 100644 index 000000000..cc821a46a --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/introduction/introduction.md @@ -0,0 +1,32 @@ +Welcome to this interactive Solidity course for beginners. + +In this first section, we will give you a short preview of the concepts we will cover in this course, look at an example smart contract, and show you how you can interact with this contract in the Remix IDE. + +This contract is a counter contract that has the functionality to increase, decrease, and return the state of a counter variable. + +If we look at the top of the contract, we can see some information about the contract like the license (line 1), the Solidity version (line 2), as well as the keyword `contract` and it's name, `Counter` (line 4). We will cover these concepts in the next section about the **Basic Syntax**. + +With `uint public count` (line 5) we declare a state variable of the type `uint` with the visibility `public`. We will cover these concepts in our sections about **Variables**, **Primitive Data Types**, and **Visibility**. + +We then create a `get` function (line 8) that is defined with the `view` keyword and returns a `uint` type. Specifically, it returns the `count` variable. This contract has two more functions, an `inc` (line 13) and `dec` (line 18) function that increases or decreases our count variable. +We will talk about these concepts in our sections about **Functions - Reading and Writing to a State Variable** and **Functions - View and pure**. + +## Compile and Deploy through Remix + +**GIF** Interacting with the contract: Compile and deploy contract + +1. We can compile your `Counter` contract in the "Solidity compiler" module of the Remix IDE. + +2. In the "Deploy & run transactions" module, we select our contract "Counter" in the contract input field and click on the "Deploy" button. + +3. We expand the token contract functions in the IDE, and test its `get`, `inc`, and `dec` functions. + +## ⭐️ Assignment + +Throughout this course, we will give you assignments to test and consolidate your newly acquired knowledge. + +Your first assignment is to: + +1. Compile this contract. +2. Deploy it to the Remix VM. +3. Interact with your contract. diff --git a/locales/ru/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md b/locales/ru/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md new file mode 100644 index 000000000..9ea6b8626 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md @@ -0,0 +1,33 @@ +In this section, we will show you Solidity’s primitive data types, how to declare them, and their characteristics. + +### bool + +You can declare data a boolean type by using the keyword ‘bool’. Booleans can either have the value `true` or `false`. + +### uint + +We use the keywords `uint` and `uint8` to `uint256` to declare an _unsigned integer type_ (they don’t have a sign, unlike -12, for example). Uints are integers that are positive or zero and range from 8 bits to 256 bits. The type `uint` is the same as `uint256`. + +### int + +We use the keywords `int` and `int8` to `int256` to declare an integer type. Integers can be positive, negative, or zero and range from 8 bits to 256 bits. The type `int` is the same as `int256`. + +### address + +Variables of the type `address` hold a 20-byte value, which is the size of an Ethereum address. There is also a special kind of Ethereum address, `address payable`, which can receive ether from the contract. + +All these data types have default values, as shown in the contract (line 29). + +You can learn more about these data types as well as _Fixed Point Numbers_, _Byte Arrays_, _Strings_, and more in the Solidity documentation. + +Later in the course, we will look at data structures like **Mappings**, **Arrays**, **Enums**, and **Structs**. + +Watch a video tutorial on Primitive Data Types. + +## ⭐️ Assignment + +1. Create a new variable `newAddr` that is a `public` `address` and give it a value that is not the same as the available variable `addr`. +2. Create a `public` variable called `neg` that is a negative number, decide upon the type. +3. Create a new variable, `newU` that has the smallest `uint` size type and the smallest `uint` value and is `public`. + +Tip: Look at the other address in the contract or search the internet for an Ethereum address. diff --git a/locales/ru/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md b/locales/ru/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md new file mode 100644 index 000000000..57208c555 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md @@ -0,0 +1,26 @@ +_Ether_ (ETH) is a cryptocurrency. _Ether_ is also used to pay fees for using the Ethereum network, like making transactions in the form of sending _Ether_ to an address or interacting with an Ethereum application. + +### Ether Units + +To specify a unit of _Ether_, we can add the suffixes `wei`, `gwei`, or `ether` to a literal number. + +#### `wei` + +_Wei_ is the smallest subunit of _Ether_, named after the cryptographer [Wei Dai](https://en.wikipedia.org/wiki/Wei_Dai). _Ether_ numbers without a suffix are treated as `wei` (line 7). + +#### `gwei` + +One `gwei` (giga-wei) is equal to 1,000,000,000 (10^9) `wei`. + +#### `ether` + +One `ether` is equal to 1,000,000,000,000,000,000 (10^18) `wei` (line 11). + +Watch a video tutorial on Ether and Wei. + +## ⭐️ Assignment + +1. Create a `public` `uint` called `oneGWei` and set it to 1 `gwei`. +2. Create a `public` `bool` called `isOneGWei` and set it to the result of a comparison operation between 1 gwei and 10^9. + +Tip: Look at how this is written for `gwei` and `ether` in the contract. diff --git a/locales/ru/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md b/locales/ru/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md new file mode 100644 index 000000000..bbc25575c --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md @@ -0,0 +1,29 @@ +As we have seen in the previous section, executing code via transactions on the Ethereum Network costs transaction fees in the form of Ether. The amount of fees that have to be paid to execute a transaction depends on the amount of _gas_ that the execution of the transaction costs. + +### Gas + +_Gas_ is the unit that measures the amount of computational effort that is required to execute a specific operation on the Ethereum network. + +### Gas price + +The _gas_ that fuels Ethereum is sometimes compared to the gas that fuels a car. The amount of gas your car consumes is mostly the same, but the price you pay for gas depends on the market. + +Similarly, the amount of _gas_ that a transaction requires is always the same for the same computational work that is associated with it. However the price that the sender of the transaction is willing to pay for the _gas_ is up to them. Transactions with higher _gas prices_ are going through faster; transactions with very low _gas prices_ might not go through at all. + +When sending a transaction, the sender has to pay the _gas_ fee (gas_price \* gas) upon execution of the transaction. If _gas_ is left over after the execution is completed, the sender gets refunded. + +_Gas_ prices are denoted in gwei. + +### Gas limit + +When sending a transaction, the sender specifies the maximum amount of gas that they are willing to pay for. If they set the limit too low, their transaction can run out of _gas_ before being completed, reverting any changes being made. In this case, the _gas_ was consumed and can’t be refunded. + +Learn more about _gas_ on ethereum.org. + +Watch a video tutorial on Gas and Gas Price. + +## ⭐️ Assignment + +Create a new `public` state variable in the `Gas` contract called `cost` of the type `uint`. Store the value of the gas cost for deploying the contract in the new variable, including the cost for the value you are storing. + +Tip: You can check in the Remix terminal the details of a transaction, including the gas cost. You can also use the Remix plugin _Gas Profiler_ to check for the gas cost of transactions. diff --git a/locales/ru/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md b/locales/ru/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md new file mode 100644 index 000000000..58fb4c5a6 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md @@ -0,0 +1,86 @@ +In this section, we will learn how a contract can send and receive Ether. + +### Sending Ether + +We have three different options to transfer Ether: `transfer()`, `send()` and `call()`. + +#### **transfer** + +`
.transfer(uint256 amount)` + +- `transfer()` throws an exception on failure +- Forwards a fixed 2300 gas stipend + +An example of `transfer()` can be seen in the `SendEther` contract (line 35). +**`Transfer()` is not recommended to be used anymore.** + +#### **send** + +`
.send(uint256 amount) returns (bool)` + +- `send()` returns false on failure +- Forwards a fixed 2300 gas stipend + +An example of `send()` can be seen in the `SendEther` contract (line 41). +**`Send()` is not recommended to be used anymore.** + +#### **call** + +`
.call(bytes memory) returns (bool, bytes memory)` + +- `call()` returns false on failure +- Forwards the maximum amount of gas, but this is adjustable + +An example of `call()` can be seen in the `SendEther` contract (line 48). +`Call()` is currently recommended if you are transfering Ether. + +The reason `transfer()` and `send()` were introduced was to guard against _reentry attacks_ by limiting the forwarded gas to 2300, which would be insufficient to make a reentrant call that can modify storage. + +As we discussed in the last section, each operation on Ethereum has a specific cost associated with it. Certain operations have become more cost intensive over time, so the gas costs associated with them are also raised. When gas costs for operations are subject to change it is not good to use a hardcoded gas amount like transfer(), and send() do. + +That’s why `call()` instead of `transfer()` is now recommended to send Ether. + +Learn more about the subject in this Consensys blog post. + +### Reentrancy attack + +A _reentrancy attack_ occurs when a function makes an external call to an untrusted contract and the attacker uses the contract to make recursive calls back to the original function before it finishes its execution. Through this method, the attacker can drain funds and manipulate data in unintended ways. + +To guard against a _reentrancy attack_, all state changes should be made before calling an external contract. This is also called the Checks-Effects-Interactions pattern. + +Another way to prevent reentrancy is to use a _Reentrancy Guard_ that checks for such calls and rejects them. You can see an example of this in the contract in our modifier section or a more gas-efficient version on Open Zepplin. + +### Receiving Ether + +If we want to enable a contract to receive Ether without a function being called, we need to create a `receive` function (line 22) or a `fallback` function (line 25); otherwise, the Ether will be rejected, and the contract will throw an exception. + +The `receive` function is executed on calls with empty calldata (e.g. plain Ether transfers via send() or transfer()), while the fallback function is executed on calls with calldata. If no receive function exists but a fallback function does, calls with empty calldata will also use the fallback function. + +### Payable function modifier + +The `payable` function modifier allows a function to receive Ether. + +The `receive` function (line 22) needs to be `payable`. If you delete the `payable` modifier you will get an error from the compiler. If you delete the `payable` modifier from the `fallback` function (line 25) it will compile, but it won’t be able to receive Ether. +The functions `sendViaTransfer`, `sendViaSend`, and `sendViaCall` (lines 33, 38, and 45) also need to be `payable` in order to receive Ether. + +### Payable address + +Solidity makes a distinction between two different flavors of the address data type: address and address payable. + +`address`: Holds a 20-byte value. +`address payable`: Holds a 20-byte value and can receive Ether via its members: transfer and send. + +If you change the parameter type for the functions `sendViaTransfer` and `sendViaSend` (line 33 and 38) from `payable address` to `address`, you won’t be able to use `transfer()` (line 35) or `send()` (line 41). + +Watch a video tutorial on Sending Ether. + +## ⭐️ Assignment + +Build a charity contract that receives Ether that can be withdrawn by a beneficiary. + +1. Create a contract called `Charity`. +2. Add a public state variable called `owner` of the type address. +3. Create a donate function that is public and payable without any parameters or function code. +4. Create a withdraw function that is public and sends the total balance of the contract to the `owner` address. + +Tip: Test your contract by deploying it from one account and then sending Ether to it from another account. Then execute the withdraw function. diff --git a/locales/ru/SolidityBeginnerCourse/variables/variables.md b/locales/ru/SolidityBeginnerCourse/variables/variables.md new file mode 100644 index 000000000..dfb35b382 --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/variables/variables.md @@ -0,0 +1,29 @@ +There are three different types of variables in Solidity: _State Variables_, _Local Variables_, and _Global Variables_. + +## 1. State Variables + +_State Variables_ are stored in the contract _storage_ and thereby on the blockchain. They are declared inside the contract but outside the function. +This contract has two state variables, the string `text`(line 6) and the uint `num` (line 7). + +## 2. Local Variables + +_Local Variables_ are stored in the _memory_ and their values are only accessible within the function they are defined in. Local Variables are not stored on the blockchain. +In this contract, the uint `i` (line 11) is a local variable. + +## 3. Global Variables + +_Global Variables_, also called _Special Variables_, exist in the global namespace. They don't need to be declared but can be accessed from within your contract. +Global Variables are used to retrieve information about the blockchain, particular addresses, contracts, and transactions. + +In this example, we use `block.timestamp` (line 14) to get a Unix timestamp of when the current block was generated and `msg.sender` (line 15) to get the caller of the contract function’s address. + +A list of all Global Variables is available in the Solidity documentation. + +Watch video tutorials on State Variables, Local Variables, and Global Variables. + +## ⭐️ Assignment + +1. Create a new public state variable called `blockNumber`. +2. Inside the function `doSomething()`, assign the value of the current block number to the state variable `blockNumber`. + +Tip: Look into the global variables section of the Solidity documentation to find out how to read the current block number. diff --git a/locales/ru/SolidityBeginnerCourse/visibility/visibility.md b/locales/ru/SolidityBeginnerCourse/visibility/visibility.md new file mode 100644 index 000000000..79e4307bf --- /dev/null +++ b/locales/ru/SolidityBeginnerCourse/visibility/visibility.md @@ -0,0 +1,37 @@ +The `visibility` specifier is used to control who has access to functions and state variables. + +There are four types of visibilities: `external`, `public`, `internal`, and `private`. + +They regulate if functions and state variables can be called from inside the contract, from contracts that derive from the contract (child contracts), or from other contracts and transactions. + +### private + +- Can be called from inside the contract + +### internal + +- Can be called from inside the contract +- Can be called from a child contract + +### public + +- Can be called from inside the contract +- Can be called from a child contract +- Can be called from other contracts or transactions + +### external + +- Can be called from other contracts or transactions +- State variables can not be `external` + +In this example, we have two contracts, the `Base` contract (line 4) and the `Child` contract (line 55) which inherits the functions and state variables from the `Base` contract. + +When you uncomment the `testPrivateFunc` (lines 58-60) you get an error because the child contract doesn’t have access to the private function `privateFunc` from the `Base` contract. + +If you compile and deploy the two contracts, you will not be able to call the functions `privateFunc` and `internalFunc` directly. You will only be able to call them via `testPrivateFunc` and `testInternalFunc`. + +Watch a video tutorial on Visibility. + +## ⭐️ Assignment + +Create a new function in the `Child` contract called `testInternalVar` that returns the values of all state variables from the `Base` contract that are possible to return. diff --git a/locales/ru/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md b/locales/ru/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md new file mode 100644 index 000000000..801d8c582 --- /dev/null +++ b/locales/ru/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md @@ -0,0 +1,47 @@ +In this tutorial, we'll explore the Uniswap V3 Swap contract to learn about how single-hop and multi-hop swaps work. + +But first, some Uniswap fundamentals. + +## What is Uniswap? + +Uniswap is a decentralized cryptocurrency exchange. It allows users to exchange tokens without the need for a centralized intermediary. Uniswap is a key player in the decentralized finance (DeFi) space. + +## How does Uniswap work? + +Instead of using an order book like a traditional centralized exchange, Uniswap uses an automated market maker (AMM) model. In Uniswap, the AMM is a smart contract that holds reserves of tokens (Liquidity Pool). Users can trade between tokens in the Liquidity Pool. The price of each token is determined by the ratio of the reserves. + +### Step-by-step example of a Uniswap trade + +1. Alice wants to trade 1 ETH for DAI. +2. Alice sends 1 ETH to the Uniswap smart contract. +3. The Uniswap smart contract calculates the amount of DAI that Alice should receive based on the current exchange rate. +4. The Uniswap smart contract sends the DAI to Alice. +5. The Uniswap smart contract adds the 1 ETH to its reserves. +6. The Uniswap smart contract recalculates the exchange rate based on the new reserves. + +The tokens in the Liquidity Pool are provided by Liquidity Providers. When a Liquidity Provider deposits tokens into a Liquidity Pool, they receive Liquidity Provider Tokens in return. Liquidity Provider Tokens represent a user's share of a Liquidity Pool. + +Users of Uniswap pay a fee for each trade. The fee is paid to the Liquidity Providers in the form of additional Liquidity Provider Tokens. + +## Uniswap Swap Contract + +The Uniswap Swap contract allows users to swap tokens using Uniswap V3. It can do single-hop swaps, which allow users to exchange one token for another directly. It can also do multi-hop swaps, which means that users can exchange one token for another by routing through multiple tokens. Routing in this context means that the swap contract will exchange the token for another token, then exchange that token for another token, and so on until it reaches the desired token. + +## Conclusion + +In this section, we learned about Uniswap, how it works, and how we are going to use it to swap tokens. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is Uniswap? + +1. A centralized exchange protocol. +2. A decentralized exchange protocol that uses an order book. +3. A decentralized exchange protocol that uses an automated market maker (AMM) model. +4. A decentralized exchange protocol that uses an order book and an automated market maker (AMM) model. + +### 2) How does Uniswap determine the price of a token? + +1. The price of a token is determined by the ratio of the reserves. +2. The price of a token is determined by the ratio of the reserves and the number of trades. +3. The price of a token is determined by the ratio of the reserves and the number of Liquidity Providers. diff --git a/locales/ru/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md b/locales/ru/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md new file mode 100644 index 000000000..e5cc248f5 --- /dev/null +++ b/locales/ru/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md @@ -0,0 +1,41 @@ +The entire UniswapSwapExamples contract will only be presented in section 5 of this tutorial. Before then, we'll build up blocks of code. + +This section explores the `ISwapRouter` interface, which defines the functions that can be called on the Uniswap Swap contract. + +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. +Multi-hop swaps allow users to exchange one token for another by routing through multiple tokens. + +Interfaces in Solidity specify functions that must be included in a contract that inherits them. They are useful for declaring what functions be supported and allow for easier integration and interaction between different contracts. + +Structs are used to define custom data types. + +## ISwapRouter Interface + +The ISwapRouter interface defines the functions that can be called on the Uniswap Swap contract. We will need to use this interface to interact with the Uniswap Swap contract and execute swaps. + +On line 5, we define a constant variable called `router` that is of type `ISwapRouter`. We set the value of this variable to the interface instance of a smart contract that is deployed at the address `0xE592427A0AEce92De3Edee1F18E0157C05861564`. This is the address of the Uniswap V3 Swap contract on the Ethereum mainnet. + +On line 9, we define an interface called `ISwapRouter`. This interface defines two functions: `exactInputSingle` and `exactInput`. + +## exactInputSingle + +On line 25, we define a struct called `ExactInputSingleParams`. This struct defines the parameters that are required for our exactInputSingle function on line 21, which will execute a single-hop swap. The struct has the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 fee`**: The fee associated with the swap. +- **`address recipient`**: The address that will receive the output token. +- **`uint deadline`**: A timestamp by which the transaction must be processed, for time-limiting the swap. +- **`uint amountIn`**: The amount of the input token being sent. +- **`uint amountOutMinimum`**: The minimum amount of the output token that the sender is willing to accept, to protect against unfavorable price movements. +- **`uint160 sqrtPriceLimitX96`**: A limit on the price, represented in a specific format, to prevent the swap from occurring at unfavorable prices. + +## exactInput + +On line 25, we define a struct called `ExactInputParams`. This struct defines the parameters that are required for our `exactInput` function on line 33. This function will execute a multi-hop swap. The struct has the following parameters: + +- **`bytes path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address recipient`**: The address receiving the output tokens. +- **`uint deadline`**: Similar to above, a timestamp by which the transaction must be processed. +- **`uint amountIn`**: The amount of the input token. +- **`uint amountOutMinimum`**: The minimum amount of the output token the sender expects to receive. diff --git a/locales/ru/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md b/locales/ru/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md new file mode 100644 index 000000000..f4d70c445 --- /dev/null +++ b/locales/ru/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md @@ -0,0 +1,36 @@ +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. In this section, we will learn how to use the Uniswap V3 Swap contract to execute single-hop swaps. + +## Function Parameters + +On line 8, we define a function called `swapExactInputSingleHop`. This function executes a single-hop swap. It takes the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 poolFee`**: The fee associated with the swap. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +## Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 14. +Then, we approve the Uniswap Swap contract to spend the input token on our behalf, line 15. + +On line 17, we create an instance of the `ExactInputSingleParams` struct. This struct contains the parameters that are required for our `exactInputSingle` function on line 45, which will execute the single-hop swap. We repeat `ISwapRouter.ExactInputSingleParams` two times on that line because we are making an instance of a struct that is defined in an interface. + +## Parameters of the ExactInputSingleParams Struct + +We set the parameters of the struct as follows: + +- **`tokenIn`**: We set this to the `tokenIn` parameter of our function. +- **`tokenOut`**: We set this to the `tokenOut` parameter of our function. +- **`fee`**: We set this to the `poolFee` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. +- **`sqrtPriceLimitX96`**: We set this to 0 because we do not want to specify a limit on the price. + +## Executing the Single-hop Swap + +On line 29, we assign the output of the `exactInputSingle` function to the `amountOut` variable. This function executes the single-hop swap and returns the amount of the output token that was received. diff --git a/locales/ru/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md b/locales/ru/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md new file mode 100644 index 000000000..7883b4718 --- /dev/null +++ b/locales/ru/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md @@ -0,0 +1,30 @@ +In this section, we'll delve into the `swapExactInputMultiHop` function in the `UniswapV3SwapExamples` contract. This function enables more complex token swaps by allowing users to specify a custom path through multiple liquidity pools. + +If for example, a user wants to swap token A for token D, but there is no direct liquidity pool for A and D, the user can specify a path through multiple tokens. For example, the user can swap A for B, then B for C, and finally C for D. This is of course automatically done by the Uniswap V3 Swap contract. + +### Parameters and Return Value + +On line 32, we define a function called `swapExactInputMultiHop`. This function executes a multi-hop swap. It takes the following parameters: + +- **`bytes calldata path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address tokenIn`**: The address of the token being sent. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +### Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 38. +Then, we approve the Uniswap Swap router to spend the input token on our behalf, line 41. + +On line 43, we create an instance of the `ExactInputParams` struct, line 73. This struct contains the parameters that are required for our `exactInput` function on line 81, which will execute the multi-hop swap. + +We set the parameters of the struct as follows: + +- **`path`**: We set this to the `path` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. + +On line 53, we execute the multi-hop swap by calling the `exactInput` function. This function returns the amount of the output token that was received. diff --git a/locales/ru/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md b/locales/ru/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md new file mode 100644 index 000000000..b3cec34e9 --- /dev/null +++ b/locales/ru/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md @@ -0,0 +1,52 @@ +In this section, we'll explore the `IERC20` interface, a standard interface for interacting with ERC-20 tokens and the `IWETH` interface, a standard interface for interacting with wrapped Ether (WETH). Understanding these interfaces is crucial as it is used in the Uniswap V3 Swap contract to handle token transfers and approvals. + +You can find a "Solidity ERC20 Token Course" for beginners in LearnEth to understand the ERC20 token standard in more detail. + +## IERC20 Interface + +On line 80, we define the `IERC20` interface. This interface defines a standard set of functions that ERC-20 tokens must implement. Let's examine the key functions within this interface: + +### 1. totalSupply + +On line 81, we define the `totalSupply` function. This function returns the total supply of the token. + +### 2. balanceOf + +On line 83, we define the `balanceOf` function. This function returns the balance of the specified address. + +### 3. transfer + +On line 85, we define the `transfer` function. This function transfers tokens from the sender to the specified recipient. + +### 4. allowance + +On line 87, we define the `allowance` function. This function returns the amount of tokens that the spender is allowed to spend on behalf of the owner. + +### 5. approve + +On line 89, we define the `approve` function. When called, this function approves a spender to spend the specified amount of tokens on behalf of the sender. + +### 6. transferFrom + +On line 91, we define the `transferFrom` function. This function transfers tokens from the specified sender to the recipient. The function can only be called by the spender if the spender is allowed to spend the specified amount of tokens on behalf of the sender. + +### 7. Events + +On lines 102-103, we define the `Transfer` and `Approval` events. These events are emitted when the `transfer` and `approve` functions are called, respectively. + +## IWETH Interface + +On line 106, we define the `IWETH` interface. This interface extends the `IERC20` interface and defines two additional functions: + +### 1. deposit + +On line 107, we define the `deposit` function. This function deposits ETH into the contract and returns the equivalent amount of WETH. This function is used to wrap ETH into WETH. +We need to wrap ETH into WETH because the Uniswap V3 Swap contract only supports ERC-20 tokens. + +### 2. withdraw + +On line 109, we define the `withdraw` function. This function withdraws the specified amount of WETH from the contract and returns the equivalent amount of ETH. This function is used to unwrap WETH into ETH. + +## Conclusion + +In this tutorial, we explored the Uniswap V3 Swap contract. To get a full sense of how Uniswap works, try making some swaps on the Uniswap DApp and go to the Uniswap docs. diff --git a/locales/ru/Uniswap-Tutorial/README.md b/locales/ru/Uniswap-Tutorial/README.md new file mode 100644 index 000000000..cf66c5582 --- /dev/null +++ b/locales/ru/Uniswap-Tutorial/README.md @@ -0,0 +1,5 @@ +# Uniswap Swap Course + +Review the code of the Uniswap V3 Swap contract for performing token swaps. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/ru/Uniswap-Tutorial/config.yml b/locales/ru/Uniswap-Tutorial/config.yml new file mode 100644 index 000000000..f49f02abc --- /dev/null +++ b/locales/ru/Uniswap-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: uniswapSwapCourse +name: Uniswap Swap Course +summary: Go through the Solidity code of the Uniswap V3 Swap contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - Uniswap +steps: + - + name: 1. Introduction + path: 1-introduction-to-uniswap + - + name: 2. Routers, Interfaces, and Structs + path: 2-router-interfaces-and-structs + - + name: 3. Single Hop Swaps + path: 3-single-hop-swaps + - + name: 4. Multi-Hop Swaps + path: 4-multi-hop-swaps + - + name: 5. Erc20 and Weth Interfaces + path: 5-erc20-weth-interfaces diff --git a/locales/ru/Web3Client/1_Using_Web3/Running_a_script.md b/locales/ru/Web3Client/1_Using_Web3/Running_a_script.md new file mode 100644 index 000000000..3b7b23332 --- /dev/null +++ b/locales/ru/Web3Client/1_Using_Web3/Running_a_script.md @@ -0,0 +1,24 @@ +## Querying the Blockchain + +In this tutorial, we'll run a script that queries the blockchain using a JavaScript library. + +This means that instead of using the Remix GUI or a block explorer like Etherscan, we'll use a script in the editor and will run it from the terminal. + +The JS libraries that are used the most for interacting with the blockchain are web3.js & ethers.js. + +Let's begin with a simple web3.js example, queryBlockNum.js. + +The script's call to web3.js is wrapped in a self-executing async function that contains a try/catch block. + +We'll query the current blocknumber with: +`let blockNumber = await web3.eth.getBlockNumber()` + +Note that the object `web3` is injected by Remix. For more info on web3.js, check their docs, https://web3js.readthedocs.io. + +To use web3.js or ethers.js, you need to select the **Injected Web3** or **Web3 Provider** environment in the **Deploy & Run** module. Scripts don't currently work with the JSVM. **If you try, you'll get an error.** + +So for this example choose **Injected Web3** in the Deploy & Run module and have Metamask installed. + +From the terminal, execute `remix.execute()`. This command will execute the current JavaScript file with the line `let blockNumber = await web3.eth.getBlockNumber()`. + +In the console, you should see the current block number of the chain that metamask is connected to. diff --git a/locales/ru/Web3Client/2_Querying_a_Contract/queryContract.md b/locales/ru/Web3Client/2_Querying_a_Contract/queryContract.md new file mode 100644 index 000000000..461c98244 --- /dev/null +++ b/locales/ru/Web3Client/2_Querying_a_Contract/queryContract.md @@ -0,0 +1,23 @@ +Now that we know how to query simple data, let's try a more complex query. + +This is a contract deployed to the mainnet - at this address: https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code + +We are going to query the contract to find the name of it's token. + +The **name** variable is a state variable of the contract. + +To access this **mainnet** contract, we need to do some setup. + +1. Switch to the mainnet in metamask. +2. You'll probably need to refresh Remix. +3. As a result of the refresh, you may need to reload this tutorial too. +4. Go to Deploy & Run and switch to **Injected Web3**. + +**Using Web3** +In the script, queryContract.js, we need to instantiate a new instance of web3.eth.Contract object. For this we need to grab the contract's ABI and its address. The source code & ABI is available in etherscan because the contract's developer intentionally published it. + +In etherscan, we can see that its name is **TetherToken**. Scrolling down to the TetherToken contract in the source code section of etherscan, we can see the state variables for the contract - the first of which is named **name**. + +There are a few syntactic hoops to jump through to return the value of the state variable. + +- To call the autogenerated getter function of the public state variable, you need to both treat the variable as a function (by adding parentheses) and also to tack on a call(). diff --git a/locales/ru/Web3Client/README.md b/locales/ru/Web3Client/README.md new file mode 100644 index 000000000..a319f312f --- /dev/null +++ b/locales/ru/Web3Client/README.md @@ -0,0 +1 @@ +This workshop is about using the web3.js to interact with a contract and more generally to the blockchain. diff --git a/locales/ru/Web3Client/config.yml b/locales/ru/Web3Client/config.yml new file mode 100644 index 000000000..07cb1760c --- /dev/null +++ b/locales/ru/Web3Client/config.yml @@ -0,0 +1,9 @@ +--- +id: useofweb3js +name: Basic use of web3.js +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 2 +tags: + - JS + - Remix + - Web3 diff --git a/locales/tr/Basics/README.md b/locales/tr/Basics/README.md new file mode 100644 index 000000000..ed3ee86a0 --- /dev/null +++ b/locales/tr/Basics/README.md @@ -0,0 +1,3 @@ +## Yükleme, Derleme, Dağıtma + +This beginner level tutorial introduces Remix's interface and concepts used in Ethereum. diff --git a/locales/tr/Basics/config.yml b/locales/tr/Basics/config.yml new file mode 100644 index 000000000..8c160b545 --- /dev/null +++ b/locales/tr/Basics/config.yml @@ -0,0 +1,26 @@ +--- +id: basics +name: Basics of Remix +summary: A typical workflow in Remix +level: 1 +tags: + - Remix +steps: + - + name: Intro to the Interface + path: interface_introduction + - + name: Intro to Workspaces + path: workspaces + - + name: Loading & Compiling + path: load_and_compile + - + name: Deploying to the Remix VM + path: deploy_to_the_remixvm + - + name: Interacting with Functions + path: interacting + - + name: Deploying to Public Networks + path: deploy_injected diff --git a/locales/tr/Basics/deploy_injected/README.md b/locales/tr/Basics/deploy_injected/README.md new file mode 100644 index 000000000..172396527 --- /dev/null +++ b/locales/tr/Basics/deploy_injected/README.md @@ -0,0 +1,21 @@ +1. If you don't have a browser wallet like **MetaMask** download and install one now. + +2. Click the MetaMask icon in your browser. Sign in and choose the Ephemery test network. You might need to update your wallet's settings so that you can see **test networks**. Alternatively, you can go to Remix's Deploy & Run transation module and in the ENVIRONMENT section select Ephemery. + +3. Getting test ETH for public test networks is often annoying. Ephemery is a public network that is refreshed monthly, so getting test ETH should be painless. Here is a link to some Ephemery faucets. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/testnet.png) + +Sepolia is another popular testnet that is not refreshed, so deployments will persist, but Sepolia faucets are more difficult to use. + +In your browser wallet make sure that you have NOT selected mainnet or any network that will cost real ETH. In the Deploy & Run module, below the Environment select box, you'll see a badge with the network's ID and for popular chains, its name. In the case below its Sepolia. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/sepolia.png) + +5. Make sure you see the 2_Owner.sol as a choice in the **CONTRACT** select box, then click the **Deploy** button. + +If the **CONTRACT** select box is empty, you'll need to compile 2_Owner again by making 2_Owner.sol the active file in the **editor** and then go to the **Solidity Compiler** to compile it. + +6. After you hit the `Deploy` button, you'll see the browser wallet popup asking you to pay for the transactions. If you have the appropriate kind of ETH for this chain, approve this transaction. Check the printout in the terminal. Once the block is validated, the **deployed instance** will appear at the bottom of Deploy & Run + +And with that you have finished this tutorial. You now have experience with opening, compiling, deploying and interacting with Smart Contracts in Remix IDE. diff --git a/locales/tr/Basics/deploy_to_the_remixvm/README.md b/locales/tr/Basics/deploy_to_the_remixvm/README.md new file mode 100644 index 000000000..8035d631b --- /dev/null +++ b/locales/tr/Basics/deploy_to_the_remixvm/README.md @@ -0,0 +1,15 @@ +In the previous chapter, we compiled a contract - which is to say the Solidity code has been transformed into little chunks of Ethereum Virtual Machine (EVM) bytecode. + +Now we will put that code on a test blockchain. + +1. Click the Deploy and Run icon ![deploy & run icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_to_the_remixvm/images/run.png "deploy & run icon"). + +2. Select one of the **Remix VM**s from the **Environment** pulldown. + +3. Click the Deploy button (or the transact button in the expanded view). + +4. You have deployed your compiled contract to the Remix VM - a simulated blockchain that is running inside of your browser window. The Remix VM is simple, fast test chain. It is not that realistic because you don't need to approve each transaction. + +5. Check the terminal to see detail of this deployment transaction. + +You can also use Remix to deploy to other public EVM chains. To do this, you'll need to connect to a different **Environment** - like Injected Provider. The Injected Provider connects Remix to browser wallet (like MetaMask or similar). We'll try deploying to a public network at the end of this tutorial. But before we get there, we'll cover how to interact with a deployed contract's functions. diff --git a/locales/tr/Basics/interacting/README.md b/locales/tr/Basics/interacting/README.md new file mode 100644 index 000000000..59ef44200 --- /dev/null +++ b/locales/tr/Basics/interacting/README.md @@ -0,0 +1,19 @@ +## Accessing functions in a deployed contract + +1. When a contract has been successfully deployed, it will appear at the bottom of the Deploy and Run plugin. Open up the contract by clicking the caret - so the caret points down. + ![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/instance.png "deployed contract") + +2. There are 2 functions in this contract. To input the parameters individually, clicking the caret to the right of changeOwner (outlined in red below). In the expanded view, each parameter has its own input box. + +![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/deployed_open2.png "deployed contract") + +If this contract had imported other contracts, then the functions of the imported contracts would also be visible here. At some point, try playing with An ERC20 contract to see all its many functions. + +3. Functions with blue buttons are either **pure** or **view** functions. This means that they are just reading a property or are returning a value. In other words, they aren't saving anything - so they are FREE (they don’t cost gas). Functions with other colors - usually orange (depending on the Remix theme) cost gas because they are saving information. They are creating a **transaction**. + +4. 2_Owner.sol does not have a **payable** function. If it did, the button's color would be red. Payable functions allow you to send Ether to the function. To send ETH with a payable function, you put the amount you want to send in the **value** field towards the top of the Deploy & Run module. + +5. In the Remix VM, you don't need to approve a transaction. When using a more realistic test environment or when using the mainnet - you will need to approve the transactions for them to go through. Approving a transaction costs gas. + +6. Choosing a public network is not done in Remix but in your Browser Wallet. There is a plug icon to the right of the Environment title that links to chainlist.org where you can get the specs of the chain you want to interact with. + ![chainlist](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/chainlist.png "chainlist") diff --git a/locales/tr/Basics/interface_introduction/README.md b/locales/tr/Basics/interface_introduction/README.md new file mode 100644 index 000000000..76c953fbd --- /dev/null +++ b/locales/tr/Basics/interface_introduction/README.md @@ -0,0 +1,15 @@ +## Remix is composed of four panels. + +![Remix layout](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/a-layout1c.png "Remix layout") + +- Most plugins appear in the **Side Panel**. +- Editing code happens in tabs in the **Main Panel**. +- The results of transactions and other actions are visible in the **Terminal**. +- Switching between plugins happens in the **Icons Panel**. +- To make a panel larger, drag its border. + +Try clicking the **Solidity Compiler** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/solidity-icon.png) in the **Icons Panel**. Then click the **Deploy & Run** icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/deploy-run.png). Then come back to **LearnEth** by clicking this icon ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/learneth.png). + +In the **Main Panel** of Remix, make sure you see the **Home** tab. The **Home** tab has lots of useful links. To navigate there, either click the **Home** tab in the **Main Panel** or click the Remix icon ![Remix icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/remix-logo.png "Remix icon") on the top of the icon panel. + +- See all the plugins in the **Plugin Manager**. Click this icon ![plugin manager](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/plugin1.png "Plugin Manager icon") in the lower left corner Remix. diff --git a/locales/tr/Basics/load_and_compile/README.md b/locales/tr/Basics/load_and_compile/README.md new file mode 100644 index 000000000..a666d5d13 --- /dev/null +++ b/locales/tr/Basics/load_and_compile/README.md @@ -0,0 +1,20 @@ +Let's load a file from the File Explorer into the Editor. + +1. In the icon panel, click ![file explorer icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/files1.png "file explorer icon") , the File Explorer's icon. + +2. Make sure you are in the **default_workspace**. + +![default workspace](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/default_workspace_open.png) + +3. Open the contracts folder and click on **2_Owner.sol** in the contracts folder. Click it. The file will appear in a tab in the main panel. + +4. In the icon panel, click the **Solidity Compiler** ![solidity compiler icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/solidity1.png "solidity compiler icon"). The Solidity compiler should now be in the side panel. + +5. Click the compile button. + ![compile 2\_owner](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/compile2owner.png "compile 2_Owner") + +6. Compiling can also be triggered by hitting **CTRL + S**. + +The spinner will turn while the file is compiling. + +**Note:** The spinner also turns when the compiler itself is loading. To choose a **different version of Solidity**, go to the select box at the top of the plugin. diff --git a/locales/tr/Basics/workspaces/README.md b/locales/tr/Basics/workspaces/README.md new file mode 100644 index 000000000..97a47d283 --- /dev/null +++ b/locales/tr/Basics/workspaces/README.md @@ -0,0 +1,23 @@ +## Workspaces help organize your separate projects. + +If this is your first time to Remix, a Workspace named **default_workspace** is loaded in the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/default_workspace.png) + +The **default_workspace** has three Solidity (.sol) files in the contracts folder. Remix has a number of other templates. When you load a template, it goes into a Workspace. To go between Workspaces, use the select box at the top of the File Explorer. + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/select-box.png) + +But Workspaces are not only for templates. When cloning a repo into Remix, the files will be put into a Workspace. + +Let's create a new Workspace + +1. At the top of the File Explorer, click the hamburger icon (the 3 horizontal lines). Read through the commands and tools in this menu. + +2. Select **+ Create** (the first choice). + +3. In the modal the comes up, choose one of the templates. + +![hamburger](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/workspaces/images/popup.png) + +Notice that in this popup menu, you can clone a repo. Managing a Git repo happens in the DGit plugin. You can also create Github actions with the three workflow choices in the popup menu. diff --git a/locales/tr/CircomHashChecker/README.md b/locales/tr/CircomHashChecker/README.md new file mode 100644 index 000000000..20391a668 --- /dev/null +++ b/locales/tr/CircomHashChecker/README.md @@ -0,0 +1,14 @@ +Hash Checker Tutorial + +This tutorial guides you through creating and understanding a Hash Checker circuit using Remix-IDE. You'll learn how to generate the circuit using a template, explore the code, perform a trusted setup, generate proofs, and verify them. This tutorial is suitable for beginners familiar with Circom and Zero-Knowledge Proofs. + +Prerequisites + +``` +Basic understanding of Zero-Knowledge Proofs and Circom. +Familiarity with Remix-IDE. +``` + +Estimated Time + +Approximately 1-2 hours. diff --git a/locales/tr/CircomHashChecker/config.yml b/locales/tr/CircomHashChecker/config.yml new file mode 100644 index 000000000..2c2aae80a --- /dev/null +++ b/locales/tr/CircomHashChecker/config.yml @@ -0,0 +1,35 @@ +id: circom-hash-checker +name: Hash Checker Tutorial +summary: A tutorial on creating and understanding a Hash Checker circuit using Remix-IDE templates, including trusted setup and proof generation. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction to the Hash Checker Circuit + path: step-1 + - + name: Generating the Hash Checker Template in Remix-IDE + path: step-2 + - + name: Exploring calculate_hash.circom + path: step-3 + - + name: Compiling the Circuit + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Compute Witness + path: step-6 + - + name: Generate Proof + path: step-7 + - + name: Exploring the Trusted Setup Script (Optional) + path: step-8 + - + name: Exploring the Proof Generation Script (Optional) + path: step-9 diff --git a/locales/tr/CircomHashChecker/step-1/README.md b/locales/tr/CircomHashChecker/step-1/README.md new file mode 100644 index 000000000..be922e93b --- /dev/null +++ b/locales/tr/CircomHashChecker/step-1/README.md @@ -0,0 +1,8 @@ +In this tutorial, we'll explore the **Hash Checker** circuit, a zero-knowledge proof (ZKP) application using Circom and Remix-IDE. The Hash Checker circuit allows you to prove knowledge of certain inputs that hash to a given value without revealing the inputs themselves. + +### What You'll Learn + +- How to generate a Hash Checker circuit using Remix-IDE's workspace templates. +- Understanding the Circom code for hashing and checking hashes. +- Performing a trusted setup using Groth16. +- Generating zero-knowledge proofs. diff --git a/locales/tr/CircomHashChecker/step-2/README.md b/locales/tr/CircomHashChecker/step-2/README.md new file mode 100644 index 000000000..bc827019e --- /dev/null +++ b/locales/tr/CircomHashChecker/step-2/README.md @@ -0,0 +1,37 @@ +Follow these steps to create the Hash Checker workspace in Remix-IDE. + +### Step 1: Access the Workspace Templates + +1. In the **File Explorer** sidebar, click on the **hamburger menu icon** (three horizontal lines). + + hamburger-menu + +2. Select **"Create Using Template"** from the dropdown. + + create-using-template + +### Step 2: Find the Hash Checker Template + +1. In the main panel, scroll down to the **"Circom ZKP"** section. + + create-zkp-section + +2. Locate the **"Hash Checker"** item. + +### Step 3: Create the Workspace + +1. Click on the **"Create"** button on the Hash Checker item. + + create-hash-checker + +2. In the modal pop-up, provide a **workspace name** (e.g., `hash-checker-workspace`). + + workspace-name-modal + +3. Click **"OK"** to create the template. + +### Result + +- The workspace is created with the necessary files and directories. + + workspace-name-modal diff --git a/locales/tr/CircomHashChecker/step-3/README.md b/locales/tr/CircomHashChecker/step-3/README.md new file mode 100644 index 000000000..b3ac14050 --- /dev/null +++ b/locales/tr/CircomHashChecker/step-3/README.md @@ -0,0 +1,32 @@ +## Exploring `calculate_hash.circom` + +Navigate to the `circuits` directory and open `calculate_hash.circom`. This file contains the Circom code for the Hash Checker circuit. + +### Code Breakdown + +#### Pragma and Includes: + +- `pragma circom 2.0.0;` specifies the Circom version. +- `include "circomlib/circuits/poseidon.circom";` fetch and includes the Poseidon hash function from [CircomLib](https://github.com/iden3/circomlib). + +#### `CalculateHash` Template: + +- Defines inputs `value1`, `value2`, `value3`, `value4`. +- Uses the `Poseidon` hash function to compute a hash of these values.\ +- Outputs `out`, which is the hash. + +#### `HashChecker` Template: + +- Inputs are the same values plus a `hash`. +- Instantiates `CalculateHash` as `calculateSecret`. +- Computes `calculatedHash`. +- Uses `assert(hash == calculatedHash);` to ensure the provided hash matches the calculated hash. + +#### Main Component: + +- `component main {public [hash]} = HashChecker();` +- Specifies that `hash` is a `public` input, while the values are `private`. + +### Purpose + +The circuit allows someone to prove they know `value1`, `value2`, `value3`, and `value4` that hash to a specific `hash` without revealing the values themselves. diff --git a/locales/tr/CircomHashChecker/step-4/README.md b/locales/tr/CircomHashChecker/step-4/README.md new file mode 100644 index 000000000..537c6a241 --- /dev/null +++ b/locales/tr/CircomHashChecker/step-4/README.md @@ -0,0 +1,32 @@ +## Compiling the Circuit + +### Selecting the Compiler Version + +1. Go to the **Circuit Compiler** plugin in the sidebar. +2. Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +### Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +### Compiling the Circuit + +1. Click on the **Compile** button. +2. Wait for the compilation to complete. A success badge will appear if compilation is successful. + +compilation-success + +### Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/tr/CircomHashChecker/step-5/README.md b/locales/tr/CircomHashChecker/step-5/README.md new file mode 100644 index 000000000..c3ea8509b --- /dev/null +++ b/locales/tr/CircomHashChecker/step-5/README.md @@ -0,0 +1,25 @@ +## Performing a Trusted Setup + +1. **Access the Setup and Exports Section**: + +- After successful compilation, the **Setup and Exports** section becomes available in the plugin. + +2. **Select Proving Scheme**: + +- Choose **Groth16** from the **Proving Scheme** dropdown. + +3. **Select Power of Tau File**: + +- Choose the appropriate **Power of Tau** file from the dropdown. If unsure, use the default option. + +4. **Export Verification Key and Contract** (optional): + +- Enable **Export Verification Key** to save the verification key to the File Explorer. +- Enable **Export Verifier Contract** to save the Solidity contract for on-chain verification. + +trusted-setup + +5. **Run the Trusted Setup**: + +- Click on the **Run Setup** button. +- Wait for the process to complete. This may take some time depending on the circuit complexity. diff --git a/locales/tr/CircomHashChecker/step-6/README.md b/locales/tr/CircomHashChecker/step-6/README.md new file mode 100644 index 000000000..03b848f81 --- /dev/null +++ b/locales/tr/CircomHashChecker/step-6/README.md @@ -0,0 +1,28 @@ +## Compute Witness + +1. **Access the Compute Witness Section**: + - After the trusted setup, the **Compute Witness** section becomes available. + +2. **Input Values**: + - You'll see input fields for `value1`, `value2`, `value3`, `value4`, and `hash`. + - Enter values for each input. For example: + - `value1`: `1234` + - `value2`: `2` + - `value3`: `3` + - `value4`: `4` + +3. **Calculate the Hash**: + + - Compute the Poseidon hash of the four values using an external tool or library compatible with the Poseidon hash function. + - For the values above, here is the computed Poseidon hash `16382790289988537028417564277589554649233048801038362947503054340165041751802`. + - Enter the calculated `hash` value in the `hash` input field. + + compute-witness + +4. **Compute the Witness**: + + - Click on the **Compute Witness** button. + - Wait for the process to complete. A success badge will appear if the witness is computed successfully. + - If successful, you'll see `calculate_hash.wtn` created in the `.bin` directory in the file explorer. + + witness-computed diff --git a/locales/tr/CircomHashChecker/step-7/README.md b/locales/tr/CircomHashChecker/step-7/README.md new file mode 100644 index 000000000..e6ae80fea --- /dev/null +++ b/locales/tr/CircomHashChecker/step-7/README.md @@ -0,0 +1,21 @@ +## Generate Proof + +1. **Access the Generate Proof Section**: + - After computing the witness, expand the **Generate Proof** section. + +2. **Configure Proof Generation**: + - **Export Verifier Calldata**: Enable this option if you plan to verify the proof on-chain. + +3. **Generate the Proof**: + + - Click on the **Generate Proof** button. + - Wait for the proof generation to complete. + + generate-proof + +4. **View the Proof**: + + - The proof data will be displayed in the File Explorer. + - **Congratulations!** You've successfully compiled the `Hash Checker` circuit, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + + generate-proof diff --git a/locales/tr/CircomHashChecker/step-8/README.md b/locales/tr/CircomHashChecker/step-8/README.md new file mode 100644 index 000000000..e489a8cab --- /dev/null +++ b/locales/tr/CircomHashChecker/step-8/README.md @@ -0,0 +1,34 @@ +## Understanding `groth16_trusted_setup.ts` + +Navigate to `scripts/groth16/groth16_trusted_setup.ts`. This script performs the trusted setup necessary for generating proofs. + +### Code Breakdown + +#### Circuit Compilation: + +- Uses `remix.call('circuit-compiler', 'generateR1cs', ...)` to generate `R1CS` (Rank-1 Constraint System) from the circuit. + +#### Trusted Setup Steps: + +- `snarkjs.zKey.newZKey`: Initializes the proving key (`zkey_0`). +- `snarkjs.zKey.contribute`: Adds contributions to the proving key (`zkey_1`). +- `snarkjs.zKey.beacon`: Finalizes the proving key (`zkey_final`). + +#### Verification: + +- `snarkjs.zKey.verifyFromR1cs`: Verifies the proving key against the `R1CS` and initial parameters. + +#### Exporting Keys: + +- Exports the verification key to `scripts/groth16/zk/keys/verification_key.json`. +- Exports the final proving key (`scripts/groth16/zk/keys/zkey_final.txt`). + +### Purpose + +- Performs the trusted setup required for the `Groth16` proving system. +- Generates the necessary keys for proof generation and verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"setup done."` logged in the terminal. diff --git a/locales/tr/CircomHashChecker/step-9/README.md b/locales/tr/CircomHashChecker/step-9/README.md new file mode 100644 index 000000000..653d5ced1 --- /dev/null +++ b/locales/tr/CircomHashChecker/step-9/README.md @@ -0,0 +1,37 @@ +## Understanding `groth16_zkproof.ts` + +Navigate to `scripts/groth16/groth16_zkproof.ts`. This script generates the zero-knowledge proof and prepares it for verification. + +### Code Overview + +#### Loading Files: + +- Reads the R1CS and WASM files generated from the circuit. +- Loads the final proving key (`zkey_final`) and verification key (`vKey`). + +#### Defining Inputs: + +- Sets the private values (`value1`, `value2`, `value3`, `value4`). +- Computes the `hash` using Poseidon from [CircomLib](https://github.com/iden3/circomlib). + +#### Witness Calculation and Proof Generation: + +- Calculates the witness (`wtns`). +- Checks the witness against the `R1CS`. +- Generates the proof using `Groth16`. +- Verifies the proof. + +#### Exporting Verifier Contract and Inputs: + +- Generates a Solidity verifier contract. +- Exports the proof inputs to `input.json`. + +### Purpose + +- Generates a zero-knowledge proof that the prover knows values hashing to a specific hash. +- Prepares the verifier contract and inputs for on-chain verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"zk proof validity"` logged in the terminal. diff --git a/locales/tr/CircomIntro/README.md b/locales/tr/CircomIntro/README.md new file mode 100644 index 000000000..c58b2daec --- /dev/null +++ b/locales/tr/CircomIntro/README.md @@ -0,0 +1,21 @@ +Intro to Circom + +This is an introduction to Circom. You'll learn how to write, compile, and test arithmetic circuits in Circom. We'll go over how to do this within Remix-IDE. + +Tutorial Overview + +``` +Step 1: Introduction +Step 2: Setting Up Remix-IDE and Installing the Circuit-Compiler Plugin +Step 3: Writing Your First Circom Circuit +Step 4: Compiling the Circuit Using the Plugin +Step 5: Performing a Trusted Setup +Step 6: Computing the Witness +Step 7: Generating the Proof +``` + +Prerequisites: + +``` +Basic understanding of cryptography and zero-knowledge proofs is helpful but not required. +``` diff --git a/locales/tr/CircomIntro/config.yml b/locales/tr/CircomIntro/config.yml new file mode 100644 index 000000000..d6dfdca46 --- /dev/null +++ b/locales/tr/CircomIntro/config.yml @@ -0,0 +1,29 @@ +id: circom-intro +name: Intro to Circom +summary: A intro to using Circom for creating arithmetic circuits. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction + path: step-1 + - + name: Installing the Circuit-Compiler + path: step-2 + - + name: Writing Your First Circom Circuit + path: step-3 + - + name: Compiling the Circuit Using the Plugin + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Computing the Witness + path: step-6 + - + name: Generating the Proof + path: step-7 diff --git a/locales/tr/CircomIntro/step-1/README.md b/locales/tr/CircomIntro/step-1/README.md new file mode 100644 index 000000000..0766ce6f4 --- /dev/null +++ b/locales/tr/CircomIntro/step-1/README.md @@ -0,0 +1,13 @@ +Welcome to this beginner-level tutorial on Circom using Remix. In this tutorial, you'll learn the basics of Circom, a domain-specific language used for creating arithmetic circuits. + +**What is Circom?** + +Circom is a language designed for writing arithmetic circuits that can be used in zero-knowledge proofs, particularly zk-SNARKs. It allows developers to define complex mathematical circuits that can prove knowledge of certain data without revealing it. + +**Why Use Remix-IDE for Circom?** + +- **Ease of Use:** Remix-IDE provides a user-friendly interface that simplifies the development process. +- **Integrated Tools:** With plugins like `circuit-compiler`, you can compile Circom code, perform trusted setups, compute witnesses, and generate proofs all within the same environment. +- **No Installation Required:** As a web-based IDE, you can start coding immediately without setting up a local development environment. + +In the next steps, we'll guide you through setting up Remix-IDE for Circom development and help you write your first circuit. diff --git a/locales/tr/CircomIntro/step-2/README.md b/locales/tr/CircomIntro/step-2/README.md new file mode 100644 index 000000000..4b228c298 --- /dev/null +++ b/locales/tr/CircomIntro/step-2/README.md @@ -0,0 +1,25 @@ +In this step, we'll set up Remix for Circom development by activating the `Circom ZKP compiler` plugin. + +## Activating the Circom ZKP compiler + +1. At the bottom of the icon panel on the left of the screen, click on the **Plugin Manager** (the plug icon). + 2.In the search bar, type **Circom**. +2. Find the **Circuit Compiler** plugin in the list and click on the **Activate** button. +3. The plugin will now appear in your sidebar. + +install-plugin + +## The Circom Compiler Interface + +- **Compiler Version Dropdown:** Select the Circom compiler version you wish to use. +- **Auto Compile Checkbox:** Enable this to automatically compile your circuit whenever you make changes. +- **Hide Warnings Checkbox:** Enable this to suppress compiler warnings. +- **Advanced Configuration:** Click to expand options for selecting the prime field (e.g., BN128, BLS12381). + +compiler-interface + +With the plugin installed, you're now ready to start writing Circom code in Remix-IDE. + +**Note:** Make sure your internet connection is stable, as Remix-IDE is a web-based tool. + +In the next step, we'll write our first Circom circuit. diff --git a/locales/tr/CircomIntro/step-3/README.md b/locales/tr/CircomIntro/step-3/README.md new file mode 100644 index 000000000..6424668f6 --- /dev/null +++ b/locales/tr/CircomIntro/step-3/README.md @@ -0,0 +1,38 @@ +Let's write a simple Circom circuit. + +## Creating a New Circuit File + +1. In the **File Explorer** on the left sidebar, click on the **Create New File** icon. +2. Name your file `multiplier.circom` and press **Enter**. + +create-new-file + +## Writing the Circuit + +Open `multiplier.circom` and add the following code: + +```circom +pragma circom 2.0.0; + +template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; +} + +component main = Multiplier(); +``` + +## Explanation: + +- template `Multiplier()`: Defines a new circuit template called Multiplier. +- `signal input a;` and `signal input b;`: Declare input signals a and b. +- `signal output c;`: Declare an output signal c. +- `c <== a * b;`: Constrain c to be the product of a and b. +- `component main = Multiplier();`: Instantiates the Multiplier circuit as main, which is required for the compiler. + +### NB: + +Signals are values in a cryptographic circuit that are strictly determined by the circuit's equations and constraints. Think of a signal as a value that must follow specific mathematical rules defined by the circuit—once set, it can't be changed arbitrarily. In regular programming, variables are flexible and can be updated or reassigned as needed, whereas, signals can't be altered freely. diff --git a/locales/tr/CircomIntro/step-4/README.md b/locales/tr/CircomIntro/step-4/README.md new file mode 100644 index 000000000..ad3f2a089 --- /dev/null +++ b/locales/tr/CircomIntro/step-4/README.md @@ -0,0 +1,34 @@ +With your `multiplier.circom` circuit ready, let's compile it using the Circuit Compiler plugin. + +## Selecting the Compiler Version + +Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +## Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +## Compiling the Circuit + +1. Click on the **Compile** button. +2. The compiler will process your circuit. +3. If successful, you'll see a compilation success message. + +compilation-success + +**Note:** If there are any errors, they will be displayed in the console. Check your code for typos or syntax errors. + +## Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/tr/CircomIntro/step-5/README.md b/locales/tr/CircomIntro/step-5/README.md new file mode 100644 index 000000000..8e8496bbd --- /dev/null +++ b/locales/tr/CircomIntro/step-5/README.md @@ -0,0 +1,26 @@ +After compiling your circuit, you need to perform a trusted setup to generate proving and verification keys. + +## Understanding Trusted Setup + +- **Trusted Setup:** A process required for zk-SNARKs to generate the necessary parameters for proof generation and verification. +- You can choose between different protocols like **Groth16** and **Plonk**. + +## Performing the Trusted Setup + +1. In the **Setup and Exports** section, select the **Proving Scheme**: + - Choose between **Groth16** or **Plonk**. We'll use **Groth16** for this tutorial. + +2. Choose the appropriate **Power of Tau** file from the dropdown. This file is necessary for the trusted setup. + - If unsure, select the default option. + +3. Click on the **Setup** button to start the trusted setup process. + +4. You can enable **Export Verification Key** to get the verification parameters. + +5. You can enable **Export Verification Contract** if you intend to verify proofs on-chain. + +trusted-setup + +**Note:** The trusted setup may take some time, depending on the complexity of your circuit. + +In the next step, we'll compute the witness for our circuit. diff --git a/locales/tr/CircomIntro/step-6/README.md b/locales/tr/CircomIntro/step-6/README.md new file mode 100644 index 000000000..e13d33d32 --- /dev/null +++ b/locales/tr/CircomIntro/step-6/README.md @@ -0,0 +1,27 @@ +With the trusted setup complete, you can now compute the witness for your circuit based on specific inputs. + +## What is a Witness? + +- A **Witness** is a set of values that satisfy all the constraints of your circuit. It includes all the intermediate numbers and results that satisfy the circuit's rules. The witness is used in zero-knowledge proofs to demonstrate that you know a valid solution to the problem without actually showing the solution itself. This allows others to verify that you did everything correctly while keeping your specific numbers and calculations private. +- It is essential for generating a proof. + +## Inputting Values + +1. In the **Compute Witness** section, you'll see input fields dynamically generated based on your circuit's inputs. +2. Enter values for `a` and `b`. For example: + - `a = 3` + - `b = 4` + +compute-witness + +## Computing the Witness + +1. After entering the inputs, click on the **Compute Witness** button. +2. The plugin will compute the witness based on your inputs. +3. If successful, you'll see `multiplier.wtn` created in the `.bin` directory in the file explorer. + +witness-computed + +**Note:** If there are any errors, ensure that your inputs are valid and satisfy the circuit's constraints. + +In the next step, we'll generate a proof using the computed witness. diff --git a/locales/tr/CircomIntro/step-7/README.md b/locales/tr/CircomIntro/step-7/README.md new file mode 100644 index 000000000..f5cf332a9 --- /dev/null +++ b/locales/tr/CircomIntro/step-7/README.md @@ -0,0 +1,31 @@ +With the witness computed, the final step is to generate a proof that can be verified by others. + +## Generating the Proof + +1. In the **Generate Proof** section, you have the option to **Export Verifier Calldata**. + - Enable the **Export Verifier Calldata** checkbox if you plan to verify the proof on-chain. +2. Click on the **Generate Proof** button. + +generate-proof + +## Understanding the Output + +- After generating the proof, the plugin will display the proof data. +- If you enabled **Export Verifier Calldata**, it will also provide the calldata needed for on-chain verification. + +proof-generated + +## Next Steps + +- **Verification:** You can use the verification key or contract exported earlier to verify the proof. +- **On-Chain Verification:** If you're familiar with smart contracts, you can deploy the verification contract and use the calldata to perform on-chain verification. + +**Congratulations!** You've successfully written a Circom circuit, compiled it, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + +## Additional Resources + +- [Circom Documentation](https://docs.circom.io/) +- [Remix-IDE Documentation](https://remix-ide.readthedocs.io/) +- [Zero-Knowledge Proofs Explained](https://zkproof.org/) + +Feel free to experiment with more complex circuits and explore the capabilities of Circom and Remix-IDE further. diff --git a/locales/tr/DeployWithLibraries/1_Writing_a_Library/step1.md b/locales/tr/DeployWithLibraries/1_Writing_a_Library/step1.md new file mode 100644 index 000000000..1ad984835 --- /dev/null +++ b/locales/tr/DeployWithLibraries/1_Writing_a_Library/step1.md @@ -0,0 +1,17 @@ +A libraries looks like a **contract** but use the keyword `library` + +A library typically is a collection of useful functions sitting out there on the blockchain that any contract can use. Because the library is already deployed, it saves the deployment costs of the many contracts that use it. + +In the following contract: + +- Make a library with the name `LibraryForTest`. + +It is possible to put a library in same file with another contract. So put the library below the contract. + +This library should have a method called `getFromLib` method which returns `3`. + +- Update the `get` method in the `test` contract to use the `LibraryForTest` library. The function `get` should return the value it receives from `getFromLib`. + +--------- + +You can find more info about libraries in this section of the Solidity Docs. diff --git a/locales/tr/DeployWithLibraries/2_Generate_Metadata/step2.md b/locales/tr/DeployWithLibraries/2_Generate_Metadata/step2.md new file mode 100644 index 000000000..218c86ff9 --- /dev/null +++ b/locales/tr/DeployWithLibraries/2_Generate_Metadata/step2.md @@ -0,0 +1,38 @@ +## Deploying Library + +The **library** from the previous chapter was in the same file as the **contract**. However, they won't be deployed together and will have different addresses. + +In order to use a library, the calling contract must have the library's **address**. + +But the library's address is not directly specified in the solidity code. The calling contract's compiled bytecode contains a **placeholder** where library's **addresses** will go. + +At deployment of the **calling contract**, Remix will look in the contract's **metadata** for the library's address and will update the placeholder with the address. + +So before deploying a contract that calls a library, you need to generate the contract's metadata (AKA its **build artifact**) and then you need to input the library's address into the metadata file. + +A contract's metadata is generated at **compile time**. + +Let's setup Remix to generate the **metadata file**. + +- Go to the settings module by clicking on the settings ![settings](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/settings.png "Settings") icon in the icon panel. + +![settings module](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_settings.png "Settings Module") + +- And check the first option `Generate contract metadata`. + +# Compile and generate metadata (JSON) file. + +1. Open the Solidity Compiler ![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +2. Compile `2_contractSimpleLibrary.sol`. + +3. Switch to the File Explorer ![File Explorer](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_file_explorer.png "File Explorer") + +4. Navigate to the newly create JSON files. + - It should be in the folder: + +**browser/.learneth/DeployWithLibraries/2_Generate_Metadata/artifacts/** + +5. Select the newly created JSON file created from the contract. It has the **same name** as the contract `sample` but with the extension **json**: `sample.json` (don't select the library's metadata `contractSimpleLibrary.json`). + +In the next step we'll make some adjustments to the metadata file. diff --git a/locales/tr/DeployWithLibraries/3_Edit_Metadata/step3.md b/locales/tr/DeployWithLibraries/3_Edit_Metadata/step3.md new file mode 100644 index 000000000..1555d645d --- /dev/null +++ b/locales/tr/DeployWithLibraries/3_Edit_Metadata/step3.md @@ -0,0 +1,12 @@ +The `Deploy` property in `sampleContract.json` contains everything you need for telling Remix IDE the address of the library for a specific network. + +- `
` contains the address of the library that is already deployed. You have to specify this address for each network. +- `autoDeployLib` is a boolean and tells Remix IDE if it should autodeploy the library before deploying the contract. + +Basically if `autoDeployLib` is **true**, the `
` will not be used and Remix will automatically deploy the library before deploying the contract. + +For the purpose of this demo - we are mimicking a situation where the library has already been deployed because this is a more common situation. + +So set `autoDeploy` to **false**, for the `VM:-` entry. + +Move to next Step. diff --git a/locales/tr/DeployWithLibraries/4_Linking_and_Deploying/step4.md b/locales/tr/DeployWithLibraries/4_Linking_and_Deploying/step4.md new file mode 100644 index 000000000..ad5f52e2d --- /dev/null +++ b/locales/tr/DeployWithLibraries/4_Linking_and_Deploying/step4.md @@ -0,0 +1,25 @@ +Switch to the `Deploy & Run` module +![Run transaction](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/remix_runtransaction.png "Run Transaction") + +- Select the Remix VM Environment and select the `sampleContract` contract in the list of compiled contracts. + +- Click on `Deploy` + +The terminal should output something like `creation of sample errored:
is not a valid address. Please check the provided address is valid.` +That is expected: **We have set `autoDeployLib` to false, so Remix expects to have an address and not just `
`** + +So we need deploy the library to get its address. + +- Select the library `aLib` in the list of compiled contract and hit `deploy` + + ![Choose aLib](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/contract_alib.png "Choose aLib") + +- Click the clipboard icon to copy the address of the library. + + ![Copy lib1](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/alib_copy.png "Copy") + +- Paste it into the **contract sample's** metadata JSON. + +- Reselect the `sampleContract` contract in the `Run transaction` module and hit deploy. + +- Deploy should now be successful. diff --git a/locales/tr/DeployWithLibraries/5_Under_The_Hood/step5.md b/locales/tr/DeployWithLibraries/5_Under_The_Hood/step5.md new file mode 100644 index 000000000..860b48b24 --- /dev/null +++ b/locales/tr/DeployWithLibraries/5_Under_The_Hood/step5.md @@ -0,0 +1,30 @@ +Switch to the `Solidity compiler` module +![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +- Select the `sampleContract` contract in the list of compiled contracts. +- click on `ByteCode`, it should copy the following to the clipboard: + +``` +{ + "linkReferences": { + "browser/contractSimpleLibrary.sol": { + "lib1": [ + { + "length": 20, + "start": 115 + } + ] + } + }, + "object": "608060405234801561001057600080fd5b5060f68061001f6000396000f3fe6080604052600436106039576000357c0100000000000000000000000000000000000000000000000000000000900480636d4ce63c14603e575b600080fd5b348015604957600080fd5b5060506052565b005b73__$d42d70ba92b626965f4c69b39148e37a33$__63fea24e5f6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801560b157600080fd5b505af415801560c4573d6000803e3d6000fd5b5050505056fea165627a7a7230582068c9a3a9a5cbfd26cfdab2534abfc926912d9b89eaa14e36c8248b7e7eb0ab090029", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xF6 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x39 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x3E JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x50 PUSH1 0x52 JUMP JUMPDEST STOP JUMPDEST PUSH20 0x0 PUSH4 0xFEA24E5F PUSH1 0x40 MLOAD DUP2 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH1 0xB1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS DELEGATECALL ISZERO DUP1 ISZERO PUSH1 0xC4 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 PUSH9 0xC9A3A9A5CBFD26CFDA 0xb2 MSTORE8 0x4a 0xbf 0xc9 0x26 SWAP2 0x2d SWAP12 DUP10 0xea LOG1 0x4e CALLDATASIZE 0xc8 0x24 DUP12 PUSH31 0x7EB0AB09002900000000000000000000000000000000000000000000000000 ", + "sourceMap": "63:85:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63:85:0;;;;;;;" +} +``` + +This is basically what the compiler is returning: + +- `linkReferences` describes what are the libraries used by the contract. +- `object` is the compiled contract (bytecode). This is what gets deployed and saved onto the blockchain. In this example, the value `__$d42d70ba92b626965f4c69b39148e37a33$__` inside the bytecode is just a placeholder for the library address. In your case, the placeholder will be between `__$` and `$__`. + +The metadata JSON from Remix IDE tells Remix to replace the placeholder with the given address. diff --git a/locales/tr/DeployWithLibraries/README.md b/locales/tr/DeployWithLibraries/README.md new file mode 100644 index 000000000..fb31b1264 --- /dev/null +++ b/locales/tr/DeployWithLibraries/README.md @@ -0,0 +1,3 @@ +**Libraries** are deployed contracts that do not store state and are used by other contracts to decrease their size and thus their deployment costs. + +Learn to work with **Libraries** in Remix - you won't need to whisper. diff --git a/locales/tr/DeployWithLibraries/config.yml b/locales/tr/DeployWithLibraries/config.yml new file mode 100644 index 000000000..0816e2346 --- /dev/null +++ b/locales/tr/DeployWithLibraries/config.yml @@ -0,0 +1,8 @@ +--- +id: deploylibraries +name: Deploy with Libraries +summary: Write, Deploy and link a Library to a Contract +level: 3 +tags: + - Remix + - Solidity diff --git a/locales/tr/ERC20TokenCourse/README.md b/locales/tr/ERC20TokenCourse/README.md new file mode 100644 index 000000000..25a6ccf95 --- /dev/null +++ b/locales/tr/ERC20TokenCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Token Course + +Learn to understand and create ERC20 tokens. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/tr/ERC20TokenCourse/config.yml b/locales/tr/ERC20TokenCourse/config.yml new file mode 100644 index 000000000..8c12a5213 --- /dev/null +++ b/locales/tr/ERC20TokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: tokenCourse +name: Solidity ERC20 Token Course +summary: Learn how to create your own ERC20 tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - ERC20 +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc20-interface + - + name: 3. Token Creation + path: erc20-token-creation + - + name: 4. Interaction + path: erc20-interaction + - + name: 5. Testnet Deployment + path: erc20-testnet-deployment + - + name: 6. Extensions + path: erc20-extensions diff --git a/locales/tr/ERC20TokenCourse/erc20-extensions/erc20extensions.md b/locales/tr/ERC20TokenCourse/erc20-extensions/erc20extensions.md new file mode 100644 index 000000000..b3649fbba --- /dev/null +++ b/locales/tr/ERC20TokenCourse/erc20-extensions/erc20extensions.md @@ -0,0 +1,33 @@ +The ERC20 standard only describes the required and optional functionality that your contract needs, but you can add additional functionality. + +In this section, we added the functionality to burn and mint tokens, as well as the ability to pause the contract, by using OpenZeppelin extensions. + +Of course, you can write your own ERC20 token contract implementation or extensions and import them into your contract. But OpenZeppelin contracts have been audited by security experts and are a great way to add desired functionality. + +### Mintable + +The mint function allows the creator of the contract to mint (create) additional tokens after the contract has been deployed (line 22). As input parameters, the function needs the address that the tokens will be minted to, and the amount of tokens that should be minted. + +We don't have to import `mint()` from another contract since the mint function is already part of the ERC20 contract implementation of OpenZeppelin. We import `Ownable` (line 7) which is a contract module that provides a basic access control mechanism that allows an owner to have exclusive access to specific functions. In this contract, we add the inherited `onlyOwner` modifier to the `mint` function (line 22) and restrict access to this function to the "owner". + +The contract will inherit additional functions like owner(), transferOwnership() and renounceOwnership() to manage access, from the Ownable contract. + +### Burnable + +By importing the "ERC20Burnable" (line 5) and inheriting its functions (line 9) our contract allows token holders to destroy their tokens as well as the tokens in their allowance. +For more information, have a look at the ERC20Burnable contract. + +### Pausable + +With the "Pausable" contract module (line 6 and 9) the owner is able to pause (line 14) and unpause (line 18) the contract. In the pause state, tokens can't be transferred, which can be helpful in emergency scenarios. +For more information, have a look at the Pausable contract. + +Have a look at the OpenZeppelins Contract Wizard, which allows you to easily add additional functionality. + +If you successfully completed this course, try the Learneth NFT Course as the next step in your journey. + +## ⭐️ Assignment + +1. Try to mint tokens to an account after deployment. Call `totalSupply()` and `balanceOf()` to confirm the correct execution. +2. Burn tokens and then call `totalSupply()` and `balanceOf()` to confirm the correct execution. +3. Test the pause function by pausing the contract using the owner account and trying to make a transfer with a second account. The transaction should not be able to be executed and will throw the exception: "Pausable: paused". diff --git a/locales/tr/ERC20TokenCourse/erc20-interaction/er20interaction.md b/locales/tr/ERC20TokenCourse/erc20-interaction/er20interaction.md new file mode 100644 index 000000000..5c082b248 --- /dev/null +++ b/locales/tr/ERC20TokenCourse/erc20-interaction/er20interaction.md @@ -0,0 +1,87 @@ +In this section, we will deploy a contract in our browser and test its functionality. + +### 1. Deploy the contract + +**1.1** Compile your EduCoin contract in the "Solidity compiler" module of the Remix IDE. + +**1.2** In the "Deploy & run transactions" module, select your contract "EduCoin" in the contract input field and click on the "Deploy" button. Always make sure to select the correct contract in the contract selector input field. + +**GIF** Compile and deploy: Compile and deploy contract + +### 2. Test the functions + +Expand the token contract functions in the IDE. + +#### 2.1 Decimals + +Click on the "decimals" button to call the decimals() function. +It should return "18". + +#### 2.2 Name + +Click on the "name" button to call the name() function. +It should return "EduCoin". + +#### 2.3 Symbol + +Click on the "symbol" button to call the symbol() function. +It should return "EDC". + +#### 2.4 Total supply + +Click on the "totalSupply" button to call the totalSupply() function. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test decimals, name, symbol, and totalSupply functions: Test transfer function + +#### 2.5 Balance of + +**2.5.1** Go to the "ACCOUNT" section in the sidebar and copy the displayed address by using the copy icon next to it. + +**2.5.2** Paste the address in the input field next to the "balanceOf" function button and click on the button. +It should return 1000000000000000000000 (1000\*10\*\*18). + +**GIF** Test balanceOf function: Test transfer function + +#### 2.6 Transfer + +We will transfer EduCoin from one account to a second account. + +**2.6.1** Go to the "ACCOUNT" section in the sidebar and click on the displayed address. This should open a dropdown. Select the second address displayed and copy its address (account 2). + +**2.6.2** Open the dropdown and select the first account again (account 1), because this is the account that we want to use to make the transfer. + +**2.6.3** Paste the address in the input field next to the "transfer" function button, input the number 500000000000000000000, and click on the button. + +**2.6.4** If you check the balances for account 1 and account 2, they should both return the amount 500000000000000000000. + +**GIF** Test transfer function: Test transfer function + +#### 2.7 Approve + +We will now allow account 1 to spend tokens on behalf of account 2. + +**2.7.1** Go to the "Account" section, copy the address of account 1, then set it to account 2 again. + +**2.7.2** In the approve function, enter the address of account 1 as the input for spender and set the amount to 250000000000000000000. + +**GIF** Test approve function: Test approve function + +#### 2.8 Allowance + +Next to the "allowance" button enter the address of account 2 as the owner and account 1 as the spender; click on the button. +It should return 1000000000000000000000. + +**GIF** Test allowance function: Test allowance function + +#### 2.9 TransferFrom + +Now account 1 will transfer 250000000000000000000 tokens from account 2 to its own account. + +**2.9.1** Select account 1 in the "ACCOUNT" section. + +**2.9.2** Next to the "transferFrom" button enter the address of account 2 as the sender and account 1 as the recipient, enter 250000000000000000000 as the amount and click on the button. + +**2.9.3** Check the balances of accounts 2 and 1, they should return 250000000000000000000 and 750000000000000000000. + +**GIF** Test transferFrom function: Test transferFrom function diff --git a/locales/tr/ERC20TokenCourse/erc20-interface/erc20interface.md b/locales/tr/ERC20TokenCourse/erc20-interface/erc20interface.md new file mode 100644 index 000000000..5c4e8137c --- /dev/null +++ b/locales/tr/ERC20TokenCourse/erc20-interface/erc20interface.md @@ -0,0 +1,76 @@ +ERC20 (Ethereum Request for Comments 20) is a standard for token contracts that manages fungible tokens on the Ethereum blockchain. + +Fungible tokens are all equal to each other and have the same value, behavior, and rights. Fungible tokens are often used as a medium of exchange, like the currencies ETH or BTC. However, they can also have other use cases like voting rights or reputation. + +If you want to know more about the ERC20 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +To get an overview of the required functionality of an ERC20 token contract, we will look at an interface that interacts with an ERC20 contract. +This interface (line 9) is part of the open-source contract library provided by OpenZeppelin. + +## ERC20 Functions + +Contracts compliant with the ERC20 standard must implement the following six functions: + +### totalSupply + +The function `totalSupply` (line 13) returns the total amount of tokens available. + +### balanceOf + +The function `balanceOf` (line 18) returns the amount of tokens owned by the account with the address `account`. + +### transfer + +The function `transfer` (line 27) transfers `amount` of tokens to the address `recipient`. +This function **must** emit (produce) a `Transfer` event (see below) and **should** throw an exception when the sender doesn't have enough tokens to make the transfer. + +### approve + +The function `approve` (line 52) creates an allowance for the address `spender` to transfer `amount` of tokens on behalf of the account calling the function. + +### allowance + +The function `allowance` (line 36) returns the amount of tokens that the address `spender` is allowed to spend on behalf of the account with the address `owner`. + +### transferFrom + +The function `transferFrom` (line 63) transfers `amount` of tokens on behalf of the address `sender` to the address `recipient`. +This function **must** emit a `Transfer` event. + +## ERC20 Events + +ERC20 contracts must also emit two events: + +### Transfer + +The `Transfer` (line 71) event must be emitted when `value` amount of tokens are transferred from the account with the address `indexed from` to `indexed to`. The parameters `from` and `to` are `indexed` allowing us to search for these events using the indexed parameters as filters. + +### Approval + +The `Approval` (line 77) event must be emitted when the account `indexed owner` approves the account `indexed spender` to transfer `value` amount of tokens on its behalf. + +## ERC20 Optional functions + +In addition to the mandatory functions and events, there are also three optional functions specified in the ERC20 standard that are not implemented in this interface: + +### name + +`function name() external view returns (string);` + +Returns the name of the token. + +### symbol + +`function symbol() external view returns (string);` + +Returns the symbol of the token. + +### decimals + +`function decimals() external view returns (uint8);` + +Returns the number of decimal places the token uses. + +You may want to use decimals to make your token divisible into arbitrary amounts like 1.5 ETH when displayed. The EVM (Ethereum virtual machine) only supports integer numbers. That's why the ERC20 standard suggests to implement the decimal functionality that specifies how many decimal places a token has. 18 decimal places is the industry standard. diff --git a/locales/tr/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md b/locales/tr/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md new file mode 100644 index 000000000..94b513922 --- /dev/null +++ b/locales/tr/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md @@ -0,0 +1,41 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to a testnet of the Ethereum blockchain. This testnet behaves very similarly to the real blockchain (mainnet), but does not require real ETH to pay for transactions. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token + +In order to make transactions on the testnet we need Ethereum testnet tokens, which you can receive from something called a _faucet_. + +**2.1** Switch your Metamask network by clicking on the "Ethereum Mainnetwork" drop down and selecting "Ropsten Test Network". If you don’t see any test networks, click on the "Show/hide" link and enable "Show test networks" in the settings. + +**2.2** Go to https://faucet.ropsten.be/, enter the address of your account, and claim testnet ETH. You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Deployment + +Make sure the EduCoin contract is compiled. + +**3.1.** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It will ask you to connect your account which you should confirm. + +**3.2** Deploy the EduCoin contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. Copy the contract address. + +**3.4** In Metamask, click on assets, then click on the "Import tokens" link, and paste the address of your contract in the input field. + +You should now see a balance of 1000 EDC in your wallet. + +### 4. Make a transaction + +**4.1** Click on the identicon (visual representation of your address) in the Metamask wallet and create a second account (Account 2). + +**4.2** Copy the address of Account 2. + +**4.3** Switch to the first account (Account 1) and send 250 EDC to Account 2. Check the balances of Account 1 and Account 2. You might need to add the token address again for Account 2 to import the tokens and you will need testeth if you want to make a transaction with this account. + +You can also see your account balances if you look at the contract in Remix and call the `balanceOf` function using the addresses of Account 1 and Account 2. diff --git a/locales/tr/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md b/locales/tr/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md new file mode 100644 index 000000000..49b71abdd --- /dev/null +++ b/locales/tr/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md @@ -0,0 +1,18 @@ +A token standard tells us what functionality the contract needs to comply with it. How this functionality is implemented is up to the developers. In this contract, we will use an ERC20 token contract implementation from OpenZeppelin (line 4). In this case, we import version 4.4.0 of the OpenZeppelin contracts. + +Have a look at their nicely documented ERC20 contract to have a better understanding of how an implementation might look. Apart from the functionality specified in the ERC20 standard, this contract provides additional functionality. + +We will create our own contract called MyToken (line 6), which inherits the functionality from the OpenZepplin ERC20 token contract implementation that we imported (line 4). + +This contract implements the optional functions `name()` and `symbol()` of the ERC20 Token standard and has a constructor where their values can be set during the deployment of the contract (line 7). +In this case, we are going to use the default values. We will call our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +Next, we make use of the inherited `_mint` function (line 8) that allows us to create tokens upon deployment of the contract. Inside the parameters, we specify the address of the account that receives the tokens and the amount of tokens that are created. +In this case, the account that deploys the contract will receive the tokens and we set the amount to 1000000 to the power of `decimals()`. The optional function `decimals()` of the ERC20 token standard is implemented and set to the default value of 18. This will create 1000000 tokens that will have 18 decimal places. + +## ⭐️ Assignment + +1. Rename your contract to `EduCoin`. +2. Rename your token to `EduCoin`. +3. Change the symbol of your token to `EDC`. +4. Change the amount of tokens that will be minted from 1000000 to 1000. diff --git a/locales/tr/ERC20TokenCourse/introduction/introduction.md b/locales/tr/ERC20TokenCourse/introduction/introduction.md new file mode 100644 index 000000000..4eaf7583c --- /dev/null +++ b/locales/tr/ERC20TokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with the ERC20 token standard in the following sections. + +If you want to learn more about NFTs and the ERC721 token standard, have a look at the Learneth NFT Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/tr/ERC721Auction/README.md b/locales/tr/ERC721Auction/README.md new file mode 100644 index 000000000..325e4d60e --- /dev/null +++ b/locales/tr/ERC721Auction/README.md @@ -0,0 +1,5 @@ +## NFT Auction Contract + +Learn how to write an ERC721 (NFT) auction contract. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/tr/ERC721Auction/auction-contract-setup/auctionContractSetup.md b/locales/tr/ERC721Auction/auction-contract-setup/auctionContractSetup.md new file mode 100644 index 000000000..945f0f803 --- /dev/null +++ b/locales/tr/ERC721Auction/auction-contract-setup/auctionContractSetup.md @@ -0,0 +1,46 @@ +In this contract tutorial, we will learn how to create an ERC721 (NFT) auction contract. +We recommend to you, to do the Learneth "Solidity NFT Course" before starting this tutorial. + +In the following sections, we will create a contract that will enable a seller to auction an NFT to the highest bidder. This contract was created by the Solidity by Example project. In this first section, we will create an interface, the necessary state variables, and the constructor. + +### Interface + +We create the interface (line 5) for the ERC721 token since our contract will need to interact with it. We will need the `safeTransferFrom` (line 5), and` transferFrom` (line 11) methods. + +### EnglishAuction + +We create the four events `Start`, `Bid`, `Withdraw`, `End` (line 19-22) so we can log important interactions. + +Next, we will create the state variables that store all the necessary information about our auction on-chain. + +We create two state variables for the NFT we want to auction. In the variable `nft` (line 24) we store a representation of the NFT contract, that will allow us to call its functions by combining the interface IERC721 and the address of the NFT contract. +In `nftId` (line 25), we store the specific token id in our NFT contract that will be auctioned. + +Next, we need a variable to store the address of the person that is auctioning off the NFT, the `seller` (line 27). +We want our NFT contract to send the seller the proceeds of the auction when it is finished, that’s why use `address payable`. + +We create a state variable `endAt` (line 28) where we will store the end date of the auction. +We also create the two booleans, `started` (line 29) and `ended` (line 30), that keep track of whether the auction has started or ended. + +We create a variable `highestBidder` (line 32) where we will store the address of the highest bidder. We will send the highest bidder the NFT once the auction has ended. + +Finally, we need a uint `highestBid` (line 33) to store the highest bid and a mapping `bids` (line 34), where we can store the total value of bids that an account has made before withdrawing; more on this in the next section. + +### Constructor + +When the auctioneer deploys the contract, they need to provide a few arguments: +the address of the contract of the NFT they want to auction `_nft` (line 37), the token id of the NFT they want to auction `_nftId` (line 38), and a starting price that must be overbid to place the first bid in the auction,`_startingBid` (line 39). + +Once deployed, the state variables `nft` (line 41), `nftId` (line 42), `highestBid` (line 45) will be assigned the values from the arguments. The address of the `seller` that deployed the contract will be automatically read out via msg.sender and stored in the state variable `seller` (line 44). + +In the next section, we will enable the auctioneer to start the auction and bidders to place their bids. + +## ⭐️ Assignment + +We will use the assignment part of the following sections to give you instructions on testing your contract in the Remix VM environment of Remix. + +1. Deploy an NFT contract. You can use the NFT contract that we created in our "3.3 ERC721 - Token Creation" section. + +2. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +3. After deploying your contract, test if contract functions like `nft`, `nftId`, and `started` work as expected. diff --git a/locales/tr/ERC721Auction/auction-start-bid/auctionContractStartBid.md b/locales/tr/ERC721Auction/auction-start-bid/auctionContractStartBid.md new file mode 100644 index 000000000..c2b944e0c --- /dev/null +++ b/locales/tr/ERC721Auction/auction-start-bid/auctionContractStartBid.md @@ -0,0 +1,42 @@ +In this section, we will create a function to start the auction and a function to bid on the NFT. + +### Start + +We use some control structures to check if necessary conditions are met before we let the seller start the auction. + +First, we check if the auction has already started (line 49). If it has started and our state variable `started` returns `true` we exit the function and throw an exception. + +The second condition we check for is whether the seller is executing the function (line 50). We have already created a function to store the seller's address when they deploy the contract in the `seller` state variable and can now check if the account executing the start function is the seller. If not we throw an exception. + +Next, we want to transfer the NFT that is up for auction from the seller to the contract (line 52). +We set the state variable `started` to `true` (line 53), and create an end date for the auction (line 54). In this case, it will be seven days from when the start function has been called. We can use a suffix like `days` after a literal number to specify units of time. If you want to learn more about time units have a look at the solidity documentation. + +Finally, we will emit our `Start()` event (line 56). + +### Bid + +Before the function caller can make a bid, we need to be sure that certain conditions are met. The auction needs to have started (line 60), the auction can not have ended (line 61) and the bid (the value attached to the call) needs to be higher than the current highest bid (line 62). + +Now we want to store the bid of the current highest bidder before we make a new bid. +First, we check if there is a bidder (line 64). If this function call is the first bid then the next line would be irrelevant. +In our mapping `bids` (line 34) we map the key, the `address` of the bidder, to the value, a `uint` that represents the total amount of ETH a bidder has bid in the auction before withdrawing. +If there is a bidder, we add the last bid (`highestBid`) of the `highestBidder` to the total value of the bids they have made (line 65) before withdrawing. +We store the bids because we want to enable the bidder to withdraw the ETH they used to make bids if they are no longer the highest bidder. + +Next, we set the `highestBidder` to the account calling the function (line 68), and the `highestBid` to their bid, the value that was sent with the call (line 69). + +Finally, we emit the `Bid` event (line 71). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we create in our "Solidity NFT Course" Learneth course. + +2. Mint yourself an NFT with the tokenId 0. + +3. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +4. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for `tokenId`. This will allow the contract to transfer the token to be auctioned. + +5. Call the `start` function of your auction contract. If you call the `started` function now, it should return `true`. If you call the `highestBid` function it should return 1. + +6. Set the value that you can attach to transactions to 3 Wei and call the `bid` function of the auction contract. If you call the `highestBid` function it should now return 3. diff --git a/locales/tr/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md b/locales/tr/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md new file mode 100644 index 000000000..e324a5c6e --- /dev/null +++ b/locales/tr/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md @@ -0,0 +1,45 @@ +In this section, we will finish the contract, create a function to withdraw the bids that an account has made, and create a function to end the auction. + +### Withdraw + +We create a local variable `bal` (balance) that stores the total value of bids that the function caller has made (line 75) since their last withdrawal. We can assign this value to `bal` by accessing the bids mapping using the address of the function caller as the key. + +Next, we set the value of the address of the function caller to 0 in the bids mapping because they will withdraw the total value of their bids (line 76). + +Now we transfer that amount of ETH from the contract to the function caller and emit the `Withdraw` event (line 79). + +### End + +Before the function caller can execute this function and end the auction, we need to check if certain conditions are met. The auction needs to have started (line 83), the end date of the auction needs to have been reached (line 84), and the auction must not have ended already (line 85). + +Once the auction has ended, we set the state variable `ended` to `true` (line 87). + +We check if anybody participated in the auction and bid on the NFT (line 88). + +If there was a bid, we transfer the NFT from the contract to the highest bidder (line 89) and transfer the ETH that was sent from the highest bidder to the contract, now to the address of the auctioneer, the seller of the NFT (line 90). + +If nobody bids on the NFT, we send the NFT back to the auctioneer (line 92). + +Finally, we emit the `End` event (line 95). + +## ⭐️ Assignment + +1. Deploy an NFT contract. You can use the NFT contract that we created in our Learneth "Solidity NFT Course". + +2. Mint yourself an NFT with the tokenId 0. + +3. For testing purposes, change the value that is assigned to the `endAt` state variable (line 54) from `7 days` to `5 minutes`. + +4. Deploy this EnglishAuction contract. Use the address of the NFT contract as an argument for the `_nft` parameter, 0 for `_nftId`, and 1 for `_startingBid`. + +5. Call the `approve` function of your NFT contract with the address of the auction contract as an argument for the `to` parameter, and 0 for the `tokenId`. + +6. Call the `start` function of your auction contract. + +7. Bid 2 Ether using account 1, and 3 Ether using account 2. If you call the `highestBidder` function, it should now return the address of account 2. + +8. Call the `withdraw` function with account 1. In the balance of account 1, you should see the 2 Ether minus some transaction fees. + +9. After 5 minutes have passed, call the `end` function. Then, call the `ended` function which should return `true`. + +In the NFT contract, if you call the `ownerOf` function with the tokenId 0, it should return the address of account 2. If you look at the balance of account 1 it should have increased by 3 Ether minus some transaction fees. diff --git a/locales/tr/ERC721Auction/config.yml b/locales/tr/ERC721Auction/config.yml new file mode 100644 index 000000000..0783a37a1 --- /dev/null +++ b/locales/tr/ERC721Auction/config.yml @@ -0,0 +1,19 @@ +--- +id: er721Auction +name: NFT Auction Contract +summary: Learn how to write an ERC721 (NFT) auction contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: Contract Setup + path: auction-contract-setup + - + name: Start and Bid Functions + path: auction-start-bid + - + name: Withdraw and End Functions + path: auction-withdraw-end diff --git a/locales/tr/Interoperability/1_Intro/intro.md b/locales/tr/Interoperability/1_Intro/intro.md new file mode 100644 index 000000000..ab26f4f6d --- /dev/null +++ b/locales/tr/Interoperability/1_Intro/intro.md @@ -0,0 +1,5 @@ +As the web3 world grows, there will be more blockchains. Unless the chains can communicate with one another, the ecosystem will become increasingly fragmented. + +The Axelar network enables protocols to have cross-chain functionality between any two blockchains. + +Building a protocol that is interoperable between ecosystems is essential for growth. diff --git a/locales/tr/Interoperability/2_Gateway/gateway.md b/locales/tr/Interoperability/2_Gateway/gateway.md new file mode 100644 index 000000000..dc752d3eb --- /dev/null +++ b/locales/tr/Interoperability/2_Gateway/gateway.md @@ -0,0 +1,25 @@ +The Axelar Gateway is the entrypoint for your smart contract into the Axelar ecosystem. Once you have triggered the appropriate function on the Gateway, your transaction will begin its interchain journey from your source chain across the Axelar network to the destination chain. Each chain that is connected to Axelar has a deployed gateway contract for you to interact with. + +The following are the two more relevant functions you will need to be familiar with. + +## callContract() + +This function triggers an interchain transaction with a message from the source to the destination chain. It takes three relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent + +The first two parameters are quite intuitive. They consist of both the name of the chain you want this transaction to go to and the address on that chain you want to end execute at. The final parameter is the payload. This payload represents a general message that is sent to the destination chain. The message can be used in many different ways on the destination chain. For example, you can send data to be used as a parameter in another function on the destination chain, you can send a function signature as a message that will then get executed on a destination chain, and much more. + +## callContractWithToken() + +This function triggers an interchain with a message and a fungible token from the source to the destination chain. It takes five relevant parameters: + +1. `destinationChain`: The name of the destination chain +2. `destinationContractAddress`: The address on the destination chain this transaction will execute at. +3. `payload`: The message that is being sent +4. `symbol`: The symbol of the token being sent +5. `amount`: The amount of that token that is being sent + +The first three parameters here are the same as in `callContract()`. The final two parameters are relevant to the token that is being sent along with the message. These are the symbol of the token and the amount of the token that is being sent. diff --git a/locales/tr/Interoperability/3_GasService/GasService.md b/locales/tr/Interoperability/3_GasService/GasService.md new file mode 100644 index 000000000..4ed0afbbf --- /dev/null +++ b/locales/tr/Interoperability/3_GasService/GasService.md @@ -0,0 +1,29 @@ +The Axelar Gas Service is an extremely useful tool made available to pay gas for an interchain transaction. It allows you to pay for the cost of a transaction in the token of the source chain, making for a much easier end user (and developer) experience. If for example the source chain is Ethereum and the destination chain is Polygon then the gas service will receive the complete payment for the transaction in ETH and no matic is needed from the caller to pay for the execution on the Polygon destination chain. + +The following are the two more relevant functions you will need to be familiar with in regards to the Gas Service. + +## payNativeGasForContractCall() + +This function allows you to pay for the entirety of an interchain transaction in the native token of the source chain. It takes five relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +The parameters overlap with the parameters required by the `callContract()` function in the Gateway contract. The two parameters not discussed in the Gateway section are `sender` and `refundAddress`. The sender is the address paying for the transaction and the refund address is the address that will receive any surplus funds sent to the gas service. + +## payNativeGasForContractCallWithToken() + +This function allows you to pay for the entirety of an interchain transaction (that includes a token transfer) in the native token of the source chain. It takes seven relevant parameters: + +1. `sender`: The address making the payment +2. `destinationAddress`: The address on the destination chain the transaction is sent to +3. `destinationChain`: The name of the destination the transaction is sent to +4. `payload`: The message that is being sent +5. `symbol`: The symbol of the token that was sent +6. `amount`: The amount of the token that was sent +7. `refundAddress`: The address any refunds should be sent to if too much gas was sent along with this transaction. + +This function is nearly identical to the first top one the main difference being that it is used for message + token transfer transactions as opposed to just interchain message transactions (aka GMP Transactions). As a result the GasService needs to also know the `symbol` and `amount` of the token that is being sent. diff --git a/locales/tr/Interoperability/4_Executable/executable.md b/locales/tr/Interoperability/4_Executable/executable.md new file mode 100644 index 000000000..1f72c6be4 --- /dev/null +++ b/locales/tr/Interoperability/4_Executable/executable.md @@ -0,0 +1,27 @@ +The Axelar executable contains relevant helper functions that will be automatically executed on the destination chain in correspondence to the relevant inbound transaction from the source chain. + +The following are the relevant functions you will need to use from Axelar Executable + +## \_execute() + +This function handles the execution on the destination chain. It takes the following four parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent + +The `sourceChain` and `sourceAddress` are key parameters which you receive out of the box that can be used for verifying authenticity of messages on the destination chain. The payload (as discussed in the gateway section) is the message that was sent from the source chain to be used on your destination chain. The `commandId` will not be used during the rest of this module. + +## \_executeWithToken() + +This function handles the execution on the destination chain for a message being sent with a fungible token. It takes six relevant parameters: + +1. `commandId`: A unique transaction id on the Axelar chain. +2. `sourceChain`: The blockchain which the transaction has been sent from +3. `sourceAddress`: The address from the source chain that the transaction has been sent from +4. `payload`: The message that is being sent +5. `tokenSymbol`: The symbol of the token being sent +6. `amount`: The amount of that token that is being sent + +The first four parameters are identical to that of the `_execute()` function. The final two parameters of `tokenSymbol` and `amount` are in reference to the token that is being sent along with the message. It allows you on the destination chain to interact with the token accordingly, for example transferring it to another receiving address. The `commandId` will not be used during the rest of this module. diff --git a/locales/tr/Interoperability/5_InterchainMessage/interchainMessage.md b/locales/tr/Interoperability/5_InterchainMessage/interchainMessage.md new file mode 100644 index 000000000..029f642ce --- /dev/null +++ b/locales/tr/Interoperability/5_InterchainMessage/interchainMessage.md @@ -0,0 +1,53 @@ +In this section we will create a contract that will send a "hello world" message between two blockchains. + +## Constructor + +The first thing you will need to create is the `constructor` for the function. This will allow you to set the `Gateway` and `Gas Service` contracts we discussed in the previous sections. + +When deploying the contract you will pass in the address of the `Gateway` and `GasService` for Ethereum Sepolia those addresses are `0xe432150cce91c13a887f7D836923d5597adD8E31` for the Gateway and `0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6` for the Gas Service. + +For the full list of relevant Axelar addresses see here + +## Send Interchain Message + +Now that the constructor has set the relevant Axelar addresses needed to trigger an interchain transaction you can move on to the `setRemoteValue()`, which will trigger this transaction. + +This function takes three parameters: + +1. `_destinationChain`: The chain which the transaction is going to +2. `_destinationAddress`: The address on the destination chain the transaction will execute at +3. `_message`: The message being passed to the destination chain + +First, you have a `require` statement which ensures that the `msg.value` contains a value. This `msg.value` will be used to pay the `GasService`. If no funds were sent, then the transaction should be reverted as the transaction cannot execute on the Axelar blockchain and destination chain without any gas. + +Next, you encode the `_message` that was passed in. Notice that the `_message` is set as a `string` type. Axelar expects this message to be submitted as a `bytes` type so to convert the `string` to `bytes` you simply pass it through `abi.encode()`. + +Now, with your message encoded you can begin to interact with the `GasService` and the `Gateway` + +To pay for the entire interchain transaction you will trigger the function `payNativeGasForContractCall`, which is defined in the `GasService`. + +This function needs the parameters explained earlier in the GasService section. The `sender` for this transaction will be this contract, which is `address(this)`. The `destinationChain` and `destinationAddress` can simply be passed in from this functions parameters, the `payload` is the encoded \_message we wrote earlier. Finally, you need to specify what the refund address is, this can be the address that triggers this function, which you get by writing `msg.sender`. + +Once you trigger this function you will have successfully sent a transaction from the source chain via Axelar to the destination chain! But there is still one final step that needs to be complete. + +### Receive Message on Destination Chain + +On the destination chain the inbound interchain transaction needs to be picked up and handled by the `AxelarExecutable`'s `_execute()` function. + +The `_execute()` function is defined in the `AxelarExecutable` contract so when defining this function you must remember to include the `override` keyword. + +This function takes three parameters. + +1. `_sourceChain`: The blockchain which the transaction has originated from +2. `_sourceAddress`: The address on the source chain which the transaction has been sent from +3. `_payload`: The message that has been sent from the source chain + +The first thing that needs to be done in this contract is to get access to your `message` that was sent. Recall, before sending the message it was sent through `abi.encode()` to convert the message from type `string` to type `bytes`. To convert your message back from type `bytes` to type `string` simply pass the `_payload` to the function `abi.decode()` and specify that you want the `_payload` decoded to type `string`. This will return the message as a string. + +Now that you have your message as a type string you can set the `sourceChain` and `sourceAddress` storage variables as `_sourceChain` and `_sourceAddress` to have an easy reference to the data that was passed in. You can also emit the `Executed` event with the `sourceAddress` and `message` event that you just decoded. + +Great! At this point you are now handling the interchain transaction on the destination chain. + +To interact with this contract make sure you deploy it on at least two blockchains so that you can call `setRemoteValue()` from the one chain and then have the `_execute()` function automatically triggered on another chain. You will be able to query the `sourceChain` and `sourceAddress` variables on the destination chain to ensure that the interchain execution worked correctly. + +To view the full step by step of the interchain transaction checkout the Axelarscan (testnet) block explorer. diff --git a/locales/tr/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md b/locales/tr/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md new file mode 100644 index 000000000..11915eb32 --- /dev/null +++ b/locales/tr/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md @@ -0,0 +1,39 @@ +At this point we have gone over an example of how to send a general message between one blockchain to another. Now, let's implement a contract that sends a message and a token from one blockchain to another. + +## Overview + +This contract should seem largely familiar. Much like the previous section the `constructor` receives the `Gateway` and `Gas Service` addresses. + +It then has a function that will be called from the source chain called `sendToMany` that takes in parameters similar to the previous section. + +1. `_destinationChain`: The chain the transaction is sending to +2. `_destinationAddress`: The address on the destination chain your transaction is sending to +3. `_destinationAddresses`: The message that you will be sending along with your token transfer. In this example the message is a list of receiving addresses for the token transfer. +4. `_symbol`: The symbol of the token address being sent +5. `_amount`: The amount of the token being sent + +In the function we already have the `require` statement implemented to ensure gas is sent + +We also have the basic ERC20 functionality to send the token from the calling wallet to this smart contract. The contract also calls the `approve` function to allow the Gateway to eventually transfer funds on its behalf. + +Finally, the `_executeWithToken()` function is also implemented out of the box. + +It makes use of the following params: + +1. `_payload`: The incoming message from the source chain +2. `_tokenSymbol`: The symbol of the token that was sent from the source chain +3. `_amount`: The amount of the token that was sent from the source chain + +Now with these params that were passed in, the `_execute()` function can send the tokens that were sent to the appropriate receivers. + +## Challenge + +Your challenge here is to finish off the `sendToMany()` function using the Axelar Gateway and Gas Service to trigger an interchain transaction. + +In the end you should be able to deploy this contract on two testnets, trigger the `sendToMany()` function and see the live transaction on Axelarscan (testnet) block explorer. + +### Testing Notes + +Note 1: The recommended ERC20 to use is `aUSDC` a wrapped version of the USDC token that can be obtained from the discord faucet bot. When triggering the `sendToMany()` function simply pass in the symbol `aUSDC` to the fourth param. + +Note2: When triggering the `sendToMany()` function you must remember to `approve` your contract to spend `aUSDC` tokens on your behalf, otherwise `transferFrom()` on line49 will throw an error. diff --git a/locales/tr/Interoperability/7_FurtherReading/furtherReading.md b/locales/tr/Interoperability/7_FurtherReading/furtherReading.md new file mode 100644 index 000000000..a601d7ac7 --- /dev/null +++ b/locales/tr/Interoperability/7_FurtherReading/furtherReading.md @@ -0,0 +1,11 @@ +Congratulations on making it to the end of the interoperability module! 🎉🎉 + +To continue your learning journey of interoperability with Axelar. There are many useful resources available. + +- For documentation 📚 + +- For more technical examples 💻 + +- For live coding demos 📹 + +- For the developer blog 📝 diff --git a/locales/tr/Interoperability/README.md b/locales/tr/Interoperability/README.md new file mode 100644 index 000000000..a43fc5dd5 --- /dev/null +++ b/locales/tr/Interoperability/README.md @@ -0,0 +1,3 @@ +## Interoperability Between Blockchains + +Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. diff --git a/locales/tr/Interoperability/config.yml b/locales/tr/Interoperability/config.yml new file mode 100644 index 000000000..39f1be7ed --- /dev/null +++ b/locales/tr/Interoperability/config.yml @@ -0,0 +1,31 @@ +--- +id: interopCourse +name: Multichain Protocols with Axelar +summary: Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. +level: 2 +tags: + - Solidity + - Interoperability + - Axelar +steps: + - + name: An Intro to Axelar + path: 1_Intro + - + name: Axelar Gateway + path: 2_Gateway + - + name: Axelar Gas Service + path: 3_GasService + - + name: Axelar Executable + path: 4_Executable + - + name: Interchain Messages + path: 5_InterchainMessage + - + name: Interchain Token Transfers + path: 6_InterchainTokenTransfer + - + name: Further Reading + path: 7_FurtherReading diff --git a/locales/tr/Multisig-Tutorial/1-multisig-introduction/introduction.md b/locales/tr/Multisig-Tutorial/1-multisig-introduction/introduction.md new file mode 100644 index 000000000..3e9f18938 --- /dev/null +++ b/locales/tr/Multisig-Tutorial/1-multisig-introduction/introduction.md @@ -0,0 +1,41 @@ +Welcome to the Multisignature Wallet course! In this section, we'll explore the fundamentals of Multisignature (Multisig) wallets and we'll go through a multisig wallet contract. + +## What is a Multisignature Wallet? + +A multisignature (multisig) wallet is a type of digital wallet that requires multiple keys to authorize a cryptocurrency transaction. + +Imagine a multisig wallet as a secure vault with multiple locks. To open the vault, each keyholder must open their individual lock. This setup ensures that no single person can access the vault's contents without the others' consent. + +## How Does a Multisig Wallet Work? + +In a multisig setup, each transaction must receive a predetermined number of approvals from a set group of individuals. For instance, in a 3-of-5 wallet configuration, there are five authorized addresses, but a transaction only goes through when at least three of them give their approval. When a transaction is initiated, it's presented as a **proposal** to the group. Each member who agrees to the transaction uses their private key to digitally sign it. + +These **digital signatures** are unique and are generated based on the combination of the transaction data and the private key. + +When the required number of signatures is reached, the transaction is broadcasted to the blockchain for execution. + +## Why Use a Multisig Wallet? + +Multisig wallets are crucial for enhanced security in cryptocurrency transactions. They mitigate the risk of theft or loss of a single key. In business, they're used to ensure that funds can't be moved without consensus among stakeholders. For instance, in a company managing cryptocurrency assets, a multisig wallet might require the CFO, CEO, and a board member to all approve significant transactions, protecting against internal fraud or external hacks. + +## Conclusion + +In this section, we learned that a multisig wallet requires multiple keys to authorize a proposed cryptocurrency transaction and that a multisigs mitigates the risk of theft or loss of a single key. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is a Multisignature Wallet? + +1. A digital wallet that requires a single signature for transactions. +2. A digital wallet that requires multiple signatures for transactions. +3. A physical wallet used for storing cryptocurrency. +4. A wallet that can only hold multiple types of cryptocurrencies. + +### 2) How does a Multisignature Wallet enhance security? + +1. By requiring a single private key for transactions. +2. By distributing transaction approval across multiple owners. +3. By storing transaction data on-chain. +4. None of the above. + +Feel free to take your time and answer the questions above. Once you're ready, we'll move on to exploring the Multisig smart contract and understanding its structure. diff --git a/locales/tr/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md b/locales/tr/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md new file mode 100644 index 000000000..17b0a924f --- /dev/null +++ b/locales/tr/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md @@ -0,0 +1,60 @@ +In this section, we'll explore the **initialization process** of the Multisig smart contract. We'll examine the constructor function and review how it sets up the initial state of the contract. + +## Note + +From this section on in this tutorial, we will be building up a multisig contract. In subsequent sections, the contract will become increasingly complete. + +## Overview + +In this section, the contract consists of events, state variables, modifiers, and functions. **Events** provide transparency by logging specified activities on the blockchain, while **modifiers** ensure that only authorized users can execute certain functions. + +## State Variables + +In Line 4, we have the MultisigWallet contract itself. At the beginning of the contract, we have three state variables. + +1. **`owners`:** An array containing the addresses of all owners of the multi-signature wallet (Line 5). +2. **`isOwner`:** A mapping indicating whether an address is an owner (Line 6). +3. **`numConfirmationsRequired`:** The number of confirmations required for a transaction (Line 7). + +The setup of array and mapping allows us to easily retrieve the list of owners and verify whether an address is an owner. + +## Modifiers + +Next, we have a modifier called `onlyOwner` (Line 9). Modifiers in Solidity are special keywords that can be used to amend the behavior of functions. In our case, the `onlyOwner` modifier ensures that only owners can execute a function. It does this by checking whether the address of the **caller** is an owner. + +## Constructor Function + +The `constructor` function (Line 14) is executed only once during the deployment of the contract. It initializes essential parameters, in this case, the list of owners and the required number of confirmations (Line 14). + +On lines 15 and 16, we have two `require` statements to ensure that the inputs are valid. In this case, we require that there must be at least one owner and that the number of required confirmations must be greater than zero and less than or equal to the number of owners. + +The constructor then initializes the contract state by verifying that is not address(0) (Line 25) and that the owner is unique (Line 26). Then it adds a key/ value pair to the isOwner mapping (Line 28), and then it populates the `owners` array with the provided owner addresses (Line 29). + +Finally, it sets the `numConfirmationsRequired` variable with the specified value (Line 32). + +## getOwners Function + +The `getOwners` function (Line 36) allows users to retrieve the list of owners of the multi-signature wallet. It returns the `owners` array (Line 37). + +## getNumConfirmationsRequired Function + +The `getNumConfirmationsRequired` function (Line 41) allows users to retrieve the number of confirmations required for a transaction. It returns the `numConfirmationsRequired` variable (Line 42). + +## Conclusion + +In this section, we explored the initialization process of the Multisig smart contract. We examined the constructor function and understood how it sets up the initial state of the contract. + +## ⭐️ Assignment: Deploy a Multisig Wallet + +Deploy a Multisig contract with three owners and require two confirmations for transaction execution. + +1. Compile contractInitialization.sol +2. Go to Deploy & Run Transactions in Remix. +3. Expand the "Deploy" section. +4. Under "_OWNERS", enter three an array of three addresses. +5. Under "_NUM_CONFIRMATIONS_REQUIRED", enter the number of confirmations required for a transaction. + +**Hints:** + +- You can get addresses from the "ACCOUNTS" dropdown menu. +- The array of addresses should be in the format: ["0x123...", "0x456...", "0x789..."]. diff --git a/locales/tr/Multisig-Tutorial/3-multisig-deposits/deposits.md b/locales/tr/Multisig-Tutorial/3-multisig-deposits/deposits.md new file mode 100644 index 000000000..a8a14213b --- /dev/null +++ b/locales/tr/Multisig-Tutorial/3-multisig-deposits/deposits.md @@ -0,0 +1,34 @@ +In this section, we'll explore the `receive` function and the associated Deposit event. We'll examine how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## Deposit Event + +On line, 9 we have the Deposit event. The Deposit event is emitted whenever Ether is deposited into the multi-signature wallet. It includes three parameters: + +1. `sender`: The address that sent the Ether. +2. `amount`: The amount of Ether deposited. +3. `balance`: The updated balance of the contract after the deposit. + +We can use the Deposit event to track the flow of Ether into the multi-signature wallet and maybe trigger other actions based on the event. + +## receive Function + +On line 43, we have the `receive` function. The `receive` function is a special function that is executed whenever Ether is sent to the contract. + +The `receive` function is marked as `external` and `payable`. The `external` modifier means that the function can only be called from outside the contract. The `payable` modifier means that the function can receive Ether. + +The `receive` function emits the Deposit event (Line 44) with the address of the sender, the amount of Ether sent, and the updated balance of the contract. It doesn't return anything. + +To receive Ether, a contract must have a `receive`, `fallback`, or a function with the `payable` modifier. If none of these are present, the contract will reject any Ether sent to it. + +## Conclusion + +In this section, we explored the `receive` function and the associated Deposit event. We examined how the `receive` function is used to deposit Ether into the multi-signature wallet and how the Deposit event provides transparency. + +## ⭐️ Assignment: Deposit Ether + +Deposit 2 Ether into the Multisig contract. + +1. Deploy the Multisig contract as in the previous assignment. +2. Enter a Value of 2 Ether in the Value field and select Ether in the dropdown menu. +3. At the bottom of your deployed contract in the "Low level interactions" section, click on the "Transact" button. +4. On top of your deployed contract, it should now say "Balance: 2 Ether". diff --git a/locales/tr/Multisig-Tutorial/4-multisig-transactions/transactions.md b/locales/tr/Multisig-Tutorial/4-multisig-transactions/transactions.md new file mode 100644 index 000000000..f62fd48a0 --- /dev/null +++ b/locales/tr/Multisig-Tutorial/4-multisig-transactions/transactions.md @@ -0,0 +1,73 @@ +In this section, we'll explore the process of submitting and confirming transactions. + +## Modifiers + +We have new modifiers in this iteration of the contract. Let's examine them one by one. + +1. **`txExists` modifier:** (Line 13) ensures that the transaction exists. It does this by checking whether the transaction index is less than the length of the `transactions` array. We'll go into more about in this modifier later in this section. +2. **`notExecuted` modifier:** (Line 18) ensures that the transaction has not been executed. It does this by checking whether the `executed` variable of the transaction is false. +3. **`notConfirmed` modifier:** (Line 23) ensures that the transaction has not been confirmed by the caller. It does this by checking whether the `isConfirmed` mapping of the transaction index and the caller's address is false. + +## Transaction Struct + +On line 28, we have a struct called `Transaction`. We store the struct members: `to`, `value`, `data`, `executed`, and `numConfirmations` in individual variables. + +## Mapping of Confirmations + +On line 37, we have a mapping called `isConfirmed`. This mapping is used to keep track of the confirmations of each transaction. It maps the transaction's index to a mapping of an owner addresse to a boolean value. The boolean value indicates whether this owner has confirmed the transaction. + +## Transactions Array + +On line 39, we have an array called `transactions`. The array is used to store all the transactions submitted to the multi-signature wallet. + +## Events + +We have four new events in this iteration of the contract: + +1. **`SubmitTransaction` event:** emitted whenever a transaction is submitted to the multi-signature wallet. +2. **`ConfirmTransaction` event:** emitted whenever a transaction is confirmed by an owner. +3. **`RevokeConfirmation` event:** emitted whenever a transaction confirmation is revoked by an owner. +4. **`ExecuteTransaction` event:** emitted whenever a transaction is executed. + +## submitTransaction Function + +The `submitTransaction` function (Line 78) allows users to submit a transaction to the multi-sig wallet. It takes three parameters: `to`, `value`, and `data`. The `to` parameter is the address of the recipient of the transaction. The `value` parameter is the amount of Ether to be sent. The `data` parameter is the data to be sent to the recipient. Only owners can submit transactions. + +On line, 85 we create a new transaction struct and push it to the `transactions` array and emit the `SubmitTransaction` event. The `txIndex` variable is used to keep track of the transaction index. + +## confirmTransaction Function + +The `confirmTransaction` function (Line 98) allows users to confirm a transaction. It takes one parameter: `txIndex`. +It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. The `onlyOwner` modifier ensures that only owners can confirm transactions. The `txExists` modifier ensures that the transaction exists. The `notExecuted` modifier ensures that the transaction has not been executed. + +On line 101, we store the transaction in a local variable called `transaction`. We then increment the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to true. Finally, we emit the `ConfirmTransaction` event. + +## executeTransaction Function + +The `executeTransaction` function (Line 108) allows users to execute a transaction. On line 113, we require that the number of confirmations of the transaction is greater than or equal to the required number of confirmations. We then set the `executed` variable of the transaction to true. Finally, send the funds using the `call` function. This is the `call` of the recipient address with the value and data of the transaction. If the transaction is successful, we emit the `ExecuteTransaction` event. + +## getTransactionCount Function + +The `getTransactionCount` function (Line 132) allows users to retrieve the number of transactions in the multi-signature wallet. It returns the length of the `transactions` array. + +## getTransaction Function + +The `getTransaction` function (Line 136) allows users to retrieve a transaction. It returns the transaction struct members that we explored earlier in this section. + +## Conclusion + +In this section, we explored the process of submitting, confirming, and executing transactions. We examined the `submitTransaction`, `confirmTransaction`, and `executeTransaction` functions and understood how they work together to allow multiple users to submit and confirm transactions. + +## ⭐️ Assignment: Make a Transaction + +Submit, confirm, and execute a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. Deploy the Multisig contract as in the previous assignment. Make sure that the required number of confirmations is 2. +2. Fund the multisig from any address by sending 4 Ether as you did in the previous assignment. +3. Try sending 2 Ether to the first account in the "ACCOUNTS" dropdown menu. Once you have submitted this transaction (with submitTransaction), click on `getTransactionCount` and should see one transaction or you can click on `getTransaction`, insert 0 as the transaction index and see the transaction you just submitted. +4. Now you can click on `confirmTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. +5. Switch to the second owner account and confirm the transaction again. If you click on `getTransaction` again, you should see that the transaction has been confirmed twice. +6. The last step is to execute the transaction. Click on `executeTransaction` and insert 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been executed. You can also check the balance of the first account in the "ACCOUNTS" dropdown menu. It should now be 2 Ether higher and the balance of the multi-signature wallet should be 2 Ether lower. + +**Hint:** +If you submit a transaction make sure that the value is in Wei and that the _data field is correctly filled in. E.g. it could look like this: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 2000000000000000000, 0x" for 2 Ether. diff --git a/locales/tr/Multisig-Tutorial/5-multisig-revoke/revoke.md b/locales/tr/Multisig-Tutorial/5-multisig-revoke/revoke.md new file mode 100644 index 000000000..1bf085343 --- /dev/null +++ b/locales/tr/Multisig-Tutorial/5-multisig-revoke/revoke.md @@ -0,0 +1,30 @@ +In this section, we'll explore the process of revoking confirmations. This process is necessary when an owner changes their mind about a transaction and wants to stop it from being executed. This section will be pretty straightforward. + +## revokeConfirmation Event + +On line 14, we have added the `RevokeConfirmation` event. This event is emitted whenever a transaction confirmation is revoked by an owner. + +## revokeConfirmation Function + +On line 129, we have added the `revokeConfirmation` function. It allows users to revoke a transaction confirmation. + +`revokeConfirmation` takes one parameter: `txIndex`. It has three modifiers: `onlyOwner`, `txExists`, and `notExecuted`. + +On line 134, we require that the transaction has been confirmed by the caller. This ensures that an owner who has confirmed the transaction can only revoke their own confirmation. +We then decrement the `numConfirmations` variable of the transaction and set the `isConfirmed` mapping of the transaction index and the caller's address to false. Finally, we emit the `RevokeConfirmation` event. + +## Conclusion + +In this section, we explored the process of revoking confirmations. We examined the `revokeConfirmation` function and understood how it works to allow users to revoke confirmations. + +## ⭐️ Assignment: Revoke a Confirmation + +Confirm and revoke a transaction to send 2 Ether to the first account in the "ACCOUNTS" dropdown menu. + +1. As in the previous assignment, deploy the Multisig contract, send the contract some Ether, and then submit a transaction to the first account in the "ACCOUNTS" dropdown menu with a value of 2 Ether. +2. Confirm the transaction twice as in the previous assignment. +3. Revoke the transaction by clicking on `revokeConfirmation` and inserting 0 as the transaction index. If you click on `getTransaction` again, you should see that the transaction has been confirmed once. + +## Final Conclusion + +In this tutorial, we explored the process of creating a multi-signature wallet. We learned how to initialize the contract, deposit Ether, submit, confirm, and revoke transactions. We also learned how to execute transactions and retrieve information about the multi-signature wallet. diff --git a/locales/tr/Multisig-Tutorial/README.md b/locales/tr/Multisig-Tutorial/README.md new file mode 100644 index 000000000..ae5997802 --- /dev/null +++ b/locales/tr/Multisig-Tutorial/README.md @@ -0,0 +1,5 @@ +## MultiSig Wallet + +Learn how to write a MultiSig Wallet smart contract on Ethereum. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/tr/Multisig-Tutorial/config.yml b/locales/tr/Multisig-Tutorial/config.yml new file mode 100644 index 000000000..067de0fb9 --- /dev/null +++ b/locales/tr/Multisig-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: multisigCourse +name: Multisig Wallet +summary: Learn how to create and interact with a multisig wallet. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - Multisig +steps: + - + name: 1. Introduction + path: 1-multisig-introduction + - + name: 2. Initialize the Contract + path: 2-multisig-initialization + - + name: 3. Deposits + path: 3-multisig-deposits + - + name: 4. Transactions + path: 4-multisig-transactions + - + name: 5. Revoking Confirmations + path: 5-multisig-revoke diff --git a/locales/tr/NFTTokenCourse/README.md b/locales/tr/NFTTokenCourse/README.md new file mode 100644 index 000000000..c3d2a183a --- /dev/null +++ b/locales/tr/NFTTokenCourse/README.md @@ -0,0 +1,5 @@ +## Solidity NFT Course + +Learn how to create your own NFTs (non-fungible tokens). + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/tr/NFTTokenCourse/config.yml b/locales/tr/NFTTokenCourse/config.yml new file mode 100644 index 000000000..af82db834 --- /dev/null +++ b/locales/tr/NFTTokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: nftTokenCourse +name: Solidity NFT Course +summary: Learn how to create your own NFT tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc721-interface + - + name: 3. Metadata Interface + path: erc721-interface-metadata + - + name: 4. Token Creation + path: erc721-token-creation + - + name: 5. Metadata IPFS + path: erc721-metadata-ipfs + - + name: 6. Deploy to Testnet + path: erc721-deploy-testnet-opensea diff --git a/locales/tr/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md b/locales/tr/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md new file mode 100644 index 000000000..40576500c --- /dev/null +++ b/locales/tr/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md @@ -0,0 +1,50 @@ +In this section, we will use Metamask (an Ethereum wallet) to deploy our contract to the Rinkeby testnet of the Ethereum blockchain, mint an NFT, and look at it on the NFT marketplace OpenSea. + +### 1. Install Metamask + +**1.1** Go to metamask.io. + +**1.2** Click on the download button, then click on install for your browser (e.g. Chrome) and add the extension to your browser. + +**1.3** Create a wallet as described. + +### 2. Get testnet token for Rinkeby + +In order to make transactions on the testnet, we need Ethereum testnet tokens. + +**2.1** Switch your Metamask from "Ethereum Mainnetwork" to "Rinkeby Test Network". + +**2.2** Go to https://faucet.paradigm.xyz/, enter the address of your account and claim testnet ETH. +You could also use other ropsten faucets like https://faucet.paradigm.xyz/ or https://app.mycrypto.com/faucet. Have a look at the faucets listed on ethereum.org to learn more. + +### 3. Contract Deployment + +**3.1** In the "DEPLOY & RUN TRANSACTIONS" module of the Remix IDE under "ENVIRONMENT" select "Injected Web3". It should then ask you to connect your account, which you should confirm. Then you should see the Rinkeby network badge under "Injected Web3". + +**3.2** Deploy your token contract and confirm the transaction in Metamask. + +**3.3** Your contract should appear in the "Deployed Contracts" section. + +### 4. Mint an NFT + +**4.1** Expand your contract in the IDE so you can see the buttons for the functions. + +**4.2** Expand the input fields next to the safeMint button. Enter the Ethereum address of the account that is connected to Remix in the “to:” input field. Enter “0” in the input field "tokenID:". Click on transact. + +**4.3** In Metamask click on assets, then click on the “Import tokens” link, and paste the address of your contract in the input field. You can set decimals to 0. + +You should now see the name of the symbol of your token contract (e.g. GEO) in your “Assets” view in Metamask. You should have one of these tokens. + +### 5. See your NFT on OpenSea + +OpenSea is one of the most popular online marketplace for NFTs. OpenSea also provides a version where you can see assets on the testnet, under https://testnets.opensea.io/ + +**5.1** Go to https://testnets.opensea.io/login. + +**5.2** Connect with your Metamask wallet. You should be redirected to your account https://testnets.opensea.io/account view on OpenSea, where you should be able to see your NFT. You should see the image of your NFT; when you click on it, you should see the name, description, and under properties, also the attributes that you created. + +If you successfully completed this course and are familiar with the basics of Solidity development, we encourage you to continue your learning journey by learning how to create your own NFT auction contract from the Learneth resources. diff --git a/locales/tr/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md b/locales/tr/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md new file mode 100644 index 000000000..a43162feb --- /dev/null +++ b/locales/tr/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md @@ -0,0 +1,44 @@ +The metadata extension is optional. It allows us to add additional information to our ERC721 tokens. We can specify a name, a symbol, and an URI (Uniform Resource Identifier) that can point to a file where we can add even more information in the form of a JSON. + +## ERC721 Metadata Functions + +### name + +The function `name` (line 16) returns the name of the token collection. A token collection means all tokens created with your ERC721 token contract implementation. Every token in this collection will have this name, regardless of their tokenId. + +### symbol + +The function `symbol` (line 21) returns the symbol of the token collection. + +### tokenURI + +The function `tokenURI` (line 26) returns the URI for the token with the id `tokenId`. In this case it’s not the URI of the whole collection but of an individual token in the collection. + +## ERC721 Metadata JSON Schema + +The file that the tokenURI points to should conform to the Metadata JSON Schema as it is specified in the EIP-721. + +``` +{ + "title": "Asset Metadata", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Identifies the asset to which this NFT represents" + }, + "description": { + "type": "string", + "description": "Describes the asset to which this NFT represents" + }, + "image": { + "type": "string", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." + } + } +} +``` + +The root element must be of the type object. This root object should have properties with the keys: name, description, and image that should be all of the type string. + +The ERC721 standard is pretty flexible, the tokenURI does not need to point to a JSON document and the JSON does not need to have all properties and often has additional properties. diff --git a/locales/tr/NFTTokenCourse/erc721-interface/erc721Interface.md b/locales/tr/NFTTokenCourse/erc721-interface/erc721Interface.md new file mode 100644 index 000000000..468e8e640 --- /dev/null +++ b/locales/tr/NFTTokenCourse/erc721-interface/erc721Interface.md @@ -0,0 +1,100 @@ +ERC721 is a standard for token contracts that manage non-fungible tokens (NFTs) on the Ethereum blockchain. + +Each non-fungible token is unique and not interchangeable. NFTs can have different properties, behavior, or rights. Non-fungible tokens are used to represent ownership of unique digital and physical assets like art, collectibles, or real estate. + +If you want to know more about the ERC721 token standard, have a look at the specifications in its Ethereum improvement proposal. + +## Interface + +The ERC721 standard is more complex than the ERC20 standard and it features optional extensions. ERC721 compliant contracts must, at a minimum, implement the ERC721 and ERC165 interfaces, which we will look at in this section. + +This interface (line 11) is part of the open-source contract library provided by OpenZeppelin. + +## Basic IERC721 Functions + +Contracts compliant with the ERC721 standard have to implement the following functions: + +### balanceOf + +The function `balanceOf` (line 30) returns the amount of tokens owned by the account with the address `owner`. + +### ownerOf + +The function `ownerOf` (line 39) returns the address `owner` of the account that holds the token with the id `tokenId`. + +### safeTransferFrom + +The function `safeTransferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +The function `safeTransferFrom` (line 137) is almost identical to the function `safeTransferFrom` (line 55) .The only difference is that this function has a non-empty payload `data`. + +A smart contract must implement the ERC721TokenReceiver Interface if it is to receive a transfer. This will ensure that the contract can handle ERC721 token transfers and prevent the tokens from being locked in a contract that can’t. + +### transferFrom + +The function `transferFrom` (line 55) transfers the ownership of a token with the id `tokenId` from the account with the address `from` to the account with the address `to`. + +**It is recommended to use safeTransferFrom instead of transferFrom whenever possible.** +The `transferFrom` function is not secure because it doesn’t check if the smart contract that is the recipient of the transfer has implemented the ERC721TokenReceiver interface and is capable of handling ERC721 tokens. + +## Advanced IERC721 Functions + +### approve + +The function `approve` (line 94) gives the account with the address `to` the permission to manage the token with the id `tokenId` on behalf of the account calling the function. + +### getApproved + +The function `getApproved` (line 103) returns the address of the account (return var `operator`) that is approved to manage the token with the id `tokenId`. + +### setApprovalForAll + +The function `setApprovalForAll` (line 115) sets the permission (`_approved`) for the account with the specified address (input param - `operator`) to manage all tokens of the account calling the function. + +### isApprovedForAll + +The function `getApproved` (line 103) returns the boolean true if the account with the address `operator` is approved to manage all tokens of the account with the address `owner`. + +## IERC721 Events + +ERC721 contracts must also emit the following events: + +### Transfer + +The `Transfer` event (line 15) must be emitted when the token with the id `tokenId` is transferred from the account with the address `from` to the account with the address `to`. + +### Approval + +The `Approval` event (line 20) must be emitted when the account with the address `owner` approves the account with the address `spender` to manage the token with the id `tokenId` on its behalf. + +### ApprovalForAll + +The `ApprovalForAll` event (line 25) must be emitted when the account with the address `owner` gives or removes the permission (`_approved`) of the account with the address `operator` to manage all its tokens. + +## IERC165 + +In addition to the ERC721 interface, ERC721 compliant contracts must also implement the ERC165 interface. + +With the implementation of the ERC165 interface, contracts can declare the support of specific interfaces. A contract that wants to interact with another contract can then query if the other contract supports this interface before making a transaction e.g. sending tokens to it that they might not support. + +Our IERC721 interface here imports (line 6) and inherits (line 11) from the IERC165 interface. + +This is how OpenZeppelins implementation of the ERC165 interface looks like: + +``` +interface IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +For example, the ERC165 identifier for the ERC721 interface as specified in the EIP721 is “0x80ac58cd”. Learn how to calculate an interface identifier and more about the ERC165 in its improvement proposal. + +## Other interfaces + +The IERC721TokenReceiver interface must be implemented to accept safe transfers. + +There are two optional extensions for ERC721 contracts specified in the EIP721: + +IERC721Enumerable enables a contract to publish its full list of tokens and make them discoverable. + +IERC721Metadata enables a contract to associate additional information to a token. We will have a more detailed look into this in the next section. diff --git a/locales/tr/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md b/locales/tr/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md new file mode 100644 index 000000000..27876b068 --- /dev/null +++ b/locales/tr/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md @@ -0,0 +1,101 @@ +In this section, we will create our metadata and store it in a decentralized way. + +IPFS ( InterPlanetary File System) is a peer-to-peer network for storing files in a distributed way. Pinata.cloud is a pinning service that allows users to easily host files on the IPFS network. + +We want to host our images and the JSON files with their metadata on IPFS. + +### Create Image Folder + +In this example, we will create metadata for three tokens. As you can see below, we create three images that we stored in a folder. + +``` +geo-img +├── geo_1.png +├── geo_2.png +├── geo_3.png +``` + +### Register on Pinata + +Now, we want to host these images somewhere so we can point to them in the metadata of our tokens. Let's do it in a decentralized way and use Pinata to host them on IPFS. + +First you need an account on Pinata. Go to Pinata.cloud and create an account. On Pinata you can upload up to 1 GB of data for free. + +Once you have signed up, you should be in the Pin Manager view. + +Pin Manager Pinata + +### Upload Images to IPFS + +Click on the upload button and upload the folder with your images. +Once you've uploaded your folder, you should see the name of your folder and the CID (content identifier) associated with it. If the content in the folder changes, the CID will also change. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P + +You can access a specific image by using: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png + +### Create JSON files + +We create another folder where we store three JSON files. + +``` +geo-json +├── 0 +├── 1 +├── 2 +``` + +Inside the JSON files, create the metadata for the tokens, like name, description, and image. +For the image URL, we are going to use the URL of our images on IPFS. You can add additional data if you like; in this example, we added some unique attributes for each token. + +This is how the JSON for the first token could look: + +``` +{ + "name": "Geometry#0", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png +", + "attributes": [ + { "trait_type": "background", "value": "cyan" }, + { "trait_type": "color", "value": "red" }, + { "trait_type": "shape", "value": "circle" } + ] +} +``` + +This is how the JSON for the second token could look: + +``` +{ + "name": "Geometry#1", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_2.png", + "attributes": [ + { "trait_type": "background", "value": "magenta" }, + { "trait_type": "color", "value": "green" }, + { "trait_type": "shape", "value": "square" } + ] +} +``` + +As shown above, the folder in this example is called "geo-json". Inside this folder, we have three JSON files. +The first JSON file is called "0", the second JSON file is called "1", and the third JSON file is called "2". + +Make sure that your JSON files don't have a file ending and are named like their corresponding tokenIds. +In the pin manager on pinata.cloud, click on the upload button and upload the folder with your JSON files. + +To access your folder on IPFS, enter this address "https://ipfs.io/ipfs/" and add your CID. +For our current example, you can access your folder by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp +This will become our baseURI. + +You can access a specific JSON file then by just adding a slash and the tokenId by using: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/0 + +In the contract, replace the baseURI with your own baseURI. In this example, the baseURI consists of the URL +"https://ipfs.io/ipfs/", the CID containing the JSON files, and a slash at the end "/". + +An individual tokenURI will now be created for each token by adding the tokenId to the baseURI — exactly what we did manually in the example above to access the JSON file. diff --git a/locales/tr/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md b/locales/tr/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md new file mode 100644 index 000000000..891fe00a7 --- /dev/null +++ b/locales/tr/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md @@ -0,0 +1,35 @@ +In this contract, we use an ERC721 token contract implementation from OpenZeppelin (line 4). + +Have a look at their implementation of a ERC721 contract. Apart from the functionality specified in the ERC721 standard, the contract provides additional functions which we will see in a bit. + +## myToken + +We create our own contract called MyToken (line 7), which inherits (line 7) the functionality from the OpenZepplin `ERC721` token contract implementation and `Ownable` that we imported (line 4). If you don't remember the Ownable contract module, have a look at the ERC20 extensions section. + +This ERC721 implementation makes use of the IERC721Metadata extension that is specified in the EIP. Our contract inherits the functions `name()` and `symbol()` +and has a constructor that allows their values to be set during the deployment of the contract (line 8). +In this case, we are going to use the default values. We name our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +### Base URI + +With an ERC721 contract, we are able to mint various tokens, each with its own tokenId. As we saw in the IERC721Metadata interface, each token can have its own `tokenURI`, which typically points to a JSON file to store metadata like name, description, and image link. +If a contract mints multiple tokens, ERC721 implementations often use the same URI as a base (`baseURI`) for all tokens and only differentiate them by adding their unique `tokenId` at the end via concatenation. In the next part, we will see what this looks like in practice. + +In this example, we are storing our data on IPFS — more on that in the next section. Our baseURI is https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/ (line 11). +Through concatenation the tokenURI for the token with the id 0 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/0 , the tokenURI for the token with the id 1 would be https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/1, and so on. + +When using IPFS and you run into "504 Gateway Time-out" errors, you might have to wait and retry until the data is available. + +### safeMint + +With the safeMint function (line 14) we enable the owner to create new tokens with a dedicated token id after contract deployment. +The safeMint function is part of the ERC721 implementation of OpenZeppelin and lets us safely mint a token with the id `tokenId` to the account with the address `to`. For access control, we use the `onlyOwner` modifier from the Ownable access control contract module that we imported (line 5). + +In the next section, we will see how we can create and host the metadata for our NFTs. + +## ⭐️ Assignment + +1. Rename your contract to `Geometry`. +2. Rename your token to `Geometry`. +3. Change the symbol of your token to `GEO`. +4. Change the `_baseURI` to https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/. diff --git a/locales/tr/NFTTokenCourse/introduction/introduction.md b/locales/tr/NFTTokenCourse/introduction/introduction.md new file mode 100644 index 000000000..13beea567 --- /dev/null +++ b/locales/tr/NFTTokenCourse/introduction/introduction.md @@ -0,0 +1,64 @@ +In this section of the course, we will give you a theoretical introduction to blockchain-based tokens. + +Blockchain tokens are a new technological building block created by blockchain technology (like websites were for the internet) that enables a decentralized, ownable internet (web3). + +### Introduction + +In the context of web3, tokens represent ownership. Tokens can represent ownership of anything: art, reputation, items in a video game, shares in a company, voting rights, or currencies. + +The revolutionary innovation of blockchain technology is that it allows data to be stored publicly in an immutable (unchangeable) way. +This new form of data storage allows us to keep track of ownership and enable truly ownable digital items for the first time. + +Blockchain Technology was originally invented to keep track of the ownership of Bitcoin, a decentralized digital currency and fungible token. + +### Fungible and non-fungible tokens + +Assets like money: Bitcoin or a one-dollar bill, for example, are fungible. Fungible means that all assets are the same and are interchangeable. Assets like art, collectibles, or houses are non-fungible; they are all different and not interchangeable. + +We can divide tokens into these two types: fungible tokens, where all tokens are the same, and non-fungible tokens (NFTs), where every token is unique. + +### Token standard + +The behavior of a token is specified in its smart contract (token contract). The contract could, for example, include the functionality to transfer a token or check for its total supply. + +If everybody would create their own token contracts with different behavior and naming conventions, it would make it very hard for people to build contracts or applications that are able to interact with each other. + +The Ethereum community has developed token standards that define how a developer can create tokens that are interoperable (able to work with others) with other contracts, products, and services. Contracts developed under these standards need to include a certain set of functions and events. + +The most popular token standards are the ERC20 for fungible tokens and the ERC721 for non-fungible tokens. In this course, we will learn how to create and interact with NFTs, tokens created with the ERC721 token standard. + +If you want to learn more about fungible tokens and the ERC20 token standard, have a look at the Learneth ERC20 Token Course. + +The ERC777 is a fungible token standard, like the ERC20, that includes more advanced features like hooks while remaining backward compatible with ERC20. Learn more about the ERC777 in its EIP (Ethereum improvement proposal). + +The ERC1155 is a multi-token standard that allows a single contract to manage different types of tokens, such as fungible, non-fungible, or semi-fungible tokens. +Learn more about the ERC1155 in its EIP. + +## ⭐️ Assignment + +For this assignment, we will test your knowledge via a short quiz. +Assign the number of the best answer to the variables `question1` (line 5), +`question2` (line 6), `question3` (line 7) in the `Quiz` contract (line 4). + +### Question 1: + +Why are blockchain-based tokens so revolutionary? + +1. Because people can now make investments anonymously. +2. Because they represent ownership in digital assets that can be owned and transferred. +3. Because you can use tokens to make transactions without having to pay taxes. + +### Question 2: + +Why did the community create token standards? + +1. So that the community can control and approve the tokens that are created. +2. In order to restrict the functionality of tokens to safe and non-malicious actions. +3. So that the community can create tokens that are interoperable with other contracts, products, and services. + +### Question 3: + +If you would create a decentralised application for a baseball trading card game where each baseball player would be represented by a token, what token standard would you use to write the token contract? + +1. ERC20 +2. ERC721 diff --git a/locales/tr/OpcodesInTheDebugger/1_intro/step.md b/locales/tr/OpcodesInTheDebugger/1_intro/step.md new file mode 100644 index 000000000..c1d9a2448 --- /dev/null +++ b/locales/tr/OpcodesInTheDebugger/1_intro/step.md @@ -0,0 +1,5 @@ +This workshop aims to give a better understanding about how a contract get deployed. +`SimpleStore` is a very basic contract. +It has a very simple constructor - which just uses the first parameter `_o` and saves it to `s`. + +Using the debugger, we'll try to see, what the opcode `CODECOPY` does. diff --git a/locales/tr/OpcodesInTheDebugger/2_memory/step.md b/locales/tr/OpcodesInTheDebugger/2_memory/step.md new file mode 100644 index 000000000..577169a5e --- /dev/null +++ b/locales/tr/OpcodesInTheDebugger/2_memory/step.md @@ -0,0 +1,8 @@ +Before we start, just quick reminder: + +The runtime of the EVM has several kinds of memory: + +- `calldata`: This is the input value given to the transaction. +- `stack`: Basically, this is a list of values, each value is limited in size (32 bytes). +- `memory`: Memory is used when the **type** of value getting stored is more complex like an array or a mapping. This memory is **temporary** and is **released** at the end of the execution. +- `storage`: This is a mapping, each value stored is **persisted** and saved on chain. diff --git a/locales/tr/OpcodesInTheDebugger/3_codecopy/step.md b/locales/tr/OpcodesInTheDebugger/3_codecopy/step.md new file mode 100644 index 000000000..b0c9f7d52 --- /dev/null +++ b/locales/tr/OpcodesInTheDebugger/3_codecopy/step.md @@ -0,0 +1,7 @@ +CODECOPY is one of the many opcodes run by the EVM. Check out the complete list of opcodes at https://ethervm.io/ . + +CODECOPY takes the **running code** (or part of it) and to copies it from the `calldata` to the `memory`. + +The solidity implementation is: **codecopy(t, f, s)** - copy **s** bytes from code at position **f** to memory at position **t**. + +Every contract deployment uses **CODECOPY**. diff --git a/locales/tr/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md b/locales/tr/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md new file mode 100644 index 000000000..63950051d --- /dev/null +++ b/locales/tr/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md @@ -0,0 +1,11 @@ +Let's go back to our contract. +Please make sure the `solidity compiler` and `Deploy & Run Transactions` are activated. + +Alternatively, you can click on `Solidity` from the `Home Page` **Environments** section. + +- Compile the contract from the `solidity compiler`. +- Go to the `Deploy & Run Transactions` and make sure `SimpleStore` is selected contract. +- In the textbox to the right of `Deploy`, input a positive integer. +- Click on `Deploy`. + +In the next step, we'll watch the deployment in the debugger. diff --git a/locales/tr/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md b/locales/tr/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md new file mode 100644 index 000000000..3ef3cd146 --- /dev/null +++ b/locales/tr/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md @@ -0,0 +1,7 @@ +From the Remix terminal, identify the transaction that deployed the contract and click `Debug` + +In the gutter of the editor, put a breakpoint on the line `s = _o`, and click on `Jump to the next Breakpoint` (bottom right button). + +Click on `Step into`, to move along the opcodes until you reach `SSTORE`. + +`SSTORE` is the opcode for storing the value `_o` in the storage. Let's continue further to the `CODECOPY`. diff --git a/locales/tr/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md b/locales/tr/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md new file mode 100644 index 000000000..1480728e6 --- /dev/null +++ b/locales/tr/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md @@ -0,0 +1,57 @@ +The goal here is to store the code in the blockchain. The EVM needs to tell the client (geth, parity) which what part of the **Call Data** to store. In this step, we are saving the contract MINUS its constructor (because that gets inplmented only 1 time) and MINUS the input parameter does not need to be stored. + +`CODECOPY` is the first step: it copies the bytecode to memory, then the ethereum client will be able to consume it. MUNCH! + +But wait... before the client can **MUNCH** bytecode, it needs an instruction - an opcode to tell it to MUNCH. `RETURN` is this opcode! + +As stated in the general spec, at the end of the contract creation, the client (geth, parity) takes the targeted value by the opcode `RETURN` and **persists** it by making it part of the deployed bytecode. + +Once you are in the `CODECOPY`, look at the top 3 items in the **Stack**: + +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x0000000000000000000000000000000000000000000000000000000000000055` +`2: 0x000000000000000000000000000000000000000000000000000000000000003e` + +_In your Stack - `1` & `2` may be slightly different. The difference may be due to a different compiler version._ + +**These are the parameters for `CODECOPY`.** + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +`0` is the offset where the copied code should be placed in the **memory**. In this example, ( all zeros) the code is copied to the beginning of the memory. (**t**) +`1` is the offset in **calldata** where to copy from (**f**) +`2` number of bytes to copy - (**s**) + +After `CODECOPY` is executed, (click the _step into_ button) the copied code should be: +`0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c63430005110032` in memory. **I'll refer to this value as (X)**. + +Let's look at the debugger's **Memory** panel. +The 0x number I gave above is not what you will see in the **Memory** panel -what you will see is this: +0x0: 6080604052600080fdfea265627a7a72 ????R??????ebzzr +0x10: 31582029bb0975555a15a155e2cf28e0 1X ?? uUZ??U???? +0x20: 25c8d492f0613bfb5cbf96399f6dbd4e ?????a?????9?m?N +0x30: a6fc9164736f6c634300051100320000 ???dsolcC????2?? +0x40: 00000000000000000000000000000000 ???????????????? +0x50: 000000000000000000000000000000a0 ??????????????? +0x60: 00000000000000000000000000000000 ???????????????? +0x70: 00000000000000000000000000000000 ???????????????? +0x80: 00000000000000000000000000000000 ???????????????? +0x90: 00000000000000000000000000000002 ???????????????? + +The `0x0`, `0x10`, etc is the position. The next number is the bytecode for that position. This is followed by question marks and seemingly random letters & numbers. This is **Remix**'s attempt to convert this into a string. + +So if we glue the first four sections of bytecode together, we'll get: +**0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e0a6fc9164736f6c63430005110032** The last section - `0x90` has 2 which is what I input for the constructors parameter. + +The input data from the **Call Data** panel is: +`0x6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c634300051100320000000000000000000000000000000000000000000000000000000000000002` +**I'll refer to this value as (Y).** + +This shows us that `(X)` is a subset of the original calldata `(Y)`: + +`(X)` is calldata without the input parameter `0000000000000000000000000000000000000000000000000000000000000002` (we don't need to store this) +and without the constructor code `6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe` which should be executed only 1 time. + +So `CODECOPY` extracts the bytecode from the calldata and copies it to the memory. + +Let's move to the next step. diff --git a/locales/tr/OpcodesInTheDebugger/7_returnAndStore/step.md b/locales/tr/OpcodesInTheDebugger/7_returnAndStore/step.md new file mode 100644 index 000000000..b375a24fb --- /dev/null +++ b/locales/tr/OpcodesInTheDebugger/7_returnAndStore/step.md @@ -0,0 +1,18 @@ +# The Opcode RETURN + +At the end of the last chapter we had moved to one step after **CODECOPY** to see what happened in the memory. + +Now that CODECOPY has been executed, we are on the opcode `PUSH1 00`. + +`PUSH1 00` prepares the stack for the `RETURN` opcode. +`RETURN` is the last part of this process. It is where the code is returned to the client. + +We push `00` to the stack because this is the offset position of the contract bytecode in memory. + +Now we can call the all important `RETURN` opcode. + +The **stack inspector** shows: +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x000000000000000000000000000000000000000000000000000000000000003e` + +Which is to say it returns to the client the bytecode starting `0x00` with length `0x3e`. diff --git a/locales/tr/OpcodesInTheDebugger/8_findTheOffset/step.md b/locales/tr/OpcodesInTheDebugger/8_findTheOffset/step.md new file mode 100644 index 000000000..6b1ddc5cf --- /dev/null +++ b/locales/tr/OpcodesInTheDebugger/8_findTheOffset/step.md @@ -0,0 +1,18 @@ +# Find the offset ;) + +And now for a slightly different example: + +- Compile notSimpleStore.sol +- Deploy the contract `notSoSimpleStore` +- Make sure you have a successful deployment - if not check that you used **the correct input type** in the constructor. +- Go to the Debugger by clicking the **debug** button at the (successful) creation transaction. +- Find the value of the parameter of `CODECOPY` which represents the offset in calldata where to copy from. + +Remember: _codecopy(t, f, s)_ - copy **s** bytes from code at position **f** to memory at position **t** + +If you look in the **Stack**, you should see that the 2nd element is: +0x0000000000000000000000000000000000000000000000000000000000000083 + +And this is the **f** of the input params of codecopy. + +### Hope you picked up a thing or 2 about how opcodes work! diff --git a/locales/tr/OpcodesInTheDebugger/config.yml b/locales/tr/OpcodesInTheDebugger/config.yml new file mode 100644 index 000000000..74a1bf3a1 --- /dev/null +++ b/locales/tr/OpcodesInTheDebugger/config.yml @@ -0,0 +1,10 @@ +--- +id: opcodesdebug +name: Opcodes in the Debugger +summary: Using the Debugger, we'll check out what the CODECOPY opcode does and how it is used by the EVM during contract creation. +level: 3 +tags: + - Remix + - Debugging + - EVM + - Opcodes diff --git a/locales/tr/ProxyContract/1_Why/step1.md b/locales/tr/ProxyContract/1_Why/step1.md new file mode 100644 index 000000000..b4a38aaeb --- /dev/null +++ b/locales/tr/ProxyContract/1_Why/step1.md @@ -0,0 +1,27 @@ +# Proxy Contract AKA the Dispatcher + +## Why? + +This is a great pattern that is used mainly in **library development**. + +It helps in the following ways: + +- **Save gas cost at deployment time** + The purpose of a high gas cost is to discourage the operations that cost a lot for their execution and to encourage optimized code. + +- Proxy contracts are useful when a lot of instances of the same contract need to be deployed because they reduce the duplications in the deployment. + +- **Avoid code repetition in the blockchain.** + Heavy computations are expensive because every node will need to perform them, this is of course slowing the network. + +- **Develop upgradable(versioned) contracts** + When the contract is deployed, it’s immutable. By re-designing the code into different contracts, it is possible to allow logic upgrades while keeping the storage the same. + +## Example of gas cost + +Storing contract code at creation time can cost up to: + +- 200 \* max_byte_code_length gas +- 200 \* 24576 = 49152004915200 \* 10 gwei = 49152000 gwei = 0.049152 ether = 9 EUR + +see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md for more info on max_byte_code_length. diff --git a/locales/tr/ProxyContract/2_How/step2.md b/locales/tr/ProxyContract/2_How/step2.md new file mode 100644 index 000000000..d80b6557c --- /dev/null +++ b/locales/tr/ProxyContract/2_How/step2.md @@ -0,0 +1,13 @@ +# How it works? + +**EIP-7 DelegateCall** opcode allows a separate execution in another contract while maintaining the original execution context. + +All **message calls** from the user go through a **Proxy contract**. + +The **Proxy contract** then will redirect them to the **Logic contract**. + +And when you need to **upgrade** the logic, you'll **just** deploy that - **HOWEVER** - the implementation of Proxy will remain the same. + +You'll only need to update the address of Logic contract in Proxy. + +The Proxy Contract uses **Delegate calls** and **Solidity assembly** because without it, it's impossible to return any value from **delegatecall**. diff --git a/locales/tr/ProxyContract/3_Delegatecall/step3.md b/locales/tr/ProxyContract/3_Delegatecall/step3.md new file mode 100644 index 000000000..8693e5567 --- /dev/null +++ b/locales/tr/ProxyContract/3_Delegatecall/step3.md @@ -0,0 +1,9 @@ +# Delegate call + +It's a special variant of a **message call**, which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract so **msg.sender** and **msg.value** do not change their values. + +This means that a contract can dynamically load code from a different address at runtime. + +The storage, the current address and balance still refer to the calling contract, only the code is taken from the called address. + +So when a **Proxy** delegates calls to the Logic contract, every storage modification will impact the storage of Logic contract. diff --git a/locales/tr/ProxyContract/4_Generic_proxy_example/step4.md b/locales/tr/ProxyContract/4_Generic_proxy_example/step4.md new file mode 100644 index 000000000..d20fdd16d --- /dev/null +++ b/locales/tr/ProxyContract/4_Generic_proxy_example/step4.md @@ -0,0 +1,15 @@ +# A Basic Generic Proxy Example + +In the associated solidity file, **step4.sol**, there are 2 contracts - **ProxyContract** and **LogicContract**. + +To use this system, we first deploy the LogicContract. + +And then when we go to deploy the ProxyContract, we pass the LogicContract's address as an argument of the ProxyContract's constructor. + +The ProxyContract is deployed only once. + +The code of LogicContract will be called at the line 20. It will be forwarded with delegate call while keeping the context of LogicContract. + +In case we need to change the logic we would deploy a new LogicContract and set the address of it with setLogicContractAddress setter function. + +_Note: The LogicContract we have here does not use the storage. Once you need to use the storage the implementation becomes a bit more complicated because those contracts share the context._ diff --git a/locales/tr/ProxyContract/5_Test/step5.md b/locales/tr/ProxyContract/5_Test/step5.md new file mode 100644 index 000000000..120a15e13 --- /dev/null +++ b/locales/tr/ProxyContract/5_Test/step5.md @@ -0,0 +1,6 @@ +# Let's test what we've learned + +- Write a contract named "LogicContract" which implements a public function named "getNumber" which returns 10 +- Write a proxy contract named "ProxyContract". This ProxyContract should take an address of LogicContract as a first parameter. + +Good Luck! diff --git a/locales/tr/ProxyContract/6_Storage_Problem/step6.md b/locales/tr/ProxyContract/6_Storage_Problem/step6.md new file mode 100644 index 000000000..d2b804284 --- /dev/null +++ b/locales/tr/ProxyContract/6_Storage_Problem/step6.md @@ -0,0 +1,13 @@ +# What if we have state variables? + +Things are more complicated once we need to deal with state variables. State variable are saved to **storage**. + +`storage`: is a mapping; each value stored there is persisted and saved on chain. + +_Note: Statically-sized state variables (everything except mapping and dynamically-sized array types) are laid out contiguously in storage starting from position 0. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible. For contracts that use inheritance, the ordering of state variables is determined by the C3-linearized order of contracts starting with the most base-ward contract_ + +Once we execute **delegate call**, the storage of both contracts get **"merged"** into a single messy state. + +We have to "tell" ProxyContract what the **state** of the **Logic contract** looks like. + +The easiest way to do this is to create a separate contract - in this example - named **StorageContract** which will represent the **state** and which proxyContract will inherit from. diff --git a/locales/tr/ProxyContract/7_links/step7.md b/locales/tr/ProxyContract/7_links/step7.md new file mode 100644 index 000000000..c2784c3cc --- /dev/null +++ b/locales/tr/ProxyContract/7_links/step7.md @@ -0,0 +1,19 @@ +# Check out some links for more info + +- ERC DelegateProxy + https://github.com/ethereum/EIPs/pull/897 + +- The joint post by Zeppelin Solutions and Aragon. + https://blog.openzeppelin.com/proxy-libraries-in-solidity-79fbe4b970fd/ + +- Proxy Patterns by OpenZeppelin + https://blog.openzeppelin.com/proxy-patterns/ + +- The most mature implementation of Proxy pattern is The Unstructure Storage pattern that is released as part of ZeppelinOS + https://blog.openzeppelin.com/upgradeability-using-unstructured-storage/ + +- Great blog post by Jack Tanner + https://blog.indorse.io/ethereum-upgradeable-smart-contract-strategies-456350d0557c + +- Upgradeable Ethereum Smart Contracts + https://medium.com/@daonomic/upgradeable-ethereum-smart-contracts-d036cb373d6 diff --git a/locales/tr/ProxyContract/README.md b/locales/tr/ProxyContract/README.md new file mode 100644 index 000000000..6a5364c94 --- /dev/null +++ b/locales/tr/ProxyContract/README.md @@ -0,0 +1,3 @@ +## Learn the Proxy Pattern + +Save gas & make upgradable contracts diff --git a/locales/tr/ProxyContract/config.yml b/locales/tr/ProxyContract/config.yml new file mode 100644 index 000000000..e36e640b8 --- /dev/null +++ b/locales/tr/ProxyContract/config.yml @@ -0,0 +1,9 @@ +--- +id: proxycontract +name: All about Proxy Contracts +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 3 +tags: + - Remix + - Solidity + - Code Patterns diff --git a/locales/tr/README.md b/locales/tr/README.md new file mode 100644 index 000000000..cb799bd20 --- /dev/null +++ b/locales/tr/README.md @@ -0,0 +1,36 @@ +# This is a repo of tutorials for the Remix's LearnEth Plugin + +### To use these tutorials: + +**1. Open Remix** + +https://remix.ethereum.org + +**2. In the plugin manager activate LEARNETH** + +**3. Go to the Learneth plugin and these tutorials will load by default** + +**4. You may need to sign into Github especially during an in-person workshop** + +Github will block too many requests from the same location, unless you are signed into Github and have input your token. Generally, this is only an issue during in person workshops, when there can be many requests from the same location. + +To input your Github token: + +``` +- In one browser window - go to https://remix.ethereum.org and go to the settings tab +- In another browser window go to: + +https://github.com/settings/tokens + +and create a new token and save it in Remix in the you just opened on the settings tab. +``` + +--- + +### Write your own tutorials for LEARNETH: + +See this site for instructions: + +https://remix-learneth-plugin.readthedocs.io/en/latest/index.html#creating-tutorials + +--- diff --git a/locales/tr/Recorder/1_Usecases/1_usecases.md b/locales/tr/Recorder/1_Usecases/1_usecases.md new file mode 100644 index 000000000..0c624393c --- /dev/null +++ b/locales/tr/Recorder/1_Usecases/1_usecases.md @@ -0,0 +1,7 @@ +1. You want to show someone what happens when you do a number of transactions with a contract and you don't want to explain each step - you just want to get them to the last step. + + - To show someone a problem in their code. + + - In a class, to get the students to a certain place and have them start working from there. + +2. You want to start your development in the JavascriptVM because it is quick and then to switch to another testnet - but you don't want to manually repeat all the tedious clicking for each different network. diff --git a/locales/tr/Recorder/2_Record/README.md b/locales/tr/Recorder/2_Record/README.md new file mode 100644 index 000000000..41d214277 --- /dev/null +++ b/locales/tr/Recorder/2_Record/README.md @@ -0,0 +1,32 @@ +# Setting up a tedious series of steps + +## Following this could get tedious but that's the point. + +We are going to: + +- Deploy a voting contract where there are 3 proposals input in the constructor. +- Give voting privileges to 2 additional address (so we have a total of 3 voting addresses). +- Have one address vote for proposal 1 (0-based index) and the other two vote for proposal 2. + +1. Take the 3_Ballot.sol from the sample solidity files and compile it. Then go to the **Deploy & Run** Module. + +2. Select the **JavaScript VM** Environment. + +3. In the constructor's parameter - put in **["0x5031000000000000000000000000000000000000000000000000000000000000", "0x5032000000000000000000000000000000000000000000000000000000000000", "0x5033000000000000000000000000000000000000000000000000000000000000"]** Then click the **Deploy** button. + +4. Open up the deployed contract. + +5. In the **vote** function put in 2. This means that you as the msg.sender & chairperson are voting for proposal at position 2, which is the last proposal in our list. + +6. Now you need to give other addresses the right to vote. Select another address in the **account** pulldown and copy it and then **go back to the 1st address**. Paste the copy address into the textbox next to the giveRightToVote function. And again, select another address and copy it and **then go back to the 1st address** again and paste it into giveRightToVote. + +7. Now you have 3 addresses with the right to vote. + +8. Switch to one of the addresses that you gave the right to vote and vote for proposal **1**. (Put **1** in the textbox next to the vote function). And then switch to the other address and vote for proposal **2** with that one. + +9. Open up the **Transactions recorded** section of the module - by clicking on the caret. Click the hard disk icon in the **Transactions recorded** section to save your steps. + ![recorder](https://github.com/ethereum/remix-workshops/blob/master/Recorder/2_Record/images/recorder.png?raw=true "recorder") + +10. You will get a modal window that tells you it wants to save a file called **scenario.json**. Click OK. + +11. Click on the function **winningProposal** to confirm that the final proposal won - which is the proposal at position 2 in the array. **0: uint256: winningProposal_ 2** diff --git a/locales/tr/Recorder/3_Editing_a_Senario/README.md b/locales/tr/Recorder/3_Editing_a_Senario/README.md new file mode 100644 index 000000000..d23dfb95c --- /dev/null +++ b/locales/tr/Recorder/3_Editing_a_Senario/README.md @@ -0,0 +1,54 @@ +# Editing a scenario + +Here's the first few lines of the scenario that I recorded. The addresses on my machine will be different from your's. + +``` +{ + "accounts": { + "account{0}": "0xca35b7d915458ef540ade6068dfe2f44e8fa733c", + "account{4}": "0xdd870fa1b7c4700f2bd7f44238821c26f7392148", + "account{3}": "0x583031d1113ad414f02576bd6afabfb302140225" + } +``` + +So if you wanted to play this scenario in another testnet, you'd need to change these addresses to address that you have test ETH on so that you could pay for the transactions. But other than swapping out the addresses, you can quickly run this on other nets. + +And you might change the parameters for the functions. + +For example here is a bit of the scenario.json a bit further down where proposal 2 was voted for by one of the addresses: + +``` +{ + "timestamp": 1566428184043, + "record": { + "value": "0", + "parameters": [ + "2" + ], + "to": "created{1566428035436}", + "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", + "name": "vote", + "inputs": "(uint8)", + "type": "function", + "from": "account{4}" + } + }, +``` + +Let's edit this so that another proposal wins in the playback. + +Change the **parameters** array which now is: + +``` +"parameters": [ + "2" + ] +``` + +to: + +``` +"parameters": [ + "1" + ] +``` diff --git a/locales/tr/Recorder/4_Play/README.md b/locales/tr/Recorder/4_Play/README.md new file mode 100644 index 000000000..196664550 --- /dev/null +++ b/locales/tr/Recorder/4_Play/README.md @@ -0,0 +1,8 @@ +# Playing a scenario + +1. Click the play icon to the right of the floppy disk icon to play the steps you did. + +2. You'll see another instance of the contract deployed. Open it up. + +3. Click the winningProposal function and you should see now that proposal 1 won. + It should print out: **0: uint256: winningProposal_ 1** diff --git a/locales/tr/Recorder/README.md b/locales/tr/Recorder/README.md new file mode 100644 index 000000000..94d928383 --- /dev/null +++ b/locales/tr/Recorder/README.md @@ -0,0 +1,3 @@ +## Get yourself Remixing! + +The recorder is used for recording a set of transactions in the Deploy & Run module, editing their parameters and then playing them back in another context. It really is the remix of Remix! diff --git a/locales/tr/Recorder/config.yml b/locales/tr/Recorder/config.yml new file mode 100644 index 000000000..b8980e042 --- /dev/null +++ b/locales/tr/Recorder/config.yml @@ -0,0 +1,7 @@ +--- +id: recorder +name: Recorder +summary: Save a set of actions and replay and replay and replay +level: 2 +tags: + - Remix diff --git a/locales/tr/SolidityBeginnerCourse/README.md b/locales/tr/SolidityBeginnerCourse/README.md new file mode 100644 index 000000000..ae0b6d882 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/README.md @@ -0,0 +1,5 @@ +## Interactive Solidity Course + +Learn the most important Solidity beginner concepts interactively, based on the popular https://solidity-by-example.org/ contracts. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/tr/SolidityBeginnerCourse/basic-syntax/basicSyntax.md b/locales/tr/SolidityBeginnerCourse/basic-syntax/basicSyntax.md new file mode 100644 index 000000000..e9f77871e --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/basic-syntax/basicSyntax.md @@ -0,0 +1,26 @@ +In this section, we will create our first _smart contract_. This contract only consists of a string that holds the value "Hello World!". + +In the first line, we should specify the license that we want to use. You can find a comprehensive list of licenses here: https://spdx.org/licenses/. + +Using the `pragma` keyword (line 3), we specify the Solidity version we want the compiler to use. In this case, it should be greater than or equal to `0.8.3` but less than 0.9.0. + +We define a contract with the keyword `contract` and give it a name, in this case, `HelloWorld` (line 5). + +Inside our contract, we define a _state variable_ `greet` that holds the string `"Hello World!"` (line 6). + +Solidity is a _statically typed_ language, which means that you need to specify the type of the variable when you declare it. In this case, `greet` is a `string`. + +We also define the _visibility_ of the variable, which specifies from where you can access it. In this case, it's a `public` variable that you can access from inside and outside the contract. + +Don't worry if you didn't understand some concepts like _visibility_, _data types_, or _state variables_. We will look into them in the following sections. + +To help you understand the code, we will link in all following sections to video tutorials from the creator of the Solidity by Example contracts. + +Watch a video tutorial on Basic Syntax. + +## ⭐️ Assignment + +1. Delete the HelloWorld contract and its content. +2. Create a new contract named "MyContract". +3. The contract should have a public state variable called "name" of the type string. +4. Assign the value "Alice" to your new variable. diff --git a/locales/tr/SolidityBeginnerCourse/config.yml b/locales/tr/SolidityBeginnerCourse/config.yml new file mode 100644 index 000000000..a729093d8 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/config.yml @@ -0,0 +1,65 @@ +--- +id: soliditybeginner +name: Solidity Beginner Course +summary: Solidity Beginner Course based on the popular https://solidity-by-example.org/ contracts. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Basic Syntax + path: basic-syntax + - + name: 3. Primitive Data Types + path: primitive-data-types + - + name: 4. Variables + path: variables + - + name: 5.1 Functions - Reading and Writing to a State Variable + path: functions-reading-and-writing + - + name: 5.2 Functions - View and Pure + path: functions-view-and-pure + - + name: 5.3 Functions - Modifiers and Constructors + path: functions-modifiers-and-constructors + - + name: 5.4 Functions - Inputs and Outputs + path: functions-inputs-and-outputs + - + name: 6. Visibility + path: visibility + - + name: 7.1 Control Flow - If/Else + path: control-flow-if-else + - + name: 7.2 Control Flow - Loops + path: control-flow-loops + - + name: 8.1 Data Structures - Arrays + path: data-structures-arrays + - + name: 8.2 Data Structures - Mappings + path: data-structures-mappings + - + name: 8.3 Data Structures - Structs + path: data-structures-structs + - + name: 8.4 Data Structures - Enums + path: data-structures-enums + - + name: 9. Data Locations + path: data-locations + - + name: 10.1 Transactions - Ether and Wei + path: transactions-ether-and-wei + - + name: 10.2 Transactions - Gas and Gas Price + path: transactions-gas-and-gas-price + - + name: 10.3 Transactions - Sending Ether + path: transactions-sending-ether diff --git a/locales/tr/SolidityBeginnerCourse/control-flow-if-else/ifElse.md b/locales/tr/SolidityBeginnerCourse/control-flow-if-else/ifElse.md new file mode 100644 index 000000000..634e27689 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/control-flow-if-else/ifElse.md @@ -0,0 +1,33 @@ +Solidity supports different control flow statements that determine which parts of the contract will be executed. The conditional _If/Else statement_ enables contracts to make decisions depending on whether boolean conditions are either `true` or `false`. + +Solidity differentiates between three different If/Else statements: `if`, `else`, and `else if`. + +### if + +The `if` statement is the most basic statement that allows the contract to perform an action based on a boolean expression. + +In this contract’s `foo` function (line 5) the if statement (line 6) checks if `x` is smaller than `10`. If the statement is true, the function returns `0`. + +### else + +The `else` statement enables our contract to perform an action if conditions are not met. + +In this contract, the `foo` function uses the `else` statement (line 10) to return `2` if none of the other conditions are met. + +### else if + +With the `else if` statement we can combine several conditions. + +If the first condition (line 6) of the foo function is not met, but the condition of the `else if` statement (line 8) becomes true, the function returns `1`. + +Watch a video tutorial on the If/Else statement. + +## ⭐️ Assignment + +Create a new function called `evenCheck` in the `IfElse` contract: + +- That takes in a `uint` as an argument. +- The function returns `true` if the argument is even, and `false` if the argument is odd. +- Use a ternery operator to return the result of the `evenCheck` function. + +Tip: The modulo (%) operator produces the remainder of an integer division. diff --git a/locales/tr/SolidityBeginnerCourse/control-flow-loops/loops.md b/locales/tr/SolidityBeginnerCourse/control-flow-loops/loops.md new file mode 100644 index 000000000..ffaa30650 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/control-flow-loops/loops.md @@ -0,0 +1,32 @@ +Solidity supports iterative control flow statements that allow contracts to execute code repeatedly. + +Solidity differentiates between three types of loops: `for`, `while`, and `do while` loops. + +### for + +Generally, `for` loops (line 7) are great if you know how many times you want to execute a certain block of code. In solidity, you should specify this amount to avoid transactions running out of gas and failing if the amount of iterations is too high. + +### while + +If you don’t know how many times you want to execute the code but want to break the loop based on a condition, you can use a `while` loop (line 20). +Loops are seldom used in Solidity since transactions might run out of gas and fail if there is no limit to the number of iterations that can occur. + +### do while + +The `do while` loop is a special kind of while loop where you can ensure the code is executed at least once, before checking on the condition. + +### continue + +The `continue` statement is used to skip the remaining code block and start the next iteration of the loop. In this contract, the `continue` statement (line 10) will prevent the second if statement (line 12) from being executed. + +### break + +The `break` statement is used to exit a loop. In this contract, the break statement (line 14) will cause the for loop to be terminated after the sixth iteration. + +Watch a video tutorial on Loop statements. + +## ⭐️ Assignment + +1. Create a public `uint` state variable called count in the `Loop` contract. +2. At the end of the for loop, increment the count variable by 1. +3. Try to get the count variable to be equal to 9, but make sure you don’t edit the `break` statement. diff --git a/locales/tr/SolidityBeginnerCourse/data-locations/dataLocations.md b/locales/tr/SolidityBeginnerCourse/data-locations/dataLocations.md new file mode 100644 index 000000000..881bf8ffc --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/data-locations/dataLocations.md @@ -0,0 +1,54 @@ +The values of variables in Solidity can be stored in different data locations: _memory_, _storage_, and _calldata_. + +As we have discussed before, variables of the value type store an independent copy of a value, while variables of the reference type (array, struct, mapping) only store the location (reference) of the value. + +If we use a reference type in a function, we have to specify in which data location their values are stored. The price for the execution of the function is influenced by the data location; creating copies from reference types costs gas. + +### Storage + +Values stored in _storage_ are stored permanently on the blockchain and, therefore, are expensive to use. + +In this contract, the state variables `arr`, `map`, and `myStructs` (lines 5, 6, and 10) are stored in storage. State variables are always stored in storage. + +### Memory + +Values stored in _memory_ are only stored temporarily and are not on the blockchain. They only exist during the execution of an external function and are discarded afterward. They are cheaper to use than values stored in _storage_. + +In this contract, the local variable `myMemstruct` (line 19), as well as the parameter `_arr` (line 31), are stored in memory. Function parameters need to have the data location _memory_ or _calldata_. + +### Calldata + +_Calldata_ stores function arguments. Like _memory_, _calldata_ is only stored temporarily during the execution of an external function. In contrast to values stored in _memory_, values stored in _calldata_ can not be changed. Calldata is the cheapest data location to use. + +In this contract, the parameter `_arr` (line 35) has the data location _calldata_. If we wanted to assign a new value to the first element of the array `_arr`, we could do that in the `function g` (line 31) but not in the `function h` (line 35). This is because `_arr` in `function g `has the data location _memory_ and _function h_ has the data location `calldata`. + +## Assignments + +### Memory to memory + +Assignments from _memory_ to _memory_ create references instead of copies. If you change the value in one variable, the value of all other variables that reference the same data will be changed. + +If we were to create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myMemStruct` (line 19), any change to `myMemStruct2` would also change the value of `myMemStruct`. + +### Storage to local storage + +Assignments from _storage_ to _local storage_ also create references, not copies. + +If we change the value of the local variable `myStruct` (line 17), the value of our state variable `myStructs` (line 10) changes as well. + +## Storage and memory/calldata + +Assignments between _storage_ and _memory_ (or _calldata_) create independent copies, not references. + +If we were to create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` (line 12) and assign it the value of `myStruct`, changes in `myMemStruct3` would not affect the values stored in the mapping `myStructs` (line 10). + +As we said in the beginning, when creating contracts we have to be mindful of gas costs. Therefore, we need to use data locations that require the lowest amount of gas possible. + +## ⭐️ Assignment + +1. Change the value of the `myStruct` member `foo`, inside the `function f`, to 4. +2. Create a new struct `myMemStruct2` with the data location _memory_ inside the `function f` and assign it the value of `myMemStruct`. Change the value of the `myMemStruct2` member `foo` to 1. +3. Create a new struct `myMemStruct3` with the data location _memory_ inside the `function f` and assign it the value of `myStruct`. Change the value of the `myMemStruct3` member `foo` to 3. +4. Let the function f return `myStruct`, `myMemStruct2`, and `myMemStruct3`. + +Tip: Make sure to create the correct return types for the function `f`. diff --git a/locales/tr/SolidityBeginnerCourse/data-structures-arrays/arrays.md b/locales/tr/SolidityBeginnerCourse/data-structures-arrays/arrays.md new file mode 100644 index 000000000..19af3de49 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/data-structures-arrays/arrays.md @@ -0,0 +1,44 @@ +In the next sections, we will look into the data structures that we can use to organize and store our data in Solidity. + +_Arrays_, _mappings_ and _structs_ are all _reference types_. Unlike _value types_ (e.g. _booleans_ or _integers_) reference types don't store their value directly. Instead, they store the location where the value is being stored. Multiple reference type variables could reference the same location, and a change in one variable would affect the others, therefore they need to be handled carefully. + +In Solidity, an array stores an ordered list of values of the same type that are indexed numerically. + +There are two types of arrays, compile-time _fixed-size_ and _dynamic arrays_. For fixed-size arrays, we need to declare the size of the array before it is compiled. The size of dynamic arrays can be changed after the contract has been compiled. + +### Declaring arrays + +We declare a fixed-size array by providing its type, array size (as an integer in square brackets), visibility, and name (line 9). + +We declare a dynamic array in the same manner. However, we don’t provide an array size and leave the brackets empty (line 6). + +### Initializing arrays + +We can initialize the elements of an array all at once (line 7), or initiate new elements one by one (arr[0] = 1;). If we declare an array, we automatically initialize its elements with the default value 0 (line 9). + +### Accessing array elements + +We access elements inside an array by providing the name of the array and the index in brackets (line 12). + +### Adding array elements + +Using the `push()` member function, we add an element to the end of a dynamic array (line 25). + +### Removing array elements + +Using the `pop()` member function, we delete the last element of a dynamic array (line 31). + +We can use the `delete` operator to remove an element with a specific index from an array (line 42). +When we remove an element with the `delete` operator all other elements stay the same, which means that the length of the array will stay the same. This will create a gap in our array. +If the order of the array is not important, then we can move the last element of the array to the place of the deleted element (line 46), or use a mapping. A mapping might be a better choice if we plan to remove elements in our data structure. + +### Array length + +Using the length member, we can read the number of elements that are stored in an array (line 35). + +Watch a video tutorial on Arrays. + +## ⭐️ Assignment + +1. Initialize a public fixed-sized array called `arr3` with the values 0, 1, 2. Make the size as small as possible. +2. Change the `getArr()` function to return the value of `arr3`. diff --git a/locales/tr/SolidityBeginnerCourse/data-structures-enums/enums.md b/locales/tr/SolidityBeginnerCourse/data-structures-enums/enums.md new file mode 100644 index 000000000..40411db67 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/data-structures-enums/enums.md @@ -0,0 +1,33 @@ +In Solidity _enums_ are custom data types consisting of a limited set of constant values. We use enums when our variables should only get assigned a value from a predefined set of values. + +In this contract, the state variable `status` can get assigned a value from the limited set of provided values of the enum `Status` representing the various states of a shipping status. + +### Defining enums + +We define an enum with the enum keyword, followed by the name of the custom type we want to create (line 6). Inside the curly braces, we define all available members of the enum. + +### Initializing an enum variable + +We can initialize a new variable of an enum type by providing the name of the enum, the visibility, and the name of the variable (line 16). Upon its initialization, the variable will be assigned the value of the first member of the enum, in this case, Pending (line 7). + +Even though enum members are named when you define them, they are stored as unsigned integers, not strings. They are numbered in the order that they were defined, the first member starting at 0. The initial value of status, in this case, is 0. + +### Accessing an enum value + +To access the enum value of a variable, we simply need to provide the name of the variable that is storing the value (line 25). + +### Updating an enum value + +We can update the enum value of a variable by assigning it the `uint` representing the enum member (line 30). Shipped would be 1 in this example. Another way to update the value is using the dot operator by providing the name of the enum and its member (line 35). + +### Removing an enum value + +We can use the delete operator to delete the enum value of the variable, which means as for arrays and mappings, to set the default value to 0. + +Watch a video tutorial on Enums. + +## ⭐️ Assignment + +1. Define an enum type called `Size` with the members `S`, `M`, and `L`. +2. Initialize the variable `sizes` of the enum type `Size`. +3. Create a getter function `getSize()` that returns the value of the variable `sizes`. diff --git a/locales/tr/SolidityBeginnerCourse/data-structures-mappings/mappings.md b/locales/tr/SolidityBeginnerCourse/data-structures-mappings/mappings.md new file mode 100644 index 000000000..72fc4acb4 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/data-structures-mappings/mappings.md @@ -0,0 +1,37 @@ +In Solidity, _mappings_ are a collection of key types and corresponding value type pairs. + +The biggest difference between a mapping and an array is that you can't iterate over mappings. If we don't know a key we won't be able to access its value. If we need to know all of our data or iterate over it, we should use an array. + +If we want to retrieve a value based on a known key we can use a mapping (e.g. addresses are often used as keys). Looking up values with a mapping is easier and cheaper than iterating over arrays. If arrays become too large, the gas cost of iterating over it could become too high and cause the transaction to fail. + +We could also store the keys of a mapping in an array that we can iterate over. + +### Creating mappings + +Mappings are declared with the syntax `mapping(KeyType => ValueType) VariableName`. +The key type can be any built-in value type or any contract, but not a reference type. The value type can be of any type. + +In this contract, we are creating the public mapping `myMap` (line 6) that associates the key type `address` with the value type `uint`. + +### Accessing values + +The syntax for interacting with key-value pairs of mappings is similar to that of arrays. +To find the value associated with a specific key, we provide the name of the mapping and the key in brackets (line 11). + +In contrast to arrays, we won't get an error if we try to access the value of a key whose value has not been set yet. When we create a mapping, every possible key is mapped to the default value 0. + +### Setting values + +We set a new value for a key by providing the mapping’s name and key in brackets and assigning it a new value (line 16). + +### Removing values + +We can use the delete operator to delete a value associated with a key, which will set it to the default value of 0. As we have seen in the arrays section. + +Watch a video tutorial on Mappings. + +## ⭐️ Assignment + +1. Create a public mapping `balances` that associates the key type `address` with the value type `uint`. +2. Change the functions `get` and `remove` to work with the mapping balances. +3. Change the function `set` to create a new entry to the balances mapping, where the key is the address of the parameter and the value is the balance associated with the address of the parameter. diff --git a/locales/tr/SolidityBeginnerCourse/data-structures-structs/structs.md b/locales/tr/SolidityBeginnerCourse/data-structures-structs/structs.md new file mode 100644 index 000000000..fba0d93b0 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/data-structures-structs/structs.md @@ -0,0 +1,29 @@ +In Solidity, we can define custom data types in the form of _structs_. Structs are a collection of variables that can consist of different data types. + +### Defining structs + +We define a struct using the `struct` keyword and a name (line 5). Inside curly braces, we can define our struct’s members, which consist of the variable names and their data types. + +### Initializing structs + +There are different ways to initialize a struct. + +Positional parameters: We can provide the name of the struct and the values of its members as parameters in parentheses (line 16). + +Key-value mapping: We provide the name of the struct and the keys and values as a mapping inside curly braces (line 19). + +Initialize and update a struct: We initialize an empty struct first and then update its member by assigning it a new value (line 23). + +### Accessing structs + +To access a member of a struct we can use the dot operator (line 33). + +### Updating structs + +To update a structs’ member we also use the dot operator and assign it a new value (lines 39 and 45). + +Watch a video tutorial on Structs. + +## ⭐️ Assignment + +Create a function `remove` that takes a `uint` as a parameter and deletes a struct member with the given index in the `todos` mapping. diff --git a/locales/tr/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md b/locales/tr/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md new file mode 100644 index 000000000..d0e628f6b --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md @@ -0,0 +1,37 @@ +In this section, we will learn more about the inputs and outputs of functions. + +### Multiple named Outputs + +Functions can return multiple values that can be named and assigned to their name. + +The `returnMany` function (line 6) shows how to return multiple values. +You will often return multiple values. It could be a function that collects outputs of various functions and returns them in a single function call for example. + +The `named` function (line 19) shows how to name return values. +Naming return values helps with the readability of your contracts. Named return values make it easier to keep track of the values and the order in which they are returned. You can also assign values to a name. + +The `assigned` function (line 33) shows how to assign values to a name. +When you assign values to a name you can omit (leave out) the return statement and return them individually. + +### Deconstructing Assignments + +You can use deconstructing assignments to unpack values into distinct variables. + +The `destructingAssigments` function (line 49) assigns the values of the `returnMany` function to the new local variables `i`, `b`, and `j` (line 60). + +### Input and Output restrictions + +There are a few restrictions and best practices for the input and output parameters of contract functions. + +"_[Mappings] cannot be used as parameters or return parameters of contract functions that are publicly visible._" +From the Solidity documentation. + +Arrays can be used as parameters, as shown in the function `arrayInput` (line 71). Arrays can also be used as return parameters as shown in the function `arrayOutput` (line 76). + +You have to be cautious with arrays of arbitrary size because of their gas consumption. While a function using very large arrays as inputs might fail when the gas costs are too high, a function using a smaller array might still be able to execute. + +Watch a video tutorial on Function Outputs. + +## ⭐️ Assignment + +Create a new function called `returnTwo` that returns the values `-2` and `true` without using a return statement. diff --git a/locales/tr/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md b/locales/tr/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md new file mode 100644 index 000000000..d707a987b --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md @@ -0,0 +1,39 @@ +In this section, we will learn how to modify the behavior of a function and how to run contract initialization code. + +### Function Modifier + +_Function Modifiers_ are used to change the behavior of a function. For example, they often check for a condition prior to executing a function to restrict access or validate inputs. + +This first part of this contract is about changing ownership of a contract. Ownership in this contract is expressed by the value of the state variable `owner` that is of the type `address` (line 7). + +The function `changeOwner` (line 33) can change this ownership. It takes an input parameter of the type `address` and assigns its value to the state variable `owner`. + +However, this function cannot simply be executed under all conditions; it has two modifiers, `onlyOwner` and `validAddress`. + +Let's look at `onlyOwner` first (line 18). +Function modifiers are defined with the `modifier` keyword and a unique name; they can also have parameters. + +The underscore `_` (line 23) is used inside modifiers to represent the rest of the code that will be executed in the body of the modified function. +The code you place before the underscore in the modifier will be executed before the code in the body of the modified function. The code after the underscore will be executed after the code in the body of the modified function. + +In this case, the `require` function (line 19) checks if the address executing the contract is the same as the value stored in the variable `owner`. If it is, the rest of the code will be executed, otherwise it will throw an error. + +You can learn more about `assert` and `require` in the Solidity documentation, they are used to check for conditions and throw errors if they are not met. + +The `validAddress` modifier (line 28) has a parameter of type `address` and checks if the provided address is valid. If it is, it continues to execute the code. + +### Constructor + +A constructor function is executed upon the creation of a contract. You can use it to run contract initialization code. The constructor can have parameters and is especially useful when you don't know certain initialization values before the deployment of the contract. + +You declare a constructor using the `constructor` keyword. The constructor in this contract (line 11) sets the initial value of the owner variable upon the creation of the contract. + +Watch a video tutorial on Function Modifiers. + +## ⭐️ Assignment + +1. Create a new function, `increaseX` in the contract. The function should take an input parameter of type `uint` and increase the value of the variable `x` by the value of the input parameter. +2. Make sure that x can only be increased. +3. The body of the function `increaseX` should be empty. + +Tip: Use modifiers. diff --git a/locales/tr/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md b/locales/tr/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md new file mode 100644 index 000000000..3670c03e2 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md @@ -0,0 +1,23 @@ +This section will give a short introduction to functions and teach you how to use them to read from and write to a state variable. + +As in other languages, we use functions in Solidity to create modular, reusable code. However, Solidity functions have some particularities. + +Solidity functions can be split into two types: + +1. Functions that modify the state of the blockchain, like writing to a state variable. In this contract, the `set` function (line 9) changes the state variable `num`. +2. Functions that don't modify the state of the blockchain. These functions are marked `view` or `pure`. For example, in this contract, the `get` function (line 14) marked `view` that only returns `num` does not change the state. + +To define a function, use the `function` keyword followed by a unique name. + +If the function takes inputs like our `set` function (line 9), you must specify the parameter types and names. A common convention is to use an underscore as a prefix for the parameter name to distinguish them from state variables. + +You can then set the visibility of a function and declare them `view` or `pure` as we do for the `get` function if they don't modify the state. Our `get` function also returns values, so we have to specify the return types. In this case, it's a `uint` since the state variable `num` that the function returns is a `uint`. + +We will explore the particularities of Solidity functions in more detail in the following sections. + +Watch a video tutorial on Functions. + +## ⭐️ Assignment + +1. Create a public state variable called `b` that is of type `bool` and initialize it to `true`. +2. Create a public function called `get_b` that returns the value of `b`. diff --git a/locales/tr/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md b/locales/tr/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md new file mode 100644 index 000000000..b846c7d99 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md @@ -0,0 +1,44 @@ +This section will look into the types of functions that don't modify the state of the blockchain: _view_ and _pure_ functions. + +### View Functions + +_View functions_ promise to not modify the state. + +"The following statements are considered modifying the state: + +1. Writing to state variables. +2. Emitting events. +3. Creating other contracts. +4. Using selfdestruct. +5. Sending Ether via calls. +6. Calling any function not marked view or pure. +7. Using low-level calls. +8. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a view function using the keyword `view`. In this contract, `addToX` (line 8) is a view function. This function takes the parameter `y` and returns the sum of the parameter and the state variable `x`. It reads `x` but does not modify it. + +### Pure functions + +_Pure functions_ promise to neither modify nor to read the state. + +"In addition to the list of state modifying statements explained above, the following are considered reading from the state: + +1. Reading from state variables. +2. Accessing `address(this).balance` or `
.balance`. +3. Accessing any of the members of block, tx, msg (with the exception of `msg.sig` and `msg.data`). +4. Calling any function not marked pure. +5. Using inline assembly that contains certain opcodes." + +From the Solidity documentation. + +You can declare a pure function using the keyword `pure`. In this contract, `add` (line 13) is a pure function. This function takes the parameters `i` and `j`, and returns the sum of them. It neither reads nor modifies the state variable `x`. + +In Solidity development, you need to optimise your code for saving computation cost (gas cost). Declaring functions view and pure can save gas cost and make the code more readable and easier to maintain. Pure functions don't have any side effects and will always return the same result if you pass the same arguments. + +Watch a video tutorial on View and Pure Functions. + +## ⭐️ Assignment + +Create a function called `addToX2` that takes the parameter `y` and updates the state variable `x` with the sum of the parameter and the state variable `x`. diff --git a/locales/tr/SolidityBeginnerCourse/introduction/introduction.md b/locales/tr/SolidityBeginnerCourse/introduction/introduction.md new file mode 100644 index 000000000..cc821a46a --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/introduction/introduction.md @@ -0,0 +1,32 @@ +Welcome to this interactive Solidity course for beginners. + +In this first section, we will give you a short preview of the concepts we will cover in this course, look at an example smart contract, and show you how you can interact with this contract in the Remix IDE. + +This contract is a counter contract that has the functionality to increase, decrease, and return the state of a counter variable. + +If we look at the top of the contract, we can see some information about the contract like the license (line 1), the Solidity version (line 2), as well as the keyword `contract` and it's name, `Counter` (line 4). We will cover these concepts in the next section about the **Basic Syntax**. + +With `uint public count` (line 5) we declare a state variable of the type `uint` with the visibility `public`. We will cover these concepts in our sections about **Variables**, **Primitive Data Types**, and **Visibility**. + +We then create a `get` function (line 8) that is defined with the `view` keyword and returns a `uint` type. Specifically, it returns the `count` variable. This contract has two more functions, an `inc` (line 13) and `dec` (line 18) function that increases or decreases our count variable. +We will talk about these concepts in our sections about **Functions - Reading and Writing to a State Variable** and **Functions - View and pure**. + +## Compile and Deploy through Remix + +**GIF** Interacting with the contract: Compile and deploy contract + +1. We can compile your `Counter` contract in the "Solidity compiler" module of the Remix IDE. + +2. In the "Deploy & run transactions" module, we select our contract "Counter" in the contract input field and click on the "Deploy" button. + +3. We expand the token contract functions in the IDE, and test its `get`, `inc`, and `dec` functions. + +## ⭐️ Assignment + +Throughout this course, we will give you assignments to test and consolidate your newly acquired knowledge. + +Your first assignment is to: + +1. Compile this contract. +2. Deploy it to the Remix VM. +3. Interact with your contract. diff --git a/locales/tr/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md b/locales/tr/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md new file mode 100644 index 000000000..9ea6b8626 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md @@ -0,0 +1,33 @@ +In this section, we will show you Solidity’s primitive data types, how to declare them, and their characteristics. + +### bool + +You can declare data a boolean type by using the keyword ‘bool’. Booleans can either have the value `true` or `false`. + +### uint + +We use the keywords `uint` and `uint8` to `uint256` to declare an _unsigned integer type_ (they don’t have a sign, unlike -12, for example). Uints are integers that are positive or zero and range from 8 bits to 256 bits. The type `uint` is the same as `uint256`. + +### int + +We use the keywords `int` and `int8` to `int256` to declare an integer type. Integers can be positive, negative, or zero and range from 8 bits to 256 bits. The type `int` is the same as `int256`. + +### address + +Variables of the type `address` hold a 20-byte value, which is the size of an Ethereum address. There is also a special kind of Ethereum address, `address payable`, which can receive ether from the contract. + +All these data types have default values, as shown in the contract (line 29). + +You can learn more about these data types as well as _Fixed Point Numbers_, _Byte Arrays_, _Strings_, and more in the Solidity documentation. + +Later in the course, we will look at data structures like **Mappings**, **Arrays**, **Enums**, and **Structs**. + +Watch a video tutorial on Primitive Data Types. + +## ⭐️ Assignment + +1. Create a new variable `newAddr` that is a `public` `address` and give it a value that is not the same as the available variable `addr`. +2. Create a `public` variable called `neg` that is a negative number, decide upon the type. +3. Create a new variable, `newU` that has the smallest `uint` size type and the smallest `uint` value and is `public`. + +Tip: Look at the other address in the contract or search the internet for an Ethereum address. diff --git a/locales/tr/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md b/locales/tr/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md new file mode 100644 index 000000000..57208c555 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md @@ -0,0 +1,26 @@ +_Ether_ (ETH) is a cryptocurrency. _Ether_ is also used to pay fees for using the Ethereum network, like making transactions in the form of sending _Ether_ to an address or interacting with an Ethereum application. + +### Ether Units + +To specify a unit of _Ether_, we can add the suffixes `wei`, `gwei`, or `ether` to a literal number. + +#### `wei` + +_Wei_ is the smallest subunit of _Ether_, named after the cryptographer [Wei Dai](https://en.wikipedia.org/wiki/Wei_Dai). _Ether_ numbers without a suffix are treated as `wei` (line 7). + +#### `gwei` + +One `gwei` (giga-wei) is equal to 1,000,000,000 (10^9) `wei`. + +#### `ether` + +One `ether` is equal to 1,000,000,000,000,000,000 (10^18) `wei` (line 11). + +Watch a video tutorial on Ether and Wei. + +## ⭐️ Assignment + +1. Create a `public` `uint` called `oneGWei` and set it to 1 `gwei`. +2. Create a `public` `bool` called `isOneGWei` and set it to the result of a comparison operation between 1 gwei and 10^9. + +Tip: Look at how this is written for `gwei` and `ether` in the contract. diff --git a/locales/tr/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md b/locales/tr/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md new file mode 100644 index 000000000..bbc25575c --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md @@ -0,0 +1,29 @@ +As we have seen in the previous section, executing code via transactions on the Ethereum Network costs transaction fees in the form of Ether. The amount of fees that have to be paid to execute a transaction depends on the amount of _gas_ that the execution of the transaction costs. + +### Gas + +_Gas_ is the unit that measures the amount of computational effort that is required to execute a specific operation on the Ethereum network. + +### Gas price + +The _gas_ that fuels Ethereum is sometimes compared to the gas that fuels a car. The amount of gas your car consumes is mostly the same, but the price you pay for gas depends on the market. + +Similarly, the amount of _gas_ that a transaction requires is always the same for the same computational work that is associated with it. However the price that the sender of the transaction is willing to pay for the _gas_ is up to them. Transactions with higher _gas prices_ are going through faster; transactions with very low _gas prices_ might not go through at all. + +When sending a transaction, the sender has to pay the _gas_ fee (gas_price \* gas) upon execution of the transaction. If _gas_ is left over after the execution is completed, the sender gets refunded. + +_Gas_ prices are denoted in gwei. + +### Gas limit + +When sending a transaction, the sender specifies the maximum amount of gas that they are willing to pay for. If they set the limit too low, their transaction can run out of _gas_ before being completed, reverting any changes being made. In this case, the _gas_ was consumed and can’t be refunded. + +Learn more about _gas_ on ethereum.org. + +Watch a video tutorial on Gas and Gas Price. + +## ⭐️ Assignment + +Create a new `public` state variable in the `Gas` contract called `cost` of the type `uint`. Store the value of the gas cost for deploying the contract in the new variable, including the cost for the value you are storing. + +Tip: You can check in the Remix terminal the details of a transaction, including the gas cost. You can also use the Remix plugin _Gas Profiler_ to check for the gas cost of transactions. diff --git a/locales/tr/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md b/locales/tr/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md new file mode 100644 index 000000000..58fb4c5a6 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md @@ -0,0 +1,86 @@ +In this section, we will learn how a contract can send and receive Ether. + +### Sending Ether + +We have three different options to transfer Ether: `transfer()`, `send()` and `call()`. + +#### **transfer** + +`
.transfer(uint256 amount)` + +- `transfer()` throws an exception on failure +- Forwards a fixed 2300 gas stipend + +An example of `transfer()` can be seen in the `SendEther` contract (line 35). +**`Transfer()` is not recommended to be used anymore.** + +#### **send** + +`
.send(uint256 amount) returns (bool)` + +- `send()` returns false on failure +- Forwards a fixed 2300 gas stipend + +An example of `send()` can be seen in the `SendEther` contract (line 41). +**`Send()` is not recommended to be used anymore.** + +#### **call** + +`
.call(bytes memory) returns (bool, bytes memory)` + +- `call()` returns false on failure +- Forwards the maximum amount of gas, but this is adjustable + +An example of `call()` can be seen in the `SendEther` contract (line 48). +`Call()` is currently recommended if you are transfering Ether. + +The reason `transfer()` and `send()` were introduced was to guard against _reentry attacks_ by limiting the forwarded gas to 2300, which would be insufficient to make a reentrant call that can modify storage. + +As we discussed in the last section, each operation on Ethereum has a specific cost associated with it. Certain operations have become more cost intensive over time, so the gas costs associated with them are also raised. When gas costs for operations are subject to change it is not good to use a hardcoded gas amount like transfer(), and send() do. + +That’s why `call()` instead of `transfer()` is now recommended to send Ether. + +Learn more about the subject in this Consensys blog post. + +### Reentrancy attack + +A _reentrancy attack_ occurs when a function makes an external call to an untrusted contract and the attacker uses the contract to make recursive calls back to the original function before it finishes its execution. Through this method, the attacker can drain funds and manipulate data in unintended ways. + +To guard against a _reentrancy attack_, all state changes should be made before calling an external contract. This is also called the Checks-Effects-Interactions pattern. + +Another way to prevent reentrancy is to use a _Reentrancy Guard_ that checks for such calls and rejects them. You can see an example of this in the contract in our modifier section or a more gas-efficient version on Open Zepplin. + +### Receiving Ether + +If we want to enable a contract to receive Ether without a function being called, we need to create a `receive` function (line 22) or a `fallback` function (line 25); otherwise, the Ether will be rejected, and the contract will throw an exception. + +The `receive` function is executed on calls with empty calldata (e.g. plain Ether transfers via send() or transfer()), while the fallback function is executed on calls with calldata. If no receive function exists but a fallback function does, calls with empty calldata will also use the fallback function. + +### Payable function modifier + +The `payable` function modifier allows a function to receive Ether. + +The `receive` function (line 22) needs to be `payable`. If you delete the `payable` modifier you will get an error from the compiler. If you delete the `payable` modifier from the `fallback` function (line 25) it will compile, but it won’t be able to receive Ether. +The functions `sendViaTransfer`, `sendViaSend`, and `sendViaCall` (lines 33, 38, and 45) also need to be `payable` in order to receive Ether. + +### Payable address + +Solidity makes a distinction between two different flavors of the address data type: address and address payable. + +`address`: Holds a 20-byte value. +`address payable`: Holds a 20-byte value and can receive Ether via its members: transfer and send. + +If you change the parameter type for the functions `sendViaTransfer` and `sendViaSend` (line 33 and 38) from `payable address` to `address`, you won’t be able to use `transfer()` (line 35) or `send()` (line 41). + +Watch a video tutorial on Sending Ether. + +## ⭐️ Assignment + +Build a charity contract that receives Ether that can be withdrawn by a beneficiary. + +1. Create a contract called `Charity`. +2. Add a public state variable called `owner` of the type address. +3. Create a donate function that is public and payable without any parameters or function code. +4. Create a withdraw function that is public and sends the total balance of the contract to the `owner` address. + +Tip: Test your contract by deploying it from one account and then sending Ether to it from another account. Then execute the withdraw function. diff --git a/locales/tr/SolidityBeginnerCourse/variables/variables.md b/locales/tr/SolidityBeginnerCourse/variables/variables.md new file mode 100644 index 000000000..dfb35b382 --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/variables/variables.md @@ -0,0 +1,29 @@ +There are three different types of variables in Solidity: _State Variables_, _Local Variables_, and _Global Variables_. + +## 1. State Variables + +_State Variables_ are stored in the contract _storage_ and thereby on the blockchain. They are declared inside the contract but outside the function. +This contract has two state variables, the string `text`(line 6) and the uint `num` (line 7). + +## 2. Local Variables + +_Local Variables_ are stored in the _memory_ and their values are only accessible within the function they are defined in. Local Variables are not stored on the blockchain. +In this contract, the uint `i` (line 11) is a local variable. + +## 3. Global Variables + +_Global Variables_, also called _Special Variables_, exist in the global namespace. They don't need to be declared but can be accessed from within your contract. +Global Variables are used to retrieve information about the blockchain, particular addresses, contracts, and transactions. + +In this example, we use `block.timestamp` (line 14) to get a Unix timestamp of when the current block was generated and `msg.sender` (line 15) to get the caller of the contract function’s address. + +A list of all Global Variables is available in the Solidity documentation. + +Watch video tutorials on State Variables, Local Variables, and Global Variables. + +## ⭐️ Assignment + +1. Create a new public state variable called `blockNumber`. +2. Inside the function `doSomething()`, assign the value of the current block number to the state variable `blockNumber`. + +Tip: Look into the global variables section of the Solidity documentation to find out how to read the current block number. diff --git a/locales/tr/SolidityBeginnerCourse/visibility/visibility.md b/locales/tr/SolidityBeginnerCourse/visibility/visibility.md new file mode 100644 index 000000000..79e4307bf --- /dev/null +++ b/locales/tr/SolidityBeginnerCourse/visibility/visibility.md @@ -0,0 +1,37 @@ +The `visibility` specifier is used to control who has access to functions and state variables. + +There are four types of visibilities: `external`, `public`, `internal`, and `private`. + +They regulate if functions and state variables can be called from inside the contract, from contracts that derive from the contract (child contracts), or from other contracts and transactions. + +### private + +- Can be called from inside the contract + +### internal + +- Can be called from inside the contract +- Can be called from a child contract + +### public + +- Can be called from inside the contract +- Can be called from a child contract +- Can be called from other contracts or transactions + +### external + +- Can be called from other contracts or transactions +- State variables can not be `external` + +In this example, we have two contracts, the `Base` contract (line 4) and the `Child` contract (line 55) which inherits the functions and state variables from the `Base` contract. + +When you uncomment the `testPrivateFunc` (lines 58-60) you get an error because the child contract doesn’t have access to the private function `privateFunc` from the `Base` contract. + +If you compile and deploy the two contracts, you will not be able to call the functions `privateFunc` and `internalFunc` directly. You will only be able to call them via `testPrivateFunc` and `testInternalFunc`. + +Watch a video tutorial on Visibility. + +## ⭐️ Assignment + +Create a new function in the `Child` contract called `testInternalVar` that returns the values of all state variables from the `Base` contract that are possible to return. diff --git a/locales/tr/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md b/locales/tr/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md new file mode 100644 index 000000000..801d8c582 --- /dev/null +++ b/locales/tr/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md @@ -0,0 +1,47 @@ +In this tutorial, we'll explore the Uniswap V3 Swap contract to learn about how single-hop and multi-hop swaps work. + +But first, some Uniswap fundamentals. + +## What is Uniswap? + +Uniswap is a decentralized cryptocurrency exchange. It allows users to exchange tokens without the need for a centralized intermediary. Uniswap is a key player in the decentralized finance (DeFi) space. + +## How does Uniswap work? + +Instead of using an order book like a traditional centralized exchange, Uniswap uses an automated market maker (AMM) model. In Uniswap, the AMM is a smart contract that holds reserves of tokens (Liquidity Pool). Users can trade between tokens in the Liquidity Pool. The price of each token is determined by the ratio of the reserves. + +### Step-by-step example of a Uniswap trade + +1. Alice wants to trade 1 ETH for DAI. +2. Alice sends 1 ETH to the Uniswap smart contract. +3. The Uniswap smart contract calculates the amount of DAI that Alice should receive based on the current exchange rate. +4. The Uniswap smart contract sends the DAI to Alice. +5. The Uniswap smart contract adds the 1 ETH to its reserves. +6. The Uniswap smart contract recalculates the exchange rate based on the new reserves. + +The tokens in the Liquidity Pool are provided by Liquidity Providers. When a Liquidity Provider deposits tokens into a Liquidity Pool, they receive Liquidity Provider Tokens in return. Liquidity Provider Tokens represent a user's share of a Liquidity Pool. + +Users of Uniswap pay a fee for each trade. The fee is paid to the Liquidity Providers in the form of additional Liquidity Provider Tokens. + +## Uniswap Swap Contract + +The Uniswap Swap contract allows users to swap tokens using Uniswap V3. It can do single-hop swaps, which allow users to exchange one token for another directly. It can also do multi-hop swaps, which means that users can exchange one token for another by routing through multiple tokens. Routing in this context means that the swap contract will exchange the token for another token, then exchange that token for another token, and so on until it reaches the desired token. + +## Conclusion + +In this section, we learned about Uniswap, how it works, and how we are going to use it to swap tokens. + +## ⭐️ Assignment: Multiple Choice Test + +### 1. What is Uniswap? + +1. A centralized exchange protocol. +2. A decentralized exchange protocol that uses an order book. +3. A decentralized exchange protocol that uses an automated market maker (AMM) model. +4. A decentralized exchange protocol that uses an order book and an automated market maker (AMM) model. + +### 2) How does Uniswap determine the price of a token? + +1. The price of a token is determined by the ratio of the reserves. +2. The price of a token is determined by the ratio of the reserves and the number of trades. +3. The price of a token is determined by the ratio of the reserves and the number of Liquidity Providers. diff --git a/locales/tr/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md b/locales/tr/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md new file mode 100644 index 000000000..e5cc248f5 --- /dev/null +++ b/locales/tr/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md @@ -0,0 +1,41 @@ +The entire UniswapSwapExamples contract will only be presented in section 5 of this tutorial. Before then, we'll build up blocks of code. + +This section explores the `ISwapRouter` interface, which defines the functions that can be called on the Uniswap Swap contract. + +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. +Multi-hop swaps allow users to exchange one token for another by routing through multiple tokens. + +Interfaces in Solidity specify functions that must be included in a contract that inherits them. They are useful for declaring what functions be supported and allow for easier integration and interaction between different contracts. + +Structs are used to define custom data types. + +## ISwapRouter Interface + +The ISwapRouter interface defines the functions that can be called on the Uniswap Swap contract. We will need to use this interface to interact with the Uniswap Swap contract and execute swaps. + +On line 5, we define a constant variable called `router` that is of type `ISwapRouter`. We set the value of this variable to the interface instance of a smart contract that is deployed at the address `0xE592427A0AEce92De3Edee1F18E0157C05861564`. This is the address of the Uniswap V3 Swap contract on the Ethereum mainnet. + +On line 9, we define an interface called `ISwapRouter`. This interface defines two functions: `exactInputSingle` and `exactInput`. + +## exactInputSingle + +On line 25, we define a struct called `ExactInputSingleParams`. This struct defines the parameters that are required for our exactInputSingle function on line 21, which will execute a single-hop swap. The struct has the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 fee`**: The fee associated with the swap. +- **`address recipient`**: The address that will receive the output token. +- **`uint deadline`**: A timestamp by which the transaction must be processed, for time-limiting the swap. +- **`uint amountIn`**: The amount of the input token being sent. +- **`uint amountOutMinimum`**: The minimum amount of the output token that the sender is willing to accept, to protect against unfavorable price movements. +- **`uint160 sqrtPriceLimitX96`**: A limit on the price, represented in a specific format, to prevent the swap from occurring at unfavorable prices. + +## exactInput + +On line 25, we define a struct called `ExactInputParams`. This struct defines the parameters that are required for our `exactInput` function on line 33. This function will execute a multi-hop swap. The struct has the following parameters: + +- **`bytes path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address recipient`**: The address receiving the output tokens. +- **`uint deadline`**: Similar to above, a timestamp by which the transaction must be processed. +- **`uint amountIn`**: The amount of the input token. +- **`uint amountOutMinimum`**: The minimum amount of the output token the sender expects to receive. diff --git a/locales/tr/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md b/locales/tr/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md new file mode 100644 index 000000000..f4d70c445 --- /dev/null +++ b/locales/tr/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md @@ -0,0 +1,36 @@ +Single-hop swaps allow users to exchange one token for another directly within a liquidity pool. In this section, we will learn how to use the Uniswap V3 Swap contract to execute single-hop swaps. + +## Function Parameters + +On line 8, we define a function called `swapExactInputSingleHop`. This function executes a single-hop swap. It takes the following parameters: + +- **`address tokenIn`**: The address of the token being sent. +- **`address tokenOut`**: The address of the token being received. +- **`uint24 poolFee`**: The fee associated with the swap. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +## Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 14. +Then, we approve the Uniswap Swap contract to spend the input token on our behalf, line 15. + +On line 17, we create an instance of the `ExactInputSingleParams` struct. This struct contains the parameters that are required for our `exactInputSingle` function on line 45, which will execute the single-hop swap. We repeat `ISwapRouter.ExactInputSingleParams` two times on that line because we are making an instance of a struct that is defined in an interface. + +## Parameters of the ExactInputSingleParams Struct + +We set the parameters of the struct as follows: + +- **`tokenIn`**: We set this to the `tokenIn` parameter of our function. +- **`tokenOut`**: We set this to the `tokenOut` parameter of our function. +- **`fee`**: We set this to the `poolFee` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. +- **`sqrtPriceLimitX96`**: We set this to 0 because we do not want to specify a limit on the price. + +## Executing the Single-hop Swap + +On line 29, we assign the output of the `exactInputSingle` function to the `amountOut` variable. This function executes the single-hop swap and returns the amount of the output token that was received. diff --git a/locales/tr/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md b/locales/tr/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md new file mode 100644 index 000000000..7883b4718 --- /dev/null +++ b/locales/tr/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md @@ -0,0 +1,30 @@ +In this section, we'll delve into the `swapExactInputMultiHop` function in the `UniswapV3SwapExamples` contract. This function enables more complex token swaps by allowing users to specify a custom path through multiple liquidity pools. + +If for example, a user wants to swap token A for token D, but there is no direct liquidity pool for A and D, the user can specify a path through multiple tokens. For example, the user can swap A for B, then B for C, and finally C for D. This is of course automatically done by the Uniswap V3 Swap contract. + +### Parameters and Return Value + +On line 32, we define a function called `swapExactInputMultiHop`. This function executes a multi-hop swap. It takes the following parameters: + +- **`bytes calldata path`**: Encoded information about the swap path (i.e., which tokens to swap through). +- **`address tokenIn`**: The address of the token being sent. +- **`uint amountIn`**: The amount of the input token being sent. + +It returns a `uint` called `amountOut`, which is the amount of the output token that was received. + +### Function Body + +In the function body, we first transfer the input token from the sender to our contract, line 38. +Then, we approve the Uniswap Swap router to spend the input token on our behalf, line 41. + +On line 43, we create an instance of the `ExactInputParams` struct, line 73. This struct contains the parameters that are required for our `exactInput` function on line 81, which will execute the multi-hop swap. + +We set the parameters of the struct as follows: + +- **`path`**: We set this to the `path` parameter of our function. +- **`recipient`**: We set this to the sender of the transaction. +- **`deadline`**: We set this to the current timestamp. We do this because we want the transaction to be processed as soon as possible. +- **`amountIn`**: We set this to the `amountIn` parameter of our function. +- **`amountOutMinimum`**: We set this to 0 because we do not want to specify a minimum amount of the output token that we are willing to accept. + +On line 53, we execute the multi-hop swap by calling the `exactInput` function. This function returns the amount of the output token that was received. diff --git a/locales/tr/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md b/locales/tr/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md new file mode 100644 index 000000000..b3cec34e9 --- /dev/null +++ b/locales/tr/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md @@ -0,0 +1,52 @@ +In this section, we'll explore the `IERC20` interface, a standard interface for interacting with ERC-20 tokens and the `IWETH` interface, a standard interface for interacting with wrapped Ether (WETH). Understanding these interfaces is crucial as it is used in the Uniswap V3 Swap contract to handle token transfers and approvals. + +You can find a "Solidity ERC20 Token Course" for beginners in LearnEth to understand the ERC20 token standard in more detail. + +## IERC20 Interface + +On line 80, we define the `IERC20` interface. This interface defines a standard set of functions that ERC-20 tokens must implement. Let's examine the key functions within this interface: + +### 1. totalSupply + +On line 81, we define the `totalSupply` function. This function returns the total supply of the token. + +### 2. balanceOf + +On line 83, we define the `balanceOf` function. This function returns the balance of the specified address. + +### 3. transfer + +On line 85, we define the `transfer` function. This function transfers tokens from the sender to the specified recipient. + +### 4. allowance + +On line 87, we define the `allowance` function. This function returns the amount of tokens that the spender is allowed to spend on behalf of the owner. + +### 5. approve + +On line 89, we define the `approve` function. When called, this function approves a spender to spend the specified amount of tokens on behalf of the sender. + +### 6. transferFrom + +On line 91, we define the `transferFrom` function. This function transfers tokens from the specified sender to the recipient. The function can only be called by the spender if the spender is allowed to spend the specified amount of tokens on behalf of the sender. + +### 7. Events + +On lines 102-103, we define the `Transfer` and `Approval` events. These events are emitted when the `transfer` and `approve` functions are called, respectively. + +## IWETH Interface + +On line 106, we define the `IWETH` interface. This interface extends the `IERC20` interface and defines two additional functions: + +### 1. deposit + +On line 107, we define the `deposit` function. This function deposits ETH into the contract and returns the equivalent amount of WETH. This function is used to wrap ETH into WETH. +We need to wrap ETH into WETH because the Uniswap V3 Swap contract only supports ERC-20 tokens. + +### 2. withdraw + +On line 109, we define the `withdraw` function. This function withdraws the specified amount of WETH from the contract and returns the equivalent amount of ETH. This function is used to unwrap WETH into ETH. + +## Conclusion + +In this tutorial, we explored the Uniswap V3 Swap contract. To get a full sense of how Uniswap works, try making some swaps on the Uniswap DApp and go to the Uniswap docs. diff --git a/locales/tr/Uniswap-Tutorial/README.md b/locales/tr/Uniswap-Tutorial/README.md new file mode 100644 index 000000000..cf66c5582 --- /dev/null +++ b/locales/tr/Uniswap-Tutorial/README.md @@ -0,0 +1,5 @@ +# Uniswap Swap Course + +Review the code of the Uniswap V3 Swap contract for performing token swaps. + +Developed by the p2p learning platform https://dacade.org. diff --git a/locales/tr/Uniswap-Tutorial/config.yml b/locales/tr/Uniswap-Tutorial/config.yml new file mode 100644 index 000000000..f49f02abc --- /dev/null +++ b/locales/tr/Uniswap-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: uniswapSwapCourse +name: Uniswap Swap Course +summary: Go through the Solidity code of the Uniswap V3 Swap contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - Uniswap +steps: + - + name: 1. Introduction + path: 1-introduction-to-uniswap + - + name: 2. Routers, Interfaces, and Structs + path: 2-router-interfaces-and-structs + - + name: 3. Single Hop Swaps + path: 3-single-hop-swaps + - + name: 4. Multi-Hop Swaps + path: 4-multi-hop-swaps + - + name: 5. Erc20 and Weth Interfaces + path: 5-erc20-weth-interfaces diff --git a/locales/tr/Web3Client/1_Using_Web3/Running_a_script.md b/locales/tr/Web3Client/1_Using_Web3/Running_a_script.md new file mode 100644 index 000000000..3b7b23332 --- /dev/null +++ b/locales/tr/Web3Client/1_Using_Web3/Running_a_script.md @@ -0,0 +1,24 @@ +## Querying the Blockchain + +In this tutorial, we'll run a script that queries the blockchain using a JavaScript library. + +This means that instead of using the Remix GUI or a block explorer like Etherscan, we'll use a script in the editor and will run it from the terminal. + +The JS libraries that are used the most for interacting with the blockchain are web3.js & ethers.js. + +Let's begin with a simple web3.js example, queryBlockNum.js. + +The script's call to web3.js is wrapped in a self-executing async function that contains a try/catch block. + +We'll query the current blocknumber with: +`let blockNumber = await web3.eth.getBlockNumber()` + +Note that the object `web3` is injected by Remix. For more info on web3.js, check their docs, https://web3js.readthedocs.io. + +To use web3.js or ethers.js, you need to select the **Injected Web3** or **Web3 Provider** environment in the **Deploy & Run** module. Scripts don't currently work with the JSVM. **If you try, you'll get an error.** + +So for this example choose **Injected Web3** in the Deploy & Run module and have Metamask installed. + +From the terminal, execute `remix.execute()`. This command will execute the current JavaScript file with the line `let blockNumber = await web3.eth.getBlockNumber()`. + +In the console, you should see the current block number of the chain that metamask is connected to. diff --git a/locales/tr/Web3Client/2_Querying_a_Contract/queryContract.md b/locales/tr/Web3Client/2_Querying_a_Contract/queryContract.md new file mode 100644 index 000000000..461c98244 --- /dev/null +++ b/locales/tr/Web3Client/2_Querying_a_Contract/queryContract.md @@ -0,0 +1,23 @@ +Now that we know how to query simple data, let's try a more complex query. + +This is a contract deployed to the mainnet - at this address: https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code + +We are going to query the contract to find the name of it's token. + +The **name** variable is a state variable of the contract. + +To access this **mainnet** contract, we need to do some setup. + +1. Switch to the mainnet in metamask. +2. You'll probably need to refresh Remix. +3. As a result of the refresh, you may need to reload this tutorial too. +4. Go to Deploy & Run and switch to **Injected Web3**. + +**Using Web3** +In the script, queryContract.js, we need to instantiate a new instance of web3.eth.Contract object. For this we need to grab the contract's ABI and its address. The source code & ABI is available in etherscan because the contract's developer intentionally published it. + +In etherscan, we can see that its name is **TetherToken**. Scrolling down to the TetherToken contract in the source code section of etherscan, we can see the state variables for the contract - the first of which is named **name**. + +There are a few syntactic hoops to jump through to return the value of the state variable. + +- To call the autogenerated getter function of the public state variable, you need to both treat the variable as a function (by adding parentheses) and also to tack on a call(). diff --git a/locales/tr/Web3Client/README.md b/locales/tr/Web3Client/README.md new file mode 100644 index 000000000..a319f312f --- /dev/null +++ b/locales/tr/Web3Client/README.md @@ -0,0 +1 @@ +This workshop is about using the web3.js to interact with a contract and more generally to the blockchain. diff --git a/locales/tr/Web3Client/config.yml b/locales/tr/Web3Client/config.yml new file mode 100644 index 000000000..07cb1760c --- /dev/null +++ b/locales/tr/Web3Client/config.yml @@ -0,0 +1,9 @@ +--- +id: useofweb3js +name: Basic use of web3.js +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 2 +tags: + - JS + - Remix + - Web3 diff --git a/locales/zh/Basics/README.md b/locales/zh/Basics/README.md new file mode 100644 index 000000000..f1948d90b --- /dev/null +++ b/locales/zh/Basics/README.md @@ -0,0 +1,3 @@ +## 加载、编译、部署 + +这个初学者级别的教程介绍了 Remix 的界面和以太坊中使用的概念。 diff --git a/locales/zh/Basics/config.yml b/locales/zh/Basics/config.yml new file mode 100644 index 000000000..8c160b545 --- /dev/null +++ b/locales/zh/Basics/config.yml @@ -0,0 +1,26 @@ +--- +id: basics +name: Basics of Remix +summary: A typical workflow in Remix +level: 1 +tags: + - Remix +steps: + - + name: Intro to the Interface + path: interface_introduction + - + name: Intro to Workspaces + path: workspaces + - + name: Loading & Compiling + path: load_and_compile + - + name: Deploying to the Remix VM + path: deploy_to_the_remixvm + - + name: Interacting with Functions + path: interacting + - + name: Deploying to Public Networks + path: deploy_injected diff --git a/locales/zh/Basics/deploy_injected/README.md b/locales/zh/Basics/deploy_injected/README.md new file mode 100644 index 000000000..8fce024a3 --- /dev/null +++ b/locales/zh/Basics/deploy_injected/README.md @@ -0,0 +1,21 @@ +1. 如果您没有像 **MetaMask** 这样的浏览器钱包,请立即下载并安装一个。 + +2. 在浏览器中点击MetaMask图标。 登录并选择 Ephemery 测试网络。 您可能需要更新钱包的设置,以便可以看到**测试网络**。 或者,您可以转到 Remix 的 Deploy & Run transation 模块,然后在环境部分中选择 Ephemery。 + +3. 为公共测试网络获取测试 ETH 通常很烦人。 Ephemery 是一个每月更新一次的公共网络,因此获得测试 ETH 应该很容易。 以下是一些Ephemery 水龙头的链接。 + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/testnet.png) + +Sepolia 是另一个流行的测试网,未刷新,因此部署将持续存在,但 Sepolia 水龙头更难使用。 + +在您的浏览器钱包中,确保您没有选择主网或任何需要花费真实 ETH 的网络。 在 Deploy & Run 模块中的“环境”选择框下方,您将看到一个带有网络 ID 的图标,对于流行的链来说,还有其名称。 下面的例子是Sepolia。 + +![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_injected/images/sepolia.png) + +5. 确保你看到 2_Owner.sol 作为 **CONTRACT** 选择框的选项,然后点击 **Deploy** 按钮。 + +如果**CONTRACT** 选择框为空,则需要重新编译2_Owner。确保它是**编辑器**中的选中文件,然后转到**Solidity Compiler**进行编译。 + +6. 点击`Deploy`按钮后,您将看到浏览器钱包弹出窗口,要求您支付交易费用。 如果您有适合该链的 ETH ,请批准该交易。 检查终端中的打印输出。 一旦区块通过验证,**部署的实例**将出现在 Deploy & Run 的底部 + +通过这个教程, 你已经学会了如何打开、编译、部署和与Remix IDE中的智能合约进行交互。 diff --git a/locales/zh/Basics/deploy_to_the_remixvm/README.md b/locales/zh/Basics/deploy_to_the_remixvm/README.md new file mode 100644 index 000000000..8b0e05649 --- /dev/null +++ b/locales/zh/Basics/deploy_to_the_remixvm/README.md @@ -0,0 +1,15 @@ +在前一章中,我们编写了一个合约 - 也就是说Solidity代码已经被转换成了以太坊虚拟机(EVM)字节码片段。 + +现在我们将把该代码放到测试区块链上。 + +1. 点击“部署和运行”图标![deploy & run icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/deploy_to_the_remixvm/images/run.png "deploy & run icon")。 + +2. 从环境下拉菜单中选择**Remix VM**。 + +3. 单击 Deploy 按钮(或展开视图中的 transact 按钮)。 + +4. 您已将编译后的合约部署到 Remix VM - 一个在浏览器窗口内运行的模拟区块链。 Remix VM 是简单、快速的测试链。 这不太现实,因为您不需要批准每笔交易。 + +5. 检查终端以查看此部署交易的详细信息。 + +您也可以使用 Remix 部署到其他公共EVM 链。 为此,您需要连接到不同的**环境** - 例如 Injected Provider 。 Injected Provider 将 Remix 连接到浏览器钱包(如 MetaMask 或类似的)。 我们将在本教程结束时尝试部署到公共网络。 但在此之前,我们将介绍如何与已部署合约的函数进行交互。 diff --git a/locales/zh/Basics/interacting/README.md b/locales/zh/Basics/interacting/README.md new file mode 100644 index 000000000..41bcdb735 --- /dev/null +++ b/locales/zh/Basics/interacting/README.md @@ -0,0 +1,19 @@ +## 访问已部署合约中的函数 + +1. 合约部署成功后,它将显示在 Deploy and Run 插件的底部。 单击插入符号打开合约 - 然后插入符号会指向下方。 + ![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/instance.png "deployed contract") + +2. 这个合约有两个函数。 要单独输入参数,请单击changeOwner右侧的插入符号(下面以红色框出)。 在展开视图中,每个参数都有自己的输入框。 + +![deploy contract](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/deployed_open2.png "deployed contract") + +如果此合约导入了其他合约,则导入的合约功能也会在此处显示。 在某些时候,尝试使用 ERC20 合约来了解它的所有功能。 + +3. 带有蓝色按钮的功能要么是**pure**函数,要么是**view**函数。 这意味着它们只是读取属性或返回值。 换句话说,它们不保存任何东西 - 因此它们是免费的(不需要消耗 gas)。 其他颜色的功能 - 通常为橙色(取决于 Remix 主题)会消耗 gas,因为它们正在保存信息。 它们会创建**交易**。 + +4. 2_Owner.sol 没有**payable**函数。 如果有,则按钮将变成红色。 可支付函数允许您向该函数发送以太币。 要使用可支付函数发送 ETH,请在 Deploy & Run 模块顶部的 **value** 字段中输入您想要发送的金额。 + +5. 在 Remix VM 中,您无需批准交易即可进行操作。 当使用更真实的测试环境或使用主网时 - 您需要批准交易才能使其通过。 批准交易需要花费 gas。 + +6. 选择公共网络不是在 Remix 中完成,而是在你的浏览器钱包中。 环境标题右侧有一个插头图标,链接到 chainlist.org,在那里可以获取与所需链互动所需规格。 + ![chainlist](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interacting/images/chainlist.png "chainlist") diff --git a/locales/zh/Basics/interface_introduction/README.md b/locales/zh/Basics/interface_introduction/README.md new file mode 100644 index 000000000..bf49bfc00 --- /dev/null +++ b/locales/zh/Basics/interface_introduction/README.md @@ -0,0 +1,15 @@ +## Remix由四个面板组成 + +![Remix layout](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/a-layout1c.png "Remix layout") + +- 大多数插件出现在**侧边栏**。 +- 编辑代码发生在**主面板**的选项卡中。 +- 交易和其他操作的结果在**终端**可见。 +- 在**图标面板**中切换插件。 +- 要使一个面板变大,请拖动其边框。 + +尝试点击 **图标面板** 中的 **Solidity Compiler** 图标 ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/solidity-icon.png) 。 然后点击 **Deploy & Run** 图标 ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/deploy-run.png). 然后点击这个图标 ![](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/learneth.png) 回到 **LearnEth** 。 + +在Remix**主面板**上,确保您看到**Home**选项卡。 **Home**选项卡有很多有用的链接。 要导航到那里,请单击 **主面板** 中的 **Home** 选项卡或单击这个 Remix 图标 ![Remix icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/remix-logo.png "Remix icon")。 + +- 查看 **插件管理器** 中的所有插件。 点击 Remix 左下角的这个图标 ![plugin manager](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/interface_introduction/images/plugin1.png "Plugin Manager icon") 。 diff --git a/locales/zh/Basics/load_and_compile/README.md b/locales/zh/Basics/load_and_compile/README.md new file mode 100644 index 000000000..72fb6aecc --- /dev/null +++ b/locales/zh/Basics/load_and_compile/README.md @@ -0,0 +1,20 @@ +让我们将文件从文件资源管理器加载到编辑器中。 + +1. 在图标面板中,单击文件浏览器的图标![file explorer icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/files1.png "file explorer icon")。 + +2. 请确保您在 **default_workspace** 中。 + +![default workspace](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/default_workspace_open.png) + +3. 打开 contracts 文件夹,并点击其中的 **2_Owner.sol**。 点击它。 该文件将出现在主面板的一个选项卡中。 + +4. 在图标面板中,单击**Solidity 编译器**![solidity compiler icon](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/solidity1.png "solidity compiler icon")。 Solidity 编译器现在应该位于侧边栏中。 + +5. 点击编译按钮。 + ![compile 2\_owner](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/load_and_compile/images/compile2owner.png "compile 2_Owner") + +6. 也可以通过按**CTRL + S**来触发编译过程。 + +当文件正在编译时,旋转指示器会转动。 + +**注意:**当编译器本身正在加载时,旋转指示器也会转动。 要选择**不同版本的Solidity**,请前往插件顶部的下拉框。 diff --git a/locales/zh/Basics/workspaces/README.md b/locales/zh/Basics/workspaces/README.md new file mode 100644 index 000000000..a5c9161cd --- /dev/null +++ b/locales/zh/Basics/workspaces/README.md @@ -0,0 +1,23 @@ +## 工作区用于分离您的项目 + +如果您是第一次使用 Remix,文件资源管理器中会加载一个名为**default_workspace**的工作区。 + +在文件资源管理器顶部,单击\*\*+\*\*图标以创建新的工作区。 + +**default_workspace** 的contracts 文件夹中有三个Solidity (.sol) 文件。 Remix has a number of other templates. 当您加载模板时,它会进入工作区。 要在工作区之间切换,请使用文件资源管理器顶部的选择框。 + +当单击展开菜单(位于文件资源管理器右上角)时,会显示出工作区管理工具。 + +但工作区不仅仅适用于模板。 将克隆仓库到 Remix 时,文件将被放入工作区中。 + +让我们创建一个新的工作区 + +1. 在文件资源管理器顶部,单击汉堡包图标(3 条水平线)。 仔细阅读此菜单中的命令和工具。 + +2. 选择 **+ 创建** (第一个选项)。 + +3. 在弹出的对话框中,选择其中一个模板。 + +![hamburger](https://raw.githubusercontent.com/ethereum/remix-workshops/master/Basics/workspaces/images/workspace-man.png "hamburger") + +请注意,在此弹出菜单中,您可以克隆一个repo。 请注意,在此弹出菜单中,您可以克隆一个repo。Git repo的管理发生在 DGit 插件中。您还可以使用工作流程选项创建 Github 操作。 You can also create Github actions with the three workflow choices in the popup menu. diff --git a/locales/zh/CircomHashChecker/README.md b/locales/zh/CircomHashChecker/README.md new file mode 100644 index 000000000..20391a668 --- /dev/null +++ b/locales/zh/CircomHashChecker/README.md @@ -0,0 +1,14 @@ +Hash Checker Tutorial + +This tutorial guides you through creating and understanding a Hash Checker circuit using Remix-IDE. You'll learn how to generate the circuit using a template, explore the code, perform a trusted setup, generate proofs, and verify them. This tutorial is suitable for beginners familiar with Circom and Zero-Knowledge Proofs. + +Prerequisites + +``` +Basic understanding of Zero-Knowledge Proofs and Circom. +Familiarity with Remix-IDE. +``` + +Estimated Time + +Approximately 1-2 hours. diff --git a/locales/zh/CircomHashChecker/config.yml b/locales/zh/CircomHashChecker/config.yml new file mode 100644 index 000000000..2c2aae80a --- /dev/null +++ b/locales/zh/CircomHashChecker/config.yml @@ -0,0 +1,35 @@ +id: circom-hash-checker +name: Hash Checker Tutorial +summary: A tutorial on creating and understanding a Hash Checker circuit using Remix-IDE templates, including trusted setup and proof generation. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction to the Hash Checker Circuit + path: step-1 + - + name: Generating the Hash Checker Template in Remix-IDE + path: step-2 + - + name: Exploring calculate_hash.circom + path: step-3 + - + name: Compiling the Circuit + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Compute Witness + path: step-6 + - + name: Generate Proof + path: step-7 + - + name: Exploring the Trusted Setup Script (Optional) + path: step-8 + - + name: Exploring the Proof Generation Script (Optional) + path: step-9 diff --git a/locales/zh/CircomHashChecker/step-1/README.md b/locales/zh/CircomHashChecker/step-1/README.md new file mode 100644 index 000000000..be922e93b --- /dev/null +++ b/locales/zh/CircomHashChecker/step-1/README.md @@ -0,0 +1,8 @@ +In this tutorial, we'll explore the **Hash Checker** circuit, a zero-knowledge proof (ZKP) application using Circom and Remix-IDE. The Hash Checker circuit allows you to prove knowledge of certain inputs that hash to a given value without revealing the inputs themselves. + +### What You'll Learn + +- How to generate a Hash Checker circuit using Remix-IDE's workspace templates. +- Understanding the Circom code for hashing and checking hashes. +- Performing a trusted setup using Groth16. +- Generating zero-knowledge proofs. diff --git a/locales/zh/CircomHashChecker/step-2/README.md b/locales/zh/CircomHashChecker/step-2/README.md new file mode 100644 index 000000000..bc827019e --- /dev/null +++ b/locales/zh/CircomHashChecker/step-2/README.md @@ -0,0 +1,37 @@ +Follow these steps to create the Hash Checker workspace in Remix-IDE. + +### Step 1: Access the Workspace Templates + +1. In the **File Explorer** sidebar, click on the **hamburger menu icon** (three horizontal lines). + + hamburger-menu + +2. Select **"Create Using Template"** from the dropdown. + + create-using-template + +### Step 2: Find the Hash Checker Template + +1. In the main panel, scroll down to the **"Circom ZKP"** section. + + create-zkp-section + +2. Locate the **"Hash Checker"** item. + +### Step 3: Create the Workspace + +1. Click on the **"Create"** button on the Hash Checker item. + + create-hash-checker + +2. In the modal pop-up, provide a **workspace name** (e.g., `hash-checker-workspace`). + + workspace-name-modal + +3. Click **"OK"** to create the template. + +### Result + +- The workspace is created with the necessary files and directories. + + workspace-name-modal diff --git a/locales/zh/CircomHashChecker/step-3/README.md b/locales/zh/CircomHashChecker/step-3/README.md new file mode 100644 index 000000000..b3ac14050 --- /dev/null +++ b/locales/zh/CircomHashChecker/step-3/README.md @@ -0,0 +1,32 @@ +## Exploring `calculate_hash.circom` + +Navigate to the `circuits` directory and open `calculate_hash.circom`. This file contains the Circom code for the Hash Checker circuit. + +### Code Breakdown + +#### Pragma and Includes: + +- `pragma circom 2.0.0;` specifies the Circom version. +- `include "circomlib/circuits/poseidon.circom";` fetch and includes the Poseidon hash function from [CircomLib](https://github.com/iden3/circomlib). + +#### `CalculateHash` Template: + +- Defines inputs `value1`, `value2`, `value3`, `value4`. +- Uses the `Poseidon` hash function to compute a hash of these values.\ +- Outputs `out`, which is the hash. + +#### `HashChecker` Template: + +- Inputs are the same values plus a `hash`. +- Instantiates `CalculateHash` as `calculateSecret`. +- Computes `calculatedHash`. +- Uses `assert(hash == calculatedHash);` to ensure the provided hash matches the calculated hash. + +#### Main Component: + +- `component main {public [hash]} = HashChecker();` +- Specifies that `hash` is a `public` input, while the values are `private`. + +### Purpose + +The circuit allows someone to prove they know `value1`, `value2`, `value3`, and `value4` that hash to a specific `hash` without revealing the values themselves. diff --git a/locales/zh/CircomHashChecker/step-4/README.md b/locales/zh/CircomHashChecker/step-4/README.md new file mode 100644 index 000000000..537c6a241 --- /dev/null +++ b/locales/zh/CircomHashChecker/step-4/README.md @@ -0,0 +1,32 @@ +## Compiling the Circuit + +### Selecting the Compiler Version + +1. Go to the **Circuit Compiler** plugin in the sidebar. +2. Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +### Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +### Compiling the Circuit + +1. Click on the **Compile** button. +2. Wait for the compilation to complete. A success badge will appear if compilation is successful. + +compilation-success + +### Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/zh/CircomHashChecker/step-5/README.md b/locales/zh/CircomHashChecker/step-5/README.md new file mode 100644 index 000000000..c3ea8509b --- /dev/null +++ b/locales/zh/CircomHashChecker/step-5/README.md @@ -0,0 +1,25 @@ +## Performing a Trusted Setup + +1. **Access the Setup and Exports Section**: + +- After successful compilation, the **Setup and Exports** section becomes available in the plugin. + +2. **Select Proving Scheme**: + +- Choose **Groth16** from the **Proving Scheme** dropdown. + +3. **Select Power of Tau File**: + +- Choose the appropriate **Power of Tau** file from the dropdown. If unsure, use the default option. + +4. **Export Verification Key and Contract** (optional): + +- Enable **Export Verification Key** to save the verification key to the File Explorer. +- Enable **Export Verifier Contract** to save the Solidity contract for on-chain verification. + +trusted-setup + +5. **Run the Trusted Setup**: + +- Click on the **Run Setup** button. +- Wait for the process to complete. This may take some time depending on the circuit complexity. diff --git a/locales/zh/CircomHashChecker/step-6/README.md b/locales/zh/CircomHashChecker/step-6/README.md new file mode 100644 index 000000000..03b848f81 --- /dev/null +++ b/locales/zh/CircomHashChecker/step-6/README.md @@ -0,0 +1,28 @@ +## Compute Witness + +1. **Access the Compute Witness Section**: + - After the trusted setup, the **Compute Witness** section becomes available. + +2. **Input Values**: + - You'll see input fields for `value1`, `value2`, `value3`, `value4`, and `hash`. + - Enter values for each input. For example: + - `value1`: `1234` + - `value2`: `2` + - `value3`: `3` + - `value4`: `4` + +3. **Calculate the Hash**: + + - Compute the Poseidon hash of the four values using an external tool or library compatible with the Poseidon hash function. + - For the values above, here is the computed Poseidon hash `16382790289988537028417564277589554649233048801038362947503054340165041751802`. + - Enter the calculated `hash` value in the `hash` input field. + + compute-witness + +4. **Compute the Witness**: + + - Click on the **Compute Witness** button. + - Wait for the process to complete. A success badge will appear if the witness is computed successfully. + - If successful, you'll see `calculate_hash.wtn` created in the `.bin` directory in the file explorer. + + witness-computed diff --git a/locales/zh/CircomHashChecker/step-7/README.md b/locales/zh/CircomHashChecker/step-7/README.md new file mode 100644 index 000000000..e6ae80fea --- /dev/null +++ b/locales/zh/CircomHashChecker/step-7/README.md @@ -0,0 +1,21 @@ +## Generate Proof + +1. **Access the Generate Proof Section**: + - After computing the witness, expand the **Generate Proof** section. + +2. **Configure Proof Generation**: + - **Export Verifier Calldata**: Enable this option if you plan to verify the proof on-chain. + +3. **Generate the Proof**: + + - Click on the **Generate Proof** button. + - Wait for the proof generation to complete. + + generate-proof + +4. **View the Proof**: + + - The proof data will be displayed in the File Explorer. + - **Congratulations!** You've successfully compiled the `Hash Checker` circuit, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + + generate-proof diff --git a/locales/zh/CircomHashChecker/step-8/README.md b/locales/zh/CircomHashChecker/step-8/README.md new file mode 100644 index 000000000..e489a8cab --- /dev/null +++ b/locales/zh/CircomHashChecker/step-8/README.md @@ -0,0 +1,34 @@ +## Understanding `groth16_trusted_setup.ts` + +Navigate to `scripts/groth16/groth16_trusted_setup.ts`. This script performs the trusted setup necessary for generating proofs. + +### Code Breakdown + +#### Circuit Compilation: + +- Uses `remix.call('circuit-compiler', 'generateR1cs', ...)` to generate `R1CS` (Rank-1 Constraint System) from the circuit. + +#### Trusted Setup Steps: + +- `snarkjs.zKey.newZKey`: Initializes the proving key (`zkey_0`). +- `snarkjs.zKey.contribute`: Adds contributions to the proving key (`zkey_1`). +- `snarkjs.zKey.beacon`: Finalizes the proving key (`zkey_final`). + +#### Verification: + +- `snarkjs.zKey.verifyFromR1cs`: Verifies the proving key against the `R1CS` and initial parameters. + +#### Exporting Keys: + +- Exports the verification key to `scripts/groth16/zk/keys/verification_key.json`. +- Exports the final proving key (`scripts/groth16/zk/keys/zkey_final.txt`). + +### Purpose + +- Performs the trusted setup required for the `Groth16` proving system. +- Generates the necessary keys for proof generation and verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"setup done."` logged in the terminal. diff --git a/locales/zh/CircomHashChecker/step-9/README.md b/locales/zh/CircomHashChecker/step-9/README.md new file mode 100644 index 000000000..653d5ced1 --- /dev/null +++ b/locales/zh/CircomHashChecker/step-9/README.md @@ -0,0 +1,37 @@ +## Understanding `groth16_zkproof.ts` + +Navigate to `scripts/groth16/groth16_zkproof.ts`. This script generates the zero-knowledge proof and prepares it for verification. + +### Code Overview + +#### Loading Files: + +- Reads the R1CS and WASM files generated from the circuit. +- Loads the final proving key (`zkey_final`) and verification key (`vKey`). + +#### Defining Inputs: + +- Sets the private values (`value1`, `value2`, `value3`, `value4`). +- Computes the `hash` using Poseidon from [CircomLib](https://github.com/iden3/circomlib). + +#### Witness Calculation and Proof Generation: + +- Calculates the witness (`wtns`). +- Checks the witness against the `R1CS`. +- Generates the proof using `Groth16`. +- Verifies the proof. + +#### Exporting Verifier Contract and Inputs: + +- Generates a Solidity verifier contract. +- Exports the proof inputs to `input.json`. + +### Purpose + +- Generates a zero-knowledge proof that the prover knows values hashing to a specific hash. +- Prepares the verifier contract and inputs for on-chain verification. + +### Execute the Script + +- Click the play button in the editor, or right-click the file and select "Run". +- Wait for the script to complete and `"zk proof validity"` logged in the terminal. diff --git a/locales/zh/CircomIntro/README.md b/locales/zh/CircomIntro/README.md new file mode 100644 index 000000000..c58b2daec --- /dev/null +++ b/locales/zh/CircomIntro/README.md @@ -0,0 +1,21 @@ +Intro to Circom + +This is an introduction to Circom. You'll learn how to write, compile, and test arithmetic circuits in Circom. We'll go over how to do this within Remix-IDE. + +Tutorial Overview + +``` +Step 1: Introduction +Step 2: Setting Up Remix-IDE and Installing the Circuit-Compiler Plugin +Step 3: Writing Your First Circom Circuit +Step 4: Compiling the Circuit Using the Plugin +Step 5: Performing a Trusted Setup +Step 6: Computing the Witness +Step 7: Generating the Proof +``` + +Prerequisites: + +``` +Basic understanding of cryptography and zero-knowledge proofs is helpful but not required. +``` diff --git a/locales/zh/CircomIntro/config.yml b/locales/zh/CircomIntro/config.yml new file mode 100644 index 000000000..d6dfdca46 --- /dev/null +++ b/locales/zh/CircomIntro/config.yml @@ -0,0 +1,29 @@ +id: circom-intro +name: Intro to Circom +summary: A intro to using Circom for creating arithmetic circuits. +level: 1 +tags: + - Circom + - Remix-IDE +steps: + - + name: Introduction + path: step-1 + - + name: Installing the Circuit-Compiler + path: step-2 + - + name: Writing Your First Circom Circuit + path: step-3 + - + name: Compiling the Circuit Using the Plugin + path: step-4 + - + name: Performing a Trusted Setup + path: step-5 + - + name: Computing the Witness + path: step-6 + - + name: Generating the Proof + path: step-7 diff --git a/locales/zh/CircomIntro/step-1/README.md b/locales/zh/CircomIntro/step-1/README.md new file mode 100644 index 000000000..0766ce6f4 --- /dev/null +++ b/locales/zh/CircomIntro/step-1/README.md @@ -0,0 +1,13 @@ +Welcome to this beginner-level tutorial on Circom using Remix. In this tutorial, you'll learn the basics of Circom, a domain-specific language used for creating arithmetic circuits. + +**What is Circom?** + +Circom is a language designed for writing arithmetic circuits that can be used in zero-knowledge proofs, particularly zk-SNARKs. It allows developers to define complex mathematical circuits that can prove knowledge of certain data without revealing it. + +**Why Use Remix-IDE for Circom?** + +- **Ease of Use:** Remix-IDE provides a user-friendly interface that simplifies the development process. +- **Integrated Tools:** With plugins like `circuit-compiler`, you can compile Circom code, perform trusted setups, compute witnesses, and generate proofs all within the same environment. +- **No Installation Required:** As a web-based IDE, you can start coding immediately without setting up a local development environment. + +In the next steps, we'll guide you through setting up Remix-IDE for Circom development and help you write your first circuit. diff --git a/locales/zh/CircomIntro/step-2/README.md b/locales/zh/CircomIntro/step-2/README.md new file mode 100644 index 000000000..4b228c298 --- /dev/null +++ b/locales/zh/CircomIntro/step-2/README.md @@ -0,0 +1,25 @@ +In this step, we'll set up Remix for Circom development by activating the `Circom ZKP compiler` plugin. + +## Activating the Circom ZKP compiler + +1. At the bottom of the icon panel on the left of the screen, click on the **Plugin Manager** (the plug icon). + 2.In the search bar, type **Circom**. +2. Find the **Circuit Compiler** plugin in the list and click on the **Activate** button. +3. The plugin will now appear in your sidebar. + +install-plugin + +## The Circom Compiler Interface + +- **Compiler Version Dropdown:** Select the Circom compiler version you wish to use. +- **Auto Compile Checkbox:** Enable this to automatically compile your circuit whenever you make changes. +- **Hide Warnings Checkbox:** Enable this to suppress compiler warnings. +- **Advanced Configuration:** Click to expand options for selecting the prime field (e.g., BN128, BLS12381). + +compiler-interface + +With the plugin installed, you're now ready to start writing Circom code in Remix-IDE. + +**Note:** Make sure your internet connection is stable, as Remix-IDE is a web-based tool. + +In the next step, we'll write our first Circom circuit. diff --git a/locales/zh/CircomIntro/step-3/README.md b/locales/zh/CircomIntro/step-3/README.md new file mode 100644 index 000000000..6424668f6 --- /dev/null +++ b/locales/zh/CircomIntro/step-3/README.md @@ -0,0 +1,38 @@ +Let's write a simple Circom circuit. + +## Creating a New Circuit File + +1. In the **File Explorer** on the left sidebar, click on the **Create New File** icon. +2. Name your file `multiplier.circom` and press **Enter**. + +create-new-file + +## Writing the Circuit + +Open `multiplier.circom` and add the following code: + +```circom +pragma circom 2.0.0; + +template Multiplier() { + signal input a; + signal input b; + signal output c; + + c <== a * b; +} + +component main = Multiplier(); +``` + +## Explanation: + +- template `Multiplier()`: Defines a new circuit template called Multiplier. +- `signal input a;` and `signal input b;`: Declare input signals a and b. +- `signal output c;`: Declare an output signal c. +- `c <== a * b;`: Constrain c to be the product of a and b. +- `component main = Multiplier();`: Instantiates the Multiplier circuit as main, which is required for the compiler. + +### NB: + +Signals are values in a cryptographic circuit that are strictly determined by the circuit's equations and constraints. Think of a signal as a value that must follow specific mathematical rules defined by the circuit—once set, it can't be changed arbitrarily. In regular programming, variables are flexible and can be updated or reassigned as needed, whereas, signals can't be altered freely. diff --git a/locales/zh/CircomIntro/step-4/README.md b/locales/zh/CircomIntro/step-4/README.md new file mode 100644 index 000000000..ad3f2a089 --- /dev/null +++ b/locales/zh/CircomIntro/step-4/README.md @@ -0,0 +1,34 @@ +With your `multiplier.circom` circuit ready, let's compile it using the Circuit Compiler plugin. + +## Selecting the Compiler Version + +Choose the desired **Compiler Version** from the dropdown menu. For this tutorial, select the latest stable version. + +select-compiler-version + +## Configuring Compilation Options + +- **Auto Compile:** You can enable this option to automatically compile your circuit whenever you save changes. +- **Hide Warnings:** Enable this to suppress compiler warnings if any. +- **Advanced Configuration:** + - Click to expand. + - Select the **Prime Field**. For most cases, `BN128` is sufficient. + +advanced-configuration + +## Compiling the Circuit + +1. Click on the **Compile** button. +2. The compiler will process your circuit. +3. If successful, you'll see a compilation success message. + +compilation-success + +**Note:** If there are any errors, they will be displayed in the console. Check your code for typos or syntax errors. + +## Understanding the Compilation Output + +- After successful compilation, the **Setup and Exports** section becomes visible. +- You can proceed to the next step to perform a trusted setup. + +In the next step, we'll perform a trusted setup using the compiled circuit. diff --git a/locales/zh/CircomIntro/step-5/README.md b/locales/zh/CircomIntro/step-5/README.md new file mode 100644 index 000000000..8e8496bbd --- /dev/null +++ b/locales/zh/CircomIntro/step-5/README.md @@ -0,0 +1,26 @@ +After compiling your circuit, you need to perform a trusted setup to generate proving and verification keys. + +## Understanding Trusted Setup + +- **Trusted Setup:** A process required for zk-SNARKs to generate the necessary parameters for proof generation and verification. +- You can choose between different protocols like **Groth16** and **Plonk**. + +## Performing the Trusted Setup + +1. In the **Setup and Exports** section, select the **Proving Scheme**: + - Choose between **Groth16** or **Plonk**. We'll use **Groth16** for this tutorial. + +2. Choose the appropriate **Power of Tau** file from the dropdown. This file is necessary for the trusted setup. + - If unsure, select the default option. + +3. Click on the **Setup** button to start the trusted setup process. + +4. You can enable **Export Verification Key** to get the verification parameters. + +5. You can enable **Export Verification Contract** if you intend to verify proofs on-chain. + +trusted-setup + +**Note:** The trusted setup may take some time, depending on the complexity of your circuit. + +In the next step, we'll compute the witness for our circuit. diff --git a/locales/zh/CircomIntro/step-6/README.md b/locales/zh/CircomIntro/step-6/README.md new file mode 100644 index 000000000..e13d33d32 --- /dev/null +++ b/locales/zh/CircomIntro/step-6/README.md @@ -0,0 +1,27 @@ +With the trusted setup complete, you can now compute the witness for your circuit based on specific inputs. + +## What is a Witness? + +- A **Witness** is a set of values that satisfy all the constraints of your circuit. It includes all the intermediate numbers and results that satisfy the circuit's rules. The witness is used in zero-knowledge proofs to demonstrate that you know a valid solution to the problem without actually showing the solution itself. This allows others to verify that you did everything correctly while keeping your specific numbers and calculations private. +- It is essential for generating a proof. + +## Inputting Values + +1. In the **Compute Witness** section, you'll see input fields dynamically generated based on your circuit's inputs. +2. Enter values for `a` and `b`. For example: + - `a = 3` + - `b = 4` + +compute-witness + +## Computing the Witness + +1. After entering the inputs, click on the **Compute Witness** button. +2. The plugin will compute the witness based on your inputs. +3. If successful, you'll see `multiplier.wtn` created in the `.bin` directory in the file explorer. + +witness-computed + +**Note:** If there are any errors, ensure that your inputs are valid and satisfy the circuit's constraints. + +In the next step, we'll generate a proof using the computed witness. diff --git a/locales/zh/CircomIntro/step-7/README.md b/locales/zh/CircomIntro/step-7/README.md new file mode 100644 index 000000000..f5cf332a9 --- /dev/null +++ b/locales/zh/CircomIntro/step-7/README.md @@ -0,0 +1,31 @@ +With the witness computed, the final step is to generate a proof that can be verified by others. + +## Generating the Proof + +1. In the **Generate Proof** section, you have the option to **Export Verifier Calldata**. + - Enable the **Export Verifier Calldata** checkbox if you plan to verify the proof on-chain. +2. Click on the **Generate Proof** button. + +generate-proof + +## Understanding the Output + +- After generating the proof, the plugin will display the proof data. +- If you enabled **Export Verifier Calldata**, it will also provide the calldata needed for on-chain verification. + +proof-generated + +## Next Steps + +- **Verification:** You can use the verification key or contract exported earlier to verify the proof. +- **On-Chain Verification:** If you're familiar with smart contracts, you can deploy the verification contract and use the calldata to perform on-chain verification. + +**Congratulations!** You've successfully written a Circom circuit, compiled it, performed a trusted setup, computed a witness, and generated a proof using Remix-IDE. + +## Additional Resources + +- [Circom Documentation](https://docs.circom.io/) +- [Remix-IDE Documentation](https://remix-ide.readthedocs.io/) +- [Zero-Knowledge Proofs Explained](https://zkproof.org/) + +Feel free to experiment with more complex circuits and explore the capabilities of Circom and Remix-IDE further. diff --git a/locales/zh/DeployWithLibraries/1_Writing_a_Library/step1.md b/locales/zh/DeployWithLibraries/1_Writing_a_Library/step1.md new file mode 100644 index 000000000..1a6406e2e --- /dev/null +++ b/locales/zh/DeployWithLibraries/1_Writing_a_Library/step1.md @@ -0,0 +1,17 @@ +一个库看起来像是一个合约,但使用关键字library。 + +库通常是一组有用的函数,部署在区块链上,任何合约都可以使用。因为该库已经部署了,所以它节省了许多使用它的合约的部署成本。 因为该库已经部署了,所以它节省了许多使用它的合约的部署成本。 + +在下面的合约中: + +- 创建一个名为`LibraryForTest`的库。 + +将库放置在与另一个合约相同的文件中。因此,请将该库放置在合约下方。 因此,请将该库放置在合约下方。 + +这个库应该有一个名为`getFromLib`的方法,返回`3`。 + +- 更新`test`合约中的`get`方法以使用`LibraryForTest`库。函数`get`应返回从`getFromLib`接收到的值。 函数`get`应返回从`getFromLib`接收到的值。 + +--------- + +您可以在Solidity 文档 中找到更多关于libraries信息。 diff --git a/locales/zh/DeployWithLibraries/2_Generate_Metadata/step2.md b/locales/zh/DeployWithLibraries/2_Generate_Metadata/step2.md new file mode 100644 index 000000000..d98dc0dd2 --- /dev/null +++ b/locales/zh/DeployWithLibraries/2_Generate_Metadata/step2.md @@ -0,0 +1,38 @@ +## 部署库 + +上一章的**库**与**合约**在同一个文件中。但是它们不会一起部署,而且将拥有不同的地址。 但是它们不会一起部署,而且将拥有不同的地址。 + +为了使用库,调用合约必须具有该库的地址。 + +但是,在Solidity代码中并没有直接指定库的地址。 调用合约的编译字节码包含一个**占位符**,库的**地址**将存放在其中。 + +在部署调用合约时,Remix将查找合约元数据以获取库的地址,并更新占位符为该地址。 + +因此,在部署调用某个库的合约之前,您需要生成该合约的元数据文件,并将把使用到的相应库地址放到元数据文件中。 + +合约的元数据是在**编译时**生成的。 + +让我们设置 Remix 来生成元数据文件吧! + +- 点击图标面板上方“设置”![settings](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/settings.png "Settings")图标进入设置模块。 + +![settings module](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_settings.png "Settings Module") + +- 选择第一个选项`Generate contract metadata`. + +# 编译并生成元数据(JSON)文件。 + +1. 打开Solidity编译器 ![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +2. 编译 `2_contractSimpleLibrary.sol`。 + +3. 切换到文件浏览器 ![File Explorer](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_file_explorer.png "File Explorer") + +4. 导航到新创建的JSON文件。 + - 它应该在以下文件夹中: + +**browser/.learneth/DeployWithLibraries/2_Generate_Metadata/artifacts/** + +5. 一个智能合约在编译时就已经生成了其对应的元数据信息。 选择合约新创建的JSON文件。它与示例合约具有相同的名称,但扩展名为**json**:`sample.json`(不要选择库的元数据`contractSimpleLibrary.json`)。 + +在下一步中,我们将对元数据文件进行一些调整。 diff --git a/locales/zh/DeployWithLibraries/3_Edit_Metadata/step3.md b/locales/zh/DeployWithLibraries/3_Edit_Metadata/step3.md new file mode 100644 index 000000000..10cf2ab43 --- /dev/null +++ b/locales/zh/DeployWithLibraries/3_Edit_Metadata/step3.md @@ -0,0 +1,12 @@ +在`sampleContract.json`文件中,`Deploy`属性包含了告知 Remix IDE 特定网络库地址的所有必要信息。 + +- `
` 包含已部署的库的地址。 您需要为每个网络指定这个地址。 +- `autoDeployLib`是一个布尔值,用于告诉 Remix IDE 是否应该在部署合约之前自动部署库。 + +如果 `autoDeployLib` 为 true,则不会使用
,Remix 将自动在部署合约之前部署库。 + +对于此demo的目的 - 我们模拟已经部署了库的情况,因为这是更常见的情况。 + +所以将 VM: - entry 的`autoDeploy`设置为 false。 + +继续下一步。 diff --git a/locales/zh/DeployWithLibraries/4_Linking_and_Deploying/step4.md b/locales/zh/DeployWithLibraries/4_Linking_and_Deploying/step4.md new file mode 100644 index 000000000..609b00ae4 --- /dev/null +++ b/locales/zh/DeployWithLibraries/4_Linking_and_Deploying/step4.md @@ -0,0 +1,24 @@ +切换到`Deploy & Run`模块 +![Run transaction](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/remix_runtransaction.png "Run Transaction") + +- 选择Remix VM环境,并在已编译合约列表中选择`sampleContract`合约。 + +- 点击`Deploy`按钮。 + +终端应该输出类似于`creation of sample errored:
is not a valid address. Please check the provided address is valid.`的信息。这是预期的:**我们将`autoDeployLib`设置为false,因此Remix希望有一个地址而不仅仅是`
`** + +所以我们需要部署库来获取其地址。 + +- 在已编译合同列表中选择`aLib`库并点击`deploy`按钮。 + + ![Choose aLib](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/contract_alib.png "Choose aLib") + +- 单击剪贴板图标以复制库的地址。 + + ![Copy lib1](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/4_Linking_and_Deploying/images/alib_copy.png "Copy") + +- 将其粘贴到sample合约的元数据JSON中。 + +- 重新选择`Run transaction`模块中的`sampleContract`合约并点击deploy按钮。 + +- 现在应该可以成功部署。 diff --git a/locales/zh/DeployWithLibraries/5_Under_The_Hood/step5.md b/locales/zh/DeployWithLibraries/5_Under_The_Hood/step5.md new file mode 100644 index 000000000..7dda7d298 --- /dev/null +++ b/locales/zh/DeployWithLibraries/5_Under_The_Hood/step5.md @@ -0,0 +1,30 @@ +切换到`Solidity compiler`模块 +![Solidity Compiler](https://github.com/ethereum/remix-workshops/raw/master/DeployWithLibraries/2_Generate_Metadata/remix_icon_solidity.png "Solidity Compiler") + +- 在已编译合约列表中选择`sampleContract`合约。 +- 点击`ByteCode`,它应该将以下内容复制到剪贴板: + +``` +{ + "linkReferences": { + "browser/contractSimpleLibrary.sol": { + "lib1": [ + { + "length": 20, + "start": 115 + } + ] + } + }, + "object": "608060405234801561001057600080fd5b5060f68061001f6000396000f3fe6080604052600436106039576000357c0100000000000000000000000000000000000000000000000000000000900480636d4ce63c14603e575b600080fd5b348015604957600080fd5b5060506052565b005b73__$d42d70ba92b626965f4c69b39148e37a33$__63fea24e5f6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160006040518083038186803b15801560b157600080fd5b505af415801560c4573d6000803e3d6000fd5b5050505056fea165627a7a7230582068c9a3a9a5cbfd26cfdab2534abfc926912d9b89eaa14e36c8248b7e7eb0ab090029", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xF6 DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x39 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x3E JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x49 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x50 PUSH1 0x52 JUMP JUMPDEST STOP JUMPDEST PUSH20 0x0 PUSH4 0xFEA24E5F PUSH1 0x40 MLOAD DUP2 PUSH4 0xFFFFFFFF AND PUSH29 0x100000000000000000000000000000000000000000000000000000000 MUL DUP2 MSTORE PUSH1 0x4 ADD PUSH1 0x0 PUSH1 0x40 MLOAD DUP1 DUP4 SUB DUP2 DUP7 DUP1 EXTCODESIZE ISZERO DUP1 ISZERO PUSH1 0xB1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP GAS DELEGATECALL ISZERO DUP1 ISZERO PUSH1 0xC4 JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 PUSH9 0xC9A3A9A5CBFD26CFDA 0xb2 MSTORE8 0x4a 0xbf 0xc9 0x26 SWAP2 0x2d SWAP12 DUP10 0xea LOG1 0x4e CALLDATASIZE 0xc8 0x24 DUP12 PUSH31 0x7EB0AB09002900000000000000000000000000000000000000000000000000 ", + "sourceMap": "63:85:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;63:85:0;;;;;;;" +} +``` + +这基本上是编译器返回的内容: + +- `linkReferences` 描述了合约使用的库。 +- `object` 是编译后的合约(字节码)。 这就是部署并保存到区块链上的内容。 在此示例中,字节码内的值`__$d42d70ba92b626965f4c69b39148e37a33$__`只是库地址的占位符。 对你来说,占位符将位于`__$`和`$__`之间。 + +来自 Remix IDE 的元数据 JSON 告诉 Remix 使用给定地址替换占位符。 diff --git a/locales/zh/DeployWithLibraries/README.md b/locales/zh/DeployWithLibraries/README.md new file mode 100644 index 000000000..e33284543 --- /dev/null +++ b/locales/zh/DeployWithLibraries/README.md @@ -0,0 +1,3 @@ +**库**是不存储状态的已部署合约,由其他合约使用以减小其大小,从而减少部署成本。 + +学习在 Remix 中使用 **Libraries** - 您无需窃窃私语。 diff --git a/locales/zh/DeployWithLibraries/config.yml b/locales/zh/DeployWithLibraries/config.yml new file mode 100644 index 000000000..0816e2346 --- /dev/null +++ b/locales/zh/DeployWithLibraries/config.yml @@ -0,0 +1,8 @@ +--- +id: deploylibraries +name: Deploy with Libraries +summary: Write, Deploy and link a Library to a Contract +level: 3 +tags: + - Remix + - Solidity diff --git a/locales/zh/ERC20TokenCourse/README.md b/locales/zh/ERC20TokenCourse/README.md new file mode 100644 index 000000000..177341d3e --- /dev/null +++ b/locales/zh/ERC20TokenCourse/README.md @@ -0,0 +1,5 @@ +## 交互式 Solidity 代币课程 + +了解并创建 ERC20 代币。 + +由p2p学习平台 https://dacade.org 开发。 diff --git a/locales/zh/ERC20TokenCourse/config.yml b/locales/zh/ERC20TokenCourse/config.yml new file mode 100644 index 000000000..8c12a5213 --- /dev/null +++ b/locales/zh/ERC20TokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: tokenCourse +name: Solidity ERC20 Token Course +summary: Learn how to create your own ERC20 tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - ERC20 +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc20-interface + - + name: 3. Token Creation + path: erc20-token-creation + - + name: 4. Interaction + path: erc20-interaction + - + name: 5. Testnet Deployment + path: erc20-testnet-deployment + - + name: 6. Extensions + path: erc20-extensions diff --git a/locales/zh/ERC20TokenCourse/erc20-extensions/erc20extensions.md b/locales/zh/ERC20TokenCourse/erc20-extensions/erc20extensions.md new file mode 100644 index 000000000..75cfcd2f5 --- /dev/null +++ b/locales/zh/ERC20TokenCourse/erc20-extensions/erc20extensions.md @@ -0,0 +1,33 @@ +ERC20标准仅描述了合约所需和可选的功能,但您可以添加其他功能。 + +在本节中,我们使用OpenZeppelin扩展添加了燃烧和铸造代币的功能,以及暂停合约的能力。 + +当然,您可以编写自己的ERC20代币合约实现或扩展并将其导入到您的合约中。但是OpenZeppelin合约已经通过安全专家审核,是添加所需功能的绝佳方式。 但是OpenZeppelin合约已经通过安全专家审核,是添加所需功能的绝佳方式。 + +### 可铸造 + +mint 函数允许合约创建者在部署后铸造(创建)新的代币(第22行)。 作为输入参数,该函数需要被铸造代币地址和应该被铸造数量。 + +由于mint函数已经成为ERC20合约实现的一部分,因此我们不必从另一个合约中导入它。我们导入的Ownable(第7行),这是一个提供基本访问控制机制以允许所有者具有对特定功能独占访问权的合约模块。 在此合约中 , 我们向`mint`函数(第22行)添加了继承的`onlyOwner`修饰符,并将对此函数的访问限制为所有者才能访问。 我们导入的`Ownable`(第7行),是一个提供基本访问控制机制以允许所有者具有对特定功能独占访问权的合约模块。 在此合约中 , 我们向`mint`函数(第22行) 添加了继承的`onlyOwner`修饰符,并将对此函数的访问限制为所有者才能访问。 + +该合约将从Ownable contract继承额外的函數`owner()`、`transferOwnership()`和`renounceOwnership()`来管理访问权限。 + +### 燃烧 + +通过导入"ERC20Burnable"(第5行)并对其进行继承(第9行),我们的合约允许代币持有人销毁他们的代币以及其`allowance`中的代币。 +通过导入“ERC20Burnable”(第5行)并对其进行继承(第9行),我们的合约允许代币持有人销毁他们的代币以及其`allowance`中的代币。有关更多信息,请查看 ERC20Burnable 合约。 + +### 暂停 + +使用“Pausable”合约模块(第6和9行),所有者可以暂停(第14行)和启用(第18行)合约。 在暂停状态下,无法转移代币,这在紧急情况下可能会有所帮助。 +使用“Pausable”合约模块(第6和9行),所有者可以暂停(第14行)和启用(第18行)合约。在暂停状态下,无法转移代币,这在紧急情况下可能会有所帮助。有关更多信息,请查看Pausable 合约.。 + +请查看Contract Wizard,它使您可以轻松添加其他功能。 + +如果您成功完成了此课程,请尝试学习 NFT 课程作为您旅程的下一步。 + +## ⭐️ 作业 + +1. 尝试在部署后,向一个账户铸造代币。 尝试在部署后,向一个账户铸造代币。调用`totalSupply()`和`balanceOf()`确认正确执行。 +2. 销毁代币,然后调用`totalSupply()`和`balanceOf()`确认正确执行。 +3. 使用所有者账户测试`pause`函数,并尝试使用第二个账户进行转移。交易将无法执行并抛出异常:”Pausable: paused“。 交易将无法执行并抛出异常:"Pausable: paused"。 diff --git a/locales/zh/ERC20TokenCourse/erc20-interaction/er20interaction.md b/locales/zh/ERC20TokenCourse/erc20-interaction/er20interaction.md new file mode 100644 index 000000000..8e08d4026 --- /dev/null +++ b/locales/zh/ERC20TokenCourse/erc20-interaction/er20interaction.md @@ -0,0 +1,88 @@ +在本节中,我们将在浏览器中部署合约并测试其功能。 + +### 1. 部署合约 + +**1.1** 在 Remix IDE 的“Solidity 编译器”模块中编译您的 EduCoin 合约。 + +**1.2** 在“部署和运行交易”模块中,在合约输入字段中选择您的合约“EduCoin”,然后单击“部署”按钮。始终确保在合约选择器输入字段中选择正确的合约。 始终确保在合约选择器输入字段中选择正确的合约。 + +**GIF** 编译和部署: Compile and deploy contract + +### 2. 测试函数 + +展开 IDE 中的代币合约函数。 + +#### 2.1 Decimals + +单击“decimals”按钮以调用`decimals()`函数。它应该返回“18”。 +它应该返回“18”。 + +#### 2.2 Name + +单击“name”按钮调用 name() 函数。 +它应该返回“EduCoin”。 + +#### 2.3 Symbol + +单击“symbol”按钮来调用symbol() 函数。 +它应该返回 “EDC”。 + +#### 2.4 Total supply + +单击“totalSupply” 按钮以调用 `totalSupply()` 函数。它应该返回 1000000000000000000000(1000_10\*\*18)。 +它应该返回 1000000000000000000000 (1000_10\*\*18) 。 + +**GIF** 测试 decimals、name、symbol 和 totalSupply 函数:: Test transfer function + +#### 2.5 Balance of + +**2.5.1** 转到侧边栏的 "ACCOUNT" 部分,并使用旁边的复制图标复制地址。 + +**2.5.2** 将地址粘贴到`balanceOf`函数按钮旁边的输入字段中,然后单击该按钮。 +应该返回 1000000000000000000000 (1000_10\*\*18). +应该返回 1000000000000000000000 (1000_10\*\*18) 。 + +**GIF** 测试 balanceOf 函数: Test transfer function + +#### 2.6 Transfer + +我们将从一个帐户转移 EduCoin 到第二个帐户。 + +**2.6.1** 转到侧边栏的 "ACCOUNT" 部分,并单击显示的地址。这会打开一个下拉菜单,选择显示的第二个地址并复制其地址(帐户 2)。 这会打开一个下拉菜单。 选择显示的第二个地址并复制其地址(帐户 2)。 + +**2.6.2** 打开下拉菜单并再次选择第一个帐户(帐户 1),因为这是我们要使用来进行转账的帐户。 + +**2.6.3** 将地址粘贴到`transfer`函数按钮旁边的输入字段中,输入数字 50000000000000000000,然后单击该按钮。 + +**2.6.4** 如果您检查帐户 1 和 帐户 2 的余额,则两者都应返回金额为500000000000000000000。 + +**GIF** 测试transfer函数: Test transfer function + +#### 2.7 Approve + +现在,我们将允许账号1代表账号2消费代币。 + +**2.7.1** 转到“Account”部分,复制账号1的地址,然后再次设置回账号2。 + +**2.7.2** 在授权功能中,请将 account 1 的地址输入为 spender ,并将金额设置为250000000000000000000。 + +**GIF** 测试 approve 函数: Test approve function + +#### 2.8 Allowance + +在“allowance”按钮旁边,将帐户2的地址作为owner,账户1作为spender;然后单击该按钮。它应该返回1000000000000000000。 +它应该返回1000000000000000000。 + +**GIF** 测试 allowance 函数: Test allowance function + +#### 2.9 TransferFrom + +现在,账号1将从账号2中转移250000000000000000000个代币到自己的账户中。 + +**2.9.1** 在“ACCOUNT”部分选择帐户1。 + +**2.9.2** 在"transferFrom"按钮旁边输入account 2的地址作为发送方和account 1的地址作为接收方,输入金额250000000000000000000 + +**2.9.3** 检查account 2和account 1的余额,应该返回250000000000000000000 和 750000000000000000000。 + +**GIF** 测试 transferFrom 函数: Test transferFrom function diff --git a/locales/zh/ERC20TokenCourse/erc20-interface/erc20interface.md b/locales/zh/ERC20TokenCourse/erc20-interface/erc20interface.md new file mode 100644 index 000000000..f373746d0 --- /dev/null +++ b/locales/zh/ERC20TokenCourse/erc20-interface/erc20interface.md @@ -0,0 +1,76 @@ +ERC20(Ethereum Request for Comments 20)是管理以太坊区块链上同质化代币的标准合约。 + +同质化代币彼此相等,具有相同的价值、行为和权利。 同质化代币通常用作交换媒介,如ETH或BTC等货币。 但它们也可以有其他用途,例如投票权或声誉。 + +如果您想了解更多关于ERC20代币标准的信息,请查看其以太坊改进提案中的规范说明。 + +## 接口 + +为了获得与ERC20代币合约交互所需功能的概述,我们查看一个与ERC20合约交互的接口。 +为了获得与ERC20代币合约交互所需功能的概述,我们查看一个与ERC20合约交互的接口。该接口(第9行)是OpenZeppelin提供的开源合约库的一部分。 + +## ERC20 函数 + +符合ERC20标准的合约必须实现以下六个函数: + +### totalSupply + +函数`totalSupply`(第13行)返回可用代币的总量。 + +### balanceOf + +函数`balanceOf`(第18行)返回地址`account`账户拥有的代币数量。 + +### transfer + +函数`transfer`(第27行)将`amount`数量的代币转移到地址`recipient`。此功能必须发出`Transfer`事件(见下文),并且在发送方没有足够代币进行转移时应引发异常。 +同质化代币彼此相等,具有相同的价值、行为和权利。同质化代币通常用作交换媒介,如ETH或BTC等货币。但它们也可以有其他用途,例如投票权或声誉。 + +### approve + +函数`approve`(第52行)为地址`spender`创建一个许可,以便其可以代表调用该函数的账户转移一定数量的代币。 + +### allowance + +函数`allowance`(第36行)返回地址`spender`被允许为`owner`地址的账户消费的代币数目。 + +### transferFrom + +函数`transferFrom`(第63行)以发送方地址`sender`名义向接收方地址`recipient`转移一定数量的代币。此功能必须触发`Transfer`事件。 +此功能**必须**触发`Transfer`事件。 + +## ERC20 Events + +ERC20合约还必须发出两个事件: + +### Transfer + +当从`indexed from`帐户向`indexed to`帐户转移`value`数量的代币时,必须发出`Transfer`(第71行)事件。 当从`indexed from`帐户向`indexed to`帐户转移`value`数量的代币时,必须发出`Transfer`(第71行)事件。参数`from`和`to`是`indexed`,允许我们使用这些参数作为过滤器搜索这些事件。 + +### Approval + +当`indexed owner`批准`indexed spender`代表其自身转移`value`数量的代币时,必须发出`Approval`(第77行)事件。 + +## ERC20可选函数 + +除了强制性函数和事件外,在ERC20标准中还指定了三个未在此接口中实现的可选函数: + +### name + +`function name() external view returns (string);` + +返回代币的名称。 + +### symbol + +`function symbol() external view returns (string);` + +返回代币的符号。 + +### decimals + +`function decimals() external view returns (uint8);` + +返回代币使用的小数位数。 + +您可能想要使用小数点将您的代币分成任意金额,例如1.5 ETH。 EVM(以太坊虚拟机)只支持整数。 您可能想要使用小数点将您的代币分成任意金额,例如1.5 ETH。EVM(以太坊虚拟机)只支持整数。这就是为什么ERC20标准建议实现指定代币具有多少小数位功能。18个小数位是行业标准。 18个小数位是行业标准。 diff --git a/locales/zh/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md b/locales/zh/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md new file mode 100644 index 000000000..73e7d8950 --- /dev/null +++ b/locales/zh/ERC20TokenCourse/erc20-testnet-deployment/erc20testnetDeployment.md @@ -0,0 +1,41 @@ +在本节中,我们将使用以太坊钱包Metamask,将合约部署到以太坊区块链的测试网络上。这个测试网络与真正的区块链(主网)非常相似,但不需要真正的ETH来支付交易费用。 这个测试网络与真正的区块链(主网)非常相似,但不需要真正的ETH来支付交易费用。 + +### 1. 安装Metamask + +**1.1** 前往metamask.io。 + +**1.2** 点击下载按钮,然后点击浏览器安装(例如Chrome),并添加扩展程序到您的浏览器中。 + +**1.3** 按照说明创建一个钱包。 + +### 2. 获取测试代币 + +为了在测试网上进行交易,我们需要以太坊测试网代币,您可以从一种叫做_水龙头_的东西中获得代币。 + +**2.1** 通过单击“Ethereum Mainnetwork”下拉菜单并选择“Ropsten Test Network”来切换您的Metamask网络。如果您没有看到任何测试网络,请单击“显示/隐藏”链接,并在设置中启用“显示测试网络”。 如果您没有看到任何测试网络,请单击“显示/隐藏”链接,并在设置中启用“显示测试网络”。 + +**2.2** 前往https://faucet.ropsten.be/,输入您账户地址,并领取testnet ETH。 您也可以使用其他ropsten水龙头,如https://faucet.paradigm.xyz/https://app.mycrypto.com/faucet 。 **2.2** 前往https://faucet.ropsten.be/,输入您账户地址,并领取testnet ETH。 您也可以使用其他ropsten水龙头,如https://faucet.paradigm.xyz/https://app.mycrypto.com/faucet 。请查看ethereum.org上列出的水龙头了解更多信息。 + +### 3. 部署 + +确保已编译EduCoin合约。 + +**3.1.** 在Remix IDE的“DEPLOY&RUN TRANSACTIONS”模块下,在“ENVIRONMENT”中选择“Injected Web3”。它会要求您连接您的账户,您应该确认。 它会要求您连接您的账户,您应该确认。 + +**3.2** 部署EduCoin合约并在Metamask中确认交易。 + +**3.3** 您的合约应出现在“Deployed Contracts”部分。复制合约地址。 复制合约地址。 + +**3.4** 在Metamask中,单击资产,然后单击“导入代币”链接,并将您的合约地址粘贴到输入中。 + +现在,您应该看到钱包余额为1000 EDC。 + +### 4. 进行交易 + +**4.1** 单击Metamask钱包中的标识图像(表示您的地址),并创建第二个账户(Account 2)。 + +**4.2** 复制Account 2 的地址。 + +**4.3** 切换到第一个账户(Account 1)并向 Account 2 发送250 EDC。检查 Account 1 和 Account 2 的余额。如果要使用此帐户进行交易,则可能需要再次添加代币地址以便于 Account 2 导入代币,并且需要testeth。 检查 Account 1 和 Account 2 的余额。 为了在测试网络上进行交易,我们需要以太坊测试代币,您可以从称为水龙头的地方获得。 + +如果查看Remix中的合约并使用Account 1和Account 2 的地址调用`balanceOf`函数,则还可以查看自己的帐户余额。 diff --git a/locales/zh/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md b/locales/zh/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md new file mode 100644 index 000000000..765d2584d --- /dev/null +++ b/locales/zh/ERC20TokenCourse/erc20-token-creation/erc20TokenCreation.md @@ -0,0 +1,18 @@ +一个代币标准告诉我们合约需要遵守哪些功能。 如何实现这些功能取决于开发人员。 在此合约中,我们将使用来自OpenZeppelin的ERC20代币合约实现(第4行)。 在这种情况下,我们导入了OpenZeppelin合约的4.4.0版本。 + +查看它们精心注释的ERC20合约以更好地了解ERC20是如何实现的。除了ERC20标准规定的功能外,该合约还提供其他功能。 除了ERC20标准规定的功能外,该合约还提供其他功能。 + +我们将创建自己的名为EduCoin(第6行)的合约,并继承OpenZepplin ERC20代币合约(第4行)。 + +该合同实现了ERC20 Token标准中可选函数`name()`和`symbol()`,并具有构造函数,在部署该合约时可以设置其值(第7行)。在这种情况下,我们将使用默认值。我们将把代币起名为`MyToken`,并使`MTK`作为其符号。 +In this case, we are going to use the default values. We will call our token the same as the contract `"MyToken"` and make `"MTK"` its symbol. + +接下来,我们利用继承而来的`_mint`函数(第8行),在部署智能合约时生产代币。 在参数内部,指定接收代币账户地址和要创建多少个代币。 +在本例中,部署智能合约的账户将收到代币,并且我们将数量设置为1000000的`decimals()`次方。 本合约实现了ERC20代币标准的可选函数`decimals()`,并将其设置为默认值18。 这将创建1000000个具有18位小数的代币。 + +## ⭐️ 作业 + +1. 将您的合约名称更改为`EduCoin`。 +2. 将您的代币名称更改为`EduCoin`。 +3. 将您的代币符号更改为`EDC`。 +4. 将要铸造的代币数量从1000000更改为1000。 diff --git a/locales/zh/ERC20TokenCourse/introduction/introduction.md b/locales/zh/ERC20TokenCourse/introduction/introduction.md new file mode 100644 index 000000000..25062fc56 --- /dev/null +++ b/locales/zh/ERC20TokenCourse/introduction/introduction.md @@ -0,0 +1,63 @@ +在本课程的这部分中,我们将为您介绍基于区块链的代币理论。 + +区块链代币是由区块链技术创建的模块(就像网站对互联网),它实现了去中心化、主权独立的互联网(Web3)。 + +### 简介 + +在Web3环境下,代币表示所有权。 在Web3环境下,代币表示所有权。代币可以表示任何东西的所有权:艺术品、声誉、视频游戏中的物品、公司股份、投票权或货币等。 + +区块链技术所具备革命性创新之处在于它允许数据以不可变(无法更改)方式公开存储。这种新形式的数据存储方式使我们能够跟踪所有权并首次实现真正可拥有数字物品。 +这种新形式的数据存储方式使我们能够跟踪所有权并首次实现真正可拥有数字物品。 + +最初发明区块链技术是为了跟踪比特币的所有权(比特币是一种去中心化数字货币和同质化代币)。 + +### 同质化和非同质化代币 + +像钱这样的资产:例如,比特币或一美元纸钞,都是同质化的。 同质意味着所有资产都相同且可以互换。 像钱这样的资产:比特币或一美元纸钞,例如都是同质化资产。同质意味着所有资产都相同且可以互换。而像艺术品、收藏品或房屋等资产则是非同质化的,它们都不同且不能互换。 + +我们可以将代币分为这两种类型:同质化代币,其中所有代币都相同;以及非同质化代币(NFTs),其中每个代币都是独一无二的。 + +### 代币标准 + +一个代币的行为是在其智能合约(代币合约)中指定的。 该合约可以包括转移代币或检查其总供应量等功能。 + +如果每个人都创建自己具有不同行为和命名惯例的代币合约,那么人们将很难构建与其他人交互的合约或应用程序。 + +以太坊社区已经开发了代币标准,定义了开发者如何创建可与其他合约、产品和服务进行交互(即可互操作)的代币。 根据这些标准开发的合约需要包括一定数量的函数和事件。 + +最流行的代币标准是 ERC20 用于同质化代币和 ERC721 用于非同质化代币。在本课程中,我们将学习如何在以下章节中创建并与 ERC20 代币标准进行交互。 以太坊社区已经开发了代币标准,定义了开发者如何创建可与其他合约、产品和服务进行交互(即可互操作)的代币。根据这些标准开发的合约需要包括一定数量的函数和事件。 + +如果您想了解更多关于 NFT 和 ERC721 代币标准,请参阅 **Learneth NFT 课程** 。 + +同质化和非同质化代币 ERC777 是一种同质化代币标准,类似于 ERC20,在保持向后兼容性时包含更高级别特性,例如hooks。请通过其 EIP(以太坊改进提案)了解有关 ERC777 的更多信息。 + +一个代币的行为是在其智能合约(代币合约)中指定的。该合约可以包括转移代币或检查其总供应量等功能。 +ERC1155 是一种多代币标准,允许单个合约管理不同类型的代币,例如可同质化、非同质化或半同质化代币。请通过其 EIP 了解有关 ERC1155 的更多信息。 + +## ⭐️ 作业 + +对于这个作业,我们将通过一个简短的测验来测试您的知识。 +对于这个作业,我们将通过一个简短的测验来测试您的知识。在`Quiz`合约(第4行)中,将最佳答案的编号分配给变量`question1`(第5行),`question2`(第6行),`question3`(第7行)。 + +### 问题1: + +为什么基于区块链的代币如此具有革命性? + +1. 因为人们现在可以匿名投资。 +2. 因为它们代表了可拥有和转让的数字资产所有权。 +3. 因为你可以使用代币进行交易而无需支付税款。 + +### 问题2: + +社区为什么创建了代币标准? + +1. 以便社区可以控制和批准所创建的代币。 +2. 限制代币功能以进行安全和非恶意操作。 +3. 使社区能够创建与其他合约、产品和服务互通的代币。 + +### Question 3: + +如果您要为棒球交易卡牌游戏创建一个去中心化应用程序,其中每个棒球选手都将由一个代币表示,那么您会使用哪种标准编写该代币合约? + +1. ERC20 +2. ERC721 diff --git a/locales/zh/ERC721Auction/README.md b/locales/zh/ERC721Auction/README.md new file mode 100644 index 000000000..afc959f10 --- /dev/null +++ b/locales/zh/ERC721Auction/README.md @@ -0,0 +1,5 @@ +## NFT拍卖合约 + +学习如何编写ERC721(NFT)拍卖合约。 + +由p2p学习平台https://dacade.org开发。 diff --git a/locales/zh/ERC721Auction/auction-contract-setup/auctionContractSetup.md b/locales/zh/ERC721Auction/auction-contract-setup/auctionContractSetup.md new file mode 100644 index 000000000..2c0801d65 --- /dev/null +++ b/locales/zh/ERC721Auction/auction-contract-setup/auctionContractSetup.md @@ -0,0 +1,45 @@ +在本合约教程中,我们将学习如何创建一个ERC721(NFT)拍卖合约。 +我们建议您在开始本教程之前先完成Learneth的“Solidity NFT课程”。 + +在接下来的几节中,我们将创建一个合约,使卖家能够向出价最高者拍卖NFT。 该合约由 Solidity by Examples 项目创建。 在第一部分中,我们将创建一个接口、必要的状态变量和构造函数。 + +### 接口 + +我们为ERC721代币创建了接口(第5行),因为我们的合约需要与它进行交互。 我们需要`safeTransferFrom`方法(第5行)和`transferFrom`方法(第11行)。 + +### EnglishAuction + +我们创建了四个事件`Start`、`Bid`、`Withdraw`、`End`(19-22行),以便记录重要交互。 + +接下来,我们将创建存储所有关于链上拍卖所需信息的状态变量。 + +对于想要拍卖的NFT,我们创建了两个状态变量。 `nft`变量(24行), 我们存储了NFT合约,这样就可以通过组合IERC721接口和NFT合约地址调用其函数。 +`nftId`(25 行) 中,我们存储即将被拍卖的NFT合约中的特定 token id 。 + +接下来,我们需要一个变量来存储拍卖NFT的人的地址,即卖家(27行)。 +我们希望在拍卖结束时,NFT合约将竞拍所得发送给卖家,因此使用了可支付地址。 + +我们创建一个状态变量`endAt`(28行),用于存储拍卖的截止日期。 +我们还创建了两个布尔值`started`(29 行) 和`ended`(30 行),以跟踪拍卖是否已经开始或结束 。 + +我们创建一个变量`highestBidder`(32行),用于存储出价最高者的地址。 一旦拍卖结束,我们将向出价最高者发送NFT。 + +最后,我们需要一个uint类型的`highestBid`变量(33行)来存储最高出价和一个mapping类型的变量`bids`(34 行),在其中可以存储账户在撤回之前所做出的所有投标总值;下一节中会详细介绍这方面内容。 + +### 构造函数 + +当拍卖人部署合约时,他们需要提供几个参数:他们想要进行拍卖的NFT合约地址`_nft`(37行)、他们想要进行拍卖的NFT的token id`_nftId`(38行)以及必须超过起始价格才能在竞标中放置第一笔出价`_startingBid`(39行)。 + +部署后,状态变量`nft`(41行)、`nftId`(42行)和`highestBid`(45行)将被分配来自参数的值。 部署合约的`seller`地址将通过 msg.sender 自动读取并存储在状态变量`seller`中(44行)。 + +在下一节中,我们将使拍卖人能够开始拍卖,并让竞标者进行出价。 + +## ⭐️ 作业 + +接下来的作业部分,为您提供在Remix Remix VM环境中测试合约的指导。 + +1. 部署一个NFT合约。 您可以使用我们在“3.3 ERC721 - Token Creation”一节中创建的NFT合约。 + +2. 部署这个EnglishAuction合约。 将NFT合约地址用作`_nft`参数的值,0用于`_nftId`的值,1用于`_startingBid`的值。 + +3. 在部署您的合约后,测试`nft`、`nftId`和`started`等函数是否按预期工作。 diff --git a/locales/zh/ERC721Auction/auction-start-bid/auctionContractStartBid.md b/locales/zh/ERC721Auction/auction-start-bid/auctionContractStartBid.md new file mode 100644 index 000000000..7df32eba1 --- /dev/null +++ b/locales/zh/ERC721Auction/auction-start-bid/auctionContractStartBid.md @@ -0,0 +1,42 @@ +在这个部分,我们将创建一个函数来开始拍卖,并创建一个函数来对NFT进行竞标。 + +### 开始 + +我们使用一些控制结构来检查是否满足条件,然后才允许卖家开始拍卖。 + +首先,我们检查拍卖是否已经开始(第49行)。 如果已经开始并且状态变量`started`返回`true`,则退出函数并抛出异常。 + +第二个条件是检查执行该启动功能的帐户是否为卖方(第50行)。 当他们部署合约时,我们已经创建了一个用于存储卖家地址的功能,并且现在可以检查执行`start`函数的帐户是否为卖家。 如果不是,则抛出异常。 + +接下来,我们想将正在拍卖的NFT从卖家转移到合约中(第52行)。 +我们将状态变量`started`设置为`true`(第53行),并创建了一个结束日期以结束拍卖(第54行)。 在这种情况下,它将是从调用start函数开始的七天。 我们可以使用像`days`这样的后缀来指定时间单位。 如果您想了解更多关于时间单位的信息,请查看solidity 文档。 + +最后,我们会发出`Start`事件(第56行)。 + +### 出价 + +在函数调用者进行出价之前,我们需要确保满足某些条件。 拍卖必须已经开始(第60行),拍卖不能已经结束(第61行),并且出价(与调用相关联的值)必须高于当前最高出价(第62行)。 + +现在,我们想要在进行新的竞标之前存储当前最高竞标人的出价。 +首先,我们检查是否有投标人(第64行)。 如果这个函数调用是第一次投标,则下一行将无关紧要。 +在映射`bids`(第 34 行)中,我们将键(投标人的`地址`)映射到值(一个`uint`),表示投标人在撤回之前在拍卖中出价的 ETH 总额。 +如果有投标人,我们将`highestBidder`的最后一个投标(`highestBid`)添加到他们撤回之前的投标总价值中(第 65 行)。 +我们存储了这些报价,因为我们希望允许投资者提取他们使用来进行报价,但不再是最高竞买者时所使用过的ETH。 + +接下来,我们将`highestBidder`设置为调用该函数的账户( 第68 行),并将`highestBid`设置为其所提交的`bid`即与该调用相关联发送过来金额(第69行)。 + +最后,我们发出`Bid`事件(第71行)。 + +## ⭐️ 作业 + +1. 部署一个NFT合约。 您可以使用我们在“Solidity NFT Course” Learneth课程中创建的NFT合约。 + +2. 铸造自己tokenId为0的NFT。 + +3. 部署这个EnglishAuction合约。 将NFT合约地址用作`_nft`参数的值,0用于`_nftId`的值,1用于`_startingBid`的值。 + +4. 调用您的NFT合约的`approve`函数,并将拍卖合约地址作为`to`的参数,`tokenId`设置为0。 这将允许该合约转移要拍卖的代币。 + +5. 调用您拍卖合约的`start`函数。 如果现在调用`started`函数,则应返回`true`。 如果调用`highestBid`函数,则应返回1。 + +6. 将可以附加到交易中的值设置为3 Wei,并调用拍卖合同的`bid`函数。 如果现在调用`highestBid`函数,则应返回3。 diff --git a/locales/zh/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md b/locales/zh/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md new file mode 100644 index 000000000..67850bbfd --- /dev/null +++ b/locales/zh/ERC721Auction/auction-withdraw-end/auctionContractWithdrawEnd.md @@ -0,0 +1,45 @@ +在这个部分,我们将完成合约、创建一个函数来撤回账户所做的出价,并创建一个结束拍卖的函数。 + +### 撤回 + +我们创建了一个本地变量`bal`(余额),它存储了函数调用者自上次提款以来所做出价的总值(第75行)。 我们可以通过使用函数调用者地址作为键访问`bids`映射并将该值赋给 `bal`。 + +接下来,在`bids`映射中将函数调用者地址的值设置为 0,因为他们将提取其所有出价的总值(第76行)。 + +现在,我们从合约向函数调用者转移相应数量的 ETH 并发出`Withdraw`事件(第79行)。 + +### 结束 + +在执行此函数并结束拍卖之前,需要检查是否满足某些条件。 拍卖必须已经开始(第83行),到达了拍卖截止日期(第84行),且拍卖还没有结束过(第85行)。 + +一旦拍卖结束,我们就将状态变量`ended`设置为`true`(第87行)。 + +然后,我们检查是否有人参与竞标 NFT (第88行)。 + +如果有人竞标,则将NFT从合约转移到最高竞标人那里 (第89行),并把从最高竞标人发送到合约中的 ETH 转移到拍卖者即NFT的销售方地址 (第90行) 中去. + +如果没有人对NFT进行竞标,则将NFT发送回拍卖者 (第92行)。 + +最后,我们发出`End`事件(第95行)。 + +## ⭐️ 作业 + +1. 部署一个NFT合约。 您可以使用我们在Learneth“Solidity NFT课程”中创建的NFT合约。 + +2. 铸造自己的tokenId为0的NFT。 + +3. 为了方便测试,将`endAt`状态变量(第54行)的值从7天更改为5分钟。 + +4. 部署这个EnglishAuction合约。 将NFT合约地址用作`_nft`参数的值,0用于`_nftId`的值,1用于`_startingBid`的值。 + +5. 调用您的NFT合同`approve`函数,并将拍卖合同地址作为参数传递给`to`,并将`tokenId`设置为0。 + +6. 调用拍卖合约的`start`函数。 + +7. 使用帐户1出价2 Ether,并使用帐户2出价3 Ether。 如果调用`highestBidder`函数,则现在应返回帐户2的地址。 + +8. 调用帐户1的`withdraw`函数。 在账户1余额中,您应该看到减去一些交易费用后的2 Ether金额。 + +9. 等待5分钟后,调用`end`函数。 然后,调用`ended`函数应返回`true`。 + +在NFT合约中,如果您调用以tokenId 0为参数的`ownerOf`函数,则它应返回帐户2的地址。 如果查看账户1余额,则其应增加3 Ether并减去一些交易费。 diff --git a/locales/zh/ERC721Auction/config.yml b/locales/zh/ERC721Auction/config.yml new file mode 100644 index 000000000..0783a37a1 --- /dev/null +++ b/locales/zh/ERC721Auction/config.yml @@ -0,0 +1,19 @@ +--- +id: er721Auction +name: NFT Auction Contract +summary: Learn how to write an ERC721 (NFT) auction contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: Contract Setup + path: auction-contract-setup + - + name: Start and Bid Functions + path: auction-start-bid + - + name: Withdraw and End Functions + path: auction-withdraw-end diff --git a/locales/zh/Interoperability/1_Intro/intro.md b/locales/zh/Interoperability/1_Intro/intro.md new file mode 100644 index 000000000..3a3589b8e --- /dev/null +++ b/locales/zh/Interoperability/1_Intro/intro.md @@ -0,0 +1,5 @@ +As the web3 world grows, there will be more blockchains. 除非这些链之间可以互相通信,否则生态系统将越来越碎片化。 + +Axelar 网络使协议能够在任意两个区块链之间具有跨链功能。 + +建立一个在生态系统之间互操作的协议对增长至关重要。 diff --git a/locales/zh/Interoperability/2_Gateway/gateway.md b/locales/zh/Interoperability/2_Gateway/gateway.md new file mode 100644 index 000000000..ba46e04a9 --- /dev/null +++ b/locales/zh/Interoperability/2_Gateway/gateway.md @@ -0,0 +1,25 @@ +Axelar网关是您的智能合约进入Axelar生态系统的入口。 一旦你在网关上触发了适当的函数,你的交易将从源链跨越Axelar网络开始其跨链之旅到目标链。 每个连接到Axelar的链都有一个部署的网关合约供您互动。 + +The following are the two more relevant functions you will need to be familiar with. + +## callContract() + +此函数触发一笔带有信息的跨链交易,从源链到目标链。 它需要三个相关参数: + +1. `destinationChain`:目标链的名称 +2. `destinationContractAddress`:此交易将在目标链上执行的地址。 +3. `payload`: 发送的信息 + +前两个参数很直观。 它们包括你希望此交易发送到的链的名称以及你希望在该链上执行的地址。 最后一个参数是payload。 这个payload代表发送到目标链的通用信息。 此信息可以在目的链上以多种不同的方式使用。 例如,您可以发送数据作为目标链上另一个函数的参数,您可以发送一个函数签名作为信息然后在目标链上执行,等等。 + +## callContractWithToken() + +此函数触发一笔带有信息和可互换代币的跨链交易,从源链到目标链。 它需要五个相关参数: + +1. `destinationChain`:目标链的名称 +2. `destinationContractAddress`:此交易将在目标链上执行的地址。 +3. `payload`: 发送的信息 +4. `symbol`:正在发送的代币的符号 +5. `amount`: 被发送的代币数量 + +这里的前三个参数与 `callContract()` 中的相同。 最后两个参数与随信息发送的代币有关。 这是代币的符号和正在发送的代币数量。 diff --git a/locales/zh/Interoperability/3_GasService/GasService.md b/locales/zh/Interoperability/3_GasService/GasService.md new file mode 100644 index 000000000..c260f059d --- /dev/null +++ b/locales/zh/Interoperability/3_GasService/GasService.md @@ -0,0 +1,29 @@ +Axelar 燃料服务是一个非常有用的工具,可用于支付链间交易的燃料。 它允许您使用源链的代币来支付交易费用,从而大大简化了终端用户(和开发者)的体验。 例如,如果源链是Ethereum,而目标链是Polygon,那么燃料服务将以ETH接收交易的全部付款,调用者无需提供matic来支付在Polygon目标链上的执行费用。 + +你需要熟悉下面两个与燃料服务更具相关性的函数。 + +## payNativeGasForContractCall() + +此功能允许您使用源链的原生代币支付整个跨链交易的费用。 它需要五个相关参数: + +1. `sender`:付款地址 +2. `destinationAddress`:交易被发往的目标链上的地址 +3. `destinationChain`:交易被发往的目标链名称 +4. `payload`: 发送的信息 +5. `refundAddress`:如果随此交易发送的燃气费过多,则应将任何退款发送到的地址。 + +这些参数与Gateway合约中`callContract()`函数所需的参数重叠。 在网关部分没有讨论的两个参数是 `sender` 和 `refundAddress`。 sender是支付交易费用的地址,refundAddress是将收到发送到燃气服务的任何多余资金的地址。 + +## payNativeGasForContractCallWithToken() + +This function allows you to pay for the entirety of an interchain transaction (that includes a token transfer) in the native token of the source chain. 它需要七个相关参数: + +1. `sender`:付款地址 +2. `destinationAddress`:交易被发往的目标链上的地址 +3. `destinationChain`:交易被发往的目标链名称 +4. `payload`: 发送的信息 +5. `symbol`:被发送的代币的符号 +6. `amount`: 被发送的代币数量 +7. `refundAddress`:如果随此交易发送的燃气费过多,则应将任何退款发送到的地址。 + +This function is nearly identical to the first top one the main difference being that it is used for message + token transfer transactions as opposed to just interchain message transactions (aka GMP Transactions). 因此,燃料服务也需要知道正在发送的代币的`symbol`和`amount`。 diff --git a/locales/zh/Interoperability/4_Executable/executable.md b/locales/zh/Interoperability/4_Executable/executable.md new file mode 100644 index 000000000..2458e547b --- /dev/null +++ b/locales/zh/Interoperability/4_Executable/executable.md @@ -0,0 +1,27 @@ +Axelar 可执行文件包含相关的辅助函数,这些函数将根据源链的相关入站交易在目标链上自动执行。 + +以下是您需要使用 Axelar 可执行文件中的相关函数 + +## \_execute() + +此函数处理目标链上的执行操作。 它需要以下四个参数: + +1. `commandId`: Axelar 链上唯一的交易ID。 +2. `sourceChain`: 被发送的这条交易所在的源链 +3. `sourceAddress`: 被发送的这条交易所在源链上的地址 +4. `payload`: 发送的信息 + +The `sourceChain` and `sourceAddress` are key parameters which you receive out of the box that can be used for verifying authenticity of messages on the destination chain. 有效负载(如网关部分中所述)是从源链发送并在目标链上使用的消息。 此模块的其余部分不会使用 `commandId` 。 + +## \_executeWithoken() + +此函数处理被发送到目标链上带有可替代代币的消息交易。 它需要六个相关参数: + +1. `commandId`: Axelar 链上唯一的交易ID。 +2. `sourceChain`: 被发送的这条交易所在的源链 +3. `sourceAddress`: 被发送的这条交易所在源链上的地址 +4. `payload`: 发送的信息 +5. `tokenSymbol `:正在发送的代币的符号 +6. `amount`: 被发送的代币数量 + +前四个参数与 `_execute()` 函数相同。 最后两个参数`tokenSymbol` 和 `amount` 与随信息发送的代币有关。 它允许您在目标链上与代币进行交互,例如将其转移到另一个接收地址。 此模块的其余部分不会使用 `commandId` 。 diff --git a/locales/zh/Interoperability/5_InterchainMessage/interchainMessage.md b/locales/zh/Interoperability/5_InterchainMessage/interchainMessage.md new file mode 100644 index 000000000..215f123a4 --- /dev/null +++ b/locales/zh/Interoperability/5_InterchainMessage/interchainMessage.md @@ -0,0 +1,53 @@ +在本节中,我们将创建一个合约,在两个区块链之间发送"hello world"消息。 + +## 构造函数 + +The first thing you will need to create is the `constructor` for the function. 这样就可以设置前几节讨论过的 "网关" 和 "燃气服务" 合约。 + +部署合约时,你需要输入以太坊 Sepolia 的 `Gateway` 和 `GasService` 的地址,Gateway 是 `0xe43250cce91cce91c13a887f7D836923d5597adD8E31` ,GasService 是 `0xbE406F0189A0B4cf3A05C286473D23791Dd44Cc6`。 + +关于相关的 Axelar 地址的完整列表 查看这里 + +## 发送链际消息 + +现在构造函数已经设置了触发链间交易所需的相关 Axelar 地址,您可以继续执行`setRemoteValue()`,这将触发此交易。 + +此函数需要三个参数: + +1. `_destinationChain`: 交易将要前往的链 +2. `_destinationAddress`:交易将在目标链上执行的地址 +3. `_message`:传递到目标链的消息 + +First, you have a `require` statement which ensures that the `msg.value` contains a value. 此 `msg.value` 将用于支付 `GasService` 。 如果没有发送资金,则应撤销交易,因为在没有任何 gas 的情况下,交易无法在 Axelar 区块链和目标链上执行。 + +接下来,你需要对传入的 `_message` 进行编码。 请注意,`_message`已设置为`string`类型。 Axelar 希望此消息以 `bytes` 类型提交,要将`string` 转换为 `bytes` ,您只需通过 `abi.encode()` 传递。 + +现在,你可以用你的消息编码开始与 `GasService` 和 `Gateway ` 交互。 + +要支付整个跨链交易,您将触发`payNativeGasForContractCall`的函数,这个函数在`GasService`中被定义。 + +该函数需要前面 GasService 部分中解释的参数。 此交易的 `sender` 就是该合约,也就是 `address(this)` 。 `destinationChain` 和 `destinationAddress` 可以从这个函数参数中传递,`payload` 是我们先前所写的 \_message 的编码。 最后,您需要指定退款地址,这可以是触发此函数的地址,您可以写入`msg.sender`。 + +Once you trigger this function you will have successfully sent a transaction from the source chain via Axelar to the destination chain! But there is still one final step that needs to be complete. + +### 在目标链上接收消息 + +在目标链上,需要通过`AxelarExecutable`的`_execute()`来提取和处理进来的链际交易。 + +`_execute()` 函数是在 `AxelarExecutable` 合约中定义的,因此在定义这个函数时,你必须记住要包含`override`关键字。 + +此函数需要三个参数。 + +1. `_sourceChain`:交易源自的区块链 +2. `_sourceAddress`: 被发送的这条交易所在源链上的地址 +3. `_payload`: 从源链发送的消息 + +在此合约中需要做的第一件事是访问您发送的`message `。 回想一下,在发送信息之前,我们通过 `abi.encode()` 将信息从`string`类型转换为`bytes`类型。 要将消息从`bytes`类型转换回`string`类型,只需将`_payload`传递给函数`abi.decode()`,并指定您希望将`_payload`解码为`string`类型。 这将会把消息作为字符串返回。 + +现在您已将消息设置为字符串类型,您可以将`sourceChain`和`sourceAddress`存储变量设置为`_sourceChain`和`_sourceAddress`,以便引用传入的数据。 您还可以使用刚刚解码的`sourceAddress`和`message`事件发出`Executed`事件。 + +太棒了! 此刻,您正在处理目标链上的跨链交易。 + +要与此合约交互,请确保将其部署在至少两个区块链上,以便您可以从一条链调用`setRemoteValue()`,然后在另一条链上自动触发`_execute()`函数。 您将能够查询目标链上的`sourceChain`和`sourceAddress`变量,以确保链间执行正常工作。 + +要查看链间交易的完整步骤,请查看Axelarscan(测试网)区块浏览器。 diff --git a/locales/zh/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md b/locales/zh/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md new file mode 100644 index 000000000..5e30d6e3b --- /dev/null +++ b/locales/zh/Interoperability/6_InterchainTokenTransfer/interchainTokenTransfer.md @@ -0,0 +1,39 @@ +At this point we have gone over an example of how to send a general message between one blockchain to another. 现在,让我们来实现一个合约,从一个区块链向另一个区块链发送一条信息和一个代币。 + +## 概述 + +这份合约看起来应该很熟悉。 与上一节非常相似,`constructor`接收`Gateway` 和 `Gas Service`地址。 + +然后,它将从源链中调用一个名为 `sendToMany` 的函数,该函数接收的参数与上一节类似。 + +1. `_destinationChain`: 交易被发往的链 +2. `_destinationAddress`:交易被发往的目标链上的地址 +3. `_destinationAddresses`:将随代币转账一起发送的消息。 在此示例中,消息是代币转账的接收地址列表。 +4. `_symbol`:正在发送的代币的符号 +5. `_amount`: 正在发送的代币数量 + +在函数中,我们已经实现了 `require` 语句,以确保 gas 被发送 + +我们还具有基本的 ERC20 功能,可将代币从调用钱包发送到此智能合约。 The contract also calls the `approve` function to allow the Gateway to eventually transfer funds on its behalf. + +最后,`_executeWithToken()`函数也是开箱即用的。 + +它使用以下参数: + +1. `_payload`: 源链中传入的消息 +2. `_tokenSymbol`: 从源链发来的代币符号 +3. `_amount`: 从源链发来的代币数量 + +现在,通过传入的这些参数,`_execute()`函数可以将已发送的代币发给合适的接收者。 + +## 挑战 + +这里您面临的挑战是使用 Axelar 网关和 Gas 服务完成`sendToMany()`函数以触发链间交易。 + +最后,您应该能够在两个测试网上部署此合约,触发`sendToMany()`函数并在Axelarscan(测试网)区块浏览器上查看实时交易。 + +### 测试备注 + +注 1:建议使用的 ERC20 是`aUSDC`,它是 USDC 代币的封装版本,可以从 discord faucet bot 获取。 触发`sendToMany()`函数时,只需将符号`aUSDC`传递给第四个参数即可。 + +注2:当触发`sendToMany()`函数时,您必须记住`approve`您的合约以代表您花费`aUSDC`代币,否则第49行的`transferFrom()`将抛出错误。 diff --git a/locales/zh/Interoperability/7_FurtherReading/furtherReading.md b/locales/zh/Interoperability/7_FurtherReading/furtherReading.md new file mode 100644 index 000000000..2b96d9697 --- /dev/null +++ b/locales/zh/Interoperability/7_FurtherReading/furtherReading.md @@ -0,0 +1,11 @@ +恭喜您完成了互操作性模块! 🎉🎉 + +想要继续学习与Axelar的互操作性。 There are many useful resources available. + +- 关于 文档 📚 + +- 关于 更多技术示例 💻 + +- 关于 实时编码演示📹 + +- 关于 开发人员博客 📝 diff --git a/locales/zh/Interoperability/README.md b/locales/zh/Interoperability/README.md new file mode 100644 index 000000000..7837678ae --- /dev/null +++ b/locales/zh/Interoperability/README.md @@ -0,0 +1,3 @@ +## 区块链之间的互操作性 + +了解如何构建可互操作的智能合约,以便使用 Axelar 技术在不同区块链之间发送消息和资产。 diff --git a/locales/zh/Interoperability/config.yml b/locales/zh/Interoperability/config.yml new file mode 100644 index 000000000..39f1be7ed --- /dev/null +++ b/locales/zh/Interoperability/config.yml @@ -0,0 +1,31 @@ +--- +id: interopCourse +name: Multichain Protocols with Axelar +summary: Learn how to build interoperable smart contracts that can send messages and assets between different blockchains using Axelar technology. +level: 2 +tags: + - Solidity + - Interoperability + - Axelar +steps: + - + name: An Intro to Axelar + path: 1_Intro + - + name: Axelar Gateway + path: 2_Gateway + - + name: Axelar Gas Service + path: 3_GasService + - + name: Axelar Executable + path: 4_Executable + - + name: Interchain Messages + path: 5_InterchainMessage + - + name: Interchain Token Transfers + path: 6_InterchainTokenTransfer + - + name: Further Reading + path: 7_FurtherReading diff --git a/locales/zh/Multisig-Tutorial/1-multisig-introduction/introduction.md b/locales/zh/Multisig-Tutorial/1-multisig-introduction/introduction.md new file mode 100644 index 000000000..6f55fa12e --- /dev/null +++ b/locales/zh/Multisig-Tutorial/1-multisig-introduction/introduction.md @@ -0,0 +1,41 @@ +欢迎来到多重签名钱包课程! 在本节中,我们将探讨多重签名(Multisig)钱包的基础知识,并将介绍多签钱包合约。 + +## 什么是多重签名钱包? + +多重签名(multisig)钱包是一种需要多个密钥来授权加密货币交易的数字钱包。 + +将多签钱包想象成一个带有多个锁的安全保险库。 To open the vault, each keyholder must open their individual lock. 这种设置可确保任何人都无法在未经其他人同意的情况下访问保险库的内容。 + +## 多签钱包如何工作? + +在多重签名设置中,每笔交易都必须获得一组人的预定数量的批准。 例如,在 3-of-5 钱包配置中,有 5 个授权地址,但只有当至少其中 3 个地址批准时,交易才会进行。 当交易启动时,它会作为**提案**提交给小组。 每个同意交易的成员都使用他们的私钥对其进行数字签名。 + +这些**数字签名**是唯一的,是根据交易数据和私钥组合生成的。 + +当达到所需的签名数量时,交易将被广播到区块链上执行。 + +## 为什么要使用多签钱包? + +多签钱包对于增强加密货币交易的安全性至关重要。 它们降低了单个钥匙被盗或丢失的风险。 在商业中,它们被用来确保资金在利益相关者之间没有达成共识的情况下不会被转移。 例如,在管理加密货币资产的公司中,多重签名钱包可能需要首席财务官、首席执行官和董事会成员全部批准重大交易,以防止内部欺诈或外部黑客攻击。 + +## 结论 + +在本节中,我们了解到多重签名钱包需要多个密钥来授权拟议的加密货币交易,并且多重签名可以降低单个密钥被盗或丢失的风险。 + +## ⭐ 作业: 多选测试 + +### 1. 什么是多重签名钱包? + +1. 需要单一签名进行交易的数字钱包。 +2. 需要多个签名才能进行交易的数字钱包。 +3. 用于存储加密货币的物理钱包。 +4. 只能容纳多种加密货币的钱包。 + +### 2) 多重签名钱包如何增强安全性? + +1. 要求交易使用单一私人密钥。 +2. 通过将交易批准分配给多个所有者。 +3. 通过在链上存储交易数据。 +4. 以上都不是。 + +请回答上述问题,慢慢来,不着急。 一旦您准备好,我们将继续探索多重签名智能合约并了解其结构。 diff --git a/locales/zh/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md b/locales/zh/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md new file mode 100644 index 000000000..e7575197a --- /dev/null +++ b/locales/zh/Multisig-Tutorial/2-multisig-initialization/contractInitialization.md @@ -0,0 +1,60 @@ +在本节中,我们将探讨多重签名智能合约的**初始化过程**。 我们将检查构造函数并回顾它如何设置合约的初始状态。 + +## 备注 + +从本教程的这一部分开始,我们将构建一个多重签名合约。 在接下来的章节中,合约将会变得越来越完整。 + +## 概述 + +在本节中,合约由事件、状态变量、修饰符和函数组成。 **事件**通过在区块链上记录指定的活动来提供透明度,而**修饰符**确保只有授权用户才能执行某些功能。 + +## 状态变量 + +在第 4 行中,我们有 MultisigWallet 合约本身。 在合约开始时,我们有三个状态变量。 + +1. **`owners`:** 包含多重签名钱包所有所有者地址的数组(第 5 行)。 +2. **`isOwner`:** 指示地址是否是所有者的映射(第 6 行)。 +3. **`numConfirmationsRequired`:** 一笔交易所需的确认数量(第 7 行)。 + +通过设置数组和映射,我们可以轻松检索所有者列表,并验证某个地址是否为所有者。 + +## 修饰符 + +接下来,我们有一个名为 `onlyOwner` 的修饰符(第 9 行)。 Solidity 中的修饰符是特殊的关键字,可用于修改函数的行为。 在我们的例子中,`onlyOwner`修饰符确保只有所有者才能执行函数。 它通过检查 **调用者** 的地址是否是所有者来实现这一点。 + +## 构造函数 + +`constructor` 函数(第 14 行)在合约部署期间仅执行一次。 它初始化基本参数,在本例中为所有者列表和所需的确认数量(第 14 行)。 + +在第 15 行和第 16 行,我们有两个`require`语句来确保输入有效。 在这种情况下,我们要求必须至少有一个所有者,并且所需确认的数量必须大于零且小于或等于所有者的数量。 + +然后,构造函数通过验证不是 address(0)(第 25 行)并且所有者是唯一的(第 26 行)来初始化合约状态。 然后它向 isOwner 映射添加一个键/值对(第 28 行),然后用提供的所有者地址填充`owners`数组(第 29 行)。 + +最后,它会将 `numConfirmationsRequired` 变量设置为指定值(第 32 行)。 + +## getOwners 函数 + +`getOwners` 函数(第 36 行)允许用户检索多重签名钱包的所有者列表。 它返回 `owners` 数组(第 37 行)。 + +## getNumConfirmationsRequired 函数 + +`getNumConfirmationsRequired` 函数(第 41 行)允许用户检索交易所需的确认数量。 它会返回 `numConfirmationsRequired` 变量(第 42 行)。 + +## 结论 + +在本节中,我们探讨了多重签名智能合约的初始化过程。 我们检查了构造函数并了解它如何设置合约的初始状态。 + +## ⭐ 作业: 部署一个多签钱包 + +部署一个具有三个所有者并需要两次确认才能执行交易的多重签名合约。 + +1. 编译 contractInitialization.sol +2. 进入 Remix 的 Deploy & Run Transactions 模块。 +3. 展开 "Deploy" 部分。 +4. 在"_OWNERS"下,输入三个地址的数组。 +5. 在"_NUM_CONFIRMATIONS_REQUIRED"下,输入交易所需的确认数量。 + +**提示:** + +- 您可以从"ACCOUNTS"下拉菜单中获取地址。 +- 地址数组的格式应该是:["0x123...", "0x456...", "0x789..."]。 diff --git a/locales/zh/Multisig-Tutorial/3-multisig-deposits/deposits.md b/locales/zh/Multisig-Tutorial/3-multisig-deposits/deposits.md new file mode 100644 index 000000000..b514433b1 --- /dev/null +++ b/locales/zh/Multisig-Tutorial/3-multisig-deposits/deposits.md @@ -0,0 +1,34 @@ +在本节中,我们将探讨`receive`函数和相关的存款事件。 我们将研究如何使用`receive `函数将以太币存入多重签名钱包,以及存款事件如何提供透明度。 + +## 存款事件 + +在第 9 行,我们有存款事件。 每当以太币存入多重签名钱包时,就会发出存款事件。 它包括三个参数: + +1. `sender`:发送以太币的地址。 +2. `amount`:存入的以太币数量。 +3. `balance`:入金后合约更新后的余额。 + +我们可以使用存款事件来跟踪进入多重签名钱包的以太币流量,并可能根据该事件触发其他操作。 + +## receive 函数 + +第 43 行,我们有`receive`函数。 `receive`函数是一个特殊函数,每当以太币发送到合约时就会执行。 + +`receive`函数被标记为`external`和`payable`。 `external`修饰符意味着该函数只能从合约外部调用。 `payable`修饰符意味着该函数可以接收以太币。 + +`receive`函数发出 Deposit 事件(第 44 行),其中包含发送者的地址、发送的以太币数量以及更新后的合约余额。 它不返回任何内容。 + +要接收以太币,合约必须具有`receive`、`fallback`或带有`payable`修饰符的函数。 如果这些都不存在,合约将拒绝发送给它的任何以太币。 + +## 结论 + +在本节中,我们探讨了`receive函数和相关的存款事件。 我们研究了如何使用`receive\`函数将以太币存入多重签名钱包,以及存款事件如何提供透明度。 + +## ⭐ 作业: 存入以太币 + +将 2 个以太币存入多重签名合约。 + +1. 按照之前的任务部署多重签名合约。 +2. 在值字段中输入 2 Ether 的值,然后在下拉菜单中选择 Ether。 +3. 在已部署合约底部的”低级交互”部分中,单击“交易”按钮。 +4. 在您部署的合约之上,现在应该显示“余额:2 以太币”。 diff --git a/locales/zh/Multisig-Tutorial/4-multisig-transactions/transactions.md b/locales/zh/Multisig-Tutorial/4-multisig-transactions/transactions.md new file mode 100644 index 000000000..0e885e383 --- /dev/null +++ b/locales/zh/Multisig-Tutorial/4-multisig-transactions/transactions.md @@ -0,0 +1,73 @@ +在本节中,我们将探讨提交和确认交易的过程。 + +## 修饰符 + +我们在合约的本次迭代中添加了新的修饰符。 让我们逐一来研究一下。 + +1. **`txExists` 修饰符:**(第 13 行)确保交易存在。 它通过检查交易索引是否小于“交易”数组的长度来实现这一点。 我们将在本节后面详细介绍此修饰符。 +2. **`notExecuted` 修饰符:**(第 18 行)确保事务尚未执行。 它通过检查交易的`executed` 变量是否为 false 来实现这一点。 +3. **`notConfirmed` 修饰符:**(第 23 行)确保交易尚未被调用者确认。 它通过检查交易索引和调用者地址的`isConfirmed`映射是否为 false 来实现这一点。 + +## 交易结构体 + +在第 28 行,我们有一个名为`Transaction`的结构体。 我们将结构体成员:`to`, `value`, `data`, `executed`, 和 `numConfirmations`存储在各个变量中。 + +## 映射确认 + +在第 37 行,我们有一个名为`isConfirmed`的映射。 该映射用于跟踪每笔交易的确认。 它将交易的索引映射到所有者地址到布尔值的映射。 布尔值表示该所有者是否已确认交易。 + +## 交易数组 + +在第 39 行,我们有一个名为`transactions`的数组。 该数组用于存储提交到多重签名钱包的所有交易。 + +## 事件 + +在本次合约迭代中,我们有四个新事件: + +1. **`SubmitTransaction` 事件:** 每当交易提交到多重签名钱包时就会发出。 +2. **`ConfirmTransaction` 事件:** 每当交易被所有者确认时发出。 +3. **`RevokeConfirmation` 事件:** 每当所有者撤销交易确认时就会发出。 +4. **`ExecuteTransaction` 事件:** 每当执行事务时都会发出。 + +## submitTransaction 函数 + +`submitTransaction` 函数(第 78 行)允许用户向多重签名钱包提交交易。 它需要三个参数:`to`、`value`和`data`。 `to`参数是交易接收者的地址。 `value`参数是要发送的以太币数量。 `data` 参数是要发送给接收者的数据。 只有所有者才能提交交易。 + +在第 85 行,我们创建了一个新的交易结构体,并将其推送到 `transactions` 数组中,然后发出 `SubmitTransaction` 事件。 `txIndex` 变量用于跟踪交易索引。 + +## confirmTransaction 函数 + +`confirmTransaction` 函数(第 98 行)允许用户确认交易。 它需要一个参数:`txIndex'。 +它具有三个修饰符:`onlyOwner`, `txExists`, 和 `notExecuted`。 `onlyOwer`修饰符确保只有所有者可以确认交易。`txExists`修饰符确保交易存在。`notExecuted\`修饰符确保交易尚未执行。 + +在第 101 行,我们将交易存储在名为`transaction`的局部变量中。 然后,我们增加交易的`numConfirmations`变量,并将交易索引和调用者地址的 `isConfirmed`映射设置为 true。 最后,我们发出 `ConfirmTransaction` 事件。 + +## executeTransaction 函数 + +`executeTransaction` 函数(第 108 行)允许用户执行交易。 在第113行,我们要求交易的确认数大于或等于所需的确认数。 然后,我们将交易的`executed`变量设置为 true。 最后,使用 `call` 函数发送资金。 这是使用交易的值和数据对接收者地址进行 `call` 。 如果交易成功,我们就会发出 `ExecuteTransaction` 事件。 + +## getTransactionCount 函数 + +`getTransactionCount` 函数(第 132 行)允许用户检索多重签名钱包中的交易数量。 它返回 `transactions` 数组的长度。 + +## getTransaction 函数 + +`getTransaction` 函数(第 136 行)允许用户检索交易。 它返回我们在本节前面探讨过的交易结构体的成员。 + +## 结论 + +在本节中,我们探讨了提交、确认和执行交易的过程。 我们检查了`submitTransaction`、`confirmTransaction`和`executeTransaction`函数,并了解它们如何协同工作以允许多个用户提交和确认交易。 + +## ⭐ 作业: 进行一笔交易 + +提交、确认并执行交易,将 2 以太币发送到“账户”下拉菜单中的第一个账户。 + +1. 按照之前的任务部署多重签名合约。 请确保所需的确认数量为 2。 +2. 就像您在之前的任务中所做的那样,通过发送 4 个以太币从任何地址为多重签名提供资金。 +3. 尝试将 2 以太币发送到“账户”下拉菜单中的第一个账户。 提交此交易(使用submitTransaction)后,单击`getTransactionCount`,应该会看到一笔交易,或者您可以单击`getTransaction`,插入 0 作为交易索引,然后查看您刚刚提交的交易。 +4. 现在您可以点击`confirmTransaction`并插入0作为交易索引。 如果您再次点击`getTransaction`,您应该会看到交易已被确认一次。 +5. 切换到第二所有者账户并再次确认交易。 如果您再次点击`getTransaction`,您应该看到交易已被确认两次。 +6. 最后一步是执行交易。 单击`executeTransaction`并插入 0 作为事务索引。 如果您再次单击`getTransaction`,您应该看到交易已被执行。 您还可以在“账户”下拉菜单中查看第一个账户的余额。 现在应该增加 2 个以太币,而多重签名钱包的余额应该减少 2 个以太币。 + +**提示:** +如果您提交了一个交易,请确保值选中了 Wei ,并且 _data 字段填写得正确。 例如, 它看起来像这样: "0x5B38Da6a701c568545dCfcB03FcB875f56beddC4, 20000000000, 0x" 表示 2 以太币。 diff --git a/locales/zh/Multisig-Tutorial/5-multisig-revoke/revoke.md b/locales/zh/Multisig-Tutorial/5-multisig-revoke/revoke.md new file mode 100644 index 000000000..03d6c7e11 --- /dev/null +++ b/locales/zh/Multisig-Tutorial/5-multisig-revoke/revoke.md @@ -0,0 +1,30 @@ +在本节中,我们将探讨撤销确认的过程。 当所有者改变对交易的想法并想要阻止其执行时,此过程是必要的。 这部分将非常简单。 + +## revokeConfirmation 事件 + +在第 14 行,我们添加了 `RevokeConfirmation` 事件。 每当交易确认被所有者撤销时,就会发出此事件。 + +## revokeConfirmation 函数 + +在第 129 行,我们添加了 `revokeConfirmation` 函数。 它允许用户撤销交易确认。 + +`revokeConfirmation` 需要一个参数:`txIndex`。 它有三个修饰符:`onlyOwner`, `txExists`, 和 `notExecuted`。 + +在第 134 行,我们要求调用方已确认交易。 这确保了已确认交易的所有者只能撤销自己的确认。 +然后,我们递减交易的`numConfirmations`变量,并将交易索引和调用者地址的`isConfirmed`映射设置为 false。 最后,我们发出 `RevokeConfirmation` 事件。 + +## 结论 + +在本节中,我们探讨了撤销确认的过程。 我们检查了`revokeConfirmation`函数并了解它如何允许用户撤销确认。 + +## ⭐ 作业: 撤销一个确认 + +确认并撤销将 2 以太币发送到“账户”下拉菜单中的第一个账户的交易。 + +1. 与之前的作业一样,部署多重签名合约,向合约发送一些以太币,然后向“账户”下拉菜单中的第一个账户提交一笔交易,交易值为 2 以太币。 +2. 与之前的任务一样确认交易两次。 +3. 通过点击`revokeConfirmation` 并插入 0 作为交易索引来撤销交易。 如果您再次点击 `getTransaction` ,您应该会看到交易已被确认一次。 + +## 最终结论 + +在本教程中,我们探索了创建多重签名钱包的过程。 我们学习了如何初始化合约、存入以太币、提交、确认和撤销交易。 我们还学习了如何执行交易和检索有关多重签名钱包的信息。 diff --git a/locales/zh/Multisig-Tutorial/README.md b/locales/zh/Multisig-Tutorial/README.md new file mode 100644 index 000000000..4dce8e0ec --- /dev/null +++ b/locales/zh/Multisig-Tutorial/README.md @@ -0,0 +1,5 @@ +## 多签钱包 + +了解如何在以太坊上编写多重签名钱包智能合约。 + +由p2p学习平台 https://dacade.org 开发。 diff --git a/locales/zh/Multisig-Tutorial/config.yml b/locales/zh/Multisig-Tutorial/config.yml new file mode 100644 index 000000000..067de0fb9 --- /dev/null +++ b/locales/zh/Multisig-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: multisigCourse +name: Multisig Wallet +summary: Learn how to create and interact with a multisig wallet. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - Multisig +steps: + - + name: 1. Introduction + path: 1-multisig-introduction + - + name: 2. Initialize the Contract + path: 2-multisig-initialization + - + name: 3. Deposits + path: 3-multisig-deposits + - + name: 4. Transactions + path: 4-multisig-transactions + - + name: 5. Revoking Confirmations + path: 5-multisig-revoke diff --git a/locales/zh/NFTTokenCourse/README.md b/locales/zh/NFTTokenCourse/README.md new file mode 100644 index 000000000..792623c1b --- /dev/null +++ b/locales/zh/NFTTokenCourse/README.md @@ -0,0 +1,5 @@ +## Solidity NFT 课程 + +了解如何创建您自己的 NFT(非同质化代币)。 + +由p2p学习平台 https://dacade.org 开发。 diff --git a/locales/zh/NFTTokenCourse/config.yml b/locales/zh/NFTTokenCourse/config.yml new file mode 100644 index 000000000..af82db834 --- /dev/null +++ b/locales/zh/NFTTokenCourse/config.yml @@ -0,0 +1,28 @@ +--- +id: nftTokenCourse +name: Solidity NFT Course +summary: Learn how to create your own NFT tokens. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity + - Tokens + - NFT +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Interface + path: erc721-interface + - + name: 3. Metadata Interface + path: erc721-interface-metadata + - + name: 4. Token Creation + path: erc721-token-creation + - + name: 5. Metadata IPFS + path: erc721-metadata-ipfs + - + name: 6. Deploy to Testnet + path: erc721-deploy-testnet-opensea diff --git a/locales/zh/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md b/locales/zh/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md new file mode 100644 index 000000000..2343bdaf6 --- /dev/null +++ b/locales/zh/NFTTokenCourse/erc721-deploy-testnet-opensea/rec721DeployTestnetOpensea.md @@ -0,0 +1,50 @@ +在本节中,我们将使用以太坊钱包Metamask来部署我们的合约到以太坊区块链上的Rinkeby测试网络,铸造一个NFT,并在NFT市场OpenSea上查看它。 + +### 1. 安装Metamask + +**1.1** 前往metamask.io. + +**1.2** 点击下载按钮,然后点击安装您的浏览器(例如Chrome)并添加扩展程序到您的浏览器。 + +**1.3** 按照说明创建一个钱包。 + +### 2. 获取Rinkeby测试网的测试代币 + +为了在测试网上进行交易,我们需要以太坊测试代币。 + +**2.1** 将您的Metamask从“Ethereum Mainnetwork”切换到“Rinkeby Test Network”。 + +**2.2** 前往https://faucet.paradigm.xyz/,输入您账户地址,并领取testnet ETH。 +您也可以使用其他ropsten水龙头,如https://faucet.paradigm.xyz/https://app.mycrypto.com/faucet 。 查看 ethereum.org 上列出的水龙头以了解更多信息。 + +### 3. 合约部署 + +**3.1** 在Remix IDE 的“DEPLOY&RUN TRANSACTIONS”模块下,在“ENVIRONMENT”下选择“Injected Web3”。然后它应该要求您连接您的账户,请确认。然后你应该在“Injected Web3”下看到Rinkeby网络标志。 然后它应该要求您连接您的账户,请确认。 然后你应该在“Injected Web3”下看到Rinkeby网络标志。 + +**3.2** 部署您的代币合约并在Metamask中确认交易。 + +**3.3** 您的合约应该出现在“Deployed Contracts”部分。 + +### 4. 铸造 NFT + +**4.1** 在 IDE 中展开您的合约,以便您可以看到函数按钮。 + +**4.2** 展开 safeMint 按钮旁边的输入字段。 在“to:”输入字段中输入与 Remix 连接的以太坊地址。 在“tokenID:”输入字段中输入“0”。 点击交易。 + +**4.3** 在 Metamask 中单击资产,然后单击“导入代币”链接,并粘贴您合约的地址到该输入框中。您可以将小数位设置为 0。 您可以将小数位设置为 0。 + +现在,在 Metamask 的 “资产” 视图中应该能看到您代币合约符号(例如 GEO)的名称。你应该有其中一个代币了。 你应该有其中一个代币了。 + +### 5. 在 OpenSea 上查看您的 NFT + +OpenSea 是最受欢迎的 NFT 在线市场之一。OpenSea 还提供了一个版本,可以在测试网络上查看资产,网址是https://testnets.opensea.io/ **2.2** 前往https://faucet.paradigm.xyz/,输入您账户地址并领取测试网ETH。 您也可以使用其他ropsten水龙头,如https://faucet.paradigm.xyz/ 或者 https://app.mycrypto.com/faucet。请访问ethereum.org列出的水龙头列表以获取更多信息。 + +**5.1** 前往 https://testnets.opensea.io/login. + +**4.2** 展开`safeMint`按钮旁边的输入字段。在“to:”输入字段中输入与 Remix 连接的以太坊地址。在“tokenID:”输入字段中输入“0”。点击交易。 **5.2** 连接你的 Metamask 钱包。你会被重定向到 OpenSea 上你账户下面名为https://testnets.opensea.io/account的视图,在那里你应该能够看到自己铸造出来NFT。当你点击它时,你应该能够看到名称、描述和属性下面也创建好了。 您应该看到您的 NFT 的图像;当您单击它时,您应该会看到名称、描述,并在属性下看到您创建的属性。 + +如果您已经成功完成了这门课程并熟悉Solidity开发的基础知识,我们鼓励您通过Learneth资源学习如何创建自己的NFT拍卖合约,继续您的学习之旅。 diff --git a/locales/zh/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md b/locales/zh/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md new file mode 100644 index 000000000..ba6a9e973 --- /dev/null +++ b/locales/zh/NFTTokenCourse/erc721-interface-metadata/erc721InterfaceMetadata.md @@ -0,0 +1,44 @@ +元数据扩展是可选的。 它允许我们向ERC721代币添加附加信息。 元数据扩展是可选的。它允许我们向ERC721代币添加附加信息。我们可以指定名称、符号和URI(统一资源标识符),该URI可以指向一个文件,在其中以JSON格式添加更多信息。 + +## ERC721元数据函数 + +### name + +函数`name`(第16行)返回代币集合的名称。代币集合是指使用您的ERC721代币合约实现的。无论其`tokenId`是什么,该集合中的每个代币都将具有此名称。 代币集合是指使用您的ERC721代币合约实现的。 无论其 tokenId 是什么,该集合中的每个代币都将具有此名称。 + +### symbol + +函数`symbol`(第21行)返回代币集合的符号。 + +### tokenURI + +函数`tokenURI`(第26行)返回id为`tokenId`的token的URI。在这种情况下,它不是整个集合而是集合中单个代币的URI。 在这种情况下,它不是整个集合而是集合中单个代币的URI。 + +## ERC721 Metadata JSON Schema + +tokenURI指向的文件应符合EIP-721中指定的元数据JSON模式。 + +``` +{ + "title": "Asset Metadata", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Identifies the asset to which this NFT represents" + }, + "description": { + "type": "string", + "description": "Describes the asset to which this NFT represents" + }, + "image": { + "type": "string", + "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." + } + } +} +``` + +根元素必须是对象类型。 根元素必须是对象类型。该根对象应具有以下键的属性:名称、描述和图像,这些属性都应为字符串类型。 + +ERC721标准非常灵活,`tokenURI`不需要指向JSON文档,并且JSON不需要具有所有属性,通常还会有其他属性。 diff --git a/locales/zh/NFTTokenCourse/erc721-interface/erc721Interface.md b/locales/zh/NFTTokenCourse/erc721-interface/erc721Interface.md new file mode 100644 index 000000000..42e82f817 --- /dev/null +++ b/locales/zh/NFTTokenCourse/erc721-interface/erc721Interface.md @@ -0,0 +1,100 @@ +ERC721是以太坊区块链上管理非同质化代币(NFT)的标准合约。 + +每个非同质化代币都是独一无二且不可互换的。 NFT可以具有不同的属性、行为或权利。 非同质化代币用于表示对唯一数字和实物资产(如艺术品、收藏品或房地产)的所有权。 + +如果您想了解更多关于ERC721令牌标准的信息,请查看其以以太坊改进提案的规范。 + +## 接口 + +ERC721标准比ERC20标准更复杂,并具有可选扩展功能。符合ERC721规范的合约必须至少实现本节中介绍的ERC721和ERC165接口。 符合ERC721规范的合约必须至少实现本节中介绍的ERC721和ERC165接口。 + +此接口(第11行)是OpenZeppelin提供的开源合约库之一。 + +## 基础IERC721函数 + +符合ERC721标准的合约必须实现以下函数: + +### balanceOf + +函数`balanceOf`(第30行)返回地址`owner`拥有数量的token数量。 + +### ownerOf + +函数`ownerOf`(第39行)返回持有`tokenId`的账户地址。 + +### safeTransferFrom + +函数`safeTransferFrom`(第55行)将`tokenId`的所属权从地址`from`拥有者转移到地址`to`拥有者名下. + +该函数`safeTransferFrom`(第137行)与函数`safeTransferFrom`(第55行)几乎相同。唯一的区别是此函数具有非空有效负载数据。 + +如果要接收转移,则智能合约必须实现 ERC721TokenReceiver 接口。这将确保该合约可以处理ERC721代币转移并防止代币被锁定在无法处理ERC721代币的合约中。 这将确保该合约可以处理ERC721代币转移并防止代币被锁定在无法处理ERC721代币的合约中。 + +### transferFrom + +函数`transferFrom`(第55行)将`tokenId`所属权从地址`from`拥有者转移到地址`to`拥有者名下. + +**建议尽可能使用 safeTransferFrom 而不是 transferFrom。** +`transferFrom`函数不安全,因为它不检查作为传输接收方的智能合约是否已实现`ERC721TokenReceiver`接口并且是否能够处理`ERC721`代币。 + +## 高级IERC721功能 + +### approve + +函数`approve`(第94行)授予地址`to`代表调用该函数的账户管理id为`tokenId`的权限。 + +### getApproved + +函数`getApproved`(第103行)返回获得批准管理id为`tokenId`的token的操作者地址(return var `operator`)。 + +### setApprovalForAll + +函数`setApprovalForAll`(第115行)设置指定地址(输入参数 - operator)拥有调用者账户持有的所有token的权限 (_approved) 。 + +### isApprovedForAll + +如果地址`operator`的账户已获得管理拥有者`owner`持有的token权限,则函数`getApproved`(第103行)返回布尔值 true。 + +## IERC721 Events + +ERC721合约还必须发出以下事件: + +### Transfer + +当id为`tokenId`的token从地址`from`转移到地址`to`时,必须发出`Transfer`事件(第15行)。 + +### Approval + +当具有地址`owner`的账户批准地址`spender`的账户代表其管理id为`tokenId`的token的权限时,必须发出`Approval`事件(第20行)。 + +### ApprovalForAll + +当拥有者`owner`授予或删除操作员,管理其所有token的权限时,必须发出`ApprovalForAll`事件(第25行)。 + +## IERC165 + +除了`ERC721`接口外,符合`ERC721`规范的合约还必须实现`ERC165`接口。 + +通过实现ERC165接口,合约可以声明对特定接口的支持。想要与另一个合约交互的合约可以在进行交易之前查询该合约是否支持此接口,例如向其发送可能不支持的代币。 每个非同质化代币都是独一无二且不可互换的。NFT可以具有不同的属性、行为或权利。非同质化代币用于表示对唯一数字和实物资产(如艺术品、收藏品或房地产)的所有权。 + +IERC721接口导入(第6行)并继承(第11行)了IERC165接口。 + +以下是OpenZeppelins实现ERC165接口的方式: + +``` +interface IERC165 { + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} +``` + +例如,在EIP721中指定的ERC721界面的ERC165标识符为“0x80ac58cd”。 例如,在EIP721中指定的ERC721界面的ERC165标识符为“0x80ac58cd”。学习如何计算接口标识符以及有关改进提案中ERC165更多信息。 + +## 其他接口 + +必须实现IERC721TokenReceiver接口才能接受安全转移。 + +在EIP721中指定了两个可选扩展名用于ERC721合约: + +IERC721Enumerable使合约能够发布其完整的代币列表并使用户可以发现它们。 + +IERC721Metadata使合约能够将附加信息与代币关联。我们将在下一节中更详细地了解这个功能。 我们将在下一节中更详细地了解这个功能。 diff --git a/locales/zh/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md b/locales/zh/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md new file mode 100644 index 000000000..87ae039a6 --- /dev/null +++ b/locales/zh/NFTTokenCourse/erc721-metadata-ipfs/erc721MetadataIpfs.md @@ -0,0 +1,103 @@ +在这个部分,我们将创建元数据并以去中心化的方式存储它。 + +IPFS(星际文件系统)是一种用于以分布式方式存储文件的点对点网络。 IPFS(星际文件系统)是一种用于以分布式方式存储文件的点对点网络。Pinata.cloud 是一个固定服务,允许用户轻松地在 IPFS 网络上托管文件。 + +我们希望将图像和其元数据的 JSON 文件托管到 IPFS 上。 + +### Create Image Folder + +在这个例子中,我们将为三个代币创建元数据。 在这个例子中,我们将为三个代币创建元数据。如下所示,我们创建了三张图片并将它们存储在一个文件夹中。 + +``` +geo-img +├── geo_1.png +├── geo_2.png +├── geo_3.png +``` + +### 注册Pinata + +现在,我们想要将这些图像托管到某个地方,以便我们可以在代币的元数据中指向它们。 现在,我们想要将这些图像托管到某个地方,以便我们可以在代币的元数据中指向它们。让我们使用去中心化的方式并使用Pinata将它们托管到IPFS。 + +首先您需要有一个 Pinata 帐户。 访问 Pinata.cloud 并创建一个账户。 在 Pinata 上,您最多可以免费上传 1 GB 的数据。 + +注册完成后,您应该会看到`Pin Manager`视图。 + +Pin Manager Pinata + +### 将图片上传到IPFS + +点击上传按钮并上传包含您的图像的文件夹。 +点击上传按钮并上传包含您的图像的文件夹。一旦您上传了文件夹,您应该会看到文件夹名称和与之关联的CID(内容标识符)。如果文件夹中的内容发生更改,则CID也会更改。 如果文件夹中的内容发生更改,则CID也会更改。 + +要在IPFS上访问您的文件夹,请输入此地址"https://ipfs.io/ipfs/"并添加您的CID。对于我们当前的示例,您可以使用以下方式访问您的文件夹: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P 对于我们当前的示例,您可以使用以下方式访问您的文件夹: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P + +通过使用以下方式,可以访问特定图像: +https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png + +### Create JSON files + +我们创建另一个文件夹,其中包含三个JSON文件。 + +``` +geo-json +├── 0 +├── 1 +├── 2 +``` + +在JSON文件中,为代币创建元数据,例如名称、描述和图像。 +对于图像URL,我们将使用IPFS上的图像URL。 如果您愿意,可以添加其他数据;在此示例中,我们为每个代币添加了一些独特属性。 + +以下是第一个代币的JSON示例: + +``` +{ + "name": "Geometry#0", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_1.png +", + "attributes": [ + { "trait_type": "background", "value": "cyan" }, + { "trait_type": "color", "value": "red" }, + { "trait_type": "shape", "value": "circle" } + ] +} +``` + +第二个代币的JSON可能如下所示: + +``` +{ + "name": "Geometry#1", + "description": "Geometry is an NFT collection for educational purposes.", + "image": "https://ipfs.io/ipfs/QmTJok2tju9zstjtAqESdZxTiUiFCBAyApHiDVj4maV75P/geo_2.png", + "attributes": [ + { "trait_type": "background", "value": "magenta" }, + { "trait_type": "color", "value": "green" }, + { "trait_type": "shape", "value": "square" } + ] +} +``` + +如上所示,此示例中的文件夹名为“geo-json”。 在JSON文件中,为代币创建元数据,例如名称、描述和图像。对于图像URL,我们将使用IPFS上的图像URL。如果您愿意,可以添加其他数据;在此示例中,我们为每个代币添加了一些独特属性。 +如上所示,此示例中的文件夹名为“geo-json”。在该文件夹内,我们有三个JSON文件。第一个JSON文件名为“0”,第二个JSON文件名为“1”,第三个JSON文件名为“2”。 + +确保您的JSON文件没有扩展名,并按其对应的tokenIds进行命名。在pinata.cloud上的pin manager中,单击上传按钮并上传包含您的JSON文件的整个文件夹。 +首先,您需要在Pinata.cloud上创建一个帐户。您可以免费上传高达1GB的数据。 + +要访问IPFS上的您的文件夹,请输入此地址"https://ipfs.io/ipfs/"并添加CID。对于我们当前的示例,您可以使用以下方式访问您的文件夹: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp +这将成为我们的baseURI。 +对于我们当前的示例,您可以使用以下方式访问您的文件夹: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp +这将成为我们的baseURI。 + +然后只需通过添加斜杠和tokenId即可访问特定JSON文件: +https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/0 + +在合约中用自己的baseURI替换原来的baseURI。 在合约中用自己的baseURI替换原来的baseURI。在本例中,baseURI由URL"https://ipfs.io/ipfs/"、包含JSON文件的CID和一个斜杠“/”。 + +现在,通过将tokenId添加到baseURI来为每个代币创建单独的tokenURI —— 就像我们在上面的示例中手动访问JSON文件一样。 diff --git a/locales/zh/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md b/locales/zh/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md new file mode 100644 index 000000000..f204752fa --- /dev/null +++ b/locales/zh/NFTTokenCourse/erc721-token-creation/erc721TokenCreation.md @@ -0,0 +1,34 @@ +在本合约中,我们使用了OpenZeppelin的ERC721代币合约实现(第4行)。 + +请查看他们的ERC721 合约实现。除了符合ERC721标准规定的功能外,该合约还提供了一些额外的函数,稍后我们将会看到。 除了符合ERC721标准规定的功能外,该合约还提供了一些额外的函数,稍后我们将会看到。 + +## myToken + +我们创建了一个名为MyToken的合约(第7行),该合约继承了我们导入的OpenZepplin ERC721代币合约实现和Ownable(第4行)。如果您不记得Ownable合约,请查看ERC20扩展部分。 如果您不记得Ownable合约,请查看ERC20扩展部分。 + +ERC721实现使用了在EIP中指定的IERC721Metadata扩展。 我们的合约继承函数`name()`和`symbol()`,并具有允许在部署合约时设置它们值的构造函数(第8行)。 +在这种情况下,我们将使用默认值。 我们将代币命名为与合约 `"MyToken"` 相同的名称,并将 `"MTK"` 作为其符号。 + +### baseURI + +使用ERC721合约,我们能够铸造各种代币,每个代币都有自己的tokenId。 正如我们在IERC721Metadata接口中看到的那样,每个代币可以拥有自己的 `tokenURI`,通常指向一个JSON文件来存储元数据,例如名称、描述和图像链接。 +如果合约铸造多个代币,ERC721 实现通常使用相同的 URI 作为所有代币的基础 (`baseURI`),并且仅通过串联在末尾添加其唯一的 `tokenId` 来区分它们。 在下一部分中,我们将看到这在实践中是什么样子。 + +在此示例中,我们将数据存储在IPFS上——关于此内容,请参见下一节。 在此示例中,我们将数据存储在IPFS上——关于此内容,请参见下一节。我们的baseURI是https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/(第11行)。通过连接操作,在id为0的代币tokenURI是https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/0,在id为1 的代币tokenURI是https://ipfs.io/ipfs/QmUYLUKwqX6CaZxeiYGwmAYeEkeTsV4cHNZJmCesuu3xKy/1等等。 +使用ERC721合约,我们能够铸造各种代币,每个代币都有自己的tokenId。正如我们在IERC721Metadata接口中看到的那样,每个代币可以拥有自己的`tokenURI`,通常指向一个JSON文件来存储元数据,例如名称、描述和图像链接。如果一个合约铸造多个代币,则ERC721实现通常使用相同的URI,只通过不同的tokenId来区分它们。在下一部分中,我们将看到这在实践中是什么样子。 + +当使用IPFS遇到“504网关超时”错误时,您可能需要等待并重试,直到数据可用。 + +### safeMint + +通过safeMint函数(第14行),我们使所有者能够在合约部署后使用专用代币ID创建新的代币。 +通过safeMint函数(第14行),我们使所有者能够在合约部署后使用专用代币ID创建新的代币。safeMint函数是OpenZeppelin ERC721实现的一部分,它让我们安全地将`tokenId`的ID代币铸造到地址为`to`的账户中。对于访问控制,我们使用了导入的Ownable访问控制合约模块中的onlyOwner修饰符(第5行)。 对于访问控制,我们使用了导入的Ownable访问控制合约模块中的 `onlyOwner` 修饰符(第5行)。 + +在下一节中,我们将看到如何为NFT创建和托管元数据。 + +## ⭐️ 作业 + +1. 将您的合约名称更改为`Geometry`。 +2. 将您的代币名称更改为`Geometry`。 +3. 将您代币符号更改为`GEO`。 +4. 将`_baseURI`更改为https://ipfs.io/ipfs/QmVrsYxXh5PzTfkKZr1MfUN6PotJj8VQkGQ3kGyBNVKtqp/。 diff --git a/locales/zh/NFTTokenCourse/introduction/introduction.md b/locales/zh/NFTTokenCourse/introduction/introduction.md new file mode 100644 index 000000000..4efed6ff4 --- /dev/null +++ b/locales/zh/NFTTokenCourse/introduction/introduction.md @@ -0,0 +1,63 @@ +在本课程的这部分中,我们将为您介绍基于区块链的代币理论。 + +区块链代币是由区块链技术创建的模块(就像网站对互联网),它实现了去中心化、主权独立的互联网(Web3)。 + +### 简介 + +在Web3环境下,代币表示所有权。 在Web3环境下,代币表示所有权。代币可以表示任何东西的所有权:艺术品、声誉、视频游戏中的物品、公司股份、投票权或货币等。 + +区块链技术所具备革命性创新之处在于它允许数据以不可变(无法更改)方式公开存储。 +这种新形式的数据存储方式使我们能够跟踪所有权并首次实现真正可拥有数字物品。 + +最初发明区块链技术是为了跟踪比特币的所有权(比特币是一种去中心化数字货币和同质化代币)。 + +### 同质化和非同质化代币 + +像钱这样的资产:例如,比特币或一美元纸钞,都是同质化的。 同质意味着所有资产都相同且可以互换。 而像艺术品、收藏品或房屋等资产则是非同质化的,它们都不同且不能互换。 + +我们可以将代币分为这两种类型:同质化代币,其中所有代币都相同;以及非同质化代币(NFTs),其中每个代币都是独一无二的。 + +### 代币标准 + +一个代币的行为是在其智能合约(代币合约)中指定的。 该合约可以包括转移代币或检查其总供应量等功能。 + +如果每个人都创建自己具有不同行为和命名惯例的代币合约,那么人们将很难构建与其他人交互的合约或应用程序。 + +以太坊社区已经开发了代币标准,定义了开发者如何创建可与其他合约、产品和服务进行交互(即可互操作)的代币。 根据这些标准开发的合约需要包括一定数量的函数和事件。 + +最流行的代币标准是 ERC20 用于同质化代币和 ERC721 用于非同质化代币。 在本课程中,我们将学习如何创建 NFT(使用 ERC721 代币标准创建的代币)并与之交互。 + +如果您想了解有关同质化代币和 ERC20 代币标准的更多信息,请查看 Learneth ERC20 代币课程。 + +ERC777 是一种同质化代币标准,类似于 ERC20,在保持向后兼容性时包含更高级别特性,例如hooks。 请通过其 EIP(以太坊改进提案)了解有关 ERC777 的更多信息。 + +ERC1155 是一种多代币标准,允许单个合约管理不同类型的代币,例如可同质化、非同质化或半同质化代币。 +请通过其 EIP 了解有关 ERC1155 的更多信息。 + +## ⭐️ 作业 + +对于这个作业,我们将通过一个简短的测验来测试您的知识。 +在`Quiz`合约(第4行)中,将最佳答案的编号分配给变量`question1`(第5行),`question2`(第6行),`question3`(第7行)。 + +### 问题1: + +为什么基于区块链的代币如此具有革命性? + +1. 因为人们现在可以匿名投资。 +2. 因为它们代表了可拥有和转让的数字资产所有权。 +3. 因为你可以使用代币进行交易而无需支付税款。 + +### 问题2: + +社区为什么创建了代币标准? + +1. 以便社区可以控制和批准所创建的代币。 +2. 限制代币功能以进行安全和非恶意操作。 +3. 使社区能够创建与其他合约、产品和服务互通的代币。 + +### Question 3: + +如果您要为棒球交易卡牌游戏创建一个去中心化应用程序,其中每个棒球选手都将由一个代币表示,那么您会使用哪种标准编写该代币合约? + +1. ERC20 +2. ERC721 diff --git a/locales/zh/OpcodesInTheDebugger/1_intro/step.md b/locales/zh/OpcodesInTheDebugger/1_intro/step.md new file mode 100644 index 000000000..505a01fa8 --- /dev/null +++ b/locales/zh/OpcodesInTheDebugger/1_intro/step.md @@ -0,0 +1,5 @@ +本次workshop旨在更好地了解合约如何部署。 +`SimpleStore`是一个非常基础的合约。 +它有一个非常简单的构造函数 - 只使用第一个参数`_o`并将其保存到`s`中。 + +通过调试器,我们将尝试查看操作码`CODECOPY`的作用。 diff --git a/locales/zh/OpcodesInTheDebugger/2_memory/step.md b/locales/zh/OpcodesInTheDebugger/2_memory/step.md new file mode 100644 index 000000000..dd000c7f0 --- /dev/null +++ b/locales/zh/OpcodesInTheDebugger/2_memory/step.md @@ -0,0 +1,8 @@ +在我们开始之前,快速提醒一下: + +EVM的运行时有几种内存类型: + +- `calldata`:这是交易所提供的输入值。 +- `stack`: 基本上,这是一个值列表,每个值都有大小限制(32字节)。 +- `memory`:当要存储的值类型更复杂(如数组或映射)时使用内存。此内存是临时性的,并在执行结束时释放。 此内存是**临时性的**,并在执行结束时**释放**。 +- `storage`:这是一个映射,每个存储的值都被持久化并保存在链上。 diff --git a/locales/zh/OpcodesInTheDebugger/3_codecopy/step.md b/locales/zh/OpcodesInTheDebugger/3_codecopy/step.md new file mode 100644 index 000000000..73aa6bc7e --- /dev/null +++ b/locales/zh/OpcodesInTheDebugger/3_codecopy/step.md @@ -0,0 +1,7 @@ +CODECOPY是EVM运行的众多操作码之一。请访问https://ethervm.io/查看完整的操作码列表。 请访问https://ethervm.io/查看完整的操作码列表。 + +CODECOPY将正在运行的代码(或其中一部分)从`calldata`复制到`memory`中。 + +Solidity实现为:**codecopy(t,f,s)** - 从位置**f**处的代码复制**s**个字节到位置**t**处的内存中。 + +每次合约部署都会使用CODECOPY。 diff --git a/locales/zh/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md b/locales/zh/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md new file mode 100644 index 000000000..7c8cbd185 --- /dev/null +++ b/locales/zh/OpcodesInTheDebugger/4_Deployment_and_CODECOPY/step.md @@ -0,0 +1,11 @@ +我们回到我们的合约。 +让我们回到合约上。请确保激活了`Solidity compiler`和`Deploy&Run Transactions`。 + +或者,您可以从`主页` **Environments** 部分单击`Solidity`。 + +- 从`solidity compiler`编译合约。 +- 转到`Deploy&Run Transactions`,并确保选择了`SimpleStore`合约。 +- 在`Deploy`右侧的文本框中输入正整数。 +- 点击`Deploy`. + +在下一步中,我们将在调试器中观察部署过程。 diff --git a/locales/zh/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md b/locales/zh/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md new file mode 100644 index 000000000..672d80b37 --- /dev/null +++ b/locales/zh/OpcodesInTheDebugger/5_Debugger_and_CODECOPY/step.md @@ -0,0 +1,7 @@ +从Remix终端,找到部署合约的交易并单击`Debug`。 + +在编辑器的沟槽中,在行`s = _o`上设置断点,并单击跳转到下一个断点(右下角按钮)。 + +点击`Step into`,沿着操作码移动,直到达到`SSTORE`。 + +`SSTORE`是将值`_o`存储在存储器中的操作码。让我们进一步进行`CODECOPY`。 让我们继续讨论 `CODECOPY` 。 diff --git a/locales/zh/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md b/locales/zh/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md new file mode 100644 index 000000000..3dcb00902 --- /dev/null +++ b/locales/zh/OpcodesInTheDebugger/6_Checking_CODECOPY/step.md @@ -0,0 +1,57 @@ +这里的目标是将代码存储在区块链中。 EVM 需要告诉客户端(geth、parity)要存储 **Call Data** 的哪一部分。 在这一步中,我们保存的是合约,不包括其构造函数(因为构造函数只被添加一次),也不包括不需要保存的输入参数。 + +`CODECOPY`是第一步:它将字节码复制到内存中,然后以太坊客户端就能够使用它。咀嚼! 咀嚼! + +但是,等等… 但是...在客户端可以处理字节码之前,它需要一个指令 - 一个操作码来告诉它进行处理。`RETURN`就是这个操作码! `RETURN` 就是这个操作码! + +根据通用规范,在合约创建的结尾处,客户端(geth、parity)通过操作码`RETURN`获取目标值,并通过使其成为部署的字节码的一部分而将其持久化。 + +一旦进入`CODECOPY`,请查看堆栈中的前3个项目: + +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x0000000000000000000000000000000000000000000000000000000000000055` +`2: 0x000000000000000000000000000000000000000000000000000000000000003e` + +_在您的Stack中,1和2可能略有不同。这种差异可能是由于不同的编译器版本造成的。_ 这种差异可能是由于不同的编译器版本造成的。\* + +**这些是`CODECOPY`的参数。** + +记住:_codecopy(t, f, s)_ - 将来自位置**f**处代码的**s**个字节复制到位置**t**处内存 + +`0x0`、`0x10`等是位置。下一个数字是该位置的字节码。然后跟着问号和看似随机的字母和数字。这是Remix尝试将其转换为字符串。 在此示例中,(全零)代码被复制到内存的开头。 `0` 是应将复制代码放置在内存中的偏移量。在此示例中(全零),该代码被复制到内存开头。(t) +`1` 是要从其中进行复制的**calldata**中的偏移量(**f**) +`2` 要复制的字节数 - (**s**) + +执行`CODECOPY`后(单击“step into”按钮),所复制的代码应为: +`0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c63430005110032` 在内存中。**我将把这个值称为(X)。** **我将把这个值称为(X)**。 + +让我们来看一下调试器的**内存**面板。 +让我们来看一下调试器的内存面板。我上面给出的0x数字并不是您在内存面板中看到的内容 - 您将会看到: +0x0: 6080604052600080fdfea265627a7a72 ????R??????ebzzr +0x10: 31582029bb0975555a15a155e2cf28e0 1X ?? uUZ??U???? +0x20: 25c8d492f0613bfb5cbf96399f6dbd4e ?????a?????9?m?N +0x30: a6fc9164736f6c634300051100320000 ???dsolcC????2?? +0x40: 00000000000000000000000000000000 ???????????????? +0x50: 000000000000000000000000000000a0 ??????????????? +0x60: 00000000000000000000000000000000 ???????????????? +0x70: 00000000000000000000000000000000 ???????????????? +0x80: 00000000000000000000000000000000 ???????????????? +0x90: 00000000000000000000000000000002 ???????????????? + +`0x0`, `0x10`, 等是其位置。 接下来的数字是该位置的字节码。 接下来是问号和看似随机的字母和数字。 这是 **Remix** 尝试将其转换为字符串。 + +因此,如果我们将前四个字节码部分粘合在一起,我们会得到: +**0x6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e0a6fc9164736f6c63430005110032** +最后一部分 - `0x90`是2,这就是我为构造函数参数输入的内容。 + +来自`Call Data`面板的输入数据为: +`0x6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe6080604052600080fdfea265627a7a7231582029bb0975555a15a155e2cf28e025c8d492f0613bfb5cbf96399f6dbd4ea6fc9164736f6c634300051100320000000000000000000000000000000000000000000000000000000000000002` +**将此值称为(Y)。** + +这告诉我们`(X)`是原始calldata`(Y)`的子集: + +`(X)`是一个calldata,没有输入参数`00000000000000000000000000000000000000000002`(我们不需要存储此内容)和构造函数代码`6080604052348015600f57600080fd5b506040516093380380609383398181016040526020811015602f57600080fd5b81019080805190602001909291905050508060008190555050603e8060556000396000f3fe`,应仅执行1次。 + +因此,`CODECOPY`从calldata中提取字节码并将其复制到内存中。 + +让我们进入下一步。 diff --git a/locales/zh/OpcodesInTheDebugger/7_returnAndStore/step.md b/locales/zh/OpcodesInTheDebugger/7_returnAndStore/step.md new file mode 100644 index 000000000..baad1c581 --- /dev/null +++ b/locales/zh/OpcodesInTheDebugger/7_returnAndStore/step.md @@ -0,0 +1,18 @@ +# 字节码RETURN + +在上一章的结尾,我们已经移动到**CODECOPY**之后的一个步骤,以查看内存中发生了什么。 + +现在CODECOPY已经执行完毕,我们处于操作码`PUSH1 00`。 + +`PUSH1 00`为`RETURN`操作码准备了堆栈。`RETURN`是这个过程的最后部分。它将代码返回给客户端。 +`RETURN`是这个过程的最后部分。 它将代码返回给客户端。 + +我们将`00`推入堆栈,因为这是合约字节码在内存中的偏移位置。 + +现在我们可以调用非常重要的`RETURN`操作码了。 + +**stack inspector** 显示: +`0: 0x0000000000000000000000000000000000000000000000000000000000000000` +`1: 0x000000000000000000000000000000000000000000000000000000000000003e` + +也就是说它把从`0x00`开始长度为`0x3e`的字节码返回给客户端。 diff --git a/locales/zh/OpcodesInTheDebugger/8_findTheOffset/step.md b/locales/zh/OpcodesInTheDebugger/8_findTheOffset/step.md new file mode 100644 index 000000000..24de2e09f --- /dev/null +++ b/locales/zh/OpcodesInTheDebugger/8_findTheOffset/step.md @@ -0,0 +1,17 @@ +# 找到偏移量 ;) + +现在来看一个稍微不同的例子: + +- 编译 notSimpleStore.sol +- 部署合约 `notSoSimpleStore` +- 确保您已成功部署 - 如果没有,请检查您在构造函数中使用了正确的输入类型。 +- 通过单击(成功)创建交易时的`Debug`按钮进入调试器。 +- 找到`CODECOPY`的参数值,该参数表示从 calldata 中要复制的偏移量位置。 + +记住:_codecopy(t, f, s)_ - 从位置 **f** 处代码复制 **s** 字节到位置 **t** 处内存 + +如果您查看**Stack**,应该会看到第二个元素是:0x0000000000000000000000000000000000000083 + +这就是 codecopy 输入参数中 f 的值。 + +### 希望你学习了一些关于操作码如何工作的知识! diff --git a/locales/zh/OpcodesInTheDebugger/config.yml b/locales/zh/OpcodesInTheDebugger/config.yml new file mode 100644 index 000000000..74a1bf3a1 --- /dev/null +++ b/locales/zh/OpcodesInTheDebugger/config.yml @@ -0,0 +1,10 @@ +--- +id: opcodesdebug +name: Opcodes in the Debugger +summary: Using the Debugger, we'll check out what the CODECOPY opcode does and how it is used by the EVM during contract creation. +level: 3 +tags: + - Remix + - Debugging + - EVM + - Opcodes diff --git a/locales/zh/ProxyContract/1_Why/step1.md b/locales/zh/ProxyContract/1_Why/step1.md new file mode 100644 index 000000000..47a2cee25 --- /dev/null +++ b/locales/zh/ProxyContract/1_Why/step1.md @@ -0,0 +1,27 @@ +# 代理合约,又称分发器 + +## 为什么要使用它? + +这是一个主要用于库开发的优秀模式。 + +它通过以下方式提供帮助: + +- **在部署时节省燃气成本** + 高昂的燃气成本目的是阻止执行成本高昂的操作,并鼓励优化代码。 + +- 当需要部署许多相同合约实例时,代理合约非常有用,因为它们减少了部署中的重复性。 + +- **避免区块链中出现代码重复** + 由于每个节点都需要执行大量计算,所以复杂计算很昂贵,这会拖慢网络速度。 + +- **开发可升级(版本化)合约** + 当合约被部署后就不可变了。通过将代码重新设计为不同的合约形式,可以实现逻辑升级而保持存储不变。 它有以下几个好处: + +## 燃气成本示例 + +创建时存储合约代码最多可能耗费: + +- 200 \* max_byte_code_length gas +- 200 \* 24576 = 49152004915200 \* 10 gwei = 49152000 gwei = 0.049152 ether = 9 EUR + +更多关于max_byte_code_length信息,请参见 https://github.com/ethereum/EIPs/blob/master/EIPS/eip-170.md diff --git a/locales/zh/ProxyContract/2_How/step2.md b/locales/zh/ProxyContract/2_How/step2.md new file mode 100644 index 000000000..d8cb91ecf --- /dev/null +++ b/locales/zh/ProxyContract/2_How/step2.md @@ -0,0 +1,13 @@ +# 它是如何工作的? + +**EIP-7 DelegateCall**操作码允许在保持原始执行上下文的同时,在另一个合约中进行单独的执行。 + +所有用户发起的消息调用都经过代理合约。 + +然后,**代理合约**会将它们重定向到**逻辑合约**。 + +当您需要**升级**逻辑时,您**只需**部署该逻辑 - **但是** - 代理的实现将保持不变。 + +您只需要在代理合约中更新逻辑合约地址即可。 + +代理合约使用**Delegate calls**和**Solidity assembly**,因为如果没有这些内容,则无法从**delegatecall**返回任何值。 diff --git a/locales/zh/ProxyContract/3_Delegatecall/step3.md b/locales/zh/ProxyContract/3_Delegatecall/step3.md new file mode 100644 index 000000000..cd0b2479d --- /dev/null +++ b/locales/zh/ProxyContract/3_Delegatecall/step3.md @@ -0,0 +1,9 @@ +# Delegate call + +它是**message call**的一种特殊变体,目标地址的代码使用调用合约的上下文执行,msg.sender和msg.value在目标合约中的值和调用合约的值一样。 + +这意味着一个合约可以在运行时从不同的地址动态加载代码。 + +存储、当前地址和余额仍然指向调用合约,只有代码来自被调用地址。 + +当代理将调用委托给逻辑合约时,每个存储修改都会影响逻辑合约的存储。 diff --git a/locales/zh/ProxyContract/4_Generic_proxy_example/step4.md b/locales/zh/ProxyContract/4_Generic_proxy_example/step4.md new file mode 100644 index 000000000..01b5d919c --- /dev/null +++ b/locales/zh/ProxyContract/4_Generic_proxy_example/step4.md @@ -0,0 +1,15 @@ +# 一个基本的通用代理示例 + +在关联的solidity文件**step4.sol**中,有两个合约 - **ProxyContract** 和 **LogicContract**。 + +要使用此系统,我们首先部署LogicContract。 + +然后当我们去部署ProxyContract时,将LogicContract的地址作为ProxyContract构造函数的参数传递。 + +只部署一次ProxyContract。 + +LogicContract代码将在第20行调用。它将被委托调用,并保持LogicContract上下文不变。 它将被委托调用,并保持LogicContract上下文不变。 + +如果需要更改逻辑,则会部署新的LogicContract并使用setLogicContracAddress设置器函数设置其地址。 + +_注意:这里使用的LogicConract不使用存储。一旦需要使用存储,实现就会变得更加复杂,因为这些合同共享上下文。_ 一旦需要使用存储,实现就会变得更加复杂,因为这些合同共享上下文。\* diff --git a/locales/zh/ProxyContract/5_Test/step5.md b/locales/zh/ProxyContract/5_Test/step5.md new file mode 100644 index 000000000..cf3949388 --- /dev/null +++ b/locales/zh/ProxyContract/5_Test/step5.md @@ -0,0 +1,6 @@ +# 让我们测试一下所学的知识 + +- 编写一个名为“LogicContract”的合约,其中实现了一个名为“getNumber”的公共函数,该函数返回10。 +- 编写一个名为“ProxyContract”的代理合约。 编写一个名为“ProxyContract”的代理合约。这个代理合约应该将LogicContract的地址作为第一个参数。 + +祝你好运! diff --git a/locales/zh/ProxyContract/6_Storage_Problem/step6.md b/locales/zh/ProxyContract/6_Storage_Problem/step6.md new file mode 100644 index 000000000..51287b62a --- /dev/null +++ b/locales/zh/ProxyContract/6_Storage_Problem/step6.md @@ -0,0 +1,13 @@ +# 如果我们有状态变量怎么办? + +当我们需要处理状态变量时,事情就会变得更加复杂。状态变量保存在**storage**中。 注意:静态状态变量(除了映射和动态数组类型之外的所有内容)从位置0开始连续地存储在storage中。如果可能,需要少于32字节的多个连续项将被打包到单个存储槽中。对于使用继承的合同,状态变量的排序由以最基础合约为起点的C3线性化顺序确定。 + +`storage`:是一种映射;其中每个值都被持久化并保存在链上。 + +_注意:静态状态变量(除了映射和动态数组类型之外的所有内容)从位置0开始连续地存储在storage中。 如果可能,需要少于32字节的多个连续项将被打包到单个存储槽中。 对于使用继承的合约,状态变量的顺序由合约的 C3 线性顺序决定,从最基础的 ward 合约开始_ + +一旦执行**delegate call**,两个合约的存储空间就会“合并”成一个混乱的状态。 + +我们必须“告诉”ProxyContract逻辑合约的状态看起来是什么样子。 + +最简单的方法是创建一个名为StorageContract 的独立合约代表该状态,并且proxyContract也将从它那里继承。 diff --git a/locales/zh/ProxyContract/7_links/step7.md b/locales/zh/ProxyContract/7_links/step7.md new file mode 100644 index 000000000..3361c6607 --- /dev/null +++ b/locales/zh/ProxyContract/7_links/step7.md @@ -0,0 +1,20 @@ +# 查看以下链接以获取更多信息 + +- ERC DelegateProxy + https://github.com/ethereum/EIPs/pull/897 + +- Zeppelin Solutions和Aragon的联合发布的文章 + Zeppelin Solutions和Aragon的联合文章 + https://blog.openzeppelin.com/proxy-libraries-in-solidity-79fbe4b970fd/ + +- OpenZeppelin的代理模式 + https://blog.openzeppelin.com/proxy-patterns/ + +- 最成熟的代理模式实现是作为ZeppelinOS一部分发布的The Unstructure Storage pattern + https://blog.openzeppelin.com/upgradeability-using-unstructured-storage/ + +- Jack Tanner撰写了一篇很棒的博客文章 + https://blog.indorse.io/ethereum-upgradeable-smart-contract-strategies-456350d0557c + +- 可升级Ethereum智能合约 + https://medium.com/@daonomic/upgradeable-ethereum-smart-contracts-d036cb373d6 diff --git a/locales/zh/ProxyContract/README.md b/locales/zh/ProxyContract/README.md new file mode 100644 index 000000000..3626cdc63 --- /dev/null +++ b/locales/zh/ProxyContract/README.md @@ -0,0 +1,3 @@ +## 学习代理模式 + +节省gas & 制作可升级的合约 diff --git a/locales/zh/ProxyContract/config.yml b/locales/zh/ProxyContract/config.yml new file mode 100644 index 000000000..e36e640b8 --- /dev/null +++ b/locales/zh/ProxyContract/config.yml @@ -0,0 +1,9 @@ +--- +id: proxycontract +name: All about Proxy Contracts +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 3 +tags: + - Remix + - Solidity + - Code Patterns diff --git a/locales/zh/README.md b/locales/zh/README.md new file mode 100644 index 000000000..892818728 --- /dev/null +++ b/locales/zh/README.md @@ -0,0 +1,36 @@ +# 这是一个关于 Remix 的 LearnEth 插件的教程仓库 + +### 如何使用这些教程: + +**1. 打开 Remix** + +https://remix.ethereum.org + +**2. 在插件管理器中激活 LEARNETH** + +**3. 前往 Learneth 插件, 这些教程将默认加载** + +**4. 在教程使用期间,您可能需要登录Github** + +除非你已登录Github并输入你的 token ,否则Github会阻止来自同一位置的过多请求。 一般来说,这只是教程使用过程中会出现的问题,当来自同一地点的请求很多时,就会出现这种情况。 + +输入您的Github token: + +``` +- 在一个浏览器窗口中 - 访问 https://remix.ethereum.org 并进入设置模块 +- 在另一个浏览器窗口中访问: + +https://github.com/settings/tokens + +并创建一个新的 token ,并将其保存在你刚才打开的 Remix 的设置模块中。 +``` + +--- + +### 为 LEARNETH 编写您自己的教程: + +在此站点查看编写说明: + +https://remix-learneth-plugin.readthedocs.io/en/latest/index.html#creating-tutorials + +--- diff --git a/locales/zh/Recorder/1_Usecases/1_usecases.md b/locales/zh/Recorder/1_Usecases/1_usecases.md new file mode 100644 index 000000000..85335d1f1 --- /dev/null +++ b/locales/zh/Recorder/1_Usecases/1_usecases.md @@ -0,0 +1,7 @@ +1. 你想向某人展示当您与合约进行多个交易时会发生什么,而且您不想解释每一步 - 您只想让他们到达最后一步。 + + - 向某人展示其代码中的问题。 + + - 在课堂上,将学生带到特定位置并让他们从那里开始工作。 + +2. 您希望在JavascriptVM中开始开发,因为它很快,然后切换到另一个测试网络 - 但是您不想手动重复所有繁琐的点击操作以适应每个不同的网络。 diff --git a/locales/zh/Recorder/2_Record/README.md b/locales/zh/Recorder/2_Record/README.md new file mode 100644 index 000000000..4ab69c7f6 --- /dev/null +++ b/locales/zh/Recorder/2_Record/README.md @@ -0,0 +1,33 @@ +# 设置一系列繁琐的步骤 + +## 接下来可能会变得乏味,但这就是重点。 + +我们将要: + +- 部署一个投票合约,在构造函数中输入3个提案。 +- 授予2个额外地址投票权限(因此我们总共有3个投票地址)。 +- 让一个地址为提案1(基于0的索引)进行投票,另外两个地址为提案2进行投票。 + +1. 从示例Solidity文件中获取3_Ballot.sol并编译它。然后进入“Deploy & Run Module”。 然后进入“Deploy & Run” 模块。 + +2. 选择JavaScript VM环境。 + +3. 在构造函数参数中-输入["0x50310000000000000000000000000000000000000000000 0 0 0 0", "0x50320000 00 00 00 00, "Ox503300OOOOOOOOOOOOO"],然后单击“Deploy”按钮。 + +4. 打开已部署的合约。 + +5. 在**vote**函数中输入2。 在`vote`函数中输入2。这意味着您作为`msg.sender`和`chairperson`正在对列表中位置2处的提案进行投票,即我们列表中的最后一个提案。 + +6. 现在您需要赋予其他地址投票权利。 在**帐户**下拉菜单中选择另一个地址并复制它,然后**返回到第1个地址**。 将复制的地址粘贴到 giveRightToVote 函数旁边的文本框中。 现在您需要赋予其他地址投票权利。在帐户下拉菜单中选择另一个地址并复制它,然后返回到第1个地址。将复制的地址粘贴到`giveRightToVote`函数旁边的文本框中。再次选择另一个地址并复制它,然后再回到第1个地址并将其粘贴到`giveRightToVote`中。 + +7. 现在您有3个具有投票权的地址。 + +8. 切换到您授予投票权的其中一个地址,并为提案1进行投票(在vote函数旁边的文本框中输入1)。然后切换到另一个地址,并使用该地址为提案2进行投票。 (在vote函数旁边的文本框中输入 **1**) 然后切换到另一个地址,并使用该地址为提案 **2** 进行投票。 + +9. 打开模块中的 **交易记录** - 单击这个插入符。 单击 **记录交易** 中的硬盘图标以保存您的步骤。 + 通过单击插入符号打开模块中的交易记录,点击保存图标来保存上述步骤。 + ![recorder](https://github.com/ethereum/remix-workshops/blob/master/Recorder/2_Record/images/recorder.png?raw=true "recorder") + +10. 你会得到一个模态窗口,告诉你它想要保存名为**scenario.json**的文件。点击“确定”。 点击确定。 + +11. 单击**winningProposal**函数以确认最终提案获胜-即数组中位置2处的提案。**0: uint256: winningProposal_ 2** 按照这个流程可能会变得很乏味,但这正是重点。 diff --git a/locales/zh/Recorder/3_Editing_a_Senario/README.md b/locales/zh/Recorder/3_Editing_a_Senario/README.md new file mode 100644 index 000000000..c27bc1ab9 --- /dev/null +++ b/locales/zh/Recorder/3_Editing_a_Senario/README.md @@ -0,0 +1,54 @@ +# 编辑一个场景 + +这是我录制的场景的前几行。 我这儿的地址与您的不同。 + +``` +{ + "accounts": { + "account{0}": "0xca35b7d915458ef540ade6068dfe2f44e8fa733c", + "account{4}": "0xdd870fa1b7c4700f2bd7f44238821c26f7392148", + "account{3}": "0x583031d1113ad414f02576bd6afabfb302140225" + } +``` + +如果您想在另一个测试网络中运行此场景,则需要将这些地址更改为您拥有测试ETH的地址,以便支付交易费用。但是除了更换地址之外,您可以快速在其他网络上运行它。 但是除了更换地址之外,您可以快速在其他网络上运行它。 + +并且您可能会更改函数的参数。 + +例如,这是scenario.json的一部分,提案2被其中一个地址投票支持: + +``` +{ + "timestamp": 1566428184043, + "record": { + "value": "0", + "parameters": [ + "2" + ], + "to": "created{1566428035436}", + "abi": "0xc41589e7559804ea4a2080dad19d876a024ccb05117835447d72ce08c1d020ec", + "name": "vote", + "inputs": "(uint8)", + "type": "function", + "from": "account{4}" + } + }, +``` + +让我们编辑一下,以便在回放中另一个提案获胜。 + +将参数数组更改为: + +``` +"parameters": [ + "2" + ] +``` + +to: + +``` +"parameters": [ + "1" + ] +``` diff --git a/locales/zh/Recorder/4_Play/README.md b/locales/zh/Recorder/4_Play/README.md new file mode 100644 index 000000000..bc2234d09 --- /dev/null +++ b/locales/zh/Recorder/4_Play/README.md @@ -0,0 +1,9 @@ +# 重放场景 + +1. 单击保存图标右侧的播放图标以播放您执行的步骤。 + +2. 您将看到合约的另一个实例已部署。打开它。 打开它。 + +3. 单击 winningProposal 函数,现在应该可以看到提案 1 获胜。 + 单击`winningProposal`函数,现在应该可以看到提案1获胜。 + 它应该会输出:**0: uint256: winningProposal_ 1** diff --git a/locales/zh/Recorder/README.md b/locales/zh/Recorder/README.md new file mode 100644 index 000000000..53dc641c8 --- /dev/null +++ b/locales/zh/Recorder/README.md @@ -0,0 +1,3 @@ +## 自个儿 Remixing 吧! + +录制器用于在部署和运行模块中记录一系列交易,编辑它们的参数,然后在另一个上下文中重放它们。这真是Remix的混音版本! 这真是Remix的混音版本! diff --git a/locales/zh/Recorder/config.yml b/locales/zh/Recorder/config.yml new file mode 100644 index 000000000..b8980e042 --- /dev/null +++ b/locales/zh/Recorder/config.yml @@ -0,0 +1,7 @@ +--- +id: recorder +name: Recorder +summary: Save a set of actions and replay and replay and replay +level: 2 +tags: + - Remix diff --git a/locales/zh/SolidityBeginnerCourse/README.md b/locales/zh/SolidityBeginnerCourse/README.md new file mode 100644 index 000000000..5a8b4459a --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/README.md @@ -0,0 +1,5 @@ +## 交互式 Solidity 课程 + +基于流行的 https://solidity-by-example.org/ 合约,以交互方式学习最重要的 Solidity 初级概念。 + +由p2p学习平台 https://dacade.org 开发。 diff --git a/locales/zh/SolidityBeginnerCourse/basic-syntax/basicSyntax.md b/locales/zh/SolidityBeginnerCourse/basic-syntax/basicSyntax.md new file mode 100644 index 000000000..e3cdaa1ba --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/basic-syntax/basicSyntax.md @@ -0,0 +1,26 @@ +在本节中,我们将创建我们的第一个_智能合约_。 在本节中,我们将创建我们的第一个智能合约。该合约仅包含一个字符串,其中包含值"Hello World!"。 + +在第一行中,我们应指定要使用的许可证。 在第一行中,我们应指定要使用的许可证。您可以在此处找到非常全的许可证列表:https://spdx.org/licenses/. + +使用`pragma`关键字(第3行),我们指定Solidity版本,编译器应使用该版本。在这种情况下,它应大于或等于`0.8.3`但小于`0.9.0`。 在这种情况下,它应大于或等于`0.8.3`但小于`0.9.0`。 + +我们用关键字`contract`定义了一个合约,并为其命名,在本例中为`HelloWorld`(第5行)。 + +在合约内部,我们定义了一个状态变量`greet`,其中包含字符串`"Hello World!"`(第6行)。 + +Solidity是一种静态类型语言,这意味着您需要在声明变量时指定变量类型。 在这种情况下,`greet`是一个`string`。 在这种情况下,`greet`是一个`string`。 + +我们还定义了变量的_可见性_,它指定从哪里可以访问它。 我们还定义了变量的可见性,它指定从哪里可以访问它。 在这种情况下,它是`public`类型的变量,在合约内外都可以访问。 + +如果您不理解可见性、数据类型或状态变量等概念,不要担心。我们将在接下来的章节中详细讲解. 我们将在接下来的章节中详细讲解。 + +为了帮助您理解代码,我们将所有后续章节链接到 Solidity 示例合约的创建者制作的视频教程。 + +观看有关基本语法的视频教程。. + +## ⭐️ 作业 + +1. 删除 HelloWorld 合约及其内容。 +2. 创建一个名为 "MyContract" 的新合约。 +3. 该合约应具有名为 "name" 的公共状态变量,类型为字符串。 +4. 将值 "Alice" 分配给您的新变量。 diff --git a/locales/zh/SolidityBeginnerCourse/config.yml b/locales/zh/SolidityBeginnerCourse/config.yml new file mode 100644 index 000000000..a729093d8 --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/config.yml @@ -0,0 +1,65 @@ +--- +id: soliditybeginner +name: Solidity Beginner Course +summary: Solidity Beginner Course based on the popular https://solidity-by-example.org/ contracts. Developed by the p2p learning platform https://dacade.org. +level: 1 +tags: + - Solidity +steps: + - + name: 1. Introduction + path: introduction + - + name: 2. Basic Syntax + path: basic-syntax + - + name: 3. Primitive Data Types + path: primitive-data-types + - + name: 4. Variables + path: variables + - + name: 5.1 Functions - Reading and Writing to a State Variable + path: functions-reading-and-writing + - + name: 5.2 Functions - View and Pure + path: functions-view-and-pure + - + name: 5.3 Functions - Modifiers and Constructors + path: functions-modifiers-and-constructors + - + name: 5.4 Functions - Inputs and Outputs + path: functions-inputs-and-outputs + - + name: 6. Visibility + path: visibility + - + name: 7.1 Control Flow - If/Else + path: control-flow-if-else + - + name: 7.2 Control Flow - Loops + path: control-flow-loops + - + name: 8.1 Data Structures - Arrays + path: data-structures-arrays + - + name: 8.2 Data Structures - Mappings + path: data-structures-mappings + - + name: 8.3 Data Structures - Structs + path: data-structures-structs + - + name: 8.4 Data Structures - Enums + path: data-structures-enums + - + name: 9. Data Locations + path: data-locations + - + name: 10.1 Transactions - Ether and Wei + path: transactions-ether-and-wei + - + name: 10.2 Transactions - Gas and Gas Price + path: transactions-gas-and-gas-price + - + name: 10.3 Transactions - Sending Ether + path: transactions-sending-ether diff --git a/locales/zh/SolidityBeginnerCourse/control-flow-if-else/ifElse.md b/locales/zh/SolidityBeginnerCourse/control-flow-if-else/ifElse.md new file mode 100644 index 000000000..5b5c267a3 --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/control-flow-if-else/ifElse.md @@ -0,0 +1,34 @@ +Solidity支持不同的控制流语句,确定合约的哪些部分将被执行。 Solidity支持不同的控制流语句,确定合约的哪些部分将被执行。条件If/Else语句使合约能够根据布尔条件是`true`还是`false`来做出决策。 + +Solidity区分三种不同的If/Else语句:`if`、`else`和`else if`。 + +### if + +if语句是最基本的语句,允许合约根据布尔表达式执行操作。 + +在此合约的`foo`函数(第5行)中,if语句(第6行)检查`x`是否小于`10`。如果该语句为真,则函数返回`0`。 在此合约中,`foo`函数使用`else`语句(第10行)在未满足其他任何条件时返回`2`。 + +### else + +The `else` statement enables our contract to perform an action if conditions are not met. + +In this contract, the `foo` function uses the `else` statement (line 10) to return `2` if none of the other conditions are met. + +### else if + +使用`else if`语句可以组合多个条件。 + +如果foo函数的第一个条件(第6行)未被满足,但是`else if` 语句的条件(第8行)为真,函数将返回`1`。 + +观看有关If/Else表达式的视频教程。 + +## ⭐️ 作业 + +Create a new function called `evenCheck` in the `IfElse` contract: +在`IfElse`合约中,创建一个名为`evenCheck`的新函数: + +- 它接受一个`uint`作为参数。 +- 如果参数为偶数,则函数返回 true ,否则返回 false。 +- 使用三元运算符返回 evenCheck 函数结果。 + +提示:模数(%)运算符产生整数除法的余数。 diff --git a/locales/zh/SolidityBeginnerCourse/control-flow-loops/loops.md b/locales/zh/SolidityBeginnerCourse/control-flow-loops/loops.md new file mode 100644 index 000000000..100b9bf69 --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/control-flow-loops/loops.md @@ -0,0 +1,32 @@ +Solidity支持循环控制流语句,允许合约重复执行代码。 + +Solidity区分三种类型的循环:`for`、`while`和`do while`循环。 + +### for + +通常情况下,如果您知道要执行某个代码块的次数,则使用`for`循环(第7行)。在solidity中,您应该指定此数量以避免交易用尽gas,并且如果迭代次数过多则失败。 在solidity中,您应该指定此数量以避免交易用尽gas,并且如果迭代次数过多则失败。 + +### while + +如果您不知道要执行代码的次数但想基于条件退出循环,则可以使用`while`循环(第20行)。在Solidity中很少使用循环,因为如果没有限制可能发生太多次迭代,则交易可能会用尽gas并且失败。 +在Solidity中很少使用循环,因为如果没有限制可能发生太多次迭代,则交易可能会用尽gas并且失败。 + +### do while + +`do while`循环是一种特殊类型的`while`循环,在检查条件之前可以确保至少执行一次代码。 + +### continue + +`continue` 语句用于跳过剩余的代码块并开始下一个迭代。 `continue`语句用于跳过剩余的代码块并开始下一个迭代。在这个合约中,`continue`语句(第10行)将防止第二个if语句(第12行)被执行。 + +### break + +`break`语句用于退出一个循环。 `break`语句用于退出一个循环。 在这个合约中,`break`语句(第14行)将导致`for`循环在进行了6次迭代后终止. + +观看有关循环声明的视频教程. + +## ⭐️ 作业 + +1. 在`Loop`合约中,创建名为count的公共`uint`状态变量。 +2. 在for循环结束时,将count变量增加1。 +3. 尝试使count变量等于9,但请确保不改变`break`语句。 diff --git a/locales/zh/SolidityBeginnerCourse/data-locations/dataLocations.md b/locales/zh/SolidityBeginnerCourse/data-locations/dataLocations.md new file mode 100644 index 000000000..bea65f02b --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/data-locations/dataLocations.md @@ -0,0 +1,54 @@ +Solidity中的变量值可以存储在不同的数据位置:memory、storage和calldata。 + +正如我们之前讨论过的,值类型的变量存储一个独立副本,而引用类型(array, struct, mapping)只存储值的位置(引用)。 + +赋值 如果我们在函数中使用引用类型,则必须指定它们的值存储在哪个数据位置。数据位置会影响函数执行价格;从引用类型创建副本需要消耗gas。 + +### Storage + +存储在storage中的值永久地保存在区块链上,因此使用起来很昂贵。 + +在这个合约中,状态变量`arr`、`map`和`myStructs`(第5行、第6行和第10行)都被存储在storage中。状态变量总是被存储在storage中。 状态变量总是被存储在 storage 中。 + +### Memory + +存在于memory中的值仅临时保存,并不会出现在区块链上。它们只存在于外部函数执行期间,并且之后就会被丢弃。与存在于storage中的值相比,它们更便宜易用。 它们只存在于外部函数执行期间,并且之后就会被丢弃。 与存在于 _storage_ 中的值相比,它们用起来更便宜。 + +在这个合约里面,局部变量`myMemstruct`(第19行),以及参数`_arr`(第31行),都是存在于memory里面。函数参数需要有数据存储`memory`或者`calldata`. 函数参数需要有数据存储 _memory_ 或者 _calldata_ 。 + +### Calldata + +Calldata 存放着函数参数. 与 memory 类似, calldata 只能暂时地保存,在外部函数执行期间才有效. 与存储在 memory 中的值不同,存储在 calldata 中的值不能被更改。Calldata 是使用最便宜的数据位置。 Calldata 是使用最便宜的数据位置。 + +在这个合约中,参数`_arr`(第35行)具有 _calldata_ 数据位置。 如果我们想要给数组`_arr`的第一个元素赋新值,则可以在`function g`(第31行)中执行此操作,但无法在`function h`(第35行)中执行此操作。 在这个合约中,参数`_arr`(第35行)具有calldata数据位置。如果我们想要给数组`_arr`的第一个元素赋新值,则可以在函数`g`(第31行)中执行此操作,但无法在函数`h`(第35行)中执行此操作。这是因为函数`g`中的`_arr`具有memory数据位置而函数h具有calldata数据位置。 + +## 赋值 + +### Memory to memory + +从memory到memory 的赋值会创建引用而非副本. 如果你改变了其中一个变量的值, 所有其他引用相同数据的变量也会发生改变. + +如果我们要在f函数内部创建一个新结构体`myMemStruct2`,并将其分配给`myMemStruct` (line 19),则对`myMemStruct2`进行任何更改都会同时更改`myMemStruct` 的值。 + +### Storage to local storage + +从storage到local storage 的赋值也会创建引用而非副本. + +如果我们更改局部变量`myStruct`(line 17)的值,则状态变量`myStructs`(line 10)的值也会随之发生更改。 + +## Storage and memory/calldata + +storage和memory(calldata)之间互相赋值时, 创建独立副本而非引用. + +如果我们要在`f`函数内部创建一个新结构体`myMemstruct3`并将其分配给`myStruct`,则对于`myMemstruct3`进行的更改不会影响存储在映射`myStructs`(line 10) 中的值。 + +正如我们一开始所说,创建合约时必须注意gas成本。因此,我们需要使用需要消耗最少gas的数据位置。 因此,我们需要使用需要消耗最少gas的数据位置。 + +## ⭐️ 作业 + +1. 将函数`f`内`myStruct`成员`foo`的值更改为4。 +2. 在函数`f`中创建一个新结构体`myMemStruct2`,并将其分配给`myMemStruct`。将`myMemStruct2`成员`foo`的值更改为1。 将`myMemStruct2`成员`foo`的值更改为 1。 +3. 在函数`f`中创建一个新结构体`myMemstruct3`,并将其分配给`myStruct`。 将`myMemstruct3`成员`foo`的值更改为3。 将`myMemstruct3`成员`foo`的值更改为3。 +4. 让函数`f`返回`myStruct`、 `myMemStruct2`和`myMemstruct3`。 + +提示:确保为函数`f`创建正确的返回类型。 diff --git a/locales/zh/SolidityBeginnerCourse/data-structures-arrays/arrays.md b/locales/zh/SolidityBeginnerCourse/data-structures-arrays/arrays.md new file mode 100644 index 000000000..56de3187c --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/data-structures-arrays/arrays.md @@ -0,0 +1,44 @@ +在接下来的章节中,我们将探讨在Solidity中可以用于组织和存储数据的数据结构。 + +`Arrays`、`mappings`和`structs`都是引用类型。与值类型(例如_booleans_ 或者 _integers_)不同,引用类型不直接存储其值。相反,它们存储该值被存储的位置。多个引用类型变量可能引用同一位置,并且一个变量的更改会影响其他变量,因此需要小心处理。 与 _值类型_(例如 _booleans_ 或者 _integers_)不同,引用类型不直接存储其值。 相反,它们存储该值被存储的位置。 多个引用类型变量可能引用同一位置,并且一个变量的更改会影响其他变量,因此需要小心处理。 + +在Solidity中,数组是一个列表,存储按数字索引排序的相同类型的值。 + +有两种类型的数组,编译时 _固定大小_ 和 _动态数组_ 。 对于固定大小的数组,我们需要在编译之前声明数组的大小。 动态数组的大小可以在合约编译后更改。 + +### 声明数组 + +通过提供其类型、数组大小(作为方括号内的整数)、可见性和名称(第9行)来声明固定大小数组。 + +有两种类型的数组:编译时固定大小的数组和动态数组。对于固定大小数组,在编译之前需要声明数组大小。动态数组的大小可以在合约编译后更改。 我们以相同方式声明动态数组。但是,我们不提供阵列大小并留空括号(第6行)。 + +### 初始化数组 + +我们可以一次性初始化所有元素(第7行),也可以逐个初始化新元素(arr [0] = 1;)。如果我们声明一个数组,则自动使用默认值0初始化其元素(第9行)。 如果我们声明一个数组,则自动使用默认值0初始化其元素(第9行)。 + +### 访问数组元素 + +通过提供数组名称和方括号中的索引来访问数组内部元素(第12行)。 + +### 添加数组元素 + +使用`push()`成员函数,我们将一个元素添加到动态数组的末尾(第25行)。 + +### 删除数组元素 + +使用`pop()`成员函数,我们删除动态数组的最后一个元素(第31行)。 + +我们可以使用`delete`运算符从数组中删除具有特定索引的元素(第42行)。当我们使用`delete`运算符删除一个元素时,所有其他元素保持不变,这意味着数组的长度将保持不变。这将在我们的数组中产生间隙。如果数组顺序不重要,则可以将该数组的最后一个元素移动到已删除元素所在位置(第46行),或者使用`mapping`。如果需要从数据结构中删除元素,则`mapping`可能是更好的选择。 +当我们使用`delete`运算符删除一个元素时,所有其他元素保持不变,这意味着数组的长度将保持不变。 这将在我们的数组中产生间隙。 +如果数组顺序不重要,则可以将该数组的最后一个元素移动到已删除元素所在位置(第46行),或者使用`mapping`。 如果需要从数据结构中删除元素,则 mapping 可能是更好的选择。 + +### 数组长度 + +使用`length`成员变量,我们可以读取存储在数组中的元素数量(第35行)。 + +观看关于Arrays 的视频教程。 + +## ⭐️ 作业 + +1. 用值0、1、2初始化名为arr3 的公共固定大小数组。使其大小尽可能小。 使其大小尽可能小。 +2. 更改`getArr()`函数以返回`arr3`的值。 diff --git a/locales/zh/SolidityBeginnerCourse/data-structures-enums/enums.md b/locales/zh/SolidityBeginnerCourse/data-structures-enums/enums.md new file mode 100644 index 000000000..6880dab8e --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/data-structures-enums/enums.md @@ -0,0 +1,33 @@ +在 Solidity 中,_枚举_ 是由一组有限的常量值组成的自定义数据类型。 当变量只从一组预定义的值中分配一个值时,那我们就该使用枚举。 + +在这个合约中,状态变量`status`可以从表示转换状态的enum`Status`提供的有限值集合中分配一个值。 + +### 定义枚举 + +我们使用enum关键字来定义一个枚举(第6行),后面跟着我们想要创建的自定义类型名称。在花括号内,我们定义了所有可用于该枚举类型的成员。 在花括号内,我们定义了所有可用于该枚举类型的成员。 + +### 初始化一个枚举变量 + +通过提供enum名称、可见性和变量名称(第16行),我们可以初始化一个新的enum类型变量。在其初始化时,该变量将被赋予该枚举第一个成员Pending(第7行) 的值。 在其初始化时,该变量将被赋予该枚举第一个成员Pending(第7行) 的值。 + +尽管当您定义它们时会为enum成员命名,但它们存储为无符号整数而不是字符串。它们按照它们被定义的顺序编号,并从0开始计数。 在本例中`status`的初始值为0. 它们按照它们被定义的顺序编号,并从0开始计数。 在本例中 status 的初始值为0. + +### 访问 enum 值 + +要访问存储某个 enum 变量所代表之 enum 值, 我们只需要提供存储该值的变量名称即可 (第25行) 。 + +### 更新 enum 值 + +在Solidity中,枚举是由一组有限常量值组成的自定义数据类型。当我们的变量只能从预定义的一组值中分配时,我们使用枚举。 在此示例中,Shipped 为 1。 通过将`uint`分配给表示 enum 成员(例如,在此示例中Shipped 等于1),可以更新变量的 enum 值(第30行)。更新值的另一种方法是使用点运算符,提供枚举名称及其成员 (第35行)。 + +### 删除 enum 值 + +我们可以使用delete操作符来删除变量的enum值,这意味着与数组和映射一样将默认值设置为0。 + +观看有关 Enums 的视频教程。 + +## ⭐️ 作业 + +1. 定义一个名为`Size`的枚举类型,并包含成员`S`, `M`和`L` +2. 初始化枚举类型`Size`的变量`sizes`。 +3. 创建一个getter函数`getSize()`,返回变量`sizes`的值。 diff --git a/locales/zh/SolidityBeginnerCourse/data-structures-mappings/mappings.md b/locales/zh/SolidityBeginnerCourse/data-structures-mappings/mappings.md new file mode 100644 index 000000000..d8ddc4f32 --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/data-structures-mappings/mappings.md @@ -0,0 +1,37 @@ +在Solidity中,mapping是一组键类型和相应值类型对的集合。 + +mapping与数组最大的区别在于映射无法迭代。如果我们不知道一个键,就无法访问其值。如果需要了解所有数据或迭代它们,则应使用数组。 如果我们不知道一个键,就无法访问其值。 如果需要了解所有数据或迭代它们,则应使用数组。 + +如果我们想根据已知的键检索值,我们可以使用映射(例如,地址通常用作键)。 使用映射查找值比迭代数组更容易、更便宜。 如果数组变得太大,迭代它的 Gas 成本可能会变得太高并导致交易失败。 + +我们还可以将映射的键存储在可迭代的数组中。 + +### 创建mappings + +映射是使用语法 `mapping(KeyType => ValueType) VariableName` 声明的。 +声明语法为`mapping(KeyType => ValueType) VariableName`。`KeyType`可以是任何内置值类型或任何合约,但不能是引用类型;`ValueType`可以是任何类型。 值类型可以是任何类型。 + +在此合约中,我们创建公共mapping`myMap`(第6行),将地址(address)作为 key 类型与`uint`作为value类型。 + +### 访问value + +与数组交互时操作 key-value 对象的语法类似于操作数组元素。要查找与特定 key 关联的 value 值,请提供 mapping 的名称和括号内包含该 key (第11行)。 +要查找与特定 key 关联的 value ,请提供 mapping 的名称和括号内的 key (第11行)。 + +如果我们想要根据已知键检索值,可以使用mapping(例如address通常用作键)。使用mapping查找值比遍历数组更容易、更便宜。如果数组变得太大,则遍历它的gas成本可能会变得过高,并导致交易失败。 与数组不同,在试图访问未设置value值的key时不会出现错误。当创建一个新mapping时,每个可能的key都映射到默认值0。 + +### 设置values + +我们可以通过提供 mapping 的名称,并在括号内包含该key,分配一个新value值(第16行)来为key设置新值。 + +### 删除values + +我们可以使用delete运算符来删除与key关联的value值,这将将其设置为默认值0。正如在数组部分中所看到的那样。 正如在数组部分中所看到的那样。 + +观看有关Mapping的视频教程。 + +## ⭐️ 作业 + +1. 创建公共mapping`balances`,将`address`与`uint`作为键类型和值类型。 +2. 更改函数`get`和`remove`以使用mapping`balances`。 +3. 更改函数`set`,创建一个新条目到`balances`映射中,在其中key是参数地址,value是参数地址相关联的余额。 diff --git a/locales/zh/SolidityBeginnerCourse/data-structures-structs/structs.md b/locales/zh/SolidityBeginnerCourse/data-structures-structs/structs.md new file mode 100644 index 000000000..5f59441dd --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/data-structures-structs/structs.md @@ -0,0 +1,29 @@ +在Solidity中,我们可以使用 _结构体_ 来自定义数据类型。 在Solidity中,我们可以使用结构体来自定义数据类型。结构体是由不同数据类型的变量组成的集合。 + +### 定义结构体 + +我们使用`struct`关键字和名称(第5行)来定义一个结构体。在花括号内,我们可以定义结构体的成员,包括变量名和它们的数据类型。 在花括号内,我们可以定义结构体的成员,包括变量名和它们的数据类型。 + +### 初始化结构体 + +有不同的方法来初始化一个结构体。 + +位置参数:我们可以将该结构体的名称和其成员值作为参数提供给圆括号(第16行)。 + +键值映射:我们将该结构体的名称以及键和值作为映射提供给花括号(第19行)。 + +初始化并更新一个结构体:首先我们要初始化一个空白的struct,然后通过赋予新值来更新其成员(第23行)。 + +### 访问结构体 + +要访问struct中某个成员,我们可以使用点运算符(第33行)。 + +### 更新结构体 + +要更新structs' 成员也需要使用点运算符,并分配新值 (39 和 45 行) 。 + +观看有关结构体的视频教程。 + +## ⭐️ 作业 + +创建一个函数`remove`, 接受`uint`型参数,并删除`todos`中具有给定索引(index) 的 struct 成员。 diff --git a/locales/zh/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md b/locales/zh/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md new file mode 100644 index 000000000..dbf17c6ec --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/functions-inputs-and-outputs/inputsAndOutputs.md @@ -0,0 +1,38 @@ +在本节中,我们将学习更多关于函数的输入和输出。 + +### 多个命名输出 + +函数可以返回多个值,并且这些值可以被命名并给这些名称赋值。 + +`returnMany` 函数(第6行)展示了如何返回多个值。你经常会需要返回多个值。例如,可能是一个收集各种函数输出并在单个函数调用中返回它们的函数。 +你经常会需要返回多个值。 例如,可能是一个收集各种函数输出并在单个函数调用中返回它们的函数。 + +`named` 函数(第19行)展示了如何为返回值命名。 +给返回值命名有助于提高合约的可读性。 命名的返回值可以更容易跟踪这些数值及其被返回的顺序。您还可以将数值分配到名称上。 +给返回值命名有助于提高合约的可读性。 命名的返回值可以更容易跟踪这些数值及其被返回的顺序。 您还可以将数值分配到名称上。 + +`assigned` 函数(第33行)展示了如何将数值分配到名称上。当您将数值分配到名称时,您可以省略 `return` 语句并逐一地进行分配。 +当您将值分配给名称时,您可以省略 return 语句并单独返回它们。 + +### 解构赋值 + +您可以使用解构赋值来拆开不同变量中存储的数据。 + +`destructingAssigments` 函数(第49行)将 `returnMany` 函数的结果赋给新定义的局部变量 `i`、`b` 和 `j`(第60行)。 + +### 输入和输出限制 + +对于合约函数的输入和输出参数,有一些限制和最佳实践。 + +[Mappings] 不能用作公开可见的合约函数的传入参数或返回参数。 +来自Solidity 文档. + +数组可以用作参数,如在函数`arrayInput`(第71行)中所示。数组也可以用作返回参数,如在函数`arrayOutput`(第76行)中所示。 数组也可以用作返回参数,如在函数`arrayOutput`(第76行)中所示。 + +由于燃气消耗有限制,您必须谨慎使用任意大小的数组。 由于燃气消耗有限制,您必须谨慎使用任意大小的数组。使用非常大的数组作为输入可能会导致燃气成本过高而失败,但使用较小的数组便能够执行。 + +Watch a video tutorial on Function Outputs. + +## ⭐️ 作业 + +创建一个名为`returnTwo`的新函数,在不使用return语句的情况下返回值`-2`和`true`。 diff --git a/locales/zh/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md b/locales/zh/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md new file mode 100644 index 000000000..249f14172 --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/functions-modifiers-and-constructors/modifiersAndConstructors.md @@ -0,0 +1,39 @@ +在本节中,我们将学习如何修改函数的行为以及如何运行合约初始化代码。 + +### 函数修饰符 + +_函数修饰符_ 用于更改函数的行为。 例如,他们经常在执行限制访问或验证输入的函数之前检查条件。 + +这个合约的第一部分是关于更改合约所有权。该合约中的所有权由类型为`address`(第7行)的状态变量`owner`表示。 `changeOwner`函数(第33行)可以更改此所有权。它接受一个`address`类型的输入参数,并将其值分配给状态变量`owner`。 + +The function `changeOwner` (line 33) can change this ownership. It takes an input parameter of the type `address` and assigns its value to the state variable `owner`. + +However, this function cannot simply be executed under all conditions; it has two modifiers, `onlyOwner` and `validAddress`. + +让我们先来看看`onlyOwner` (第18行)。 +函数修饰符是用`modifier`关键字和唯一的名称定义的;它们也可以有参数。 + +下划线 `_`(第 23 行)在修饰符内部使用,表示将在修改后的函数体内执行的其余代码。 +您放置在修饰符中下划线之前的代码将在被修饰函数主体中的代码之前执行。 下划线后面的代码将在被修饰函数体中的代码之后执行。 + +在这种情况下,`require`函数(第19行)检查正在执行合约的地址是否与存储在变量`owner`中的值相同。如果相同,则会继续执行其余部分,否则会抛出错误。 如果相同,则会继续执行其余部分,否则会抛出错误。 + +您可以通过 Solidity文档了解更多关于`assert`和`require`的信息,它们用于检查条件并在不满足时抛出错误。 + +`validAddress` 修饰符(第28行)具有`address`类型的参数,并检查提供的地址是否有效。如果有效,则继续执行代码。 如果有效,则继续执行代码。 + +### 构造函数 + +函数修饰符用于改变函数的行为。例如,它们经常在执行函数之前检查条件以限制访问或验证输入。 您可以使用它来运行合约初始化代码。 构造函数是在合约创建时执行的。您可以使用它来运行合约初始化代码。构造函数可以有参数,在部署合约之前不知道某些初始化值时特别有用。 + +您可以使用`constructor`关键字声明一个构造函数。 您可以使用`constructor`关键字声明一个构造函数。该合约中的构造函数(第11行)设置了在创建合约时 `owner` 变量的初始值。 + +观看关于函数修饰符的视频教程. + +## ⭐️ 作业 + +1. 在该合约中创建一个名为 `increaseX` 的新函数。 在该合约中创建一个名为 `increaseX` 的新函数。该函数应接受 `uint` 类型的输入参数,并将变量 `x` 的值增加输入参数的值。 +2. 确保只能增加 x 的值。 +3. `increaseX`函数体应为空。 + +提示:使用修饰符。 diff --git a/locales/zh/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md b/locales/zh/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md new file mode 100644 index 000000000..10bfef0d3 --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/functions-reading-and-writing/readAndWrite.md @@ -0,0 +1,23 @@ +本节将简要介绍函数并教您如何使用它们对状态变量进行读写。 + +与其他语言一样,我们在Solidity中使用函数来创建模块化、可重用的代码。但是,Solidity函数有一些特殊之处。 但是,Solidity函数有一些特殊之处。 + +Solidity函数可以分为两种类型: + +1. 修改区块链状态的函数,例如写入状态变量。 修改区块链状态的函数,例如写入状态变量。在此合约中,`set`函数(第9行)更改了状态变量`num`。 +2. 不修改区块链状态的函数。 这些函数标记为`view`或`pure`。 不修改区块链状态的函数。这些函数标记为`view`或`pure`。例如,在此合约中,`get`函数(第14行)标记为仅返回`num`而不更改状态。 + +要定义一个函数,请使用`function`关键字后跟唯一名称。 + +如果一些函数像我们的`set`函数(第9行)那样需要输入,则必须指定参数类型和名称。惯例是使用下划线作为参数名称前缀以将其与状态变量区分开来。 惯例是使用下划线作为参数名称前缀以将其与状态变量区分开来。 + +然后可以设置函数的可见性,并声明它们`view`或`pure`,就像我们对于`get`函数所做的那样,如果它们不修改状态。我们的`get` 函数还返回值,因此我们必须指定返回类型。在这种情况下,由于该函数返回`uint`类型的状态变量`num`,则其返回类型也是`uint`。 我们的`get` 函数还返回值,因此我们必须指定返回类型。 在这种情况下,由于该函数返回`uint`类型的状态变量`num`,则其返回类型也是`uint`。 + +接下来几节将详细探讨Solidity函数的特殊之处。 + +观看有关函数的视频教程. + +## ⭐️ 作业 + +1. 创建一个名为`b`的pubic状态变量,其类型为`bool`,并将其初始化为`true`。 +2. 创建一个名为`get_b`的public函数,该函数返回`b`的值。 diff --git a/locales/zh/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md b/locales/zh/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md new file mode 100644 index 000000000..10e2a0921 --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/functions-view-and-pure/viewAndPure.md @@ -0,0 +1,44 @@ +本节将介绍不修改区块链状态的函数类型:view和pure函数。 + +### View函数 + +view函数不修改状态。 + +以下语句被认为是修改状态: + +1. 写入状态变量。 +2. 发出事件。 +3. 创建其他合约。 +4. 使用 `selfdestruct`。 +5. 通过`call`发送以太币。 +6. 调用未标记为`view`或`pure`的任何函数。 +7. 使用低级别调用。 +8. 使用包含某些操作码的内联汇编。 + +来自 Solidity文档. + +您可以使用关键字`view`声明函数。 您可以使用关键字`view`声明函数。在此合约中,`addToX`(第8行)是一个`view`函数。该功能接受参数`y`并返回参数和状态变量`x`的总和。它读取`x`但不会修改它。 您可以使用关键字`pure`声明pure函数。在此合约中,`add`(第13行)是一个pure函数。该函数接受参数`i`和`j`,并返回它们的总和。它既不读取也不修改状态变量`x`。 它读取`x`但不会修改它。 + +### Pure函数 + +_Pure 函数_ 既不修改也不读取状态。 + +除了上面解释过的一系列改变状态的语句外,还有以下内容被认为是读取状态: + +1. 阅读状态变量。 +2. 访问 `address(this).balance` 或者 `
.balance`。 +3. 访问block、tx、msg 的任何成员(除了`msg.sig`和`msg.data`之外)。 +4. 调用未标记为`pure`的任何功能。 +5. 包含某些操作码的内联汇编。 + +来自 Solidity文档. + +您可以使用关键字`pure`声明纯函数。 在此合约中,`add`(第 13 行)是一个纯函数。 该函数接受参数`i`和`j`,并返回它们的总和。 pure函数承诺既不修改也不读取状态变量。 + +在Solidity开发中,您需要优化代码以节省计算成本(gas成本)。 声明函数 view 和 pure 可以节省 Gas 成本,并使代码更具可读性和更易于维护。 纯函数没有任何副作用,并且如果传递相同的参数,将始终返回相同的结果。 + +观看有关view和pure函数的视频教程 + +## ⭐️ 作业 + +创建一个名为`addToX2`的函数,该函数接受参数`y`并使用参数和状态变量`x`的和更新状态变量`x`。 diff --git a/locales/zh/SolidityBeginnerCourse/introduction/introduction.md b/locales/zh/SolidityBeginnerCourse/introduction/introduction.md new file mode 100644 index 000000000..535a20199 --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/introduction/introduction.md @@ -0,0 +1,32 @@ +欢迎来到这个面向初学者的交互式 Solidity 课程。 + +在第一节中,我们将简要介绍本课程将涉及的概念,查看一个智能合约示例,并向您展示如何在 Remix IDE 中与该合约进行交互。 + +该合约是一个计数器合约,具有增加、减少和返回计数器变量状态的功能。 + +如果我们查看合约的顶部,我们可以看到有关合约的一些信息,如许可证(第 1 行)、Solidity 版本(第 2 行),以及关键字`contract`及其名称`Counter`(第 4 行)。 我们将在下一节有关**基本语法**的内容中介绍这些概念。 + +通过`uint public count`(第 5 行),我们声明了一个`uint`类型的状态变量,其可见性为`public`。 我们将在有关 **变量**、**原始数据类型** 和 **可见性** 的部分中介绍这些概念。 + +然后,我们创建一个使用`view`关键字定义的`get`函数(第 8 行)并返回`uint`类型。 具体来说,它返回 `count` 变量。 该合约还有两个函数,`inc`(第 13 行)和`dec`(第 18 行)函数,用于增加或减少计数变量。 +我们将在有关 **函数 - 读取和写入状态变量** 和 **函数 - 查看和纯粹** 的部分中讨论这些概念。 + +## 通过Remix编译和部署 + +**GIF** 与合约交互: Compile and deploy contract + +1. 我们可以在 Remix IDE 的`Solidity 编译器`模块中编译您的`Counter`合约。 + +2. 在“部署和运行交易” 模块中,我们在合约输入字段中选择合约 “Counter”,然后单击 “部署” 按钮。 + +3. 我们在IDE中扩展了代币合约函数,并测试了其`get`、`inc`和`dec`函数。 + +## ⭐️ 作业 + +在整个课程中,我们将为您布置作业来测试和巩固您新获得的知识。 + +您的第一次作业是: + +1. 编译这个合约。 +2. 将其部署到 Remix VM +3. 与您的合约交互。 diff --git a/locales/zh/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md b/locales/zh/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md new file mode 100644 index 000000000..adac40e7b --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/primitive-data-types/primitiveDataTypes.md @@ -0,0 +1,33 @@ +在本节中,我们将展示Solidity的原始数据类型、如何声明它们以及它们的特性。 + +### bool + +您可以使用关键字‘bool’声明布尔类型的数据。布尔值只能为`true`或`false`。 布尔值只能为`true`或`false`。 + +### uint + +我们使用关键字`uint`和`uint8`到`uint256`来声明无符号整数类型(与-12不同,它们没有符号)。Uints是正整数或零,并且范围从8 bits到256 bits。 `uint`类型与`uint256`相同。 Uints是正整数或零,并且范围从8 bits到256 bits。 `uint`类型与`uint256`相同。 + +### int + +我们使用关键字`int`和`int8`到`int256`来声明整数类型。整数可以是正、负或零,并且范围从8 bits到256 bits。 `int`类型与`int256`相同。 整数可以是正、负或零,并且范围从8 bits到256 bits。 `int`类型与`int256`相同。 + +### address + +`address`类型变量保存20个字节的值,这是以太坊地址的大小。还有一种特殊的以太坊地址——可支付地址(address payable),可以从合约接收ether。 还有一种特殊的以太坊地址——可支付地址(address payable),可以从合约接收ether。 + +所有这些数据类型都有默认值,在合约中显示(第29行)。 + +您可以在Solidity文档中了解更多关于这些数据类型以及定点数字、字节数组、字符串等内容。 + +在课程后期,我们将研究像**Mappings**、**Arrays**、**Enums**和**Structs**之类的数据结构。 + +观看原始数据类型视频教程。. + +## ⭐️ 作业 + +1. 创建一个名为`newAddr`的`public` `address` 变量,并给其赋一个不同于现有变量 `addr` 的值。 +2. 创建一个名为`neg`的`public`负数变量,并确定其类型。 +3. Create a new variable, `newU` that has the smallest `uint` size type and the smallest `uint` value and is `public`.创建一个新变量`newU`,它具有最小的`uint`大小类型和最小的`uint`值,并且是`public`的。 + +提示:查看合约中的其他地址或在互联网上搜索以太坊地址。 diff --git a/locales/zh/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md b/locales/zh/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md new file mode 100644 index 000000000..1e9b0ccd0 --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/transactions-ether-and-wei/etherAndWei.md @@ -0,0 +1,26 @@ +_Ether_ (ETH) is a cryptocurrency. _Ether_ is also used to pay fees for using the Ethereum network, like making transactions in the form of sending _Ether_ to an address or interacting with an Ethereum application. + +### 以太币单位 + +To specify a unit of _Ether_, we can add the suffixes `wei`, `gwei`, or `ether` to a literal number. + +#### `wei` + +_Wei_ is the smallest subunit of _Ether_, named after the cryptographer [Wei Dai](https://en.wikipedia.org/wiki/Wei_Dai). _Ether_ numbers without a suffix are treated as `wei` (line 7). + +#### `gwei` + +1个GWei(千兆Wei)等于10^9 Wei。 + +#### `ether` + +One `ether` is equal to 1,000,000,000,000,000,000 (10^18) `wei` (line 11). + +观看有关Ether和Wei的视频教程。. + +## ⭐️ 作业 + +1. 创建一个名为`oneGWei`的`public uint`,并将其设置为1 `gWei`。 +2. 创建一个名为`isOneGWei`的`public bool`,并将其设置为比较操作 1 GWei 和 10 ^ 9 的结果。 + +提示:查看合约中如何编写gwei和ether。 diff --git a/locales/zh/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md b/locales/zh/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md new file mode 100644 index 000000000..fc39e2466 --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/transactions-gas-and-gas-price/gasAndGasPrice.md @@ -0,0 +1,29 @@ +正如我们在上一节中看到的,通过以太坊网络上的交易执行代码需要支付以太币形式的交易费。 执行交易所需支付的费用金额取决于执行交易所花费的_gas_数量。 + +### Gas + +Gas是衡量在以太坊网络上执行特定操作所需计算工作量的单位。 + +### Gas price + +Gas相对于Ethereum有时被比作给汽车提供燃料。你的汽车消耗燃料的数量大多时候是相同的,但你为燃料支付的价格取决于市场。 类似地,一个交易需要消耗固定数量gas来完成与之相关联的计算工作。然而,发送方愿意为gas支付多少钱则由他们自己决定。具有更高gas价格的交易将更快地进行;具有非常低gas价格可能根本无法进行。 + +类似地,一个交易需要消耗固定数量 _gas_ 来完成与之相关联的计算工作。 然而,发送方愿意为 _gas_ 支付多少钱则由他们自己决定。 _gas价格_ 更高的交易将更快地进行;_gas价格_ 很低的交易可能根本无法进行。 + +正如我们在前一节中所看到的,通过以太坊网络上的交易执行代码需要以Ether形式支付交易费用。要执行一个交易所需支付的费用取决于该交易执行所需的gas数量。 当发送一个交易时,发送方必须在执行该交易时支付gas费( gas_price \* gas )。如果在完成执行后还剩下了一些gas,则会退还给发送方。 + +Gas价格用gwei表示。 + +### Gas limit + +当发送一个交易时,发送方指定他们愿意为其支付最大数量的 gas。 当发送一个交易时,发送方指定他们愿意为其支付最大数量的gas。如果他们设置得过低,则其交易可能会因未能完成而耗尽所有可用gas,并导致任何已做出修改都被撤销且不可退款。 在这种情况下,_gas_ 已被消耗且无法退还。 + +了解更多关于gas的信息:ethereum.org. + +观看有关Gas和Gas价格的视频教程。 + +## ⭐️ 作业 + +在`Gas`合约中创建一个名为`cost`、类型为`uint`的新`public`状态变量。将部署合约所需的gas成本存储到这个新变量中,包括你正在存储值所需支付的费用。 将部署合约所需的gas成本存储到这个新变量中,包括你正在存储值所需支付的费用。 + +提示:您可以在Remix终端中检查交易详细信息,包括gas成本。您还可以使用Remix插件Gas Profiler来检查交易的gas成本。 您还可以使用Remix插件 _Gas Profiler_ 来检查交易的gas成本。 diff --git a/locales/zh/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md b/locales/zh/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md new file mode 100644 index 000000000..3dcf360c7 --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/transactions-sending-ether/sendingEther.md @@ -0,0 +1,87 @@ +在本节中,我们将学习如何使用合约发送和接收以太币。 + +### 发送以太币 + +我们有三种不同的选项来转移以太币:`transfer()`、`send()` 和 `call()`。 + +#### **transfer** + +`
.transfer(uint256 amount)` + +- `transfer()`失败时会抛出异常 +- gas限制是2300 + +可以在`SendEther`合约(第35行)中看到`transfer()`的示例。**现已不建议再使用`Transfer()`。** +**现已不建议再使用`Transfer()`。** + +#### **send** + +`
.send(uint256 amount) returns (bool)` + +- `send()`失败时返回false +- gas限制是2300 + +可以在`SendEther`合约(第41行)中看到`send()`的示例。**现已不建议再使用`Send()`。** +**现已不建议再使用`Send()`。** + +#### **call** + +`
.call(bytes memory) returns (bool, bytes memory)` + +- `call()`失败时返回false +- 转发的最大gas量,但是这是调整的 + +可以在`SendEther`合约(第48行)中看到`call()`的示例。如果您要转移以太币,则目前推荐使用`Call()`。 +如果您要转移以太币,则目前推荐使用`Call()`。 + +引入`transfer()`和`send()`的原因是通过将转发 gas 限制为 2300 来防范重入攻击,这对于修改storage变量而言是不够的。 + +正如我们在上一节讨论过的那样,Ethereum 上每个操作都与特定成本相关联。 随着时间推移,某些操作变得更加费用密集,因此与它们相关的 gas 成本也会提高。 正如我们在上一节讨论过的那样,Ethereum 上每个操作都与特定成本相关联。随着时间推移,某些操作变得更加费用密集,因此与它们相关的 gas 成本也会提高。当操作的 gas 成本可能发生变化时,使用像 `transfer()` 和 `send()` 这样的硬编码 gas 量是不好的。 + +这就是为什么现在推荐使用`call()`而不是`transfer()`来发送以太币。 + +在 Consensys博客中了解更多关于该主题的信息。 + +### 重入攻击 + +重入攻击发生在一个函数对不受信任的合约进行外部调用时,攻击者利用该合约在原函数执行完成之前进行递归调用。通过这种方法,攻击者可以耗尽资金并以意想不到的方式操纵数据。 通过这种方法,攻击者可以耗尽资金并以意想不到的方式操纵数据。 + +为了防止 _重入攻击_,所有状态更改都应在调用外部合约之前进行。 为了防范重入攻击,在调用外部合约之前应先进行所有状态更改。这也被称为检查-效果-交互模式。 + +另一种预防重入的方法是使用 _重入保护器_ 来检查此类调用并拒绝它们。 另一种预防重入的方法是使用重入保护器来检查此类调用并拒绝它们。您可以在我们modifier部分中看到该合约的示例,或在Open Zepplin上找到更节省gas费版本。 + +### 接收以太币 + +如果我们想让一个合约在没有调用函数的情况下接收以太币,我们需要创建一个`receive`函数(第22行)或者`fallback`函数(第25行);否则,这些以太币将被拒绝,并且合约会抛出异常。 + +`receive`函数(第22行)需要是`payable`的。如果你删除了`payable`修饰符,编译器会报错。如果你在`fallback`函数(第25行)中删除了`payable`修饰符,它将能够编译,但无法接收以太币。`sendViaTransfer`、`sendViaSend`和`sendViaCall`函数(第33、38和45行)也需要是`payable`才能接收以太币。 当使用空`calldata`进行调用时(例如通过`send()`或`transfer()`进行的纯粹的Ether转账),`receive`函数将被执行,而`fallback`函数将在有 calldata 的调用中执行。如果不存在`receive`函数但存在`fallback`函数,则使用空 calldata 进行的调用也将使用`fallback`函数。 + +### payable函数修饰符 + +`payable`函数修饰符允许一个函数接收以太币。 + +`receive`函数(第22行) 需要是`payable`。 如果删除`payable`修饰符,编译器将会出现错误。 如果您从`fallback`函数(第25行)中删除`payable`修饰符,它将编译,但无法接收以太币。 +函数 `sendViaTransfer`、`sendViaSend`和 `sendViaCall`(第 33、38 和 45 行)也需要 `payable` 才能接收以太币。 + +### Payable地址 + +Solidity 对地址数据类型进行了两种不同的区分:address 和 address payable。 + +`address`: 保存20字节值。 +`address`: 保存20字节值。 +`address payable`: 保存20字节值,并可以通过其成员`transfer`和`send`接收以太币。 + +如果你将`sendViaTransfer`和`sendViaSend`函数的参数类型(第33和38行)从`address payable`更改为`address`,则无法使用`transfer()`(第35行或`send()`(第41行)。 + +观看有关发送 Ether 的视频教程。 + +## ⭐️ 作业 + +创建一个慈善合约,可以接收以太币,并且可以被受益人提取。 + +1. 创建一个名为`Charity`的合约。 +2. 添加一个公共状态变量`owner`,类型为address。 +3. 创建一个名为`donate`的函数,该函数是public和payable,没有任何参数或函数代码。 +4. 创建一个名为`withdraw`的函数,该函数是public的,并将合同总余额发送到所有者地址。 + +提示:通过从一个账户部署它并从另一个账户向其发送Ether来测试您的合约。然后执行`withdraw`功能。 然后执行 withdraw 函数。 diff --git a/locales/zh/SolidityBeginnerCourse/variables/variables.md b/locales/zh/SolidityBeginnerCourse/variables/variables.md new file mode 100644 index 000000000..00970598e --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/variables/variables.md @@ -0,0 +1,29 @@ +在Solidity中有三种不同类型的变量:_状态变量_、_局部变量_和_全局变量_。 + +## 1. 状态变量 + +全局变量,也称为特殊变量,在全局命名空间中存在。它们不需要声明但可以从您的合约内访问。全局变量用于检索区块链、特定地址、合约和交易的信息。 它们声明在合约内、函数外。 +状态变量存储在合约存储器中,因此也存在于区块链上。它们声明在合约内、函数外。这个合约有两个状态变量,即字符串`text`(第6行)和无符号整数`num`(第7行)。 + +## 2. 局部变量 + +局部变量存储在内存中,其值仅可在定义它们的函数内访问。局部变量不会被存储到区块链上。在这个合约中,无符号整数`i`(第11行)是一个局部变量。 局部变量不会被存储到区块链上。 +在这个合约中,无符号整数`i`(第11行)是一个局部变量。 + +## 3. 全局变量 + +_全局变量_,也称为_特殊变量_,在全局命名空间中存在。 它们不需要声明但可以从您的合约内访问。 +全局变量用于检索区块链、特定地址、合约和交易的信息。 + +在本例中我们使用`block.timestamp`(第14行)来获取当前块生成时的Unix时间戳,并使用`msg.sender`(第15行)来获取调用者的地址。 + +所有全局变量列表都可以在Solidity文档中找到。 + +Watch video tutorials on State Variables, Local Variables, and Global Variables. + +## ⭐️ Assignment + +1. 创建一个public类型的`状态变量`,命名为`blockNumber`。 +2. 在函数`doSomething()`内,将当前区块号的值赋给状态变量`blockNumber`。 + +提示:查看Solidity文档中的全局变量部分以了解如何读取当前区块号。 diff --git a/locales/zh/SolidityBeginnerCourse/visibility/visibility.md b/locales/zh/SolidityBeginnerCourse/visibility/visibility.md new file mode 100644 index 000000000..47fbc5497 --- /dev/null +++ b/locales/zh/SolidityBeginnerCourse/visibility/visibility.md @@ -0,0 +1,37 @@ +可见性修饰符用于控制谁可以访问函数和状态变量。 + +有四种类型的可见性:`external`、`public`、`internal`和`private`。 + +它们规定了函数和状态变量是否可以在合约内部调用,从继承自该合约的合约(子合约)中调用,或者从其他合约和交易中调用。 + +### private + +- 可以在当前合约内部被调用 + +### internal + +- 可以在当前合约内部被调用 +- 可以从子合约调用 + +### public + +- 只能在当前合约内部被调用 +- 可以在子合约中被调用 +- 可以从其他合约或交易中调用 + +### external + +- 可以从其他合约或交易中调用 +- 状态变量不能是`external` + +在这个例子中,我们有两个合约,`Base`合约(第4行)和继承了`Base`合约函数和状态变量的`Child`合约(第55行)。 + +当你取消注释`testPrivateFunc`(第58-60行),你会得到一个错误,因为子合约没有访问来自`Base`合约的`privateFunc` private 函数。 + +如果您编译并部署这两个合约,则无法直接调用函数`privateFunc`和`internalFunc`。 如果您编译并部署这两个合约,则无法直接调用函数`privateFunc`和`internalFunc`。您只能通过`testPrivateFunc`和`testInternalFunc`来调用它们。 + +观看关于可见性的视频教程。 + +## ⭐️ 作业 + +在`Child`合约中创建一个名为`testInternalVar`的新函数,该函数返回可能返回`Base`合约所有状态变量值。 diff --git a/locales/zh/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md b/locales/zh/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md new file mode 100644 index 000000000..30c5d1b5f --- /dev/null +++ b/locales/zh/Uniswap-Tutorial/1-introduction-to-uniswap/introduction.md @@ -0,0 +1,47 @@ +在本教程中,我们将探索 Uniswap V3 交换合约,以了解单跳和多跳交换的工作原理。 + +但首先,我们需要了解一些 Uniswap 基础知识。 + +## 什么是 Uniswap? + +Uniswap 是一个去中心化的加密货币交易所。 它允许用户无需中心化中介即可交换代币。 Uniswap 是去中心化金融 (DeFi) 领域的关键参与者。 + +## Uniswap 是怎么运作的? + +Uniswap 没有像传统中心化交易所那样使用订单簿,而是使用自动做市商(AMM)模型。 在 Uniswap 中,AMM 是一个持有代币储备(流动性池)的智能合约。 用户可以在流动性池中的代币之间进行交易。 每个代币的价格由储备金比例决定。 + +### Uniswap 交易的分步示例 + +1. Alice 想要用 1 ETH 换取 DAI。 +2. Alice 向 Uniswap 智能合约发送 1 ETH。 +3. Uniswap 智能合约根据当前汇率计算 Alice 应收到的 DAI 数量。 +4. Uniswap 智能合约将 DAI 发送给 Alice。 +5. Uniswap 智能合约将 1 ETH 添加到其储备中。 +6. Uniswap 智能合约根据新的储备重新计算汇率。 + +流动性池中的代币由流动性提供者提供。 当流动性提供者将代币存入流动性池时,他们会收到流动性提供者代币作为回报。 流动性提供者代币代表用户在流动性池中的份额。 + +Uniswap 用户为每笔交易支付费用。 该费用以额外流动性提供者代币的形式支付给流动性提供者。 + +## Uniswap 交换合约 + +Uniswap Swap 合约允许用户使用 Uniswap V3 交换代币。 它可以进行单跳交换,允许用户直接将一种代币交换为另一种代币。 它还可以进行多跳交换,这意味着用户可以通过多个代币的路由来将一种代币交换为另一种代币。 在这种情况下,路由意味着交换合约会将代币交换为另一个代币,然后将该代币交换为另一个代币,依此类推,直到达到所需的代币。 + +## 结论 + +在本节中,我们了解了 Uniswap、它的工作原理以及我们将如何使用它来交换代币。 + +## ⭐ 作业: 多选测试 + +### 1. 什么是 Uniswap? + +1. 一个中心化的交易协议。 +2. 使用订单簿的去中心化交易协议。 +3. 一种使用自动做市商(AMM)模型的去中心化交易协议。 +4. 一种使用订单簿和自动做市商(AMM)模型的去中心化交易协议。 + +### 2) Uniswap 如何确定代币的价格? + +1. 代币的价格由储备金比例决定。 +2. 代币的价格由储备金和交易数量的比率决定。 +3. 代币的价格由储备金和流动性提供者数量的比例决定。 diff --git a/locales/zh/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md b/locales/zh/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md new file mode 100644 index 000000000..e1e8a6140 --- /dev/null +++ b/locales/zh/Uniswap-Tutorial/2-router-interfaces-and-structs/router-interfaces-and-structs.md @@ -0,0 +1,41 @@ +整个 UniswapSwapExamples 合约将仅在本教程的第 5 节中介绍。 在此之前,我们将构建代码块。 + +本节探讨`ISwapRouter`接口,该接口定义了可以在 Uniswap 交换合约上调用的函数。 + +单跳交换允许用户直接在流动性池内将一种代币交换为另一种代币。 +多跳交换允许用户通过路由多个代币来将一种代币交换为另一种代币。 + +Solidity 中的接口指定了必须包含在继承它们的合约中的函数。 它们对于声明支持哪些函数非常有用,并允许不同合约之间更轻松地集成和交互。 + +结构体用于定义自定义数据类型。 + +## ISwapRouter 接口 + +ISwapRouter 接口定义了可以在 Uniswap 交换合约上调用的函数。 我们需要使用此接口与 Uniswap 交换合约进行交互并执行交换。 + +在第 5 行,我们定义了一个名为`router`的常量,其类型为`ISwapRouter`。 我们将此变量的值设置为部署在地址`0xE592427A0AEce92De3Edee1F18E0157C05861564`的智能合约的接口实例。 这是以太坊主网上 Uniswap V3 Swap 合约的地址。 + +在第 9 行,我们定义了一个名为`ISwapRouter`的接口。 此接口定义了两个函数: `exactInputSingle` 和 `exactInput` 。 + +## exactInputSingle + +在第25行,我们定义了一个叫做`ExactInputSingleParams`的结构体。 该结构体定义了第 21 行的 exactInputSingle 函数所需的参数,该函数将执行单跳交换。 该结构体具有以下参数: + +- **`address tokenIn`**:发送代币的地址。 +- **`address tokenOut`**: 接收代币的地址 +- **`uint24 fee`**: 交换费用 +- **`address recipient`**: 将接收输出代币的地址。 +- **`uint deadline`**: 必须处理交易的时间戳,以限制交换的时间。 +- **`uint amountIn`**: 发送的输入代币的数量。 +- **`uint amountOutMinimum`**: 发送者愿意接受的最小输出代币数量,以防止不利的价格变动。 +- **`uint160 sqrtPriceLimitX96`**: 以特定格式表示的价格限制,以防止互换在不利价格下发生。 + +## exactInput + +在第25行,我们定义了一个叫做`ExactInputParams `的结构体。 这个结构体定义了我们在第 33 行上的 `extractInput` 函数所需的参数。 该函数将执行多跳交换。 该结构体具有以下参数: + +- **`bytes path`**: 有关交换路径的编码信息(即通过哪些代币进行交换)。 +- **`address recipient`**: 接收输出代币的地址。 +- **`uint deadline`**: 与上面类似,处理交易必须遵循的时间戳。 +- **`uint amountIn`**: 输入代币的数量。 +- **`uint amountOutMinimum`**: 发送者期望接收的输出代币的最小数量。 diff --git a/locales/zh/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md b/locales/zh/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md new file mode 100644 index 000000000..db59be514 --- /dev/null +++ b/locales/zh/Uniswap-Tutorial/3-single-hop-swaps/single-hop-swaps.md @@ -0,0 +1,36 @@ +单跳交换允许用户直接在流动性池内将一种代币交换为另一种代币。 在本节中,我们将学习如何使用 Uniswap V3 交换合约执行单跳交换。 + +## 函数参数 + +在第8行,我们定义了一个叫做`swapExactInputSingleHop `的函数。 该函数执行单跳交换。 它需要以下参数: + +- **`address tokenIn`**: 正在发送的代币的地址。 +- **`address tokenOut`**: 接收到的代币的地址。 +- **`uint24 poolFee`**: 交换费用 +- **`uint amountIn`**: 发送的输入代币的数量。 + +它返回一个叫做`amountOut`的`uint`, 即收到的输出代币的数量。 + +## 函数体 + +在函数体中,我们首先将输入代币从发送者传输到我们的合约,第 14 行。 +然后,我们批准 Uniswap 交换合约代表我们花费输入代币,第 15 行。 + +在第17行上,我们创建了一个 `ExactInputSingleParams` 结构体实例。 该结构体包含第 45 行的 `exactInputSingle`函数所需的参数,该函数将执行单跳交换。 我们在该行上重复`ISwapRouter.ExactInputSingleParams`两次,因为我们正在创建在接口中定义的结构体实例。 + +## ExactInputSingleParams 结构体参数 + +我们设置结构体的参数如下: + +- **`tokenIn`**:我们将其设置为函数的`tokenIn`参数。 +- **`tokenOut`**:我们将其设置为函数的`tokenOut`参数。 +- **`fee`**:我们将其设置为函数的`poolFee `参数。 +- **\`recipient**:我们将其设置为交易发送人。 +- **\`deadline**:我们将其设置为当前的时间戳。 我们这样做是因为我们希望尽快处理交易。 +- **`amountIn `**:我们将其设置为函数的`amountIn `参数。 +- **`amountOutMinimum`**: 我们将其设置为 0,因为我们不想指定我们愿意接受的输出代币的最小数量。 +- **`sqrtPriceLimitX96`**: 我们将其设置为 0,因为我们不想指定价格限制。 + +## 执行单跳交换 + +在第29行中,我们将`extractInputSingle`函数的输出分配给`amountOut`变量。 该函数执行单跳交换并返回收到的输出代币的数量。 diff --git a/locales/zh/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md b/locales/zh/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md new file mode 100644 index 000000000..859f50237 --- /dev/null +++ b/locales/zh/Uniswap-Tutorial/4-multi-hop-swaps/multi-hop-swaps.md @@ -0,0 +1,30 @@ +在本节中,我们将深入研究 `UniswapV3SwapExamples` 合约中的 `swapExactInputMultiHop` 函数。 此函数允许用户通过多个流动资金池指定一个自定义路径,从而执行更复杂的代币互换。 + +例如,如果用户想要将代币A交换为代币D,但A和D没有直接的流动性池,则用户可以指定通过多个代币的路径。 例如,用户可以将 A 交换为 B,然后将 B 交换为 C,最后将 C 交换为 D。这当然是由 Uniswap V3 交换合约自动完成的。 + +### 参数和返回值 + +在第32行,我们定义了一个叫做`swapExactInputMultiHop `的函数。 该函数执行多跳交换。 它需要以下参数: + +- **`bytes calldata path`**: 有关交换路径的编码信息(即通过哪些代币进行交换)。 +- **`address tokenIn`**: 正在发送的代币的地址。 +- **`uint amountIn`**: 发送的输入代币的数量。 + +它返回一个叫做`amountOut`的`uint`, 即收到的输出代币的数量。 + +### 函数体 + +在函数体中,我们首先将输入代币从发送者传输到我们的合约,第 38 行。 +然后,我们批准 Uniswap 交换路由器代表我们使用输入的代币,第 41 行。 + +在第 43 行,我们创建了第 73 行的`ExactInputParams`结构体实例 该结构体包含第 81 行的 `exactInput `函数所需的参数,该函数将执行多跳交换。 + +我们设置结构体的参数如下: + +- **`path `**:我们将其设置为函数的`path `参数。 +- **\`recipient**:我们将其设置为交易发送人。 +- **\`deadline**:我们将其设置为当前的时间戳。 我们这样做是因为我们希望尽快处理交易。 +- **`amountIn `**:我们将其设置为函数的`amountIn `参数。 +- **`amountOutMinimum`**: 我们将其设置为 0,因为我们不想指定我们愿意接受的输出代币的最小数量。 + +在第 53 行,我们通过调用`exactInput`函数执行多跳交换。 此函数返回收到的输出代币的数量。 diff --git a/locales/zh/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md b/locales/zh/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md new file mode 100644 index 000000000..b8dd7f293 --- /dev/null +++ b/locales/zh/Uniswap-Tutorial/5-erc20-weth-interfaces/erc20-weth-interfaces.md @@ -0,0 +1,52 @@ +在本节中,我们将探讨`IERC20`接口(用于与 ERC-20 代币交互的标准接口)和`IWETH`接口(用于与包装以太币`WETH`交互的标准接口)。 了解这些接口至关重要,因为它在 Uniswap V3 交换合约中用于处理代币传输和批准。 + +您可以在 LearnEth 中找到针对初学者的“Solidity ERC20 代币课程”,以更详细地了解 ERC20 代币标准。 + +## IERC20 接口 + +在第 80行上,我们定义了 `IERC20` 接口。 该接口定义了 ERC-20 代币必须实现的一组标准功能。 让我们查看一下该接口中的关键函数: + +### 1. totalSupply + +在第81行上,我们定义了 `totalSupply` 函数。 此函数返回代币的总供应量。 + +### 2. balanceOf + +在第83行上,我们定义了 `balanceOf ` 函数。 此函数返回指定地址的余额。 + +### 3. transfer + +在第85行上,我们定义了 `transfer ` 函数。 该函数将代币从发送者转移到指定的接收者。 + +### 4. allowance + +在第87行上,我们定义了 `allowance ` 函数。 此函数返回允许花费者代表所有者花费的代币数量。 + +### 5. approve + +在第89行上,我们定义了 `approve ` 函数。 调用时,此函数会批准花费者代表发送者花费指定数量的代币。 + +### 6. transferFrom + +在第91行上,我们定义了 `transferFrom ` 函数。 此函数将代币从指定的发送者传输到接收者。 仅当允许花费者代表发送者花费指定数量的代币时,该函数才能由花费者调用。 + +### 7. Events + +在第102-103行中,我们定义了`Transfer`和`Approval`事件。 这些事件分别在调用 `transfer` 和 `approve` 函数时发生。 + +## IWETH 接口 + +在第 106行上,我们定义了 `IWETH ` 接口。 这个接口扩展了 `IERC20` 接口,并定义了两个额外的函数: + +### 1. deposit + +在第107行上,我们定义了 `deposit ` 函数。 该函数将 ETH 存入合约并返回等值的 WETH。 该函数用于将ETH包装成WETH。 +我们需要将 ETH 包装成 WETH,因为 Uniswap V3 交换合约仅支持 ERC-20 代币。 + +### 2. withdraw + +在第109行上,我们定义了 `withdraw ` 函数。 该函数从合约中提取指定数量的WETH并返回等值数量的ETH。 该函数用于将 WETH 解包为 ETH。 + +## 结论 + +在本教程中,我们探索了 Uniswap V3 交换合约。 要全面了解 Uniswap 的工作原理,请尝试在 Uniswap DApp 上进行一些交换,并访问Uniswap 文档。 diff --git a/locales/zh/Uniswap-Tutorial/README.md b/locales/zh/Uniswap-Tutorial/README.md new file mode 100644 index 000000000..3250d867b --- /dev/null +++ b/locales/zh/Uniswap-Tutorial/README.md @@ -0,0 +1,5 @@ +# Uniswap 交换课程 + +查看用于执行代币交换的 Uniswap V3 交换合约的代码。 + +由p2p学习平台 https://dacade.org 开发。 diff --git a/locales/zh/Uniswap-Tutorial/config.yml b/locales/zh/Uniswap-Tutorial/config.yml new file mode 100644 index 000000000..f49f02abc --- /dev/null +++ b/locales/zh/Uniswap-Tutorial/config.yml @@ -0,0 +1,25 @@ +--- +id: uniswapSwapCourse +name: Uniswap Swap Course +summary: Go through the Solidity code of the Uniswap V3 Swap contract. Developed by the p2p learning platform https://dacade.org. +level: 2 +tags: + - Solidity + - Tokens + - Uniswap +steps: + - + name: 1. Introduction + path: 1-introduction-to-uniswap + - + name: 2. Routers, Interfaces, and Structs + path: 2-router-interfaces-and-structs + - + name: 3. Single Hop Swaps + path: 3-single-hop-swaps + - + name: 4. Multi-Hop Swaps + path: 4-multi-hop-swaps + - + name: 5. Erc20 and Weth Interfaces + path: 5-erc20-weth-interfaces diff --git a/locales/zh/Web3Client/1_Using_Web3/Running_a_script.md b/locales/zh/Web3Client/1_Using_Web3/Running_a_script.md new file mode 100644 index 000000000..57b448109 --- /dev/null +++ b/locales/zh/Web3Client/1_Using_Web3/Running_a_script.md @@ -0,0 +1,23 @@ +## 查询区块链 + +在本教程中,我们将运行一个使用JavaScript库的脚本查询区块链。 + +这表示我们不会使用Remix GUI或类似Etherscan的区块浏览器,而是使用编辑器中的脚本,并从终端运行它。 + +与区块链交互最多使用的JS库是web3.js和ethers.js。 + +让我们从一个简单的web3.js示例queryBlockNum.js开始。 + +该脚本对web3.js进行了调用,这个调用放到了try/catch代码块中进行异步执行。 + +我们将通过`let blockNumber = await web3.eth.getBlockNumber()`来查询当前区块号码 + +请注意,对象`web3`由Remix注入。 请注意,对象`web3`由Remix注入。有关更多关于web3.js信息,请查看其文档https://web3js.readthedocs.io。 + +要使用web3.js或ethers.js,请在**Deploy&Run**模块中选择**Injected Web3**或**Web3 Provider**环境。目前无法在JSVM上工作。**如果您尝试,则会收到错误消息**。 脚本目前无法在JSVM上工作。 **如果您尝试,则会收到错误消息**。 + +因此,在此示例中,请选择Deploy&Run模块中的**Injected Web3**并安装Metamask。 + +从终端执行 `remix.execute()`。 从终端执行`remix.execute()`。此命令将执行带有`let blockNumber = await web3.eth.getBlockNumber()`代码的JavaScript文件。 + +在控制台中,您应该可以看到Metamask连接到链条上当前区块的编号。 diff --git a/locales/zh/Web3Client/2_Querying_a_Contract/queryContract.md b/locales/zh/Web3Client/2_Querying_a_Contract/queryContract.md new file mode 100644 index 000000000..e7e50225f --- /dev/null +++ b/locales/zh/Web3Client/2_Querying_a_Contract/queryContract.md @@ -0,0 +1,23 @@ +现在我们知道如何查询简单数据,让我们尝试更复杂的查询。 + +这是一个部署到主网上的合约 - 地址:https://etherscan.io/address/0xdac17f958d2ee523a2206206994597c13d831ec7#code + +我们将访问该合约以查找其代币名称。 + +**name**变量是合约的状态变量。 + +要访问此主网合约,我们需要进行一些设置。 + +1. 切换到metamask中的主网。 +2. 您可能需要刷新Remix。 +3. 由于刷新,您可能还需要重新加载本教程。 +4. 转到Deploy&Run并切换到**Injected Web3**。 + +**使用Web3** +在脚本`queryContract.js`中,我们需要实例化web3.eth.Contract对象。为此,我们需要获取合约的ABI和地址。源代码和ABI可在etherscan中找到,因为合约开发人员有意发布了它们。 为此,我们需要获取合约的ABI和地址。 源代码和ABI可在etherscan中找到,因为合约开发人员有意发布了它们。 + +在 etherscan 中,可以看到它的名称为 **TetherToken**。 在etherscan中,可以看到它的名称为**TetherToken**。向下滚动至etherscan源代码部分中的TetherToken合约,则可以查看该合约的状态变量 - 其中第一个命名为**name**。 + +有一些语法技巧可用于返回状态变量值。 + +- 要调用公共状态变量自动生成器函数,请同时将变量视为函数(通过添加括号)并附加call()。 diff --git a/locales/zh/Web3Client/README.md b/locales/zh/Web3Client/README.md new file mode 100644 index 000000000..317aed025 --- /dev/null +++ b/locales/zh/Web3Client/README.md @@ -0,0 +1 @@ +本次研讨会的主题是使用 web3.js 与合约交互,更广泛地说是与区块链交互。 diff --git a/locales/zh/Web3Client/config.yml b/locales/zh/Web3Client/config.yml new file mode 100644 index 000000000..07cb1760c --- /dev/null +++ b/locales/zh/Web3Client/config.yml @@ -0,0 +1,9 @@ +--- +id: useofweb3js +name: Basic use of web3.js +summary: This tutorial gives a short introduction of the web3.js library, querying the block number +level: 2 +tags: + - JS + - Remix + - Web3