# Solidity Basics

### **1. Data Types and Variables** <a href="#id-1.-data-types-and-variables" id="id-1.-data-types-and-variables"></a>

Solidity, like other programming languages, has a variety of data types and variables used to store and manipulate data. Understanding these basics is crucial for writing smart contracts.

* **Primitive Data Types:**

  * **`uint`:** Unsigned integer (positive only).
  * **`int`:** Signed integer (can be positive or negative).
  * **`bool`:** Boolean value (`true` or `false`).
  * **`address`:** Represents a 20-byte Ethereum address.
  * **`bytes`:** Dynamically-sized byte array.
  * **`string`:** Dynamically-sized UTF-8 encoded string.

  ```
  uint256 myNumber = 42;
  bool isActive = true;
  address myAddress = 0x1234567890abcdef1234567890abcdef12345678;
  string myString = "Hello, Solidity!";
  ```

### **2. Functions** <a href="#id-2.-functions" id="id-2.-functions"></a>

Functions in Solidity are similar to functions in other programming languages. They define a piece of code that can be called and executed.

* **Basic Function Syntax:**

  ```
  function multiply(uint256 a, uint256 b) public pure returns (uint256) {
      return a * b;
  }
  ```

  * **`public`:** The function can be called both internally and externally.
  * **`pure`:** Indicates that the function does not read or modify the state.

### **3. Visibility Specifiers** <a href="#id-3.-visibility-specifiers" id="id-3.-visibility-specifiers"></a>

Visibility specifiers control how and where functions and state variables can be accessed.

* **Types of Visibility:**
  * **`public`:** Accessible externally and internally.
  * **`private`:** Accessible only within the contract that defines it.
  * **`internal`:** Accessible within the contract and contracts deriving from it.
  * **`external`:** Accessible only from outside the contract.

### **4. Modifiers** <a href="#id-4.-modifiers" id="id-4.-modifiers"></a>

Modifiers are used to change the behavior of functions. They allow you to add preconditions to functions.

* **Example of a Modifier:**

  ```solidity
  modifier onlyOwner() {
      require(msg.sender == owner, "Not the contract owner");
      _;
  }

  function changeOwner(address newOwner) public onlyOwner {
      owner = newOwner;
  }
  ```

  * **`_`:** The placeholder for the function's body.

### **5. Custom Modifiers** <a href="#id-5.-custom-modifiers" id="id-5.-custom-modifiers"></a>

You can create custom modifiers to enforce specific rules within your contract.

* **Example:**

  ```solidity
  modifier isAdult(uint256 age) {
      require(age >= 18, "Not an adult");
      _;
  }

  function enterBar(uint256 age) public isAdult(age) {
      // code for entering the bar
  }
  ```

### **6. Constructors** <a href="#id-6.-constructors" id="id-6.-constructors"></a>

Constructors are special functions that are executed only once when a contract is deployed. They are typically used to initialize contract state.

* **Example:**

  ```solidity
  contract MyContract {
      address public owner;

      constructor() {
          owner = msg.sender;
      }
  }
  ```

### **7. Global Variables** <a href="#id-7.-global-variables" id="id-7.-global-variables"></a>

Solidity provides several global variables that can be accessed within contracts.

* **Examples:**
  * **`msg.sender`:** The address of the caller.
  * **`msg.value`:** The amount of Ether sent with the transaction.
  * **`block.timestamp`:** The current block's timestamp.
  * **`block.number`:** The current block number.

### **8. Operators** <a href="#id-8.-operators" id="id-8.-operators"></a>

Solidity supports standard operators like arithmetic, comparison, and logical operators.

* **Examples:**
  * **Arithmetic:** `+`, `-`, `*`, `/`, `%`
  * **Comparison:** `==`, `!=`, `>`, `<`, `>=`, `<=`
  * **Logical:** `&&`, `||`, `!`

### **9. Conditionals** <a href="#id-9.-conditionals" id="id-9.-conditionals"></a>

