# Introduction

Hashflow uses DeFi-native RFQs to fetch quotes from market makers. Instead of a constant-product pricing function commonly used by AMMs, Hashflow allows market makers to source liquidity from anywhere and price assets using off-chain pricing functions. \
\
By moving pricing off-chain, market makers can use more sophisticated pricing strategies that factor in off-chain data like historic asset prices, volatility, and other real-world information that allows them to effectively price assets. \
\
Market makers are required to cryptographically sign quotes that remain unchanged for the duration of the trade. This ensures that the price is guaranteed, traders are protected against slippage, and cannot be front-run or sandwich attacked.&#x20;


# Protocol Fees & Revenue Share

A nominal fee is included on each trade on Hashflow RFQ. Hashflow's current fees model include two types of fees based on the type of asset pair traded:

* Dynamic fees on blue-chip trading pairs (USDC-WETH, etc.)
* Static fees on non blue-chip trading pairs (USDC-USDT, USDC-ARB, etc.)

Hashflow's dynamic fees model enables fees to adapt to live market data in real-time, adjusting roughly every five seconds - allowing for fees to be optimized to ensure quotes remain competitive without impacting trading volume.

These trading fees are baked into your price quotes, and they are paid automatically when your trades are executed.

### Revenue share for HFT Stakers

Hashflow's trading fees are a benefit to both the protocol and HFT stakers. The DAO’s approval of the [protocol fees proposal](https://snapshot.org/#/hashflowdao.eth/proposal/0x014a10517b46f895583de15713733147ca960f18a40c45d6653db7a150797ba7) has enabled another way for Hashflow to reward HFT stakers and generate revenue to offset the ongoing costs associated with operating the protocol.

Protocol revenue from these fees are distributed monthly to stakeholders as follows:

| **Fee (%)** | **Distribution**                           |
| ----------- | ------------------------------------------ |
| 50%         | Rewards for HFT stakers                    |
| 30%         | Community treasury for future HFT buybacks |
| 20%         | Foundation operating expenses              |

### How do I claim revenue share?

