> For the complete documentation index, see [llms.txt](https://docs.yarchain.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.yarchain.org/dev-docs/use-cases.md).

# Use cases

{% hint style="info" %}
More cases can be found here: [https://github.com/YARlabs/YAR-v2-contracts/](https://github.com/YARlabs/YAR-v2-contracts/tree/main)
{% endhint %}

The YAR protocol allows sending arbitrary transactions to any address, whether it's a smart contract or an EOA wallet.

### Sending Transactions to an EOA Wallet

Such transactions usually only make sense when transferring the native token of the network, the amount of which is specified in the `value` parameter.

For example, a standard transaction within one network:

```typescript
sender.sendTransaction({
  from: sender.address, // sender
  to: recipient.address, // recipient
  value: 1e18, // amount of funds sent
})
```

To deliver a similar transaction to another network, it looks like this:

```typescript
yarRequest.send({
  initialChainId,
  sender: sender.address, // sender
  payer: sender.address, // sender
  targetChainId,
  target: recipient.address, // recipient
  value: 1e18, // amount of funds sent
  data: '0x',
  _nonce: 0,
})
```

After executing this transaction, the Relayers network will transfer 1e18 of the target network's native tokens to the recipient's address.

### Sending Transactions to a Smart Contract

Sending transactions to an arbitrary smart contract makes sense when the called method does not depend on the `msg.sender` address. For example, the address is passed in the arguments, or it involves meta-transactions or account abstraction.

For example, a standard transaction within one network:

```typescript
sender.sendTransaction({
    from: sender.address, // sender
    to: smartContract.address, // called smart contract
    value: 0, // amount of funds sent
    data: '0x11111...' // encoded transaction
})
```

To deliver a similar transaction to another network, it looks like this:

```typescript
yarRequest.send({
    initialChainId,
    sender: sender.address, // sender
    payer: sender.address, // sender
    targetChainId,
    target: smartContract.address, // called smart contract
    value: 0, // amount of funds sent
    data: '0x11111...', // encoded transaction
    _nonce: 0
})
```

By executing this transaction, the `YarResponse` smart contract will parse the bytes from `data` and call the specified function at the `target` address. You can also pass the `value` parameter with this transaction if needed.

Here's the English translation of the provided Russian text, formatted for a programming context:

***

### Cross-Chain API

The main potential of the Yar protocol lies in enabling communication between smart contracts of the same application located on different networks.\
Create an empty smart contract:

```solidity
contract Example {

}
```

Register the addresses of \[YarRequest] and \[YarResponse] in the smart contract:

```solidity
contract Example {
    address public yarRequest;
    address public yarResponse;

    constructor(
        address initialYarRequest,
        address initialYarResponse
    ) {
        yarRequest = initialYarRequest;
        yarResponse = initialYarResponse;
    }
}
```

To send a cross-chain transaction from a smart contract, the \[YarRequest] will require the data model \[YarLib.YarTX].

```solidity
library YarLib {
    struct YarTX {
        uint256 initialChainId; // Identifier of the current network
        address sender; // Your smart contract [Example]
        address payer; // User who calls Example and pays the fee in Yar
        uint256 targetChainId; // Identifier of the network where the transaction will be delivered
        address target; // Address in the [TARGET] network where the transaction will be called
        uint256 value; // Amount of the native token of the [TARGET] network to be sent with the transaction
        bytes data; // Encoded transaction data (bytes4 for the function signature + function arguments)
        uint256 _nonce; // This parameter will be redefined in YarRequest; set it to 0
    }
}
```

Import `YarLib` into your smart contract:

```solidity
import { YarLib } from "./YarLib.sol";

contract Example {
    ...
}
```

Develop a receiver function that will accept a string of data. Two checks are required to identify the senders:

1. Check that `msg.sender` equals the `yarResponse` address.
2. Check that `yarTX.sender` equals the address of your smart contract from the initial network.

```solidity
contract Example {
    string public lastMessage;

    function exampleReceiveMessage(string calldata message) external {
        require(msg.sender == yarResponse, "only yarResponse!");
        YarLib.YarTX memory yarTx = YarResponse(yarResponse).trustedYarTx();
        // Check against address(this)
        // - This will work if both smart contracts have the same address
        // If your smart contracts have different addresses, you will need to register them separately
        require(yarTx.sender == address(this), "only app!");
        lastMessage = message;
    }
}
```

Example of registering the addresses of your applications from external networks:

```solidity
contract Example {

    mapping(uint256 chainId => address peer) public peers;

    function setPeer(uint256 newChainId, address newPeer) external {
        require(msg.sender == owner, "only owner!");
        peers[newChainId] = newPeer;
    }

    function getPeer(uint256 _chainId) public view returns (address) {
        address peer = peers[_chainId];
        return peer == address(0) ? address(this) : peer;
    }

    function exampleReceiveMessage(string calldata message) external {
        require(msg.sender == yarResponse, "only yarResponse!");
        YarLib.YarTX memory yarTx = YarResponse(yarResponse).trustedYarTx();
        require(yarTx.sender == getPeer(yarTx.initialChainId), "only app!");
        ...
    }
}
```

Now, to make this function callable from another network, implement a message-sending function.

```solidity
contract Example {
    function exampleSendMessage(
        string calldata message,
        uint256 targetChainId
    ) external returns(YarLib.YarTX) {
        ...
    }
}
```

Where `message` is the message to be sent\
`targetChainId` is the network where the message will be delivered\
`returns(YarLib.YarTX)` is used in simulation for gas estimation.

Encode the call to the \[exampleReceiveMessage] function:

```solidity
bytes memory encodedTX = abi.encodeWithSelector(
    Example.exampleReceiveMessage.selector,
    message
);
```

Then create `YarTX`:

```solidity
YarLib.YarTX memory yarTx = YarLib.YarTX(
    block.chainid,
    address(this), // if your applications have identical addresses
    msg.sender,
    targetChainId,
    targetAddress,
    0,
    encodedTX,
    0
);
```

or

```solidity
YarLib.YarTX memory yarTx = YarLib.YarTX(
    block.chainid,
    getPeer(targetChainId), // to get the address of your application in the target network
    msg.sender,
    targetChainId,
    targetAddress,
    0,
    encodedTX,
    0
);
```

Next, send this model to `YarRequest`:

```solidity
contract Example {
    function exampleSendMessage(
        string calldata message,
        uint256 targetChainId
    ) external returns(YarLib.YarTX) {
        bytes memory encodedTX = abi.encodeWithSelector(
            Example.exampleReceiveMessage.selector,
            message
        );

        YarLib.YarTX memory yarTx = YarLib.YarTX(
            block.chainid,
            address(this), // if your applications have identical addresses
            msg.sender,
            targetChainId,
            targetAddress,
            0,
            encodedTX,
            0
        );

        // Send the transaction
        // Returning the model can be useful for transaction simulation and fee estimation
        return YarRequest(yarRequest).send(yarTX);
    }
}
```

Now, for the user to send a transaction from one of your smart contracts to another in an external network, they must have a balance in YarHub.

The balance can be topped up through `YarRequest`:

```solidity
yarRequest.connect(user).deposit(nativeTokenAmount);
```

Next, grant permission to your application to spend funds:

```solidity
yarRequest.connect(user).approve(yourAppFromInitialChainAddress, yarAmount);
```

Then, call your application:

```solidity
example.connect(user).exampleSendMessage('Hello!', targetChainId);
```

The rest will be handled by the YAR network.

First, the deposit will be credited in YarHub:

```solidity
yarHub.connect(relayers).deposit(user.address, yarTokenAmount);
```

Next, permission will be recorded for the transfer to the application:

```solidity
yarHub.connect(relayers).approve(user.address, initialChainId, yourAppFromInitialChainAddress, yarTokenAmount);
```

Then, the user's transaction will be added to the queue:

```solidity
yarHub.connect(relayers).createTransaction(yarTX, initialNativeTxHash);
```

After that, the transaction will be processed, temporarily locking sufficient funds on the user's deposit to complete the transaction:

```solidity
yarHub.connect(relayers).executeTransaction(yarTX, feeTokensToLock);
```

Finally, the YAR network will deliver the transaction to the target network:

```solidity
yarResponse.connect(relayers).deliver(yarTX);
```

In the target network, the `YarResponse` smart contract will execute the transaction:

```solidity
yarTx.target.call{ value: yarTx.value }(yarTx.data);
```