Conditionals are used to perform different actions based on different conditions.

* **Example:**

  ```solidity
  function checkNumber(uint256 num) public pure returns (string memory) {
      if (num > 10) {
          return "Greater than 10";
      } else {
          return "10 or less";
      }
  }
  ```

### **10. Arrays** <a href="#id-10.-arrays" id="id-10.-arrays"></a>

Arrays in Solidity can be of fixed or dynamic size.

* **Example:**

  ```solidity
  uint256[] public numbers;

  function addNumber(uint256 num) public {
      numbers.push(num);
  }
  ```

### **11. Mappings** <a href="#id-11.-mappings" id="id-11.-mappings"></a>

Mappings are key-value pairs where each unique key is mapped to a single value.

* **Example:**

  ```solidity
  mapping(address => uint256) public balances;

  function updateBalance(address user, uint256 newBalance) public {
      balances[user] = newBalance;
  }
  ```

### **12. Structs** <a href="#id-12.-structs" id="id-12.-structs"></a>

Structs allow you to create more complex data types by grouping multiple variables.

* **Example:**

  ```solidity
  struct User {
      string name;
      uint256 age;
  }

  User public user;

  function setUser(string memory name, uint256 age) public {
      user = User(name, age);
  }
  ```

### **13. Events** <a href="#id-13.-events" id="id-13.-events"></a>

Events are used to log information on the blockchain, which can be listened to by off-chain applications.

* **Example:**

  ```solidity
  event UserCreated(address indexed userAddress, string name);

  function createUser(string memory name) public {
      emit UserCreated(msg.sender, name);
  }
  ```

### **14. Ether and Payments** <a href="#id-14.-ether-and-payments" id="id-14.-ether-and-payments"></a>

Solidity allows contracts to handle Ether, the native currency of Ethereum.

* **Example:**

  ```solidity
  function sendEther(address payable recipient) public payable {
      recipient.transfer(msg.value);
  }
  ```

### **15. Errors** <a href="#id-15.-errors" id="id-15.-errors"></a>

Solidity allows you to define custom errors to save gas and improve readability.

* **Example:**

  ```solidity
  error NotEnoughFunds(uint256 available, uint256 required);

  function withdraw(uint256 amount) public {
      if (amount > address(this).balance) {
          revert NotEnoughFunds(address(this).balance, amount);
      }
  }
  ```

### **16. Inheritance** <a href="#id-16.-inheritance" id="id-16.-inheritance"></a>

Solidity supports inheritance, allowing you to create new contracts based on existing ones.

* **Example:**

  ```solidity
  contract Parent {
      function sayHello() public pure returns (string memory) {
          return "Hello from Parent";
      }
  }

  contract Child is Parent {
      function sayHelloFromChild() public pure returns (string memory) {
          return "Hello from Child";
      }
  }
  ```

### **17. Calling Other Contracts** <a href="#id-17.-calling-other-contracts" id="id-17.-calling-other-contracts"></a>

You can call functions from other contracts using either `call` or interface-based method calls.

* **Example:**

  ```solidity
  contract ExternalContract {
      function externalFunction() public pure returns (string memory) {
          return "Called from another contract";
      }
  }

  contract MyContract {
      ExternalContract externalContract;

      constructor(address _externalContractAddress) {
          externalContract = ExternalContract(_externalContractAddress);
      }

      function callExternalFunction() public view returns (string memory) {
          return externalContract.externalFunction();
      }
  }
  ```

### **18. Interfaces** <a href="#id-18.-interfaces" id="id-18.-interfaces"></a>

Interfaces define the functions that must be implemented by a contract but do not contain any implementation themselves.

* **Example:**

  ```solidity
  interface IERC20 {
      function totalSupply() external view returns (uint256);
      function balanceOf(address account) external view returns (uint256);
      function transfer(address recipient, uint256 amount) external returns (bool);
  }

  contract MyToken is IERC20 {
      // Implement the functions defined in the interface
  }
  ```