To claim your rewards, visit the [Hashflow trading app](https://app.hashflow.com/stake) and follow the steps below:

1️. On your desktop, click the `Hashflow` icon on the top right of the dashboard

2️. If you’re eligible, you will see an HFT balance along with the `Claim` button enabled&#x20;

3️. Click the `Claim` button and follow the rest of the flow from your wallet

<figure><img src="https://1378959595-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-ML-MjGdn5-U1Ma0ab_Y%2Fuploads%2Fd4KL7guG06iJUcf9UOI2%2Fimage.png?alt=media&amp;token=ce6f7964-b082-45d6-b251-cf17bfc4ae6a" alt=""><figcaption></figcaption></figure>


# How To Guides

A variety of how-tos for common market making needs

### 1. Getting the list of trades

We provide a `REST` API that can return pagniated trades from a particular range for a particular pool&#x20;

* The API Endpoint is: <https://api.hashflow.com/maker/v3/trades>
* You need to provide your `marketMaker`, `networkId` , `pool`, `startTs (optional)`, `endTs (optional)` , `skip (optional)` , `limit (optional)` and authentication key to access&#x20;
* It will return a list of trades fetched

Request Example:

<pre class="language-bash"><code class="lang-bash"><strong>curl "https://api.hashflow.com/maker/v3/pool/getTrades?networkId=&#x3C;networkId>&#x26;pool=&#x3C;poolAddress>&#x26;" \
</strong><strong>"startTs=1659550186&#x26;endTs=1659700186&#x26;marketMaker=&#x3C;MakerName>" \
</strong><strong>-H "authorization:&#x3C;maker-key>"
</strong></code></pre>

### 2. Post Trade Restriction

We provide a `REST` API that allow market makers to post a restriction without having to respond to a quote with it.&#x20;

* The API Endpoint is: <https://api.hashflow.com/maker/v3/restriction>
* You will need to provide below example field in body to post the restriction together with authentication key to access the endpoint.&#x20;

```json
{
    "marketMaker": string,
    "trader": string,
    "reason": "rate_limit",
    "expiryTimestampMs": number, //optional
    "chain": {
        "chainType": string, //evm|solana 
        "chainId": number
    } // optional
}
```

* It will return with a success response

### 3. Getting the list of supported tokens

We provide a `REST` API that can return a list of supported tokens:

* The API endpoint is: <https://api.hashflow.com/maker/v3/tokens>
* You need to provide your maker name and key to access.
* It will return those fields: `chainType`, `chainID`, `token` (address), `name` and `decimals`.

Example:

```bash
curl "https://api.hashflow.com/maker/v3/tokens?marketMaker=<maker-name>" \
-H "authorization:<maker-key>"
```

You need to change `<maker-name>` and `<maker-key>` in this command accordingly.

The output will look like:

```
{
  "status": "success",
  "tokens": [
    {
      "chainType": "evm",
      "chainId": 1,
      "token": "0x0000000000000000000000000000000000000000",
      "name": "ETH",
      "decimals": 18
    },
    {
      "chainType": "evm",
      "chainId": 42,
      "token": "0x0000000000000000000000000000000000000000",
      "name": "ETH",
      "decimals": 18
    },
    ...
}
```

### Supporting other chains

You've finished [setting up](broken://pages/Fge93gl6UmgBI82Qc46e) your market maker on Ethereum but want to expand to market making on other chains? Simply follow these steps:

1. **Contact the hashflow team** (via Telegram/Discord) and tell us which chains you'd like to support. We'll then add them to your market making config which controls the market makers we request for trades on each chain.
2. **Create a new pool**. You will need to [create a pool](https://docs.hashflow.com/hashflow/market-making/pages/Fge93gl6UmgBI82Qc46e#3.-create-a-pool) for the new chain. The steps are identical to the pool you created before. If you're using an EOA:
   * You can re-use the EOA but will need a new pool
   * You'll also need to add allowances for the new pool to your EOA
3. **Support 'priceLevels'** **for the new chain**. Extend your [priceLevels logic](https://docs.hashflow.com/hashflow/market-making/pages/Fge93gl6UmgBI82Qc46e#3.-submit-price-levels-indicative-pricing) to also publish the pairs that you will be market making on the new chains. We need this to route trades your way.
4. **Support 'RFQ' for the new chain**. Extend your [market making logic](https://docs.hashflow.com/hashflow/market-making/pages/Fge93gl6UmgBI82Qc46e#4.-receive-rfq-and-respond-with-quote) to respond with quotes for RFQs on the new chain. In your quotes, include the new pool you created.
5. **Support 'signQuote' for the new chain**. Extend your [signature logic](https://docs.hashflow.com/hashflow/market-making/pages/Fge93gl6UmgBI82Qc46e#5.-support-signing-quotes) to work for the new chain. The only difference here is that you need to sign with the applicable pool/EOA
6. **Test your trades on the new chain**. You can run trades through the Hashflow UI to ensure trades on the new chain process successfully.
7. **Success!** You're on a new chain 🥳.


# Getting Started - API v3

Market Making on API v3 is JSON WebSocket based, similar to API v2.

## 1a. Creating a Pool (EVM)

Every Hashflow trade happens via a [HashflowPool](https://github.com/hashflownetwork/x-protocol/blob/main/evm/contracts/pools/HashflowPool.sol) contract. Prior to creating a pool, you will have to request to be added to the allowlist. Please reach out to the Hashflow team to have your pool creator wallet added.

There are two ways to create a pool:

* via UI on the [Hashflow App](https://app.hashflow.com/pools)
* directly via the [HashflowFactory](https://github.com/hashflownetwork/x-protocol/blob/main/evm/contracts/HashflowFactory.sol) smart contract

The HashflowFactory addresses on the supported chains are as such

Mainnets:

| Chain Name | Block Explorer Link                                                                  |
| ---------- | ------------------------------------------------------------------------------------ |
| Ethereum   | <https://etherscan.io/address/0xdE828fdc3F497F16416D1bB645261C7C6a62DAb5>            |
| Arbitrum   | <https://arbiscan.io/address/0xdE828fdc3F497F16416D1bB645261C7C6a62DAb5>             |
| Optimism   | <https://optimistic.etherscan.io/address/0x6D551f4D999faC0984eb75B2B230ba7e7651BdE7> |
| Polygon    | <https://polygonscan.com/address/0xdE828fdc3F497F16416D1bB645261C7C6a62DAb5>         |
| BSC        | <https://bscscan.com/address/0xdE828fdc3F497F16416D1bB645261C7C6a62DAb5>             |
| Avalanche  | <https://snowtrace.io/address/0xdE828fdc3F497F16416D1bB645261C7C6a62DAb5>            |
| Base       | <https://base.blockscout.com/address/0xdE828fdc3F497F16416D1bB645261C7C6a62DAb5>     |

Testnets:

| Chain Name  | Block Explorer Link                                                              |
| ----------- | -------------------------------------------------------------------------------- |
| BSC Testnet | <https://testnet.bscscan.com/address/0x7D916a5b5A23A9FB583Cd9B227B0a0b9C01eAA85> |

In order to create a pool, you will need two pieces of information:

* `name` - this can be anything, but shorter names are preferred for display
* `signer`- the 20-byte address derived from the Public Key of a `secp256k1` keypair that will be used to sign quote payloads; the simplest example of this is the address of a MetaMask wallet, the private key of which can be used to sign quotes

## 1b. Creating a Pool (Solana)

Liquidity pools are the core structure (albeit in a different from) on Solana as well.

There are two ways to create a pool:

* via UI on the [Hashflow App](https://app.hashflow.com/pools)
* directly via the Hashflow Program

The Hashflow Program is written in Anchor and can be found at the following addresses:

| Network        | Program Address                                |
| -------------- | ---------------------------------------------- |
| Solana Devnet  | `HB3LQRRBZqZWkYXhFgrPbNvXzAhUvQfX2PmFTpcceGg2` |
| Solana Mainnet | CRhtqXk98ATqo1R8gLg7qcpEMuvoPzqD5GNicPPqLMD    |

The Anchor IDL for the pool creation method is the following

```json
{
  "name": "createPool",
  "accounts": [
    {
      "name": "owner",
      "isMut": true,
      "isSigner": true,
      "docs": [
        "Market Maker."
      ]
    },
    {
      "name": "pool",
      "isMut": true,
      "isSigner": false,
      "docs": [
        "Pool account."
      ]
    },
    {
      "name": "systemProgram",
      "isMut": false,
      "isSigner": false,
      "docs": [
        "System program."
      ]
    }
  ],
  "args": [
    {
      "name": "poolId",
      "type": "u64"
    },
    {
      "name": "quoteSignerPubKey",
      "type": {
        "array": [
          "u8",
          64
        ]
      }
    }
  ]
}
```

The pool creation method takes two parameters:

* `poolId` - an arbitrary `u64` integer that is used to derive the pool address (PDA)
* `quoteSignerPubKey` - similar to EVM chains, this is the uncompressed Public Key of a `secp256k1` signer (the first `04` byte is omitted, so this is only 64 bytes) - because of this the signing mechanism for Ethereum and Solana quotes is very similar (the payloads differ)

In Solana, every account that will be touched by a transaction has to be explicitly declared within the transaction. The accounts that we need to pass to this instruction are:

* `owner` - this is the signer of the transaction and owner of the pool
* `pool` - the pool PDA address (details below on how to derive it)
* `systemProgram` - the System Program `11111111111111111111111111111111`

Deriving the PDA is done by using the following two data:

* `"pool"`
* the Little Endian byte notation of the `poolId` (8 bytes, from least significant to most significant)

In Anchor, the derivation of the pool PDA looks as such:

```rust
#[account(
    init,
    payer = owner,
    space = Pool::LEN,
    seeds = [&Pool::SEED_PREFIX[..], &pool_id.to_le_bytes()[..]],
    bump
)]
```

&#x20;The `Pool` account is defined as such

```rust
#[account]
/// Market Maker Pool data.
pub struct Pool {
    /// PDA bump.
    pub bump: u8,

    /// Unique Pool ID.
    pub pool_id: u64,

    /// Public Key part of Secp256k1 quote signature scheme.
    pub quote_signer_pub_key: [u8; 64],

    /// Market Maker key that owns the Pool.
    pub owner: Pubkey,
}

impl Pool {
    pub const LEN: usize = 8 +  // discriminator
        1 + // bump
        8 + // pool_id
        64 + // signer
        32 // owner
    ;

    pub const SEED_PREFIX: &'static [u8; 4] = b"pool";
}
```

In JavaScript / TypeScript, the `@hashflow/contracts-solana` package provides the full IDL, as well as program addresses.

```javascript
const {
  HashflowSolanaIDL,
  HASHFLOW_PROGRAM_ADDRESS
} = require('@hashflow/contracts-solana');
```

## 2. Connecting to the Maker API

Once a pool has been created, a WebSocket connection can be used to start market making. API v3 has two WebSocket endpoints for Makers:

* **Staging:** `wss://maker-ws-staging.hashflow.com/v3`
* **Production:** `wss://maker-ws.hashflow.com/v3`

The servers send `ping` requests to the clients **every 30 seconds**.

In order to authenticate, the following headers need to be present in the WebSocket request:

* **marketmaker:** the name of your Market Maker
* **authorization:** the authorization key used by the Market Maker
* **marketmakerindex (optional)**: used to run different logical Market Makers

## 3. Publishing Price Levels

In order to receive RFQs, the Market Maker needs to publish Price Levels (or indicative quotes) to the API. These should be published **every second for every supported pair**.

When publishing levels, both sides (**BUY** and **SELL**) are included in the message. All prices are specified relative to the same market (e.g. `ETH/USDC`) for both directions.

Message schema:

```typescript
{
  messageType: 'priceLevels',
  message: {
    source?: string;  // for all sources put 'null' as value or do not send "source" field
  
    baseToken: {
      chain: { chainType: 'evm' | 'solana', chainId: number };
      address: string
    };
    quoteToken: { 
      chain: { chainType: 'evm' | 'solana', chainId: number };
      address: string
    };
  
    // non-cumulative order book
    buyLevels: {
      q: string;  // quantity
      p: string;  // price
    }[]; // maker buys baseToken
    sellLevels: {
      q: string;
      p: string;
    }[]; // maker buys quoteToken
  }
}
```

A **BUY** level means that the market maker is buying the `baseToken` (and the trader is selling it).

A **SELL** level means that the market maker is selling the `baseToken` (and the trader is buying it).

Levels are an ordered list of how much (`q`) is available at what price (`p`), incrementally. The first level also serves as the **smallest quantity that the Market Maker is willing to offer a trade for**. If the Market Maker can take arbitrarily small orders, the first level should have quantity `0` and the price of the following level.

If you want to send pricelevle for all sources, put `null` as value for field `source` or do not send `source` field (this is an optional field)

Sending only one level will be rejected by the **API**.

Sending an empty list of levels (for either `BUY` or `SELL`) means that trades are not available in that direction. Sending empty levels is also **the recommended way to gracefully disconnect from the WebSocket**.

Let's look at the following example for a `ETH/USDC` pair on Ethereum:

```typescript
{
  baseToken: {
    chain: { chainType: 'evm', chainId: 1 },
    // We represent native ETH as 0x0.
    address: '0x0000000000000000000000000000000000000000', 
  },
  quoteToken: {
    chain: { chainType: 'evm', chainId: 1 },
    // USDC addrress on Ethereum
    address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
  },
  buyLevels: [
    { q: '0.1', p: '1600.00' },
    { q: '1', p: '1600.00' },
    { q: '0.5', p: '1599.00' }
  ],
  sellLevels: [
    { q: '0', p: '1601.00' },
    { q: '1', p: '1601.00' },
    { q: '1', p: '1602.00' }
  ]
}
```

Suppose the trader wanted to swap `1.2 ETH` for `USDC`. In this case, the maker would be selling `0.1 ETH` at `1600.00`, another `1 ETH` at `1600.00`, and up to another `0.5 ETH` at `1599.00`. If the trader were to make an RFQ, they would get `0.1 * 1600.00 + 1 * 1600.00 + 0.1 * 1599.00`, which is `1919.9 USDC`&#x20;

If the trader wanted to swap `0.05 ETH` instead, the maker would not be able to honor the quote, as `0.1` is the minimum amount (first level).

Suppose, on the other hand that the trader wanted to swap `2000 USDC for ETH`.We know the market maker is selling `1 ETH` for `1601.00`, and up to another `1 ETH` for `1602.00`. The trader would spend `1601 USDC` at the `1601.00` price point to get `1 ETH`, and then another `399 USDC` at the `1602.00` price to get `0.24906367041 ETH` . Therefore, the RFQ would yield `1.24906367041 ETH`&#x20;

In the case of swapping `USDC` for `ETH` , the trader could swap any small amount (e.g. `0.1 USDC`), because the first level has a quantity of `0`

## 4. Receiving an RFQ

Whenever a trader makes an RFQ, the Hashflow servers determine the best way to route that RFQ among the existing Market Makers. The winning Market Maker(s) receive messages of the following type:

<pre class="language-typescript"><code class="lang-typescript">{
  "messageType": "rfqT";
  "message": {
    rfqId: string;
    source: string;
    nonce: number;
    baseChain: { chainType: 'evm' | 'solana'; chainId: number; };
    quoteChain: { chainType: 'evm' | 'solana'; chainId: number; };
    baseToken: string;
    quoteToken: string;

    // The address of the account receiving quoteToken on quoteChain
    trader: string;
    effectiveTrader: string;
    // Exactly one of the following two fields will be present.
    baseTokenAmount?: string;
    quoteTokenAmount?: string;
<strong>    // Fees that will be charged, in basis points, up to 2 decimals.
</strong><strong>    feesBps: number;
</strong>    // The USD price of the baseToken at the time of request. (e.g. '1500.05')
    // This price will be used when computed the amount to be charged in fees.
    baseTokenPriceUsd: string;
  };
}
</code></pre>

Exactly one of `baseTokenAmount` / `quoteTokenAmount` will be present in the RFQ.

If `baseTokenAmount` is present, then the `rfqTQuote` will need to fill the `quoteTokenAmount`. This is the equivalent of a request asking "How much USDC can I get if I pay 1 ETH?".

If `quoteTokenAmount` is present, then the `rfqTQuote` will have to fill the `baseTokenAmount`. This is the equivalent of a request asking "How much ETH do I have to pay in order to get 100 USDC?".

The generated quote should have `baseTokenAmount` / `quoteTokenAmount` fields that respect the price level values sent. The price levels are used in deciding which Market Makers to route the RFQs to. Therefore, the Hashflow servers will check the quote values for correctness against Price Levels and penalize Market Makers that do not respect the prices sent in advance.

## 5. Adjusting the RFQ for fees

The Price Levels do not account for fees, which are computed at the time of the RFQ by each of Hashflow's taker sources (e.g. aggregators). The fees are sent in basis points as part of the `feesBps` field. Since the Price Levels do not include fees, the quotes have to be adjusted for fees before being sent out. The adjustments should be as follows:

* if the `rfqT` message contains `baseTokenAmount`, then the `quoteTokenAmount` should be **multiplied** by `(1 - (feesBps * 0.0001))` - this means that the trader receives less than they normally would
* if the `rfqT` message contains `quoteTokenAmount`, then the `baseTokenAmount` should be **divided** by `(1 - (feesBps * 0.0001))` - this means that the trader pays more than they normally would

Note that if accounting is done correctly, fees will have no effect on Market Maker price levels. The Market Maker worsens the rate by `feesBps`, and then remits that amount in fees monthly back to the various aggregators that compose their liquidity.

## 6. Sending the Quote

Quote messages should be sent on the same WebSocket connection that received the RFQ. The `rfqTQuote` message should be sent within **750ms** of receiving the `rfqT` message.

The quote messages are of the following type

```typescript
{
  "messageType": "rfqTQuote",
  "message": {
    rfqId: string;
    quoteExpiry: number;
    baseToken: string;
    quoteToken: string;
    baseTokenAmount: string;
    quoteTokenAmount: string;
    pool: string;
    // For cross-chain trades only.
    dstPool?: string;
    externalAccount?: string;
    // For cross-chain trades only.
    dstExternalAccount?: string;
    signature: string;
  }
}
```

In short, the Market Maker picks a liquidity source (`pool`), fills in the missing amount as described in the sections above, and signs the quote.

Every trade happens through a [HashflowPool](https://github.com/hashflownetwork/x-protocol/blob/main/evm/contracts/pools/HashflowPool.sol) contract (populated in the `pool` field).

The pool contract can store the funds used for market making. Alternatively, an external account (either an EOA or a Smart Contract) can be used to custody the funds. That account has to set allowance to the `HashflowPool` contract for every token that the Market Maker supports. This means that Market Makers can use their liquidity on multiple venues (including Hashflow) at the same time. This is only possible on EVM chains.

Whenever external accounts are used, they have to be passed in the `externalAccount` field.

The signature field proves to the HashflowPool smart contract that the information provided is correct. It should be provided using the Private Key of the signer used to deploy the pool. Details on how to generate this signature are presented in the next section.

## 7a. Signing the Quote (single-chain)

### EVM

Signing the quote can be split into two parts:

* generating the payload (hash)
* signing the payload

The Solidity code that generates the payload at the smart contract level can be found in [this file](https://github.com/hashflownetwork/x-protocol/blob/main/evm/contracts/pools/HashflowPool.sol) and looks as such:

```solidity
keccak256(
    abi.encodePacked(
        address(this),
        quote.trader,
        quote.effectiveTrader,
        quote.externalAccount,
        quote.baseToken,
        quote.quoteToken,
        quote.baseTokenAmount,
        quote.quoteTokenAmount,
        quote.nonce,
        quote.quoteExpiry,
        quote.txid,
        block.chainid
    )
)
```

Some clarifications:

* `address(this)` is the address of the pool contract itself (the `pool` field in the quote)
* `externalAccount` should be set to `0x00..0` if no external accounts are used
* `block.chainid` is the Chain ID of the EVM chain (e.g. `1` for Ethereum, `137` for Polygon)
* `txid` is the `rfqId` received in the `rfqT` message

The above code results in a 32-byte keccak hash. This is the hash that needs to be signed with the Private Key.

**IMPORTANT**: The contracts use the EIP-191 standard, which prepends the hash with the `\x19Ethereum Signed Message:\n32` string before verifying the signature. Most signing libraries **automatically do this**. For example the `signMessage` function in `ethers.js` does this. If the signing library that you are using does not provide support for this, please take note of the full form of the verified payload:

```solidity
keccak256(
    abi.encodePacked(
        '\x19Ethereum Signed Message:\n32',
        keccak256(
            abi.encodePacked(
                address(this),
                quote.trader,
                quote.effectiveTrader,
                quote.externalAccount,
                quote.baseToken,
                quote.quoteToken,
                quote.baseTokenAmount,
                quote.quoteTokenAmount,
                quote.nonce,
                quote.quoteExpiry,
                quote.txid,
                block.chainid
            )
        )
    )
)
```

Once the hash has been generated, it can be signed with the Private Key corresponding to the signer address that was used to create the pool.

Example code on how to generate the hash in TypeScript (using `ethers.js` v6):

```typescript
import { solidityPackedKeccak256 } from 'ethers';

static hashRFQTQuote(
  quoteData: UnsignedRFQTQuoteStruct,
  chainId: number
): string {
  return solidityPackedKeccak256(
    [
      'address',
      'address',
      'address',
      'address',
      'address',
      'address',
      'uint256',
      'uint256',
      'uint256',
      'uint256',
      'bytes32',
      'uint256',
    ],
    [
      quoteData.pool,
      quoteData.trader,
      quoteData.effectiveTrader ?? quoteData.trader,
      quoteData.externalAccount ?? ZERO_ADDRESS,
      quoteData.baseToken,
      quoteData.quoteToken,
      quoteData.baseTokenAmount,
      quoteData.quoteTokenAmount,
      quoteData.nonce,
      quoteData.quoteExpiry,
      quoteData.txid,
      chainId,
    ]
  );
}
```

### Solana

As with EVM signing the quote can be split into two parts:

* generating the payload (hash)
* signing the payload

Also as with EVM signing, Solana quotes are signed with the SECP256k1 curve, the same curve as EVM quotes. This is different from the curve used to sign Solana transactions (ed25519).&#x20;

The biggest difference between EVM & Solana hash that you sign, is that for EVM you first create the payload, hash it, prepend the hash with the EIP-191 prefix, and then hash it again. For Solana, you create the payload, hash it, and then sign that hash directly, with no EIP-191 prefix.

The second biggest difference is that for Solana quotes integers are encoded little-endian, while for EVM quotes integers are encoded-big endian.

The Solana quote payload is packed like this:

| Field            | Bytes |
| ---------------- | ----- |
| trader           | 32    |
| baseToken        | 32    |
| quoteToken       | 32    |
| pool             | 32    |
| baseTokenAmount  | 8     |
| quoteTokenAmount | 8     |
| floor (set to 0) | 8     |
| quoteExpiry      | 8     |
| rfqId            | 32    |

Hash the payload with KECCAK-256 and then sign it with your SECP256k1 key. While for EVM quote signatures the ‘v’ (final byte) should be 27 or 28, for Solana quote signatures the final ‘v’ byte should be 0 or 1.

## 7b. Signing the Quote (cross-chain)

Cross-chain quote signing works in similar fashion. However, the message hash is computed differently.

Before we describe the hash, it is working mentioning the concept of a **Hashflow Chain ID**. This a chain ID that is agnostic to whether the chain is an EVM chain, Solana, Sui, etc. When signing / submitting cross-chain quotes, we use the Hashflow Chain ID and not the EVM Chain ID.

Another important concept in cross-chain is that every cross-chain trade uses a **Cross-Chain Messenger**. Different cross-chain messengers are built on different protocols (e.g. Wormhole, LayerZero) and thus have different underlying security assumptions. That is why pools have to explicitly allow cross-chain messengers. The Hashflow Foundation recommends using the [Wormhole Messenger](https://github.com/hashflownetwork/x-protocol/blob/main/evm/contracts/xchain/HashflowWormholeMessenger.sol).

The Hashflow Chain ID and Wormhole messenger deployment address for each network can be found in the table below.

<table><thead><tr><th width="200">Network</th><th width="170.33333333333331">Hashflow Chain ID</th><th>Wormhole Messenger</th></tr></thead><tbody><tr><td>Ethereum</td><td>1</td><td>0x0a09b370950f69adc4c2fbf8677c7b0047599c9f</td></tr><tr><td>Arbitrum</td><td>2</td><td>0xab24a3306748e72520db800c3e93d6c861d1ba49</td></tr><tr><td>Optimism</td><td>3</td><td>0x7cdab80109d74372f1682ed0e4e65255f20ccbaa</td></tr><tr><td>Polygon</td><td>5</td><td>0xfafb0fc30140d1071606489ff36b9893f8db80bf</td></tr><tr><td>BSC</td><td>6</td><td>0x771cad61ec6dfde4a67891e982cf433aca1af7c8</td></tr><tr><td>Avalanche</td><td>4</td><td>0x771cad61ec6dfde4a67891e982cf433aca1af7c8</td></tr><tr><td>BSC Testnet</td><td>104</td><td>0x7CDAb80109D74372F1682ed0E4e65255f20ccbaA</td></tr><tr><td>Solana Devnet</td><td>100</td><td>N/A</td></tr><tr><td>Solana Mainnet</td><td>20</td><td>N/A</td></tr></tbody></table>

### EVM

With the information above, the hash for a cross-chain quote where the base-chain is EVM is defined as such:

```solidity
keccak256(
    abi.encodePacked(
        '\x19Ethereum Signed Message:\n32',
        keccak256(
            abi.encodePacked(
                keccak256(
                    abi.encodePacked(
                        quote.srcChainId,
                        quote.dstChainId,
                        quote.srcPool,
                        // Pre-pended with 00 up to 32 bytes
                        quote.dstPool,
                        quote.srcExternalAccount,
                        // Pre-pended with 00 up to 32 bytes
                        quote.dstExternalAccount 
                    )
                ),
                // Pre-pended with 00 up to 32 bytes
                quote.dstTrader,
                quote.baseToken,
                // Pre-pended with 00 up to 32 bytes
                quote.quoteToken,
                quote.baseTokenAmount,
                quote.quoteTokenAmount,
                quote.quoteExpiry,
                quote.nonce,
                quote.txid,
                quote.xChainMessenger
            )
        )
    )
)
```

Due to EVM stack limitations, we have to first compute an inner hash of 6 fields, before we compute the hash that needs to be EIP-191 signed.

The TypeScript equivalent is

```typescript
static hashXChainRFQTQuote(quoteData: UnsignedXChainRFQTQuoteStruct): string {
  const innerHash = solidityPackedKeccak256(
    ['uint16', 'uint16', 'address', 'bytes32', 'address', 'bytes32'],
    [
      quoteData.srcChainId,
      quoteData.dstChainId,
      quoteData.srcPool,
      quoteData.dstPool,
      quoteData.srcExternalAccount,
      quoteData.dstExternalAccount,
    ]
  );
  return solidityPackedKeccak256(
    [
      'bytes32',
      'bytes32',
      'address',
      'bytes32',
      'uint256',
      'uint256',
      'uint256',
      'uint256',
      'bytes32',
      'address',
    ],
    [
      innerHash,
      quoteData.dstTrader,
      quoteData.baseToken,
      quoteData.quoteToken,
      quoteData.baseTokenAmount,
      quoteData.quoteTokenAmount,
      quoteData.quoteExpiry,
      quoteData.nonce,
      quoteData.txid,
      quoteData.xChainMessenger,
    ]
  );
}
```

A few things to pay attention to:

* `srcChainId` and `dstChainId` are **Hashflow Chain IDs**
* All cross-chain addresses are 32 bytes long. EVM addresses however are 20 bytes long. In order to convert them to 32 bytes, we pre-pend them with 12 (twelve) 0-bytes. For example the `0xE8bc44AE4bA6EDDB88C8c087fD9b479Dff729850` address becomes `0x000000000000000000000000E8bc44AE4bA6EDDB88C8c087fD9b479Dff729850`
* The above 20-byte to 32-byte conversion only applies to fields that are sent to the destination chain: `dstTrader`, `quoteToken`, `dstPool`, `dstExternalAccount`

### Solana

The Solana cross-chain quote hash is not doubly-hashed like the EVM cross-chain quote hash. The same rules described above apply to cross-chain as well as single-chain. (i.e. Little-Endian, no EIP-191 prefix, SECP256k1 signing)

As with EVM cross-chain quotes, the chain ids are the Hashflow Chain Ids. If you are encoding an EVM address into a 32-byte field, it must be left-padded to 32-bytes. Note also that quoteTokenAmount is encoded to 32 bytes, while baseTokenAmount is encoded to 8 bytes.

Solana cross-chain quotes do not need a wormhole messenger address.

The payload for cross-chain:

<table><thead><tr><th width="219">Field</th><th>Bytes</th></tr></thead><tbody><tr><td>srcChainId</td><td>2</td></tr><tr><td>dstChainId</td><td>2</td></tr><tr><td>pool</td><td>32</td></tr><tr><td>dstPool</td><td>32</td></tr><tr><td>dstExternalAccount</td><td>32</td></tr><tr><td>dstTrader</td><td>32</td></tr><tr><td>baseToken</td><td>32</td></tr><tr><td>quoteToken</td><td>32</td></tr><tr><td>baseTokenAmount</td><td>8</td></tr><tr><td>quoteTokenAmount</td><td>32</td></tr><tr><td>floor (set to 0)</td><td>8</td></tr><tr><td>quoteExpiry</td><td>8</td></tr><tr><td>rfqId</td><td>32</td></tr></tbody></table>

## 8. Subscribe to Trades

Hashflow offers the option for Market Makers to subscribe to trade events on their pools. If you would like to do so, please ask the Hashflow team to set up a delivery pipeline for you. If you do not require this functionality, you can **skip this step**.

Once the pipeline is set up, you can subscribe to a pool's trades by sending a `subscribeToTrades` message over the WebSocket

```typescript
{
    "messageType": "subscribeToTrades",
    "message": {
      "chain": { chainType: 'evm' | 'solana'; chainId: number; },
      // Pool address on the chain, e.g. '0x...'
      // This must be a pool owned by Market Maker
      "pool": string  
    }
}
```

If you subscribe to trades on a pool, you will start getting `trade` messages whenever the pools that you have subscribed to receive a trade. These messages will have the following format:

```typescript
{
  "messageType": "trade",
  "message": {
    // Unique ID for the trade event.
    tradeEventId: string;
    
    baseChain: { chainType: 'evm' | 'solana'; chainId: number; };
    quoteChain: { chainType: 'evm' | 'solana'; chainId: number; };

    rfqId: string;

    blockNumber: number;
    transactionHash: string;
    blockTimestamp: number;

    baseToken: string;
    quoteToken: string;
    
    // Every quote an execute an amount that is <= the
    // baseTokenAmount provided by the Market Maker during RFQ.
    // These amounts are actual executed amounts on chain.
    baseTokenAmount: string;
    quoteTokenAmount: string;

    // e.g. '1500.3'
    baseTokenPriceUsd: string;
    // Fees to be charged for this trade.
    feesBps: number;

    pool: string;
    // Will be the same as `pool` if the trade is not cross-chain.
    dstPool: string;

    effectiveTrader?: string;
    
    // Re-orged trades will appear as `canceled`.
    tradeStatus: 'confirmed' | 'canceled';
  }
}
```

The Hashflow systems will re-try messages for a period of **20 minutes** until an acknowledgment is received.

The system guarantees **at least once** delivery. This means that in some rare cases messages could be delivered twice.

In order to let the Hashflow delivery pipeline know that the message has been processed, a matching `tradeAck` message has to be sent back following each `trade` message received. The pipeline will retry so long as these acknowledgement messages have not been received.

**IMPORTANT**: In the case of a chain re-org, a `canceled` message will be sent. This message also has to be acknowledged.

The shape of acknowledgement messages is as follows:

```typescript
{
  "messageType": "tradeAck",
  "message": {
    // The same as in the `trade` message.
    "tradeEventId": string
  }
}
```

## 9. (If using External Accounts) Set allowance for Private Pool (EVM Only)

If using an External Account, set an allowance from the External Account to the Private Pool so that it can move funds on behalf of the external account. Allowances need to be sent for:

* the ERC-20 tokens you plan on supporting
* the wrapped native token (e.g. WETH) if you plan on supporting native token trades (e.g. ETH)

In the case of an ETH trade, the Hashflow Smart Contracts will automatically wrap / unwrap as necessary, so that your External Account only gets debited / credited WETH instead.

**NOTE**: You have to send both ETH/x and WETH/x Price Levels in order to support both types of trades

**If you don't set an allowance,** **your quotes will fail on-chain** since the pool won't be able to access the funds in the External Account.&#x20;

## 10. (For Cross-Chain, EVM Only) Authorize the Cross-Chain Messenger

Because different cross-chain messengers come with different security considerations (e.g. Wormhole has different security parameters than LayerZero), the pools have to opt into the cross-chain messenger. The Hashflow Foundation provides deployments for Wormhole messengers.

In order to authorize a cross-chain messenger, the following call has to be made on a `HashflowPool` contract:

```solidity

function updateXChainMessengerAuthorization(
    address xChainMessenger,
    bool authorized
) external;
```

## 11. (For Cross-Chain, EVM Only) Authorize peer cross-chain pools

Each cross-chain pool needs to authorize the pools that it will executes swaps against on the peer chains. For example, if we want to set up cross-chain trades between Ethereum and BSC, the Ethereum pool has to authorize the BSC pool, and vice versa.

To authorize cross-chain peer pools, the following call has to be made on the `HashflowPool` contract.

```solidity
struct AuthorizedXChainPool {
    uint16 hashflowChainId;
    bytes32 pool;
}

function updateXChainPoolAuthorization(
    AuthorizedXChainPool[] calldata pools,
    bool authorized
) external;
```

Note that the chain IDs that are being used are **Hashflow Chain IDs**, as documented in section 7b.

## 12. Test the RFQ flow end-to-end

Once you have completed the above steps, you can test your connection in the Hashflow UI. First off, you will need to ask the team for access to an UI that connects to the Staging API.

Next up, if your indicative Price Levels are propagating properly, you should be able to see your liquidity source, as well as supported pairs in the UI.

To select the liquidity source, click on the "Gear" icon at the top of the trading terminal. You should see your obscured Market Maker name (e.g. *mmX*) in that list.

Next, you should unselect all liquidity sources aside from your own.

Next, select a pair and write a number in the top box. If things are working well, you should see the **rfq** and **signQuote** messages in succession, then see a quote in the UI. This means that both the Quote and the Signature have been generated.

Next, click on Trade. If things worked well, you should see your wallet successfully estimate gas, and pop up a transaction confirmation. Confirm the transaction, run the trade, and checked that everything worked out well.

## Success!!

Congrats! You've successfully set up a Market Maker 🥳

## How to send errors

The 10 steps above covered the "happy path" – what happens when everything goes right. But the real world is messy. So, invariably, we'll encounter some error cases. The Hashflow WS API is designed in a way to easily support errors, as long as they are sent in a specific format.

**Every message** that is in response to a different message **has the option of returning an error** instead of the desired payload. To do so, you send a message with the following format:

```json
{
  "messageType": "<message>",  // Same types as otherwise ("rfqTQuote", etc)
  "message": {
    "error": "<failure>",  // Only specific failures are recognized. See below.
    "originalMessage": { 
      ...  // Original inbound message
    }
  }
}
```

Let's explain these some more:

* **messageType**: The type of message you're sending. You treat this field is the exact same as you would for a successful request.&#x20;
* **message.error**: The error you want to return. We currently support the following error cases based on message type.
  * ***For all messages***: `'invalid_input'`, `'internal_error'`, `'compliance'`, `'rate_limit'`
    * When responds with `'rate_limit'` in your error message, you can specify an `"expiryTimestampMs" (UTC millisecond timestamp)` that indicates until when this rate\_limit would expire. We will then block any requests fall under given restrictions and not send messages to you until the timestamp has expired.&#x20;
  * ***For quotes only***: `insufficient_liquidity'`, `'pair_not_supported'`, `'market_conditions'`
  * ***For signatures only***: `'incorrect_payload'`, `'payload_expired'`, `'market_conditions'`, `'signing_not_supported'`, `'invalid_signature'`
* **message.originalMessage**: The body of the original inbound message you received. We need this to be able to map the failure to a request. You should only send the body here (we know which messageType it was based on the type of your response).

To give an example, if you received an `rfq` message but you didn't want to give a quote because the trader had been blacklisted, you'd respond with&#x20;

```json
{
  "messageType": "rfqTQuote",
  "message": {
    "error": "compliance",
    "expiryTimestampMs" : 1681590420000, // set this field when your error is rate_limit
    "originalMessage": {
      "rfqId": "0x67..",
      "rfqType": 1,
      "source": "hashflow",
      ...      
    }
  }
}
```

as long as you respond in this format, we'll be able to parse these messages correctly.


# Getting Started - API v3

Taker API V3 is a REST API, similar to Taker API V2.

This section will walk you through the required steps to add Hashflow as a liquidity source for your platform. This could be an aggregator, an algorithmic trading bot, or any software intended to run trades against Hashflow liquidity.

## 1. Set up authentication

Hashflow authenticates all incoming requests based on the `source` field (passed in the requests below). This helps us track usage, as well as prevent DDoS attacks.

The first step in setting up your taker is [reaching out to the Hashflow team](https://forms.gle/EEzfL59vQaTebAXN9), in order to have credentials generated. Depending on the type of taker, the team will provide you with different types of credentials.

#### A. Aggregators / API Multi-Wallet Traders

This type of API integration is viable for takers such as aggregators (e.g. `1inch`, `paraswap`). The team will provide you with two important pieces of information:

* your `source` name
* the authentication key for your `source`

#### B. API Wallet Traders

This type of API integration is viable for individual takers that generally rely on one or very few wallets (e.g. retail traders, funds).

The team will provide you with an authentication key that is bound to the wallet you will be using to access the API.

### Authenticating requests

Regardless of the integration type, you have to submit a header with each request:&#x20;

`Authorization: <generated credential key>`

This, in conjunction with your identity parameters, will authenticate your request. For identity, parameters, the type of integration matters.

#### A. Aggregators / API Multi-Wallet Traders

&#x20;You will have to provide the `source` field to every request (`GET` or `POST`).

#### B. API Wallet Traders

You will have to set `source: 'api'` to every request, and also send a field named `wallet` which is populated with your wallet address (e.g. `0x01ae...b3`).

## 2. Query `/market-makers`

Next, you will need to query which market makers (liquidity sources) are currently available on Hashflow for a given network. You can do this by sending the following HTTP REST request:

```
GET https://api.hashflow.com/taker/v3/market-makers
  ?source=<source>
  &baseChainType=<string> # use 'evm' for EVM chains 
  &baseChainId=<string>   # Chain ID
  &marketMaker=<string>   # Optional
```

OR, for single wallet traders

```
GET https://api.hashflow.com/taker/v3/marketMakers
  ?source=api
  &baseChainType=<string>    # use 'evm' for EVM chains
  &baseChainId=<string>      # Chain ID
  &wallet=<wallet-address>
```

* For `<source>` use your source identifier (e.g. `my_aggregator`) or `api`
* For `<baseChainType>` use either `evm | solana`
* For `<baseChainId>` use your network ID (e.g. `1` for Ethereum, `137` for Polygon, `1000001` for Solana).
* For `<wallet>` use the `0x` -prefixed wallet address (only populate when you are single wallet traders)
* Make sure you also use the header that authenticates your source

The response to this request includes all available market makers on that chain and has format

```javascript
{
  marketMakers: string[]
}
```

For example: `{marketMakers: ['mm1', 'mm2']}`.

You'll want to re-run this request periodically for each chain so that you can tell which market makers are available.

## 3. Query Price Levels (for price discovery)

In order to understand indicative order flow, we expose price levels for the different market makers. These levels tell you, at any given time:

* what pairs are available for a given network (chain)
* how much liquidity is available for each particular pair
* what the rough prices will be once you query signed quotes for those pairs

In general, this step will allow you to do price discovery (which is inexpensive), before requesting signed quotes (which is more expensive).

The price levels APIs benefit from caching and can be queried frequently (e.g. every second).

You can get those by querying:

<pre><code><strong>GET https://api.hashflow.com/taker/v3/price-levels
</strong>  ?source=&#x3C;source>
  &#x26;baseChainType=&#x3C;string>
  &#x26;baseChainId=&#x3C;string>
  &#x26;marketMakers[]=&#x3C;mm1>
  &#x26;marketMakers[]=&#x3C;mm2>
  &#x26;baseToken=&#x3C;token address> //optional
  &#x26;quotToken=&#x3C;token address> //optional
  
</code></pre>

OR, for single wallet traders

<pre><code><strong>GET https://api.hashflow.com/taker/v3/price-levels
</strong>  ?source=api
  &#x26;wallet=&#x3C;string>
  &#x26;baseChainType=&#x3C;string>
  &#x26;baseChainId=&#x3C;string>
  &#x26;marketMakers[]=&#x3C;mm1>
  &#x26;marketMakers[]=&#x3C;mm2>
  &#x26;baseToken=&#x3C;token address> //optional
  &#x26;quotToken=&#x3C;token address> //optional
</code></pre>

This endpoint allows you query levels for an arbitrary number of market makers.

You will then get a response of the following format:

```javascript
{ 
  status: "success" | "fail",
  baseChain: {
    chainType: "evm" | "solona",
    chainId: number,
  }
  levels: Record<
    string, // They key is the market maker name
    Array<{
      pair: {
        baseToken: string,  // The address of the base token
        quoteToken: string,  // The address of the quote token
        baseTokenName: string,  // The name of the base token (e.g. ETH)
        quoteTokenName: string,  // The name of the quote token (e.g. USDC)
      },
      // string representation of the level e.g. (2.5 for 2.5 ETH)
      levels: {
        // string representation of the level (e.g. for 2.5 ETH, this will be "2.5")
        q: string,
        
        // string representation of the price per unit at that level 
        // (e.g. 3500 for "up to 2.5 ETH at 3500 USDT per ETH")
        // this price is not in decimals -- it's the actual exchange rate, 
        // in floating point notation
        p: string
      }[]
    }>
  >
}
```

Things to note:

* for each market maker, there will be one entry in the top level array for each supported pair
* levels and prices are not in decimals (e.g. 1 means 1 ETH and not 1 WEI)
* for native tokens (e.g. AVAX on avalanche, ETH on ethereum) Hashflow uses the 0 address (`0x00..00`)

Each level represents up to how much liquidity can be accessed at a given price. Also, the first level represents the minimum amount that the market maker is willing to take a quote for.

For example, suppose our levels for `ETH-USDC` are

* `{ level: "0.5", "price": "3000" }`
* `{ level: "1.5", price: "3000"}`
* `{ level: "5", price: "2999"}`

This tells us the following:

* the trader needs to sell at least `0.5 ETH`
* the trader can sell up to `7 ETH`
* the first `2 ETH` will be sold at a price of `3000 USDC`
* the next `5 ETH` will be sold at a price `2999 USDC`

For example, if the trader wants to sell `3 ETH` they will get `2 * 3000 + 2999 = 8999 USDC`

Note that, in general, as liquidity goes up, rates go down. This is expected, as market maker prices generally mirror Centralized Exchange order books.

### Cross-Chain price levels

In order to get cross-chain price levels, simply add `quoteChainType, quoteChainId` as a parameter, indicating the destination Chain ID and type for the cross-chain trade.

For example:

<pre><code><strong>GET https://api.hashflow.com/taker/v3/price-levels
</strong><strong>  ?source=&#x3C;source>
</strong>  &#x26;baseChainType=&#x3C;evm or solana>
  &#x26;baseChainId=&#x3C;chain-id>
  &#x26;quoteChainType=&#x3C;evm or solana> //optional
  &#x26;quoteChainId=&#x3C;chain-id> //optional
  &#x26;marketMakers[]=&#x3C;mm1>
  &#x26;marketMakers[]=&#x3C;mm2>
</code></pre>

## 4. Query `/rfq`

By this point, you should have an index of what market makers are available on each chain and which trading pairs they offer, as well as prices they are offering. The next step is to request a signed quote that is ready for execution.

This can target specific market makers, or be sent to all available market makers.

This request will look like:

<pre class="language-javascript"><code class="lang-javascript">POST https://api.hashflow.com/taker/v3/rfq

// JSON body
{
  source: string, // Your identifier (e.g. "1inch", "zerion")
  baseChain: {
    chainType: string, // evm | solana
    chainId: number
  }
  quoteChain: {
    chainType: string, // evm | solana
    chainId: number
  }
  rfqs: {
    // Contract address (e.g. "0x123a...789")
    baseToken: string,
    // Contract address (e.g. "0x123a...789")
    quoteToken: string,
    // Decimal amount (e.g. "1000000" for 1 USDT)
    baseTokenAmount: ?string 
    // Decimal amount (e.g. "1000000" for 1 USDT)
    quoteTokenAmount: ?string,
    // The address that will receive quoteToken on-chain.
    trader: string,
    // The wallet address of the actual trader (e.g. end user wallet).
    // If effectiveTrader is not present, we assume trader == effectiveTrader.
    effectiveTrader: ?string,
    // The wallet address to claim trading rewards for api user.
    // Cannot be set unless source == 'api'
    // This is useful when api users needs a separate wallet to claim rewards
    // If left empty, rewards will be sent to trader address
    rewardTrader: ?string,
    
    marketMakers: ?string[], // e.g. ["mm1"]    
    excludeMarketMakers: ?string[],
<strong>    options:{
</strong>      doNotRetryWithOtherMakers: ?boolean, //Default to false
    }
    
    // The amount to be charged in fees, in basis points.
    feesBps: ?number
  }[],
  calldata: ?boolean, // If this is true, contract calldata will be provided.
}
</code></pre>

Sometimes, the received quote may be coming from a market maker that does not follow the `marketMakers` field requirements. This is because the initial market maker failed to provide a request and the API fallback picked the next best market maker. In order to avoid this behavior and skip retries, you can set the `doNotRetryWithOtherMakers` flag within the `options`field for each RFQ.

If you're a Wallet API trader, the `trader` field will be used in lieu of the `wallet` field, which does not need to be passed. However, you still need to pass `source:api` in order to avoid rate limits.

You will then get a response of the following format:

```javascript
{
  status: 'success' | 'fail',
  error?: string,
  rfqId: string,  // Unique RFQ identifier
  internalRfqIds: ?string[] 
  
  quotes?: {
    quoteData: {
      baseChain: {
        chainType: string, // evm | solana
        chainId: number
      }, 
      quoteChain: {
        chainType: string, // evm | solana
        chainId: number
      },
      baseToken: string,
      baseTokenAmount: string,
      quoteToken: string,
      quoteTokenAmount: string,
      trader: string,
      effectiveTrader: ?string,
      txid: string,  // Unique quote identifier. Different from RFQ ID.
      pool: string,
      dstPool: ?string,  // For cross-chain quotes, the pool on the destination chain ID
      quoteExpiry: number,
      nonce: number,
      externalAccount: ?string,
      dstExternalAccount: ?string
    },
    signature: string,
    xChainFeeEstimate: ?string,
    targetContract: ?string,
    calldata: ?string
    value: ?string
    hftTradingRewards: ?string
  }[],
}
```

## 5a. Execute quote on-chain (EVM)

Once you have obtained a signed quote and decided to execute it, you can submit it on-chain to the [`HashflowRouter`](https://github.com/hashflownetwork/x-protocol/blob/main/evm/deployed-contracts/IHashflowRouter.json) contract via the `tradeRFQT` call.

The call is meant to be composable. However, since it is most often composed with AMMs that have slippage, the Hashflow contracts allow you to tune the token amounts in order to account for slippage (see the description of `maxBaseTokenAmount` below).

`HashflowRouter` Contract: <https://github.com/hashflownetwork/x-protocol/blob/main/evm/deployed-contracts/IHashflowRouter.json>

ABIs: <https://github.com/hashflownetwork/x-protocol/blob/main/evm/abi/IHashflowRouter.json>

Some clarification for the ABI fields:

* **`externalAccount`**. External account address. Set to `eoa`, if set in your signed quote. Otherwise, use `0x0000000000000000000000000000000000000000` address.
* **`maxBaseTokenAmount`** **/** **`maxQuoteTokenAmount`** : These are what you receive in the API as `baseTokenAmount` / `quoteTokenAmount`. Sometimes you can receive a quote for higher than what you requested. It is essential that you use the requested amount in the effectiveBaseTokenAmount field.
* **`effectiveBaseTokenAmount`** : The actual swapped amount. This has to be less than or equal to `maxBaseTokenAmount`. We suggest to keep them equal unless there's a discrepancy with the requested amount. If the `effectiveBaseTokenAmount` is less than `maxBaseTokenAmount`, the exchange rate `maxQuoteTokenAmount / maxBaseTokenAmount` will be preserved and applied to `effectiveBaseTokenAmount`
* **`value`**: If the baseToken is the native token (e.g. ETH on Ethereum), the `effectiveBaseTokenAmount` needs to be passed as `value` to the contract call

You can use *Etherscan* (or similar tools for non-Ethereum chains) to confirm the trade went through.

### Executing cross-chain quotes

Cross-chain quotes are executed via our interoperability partner, Wormhole. Wormhole operates with 2 parties:

* a set of Guardians to attest the transaction
* a Relayer on the destination chain

Both of these entities could charge a small fee. However, once the transaction is submitted on the source chain, they will take care of execution on the destination chain.

Therefore, a fee has to be paid by the trader on the source chain, in the source chain's native token (e.g. ETH for Ethereum). This fee will pay for:

* Guardian fees
* Relayer fees
* Gas fees on the destination chain

The fee that needs to be paid for each quote is returned in the `rfqs` response's `xChainFeeEstimate` field.

The amount provided is in WEI (decimals -- usually `10^-18`).

Once we have a quote, as well as a fee estimate, we can go ahead and submit the quote for execution via the `tradeXChainRFQT` contract call.

## 5b. Execute quote on-chain (Solana)

The Hashflow program address is `CRhtqXk98ATqo1R8gLg7qcpEMuvoPzqD5GNicPPqLMD`.

This is an Anchor program with a publicly available IDL. The method that should be called for trading is `trade` .

Parameters:

* `txid` - unique identifier of the quote received from the RFQ endpoint
* `tokenFromAmount`- the `baseTokenAmount` received from the API
* `tokenToAmount` - the `quoteTokenAmount`received from the API
* `quoteExpiry`- as received from the API; the unix timestamp (in seconds) when the quote will expire and be rejected on-chain
* `signature` - the first 64 bytes of the `signature`field received from the API
* `recoveryId` - the last byte of the `signature`field received from the API
* `minTokenFromAmount` - always set to `0`
* `effectiveTokenFromAmount` - can be anything between `0` and `tokenFromAmount` ; used for cases where the actual swapped amount is less than `tokenFromAmount` (useful if the exact amount is not known a priori, due to slippage); the exchange rate of `tokenToAmount` `tokenFromAmount` is preserved when pro-rating the `tokenToAmount`&#x20;

Accounts:

* `payer`- transaction payer
* `trader` - the authority of the account that is debited the `tokenFrom` ; this can be different from the authority of the account that gets credited the `tokenTo`; that authority is specified as the `trader`field in the API request, which can be unrelated to this `trader`account; for trivial cases, they will be equal
* `tokenFromMint` - `baseToken`from the API
* `tokenToMint`  -`quoteToken` from the API
* `pool` - from the API
* `tokenFromTraderAccount` - the trader token account that is debited; the authority must be the `trader`account above
* `tokenFromPoolAccount` - ATA of the `pool`for `tokenFrom`
* `tokenToTraderAccount` - the token account that is credited; the authority has to match the `trader`field in the RFQ API request (does not need to match `trader`account above)
* `tokenToPoolAccount` - ATA of the `pool`for `tokenTo`&#x20;
* `systemProgram`
* `tokenProgram`
* `associatedTokenProgram` &#x20;

It is possible to request the calldata directly by specifying the `calldata: true` field in the RFQ endpoint, however it comes with some assumptions which may not be ideal:

* `payer` = `trader`&#x20;
* the authority of the `tokenFromTraderAccount`matches the authority of `tokenToTraderAccount`

## 6. Query `/restrictions`

Market makers can set `rate_limit` on given a trader and a network. All `rate_limit` restrictions will have an expiry window, which means traders can re-gain access to the market maker after the specified expiry time. To understand the restriction status, takers can query `/restrictions` endpoint to better understand error messages from market maker and adjust routing accordingly. When a trader has been restricted, we will automatically route their RFQs to other makers (if present) until restriction expires.&#x20;

We suggest you use the response you get from this endpoint to display proper error message as well as route your RFQs requests to other available makers accordingly.&#x20;

For example:&#x20;

```
GET https://api.hashflow.com/taker/v3/restrictions?source=<your-source>&trader=<0x...>&chainId=<chainId>&chainType=<chainType>
```

&#x20;The response will be in the following shape &#x20;

```
{ 
  isTraderRestricted: boolean; 
  restrictions?: Array<{ 
    reason: 'rate_limit'; 
    expiryTimestampMs?: number; //UTC milliseconds timestamps
    marketMaker?: string; 
    chainId?: string
    chainType: string
  }> 
}
```


# Background

HFT is the governance token for the Hashflow protocol as well as the Hashverse, Hashflow’s gamified DAO and governance platform. It will be an ERC-20 token deployed on Ethereum mainnet.&#x20;

At genesis, the total HFT supply will be `1,000,000,000` (one billion tokens).

### **What is the utility of HFT?**

**Governance**: Hashflow governance will follow a vote-escrow (ve) token model where voting rights are determined based on the amount of HFT staked as well as the duration for which HFT is locked. Staking tokens will grant users the right to vote and manage the future of the protocol. This includes decisions relating to protocol fees, marketing, and code development – Hashflow will be run by its community.


# Allocation and Distribution

### Overview

HFT will be distributed as follows:

* `19.32%` (`193,200,000 HFT`) to the **Core Team**
* `25%` (`250,000,000 HFT`) to **Early Investors**
* `2.5%` (`25,000,000 HFT`) for **Future Hires**
* `53.18%` (`531,800,000 HFT`) for **Ecosystem Development** as follows:
  * `18.54%` to Ecosystem Partners&#x20;
  * `13.08%` to Community Rewards (NFTs + Rake the Rewards + Exchange Distribution)&#x20;
  * `7.50%` to Designated Market Maker Loans&#x20;
  * `6.20%` to Early Integration Partners
  * `3.34%` for Future Community Rewards
  * `2.52%` to Vendors and Early Service Providers&#x20;
  * `1.00%` to the Community Treasury&#x20;
  * `1.00%` for Hashverse Rewards

### Detailed Breakdown

To decentralize ownership of HFT, the community and ecosystem partners will own the majority of the protocol. As such, they will receive `53%` of the HFT genesis supply, and the core team and investors will receive a total of `44%`:

<figure><img src="https://1378959595-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-ML-MjGdn5-U1Ma0ab_Y%2Fuploads%2FBsUcMWtr27XHmNC1gAZy%2FPie%20chart%20ecosystem.jpg?alt=media&amp;token=70dbe6ff-9c5c-437c-b136-5ae7a7cd7810" alt=""><figcaption></figcaption></figure>

At genesis, HFT will be distributed as following:

* **Core Team (`19.32%`):** Founding team and employees who designed, developed and deployed the Hashflow protocol&#x20;
* **Investors (`25%`):** Early investors that provided the initial runway to help launch the protocol&#x20;
* **Ecosystem Development (`53.18%`):** This is a catch-all bucket that includes the community treasury, rewards for early community members and users, and an allocation for market makers that helped provide the initial liquidity in Hashflow

### Ecosystem Development

Within Ecosystem Development, HFT will be distributed to the following sub-categories:

<figure><img src="https://1378959595-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-ML-MjGdn5-U1Ma0ab_Y%2Fuploads%2Fn43R0E2oK5LMCty6AG2Q%2Fimage.png?alt=media&amp;token=03327577-99fa-41ec-b0ee-88ecfb5fcc17" alt=""><figcaption></figcaption></figure>

* `18.54%` to Ecosystem Partners
* `13.08%` to Community Rewards (NFTs + Rake the Rewards + Exchange Distribution)
* `7.50%` to Designated Market Maker Loans
* `6.20%` to Early Integration Partners
* `3.34%` for Future Community Rewards
* `2.52%` to Vendors and Early Service Providers
* `1.00%` to the Community Treasury&#x20;
* `1.00%` for Hashverse Rewards


# Release Schedule

Tokens issued to the team, investors, and ecosystem will be subject to the following vesting schedules:

### Team

* `25%` vested at a one-year cliff following TGE&#x20;
* `75%` linear daily vesting over the subsequent 3-5 years

### Investors

* `25%` vested at a one-year cliff following TGE&#x20;
* `75%` linear daily vesting over the subsequent 3 years

### Community Rewards (NFTs + Rake the Rewards + Exchange Distribution)

NFT holders will be able to claim up to `30,000 HFT` upon TGE for each wallet holding NFTs as of their respective snapshot dates. [See the breakdown here](#community-rewards-nfts-+-rake-the-rewards-+-exchange-distribution)[.](/hashflow/hft-and-governance/community-incentives/nft-holders-rewards)&#x20;

Thereafter, all wallets holding NFTs with remaining aggregate value in excess of `30,000 HFT` will be able to claim the balance according to the following schedule:&#x20;

1. **If the total unvested amount is <25K HFT**: 100% vested and unlocked at one-year cliff (linearly over a 60-day period beginning on Nov 7, 2023).
2. **Otherwise, if the total unvested amount is <50K HFT**: 50% vested and unlocked at one-year cliff (linearly over a 60-day period beginning on Nov 7, 2023). 50% vested and unlocked daily over the 12 months thereafter.
3. **Otherwise, if the total unvested amount is <75K HFT**: 33.33% vested and unlocked at one-year cliff (linearly over a 60-day period beginning on Nov 7, 2023). 66.66% vested and unlocked daily over the 24 months thereafter.
4. **For all other users**: 25% vested and unlocked at one-year cliff (linearly over a 60-day period beginning on Nov 7, 2023). 75% vested and unlocked daily over the 36 months thereafter.

**For Rake the Rewards rewards**: HFT that were earned before July 2022 will be fully distributed and claimable by eligible wallets upon TGE. HFT that were earned on or after July 2022 will be subject to linear, daily vesting for a period of 30 days after TGE.&#x20;

### Ecosystem Development

**Ecosystem Partners:**

* `25%` vested at a one-year cliff following TGE
* `75%` linear daily vesting over the subsequent 3 years&#x20;

**Designated Market Makers Loans:**

* Fully unlocked at TGE

**Vendors & Early Service Providers:**

* `48%` unlocked at TGE
* `52%` linear daily vesting over the subsequent 1 year&#x20;

**Hashverse Rewards:**

* Full allocation will be distributed linearly over 4 years

**Future Community Rewards:**

* See the [breakdown of rewards and timeline here](/hashflow/hft-and-governance/community-incentives/rewards-timeline)

### Liquidity at TGE

The initial circulating supply will be `175,229,156 HFT` (`17.52%` of the total supply).

### Additional Issuance of HFT

After 4 years, HFT will have an annual issuance of `4%` at steady-state.&#x20;

<figure><img src="https://1378959595-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-ML-MjGdn5-U1Ma0ab_Y%2Fuploads%2FZxTDPsW9c8vqyxrMX2Uo%2FHFT%20Release%20Schedule%20(%23%20of%20HFT)%20(1).jpg?alt=media&amp;token=120b79b8-9f35-4f64-be26-a5f22c21e9dc" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1378959595-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-ML-MjGdn5-U1Ma0ab_Y%2Fuploads%2FT5MTMRIltQXYYWIBhsPE%2FHFT%20Release%20Schedule%20(%25%20of%20Total%20Supply)%20(1).jpg?alt=media&amp;token=ab7daaf1-399b-4d29-8709-880be1e00a86" alt=""><figcaption></figcaption></figure>


# Community Incentives

The initial community incentives will be distributed as follows:

**Retroactive NFT Rewards**

* `6.75%` of the HFT supply will be distributed to early users that received Hashflow NFTs
* These NFTs were distributed as rewards for early adoption, frequent usage, and exceptional contributions to the ecosystem
* Each NFT will have an [HFT value based on its relative scarcity](/hashflow/hft-and-governance/community-incentives/nft-holders-rewards), and each NFT holder will be eligible to receive HFT commensurate to the specific NFT(s) that they hold
* NFT holders will be able to claim up to `30,000 HFT` upon TGE for each wallet holding NFTs as of the snapshot taken on 2022-05-10
* Thereafter, all wallets holding NFTs with remaining aggregate value in excess of `30,000 HFT` will be able to claim the balance according to the following schedule:&#x20;
  1. **If the total unvested amount is <25K HFT**: 100% vested and unlocked at one-year cliff (linearly over a 60-day period beginning on Nov 7, 2023).
  2. **Otherwise, if the total unvested amount is <50K HFT**: 50% vested and unlocked at one-year cliff (linearly over a 60-day period beginning on Nov 7, 2023). 50% vested and unlocked daily over the 12 months thereafter.
  3. **Otherwise, if the total unvested amount is <75K HFT**: 33.33% vested and unlocked at one-year cliff (linearly over a 60-day period beginning on Nov 7, 2023). 66.66% vested and unlocked daily over the 24 months thereafter.
  4. **For all other users**: 25% vested and unlocked at one-year cliff (linearly over a 60-day period beginning on Nov 7, 2023). 75% vested and unlocked daily over the 36 months thereafter.

**On-going Community Incentive Programs**

* `8.17%` of the HFT supply has been allocated for the following incentive programs:&#x20;
  * [Trading Rewards](/hashflow/hft-and-governance/community-incentives/trading-rewards)
  * [Market Making Rewards](/hashflow/hft-and-governance/community-incentives/market-making-rewards)
  * LP Rewards

Note that while the core team has initially seeded the mechanics to distribute HFT to traders, LPs, and market makers, these programs will ultimately be subject to DAO approval once in place.


# Rewards Timeline

Starting December 20, 2021, traders, market makers, and LPs have been eligible to receive rewards as part of the community treasury distribution programs. These rewards will be distributed retroactively once the HFT token is live.

* **Trading Rewards:** `0.1%` of the total HFT supply, distributed monthly with a `350,000 HFT` per month ceiling
* **LP Rewards:** `0.1%` of the total HFT supply, distributed monthly with a `300,000 HFT` per month ceiling
* **Market Making Rewards:** `1.0%` of the total HFT supply, distributed monthly in equal installments of `416,667 HFT`


# NFT Holders Rewards

Early Hashflow community members that received select NFTs will be eligible to receive HFT. The NFTs that are eligible for HFT allocation will have an HFT value based on their relative scarcity, and each NFT holder will be eligible to receive HFT commensurate to the specific NFT(s) that they hold. The various NFTs distributed over the Hashflow Alpha and Beta phases will be redeemable for HFT as per the following:

### **Private Alpha Users**

<table><thead><tr><th>NFT</th><th>Eligibility Criteria</th><th width="150">Aggregate HFT Value</th><th width="150"> Minted</th><th width="150">HFT Value per NFT</th><th>Ownership Snapshot</th></tr></thead><tbody><tr><td>Hashbot: Genesis</td><td>Traded at least $3K in volume or 10 times</td><td>5,000,000</td><td>78</td><td>64,103</td><td>2022-05-10</td></tr><tr><td>The Hashbot #1 Cover</td><td>Traded any amount</td><td>2,500,000</td><td>968</td><td>2,583</td><td>2022-05-10</td></tr></tbody></table>

### **Open Alpha Users**

<table><thead><tr><th>NFT</th><th>Eligibility Criteria</th><th width="150">Aggregate HFT Value</th><th width="150">Minted</th><th width="150">HFT Value per NFT</th><th>Ownership Snapshot</th></tr></thead><tbody><tr><td>Hashbot Poster #1</td><td>Traded any amount</td><td>10,000,000</td><td>17,124</td><td>584</td><td>2022-05-10</td></tr><tr><td>Hashbot Poster #2</td><td>Traded $10K - $100K in total volume</td><td>7,000,000</td><td>3,741</td><td>1,871</td><td>2022-05-10</td></tr><tr><td>The Hashbot #1 Page 1</td><td>Traded at least $100k in total volume</td><td>2,500,000</td><td>561</td><td>4,456</td><td>2022-05-10</td></tr><tr><td>Hashbot: Escape</td><td>Traded at least $300k in total volume</td><td>5,000,000</td><td>82</td><td>60,976</td><td>2022-05-10</td></tr></tbody></table>

### **Open Beta Users**

<table><thead><tr><th>NFT</th><th>Eligibility Criteria</th><th width="150">Aggregate HFT Value</th><th width="150">Minted</th><th width="150">HFT Value per NFT</th><th>Ownership Snapshot</th></tr></thead><tbody><tr><td>Hashbot: Domination</td><td>Tier 1 winner of Open Beta rewards</td><td>2,500,000</td><td>25</td><td>100,000</td><td>2022-05-10</td></tr><tr><td>The Hashbot #1 Page 4</td><td>Tier 2 winner of Open Beta rewards</td><td>3,000,000</td><td>220</td><td>13,636</td><td>2022-05-10</td></tr><tr><td>The Hashbot #1 Page 3</td><td>Tier 3 winner of Open Beta rewards</td><td>2,000,000</td><td>600</td><td>3,333</td><td>2022-05-10</td></tr><tr><td>Hashbot Poster #4</td><td>Tier 4 winner of Open Beta rewards</td><td>2,000,000</td><td>832</td><td>2,404</td><td>2022-05-10</td></tr><tr><td>Hashbot Poster #3</td><td>Tier 5 winner of Open Beta rewards</td><td>2,000,000</td><td>676</td><td>2,959</td><td>2022-05-10</td></tr><tr><td>Hashbot Poster X</td><td>Winner of Open Beta Art Contest</td><td>100,000</td><td>10</td><td>10,000</td><td>2022-05-10</td></tr><tr><td>Hashbot: Unleashed</td><td>Early LP who deposited  >$50K into public pools</td><td>2,500,000</td><td>22</td><td>113,636</td><td>2022-05-10</td></tr><tr><td>The Hashtropolis Poster</td><td>Early LP who deposited  &#x26; maintained >$10K in public pools</td><td>2,500,000</td><td>60</td><td>41,667</td><td>2022-05-10</td></tr></tbody></table>

### Contest Winners

<table><thead><tr><th>NFT</th><th>Eligibility Criteria</th><th width="150">Aggregate HFT Value</th><th width="150">Minted</th><th width="150">HFT Value per NFT</th><th>Ownership Snapshot</th></tr></thead><tbody><tr><td>Hash Bonacci Gold</td><td>Winner of “Get Rich or DAI Trying”</td><td>2,500,000</td><td>11</td><td>227,273</td><td>2022-05-10</td></tr><tr><td>Hashbot Diwali Poster</td><td>Winner of the HashMatic Trading Competition</td><td>2,500,000</td><td>10</td><td>250,000</td><td>2022-05-10</td></tr><tr><td>Hashiba Poster</td><td>Winner of the Hashiba Trading Competition</td><td>2,500,000</td><td>41</td><td>60,976</td><td>2022-05-10</td></tr><tr><td>Hashbot 红包</td><td>Winner of the Year of the Tiger Competition</td><td>782,144</td><td>88</td><td>8,888</td><td>2022-05-10</td></tr><tr><td>The Hashbot #1 Page 2</td><td>Winner of the Arbitrum Athletics Trading Challenge</td><td>1,000,000</td><td>49</td><td>20,408</td><td>2022-05-10</td></tr><tr><td>Hashcraft Mount AVAX Poster</td><td>Winner of the Mount AVAX  Trading Challenge</td><td>1,000,000</td><td>35</td><td>28,571</td><td>2022-05-10</td></tr><tr><td>Hashbitrum Poster</td><td>Winner of the Arbitrum Odyssey snapshot poll</td><td>250,000</td><td>77</td><td>3,247</td><td>2022-05-10</td></tr><tr><td>Hashbot: Project Galaxy Edition</td><td>Winner of the Hashflow GAL Public Pool Giveaway</td><td>-</td><td>96</td><td>-</td><td>Not applicable</td></tr><tr><td>Hashbot: Ethereum Edition</td><td>Winner of the Hashflow Chain Wars</td><td>-</td><td>94</td><td>-</td><td>Not applicable</td></tr><tr><td>Hashbot: Arbitrum Edition</td><td>Winner of the Hashflow Chain Wars</td><td>-</td><td>96</td><td>-</td><td>Not applicable</td></tr><tr><td>Hashbot: BNB Edition</td><td>Winner of the Hashflow Chain Wars</td><td>-</td><td>94</td><td>-</td><td>Not applicable</td></tr><tr><td>Hashbot: Avalanche Edition</td><td>Winner of the Hashflow Chain Wars</td><td>-</td><td>98</td><td>-</td><td>Not applicable</td></tr><tr><td>Hashbot: Polygon Edition</td><td>Winner of the Hashflow Chain Wars</td><td>-</td><td>97</td><td>-</td><td>Not applicable</td></tr><tr><td>Hashbot: Optimism Edition</td><td>Winner of the Hashflow Chain Wars</td><td>-</td><td>95</td><td>-</td><td>Not applicable</td></tr><tr><td>Hashcraft: Original Action Figure</td><td>Winner of the Arbitrum Odyseey Bridge Week</td><td>180,000</td><td>180</td><td>1,000</td><td>2022-06-27 <br>(Winners of the contest)</td></tr><tr><td>Hashbot 8 Billion Poster</td><td>Winner of the Gasless Trading "Share-to-Win" Contest</td><td>-</td><td>713</td><td>-</td><td>Not applicable</td></tr></tbody></table>

### **Community Contributors**

<table><thead><tr><th>NFT</th><th>Eligibility Criteria</th><th width="150">Aggregate HFT Value</th><th width="150">Minted</th><th width="150">HFT Value per NFT</th><th>Ownership Snapshot</th></tr></thead><tbody><tr><td>Hashbot Halloween Poster</td><td>Top contributor during Open Alpha</td><td>5,000,000</td><td>46</td><td>108,696</td><td>2022-05-10</td></tr><tr><td>Hash Bonacci Silver</td><td>Attendee of the Hash Hour @ Mainnet 2021</td><td>2,500,000</td><td>22</td><td>113,636</td><td>2022-05-10</td></tr><tr><td>Hash Bonacci Scarlet</td><td>Attendee of the Hash Hour @ Avalanche Summit</td><td>100,000</td><td>15</td><td>6,667</td><td>2022-05-10</td></tr></tbody></table>

The total aggregate HFT value for the NFTs is **67,500,000** `HFT`, and **587,856** `HFT` is currently unallocated.

Further details around the utility of these NFTs within this context will be revealed in the future.


# Trading Rewards

`0.1%` of the total HFT supply (`1,000,000 HFT` before inflation) has been allocated to Hashflow traders with a monthly ceiling of `350,000 HFT` to be distributed as rewards. The distribution per trader will be calculated as follows:&#x20;

* for each stable coin trade, you will earn `0.0001 HFT` per USD traded
* for each non-stable coin trade, earn `0.0005 HFT` per USD traded

The `350,000 HFT` per month ceiling is broken down by trade type:

* `225,000 HFT` for non-stablecoin trades
* `125,000 HFT` for stablecoin trades


# Market Making Rewards

`10.0%` of the total HFT supply (`10,000,000 HFT` before inflation) will be reserved for market making rewards, distributed in equal installments of `416,667 HFT` each month. The rewards that each market maker will receive will be computed based on their pro-rata share of the total trading volume on the platform in the given month.

To get started as a market maker on Hashflow, [follow the instructions here](https://docs.hashflow.com/hashflow/market-making/getting-started).


# Community Treasury

`1.00%` of the initial HFT supply will be distributed to a community treasury to be allocated on an ongoing basis through contributor grants, community initiatives, and other programs.

The launch of HFT will be followed by the establishment of a governing body which will represent the collective group of HFT holders and governors that will make decisions around the Hashflow protocol.

For example, one major decision point could be around turning on network fees. Currently, Hashflow collects zero fees from traders, but governance could potentially decide to introduce revenues for the protocol, which it could add to the treasury and spend at its collective discretion.

### Proposal Process

An HFT holder with a sufficient balance will be able to submit a proposal through the governance forum, which is required to spend HFT contained within the treasury. Proposals may include but are not limited to:

* Community growth programs
* Technical improvements to the Hashflow protocol
* Educational initiatives
* Other initiatives to grow the Hashflow ecosystem

A valid proposal must be structured as a Hashflow Improvement Proposal (HIP), and have a champion to usher it from a proposal to acceptance, at which point the proposal can be enacted.

Many of the specifics around the proposal process are to be determined, and the first proposal is likely to focus on meta-governance, which will outline the rules of governance and the thresholds required to propose and pass HIPs.

### Treasury Addresses

<table><thead><tr><th width="158.33333333333331">Network</th><th width="451">Address</th><th>Type</th></tr></thead><tbody><tr><td>Ethereum</td><td>0xff830ce17D39BbD6a4fef9683308D793dF8E34fC</td><td>Multi-sig</td></tr><tr><td>Arbitrum One</td><td>0xDD125048F4A045582dA6c2768ca9D70F3259470C</td><td>Multi-sig</td></tr></tbody></table>


# Brand & Logos

Download the Hashflow official brand kit here:

{% file src="/files/j3b5C30U01tmjEA3gvdT" %}

The following Hashflow "brand assets" are copyrighted material, and you may only use them in accordance with the policy detailed below:

* The Hashflow logos, wordmark, icon
* The Hashflow name
* Other visual assets produced by Hashflow

Please review and follow the guidelines below. Have fun creating!

{% file src="/files/0tKw3Uq6tE1rMb7RY9Dy" %}


# Official Links

The following are Hashflow's official websites, social channels, and communities. Follow Hashflow on CT to stay plugged-in and join the Hashgang on Discord!

### **Official Websites**

Website: <https://hashflow.com/>&#x20;

Product: <https://app.hashflow.com/>&#x20;

Docs: <https://docs.hashflow.com/>

### **Social Channels**

Twitter (Hashflow): <https://twitter.com/hashflow>&#x20;

Discord: <https://hashflow.com/discord>&#x20;

Blog: <https://blog.hashflow.com/>&#x20;

Newsletter: <https://news.hashflow.com/>&#x20;

Governance forums: <https://gov.hashflow.com/>&#x20;

Bug bounty submissions: <https://immunefi.com/bounty/hashflow/>


