# OmniTransfers

OmniTransfers make possible the execution of multiple ERC20 or native token transfers to multiple recipients in the same transaction. Accesible from [transfer.omnify.finance](http://transfer.omnify.finance/) and [app.omnify.finance/transfers](https://app.omnify.finance/transfers)&#x20;

<figure><img src="/files/W39nl5UgYKpWFfGH3XL6" alt=""><figcaption><p>Visualization of how the OmniTransfer contract functions</p></figcaption></figure>

### Conduct Transfers

Calling the OmniTransfers contract to conduct a set of transfers is simple. Start by downloading the [OmniTransfers interface](https://github.com/OmniKobra/Omnify/blob/main/Omni/Contracts/Omnify/src/interfaces/transfersInterface.sol) found in our github repo. Before getting into making a call, let's talk about the `conductTransfers` payable function which takes `ParamTransfer[]` as its only parameter, that array can be of any length.

### ParamTransfer: A single transfer

ParamTransfer is the struct contained in the array passed as a parameter to `conductTransfers` , it represents a single transfer.

```solidity
struct ParamTransfer {
    address asset; // address of the asset, use address(0) for native token
    uint256 amount; // amount of the asset in wei
    address payable recipient; // address of the recipient
    string id; // your assigned ID of the transfer, should not be a duplicate
}
```

### Calculating msgValue based on transfers and their fees

Omnify charges a fee for each transfer it processes, so we need to make sure the total amount of msgValue includes the total value of native tokens being transferred in all the transfers (if any), and total value of fees charged from each transfer. You can find a list of all Omnify services' tiers and fees at [omnify.finance/fees](https://omnify.finance/fees).

### Steps to reproduce

{% stepper %}
{% step %}

### Define OmniTransfers variable

{% code fullWidth="false" %}

```solidity
ITransfers99 public omnitransfers = ITransfers99(0x8eAC1C3eD1e78bd373965818816987d525158148); // address on Avalanche C-Chain
```

{% endcode %}
{% endstep %}

{% step %}

### Define a `ParamTransfer[]` variable

This will contain all the transfers you wish to conduct.

```solidity
ITransfers99.ParamTransfer[] memory paramTransfers = new ITransfers99.ParamTransfer[](2); // can be any length
```

{% endstep %}

{% step %}

### Add your transfers as ParamTransfer struct to the paramTransfers array

We use address(0) for the asset if we wish to transfer the native token, and the contract address if the asset is an ERC20 token.

```solidity
ITransfers99.ParamTransfer nativeTokenTransfer = ITransfers99.ParamTransfer(address(0), 1 * 10**15, address(0x6BF6D002b5140b7CE0A0a4993621ecE52271e5f0), 'ID1');
ITransfers99.ParamTransfer usdcTransfer = ITransfers99.ParamTransfer(address(0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664), 1 * 10**3, address(0x6BF6D002b5140b7CE0A0a4993621ecE52271e5f0), 'ID2');
paramTransfers[0] = nativeTokenTransfer;
paramTransfers[1] = ercTokenTransfer;
```

{% endstep %}

{% step %}

### Get the altcoin & tier fees

Call `altcoinFee()` and `tier1()`, `tier2()`, `tier3()`, `tier4()`
{% endstep %}

{% step %}

### Define a variable msgVal

This will be the `msg.value` of the `conductTransfers` function call.

```solidity
uint256 public msgVal = 0;
```

{% endstep %}

{% step %}

### Match fee tiers&#x20;

Run a for loop for the array of `ParamTransfer` you defined to add transfer values and fee values to msgVal:

<pre class="language-solidity"><code class="lang-solidity">    uint256 public msgVal = 0;
    function _matchFeeTier(uint256 _amount) private view returns (TransferFee memory) {
        if (_amount >= tier1.lowerThreshold &#x26;&#x26; _amount &#x3C;= tier1.higherThreshold) {
            return tier1;
        }
        if (_amount >= tier2.lowerThreshold &#x26;&#x26; _amount &#x3C;= tier2.higherThreshold) {
            return tier2;
        }
        if (_amount >= tier3.lowerThreshold &#x26;&#x26; _amount &#x3C;= tier3.higherThreshold) {
            return tier3;
        }
        if (_amount >= tier4.lowerThreshold) {
            return tier4;
        }
        return tier1;
    }

    function _calculateFeeFromTier(TransferFee memory _tier) private pure returns (uint256) {
        return _tier.fee;
    }
<strong>
</strong>    for (uint256 i = 0; i &#x3C; paramTransfers.length; i++) {
        ParamTransfer memory _t = paramTransfers[i];
        address _asset = _t.asset;
        uint256 _amount = _t.amount;
        if (_asset == address(0)) {
            msgVal += _amount;
            TransferFee memory matchedTier = matchFeeTier(_amount);
            uint256 fee = _calculateFeeFromTier(matchedTier);
            msgVal += fee;
        } else {
            msgVal += altCoinFee;
        }
    }
</code></pre>

{% endstep %}

{% step %}

### Call conductTransfers

```solidity
omnitransfers.conductTransfers{value: msgVal}(paramTransfers);
```

{% endstep %}
{% endstepper %}

***We have conducted our first multisending transaction with OmniTransfers.*****&#x20;🎉**


---

# 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://omnify.gitbook.io/omnify-docs/deep-dive/omnitransfers.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.
