Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions public/data/contents/markdownData.json

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions src/challenges/solidity/inline-assembly.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
name: Inline Assembly
index: 26
lesson: 26
summary: Introduction to Inline Assembly in Solidity and its use for low-level control over the EVM
labels: ["solidity"]
---

Inline Assembly in Solidity allows developers to write low-level code directly within Solidity contracts. It provides fine-grained control over the Ethereum Virtual Machine (EVM) and enables developers to perform operations that are not directly available through Solidity's high-level constructs. Inline Assembly is written using the `assembly` keyword followed by a block of assembly code.

## Purpose of Inline Assembly

Inline Assembly is primarily used for:

- **Optimization**: To reduce gas costs by implementing more efficient low-level operations.
- **Access to EVM Internals**: Direct access to low-level features and instructions that are not available in high-level Solidity.
- **Compatibility**: Interacting with legacy smart contracts or performing operations not directly supported by Solidity.
-
## Dangerous Aspects of Inline Assembly

Inline Assembly is a powerful feature in Solidity, but it comes with certain risks and limitations:
- **Complexity**: Assembly code is more complex and harder to read than high-level Solidity code.
- **Security Risks**: Incorrectly written assembly code can lead to vulnerabilities and security risks.
- **Portability**: Assembly code may not be portable across different EVM versions or compilers.

## Example of Inline Assembly

Here is an example illustrating the use of inline assembly in Solidity to perform arithmetic operations:

```solidity
pragma solidity ^0.8.26;

contract AssemblyExample {
// Function to add two numbers using inline assembly
function add(uint256 a, uint256 b) public pure returns (uint256 result) {
assembly {
result := add(a, b)
}
}

// Function to save data to the contract storage using inline assembly
function setStorageData(uint256 slot, uint256 data) public {
assembly {
sstore(slot, data)
}
}

// Function to get stored data from the contract storage
// returns the value stored at the specified slot
function getStorageData(
uint256 slot
) public view returns (uint256 data) {
assembly {
data := sload(slot)
}
}
}
4 changes: 4 additions & 0 deletions src/constants/solidity/code-exercises.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,4 +300,8 @@ export const CODE_EXERCISES: CodeTemplatesType = {
exercise5:
"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\n// Step 1: Implement a contract named 'SendEtherChecked'\n// Step 2: Inside the 'SendEtherChecked' contract, declare a public mapping named 'balances' that maps addresses to uint256\n// Step 3: Still inside the 'SendEtherChecked' contract, implement a function named 'sendEther' that takes two parameters: an address payable 'recipient' and a uint256 'amount'\n// Step 4: The 'sendEther' function should be public and payable\n// Step 5: Inside the 'sendEther' function, add a require statement to check that the sender has enough Ether to send\n// Step 6: Still inside the 'sendEther' function, update the balances of the sender and the recipient\n// Step 7: Still inside the 'sendEther' function, use the 'call' method to send the specified amount of Ether to the specified address\n// Step 8: Add a require statement to check that the call was successful\n",
},
"inline-assembly": {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing work! Do you think it's possible to expand to five exercises and solutions?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

"exercise1": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\ncontract InlineAssemblyExercise1 {\n\n\t// Task 1: Create a function named 'multiplyNumbers' that:\n\t// - Takes two uint256 arguments named 'a' and 'b'\n\t// - Uses inline assembly to multiply 'a' and 'b' and returns the result\n\n}\n\n// tip: use the 'mul' opcode",
"exercise2": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\ncontract InlineAssemblyExercise2 {\n\n\t// Task 1: Create a function named 'isGreater' that:\n\t// - Takes two uint256 arguments named 'a' and 'b'\n\t// - Uses inline assembly to return true if 'a' is greater than 'b', otherwise returns false\n\n}\n\n// tip: use the 'gt' opcode",
}
};
4 changes: 4 additions & 0 deletions src/constants/solidity/code-solutions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,4 +300,8 @@ export const CODE_SOLUTIONS: CodeTemplatesType = {
exercise5:
"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\n// Step 1: Implement a contract named 'SendEtherChecked'\ncontract SendEtherChecked {\n\n // Step 2: Inside the 'SendEtherChecked' contract, declare a public mapping named 'balances' that maps addresses to uint256\n mapping(address => uint256) public balances;\n\n // Step 3: Still inside the 'SendEtherChecked' contract, implement a function named 'sendEther' that takes two parameters: an address payable 'recipient' and a uint256 'amount'\n // Step 4: The 'sendEther' function should be public and payable\n function sendEther(address payable recipient, uint256 amount) public payable {\n // Step 5: Inside the 'sendEther' function, add a require statement to check that the sender has enough Ether to send\n require(balances[msg.sender] >= amount, 'Not enough Ether');\n // Step 6: Still inside the 'sendEther' function, update the balances of the sender and the recipient\n balances[msg.sender] -= amount;\n balances[recipient] += amount;\n // Step 7: Still inside the 'sendEther' function, use the 'call' method to send the specified amount of Ether to the specified address\n (bool success, ) = recipient.call{value: amount}('');\n // Step 8: Add a require statement to check that the call was successful\n require(success, 'Failed to send Ether');\n }\n}",
},
"inline-assembly": {
"exercise1": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\ncontract InlineAssemblyExercise1 {\n\n\t// Task 1: Create a function named 'multiplyNumbers' that:\n\t// - Takes two uint256 arguments named 'a' and 'b'\n\t// - Uses inline assembly to multiply 'a' and 'b' and returns the result\n\n\tfunction multiplyNumbers(uint256 a, uint256 b) public pure returns (uint256 result) {\n\t\tassembly {\n\t\t\tresult := mul(a, b)\n\t\t}\n\t}\n}\n\n// tip: use the 'mul' opcode",
"exercise2": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.26;\n\ncontract InlineAssemblyExercise2 {\n\n\t// Task 1: Create a function named 'isGreater' that:\n\t// - Takes two uint256 arguments named 'a' and 'b'\n\t// - Uses inline assembly to return true if 'a' is greater than 'b', otherwise returns false\n\n\tfunction isGreater(uint256 a, uint256 b) public pure returns (bool result) {\n\t\tassembly {\n\t\t\tresult := gt(a, b)\n\t\t}\n\t}\n}\n\n// tip: use the 'gt' opcode",
}
};