# Contracts

## More information about Contract in Solidity

### constructor

Constructor is a function that runs immediately when the smart contract is initialized

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

// Base contract X
contract X {
    string public name;

    constructor(string memory _name) {
        name = _name;
    }
}
```

### State variable visibility

* `public` - Public variables are similar to `internal` variables (allowing the current contract and inherited contracts to access) but will automatically create a `getter function` so that external contracts can also access it.
* `internal` - The variable can only be accessed by the current contract and inherited contracts. This is also the default visibility for state variable.
* `private` - The variable can only be accessed by the current contract.

**Note**: The `internal` and `private` variables only restrict access to other `contracts`. The value of the variable remains visible to everyone.

### Function visibility

* `external` - `function` that can only be called from outside.
* `public` - `function` can both be called by another `function` in `contract`, and can also be called from outside.
* `internal` - `function` can only be called by an existing `contract` or an inherited `contract`.
* `private` - `function` can only be called by the current `contract`.

### Getter function

`function` is used to call the `public` variable that the compiler automatically creates. Also used to refer to the concept of `function` used to query variables to view.

```solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.9.0;

contract C {
    uint public data = 42;
}

contract Caller {
    C c = new C();
    function f() public view returns (uint) {
        return c.data();
    }
}
```

### Constants and immutable state variables

* `constant` - variables whose values ​​are fixed immediately upon compilation (put into contract bytecode).
* `immutable` - variables whose values ​​can be assigned during `construct`.

```solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.21;

uint constant X = 32**22 + 8;

contract C {
    string constant TEXT = "abc";
    bytes32 constant MY_HASH = keccak256("abc");
    uint immutable decimals = 18;
    uint immutable maxBalance;
    address immutable owner = msg.sender;

    constructor(uint decimals_, address ref) {
        if (decimals_ != 0)
            // Immutables are only immutable when deployed.
            // At construction time they can be assigned to any number of times.
            decimals = decimals_;

        // Assignments to immutables can even access the environment.
        maxBalance = ref.balance;
    }

    function isBalanceTooHigh(address other) public view returns (bool) {
        return other.balance > maxBalance;
    }
}
```

### Pure function

`function` does not read or change the state of the blockchain. Or used as a calculation `function`.

```solidity
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.9.0;

contract C {
    function f(uint a, uint b) public pure returns (uint) {
        return a * (b + 42);
    }
}
```

### Payable functions and addresses

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract Payable {
    // Payable address can send Ether via transfer or send
    address payable public owner;

    // Payable constructor can receive Ether
    constructor() payable {
        owner = payable(msg.sender);
    }

    // Function to deposit Ether into this contract.
    // Call this function along with some Ether.
    // The balance of this contract will be automatically updated.
    function deposit() public payable {}

    // Call this function along with some Ether.
    // The function will throw an error since this function is not payable.
    function notPayable() public {}

    // Function to withdraw all Ether from this contract.
    function withdraw() public {
        // get the amount of Ether stored in this contract
        uint256 amount = address(this).balance;

        // send all Ether to owner
        (bool success,) = owner.call{value: amount}("");
        require(success, "Failed to send Ether");
    }

    // Function to transfer Ether from this contract to address from input
    function transfer(address payable _to, uint256 _amount) public {
        // Note that "to" is declared as payable
        (bool success,) = _to.call{value: _amount}("");
        require(success, "Failed to send Ether");
    }
}
```

### Receive Ether and Fallback function

A `contract` can have at most one `receive` function, declared using `receive() external payable { ... }` (without the `function` keyword). This `function` must have no `arguments`, cannot `return` anything and must have `external` visibility as well as `payable` `state mutability`. It can be `virtual`, it can be `override` and it can have `modifiers`.

```
    Which function is called, fallback() or receive()?

           send Ether
               |
         msg.data is empty?
              / \
            yes  no
            /     \
receive() exists?  fallback()
         /   \
        yes   no
        /      \
    receive()   fallback()
```

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract Fallback {
    event Log(string func, uint256 gas);

    // Fallback function must be declared as external.
    fallback() external payable {
        // send / transfer (forwards 2300 gas to this fallback function)
        // call (forwards all of the gas)
        emit Log("fallback", gasleft());
    }

    // Receive is a variant of fallback that is triggered when msg.data is empty
    receive() external payable {
        emit Log("receive", gasleft());
    }

    // Helper function to check the balance of this contract
    function getBalance() public view returns (uint256) {
        return address(this).balance;
    }
}

contract SendToFallback {
    function transferToFallback(address payable _to) public payable {
        _to.transfer(msg.value);
    }

    function callFallback(address payable _to) public payable {
        (bool sent,) = _to.call{value: msg.value}("");
        require(sent, "Failed to send Ether");
    }
}
```

### Oracle

Oracle for smart contracts is a bridge between blockchain and the outside world. It provides data to smart contracts from sources outside the blockchain, such as APIs, market data, weather data, etc.

Here are some examples of how to use oracle for smart contracts:

* Providing price data for decentralized markets (DeFi): Oracle can provide price data for crypto assets, allowing traders to make trades on decentralized exchanges.
* Activate insurance contracts: Oracle can provide data about insurance events, such as accidents or natural disasters, to trigger insurance payments.
* Automate processes: Oracle can be used to automate processes, such as bill payment or supply chain management.

List of Oracles on Klaytn: <https://klaytn.foundation/ecosystem/?search=&cate=oracles-bridges&sort=abc>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bootcamp.openguild.wtf/smart-contract-development/advanced-solidity/contracts.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
