# Welcome to Toucan

Infrastructure to accelerate global climate action.

Thank you for visiting Toucan's documentation. In the pages that follow, you'll find a comprehensive guide to understanding and utilizing Toucan's platform. If you have any questions, please feel free to contact us at <support@toucan.earth>.

***

Toucan builds infrastructure to accelerate global climate action. Since our launch in 2021, we've led in real-world asset (RWA) tokenization, bringing $100 million in carbon credits onchain and enabling $4 billion in transactional volume. Our focus is on integrating high-integrity carbon removal throughout the crypto ecosystem, making climate action more accessible and widely adopted.

Our platform is composed of the following core products:

* **Puro Carbon Bridge**: The Puro carbon bridge enables the tokenization of carbon removal credits certified by [Puro.earth](https://puro.earth/).
* **TCO2 Tokens**: TCO2s are tokenized carbon credits containing data about the original environmental project, standard, and vintage. Each TCO2 represents one carbon credit and one tonne of carbon verifiably avoided or removed from the environment.
* **Carbon Pools**: Carbon pools bundle TCO2 tokens with similar attributes to create market liquidity. Our most recent pool is the CHAR carbon pool, launched in early 2024.
* **Green NFT Extension**: Enables users and NFT project creators to embed carbon removal credits into new and existing ERC-721 collections.
* **App**: Our [app](https://app.toucan.earth/) allows users to interact with tokenized carbon credits and perform key actions such as depositing into a carbon pool, redeeming from a carbon pool, and retiring credits.

## Getting Started&#x20;

Explore our documentation to dive deep into how Toucan's technology works, the principles of our carbon bridge and pools, and how we leverage smart contracts to scale climate action. Whether you're a software engineer, environmental project developer, a climate-minded corporation, or simply passionate about climate action, this documentation is your gateway to understanding and participating in this innovative approach to climate finance.


# Legal Disclaimer

This is experimental software. Use at your own risk.

By using any products built with Toucan code, you acknowledge that you do so at your own risk. We assume no responsibility or liability for any errors or omissions during the deployment or use of our products, or for any other errors or omissions on this site. Toucan's products and all information on this site are provided "as is," with no guarantees of completeness, accuracy, usefulness, or timeliness.

In no event shall we be liable for any loss or damage, including but not limited to indirect or consequential loss or damage, or any loss or damage whatsoever arising from loss of data, revenue, or profits, arising out of or in connection with the use of our platform.


# Bridging

An introduction to the tokenization of carbon credits.

Carbon credits traditionally exist in offchain registries, which are often provided by the certifying standard that issues the credits. Using Toucan's bridge, holders of carbon credits can bring them onchain. In doing so, the credits enter a tokenized (i.e. "locked") state in the offchain registry, ensuring that they cannot be claimed more than once. The credits remain in this state until the onchain assets are either detokenized, which "unlocks" them in the source registry, or retired, at which point the tokenized asset and its underlying offchain counterpart cannot be further exchanged or claimed.

Benefits of tokenization include:

* **Liquidity and Market Efficiency**: Compatible tokenized credits can be deposited into Toucan's carbon pools, which serve as automated brokers for the purchase or sale of carbon credits, available 24/7.
* **Enhanced Transparency**: Tokenized credit movements and sales are fully transparent.
* **Programmability**: Tokenized carbon credits can be integrated into new software applications for automated climate action.
* **Reduced Fragmentation**: Standardizing carbon credits onchain can increase interoperability across fragmented registry systems.
* **New Use Cases**: The onchain ecosystem offers new use cases to drive climate action, such as integrating tokenized carbon credits in decentralized finance (DeFi), games, social experiences, NFTs, and more.
* **Fractionalization**: Tokenized credits can be exchanged and consumed in sub-tonne amounts.


# Puro Carbon Bridge

Our Puro carbon bridge enables the tokenization, detokenization, and retirement of CO2 removal certificates (CORCs) issued by Puro.earth. We have developed the first two-way bridge that integrates with the Puro Connect API, providing a streamlined and secure way to move assets between the Puro Registry and the blockchain.

## Use Cases

The Puro carbon bridge is beneficial for various market participants:

* **Project Developers**: Projects that are issued Puro CORCs can tokenize their assets to take advantage of increased market efficiencies available onchain. For example, selling assets into a Toucan carbon pool offers instant settlement 24/7 with clear pricing signals. This process is faster than managing an OTC deal and can potentially offer higher prices.
* **Brokers**: Brokers can source credits onchain and bring them offchain, or vice versa. Some market participants may also pursue arbitrage opportunities that exist between the onchain and offchain prices.
* **Climate Entrepreneurs**: New use cases for carbon removal credits are emerging onchain. These projects can use Toucan's bridge to tokenize (or detokenize) carbon removal credits for their initiatives, leveraging the benefits of blockchain for climate action.

## Requirements to Bridge

To bring carbon removal credits over the Puro carbon bridge, you'll need the following:

1. **Puro.earth Account**: You must have access to a Puro.earth account. If you'd like to tokenize, you also must hold CORCs in the Puro Registry. Visit the [Puro website](https://puro.earth/) for details.
2. **Blockchain/Web3 Wallet**: In the case of tokenization, ensure you have the address of a wallet where you want the tokenized CORCs to be sent. The wallet must be compatible with our supported networks (Base, Polygon, and Celo). For detokenization, you must control a wallet that holds Puro TCO2 tokens.


# Tokenization

How to tokenize CORCs from the Puro Registry into TCO2s.

At a high level, the tokenization of carbon removal credits, or CORCs, via our Puro carbon bridge involves a few steps:

1. **Request Tokenization**: Provide details such as the serial numbers of the credits you want to bridge, the project name, and the destination address to Toucan. Further instructions on this are below.
2. **CORCs are Locked**: Upon tokenization, credits will be immobilized in an omnibus account within the Puro Registry for as long as the tokenized version exists.
3. **Toucan Mints a Batch NFT**: Toucan mints an NFT onchain that contains details about the tokenization event.
4. **Deliver TCO2 Tokens**: Toucan will fractionalize the Batch NFT into TCO2 tokens, each representing one CORC that has been tokenized. The TCO2 tokens will be delivered to the wallet address provided.

<figure><img src="/files/oEwIvv6vnO1Or8UyeKiP" alt=""><figcaption></figcaption></figure>

## Instructions to Tokenize

### Step 1: Onboard to Toucan's Bridge

{% hint style="info" %}
If you've already done this, skip to step 2 below.
{% endhint %}

1. Go to the [Puro bridge onboarding and tokenization form](https://form.typeform.com/to/uwLStfFZ) and select the onboarding option.
2. Fill in the necessary details, which will include information about your organization and a prompt to accept the bridge’s Terms and Conditions.

### Step 2: On-Ramp Assets to Toucan's Sales Channel in Puro Registry

The process of on-ramping transfers your Puro CORCs into Toucan's Sales Channel within the Puro Registry. Your assets must be in our Sales Channel to proceed with tokenization.

Also, each bridge user must be onboarded as a recognized “Trader” within the Sales Channel. The first time you use our bridge, follow step 2a so that Puro sets this up for you.

<details>

<summary><strong>2a. For first time users</strong> (Puro account holders who have not yet on-ramped any assets to Toucan’s Sales Channel)</summary>

Send the following email to Puro. If you have any questions preparing this email, contact <support@toucan.earth>.

**To**: <tech-support@puro.earth>

**CC**: <support@toucan.earth>

**Subject**: On-ramp assets to Toucan’s Sales Channel and initiate request to set up Trader account

**Body**: Please on-ramp the following assets to Toucan’s Sales Channel and, in the process, initiate a request to set up our organization’s Trader account within the Toucan Sales Channel that Toucan can then approve.

**Credit owner details**

* Organization name:
* Address:
* Business ID:

**Sales Channel details**

* Name of the organization: Toucan Protocol Association
* Business ID: CHE-381.295.616

**Other details**

* Account number credits will be transferred **from**
* Credit ID numbers
* Amount of credits
* **Set automatic transaction approval `on`**

</details>

<details>

<summary><strong>2b. For returning users</strong> (Puro account holders who have already on-ramped assets to Toucan’s Sales Channel)</summary>

Send the following email to Puro. If you have any questions preparing this email, contact <support@toucan.earth>.

**To**: <tech-support@puro.earth>

**CC**: <support@toucan.earth>

**Subject**: On-ramp assets to Toucan’s Sales Channel

**Body**: Please on-ramp the following assets to Toucan’s Sales Channel:

**Credit owner details**

* Organization name:
* Address:
* Business ID:

**Sales Channel details**

* Name of the organization: Toucan Protocol Association
* Business ID: CHE-381.295.616

**Other details**

* Account number credits will be transferred **from**
* Credit ID numbers
* Amount of credits
* **Set automatic transaction approval `on`**

</details>

### Step 3: Submit Tokenization Request

Toucan will initiate the tokenization of CORCs once your assets have been on-ramped to the Toucan Sales Channel and upon your completion of the [Puro bridge onboarding and tokenization form](https://form.typeform.com/to/uwLStfFZ) (select the tokenization option).

Once your request is processed, the offchain CORCs will be batch-minted as an ERC-721 NFT. This NFT will then be fractionalized into ERC-20 TCO2 tokens and deposited into the onchain wallet you specified in the request form.


# Detokenization

How to detokenize TCO2s into CORCs in the Puro Registry.

Similar to tokenization, the process of detokenizing requires that you hold a Puro.earth account and be onboarded as a "Trader" into the Toucan Sales Channel.

### Step 1: Onboard to Toucan's bridge

{% hint style="info" %}
If you've already done this, skip to step 2 below.
{% endhint %}

1. Go to the [Puro bridge onboarding and tokenization form](https://form.typeform.com/to/uwLStfFZ) and select the onboarding option.
2. Fill in the necessary details, which will include information about your organization and a prompt to accept the bridge’s Terms and Conditions.

### Step 2: Request that Puro Sets up Your Trader Account

{% hint style="info" %}
If you've already done this, skip to step 3 below.
{% endhint %}

This step requires that you send an email to Puro. They will submit a Trader Onboarding Proposal, which Toucan will then accept via Puro's API. Please use the format in the toggle below. If you have any questions about this email, contact us at <support@toucan.earth>

<details>

<summary><strong>Email to Puro requesting Trader account</strong></summary>

**To**: <tech-support@puro.earth>

**CC**: <support@toucan.earth>

**Subject**: Initiate request to set up Trader account

**Body**: Please initiate a request to set up our organization’s Trader account within the Toucan Sales Channel that Toucan can then approve.

* Organization name:
* Address:
* Business ID:

**Sales Channel details**

* Name of the organization: Toucan Protocol Association
* Business ID: CHE-381.295.616

**Other details**

* **Set automatic transaction approval `on`**

</details>

### Step 3: Submit Detokenization Request

Detokenization can be requested via our app. Connect to <https://app.toucan.earth/> with your web3 wallet that holds the TCO2s you'd like to detokenize. Ensure you're connected to the correct network.&#x20;

You'll see the TCO2s in our app. Click **Bring off-chain** and complete the required fields.

<figure><img src="/files/XgL1K5q0RG0aVJIVZgVY" alt=""><figcaption></figcaption></figure>


# Carbon Pools

Carbon pools bundle carbon credits that share similar attributes to create more liquid and efficient markets.

## The Problem&#x20;

Carbon credits are an illiquid asset class, meaning that often, they cannot be bought and sold quickly or efficiently. This illiquidity stems from the significant differentiation across projects, vintages, and other characteristics, each effecting a specific credit's market price.

Low liquidity poses challenges for stakeholders in the voluntary carbon market (VCM). On the supply side, project developers may struggle to sell their credits quickly at market prices. For buyers, sourcing credits often involves relying on a network of intermediaries or engaging in lengthy over-the-counter (OTC) transactions. Additionally, the lack of transparent pricing data makes it difficult to assess whether a deal is fair.

### A Balancing Act

When carbon assets are bridged and tokenized into TCO2s, they retain their unique characteristics through metadata, such as project- and vintage-specific attributes. Carbon pools introduce a level of standardization by bundling TCO2s with similar characteristics, enabling deeper market liquidity and more efficient transactions.


# How a Carbon Pool Works

A carbon pool groups similar tokenized credits (TCO2 tokens) to enhance market efficiency and liquidity. Here are the key aspects of how pools work:

* **Filtering Criteria**: Each carbon pool has specific filtering criteria—rules that define the attributes TCO2s must have to be eligible for the pool.
* **Pool Tokens**: Each carbon pool issues its own fungible pool token (i.e., all tokens from a single pool are identical).
* **1:1 Creation**: For every TCO2 token deposited into a pool, a corresponding pool token is created on a 1:1 basis.
  * While this 1:1 exchange rate is standard for Toucan pools, such as the CHAR carbon pool, some Toucan partners may choose to deviate from this exchange rate.
* **Redemption**: Carbon pool tokens can be redeemed for TCO2 tokens held in the pool—think of them as vouchers that provide access to the underlying credits.

<figure><img src="/files/Vt4hPIGh3X0IeEq5eHvS" alt=""><figcaption></figcaption></figure>

By designing pools in this way, we:

* **Preserve Market Diversity**: All differentiating attributes of carbon credits are maintained at the TCO2 level.
* **Create Liquidity**: At the carbon pool token level, we create a deeply liquid, fungible token.
* **Provide Access**: Holders of carbon pool tokens have access to any of the carbon credits held within the pool.

Because carbon pool tokens are fungible, liquid markets can easily be established for them on exchanges. This allows users to buy and sell carbon pool tokens with ease while still retaining access to the underlying TCO2s.


# Benefits of Pools

## For Suppliers

Carbon Pools acts as an automated broker to help suppliers quickly monetize their credits.

To illustrate how carbon pools work, imagine you hold biochar CORCs certified in 2024 by Puro.earth, and you'd like to sell them quickly.&#x20;

By tokenizing these credits with the Puro carbon bridge, you gain the option to deposit them into the [CHAR carbon pool](/toucan/carbon-pools/char-carbon-pool) (assuming they qualify in accordance with the filtering criteria).&#x20;

When you make the deposit, you'll then receive CHAR tokens at a 1-1 basis less any incurred deposit fees. The carbon pool tokens can then be instantly sold on an exchange. Thus, the onchain credits can be sold in a matter of minutes, without relying on brokers or other intermediaries.

## For Buyers

Alternatively, imagine you are a buyer or distributor looking to acquire Puro.earth biochar credits.

With the CHAR carbon pool, you can explore credits available in the pool from a wide range of projects around the world. When you find credits from a project that you want to support, you can [purchase CHAR](/toucan/carbon-pools/how-to-buy-char) on an exchange and then in our app, redeem the CHAR for your preferred TCO2 tokens in just a few minutes. You can then [retire the TCO2 tokens](/toucan/retire-credits) for climate action.

Buyers can access a broad stock of credits, and distributors can offer that range of credits to their customers without taking on inventory risk.&#x20;

## Transparent Prices

Since carbon pool tokens trade on exchanges, we receive a strong price signal for credits held within the pool. This creates a number of positive effects on the carbon market, including fairer deals for suppliers, increased confidence for buyers, and reduced risk in project financing.


# CHAR Carbon Pool

{% hint style="info" %}
If you're new to pools, review [how a carbon pool works](/toucan/carbon-pools/how-a-carbon-pool-works).
{% endhint %}

The CHAR carbon pool bundles carbon removal credits from Puro.earth.

It allows suppliers to convert their Puro.earth CO2 removal certificates (CORCs) into CHAR, which has a liquid market and a transparent price. End-buyers or intermediaries can access the inventory of tokenized credits within the pool at any point in time and with instant settlement.

The project composition and number of credits within the pool is always transparent, and buyers can select exactly which credits they want to redeem from the pool.

Our open infrastructure is designed to bring more liquidity to the biochar market in an effort to scale carbon removal globally.

{% hint style="info" %}
CHAR contract address on Base: [0x20b048fA035D5763685D695e66aDF62c5D9F5055](https://basescan.org/address/0x20b048fA035D5763685D695e66aDF62c5D9F5055)

CHAR contract address on Celo: [0x50E85c754929840B58614F48e29C64BC78C58345](https://celoscan.io/address/0x50E85c754929840B58614F48e29C64BC78C58345)
{% endhint %}

{% embed url="<https://www.loom.com/share/7736335f7b4542148adbaf30c778e4f3?sid=26750887-2f12-4625-870b-7a52abb44a80>" %}

## Establishing a Liquid Biochar Market

The CHAR carbon pool offers suppliers a direct pathway to monetize their CORCs. It supports a streamlined process to sell CORCs quickly and easily, with continuous demand and transparent market price signals – available 24/7.

Additionally, the pool underpins liquid markets that allow buyers, brokers, and traders from anywhere in the world to engage in instant buying and selling of biochar assets. In this capacity, it supports a highly accessible secondary market for efficient biochar transactions.

<figure><img src="/files/n2db4ScXEE7cTG4evaDP" alt=""><figcaption><p>The CHAR carbon pool bundles project-specific TCO2 tokens in exchange for fungible and liquid CHAR tokens.</p></figcaption></figure>

### An Allowlist Filter Criteria

An allowlist of projects determines which TCO2 tokens are permitted to be deposited into the CHAR pool. Toucan and its partners review and update this allowlist regularly.

The allowlist of projects currently includes:

* [Concepcion 1](https://app.toucan.earth/explorer/project/pur-432524)
* [Oregon Biochar Solutions](https://app.toucan.earth/explorer/project/pur-753518)
* [American BioCarbon CT, LLC](https://app.toucan.earth/explorer/project/pur-543800)
* [BC Biocarbon - McBride](https://app.toucan.earth/explorer/project/pur-862421)
* [Wakefield Biochar](https://app.toucan.earth/explorer/project/pur-244045)

### Pool Health Fee

With the launch of CHAR, we have implemented a dynamic pool health fee to encourage pool diversification. This promotes a balance of projects and limits the ability for any single project to monopolize the pool’s composition.

Adjustments in the form of fees are applied to deposits and redemptions, and are calculated based on the pool's post-transaction composition.

* For TCO2 deposits, the adjustments reduce the number of CHAR tokens received by the depositor. The adjustment amount increases as a project's composition within the pool rises.
* For CHAR redemptions, the adjustments reduce the number of TCO2 tokens received by the redeemer. The adjustment amount increases as a project's composition within the pool falls.

Pool health adjustments are calculated as a percentage and are deducted in the form of the CHAR token. Users are provided with full transparency regarding the fees before executing a transaction. Over time, Toucan may update the dynamic fee parameters based on pool activity and performance.


# How to Buy CHAR

The world's first liquid market for biochar.

CHAR is available on Uniswap via the Base and Celo networks.

{% hint style="info" %}
For commercial orders, feel free to contact our team directly at <support@toucan.earth>
{% endhint %}

## Wallet setup

To buy CHAR, you will need a web3 wallet set up and connected to the Base or Celo network. The most popular wallet is [MetaMask](https://metamask.io/), but you might also consider [Coinbase Wallet](https://www.coinbase.com/wallet), [Rainbow](https://rainbow.me/), or others. Instructions below will cater to MetaMask users.

If you already have MetaMask but have not added Base or Celo, add it by following these steps:

<details>

<summary>Base setup</summary>

1. Navigate to **Settings** > **Networks** > **Add network**
2. Click **Add a network manually**
3. Copy the following details:
   1. Network Name: `Base`
   2. New RPC URL: `https://mainnet.base.org`
   3. Chain ID: `8453`
   4. Currency Symbol (Optional): `ETH`
   5. Block Explorer URL (Optional): `https://basescan.org/`
4. Click **Save**

You'll now be able to toggle to the Base network directly from your MetaMask wallet.

</details>

<details>

<summary>Celo setup</summary>

1. Navigate to **Settings** > **Networks** > **Add network**
2. Click **Add a network manually**
3. Copy the following details:
   1. Network Name: `Celo (Mainnet)`
   2. New RPC URL: `https://forno.celo.org`
   3. Chain ID: `42220`
   4. Currency Symbol (Optional): `CELO`
   5. Block Explorer URL (Optional): `https://explorer.celo.org`
4. Click **Save**

You'll now be able to toggle to the Celo network directly from your MetaMask wallet.

</details>

## Getting assets onto Celo

There are multiple ways to get assets onto the Celo network, including bridging from other blockchains or on-ramping to the Celo network directly. Here we will focus on on-ramping directly to Celo via Coinbase, which is likely to be the easiest path for most users.

### How to add assets from Coinbase to Celo

If you are using Coinbase, the most direct way to get assets onto Celo is the following:

1. From Coinbase, purchase Celo's native token, CELO (symbol CGLD). Note that CELO and CGLD are the same token and various platforms use the symbols interchangeably. This token will be used to pay for transactions on the Celo network ("gas fees") and it can also be used to trade for CHAR.
2. With CELO (CGLD) in your Coinbase account, you can then send it to your web3 wallet.

As of March 2024, Coinbase only allows for the withdrawal of CELO (CGLD) directly to the Celo network.

{% embed url="<https://www.loom.com/share/cc5c4f5bf80d46dea0dd2c567c369fb1?sid=6efe63fa-838a-4c6a-a938-815ec2a4c2d7>" %}

## Steps to buy CHAR on Uniswap (Base)

* Go to <https://app.uniswap.org/>
* Connect your wallet and switch to the Base network
* Toggle the asset that you're swapping from
* Paste the CHAR contract address as the asset that you're swapping to: 0x20b048fA035D5763685D695e66aDF62c5D9F5055
* Since CHAR is a new asset, you may be prompted to accept a warning dialogue
* Complete the approval, signing, and swapping transactions
* Upon transaction execution, your CHAR balance will update at <https://app.toucan.earth/>

## Steps to buy CHAR on Uniswap (Celo)

{% hint style="info" %}
To ensure sufficient liquidity for your swap, it's recommended to use USDC to purchase CHAR. If your wallet only has CELO, first swap for USDC ("USDCoin"), contract address 0xcebA9300f2b948710d2653dD7B07f33A8B32118C.
{% endhint %}

1. With CELO and USDC in your web3 wallet on the Celo network, go to <https://app.uniswap.org/>
2. Connect your wallet and switch to the Celo network
3. Toggle the asset that you're swapping from
4. Paste the CHAR contract address as the asset that you're swapping to: 0x50E85c754929840B58614F48e29C64BC78C58345
5. Since CHAR is a new asset, you may be prompted to accept a warning dialogue
6. Complete the approval, signing, and swapping transactions
7. Upon transaction execution, your CHAR balance will update at <https://app.toucan.earth/>

### Video walkthrough

{% embed url="<https://www.loom.com/share/6409fdf78824460ba6379a7fc8afb1f7?sid=1af4ff6a-4ba2-4c4f-b155-8cea8af02c62>" %}


# Deposits and Redemptions

This guide will show you how to deposit and redeem TCO2 tokens from a carbon pool using Toucan's app UI. If you'd like to redeem with code, refer to our [developer docs](/developers/toucan-developer-resources).

{% hint style="success" %}
To **deposit** into a carbon pool, you need to have eligible TCO2 tokens in your wallet.

To **redeem** from a carbon pool, you need to have carbon pool tokens in your wallet.
{% endhint %}

{% tabs %}
{% tab title="Deposit" %}

1. Go to <https://app.toucan.earth/> and click **Connect wallet** sign in
2. Scroll down to see the TCO2 tokens and amounts that you hold. Click **Deposit.**
3. Select which TCO2 tokens and the amount that you want to deposit.
4. Review the information carefully. If it's all correct, **Approve** the transfer of the TCO2 tokens, then click **Deposit Now**. Each step will require you to confirm a transaction with your wallet.
5. Once the transaction is complete, the carbon pool tokens will be in your wallet and visible through the Toucan app interface.
   {% endtab %}

{% tab title="Redeem" %}

1. Go to <https://app.toucan.earth/> and click **Connect wallet** sign in
2. Scroll down to see the pool tokens and amounts that you hold. Click **Redeem.**
3. Select the project and number of credits that you want to redeem.
4. Review the information carefully. If it's all correct, click **Redeem Now**.
5. **Confirm** the transaction in your wallet pop-up window.
6. Once the transaction is complete, the TCO2 tokens will be in your wallet and visible through the Toucan App interface.
   {% endtab %}
   {% endtabs %}


# Carbon Retirements

When a business or individual chooses to compensate their emissions with carbon credits, the credits must be permanently removed from circulation. The process of retiring – and irrevocably removing from circulation – tokenized carbon credits can be done through the Toucan app UI or programmatically.&#x20;

**Only TCO2 tokens can be retired on Toucan.** Carbon pool tokens such as CHAR must be redeemed for underlying TCO2 tokens. Retirements performed on Toucan will be synced with the Puro Registry.

{% hint style="info" %}
Developers looking to perform retirements using code should refer to [Toucan for Developers](/developers/toucan-developer-resources).
{% endhint %}

## Guide to Retirement Through Toucan's App UI

1. Connect your wallet holding TCO2 tokens to our app at <https://app.toucan.earth/>. You'll then see your TCO2s displayed under the "My Carbon Assets" section. Click **Retire**.

<figure><img src="/files/erX9ZorDG1ol3aTvS2Oq" alt=""><figcaption></figcaption></figure>

2. Select how many TCO2s you'd like to retire, and then click **Continue**.
3. Add relevant information, including:
   1. The name of the individual or organization performing the retirement
   2. The name of the individual or organization on who’s behalf the retirement is for
   3. The wallet address on who’s behalf the retirement is for, if available
   4. A message to your retirement transaction (e.g. a reason; max. 200 characters)
4. Click **Request retirement**
5. Once submitted, your retirement will enter a pending state until finalized in the Puro Registry. You can track the status of your submitted retirement at <https://app.toucan.earth/retirements>. It typically takes 2-3 business days for a retirement to finalize.
6. Lastly, Toucan will issue you a retirement certificate, viewable from <https://app.toucan.earth/retirements>. You may also download the certificate as a PDF.


# Web3 concepts

### Account

One key difference between Web2 and Web3 is how identity works. In Web3, users control their own accounts and identity, and authenticate themselves using [digital signatures](https://proton.me/blog/what-is-a-digital-signature#what-is-a-digital-signature).

Learn more about [accounts ->](https://ethereum.org/en/guides/how-to-create-an-ethereum-account/)

### Wallet

Wallets are software applications that help you interact with blockchain networks and sign in to Web3 applications. Wallets store private keys and digitally sign transactions. With a wallet, you can manage digital assets and use smart contracts. Some wallets require a hardware device for extra security.

Learn more about [wallets ->](https://ethereum.org/en/wallets/)

### Security

Web3 builders prioritize security, and rely on a combination of cryptography, computer science and game theory to build systems that are resilient to shocks and extremely difficult to attack. In addition, Web3 systems place a lot of responsibility on the user — actions are often irreversible, and accounts cannot be recovered.

Learn about [consensus mechanisms->](https://ethereum.org/en/developers/docs/consensus-mechanisms/) which secure blockchain networks

Learn about [cryptography->](https://github.com/ethereumbook/ethereumbook/blob/develop/04keys-addresses.asciidoc#cryptography) which supports private messaging and identity systems on the Internet

### Blockchain

A blockchain is a ledger that is maintained and updated by a decentralized network of computers, called a consensus network. It's the foundational technology behind cryptocurrencies and many Web3 applications.

Learn more about [blockchains and how they work ->](https://www.mckinsey.com/featured-insights/mckinsey-explainers/what-is-blockchain)

### Smart Contract

Smart contracts are small computer programs stored and executed on a blockchain network. Smart contracts can hold tokens — decentralized finance (DeFi) applications, including Toucan, are built with the technology.

Learn more about [smart contracts ->](https://ethereum.org/en/smart-contracts/)

### Token

Digital assets or units of value issued on a blockchain. They can represent assets, access rights, or even participation in a network. Token systems are managed by smart contracts.

{% hint style="info" %}
Tokens can be created to represent anything, and often do not have any intrinsic value or backing. The tokens used in Toucan Protocol are backed by **real world assets** — carbon credits certified by reputable standards bodies, like Puro.
{% endhint %}

Learn more about [tokens ->](https://www.coinbase.com/learn/crypto-basics/what-is-a-token)

### Oracle

Oracles are services that provide external data to smart contracts on the blockchain. This data can trigger smart contract executions or inform decision-making processes.

Learn more about [oracles ->](https://chain.link/education/blockchain-oracles)

### DeFi (Decentralized Finance)

DeFi leverages blockchains and smart contracts to recreate and improve financial services like lending, borrowing, and trading, but in a decentralized, transparent, and permissionless way.

Learn more about [DeFi ->](https://ethereum.org/en/defi/)

Read a balanced take on the [risks and potential benefits of DeFi ->](https://www.economist.com/leaders/2021/09/18/the-beguiling-promise-of-decentralised-finance)

### Automated Market Maker

An automated market maker (AMM) is a type of decentralized exchange protocol enabled by smart contracts that relies on a mathematical formula to price assets.

Instead of using an order book like a traditional exchange, an AMM uses liquidity pools that traders can trade against. These pools are funded by liquidity providers who deposit their assets into the pool and earn fees based on trading activity. The AMM algorithm automatically adjusts prices based on the supply and demand of assets in the pool. This allows for continuous trading without the need for traditional market makers or buyers and sellers to create liquidity.

Read more about AMMs in the Constant Function Market Maker section of [this paper from the Federal Reserve Bank of St Louis ->](https://research.stlouisfed.org/publications/review/2021/02/05/decentralized-finance-on-blockchain-and-smart-contract-based-financial-markets)

### Web3

"Web3" refers to a movement to rebuilt the Internet so it serves its users. A wide range of technologies and products are emerging from the movement, including blockchains and smart contracts, decentralized data systems, peer-to-peer communication apps and privacy-preserving technologies.

<details>

<summary>General Web3 Resources</summary>

[Toucan — Key terms in the digital voluntary carbon market explained](https://blog.toucan.earth/dvcm-terms-explained/)

[Chris Dixon — The Potential Nof Blockchain Technology](https://podcasts.apple.com/us/podcast/chris-dixon-the-potential-of-blockchain-technology/id1154105909?i=1000516930066)

[Matt Levine — The Only Crypto Story You Need](https://www.bloomberg.com/features/2022-the-crypto-story/)

[Linda Xie — Composability is Innovation](https://a16zcrypto.com/posts/article/how-composability-unlocks-crypto-and-everything-else/)

[Coinbase Blog — Understanding Web3: A User Controlled Internet](https://www.coinbase.com/en-gb/blog/understanding-web-3-a-user-controlled-internet)

[Consensys — Blockchain in Digital Identity](https://consensys.net/blockchain-use-cases/digital-identity/)

[Andreas Antonopoulos — Mastering Ethereum](https://github.com/ethereumbook/ethereumbook/tree/develop)

</details>


# Carbon markets

## The Voluntary Carbon Market: a quick overview

The voluntary carbon market (often shortened to VCM) is an important mechanism for driving money to projects creating a climate-positive impact by reducing or avoiding greenhouse gas (GHG) emissions. Carbon credits are issued by [standards bodies](#carbon-standards), who certify that climate impact has taken place. People and organizations can then buy the credits and retire them to claim positive environmental impact. Each carbon credit represents a measurable and verifiable removal, reduction, or avoidance of GHG emissions. These credits are denominated in tCO2e, which means [tonne of CO2 equivalent](https://www.theguardian.com/environment/2011/apr/27/co2e-global-warming-potential).

Learn more about [carbon credits ->](/resources/carbon-markets/credits)

Read about how voluntary carbon markets [differ from compliance markets ->](https://www.offsetguide.org/understanding-carbon-offsets/carbon-offset-programs/mandatory-voluntary-offset-markets/)

### Carbon Standards

Carbon standards govern the methodologies which define how climate impact is created and verified. Every carbon project needs to follow these methodologies to show it meets minimum quality criteria. Once a project’s impact has been verified, standards bodies issue carbon credits to the project. Carbon standards play a key role in ensuring carbon credit quality, and buyers and offsetters value the stamp of approval that standards bodies give to carbon credits.

Currently, [Verra](https://verra.org/) and [Gold Standard](https://www.goldstandard.org/) are the two most established entities setting carbon standards. Smaller standards bodies issue less than a quarter of the voluntary market carbon credits each year. Some standards bodies specialize in different decarbonization pathways — for example, [Puro.earth](https://puro.earth) focuses on engineered carbon removal methodologies.

### Methodologies

To get carbon credits issued, each project needs to follow high-level requirements and processes, and use certain [accounting methodologies](https://verra.org/methodologies/) that describe which data should be monitored. These methodologies vary depending on the carbon credit-generating activity. A project that is [protecting forests from deforestation](https://verra.org/methodology/vm0015-methodology-for-avoided-unplanned-deforestation-v1-1/), for example, needs to collect different data than a [wetland restoration](https://verra.org/methodology/vm0033-methodology-for-tidal-wetland-and-seagrass-restoration-v1-0/) project. The same applies to technology-based methodologies: projects that focus on capturing methane emitted from coal beds have different data requirements than ones that provide charging infrastructure for electric vehicles. Independent third parties — a list of [validation/verification bodies](https://verra.org/project/vcs-program/validation-verification/) authorized by each standard — assess projects according to set rules and requirements.

Once it’s been verified, a project can be issued carbon credits by the standards body.

### Carbon Registries

Standard bodies maintain their own carbon [registries](https://registry.verra.org/). These hold a list of all the projects that have been issued carbon credits, and some records of the credits themselves. When a carbon credit is retired, this is shown in the registry.

#### **What are carbon credit retirements?**

After a project has proven that it removed or reduced GHG emissions, it receives carbon credits. These credits are issued in an ***active*** state because they represent an environmental impact claim.

Often, projects don't have connections to companies that want to buy carbon credits to compensate for their emissions. So they often sell their active credits via intermediaries — brokers, resellers, and retailers. Active carbon credits can pass from one hand to another without losing their active status. But when a buyer wants to use a credit to compensate (or offset) carbon emissions for carbon accounting purposes, their credits need to be ***retired***. After being retired, the carbon credit has fulfilled its duty, and its environmental impact claim is consumed — no one else will be able to claim a carbon removal or reduction with that specific credit.

{% hint style="info" %}
Important to know: you need to have a registry account to trade active carbon credits in legacy registries. These accounts can cost \~ [$1000 a year](https://desk.zoho.com/portal/sustaincert/en/kb/articles/how-to-open-a-gold-standard-registry-account).
{% endhint %}

The registries that standards bodies maintain typically run on centralized databases. These systems track carbon credit ownership and record which credits have been retired. Different registries have different functionalities available to users and project developers.

#### **Even more potential for carbon credits**

Toucan's infrastructure isn’t just improving carbon registries — it’s creating a brand-new use case for carbon credits. On open blockchains, they can plug into the world of [decentralized finance](/resources/interacting-with-smart-contracts#defi-decentralized-finance). We’re working with the best DeFi projects, like [Uniswap](https://uniswap.org) and [Sushiswap](https://www.sushi.com), to make sure carbon credits on Toucan can safely benefit from these new financial technologies. You can now buy carbon pool tokens 24/7 anywhere in the world, then [redeem](/toucan/carbon-pools#so-what-is-a-carbon-pool) and [retire](/toucan/retire-credits) them.


# Carbon credits

A carbon credit represents a measurable and verifiable removal, reduction, or avoidance of greenhouse gas (GHG) emissions - a tonne of CO2 equivalent that is *not* in the Earth's atmosphere.

It makes a difference whether or not emissions are being drawn down from the atmosphere—commonly referred to as carbon removal—or if the flow of emissions into the atmosphere is being reduced or avoided. The classification into removal vs. reduction/avoidance credits is a good example of the diversity of carbon credits and form the core of carbon accounting and reporting best practices.

But within these broad categories, many more differentiating criteria dictate the price carbon projects can expect to get for their credits. A few important ones are:

* **Project type.** Different approaches to reducing greenhouse gases in the atmosphere are more or less effective - techniques like reforestation, protecting forests from deforestation, renewable energy projects (solar, wind, hydro), methane capture, soil carbon, or carbon capture and storage (CCS) projects.
* **Country.** Project costs are higher in some countries than others, plus credits from some countries may be perceived as higher-quality than from other countries.
* **Carbon standard.** Some standards are more rigorous than others or demand additional data points to be collected during project monitoring and verification.
* **Co-benefits.** Some projects seek additional certification from standards like the Climate, Community and Biodiversity Standards ([CCB Standards](https://www.climate-standards.org/ccb-standards/)), which certifies additional benefits like an increase in biodiversity or specific [Sustainable Development Goals](https://sdgs.un.org/goals) (SDGs).

The unique attributes tied to a carbon project results in credits being traded and sold like differentiated products (e.g. wine) rather than like commodities (e.g. corn or rice). Subsequently, the majority of carbon transactions happen over-the-counter (OTC) and behind closed doors, meaning credit prices remain unknown to the broader market. This makes it hard for end customers to know whether or not they are paying a fair price and which percentage of the money lands in the hands of the initial project developer.

Toucan [Carbon Pools](/toucan/carbon-pools) allow for some level of commoditization by pooling similar carbon tokens. This is necessary to produce a transparent price signal to the market for different categories of carbon credits. These standardized carbon tokens can be traded on DEXs ([decentralized exchanges](/resources/interacting-with-smart-contracts#automated-market-maker)) with much deeper liquidity than a single project's credits ever could.


# Frequently asked questions

This can be a bit confusing. We're here to help.

Here, you'll find answers to common questions about Toucan's platform, our approach to carbon credits, and how to engage with our digital tools. This section is designed to clarify any uncertainties and provide quick, straightforward information. Whether you're new to carbon markets or looking for specific details about our processes, this is your go-to resource for fast, reliable answers.


# How do I use the Carbon Bridge?

Please follow the Carbon Bridge tutorial:

{% content-ref url="/pages/-MeuHApzA92Ye5P-XHmd" %}
[Bridging](/toucan/carbon-bridge)
{% endcontent-ref %}


# How can one carbon pool token, like CHAR, represent one tonne of carbon?

When they're tokenized, carbon credits are represented as TCO2 tokens. When a TCO2 token is deposited in a carbon pool, it is locked, and a corresponding carbon pool token, like CHAR, is created.&#x20;

Every carbon pool token in circulation is backed by a TCO2 token. This can be verified by looking at a third party website like a block scanner and inspecting the contents of the pool, or by auditing the contents using a function like [`fetchPoolContents`](/developers/sdk/subgraph-interactions#fetchpoolcontents).


# Can I retire carbon pool tokens, like CHAR, to offset my emissions?

**No, carbon pool tokens like CHAR cannot be retired.** Only TCO2 tokens — which back each reference token — can be [retired](/toucan/retire-credits) to make impact claims.

Instead, carbon pool tokens can be redeemed for underlying TCO2 tokens, which can then be retired using our app. Learn how to [redeem here](/toucan/carbon-pools/deposits-and-redemptions), and how to [retire here](/toucan/retire-credits).


# Where can I find the addresses of CHAR or other contracts?

A "contract address" refers to a unique identifier for a smart contract, which is a self-executing contract with the terms of the agreement directly written into code, deployed and stored on the blockchain.

You can find the addresses of our deployed contracts on every network [at app.toucan.earth/contracts](https://app.toucan.earth/contracts). The addresses to be interacted with are the Proxy labelled contracts.


# How long does it take to bridge carbon credits?

The Toucan team approves requests usually two times day. The bridging process takes only a few minutes, however, expect to wait about 12-24 hours in most cases before the bridging is complete.


# What happens to a pool token if it is bridged to another network?

In order for carbon pool tokens to be created on the chosen network e.g. [Celo](https://celo.org/), they will be burned on the former network e.g. [Polygon](https://polygon.technology/).


# FAQ for transition to Open Source

This page provides more details on the May 2025 strategic announcement to incrementally transition Toucan Protocol to Open Source licenses.  The summary is that this transition will cause no significant changes to tokens or existing infrastructure.

* **What will happen to my CHAR?**

  There will be no significant change. CHAR will continue to be available on Base and Celo, with cross-chain bridging remaining available between these chains. On/off-chain bridging of underlying TCO2s will continue to be supported via our Puro Bridge. Deposits/redemptions will continue to be supported at [app.toucan.earth](http://app.toucan.earth). Liquidity will remain at the discretion of liquidity providers, as before.
* **What will happen to my NCT?**

  No significant change. Cross-chain bridging will remain available between Polygon, Celo, and Regen. Deposits/redemptions will continue to be supported at [app.toucan.earth](http://app.toucan.earth).
* **What will happen to my BCT?**

  BCT is no longer a Toucan product, as admin control of the BCT contracts was transitioned to KlimaDAO in 2024. While there will be no significant changes, cross-chain bridging is deprecated - please inquire with KlimaDAO regarding bridge availability. Deposits/redemptions will continue to be supported at [app.toucan.earth](http://app.toucan.earth). Liquidity will remain at the discretion of liquidity providers.
* **What will happen to my TCO2s?**

  There will be no significant changes to TCO2s. Puro TCO2s eligible for the CHAR carbon pool can continue to be deposited and redeemed. On/off-chain bridging and retirement of Puro TCO2s will continue to be supported for the foreseeable future. Verra TCO2s will continue to be eligible for BCT and selectively, NCT as well. Note that Verra credits not already tokenized are not eligible for tokenization and have not been since 2022. All Verra TCO2s will continue to be retirable at any time.
* **Will my existing tokens and assets remain secure during and after the transition?**

  We don't anticipate any impact to the security of your assets.
* **Who will govern and make decisions for the project?**

  There will be no significant changes. We welcome community input on the structure moving forward.
* **What will happen to the bridge to Puro.earth?**

  This will continue to remain operational.
* **How can I get involved in the open source project?**

  Reach out to us on [Discord](https://toucan.earth/discord) or via [GitHub](https://github.com/ToucanProtocol).
* **Will there be any changes to the existing smart contracts?**

  We will be open sourcing our smart contracts. Any maintenance and development of smart contracts will be handled along the same lines as before.
* **Will the code continue to undergo regular audits?**

  Smart contract upgrades and new deployments will continue to be audited.
* **How will security and maintenance be handled going forward?**

  Security and maintenance procedures for smart contracts will be handled along the same lines as before.
* **Will there be any changes to fees or cost structures?**

  No.


# Archives

Welcome to the Archives section of our technical documentation. Here, you'll find previous versions of guides, FAQs, and more. It's a treasure trove of info for those who need to reference older material or track changes over time.

{% hint style="warning" %}
Information in the Archives is NOT up to date, and may include inaccurate details and broken links. The Archives are not actively maintained.
{% endhint %}


# Verra Bridge \[Deprecated]

Below is the historical archive of documentation regarding the deprecated Carbon Bridge to Verra

{% hint style="warning" %}
**Attention:** The Verra Registry currently [does not support the tokenization of carbon credits](https://verra.org/verra-addresses-crypto-instruments-and-tokens/) and this will not be available on the Toucan UI. Read our [official response](https://blog.toucan.earth/response-to-verras-announcement/) to the Verra announcement.
{% endhint %}

***

## Verra Guide to Bridging

### Initialize

Create an empty Batch NFT on Polygon, which will represent a tokenized batch of carbon offsets retired in the source registry.”Attention: Verra Registry currently [does not support the tokenization of carbon credits](https://verra.org/verra-addresses-crypto-instruments-and-tokens/) and this will not be available on the Toucan UI. Verra Registry is currently identifying the safest way forward regarding carbon credit tokenization. Read our [official response](https://blog.toucan.earth/response-to-verras-announcement/) to the Verra announcement.”The bridging process starts on [our dApp](https://app.toucan.earth/overview) with the minting of a [non-fungible token](https://ethereum.org/en/developers/docs/standards/tokens/erc-721): a `BatchNFT`. The `BatchNFT` is in an *initialized* state and doesn't have any offset-specific metadata yet. But it has a *unique identifier,* which is our input for step 2 of the process.You will need a batch NFT for each project and vintage of carbon offsets you want to retire in the source registry. This might mean you need to initialize multiple batches, and provide multiple Toucan IDs in the Retirement Details of different batch retirements.To initialize a batch retirement, [sign in](https://github.com/ToucanProtocol/docs/blob/main/introduction/sign-in.md) and go to the Toucan [Bridge](https://toucan.earth/bridge).

1. 1.Click on "New Retirement".
2. 2.Select which registry you're bridging from — at launch, only Verra is supported.
3. 3.Select whether you have access to the registry, or if a partner will be retiring the offsets on your behalf.
4. 4.Click "Initialize". Metamask will load a pop-up: review and if everything looks good, click "Submit" to sign and broadcast the message to the [Polygon](https://polygon.technology/) network.
5. 5.Within a few seconds, the transaction should be validated. A new page will load with detailed instructions on the next step.

It is very important that you read these instructions carefully! They explain how to retire the batch of offsets you want to bridge in the Verra registry.The interface will include a few pieces of information that you MUST carefully and correctly copy and include when you or your partner retires the batch on Verra.Mistakes here will result in an irrevocable loss of funds!Here is an example of the box showing retirement details on the Toucan Carbon Bridge interface. This appears after the transaction initializing a batch has been validated on [Polygon](https://polygon.technology/)

![](https://2999789225-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me5rkziwb6eXQeWAAwd%2Fuploads%2Fk1Cmj7HMpYC62TnsN8Sp%2FScreen%20Shot%202021-10-17%20at%2015.17.45.png?alt=media\&token=ebb60e2f-0261-4d6b-851f-1083ccd76501)

With these details you're ready to [retire the batch of offsets on Verra ->](https://docs.toucan.earth/toucan/bridge/carbon-bridge/retire-on-verra).

Next, the carbon credits to be tokenized are retired in a traditional carbon registry and the *unique identifier* of the `BatchNFT` is included in the retirement note. By including this unique identifier in the public registry, we create a permanent link between the retirement event and the NFT.

For this step, you need to have a registry account or work with someone who does. If you don't have access to a registry account, you will need to work with someone who does.

**It is critically important that you or the Verra account holder follow these instructions carefully, or you may make mistakes that lead to irrevocable loss of funds / carbon credits, for which** [**Toucan is not liable**](/introduction/legal-disclaimer)**.**

### Retire on Verra

{% hint style="danger" %}
**Caution!!! You must only retire credits from the same project AND vintage in a single retirement.** In no case can you retire credits from different projects or vintages in the same retirement event!

So if you have credits from Project A from 2010 and 2011, **these must be retired in separate events!**

Furthermore, you must include *different Retirement details* for these different retirements. You will need to work with the person buying the credits from you to provide enough [Toucan](https://toucan.earth) retirement details for each retirement.

**DO NOT RETIRE CREDITS FROM DIFFERENT PROJECTS OR VINTAGES IN THE SAME RETIREMENT!!**
{% endhint %}

Next, you'll retire the batch of carbon credits you want to bridge on the Verra registry. It is critical that you include the information provided by Toucan when you submit the retirement, including:

* the Beneficial Owner: the Ethereum address that initiated the batch bridging process,
* the Retirement Reason: "Other",
* the Retirement Detail: a string containing the Toucan batch NFT ID.
* Also check two boxes: `Make Account Name, Beneficial Owner, and Retirement Reason Public` and `Make Retirement Reason Details Public`.
* Include a link to this section — [Instructions for Verra account holders](#instructions-for-verra-account-holders).

{% hint style="info" %}
Notice how the code [Toucan](https://toucan.earth) provides to include as the retirement detail includes a hexadecimal number. This is the transaction hash of the "mint empty batch" transaction, meaning it is connected to the Ethereum address that initiated it, the NFT contract and the token ID.

`TOUCAN-1.0-137-0x39068bed8fc828b4759289af9f91c98a1f1994f450088ba7b49bb6474cff8132-138`

\
<https://polygonscan.com/tx/0x39068bed8fc828b4759289af9f91c98a1f1994f450088ba7b49bb6474cff8132>
{% endhint %}

Including this information in the retirement creates a unique, one-to-one link from the batch retirement in the source registry and the batch NFT on chain.

### Instructions for Verra account holders

1. Log into your Verra account. (If you are using the EMA interface for Verra, that is ok as well).
2. Go into the account where you are holding the credits to be retired In “Transfer Quantity” on the right, input the number of credits to be retired, and check the box for “Add Batch.” DO NOT select credits from different projects, or from the same project but different vintages.
3. Go to the top left and make sure the total number to be retired matches what you inputted, and hit the “Batch Transfer” button.
4. In the retirement interface, select the “Retirement Sub-account” radio button.
5. Input in the exact details provided by Toucan.
6. Check the boxes to make all information public.
7. In the “email notifications” section, make sure to include <retirements@toucan.earth> among the emails you send confirmation to. (**This is important!!**)
8. Send the serial number of the retirement to the person using the Toucan Carbon Bridge.

![Initiating a retirement in the Verra account interface. Project Type and Vintage values MUST be the same to check "Add Batch".](/files/SdzH1Jv28GwpW83zsx5D)

![Input the details provided by Toucan in the appropriate fields here, and check the right boxes!](/files/7AMNJL4jAHirJGGPCmEE)

##

### Submit serial number

Offsets are retired in batches and each retired batch of credits has a unique *serial number* provided by the registry after retirement. For VCS credits, it looks something like this:`0001-000001-000100-VCS-VCU-003-VER-US-0003-01012020-31122020-1`This serial number carries a lot of relevant information, including the *number of offsets*, *certifying standard body*, *project identifier*, *country*, *monitoring period (vintage),* and more. The full taxonomy can be found [here](https://registry.verra.org/pdf/VCU%20Serial%20Number%20Help%20Format.pdf).The next step is to update the `BatchNFT` with this *serial number*. Now the link between the legacy and on-chain registries is complete—the `BatchNFT` is linked to the retirement entry in the legacy registry through the *serial number* and the retirement entry has the NFT's *unique identifier* in its metadata\_.\_ These steps are key because they ensure that double counting / double bridging of carbon offsets is not possible.Furthermore, the *serial number* is used to update the `BatchNFT` with project-specific attributes, some of which are stored on-chain while others are stored as metadata on IPFS. This information will be useful down the line. Submitting the serial number to the `BatchNFT` contract changes the state of the NFT to \_awaits approval.\_We discovered that some retirements (especially those made through EMA) sometimes return multiple serial numbers. You can input these numbers in the interface by clicking `+` to add additional fields.These serial numbers **must** all refer to the same project AND vintage, as described in the [Retire](https://docs.toucan.earth/toucan/bridge/carbon-bridge/retire-on-verra#retire-on-verra) section.

#### Submit <a href="#submit" id="submit"></a>

In order to complete the one-to-one link between the source registry and the on-chain, tokenized carbon offsets, we need to write the serial number we received from Verra on chain. This ensures that every Toucan carbon offset can be easily traced back to the entry in the source registry.

1. From the interface we left at the end of the [Initialize](https://docs.toucan.earth/toucan/bridge/carbon-bridge/initialize) step, click "I have retired my credits" to advance to the next page.
2. Paste the serial number provided by Verra into the text box. Clicking "Confirm serial number" should trigger the app to fetch project details and display them. Inspect this to make sure it all looks accurate!
3. If it all looks accurate, "Submit for approval", review the data in Metamask and click Submit to sign and broadcast the transaction to the network.
4. **Check to make sure that <retirements@toucan.earth> was included in the retirement confirmation email you received from Verra.** If not, forward that email to <retirements@toucan.earth> with the batch NFT token ID in the subject line.

Great! You've completed the first sequence in the bridging process.

### Await approval

”Attention: Verra Registry currently [does not support the tokenization of carbon credits](https://verra.org/verra-addresses-crypto-instruments-and-tokens/) and this will not be available on the Toucan UI. Verra Registry is currently identifying the safest way forward regarding carbon credit tokenization. Read our [official response](https://blog.toucan.earth/response-to-verras-announcement/) to the Verra announcement.”Once the `BatchNFT` is updated with a *serial number*, it needs to be approved by a [Toucan](https://toucan.earth/) Verifier, a trusted member of the [Toucan](https://toucan.earth/) community. This step is required to protect against fraudulent inputs and is dependent on human action and trust, for now. However, there are ways to automate this process in the future, e.g. with a decentralized arbitration service like [Kleros](https://kleros.io/) managing disputes, which we are exploring.Once the correctness of the *serial number* input is confirmed by a [Toucan](https://toucan.earth/) Verifier, the state of the `BatchNFT` changes to *approved* and is now a fully tokenized batch of carbon credits that can be sold on NFT marketplaces or used as collateral in DeFi lending markets 🥳However, for many other use cases—such as sending a fraction of a credit or creating carbon pool tokens—NFTs can be a bit unpractical. This is why we think most users will want to take at least one more step: to fractionalize the batch NFT into fungible TCO2 tokens.

### Fractionalize

#### From a batch NFT to ERC20 carbon tokens.

The bridging process is completed when a [Toucan](https://toucan.earth/) Verifier approves the batch NFT — that means the batch has been successfully tokenized! This NFT is an ERC721 token, which means it is compatible with a range of other NFT protocols on [Polygon](https://polygon.technology/). We're excited to see what people build with these NFTs.However, there's another step required to move towards the Toucan vision of programmable carbon.In the last step of the bridging process, the `BatchNFT` can be used to mint an equivalent number of fully fungible [ERC20 tokens](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) which we call `TCO2` tokens. The "T" here stands for "Toucan" - or "tonne" — or "tokenized" — and 1 `TCO2` token represents 1 carbon credit with a value of 1 [tCO2e](https://coolerfuture.com/en/blog/co2e). So, an NFT representing a batch of 100 credits can be fractionalized into 100 `TCO2` tokens.To fractionalize your *approved* batch NFT, make sure you're [signed in](https://github.com/ToucanProtocol/docs/blob/main/introduction/sign-in.md):

1. Once your batch is Verified, click "Finalize". (This will be available via that "Take action" button on the right of the batch row in the claims interface as well.)
2. Approve the transaction. When it's validated, you'll have TCO2 tokens in your account!

***

## Toucan Statement on HFC-23 VCUs

{% hint style="danger" %}
**Toucan has blocklisted batches from methodology `AM0001` from being sent across the Carbon Bridge or deposited in the Base Carbon Pool.**
{% endhint %}

The [Toucan](https://toucan.earth) Protocol bridges the world's voluntary carbon markets onto public blockchains where open, transparent markets can securely flourish at scale. Healthy carbon markets are a key component to support humanity's efforts to address the climate crisis — climate finance connects planet-positive projects with the capital needed to create ecological impact.

Carbon markets have been evolving over the past decades, with key ecosystem players constantly working to improve the quality and integrity of carbon credits. At times this has meant ceasing to approve carbon credits that were previously valid.

Specifically, in 2014 the Verified Carbon Standard [announced](https://verra.org/phasing-out-hfc-23-projects/) that it would stop issuing credits for projects related to HFC-23, a byproduct of the refrigerant manufacturing process. This decision was based on Verra's [acknowledgement of the misincentives](https://verra.org/major-win-climate-voluntary-market-closes-door-hfc-23-projects/) created by these methodologies. ([9 January Program Update](https://verra.org/wp-content/uploads/2018/03/HFC-23-Program-Update-9-JAN-2014.pdf))

These HFC-23 credits are still active in the Verra registry. It was brought to our attention that these phased-out credits were being bridged after a number of batches constituting \~600,000 tCO2e had been approved. Upon learning that these credits were being bridged, the two projects employing this methodology were immediately blocklisted to prevent further credits from these projects being tokenized. Toucan has also updated the gating criteria of the Base Carbon Pool to prevent these phased out credits being deposited into the pool in return for BCT tokens.

We feel this action is important and justified — our objective is to create a high-integrity carbon market. The Toucan Bridge builds on Verra's role verifying the integrity of carbon credits. Verra's public statements indicating their decision to stop issuing HFC-23 credits in 2014 serves as our basis for blocklisting these credits on the Toucan Bridge without undermining our neutrality. We will not approve any further HFC-23 credit batches over the bridge or the BCT pool.

We are exploring to what degree we need to develop further governance processes to manage risks related to low-integrity credits.

Toucan's overarching objective is to provide infrastructure for a regenerative economy. We believe that care for the Earth should be embedded in the ways we transact value — that planet-positive actions should be the default, not the exception. To get there, we are building open infrastructure and doing everything we can to build and scale in line with our values. After considering this deeply, we feel strongly that this action is warranted, mainly because Verra itself deprecated support for these credits.


# Pool Acceptance Criteria: NCT, BCT

There are two existing pools deployed with Toucan contracts: **NCT** (Nature Carbon Tonne) and **BCT** (Base Carbon Tonne). The acceptance criteria for these pools is as follows:

#### NCT

<details>

<summary>List of approved methodologies</summary>

* VM0003: Methodology for Improved Forest Management through Extension of Rotation Age, V1.2
* VM0004: Methodology for Conservation Programs that Avoid Planned Land Use Conversion in Peat Swamp Forests, v1.0
* VM0005: Methodology for Conversion of Low-productive Forest to High-productive Forest, v1.2
* VM0006: Methodology for Carbon Accounting for Mosaic and Landscape-scale REDD Projects, v2.2
* VM0007: REDD+ Methodology Framework (REDD-MF), v1.6
* VM0009: Methodology for Avoided Ecosystem Conversion, v3.0
* VM0010: Methodology for Improvement Forest Management: Conversion from Logged to Protected Forest, v1.3
* VM0011: Methodology for Calculating GHG Benefits from Preventing Planned Degradation, v1.0
* VM0012: Improved Forest Management in Temperate and Boreal Forests (LtPF), v1.2
* VM0015: Methodology for Avoided Unplanned Deforestation, v1.1
* VM0017: Adoption of Sustainable Agricultural Land Management, v1.0
* VM0021: Soil Carbon Quantification Methodology, v1.0
* VM0024: Methodology for Coastal Wetland Creation, v1.0
* VM0026: Methodology for Sustainable Grassland Management (SGM)
* VM0027: Methodology for Rewetting Drained Tropical Peatlands, v1.0
* VM0029: Methodology for Avoided Forest Degradation through Fire Management, v1.0
* VM0032: Methodology for Adoption for Sustainable Grasslands through Adjustment of Fire and Grazing
* VM0033: Methodology for Tidal Wetland and Seagrass Restoration, v1.0
* VM0034: British Columbia Forest Carbon Offset Methodology, v1.0
* VM0035: Methodology for Improved Forest Management through Reduced Impact Logging, v1.0
* VM0036: Methodology for Rewetting Drained Temperate Peatlands, v1.0
* VM0037: Methodology for Implementation of REDD+ Activities in Landscapes Affected by Mosaic Deforestation and Degradation, v1.0
* VM0042: Methodology for Improved Agricultural Land Management, v1.0
* Also included: AR-AM0001, AR-AM0002, AR-AM0003, AR-AM0004, AR-AM0005, AR-AM0006, AR-AM0007, AR-AM0008, AR-AM009, AR-AM0010, AR-AM0011, AR-AM0012, AR-AM0013, AR-AM0014, AR-AMS0001, AR-AMS0002, AR-AMS0003, AR-AMS0004, AR-AMS0005, AR-AMS0006, AR-AMS0007, AR-ACM0001, AR-ACM0002, AR-ACM0003

</details>

* Exclusion Criteria:
  * Projects using partially or fully the methodology "VM0022: Quantifying N20 Emissions Reductions in Agricultural Crops through Nitrogen Fertilizer Rate Reduction"
  * Projects issuing credits under non-nature based methodologies additionally to nature-based methodologies within the same project scope

{% hint style="info" %}
Read more about the rationale and the approach to choosing the NCT acceptance criteria [here](/resources/archives/nct-pool-party-report)
{% endhint %}

* Earliest Vintage: 01.01.2012

#### BCT

<details>

<summary>List of approved methodologies</summary>

* All Verra-approved methodologies (including Verra Standard Methodologies, CDM, CAR), **excluding** all versions of "**AM0001**: Decomposition of fluoroform (HFC-23) waste streams." Read more about our policy on HFC-23 based credits [here](/resources/archives/verra-bridge-deprecated#toucan-statement-on-hfc-23-vcus).

</details>

* Exclusion Criteria:
  * All versions of "**AM0001**: Decomposition of fluoroform (HFC-23) waste streams." Read more about our policy on HFC-23 based credits [here](/resources/archives/verra-bridge-deprecated#toucan-statement-on-hfc-23-vcus).
* Earliest Vintage: 1.1.2008


# NCT Pool Report

A report detailing the Nature Carbon Tonne criteria design process

{% hint style="warning" %}
**Since April 2023**: The rolling vintage is abandoned in favor of a minimum vintage set at 01.01.2012
{% endhint %}

## NCT: Pool Party Report

{% hint style="success" %}
This report was compiled by [Sarah Baxendell](https://www.linkedin.com/in/sarahashleybaxendell/) of Regen Network, one of the stakeholders involved with the design of the Nature Carbon Pool.
{% endhint %}

**Development Timeline:** October 2021 to February 2022\
**Core methodology developers:** [Toucan](https://toucan.earth/), [Regen Network](https://www.regen.network/), [Moss.Earth](https://moss.earth/), [Joseph Pallant](https://twitter.com/josephpallant) ([Blockchain for Climate Foundation](https://www.blockchainforclimate.org/))\
**Advisors & Stakeholders:** [KlimaDAO](https://www.klimadao.finance/), [BICOWG](https://twitter.com/BICOWG), [StarCB](https://starcb.com/)

#### **Why NCT?**

Nature-based carbon credits are higher quality than non-nature-based carbon credits, because of their intrinsic benefits, including ecological co-benefits (soil quality, water quality, air quality), habitat preservation, species protection, social and economic benefits for communities who engage in carbon credits projects. These credits typically sell for market price premiums, and in more limited vintage quantities, than other forms of carbon credits. Nature is a finite resource.

The digital carbon marketplace will evolve over time, offering indexes that focus on distinct credit types, as a way of utilizing fungible strategies while honoring the uniqueness of different carbon credit types. From this, NCT was born, a fungible representation of nature-based carbon credits held in a carbon pool on the blockchain, so that price discovery for natural world solutions can be explored.

#### **What are the inclusion criteria?**

**Methodologies:** Nature-based carbon credits, excluding [VM022](https://verra.org/methodology/vm0022-quantifying-n2o-emissions-reductions-in-agricultural-crops-through-nitrogen-fertilizer-rate-reduction-v1-1/)

NCT\*-compatible credits have clear and verified ecological benefits, positively affecting our environment from local to global scales.\*

**Vintages:** 2012 and later, with a 10-year rolling acceptance window

*The Pool Party agreed that a rolling acceptance window provided an elegant, governance-minimized way to ensure that eligible credits remain high quality. By starting with 2012, the Nature Carbon Tonne will support significant liquidity for nature based carbon.*

***Standards:*** [Verra](https://verra.org/)

*As the largest and most widely-known carbon standard, Verra was chosen to ensure that on-chain carbon credits inherit the credibility and reputation of the VCS Program. Expanded support for additional respected registries is planned over time.*

#### **How were the inclusion criteria for NCT determined?**

A series of 10 weekly meetings including participation of methodology developers, advisors and stakeholders, were held to explore the edges of the inclusion criteria, and informed the final criteria for NCT as well as launch parameters. In addition to these weekly meetings, a large number of interactions were held synchronously and asynchronously via documents, chats and video calls, to incorporate feedback from various actors to create an inclusion criteria that would best serve the on-chain carbon market.

**Included and excluded methods**

The NCT inclusion criteria (at launch) should align with the list of methodologies that is already accepted by the Open Climate Registry, but only include nature-based methodologies from the Verra Registry.

1. ✅ Included Methods:
   1. VM0003: Methodology for Improved Forest Management through Extension of Rotation Age, V1.2
   2. VM0004: Methodology for Conservation Programs that Avoid Planned Land Use Conversion in Peat Swamp Forests, v1.0
   3. VM0005: Methodology for Conversion of Low-productive Forest to High-productive Forest, v1.2
   4. VM0006: Methodology for Carbon Accounting for Mosaic and Landscape-scale REDD Projects, v2.2
   5. VM0007: REDD+ Methodology Framework (REDD-MF), v1.6
   6. VM0009: Methodology for Avoided Ecosystem Conversion, v3.0
   7. VM0010: Methodology for Improvement Forest Management: Conversion from Logged to Protected Forest, v1.3
   8. VM0011: Methodology for Calculating GHG Benefits from Preventing Planned Degradation, v1.0
   9. VM0012: Improved Forest Management in Temperate and Boreal Forests (LtPF), v1.2
   10. VM0015: Methodology for Avoided Unplanned Deforestation, v1.1
   11. VM0017: Adoption of Sustainable Agricultural Land Management, v1.0
   12. VM0021: Soil Carbon Quantification Methodology, v1.0
   13. VM0024: Methodology for Coastal Wetland Creation, v1.0
   14. VM0026: Methodology for Sustainable Grassland Management (SGM)
   15. VM0027: Methodology for Rewetting Drained Tropical Peatlands, v1.0
   16. VM0029: Methodology for Avoided Forest Degradation through Fire Management, v1.0
   17. VM0032: Methodology for Adoption for Sustainable Grasslands through Adjustment of Fire and Grazing
   18. VM0033: Methodology for Tidal Wetland and Seagrass Restoration, v1.0
   19. VM0034: British Columbia Forest Carbon Offset Methodology, v1.0
   20. VM0035: Methodology for Improved Forest Management through Reduced Impact Logging, v1.0
   21. VM0036: Methodology for Rewetting Drained Temperate Peatlands, v1.0
   22. VM0037: Methodology for Implementation of REDD+ Activities in Landscapes Affected by Mosaic Deforestation and Degradation, v1.0
   23. VM0042: Methodology for Improved Agricultural Land Management, v1.0
   24. Also included: AR-AM0001, AR-AM0002, AR-AM0003, AR-AM0004, AR-AM0005, AR-AM0006, AR-AM0007, AR-AM0008, AR-AM009, AR-AM0010, AR-AM0011, AR-AM0012, AR-AM0013, AR-AM0014, AR-AMS0001, AR-AMS0002, AR-AMS0003, AR-AMS0004, AR-AMS0005, AR-AMS0006, AR-AMS0007, AR-ACM0001, AR-ACM0002, AR-ACM0003
2. ❌ Excluded Methods:
   1. VM0022: Quantifying N20 Emissions Reductions in Agricultural Crops through Nitrogen Fertilizer Rate Reduction, v1.1
      1. Argument: Not necessarily a bad methodology, just not working on the same SSRs (sources, sinks and reservoirs) as projects seeking to keep or increase carbon sequestered in biogenic material.
3. ⚠️ Projects should only utilize nature-based methodologies - ie. if a project uses both a nature-based methodology and a non-nature-based methodology for the same credit issuance, it would not qualify for NCT.

**Vintage year selection**

NCT utilizes a 2012 start date for vintage year requirements. The following pros/cons of start date criteria were explored in determining this vintage start date:

**Selected criteria**:

* ✅ 10-year rolling inclusion criteria, 2012 vintage start date:
  1. Pros
     1. Keeps the carbon high quality and hopefully the price higher, governance-minimized criteria evolution, mimics the commonly enacted progression of vintage/start date eligibility employed by offset systems.
     2. Relatively early start date means 95%+ of nature-based credits to be eligible for the pool, enabling significant liquidity.
  2. Cons
     1. Excludes some vintage years of projects that also have credits for vintages 2008 - 2011.
     2. Early start date reduces attractiveness for newer credits to enter the pool.

**Rejected criteria:**

* ❌ 2008 vintage start date:
  1. Pros
     1. Mirrors current BCT start dates, doesn't exclude older vintages, some projects developed at this time were great.
  2. Cons
     1. Some potential issues with CDM projects starting prior to 2012 regarding financial additionality, older credits could be perceived as low-quality and reduce their value as collateral.
* ❌ 2016 vintage start date with 10 year rolling window:
  1. Pros
     1. Follows CORSIA criteria, as newer vintages are included the likelihood that the prices of these credits are higher goes up.
     2. Increases differentiation between NCT and BCT whilst allowing for over 60% of available nature-based credits to be eligible for the pool.
  2. Cons
     1. Excludes many vintage years of projects that also have credits for vintages 2008 -2015, reducing liquidity.

1. ❌ 2012 vintage start date, no rolling inclusion criteria:
   1. Pros
      1. Reflects more closely the vintages that are available for purchase in the over-the-counter marketplaces (ie. many older vintages are sold out), as newer vintages are included the likelihood that the prices of these credits are higher goes up, Matches MOSS.earth's criteria for MCO2.
   2. Cons
      1. Excludes many vintage years of projects that also have credits for vintages 2008 - 2011 and early start date decreases price differentiation with $BCT and reduces attractiveness for newer credits to enter the pool.

#### Supporting Data

![](/files/TY3YH9RXnHP3r9mRstto)

![](/files/GwlQWVPv9m22cx3Lx2uJ)


# Audits

At Toucan we value security. Consequently, we have worked with numerous experienced blockchain developers for peer-reviews and have requested smart contract audits of our code.

For minor contract upgrades we rely on the same security companies we have been working with closely in order to get the changes reviewed pre-upgrade.

### Audits

* [Whole Protocol Pre-Launch, Byterocket, October 2021](https://byterocket.com/audit/toucan-protocol)
* [NCT Pool, Byterocket, February 2022](https://byterocket.com/audit/toucan-nct)
* [Retirement Certificates, Byterocket, June 2022](https://byterocket.com/audit/toucan-protocol-retirement-certificates)
* [Cross-Chain Pool Bridge, Team Omega, July 2022](https://gateway.pinata.cloud/ipfs/QmYBKAjhcvuPKyxCnsmC2ArfXUkfHj8wT76wV8BuJP3E1Z)


# Toucan for developers

## Welcome to Toucan

These docs will help you get up and building with Toucan's digital carbon market infrastructure. Begin by drawing inspiration from our range of [integration examples](/developers/tools-+-examples/integration-examples).

{% hint style="info" %}
To understand how Toucan works, read about our [Carbon Bridge](/toucan/carbon-bridge), [Carbon Pools](/toucan/carbon-pools) and [Retirements](/toucan/retire-credits). To get a broader background understanding, read our resources on [Web3](/resources/interacting-with-smart-contracts) and [Carbon Markets](/resources/carbon-markets).
{% endhint %}

### Ready to start building?

Dive into our technical resources.

* Check out our [**smart contracts**](/developers/smart-contracts) and get some **tokens** at our [**faucet**](/developers/tools-+-examples/faucet) to play around with Toucan's tooling on a testnet. (We recommend using local forks in your testing environment when developing on Toucan.)
* Also check out our **developer tools** like our [**Toucan SDK**](/developers/sdk/quickstart) and find out how you can easily integrate retirement of carbon credits with our [**OffsetHelper**](/developers/smart-contracts/offset-helper).
* You want to start building with the **rich data** Toucan can offer? Explore our Subgraphs through the [API endpoints](/developers/subgraph#api-endpoints) or [playground](/developers/subgraph#playground).

### New to Web3?

Toucan is built using blockchains and smart contracts — advanced digital tools that enable us to offer improved transparency, liquidity and efficiency to the carbon market. The Web3 developer experience is a bit different to common patterns found elsewhere. To understand how to build in Web3, we recommend reading the [Ethereum docs](https://ethereum.org/en/learn/).


# Smart contracts

This section will walk you through the functions of the core smart contracts you're likely to interact with.

If you need to see where the contract are deployed, you can find addresses and ABIs [here ->](https://app.toucan.earth/contracts)

If you'd like to see the source code of the contracts, you can find it [here ->](https://github.com/ToucanProtocol/contracts). You'll also find `.json` artifacts in this repository. Do keep in mind that our contracts actually live in a different (private) repository — the linked repo is a delayed mirror of it.

{% hint style="success" %}
In the EVM, Ether and token amounts are often converted into (much) smaller standard units, to allow the use of sub-integer amounts.

Toucan's token contracts use 18 decimals, which means whenever a number of tokens is referenced, the value is converted by multiplying the quantity by 1e+18. This standard unit helps in dealing with very small amounts and avoids floating point operations. Always remember to convert for accuracy in transactions.
{% endhint %}


# Carbon pool contracts

All carbon pools have the same standard functions

Toucan's Carbon Pool smart contracts extend the ERC20 standard — carbon reference tokens are ERC20 tokens. Pool contracts are upgradeable. Contract addresses for deployed carbon pools can be found at [app.toucan.earth/contracts](https://app.toucan.earth/contracts).

### calculateDepositFees

```solidity
function calculateDepositFees(address tco2, uint256 amount) external view returns (uint256 feeDistributionTotal)
```

View function to calculate deposit fees pre-execution

*User specifies in front-end the address and amount they want*

#### Parameters

| Name   | Type    | Description           |
| ------ | ------- | --------------------- |
| tco2   | address | TCO2 contract address |
| amount | uint256 | Amount to redeem      |

#### Return Values

| Name                 | Type    | Description                 |
| -------------------- | ------- | --------------------------- |
| feeDistributionTotal | uint256 | Total fee amount to be paid |

### calculateRedemptionOutFees

```solidity
function calculateRedemptionOutFees(address[] tco2s, uint256[] amounts, bool toRetire) external view returns (uint256 feeDistributionTotal)
```

View function to calculate fees pre-execution, according to the amounts of TCO2 to be redeemed.

#### Parameters

| Name     | Type       | Description                                                                                                                                        |
| -------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| tco2s    | address\[] | Array of TCO2 contract addresses                                                                                                                   |
| amounts  | uint256\[] | Array of TCO2 amounts to redeem The indexes of this array are matching 1:1 with the tco2s array.                                                   |
| toRetire | bool       | Whether the TCO2s will be retired atomically with the redemption. It may be that lower fees will be charged in this case. Currently not supported. |

#### Return Values

| Name                 | Type    | Description                 |
| -------------------- | ------- | --------------------------- |
| feeDistributionTotal | uint256 | Total fee amount to be paid |

### checkEligible

```solidity
function checkEligible(address vintageToken) external view virtual returns (bool isEligible)
```

Checks if token to be deposited is eligible for this pool. Reverts if not. Beware that the revert reason might depend on the underlying implementation of IPoolFilter.checkEligible

#### Parameters

| Name         | Type    | Description           |
| ------------ | ------- | --------------------- |
| vintageToken | address | the contract to check |

#### Return Values

| Name       | Type | Description                                           |
| ---------- | ---- | ----------------------------------------------------- |
| isEligible | bool | true if address is eligible and no other issues occur |

### deposit

```solidity
function deposit(address tco2, uint256 amount, uint256 maxFee) external returns (uint256 mintedPoolTokenAmount)
```

Deposit function for pool that accepts TCO2s and mints pool token 1:1

*Eligibility of the ERC20 token to be deposited is checked via `checkEligible`*

#### Parameters

| Name   | Type    | Description                                                                                                                                                                                                                                                                                     |
| ------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| tco2   | address | TCO2 to be deposited. The pool contract needs to be approved in the TCO2 contract by the caller in order to allow the transfer of TCO2 tokens to the pool                                                                                                                                       |
| amount | uint256 | Amount of TCO2 to be deposited                                                                                                                                                                                                                                                                  |
| maxFee | uint256 | Maximum fee to be paid for the deposit. This value cannot be zero. Use `calculateDepositFees(tco2,amount)` to determine the fee that will be charged given the state of the pool during this call. Add a buffer on top of the returned fee amount up to the maximum fee you are willing to pay. |

#### Return Values

| Name                  | Type    | Description                                |
| --------------------- | ------- | ------------------------------------------ |
| mintedPoolTokenAmount | uint256 | Amount of pool tokens minted to the caller |

### redeemOutMany

```solidity
function redeemOutMany(address[] tco2s, uint256[] amounts, uint256 maxFee) external virtual returns (uint256 poolAmountSpent)
```

Redeem TCO2s for pool tokens 1:1 minus fees The amounts provided are the exact amounts of TCO2s to be redeemed.

#### Parameters

| Name    | Type       | Description                                                                                                                                                                                                                                                                                                      |
| ------- | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| tco2s   | address\[] | Array of TCO2 contract addresses                                                                                                                                                                                                                                                                                 |
| amounts | uint256\[] | Array of TCO2 amounts to redeem The indexes of this array are matching 1:1 with the tco2s array.                                                                                                                                                                                                                 |
| maxFee  | uint256    | Maximum fee to be paid for the redemption. This value cannot be zero. Use `calculateRedemptionOutFees(tco2s,amounts,false)` to determine the fee that will be charged given the state of the pool during this call. Add a buffer on top of the returned fee amount up to the maximum fee you are willing to pay. |

#### Return Values

| Name            | Type    | Description                                   |
| --------------- | ------- | --------------------------------------------- |
| poolAmountSpent | uint256 | The amount of pool tokens spent by the caller |


# TCO2 contracts

TCO2 tokens represents tokenized carbon credits

A separate TCO2 contract is created for each different vintage issuance. Each token contract has the same standard functions, extends ERC20, and is upgradeable.

Find out more about how we name TCO2s in the [Carbon Rosetta Stone](https://toucan-protocol.notion.site/Carbon-Rosetta-Stone-Standard-Attributes-DB-bb0bb434bf6c4661b45155a84d192e22?p=337ff61399244063aee2b4e2e4dca9bb\&pm=s).

Currently, we support TCO2s for two different carbon registries, [Puro](https://puro.earth/) and [Verra](https://verra.org/), each with a varying degree of functionality documented below.

### getAttributes

Function to get corresponding attributes from the carbon project vintage that is represented by this TCO2 contract.

```solidity
function getAttributes() public view virtual returns (ProjectData memory, VintageData memory);
```

The return values are tuples — below you can find the definitions of the `ProjectData` & `VintageData` structs.

```solidity
struct ProjectData {
    string projectId;
    string standard;
    string methodology;
    string region;
    string storageMethod;
    string method;
    string emissionType;
    string category;
    string uri;
    address beneficiary;
}

struct VintageData {
    /// @dev A human-readable string which differentiates this from other vintages in
    /// the same project, and helps build the corresponding TCO2 name and symbol.
    string name; // the vintage year
    uint64 startTime; // UNIX timestamp
    uint64 endTime; // UNIX timestamp
    uint256 projectTokenId;
    uint64 totalVintageQuantity;
    bool isCorsiaCompliant;
    bool isCCPcompliant;
    string coBenefits;
    string correspAdjustment;
    string additionalCertification;
    string uri;
    string registry;
}
```

## Puro

The integration with Puro is achieved through a two-way bridge, where state is synced between the registry and onchain. For more high-level info on the Puro bridge read [here](/toucan/carbon-bridge/puro-carbon-bridge).

To ensure a robust sync between the Puro offchain registry and the Toucan onchain contracts, our Puro TCO2 contracts use an escrow contract to hold TCO2s temporarily. The TCO2s are escrowed on every detokenization or retirement request, until the request is completed in the registry, before it can be finalized onchain.

Developers only need to care about creating the request with one of the functions documented below, then it's up to Toucan to finalize the request. In the future, we envision deprecating the admin functionality to process requests offchain and finalize onchain with the use of oracles.

### requestDetokenization

```solidity
function requestDetokenization(uint256[] tokenIds, uint256 amount) external returns (uint256 requestId)
```

Request a detokenization of batch-NFTs. The amount of TCO2 to detokenize will be transferred from the user to an escrow contract. The detokenization request will be processed asynchronously by Toucan so callers should monitor the status of the request by listening to the DetokenizationFinalized and DetokenizationReverted events.

*This function is permissionless and can be called by anyone with enough TCO2 to detokenize*

#### Parameters

| Name       | Type        | Description                                                                                                                                                                                              |
| ---------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tokenIds` | `uint256[]` | Token IDs of one or more batches to detokenize                                                                                                                                                           |
| `amount`   | `uint256`   | The amount of TCO2 to detokenize, must be greater than zero and equal to or smaller than the total amount of the batches (and also greater then the total amount of all the batches except the last one) |

#### Return Values

| Name        | Type      | Description                                  |
| ----------- | --------- | -------------------------------------------- |
| `requestId` | `uint256` | The ID of the request in the escrow contract |

### requestRetirement

```solidity
function requestRetirement(struct CreateRetirementRequestParams params) external returns (uint256 requestId)
```

Request a retirement of TCO2s from batch-NFTs. The amount of TCO2s to retire will be transferred from the user to an escrow contract. The retirement request will be processed asynchronously by Toucan so callers should monitor the status of the request by listening to the RetirementFinalized and RetirementReverted events.

*This function is permissionless and can be called by anyone with enough TCO2 to retire*

#### Parameters

| Name     | Type                                   | Description                                                                                                                                                                                                              |
| -------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `params` | struct `CreateRetirementRequestParams` | The parameters of the retirement request:                                                                                                                                                                                |
|          |                                        | - **`uint256[] tokenIds`**: One or more batches to retire                                                                                                                                                                |
|          |                                        | - **`uint256 amount`**: The amount of TCO2 to retire; must be greater than zero and equal to or smaller than the total amount of the batches (and also greater than the total amount of all batches except the last one) |
|          |                                        | - **`string retiringEntityString`**: An identifiable string for the retiring entity, e.g., their name                                                                                                                    |
|          |                                        | - **`address beneficiary`**: The address of the beneficiary of the retirement                                                                                                                                            |
|          |                                        | - **`string beneficiaryString`**: An identifiable string for the beneficiary, e.g., their name                                                                                                                           |
|          |                                        | - **`string retirementMessage`**: A message to include in the retirement certificate                                                                                                                                     |
|          |                                        | - **`string beneficiaryLocation`**: The location of the beneficiary of the retirement                                                                                                                                    |
|          |                                        | - **`string consumptionCountryCode`**: The country code of the consumption location                                                                                                                                      |
|          |                                        | - **`uint256 consumptionPeriodStart`**: The start of the consumption period, in seconds since the epoch                                                                                                                  |
|          |                                        | - **`uint256 consumptionPeriodEnd`**: The end of the consumption period, in seconds since the epoch                                                                                                                      |

#### Return Values

| Name        | Type      | Description                                  |
| ----------- | --------- | -------------------------------------------- |
| `requestId` | `uint256` | The ID of the request in the escrow contract |

## Verra

[Note that the Verra bridge does not support bringing new credits onchain anymore](/resources/archives/verra-bridge-deprecated). Nevertheless for existing Verra credits, we support direct onchain retirements, which can be executed using any of the functions documented below.

### retire

To retire a given amount of CO2 tons. The credits are permanently removed from circulation — this achieves the offset. This also emits a `Retired` event.

```solidity
function retire(uint256 amount) public virtual returns (uint256 retirementEventId);
```

#### Params

| Name     | Type      | Description                     |
| -------- | --------- | ------------------------------- |
| `amount` | `uint256` | Amount of TCO2 tokens to retire |

#### Return values

| Name                | Type      | Description                                                                                                                                            |
| ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `retirementEventId` | `uint256` | The ID of the event emitted upon retirement. Can be used later to mint [`RetirementCertificates`](/developers/smart-contracts/retirement-certificates) |

### retireFrom

Achieves similar functionality as `retire()`, but instead of retiring from the caller's address, it does so from the provided address. This allow for pools or third party contracts to retire for the user.

{% hint style="info" %}
This function requires the user to approve the third party from the TCO2 contract.
{% endhint %}

```solidity
function retireFrom(address account, uint256 amount) external virtual returns (uint256 retirementEventId);
```

#### Params

| Name      | Type      | Description                     |
| --------- | --------- | ------------------------------- |
| `account` | `address` | Address from which to retire    |
| `amount`  | `uint256` | Amount of TCO2 tokens to retire |

#### Return values

| Name                | Type      | Description                                                                                     |
| ------------------- | --------- | ----------------------------------------------------------------------------------------------- |
| `retirementEventId` | `uint256` | The ID of the event emitted upon retirement. Can be used later to mint `RetirementCertificates` |

### retireAndMintCertificate

Retires an amount of TCO2 tokensand mints a certificate, passing the `retirementEventId`. The information provided is set in the `RetirementCertificate` NFT.

{% hint style="warning" %}
**Note:** This information is publicly written to the blockchain in plaintext.
{% endhint %}

```solidity
function retireAndMintCertificate(
    string calldata retiringEntityString,
    address beneficiary,
    string calldata beneficiaryString,
    string calldata retirementMessage,
    uint256 amount
) external virtual;
```

#### Params

| Name                   | Type      | Description                                                      |
| ---------------------- | --------- | ---------------------------------------------------------------- |
| `retiringEntityString` | `string`  | An identifiable string for the retiring entity, e.g., their name |
| `beneficiary`          | `address` | The address of the beneficiary of the retirement                 |
| `beneficiaryString`    | `string`  | An identifiable string for the beneficiary, e.g., their name     |
| `retirementMessage`    | `string`  | A message to be included in the retirement certificate           |
| `amount`               | `uint256` | The amount to retire and issue an NFT certificate for            |

### mintCertificateLegacy

This function mints a `RetirementCertificate` NFT based on the legacy retirement functionality. **This function is used only for backwards-compatibility reasons**. (In case you retired before the `RetirementCertificates` NFT was introduced, but still want the NFT.)

{% hint style="info" %}
**Some context:** before the `RetirementCertificates` NFT was introduced, retirements didn't emit the `Retired` event. How much an address/entity had retired was stored solely in a mapping (`mapping(address => uint256) public retiredAmount;`).

* **This is relevant for retirements performed before Block 27360444 on Polygon**
* **All retirements on Celo are compatible with `RetirementCertificates`**
  {% endhint %}

Going forward users should mint NFT either directly in the `RetirementCertificates` contract or using the `retireAndMintCertificate()` function above.

```solidity
function mintCertificateLegacy(
    string calldata retiringEntityString,
    address beneficiary,
    string calldata beneficiaryString,
    string calldata retirementMessage
) external;
```

#### Params

| Name                   | Type      | Description                                                      |
| ---------------------- | --------- | ---------------------------------------------------------------- |
| `retiringEntityString` | `string`  | An identifiable string for the retiring entity, e.g., their name |
| `beneficiary`          | `address` | The address of the beneficiary of the retirement                 |
| `beneficiaryString`    | `string`  | An identifiable string for the beneficiary, e.g., their name     |
| `retirementMessage`    | `string`  | A message to be included in the retirement certificate           |


# Retirement certificates

## Retirement certificates

The `RetirementCertificates` contract lets users mint NFTs that act as *proof of retirement*. These NFTs display how many TCO2 tokens a user has retired, along with retirement details such as the beneficiary of the retirement and a message. This contract extends ERC721 and is upgradeable.

Note that minting NFTs directly via the `RetirementCertificates` contract is only supported for Verra retirements. For Puro retirements, users can only [request a retirement](/developers/smart-contracts/tco2#requestretirement) that will then need to be processed by Toucan offchain in the Puro registry, before finalizing onchain by minting the certificate to the retirer.

If you are interested in building on top of Puro retirements, we recommend using [fractional retirements](#fractional-retirements) as that model can accommodate sub-tonnage retirement use cases.

#### mintCertificate

Mints a new `RetirementCertificates` NFT based on existing `Retired` events. The function can either be called by a valid `TCO2` contract (in its `retireAndMintCertificate()` function), or by a user who owns `Retired` events.

{% hint style="warning" %}
**Note:** This information is publicly written to the blockchain in plaintext.
{% endhint %}

```solidity
function mintCertificate(
  address retiringEntity,
  string calldata retiringEntityString,
  address beneficiary,
  string calldata beneficiaryString,
  string calldata retirementMessage,
  uint256[] calldata retirementEventIds
) external;
```

**Params**

| Name                   | Type        | Description                                                                   |
| ---------------------- | ----------- | ----------------------------------------------------------------------------- |
| `retiringEntity`       | `address`   | The entity that has retired TCO2 and is eligible to mint an NFT               |
| `retiringEntityString` | `string`    | An identifiable string for the retiring entity, e.g. their name               |
| `beneficiary`          | `address`   | The address of the beneficiary to set in the NFT                              |
| `beneficiaryString`    | `string`    | An identifiable string for the beneficiary to set in the NFT, e.g. their name |
| `retirementMessage`    | `string`    | A retirement message to be set in the NFT                                     |
| `retirementEventIds`   | `uint256[]` | An array with with event IDs to associate with the NFT                        |

#### attachRetirementEvents

This function allows you to attach the `Retired` events to a `RetirementCertificates` NFT.

For context, if you go back to the [TCO2 contract docs](/developers/smart-contracts/tco2) you will see that you are able to retire TCO2 without minting a `RetirementCertificates`, but you do get a `retirementEventId`.

This allows you to update the amount in an existent `RetirementCertificates` NFT with new retirements.

```solidity
function attachRetirementEvents(
  uint256 tokenId,
  uint256[] calldata retirementEventIds
) external;
```

**Params**

| Name                 | Type        | Description                                                   |
| -------------------- | ----------- | ------------------------------------------------------------- |
| `tokenId`            | `uint256`   | The ID of the `RetirementCertificate` NFT to attach events to |
| `retirementEventIds` | `uint256[]` | An array with with event IDs to associate with the NFT        |

#### getUserEvents

Fetches all the `Retired` events that a given user owns.

```solidity
function getUserEvents(address user)external view returns (uint256[] memory);
```

**Params**

| Name   | Type      | Description                                           |
| ------ | --------- | ----------------------------------------------------- |
| `user` | `address` | The address of the user for whom to fetch all events. |

**Return Values**

| Name                 | Type        | Description                                    |
| -------------------- | ----------- | ---------------------------------------------- |
| `retirementEventIds` | `uint256[]` | The IDs of the events owned by the given user. |

#### updateCertificate

This function allows you to update the `retirementMessage`, `beneficiary`, and `beneficiaryString` of a `RetirementCertificates` NFT **within 24 hours of creation**. Empty param values are ignored, and will **not** overwrite the existing stored values in the NFT.

```solidity
function updateCertificate(
  uint256 tokenId,
  string calldata retiringEntityString,
  address beneficiary,
  string calldata beneficiaryString,
  string calldata retirementMessage
) external;
```

**Params**

| Name                   | Type      | Description                                                                   |
| ---------------------- | --------- | ----------------------------------------------------------------------------- |
| `tokenId`              | `uint256` | The ID of the `RetirementCertificates` NFT to update                          |
| `retiringEntityString` | `string`  | An identifiable string for the retiring entity, e.g. their name               |
| `beneficiary`          | `address` | The address of the beneficiary to set in the NFT                              |
| `beneficiaryString`    | `string`  | An identifiable string for the beneficiary to set in the NFT, e.g. their name |
| `retirementMessage`    | `string`  | A retirement message to be set in the NFT                                     |

#### getRetiredAmount

This function returns the amount of TCO2 tokens retired by a user that's associated with a given `RetirementCertificates` NFT. The function sums up all the retirement amounts from all of event IDs attached to the RetirementCertificate.

```solidity
function getRetiredAmount(uint256 tokenId) external view returns (uint256);
```

**Params**

| Name      | Type      | Description                                                        |
| --------- | --------- | ------------------------------------------------------------------ |
| `tokenId` | `uint256` | The ID of the `RetirementCertificates` NFT to fetch the amount for |

**Return Values**

| Name     | Type      | Description                                                      |
| -------- | --------- | ---------------------------------------------------------------- |
| `amount` | `uint256` | The amount of retired TCO2 tokens associated with that `tokenId` |

## Fractional retirements

{% hint style="info" %}
Fractional retirements are currently supported only on Base Sepolia
{% endhint %}

The Puro registry supports retirements only of tonne denominations, hence we have extended our protocol to support franctionalizing retirement certificate NFTs so we can enable sub-tonnage retirement use cases. There are two new contracts involved in fractionalizing a `RetirementCertificates` NFT:

* `RetirementCertificateFractionalizer`, an ERC1155 contract that fractionalizes certificates and keeps track of fractional balances. These balances represent the **right to mint** a fractional retirement certificate, they are **not an environmental claim**
* `RetirementCertificateFractions`, an ERC721 contract that is used to mint fractional retirement certificates. Minting such a certificate can only be done by an account that holds or has been approved to use `RetirementCertificateFractionalizer` balance. In order to mint a fractional certificate, the equivalent amount of `RetirementCertificateFractionalizer` balance is burnt

### How to fractionalize a certificate

On a high level, Alice has to retire a Puro TCO2 on behalf of `RetirementCertificateFractionalizer`. Alice can then send her `RetirementCertificates` NFT to the `RetirementCertificateFractionalizer`. The act of transferring a `RetirementCertificates` NFT to the fractionalizer plus the fact that the fractionalizer is set as the beneficiary of the certificate allows the fractionalizer to mint an ERC1155 balance to Alice.

Alice can then list her ERC1155 balance on any NFT marketplace from where it can be bought by whomever needs to do a fractional retirement. We invite the community to come up with novel mechanisms to buy and sell `RetirementCertificateFractionalizer` liquidity.

Concretely:

{% tabs %}
{% tab title="via the dApp" %}

1. Request a retirement by using any available TCO2 balance in the `My Carbon Assets` section and include the following information:
   * **`Beneficiary wallet address`**: Set this to the address of the `RetirementCertificateFractionalizer` (found in the [`Contracts`](https://app.toucan.earth/contracts) page – ensure the correct network tab is selected).
   * **`Beneficiary name or organization name`**: Set this to the output of `RetirementCertificateFractionalizer.beneficiaryString()`, formatted as `TOUCAN-2.0-RCS-[CHAIN_ID]`, where `[CHAIN_ID]` represents the chain ID of the current chain.
2. Once the retirement is finalized by Toucan, transfer the newly minted `RetirementCertificates` NFT to the `RetirementCertificateFractionalizer` contract. The transfer should mint the equivalent amount of ERC1155 balance to your account.
   {% endtab %}

{% tab title="via smart contract" %}

1. Request a retirement by calling [`TCO2.requestRetirement`](/developers/smart-contracts/tco2#requestretirement) and include the following information:
   * **`beneficiary`**: Set this to the address of the `RetirementCertificateFractionalizer` (found in the [`Contracts`](https://app.toucan.earth/contracts) page – ensure the correct network tab is selected).
   * **`beneficiaryString`**: Set this to the output of `RetirementCertificateFractionalizer.beneficiaryString()`, formatted as `TOUCAN-2.0-RCS-[CHAIN_ID]`, where `[CHAIN_ID]` represents the chain ID of the current chain.
2. Once the retirement is finalized by Toucan, transfer the newly minted `RetirementCertificates` NFT to the `RetirementCertificateFractionalizer` contract. The transfer should mint the equivalent amount of ERC1155 balance to your account.
   {% endtab %}
   {% endtabs %}

{% hint style="info" %}
Each `RetirementCertificateFractionalizer` token id maps to the respective `CarbonProjectVintages` token id on the same chain.
{% endhint %}

### How to retire fractional balance

{% hint style="info" %}
You can acquire `RetirementCertificateFractionalizer` balance on Base Sepolia [via OpenSea](https://testnets.opensea.io/collection/retirement-certificate-fractionalizer-base-sepolia).
{% endhint %}

Once you hold `RetirementCertificateFractionalizer` balance, you can retire it and mint a `RetirementCertificateFractions` NFT by calling `mintFraction` on the fractionalizer contract.

### RetirementCertificateFractionalizer

#### FractionRequestData

```solidity
struct FractionRequestData {
  uint256 amount;
  uint256 projectVintageTokenId;
  address beneficiary;
  string beneficiaryString;
  string retirementMessage;
  string beneficiaryLocation;
  string consumptionCountryCode;
  uint256 consumptionPeriodStart;
  uint256 consumptionPeriodEnd;
  string tokenURI;
  bytes extraData;
}
```

#### mintFraction

```solidity
function mintFraction(struct FractionRequestData params) external returns (uint256 fractionTokenId)
```

Mint a fraction of a retirement certificate, from the balance of the caller

**Parameters**

| Name     | Type                         | Description                              |
| -------- | ---------------------------- | ---------------------------------------- |
| `params` | struct `FractionRequestData` | The request data of the fraction to mint |

**Return Values**

| Name              | Type      | Description                                                  |
| ----------------- | --------- | ------------------------------------------------------------ |
| `fractionTokenId` | `uint256` | The id of the minted fraction NFT, in the fractions contract |

#### mintFractionFrom

```solidity
function mintFractionFrom(address from, struct FractionRequestData params) public returns (uint256 fractionTokenId)
```

Mint a fraction of a retirement certificate, from the balance of the listing owner

**Parameters**

| Name     | Type                         | Description                                        |
| -------- | ---------------------------- | -------------------------------------------------- |
| `from`   | `address`                    | The owner of the balance to mint the fraction from |
| `params` | struct `FractionRequestData` | The request data of the fraction to mint           |

**Return Values**

| Name              | Type      | Description                                                  |
| ----------------- | --------- | ------------------------------------------------------------ |
| `fractionTokenId` | `uint256` | The id of the minted fraction NFT, in the fractions contract |


# OffsetHelper

The OffsetHelper contract simplifies the carbon offsetting (retirement) process.

The OffsetHelper is a peripheral contract that simplifies the experience of buying and redeeming carbon reference tokens and retiring TCO2 tokens. The contract lives in this [repository](https://github.com/ToucanProtocol/OffsetHelper).

In more exact terms, the OffsetHelper abstracts the process of retiring TCO2, which normally looks like so:

* user exchanges USDC for BCT/NCT tokens at one of the DEXs (Uniswap, Sushiswap, etc. depending on network)
* user interacts with the BCT/NCT token contract to redeem the tokens for TCO2
* user interacts with the TCO2 token contract to retire the TCO2

With the OffsetHelper contract, the user only needs to interact with the OffsetHelper contract, which will take care of the rest of the contract calls in a single transaction.

{% hint style="info" %}
In these methods, "auto" refers to the fact that these methods use `autoRedeem()` in order to automatically choose a TCO2 token corresponding to the oldest tokenized carbon project in the specified token pool. There are no fees incurred by the user when using `autoRedeem()`, i.e., the user receives 1 TCO2 token for each carbon reference token e.g., NCT redeemed.
{% endhint %}

{% hint style="warning" %}
Testing the OffsetHelper on testnet may lead to an `Error: execution reverted` as the OffsetHelper depends on available liquidity in some DEX pools, which can not always be guaranteed.
{% endhint %}

## Approvals

The OffsetHelper is a smart contract that calls other smart contracts. As a security measure, users need to `approve` the OffsetHelper contract address, so the other smart contracts accept interactions routed through this address.&#x20;

{% hint style="success" %}
**Note:** you must approve the pool contract in the TCO2 token that is to be deposited in order for the pool to be able to transfer the TCO2 on your behalf.
{% endhint %}

## Accepted tokens

| Chain   | Tokens                   |
| ------- | ------------------------ |
| Celo    | `cUSD`, `WETH`, `USDC`   |
| Polygon | `USDC`, `WETH`, `WMATIC` |

## Functions

### autoOffsetExactOutToken

```solidity
function autoOffsetExactOutToken(address _fromToken, address _poolToken, uint256 _amountToOffset) public returns (address[] tco2s, uint256[] amounts)
```

Retire carbon credits using the oldest TCO2 tokens available from the specified Toucan token pool by sending ERC20 tokens (cUSD, USDC, WETH, WMATIC).&#x20;

The `view` helper function [`calculateNeededTokenAmount()`](#calculateneededtokenamount) should be called before using `autoOffsetExactOutToken()`, to determine how many native tokens (e.g., MATIC) must be sent to the `OffsetHelper` contract in order to retire the specified amount of TCO2 tokens.

This function:

1. Swaps the ERC20 token sent to the contract for the specified carbon reference token
2. Redeems the reference tokens received for the lowest quality TCO2 tokens available
3. Retires the TCO2 tokens

{% hint style="success" %}
**Note:** The user must approve the ERC20 token that will be used for the swap.
{% endhint %}

#### Parameters

| Name              | Type      | Description                                                                                            |
| ----------------- | --------- | ------------------------------------------------------------------------------------------------------ |
| `_fromToken`      | `address` | The address of the ERC20 token that the user will use to swap (e.g., `cUSD`, `USDC`, `WETH`, `WMATIC`) |
| `_poolToken`      | `address` | The address of the carbon reference token that the user wants to redeem, e.g., NCT                     |
| `_amountToOffset` | `uint256` | The amount of TCO2 to retire                                                                           |

#### Return Values

| Name      | Type        | Description                                             |
| --------- | ----------- | ------------------------------------------------------- |
| `tco2s`   | `address[]` | An array of the TCO2 addresses that were redeemed       |
| `amounts` | `uint256[]` | An array of the amounts of each TCO2 that were redeemed |

### autoOffsetExactInToken

```solidity
function autoOffsetExactInToken(address _fromToken, address _poolToken, uint256 _amountToSwap) public returns (address[] tco2s, uint256[] amounts)
```

Retire carbon credits using the oldest TCO2 tokens available from the specified Toucan carbon pool by swapping ERC20 tokens (`cUSD`, `USDC`, `WETH`, `WMATIC`). All of provided "`in`" token is consumed for retirement.

The `view` helper function [`calculateExpectedPoolTokenForToken()`](#calculateexpectedpooltokenfortoken) can be used to calculate the expected amount of TCO2s that will be offset using `autoOffsetExactInToken()`.

This function:

1. Swaps the ERC20 token sent to the contract for the specified carbon reference token
2. Redeems the reference token for the lowest quality TCO2 tokens available
3. Retires the TCO2 tokens

{% hint style="success" %}
**Note:** The client must approve the ERC20 token that is sent to the contract.
{% endhint %}

#### Parameters

| Name            | Type      | Description                                                                                             |
| --------------- | --------- | ------------------------------------------------------------------------------------------------------- |
| `_fromToken`    | `address` | The address of the ERC20 token that the user sends (e.g., `cUSD`, `USDC`, `WETH`, `WMATIC`)             |
| `_poolToken`    | `address` | The address of the carbon reference token to offset                                                     |
| `_amountToSwap` | `uint256` | The amount of ERC20 token to swap into carbon reference token. Full amount will be used for retirement. |

#### Return Values

| Name      | Type        | Description                                             |
| --------- | ----------- | ------------------------------------------------------- |
| `tco2s`   | `address[]` | An array of the TCO2 addresses that were redeemed       |
| `amounts` | `uint256[]` | An array of the amounts of each TCO2 that were redeemed |

### autoOffsetExactOutETH

```solidity
function autoOffsetExactOutETH(address _poolToken, uint256 _amountToOffset) public payable returns (address[] tco2s, uint256[] amounts)
```

Retire carbon credits using the oldest TCO2 tokens available from the specified Toucan token pool by sending native tokens e.g., MATIC.

{% hint style="danger" %}
**Note:** While this method refers to "ETH", it actually refers to the blockchain's native token, and will use WMATIC on Polygon.
{% endhint %}

The `view` helper function `calculateNeededETHAmount()` should be called before using `autoOffsetExactOutETH()`, to determine how much native tokens e.g., MATIC must be sent to the `OffsetHelper` contract in order to retire the specified amount of carbon.

This function:

1. Swaps the native token e.g. MATIC sent to the contract for the specified pool token
2. Redeems the pool token for the poorest quality TCO2 tokens available
3. Retires the TCO2 tokens

{% hint style="info" %}
If the user sends too much native tokens, the leftover amount will be sent back to the user. This function is only available on Polygon, not on Celo.
{% endhint %}

#### Parameters

| Name              | Type      | Description                                        |
| ----------------- | --------- | -------------------------------------------------- |
| `_poolToken`      | `address` | The address of the pool token to offset, e.g., NCT |
| `_amountToOffset` | `uint256` | The amount of TCO2 to retire                       |

#### Return Values

| Name      | Type        | Description                                             |
| --------- | ----------- | ------------------------------------------------------- |
| `tco2s`   | `address[]` | An array of the TCO2 addresses that were redeemed       |
| `amounts` | `uint256[]` | An array of the amounts of each TCO2 that were redeemed |

### autoOffsetExactInETH

```solidity
function autoOffsetExactInETH(address _poolToken) public payable returns (address[] tco2s, uint256[] amounts)
```

Retire carbon credits using the oldest TCO2 tokens available from the specified Toucan token pool by sending native tokens e.g., MATIC. All provided native tokens is consumed for offsetting.

The `view` helper function [`calculateExpectedPoolTokenForETH()`](#calculateexpectedpooltokenforeth) can be used to calculate the expected amount of TCO2s that will be offset using `autoOffsetExactInETH()`.

This function:

1. Swaps the native token e.g. MATIC sent to the contract for the specified pool token
2. Redeems the pool token for the poorest quality TCO2 tokens available
3. Retires the TCO2 tokens

*This function is only available on Polygon, not on Celo.*

#### Parameters

| Name         | Type      | Description                             |
| ------------ | --------- | --------------------------------------- |
| `_poolToken` | `address` | The address of the pool token to offset |

#### Return Values

| Name      | Type        | Description                                             |
| --------- | ----------- | ------------------------------------------------------- |
| `tco2s`   | `address[]` | An array of the TCO2 addresses that were redeemed       |
| `amounts` | `uint256[]` | An array of the amounts of each TCO2 that were redeemed |

### autoOffsetPoolToken

```solidity
function autoOffsetPoolToken(address _poolToken, uint256 _amountToOffset) public returns (address[] tco2s, uint256[] amounts)
```

Retire carbon credits using the oldest TCO2 tokens available by sending Toucan carbon reference tokens, e.g., NCT.

This function:

1. Redeems the reference tokens for the poorest quality TCO2 tokens available
2. Retires the TCO2 tokens

{% hint style="success" %}
**Note:** The user must approve the carbon reference token to be swapped.
{% endhint %}

#### Parameters

| Name              | Type      | Description                                        |
| ----------------- | --------- | -------------------------------------------------- |
| `_poolToken`      | `address` | The address of the pool token to offset, e.g., NCT |
| `_amountToOffset` | `uint256` | The amount of TCO2 to retire                       |

#### Return Values

| Name      | Type        | Description                                             |
| --------- | ----------- | ------------------------------------------------------- |
| `tco2s`   | `address[]` | An array of the TCO2 addresses that were redeemed       |
| `amounts` | `uint256[]` | An array of the amounts of each TCO2 that were redeemed |

### swapExactOutToken

```solidity
function swapExactOutToken(address _fromToken, address _poolToken, uint256 _toAmount) public
```

Swap eligible ERC20 tokens for Toucan carbon reference tokens (BCT/NCT) on a DEX.

{% hint style="success" %}
**Note:** The user must approve the carbon reference token to be swapped.
{% endhint %}

#### Parameters

| Name         | Type      | Description                                                      |
| ------------ | --------- | ---------------------------------------------------------------- |
| `_fromToken` | `address` | The address of the ERC20 token used for the swap                 |
| `_poolToken` | `address` | The address of the carbon reference token to swap for, e.g., NCT |
| `_toAmount`  | `uint256` | The required amount of the Toucan reference token (NCT/BCT)      |

### swapExactInToken

```solidity
function swapExactInToken(address _fromToken, address _poolToken, uint256 _fromAmount) public returns (uint256 amountOut)
```

Swap eligible ERC20 tokens for Toucan carbon reference tokens (BCT/NCT) on a DEX. All provided ERC20 tokens will be swapped.

{% hint style="success" %}
**Note:** The user must approve the carbon reference token to be swapped.
{% endhint %}

#### Parameters

| Name          | Type      | Description                                                      |
| ------------- | --------- | ---------------------------------------------------------------- |
| `_fromToken`  | `address` | The address of the ERC20 token used for the swap                 |
| `_poolToken`  | `address` | The address of the carbon reference token to swap for, e.g., NCT |
| `_fromAmount` | `uint256` | The amount of ERC20 token to swap                                |

#### Return Values

| Name        | Type      | Description                                                                                         |
| ----------- | --------- | --------------------------------------------------------------------------------------------------- |
| `amountOut` | `uint256` | Resulting amount of Toucan carbon reference tokens that were acquired for the swapped ERC20 tokens. |

### swapExactOutETH

```solidity
function swapExactOutETH(address _poolToken, uint256 _toAmount) public payable
```

Swap native tokens (e.g., MATIC) for Toucan carbon reference tokens (BCT/NCT) on a DEX. Remaining native tokens that were not consumed by the swap are returned.

#### Parameters

| Name         | Type      | Description                                                        |
| ------------ | --------- | ------------------------------------------------------------------ |
| `_poolToken` | `address` | The address of the carbon reference token to swap for, e.g., NCT   |
| `_toAmount`  | `uint256` | The required amount of the Toucan carbon reference token (NCT/BCT) |

### swapExactInETH

```solidity
function swapExactInETH(address _poolToken) public payable returns (uint256 amountOut)
```

Swap native tokens (e.g., MATIC) for Toucan carbon reference tokens (BCT/NCT) on a DEX. All provided native tokens will be swapped.

#### Parameters

| Name         | Type      | Description                                                      |
| ------------ | --------- | ---------------------------------------------------------------- |
| `_poolToken` | `address` | The address of the carbon reference token to swap for, e.g., NCT |

#### Return Values

| Name        | Type      | Description                                                                                       |
| ----------- | --------- | ------------------------------------------------------------------------------------------------- |
| `amountOut` | `uint256` | Resulting amount of Toucan carbon reference token that got acquired for the swapped native tokens |

### autoRedeem

```solidity
function autoRedeem(address _fromToken, uint256 _amount) public returns (address[] tco2s, uint256[] amounts)
```

Auto-redeems the specified amount of NCT / BCT for default TCO2 tokens.

{% hint style="success" %}
**Note:** The user must approve the carbon reference token to be redeemed.
{% endhint %}

#### Parameters

| Name         | Type      | Description                                   |
| ------------ | --------- | --------------------------------------------- |
| `_fromToken` | `address` | The address of the carbon pool to redeem from |
| `_amount`    | `uint256` | Amount to redeem                              |

#### Return Values

| Name      | Type        | Description                                             |
| --------- | ----------- | ------------------------------------------------------- |
| `tco2s`   | `address[]` | An array of the TCO2 addresses that were redeemed       |
| `amounts` | `uint256[]` | An array of the amounts of each TCO2 that were redeemed |

### autoRetire

```solidity
function autoRetire(address[] _tco2s, uint256[] _amounts) public
```

Retire the specified TCO2 tokens.

{% hint style="success" %}
The account sending the transaction needs to hold enough of each of the TCO2 tokens specified for this function to execute.
{% endhint %}

#### Parameters

| Name       | Type        | Description                                                         |
| ---------- | ----------- | ------------------------------------------------------------------- |
| `_tco2s`   | `address[]` | The addresses of the TCO2s to retire                                |
| `_amounts` | `uint256[]` | The amounts to retire from each of the corresponding TCO2 addresses |

### calculateNeededTokenAmount

```solidity
function calculateNeededTokenAmount(address _fromToken, address _poolToken, uint256 _toAmount) public view returns (uint256 amountIn)
```

Returns how much of the specified ERC20 token is required in order to swap for the desired amount of a Toucan carbon reference token such as NCT.

#### Parameters

| Name         | Type      | Description                                          |
| ------------ | --------- | ---------------------------------------------------- |
| `_fromToken` | `address` | The address of the ERC20 token used for the swap     |
| `_poolToken` | `address` | The address of the pool token to swap for, e.g., NCT |
| `_toAmount`  | `uint256` | The desired amount of pool token to receive          |

#### Return Values

| Name       | Type      | Description                                                                                        |
| ---------- | --------- | -------------------------------------------------------------------------------------------------- |
| `amountIn` | `uint256` | The amount of the ERC20 token required in order to swap for the specified amount of the pool token |

### calculateExpectedPoolTokenForToken

```solidity
function calculateExpectedPoolTokenForToken(address _fromToken, address _poolToken, uint256 _fromAmount) public view returns (uint256 amountOut)
```

Calculates the expected amount of Toucan carbon reference token that can be acquired by swapping the provided amount of ERC20 token.

#### Parameters

| Name          | Type      | Description                                                        |
| ------------- | --------- | ------------------------------------------------------------------ |
| `_fromToken`  | `address` | The address of the ERC20 token used for the swap                   |
| `_poolToken`  | `address` | The address of the carbon reference token to swap for, such as NCT |
| `_fromAmount` | `uint256` | The amount of ERC20 token to swap                                  |

#### Return Values

| Name        | Type      | Description                                                        |
| ----------- | --------- | ------------------------------------------------------------------ |
| `amountOut` | `uint256` | The expected amount of carbon reference token that can be acquired |

### calculateNeededETHAmount

```solidity
function calculateNeededETHAmount(address _poolToken, uint256 _toAmount) public view returns (uint256 amountIn)
```

Return how much native tokens e.g, MATIC is required in order to swap for the desired amount of a Toucan carbon reference token, e.g., NCT.

#### Parameters

| Name         | Type      | Description                                                      |
| ------------ | --------- | ---------------------------------------------------------------- |
| `_poolToken` | `address` | The address of the carbon reference token to swap for, e.g., NCT |
| `_toAmount`  | `uint256` | The desired amount of carbon reference token to receive          |

#### Return Values

| Name       | Type      | Description                                                                                                  |
| ---------- | --------- | ------------------------------------------------------------------------------------------------------------ |
| `amountIn` | `uint256` | The amount of native tokens required in order to swap for the specified amount of the carbon reference token |

### calculateExpectedPoolTokenForETH

```solidity
function calculateExpectedPoolTokenForETH(address _poolToken, uint256 _fromTokenAmount) public view returns (uint256 amountOut)
```

Calculates the expected amount of Toucan carbon reference tokens that can be acquired by swapping the provided amount of native tokens e.g., MATIC.

#### Parameters

| Name               | Type      | Description                                                      |
| ------------------ | --------- | ---------------------------------------------------------------- |
| `_poolToken`       | `address` | The address of the carbon reference token to swap for, e.g., NCT |
| `_fromTokenAmount` | `uint256` | The amount of native tokens to swap                              |

#### Return Values

| Name        | Type      | Description                                                        |
| ----------- | --------- | ------------------------------------------------------------------ |
| `amountOut` | `uint256` | The expected amount of carbon reference token that can be acquired |

### isPoolAddressEligible

```solidity
function isPoolAddressEligible(address _poolToken) public view returns (bool _isEligible)
```

Checks if an address identifies a Toucan carbon pool.

#### Parameters

| Name         | Type      | Description                                       |
| ------------ | --------- | ------------------------------------------------- |
| `_poolToken` | `address` | The address of the carbon reference token to test |

#### Return Values

| Name          | Type   | Description                                                   |
| ------------- | ------ | ------------------------------------------------------------- |
| `_isEligible` | `bool` | Returns a bool if the address identifies a Toucan carbon pool |

### isERC20AddressEligible

```solidity
function isERC20AddressEligible(address _erc20Address) public view returns (address[] _path)
```

Checks if ERC20 Token is supported for swapping. Check the [accepted tokens](#accepted-tokens).

#### Parameters

| Name            | Type      | Description                                                                               |
| --------------- | --------- | ----------------------------------------------------------------------------------------- |
| `_erc20Address` | `address` | The address of the ERC20 token that the user sends (e.g., cUSD, cUSD, USDC, WETH, WMATIC) |

#### Return Values

| Name    | Type        | Description                                   |
| ------- | ----------- | --------------------------------------------- |
| `_path` | `address[]` | Returns the path of the token to be exchanged |


# Subgraphs

## API endpoints

Below are the URLs for our [Subgraphs](https://thegraph.com/docs/en/about/), providing endpoints for querying Toucan infrastructure and ecosystem data on various networks. Please replace `[api-key]` in each URL with your Graph API key, which you can generate at <https://thegraph.com/studio/apikeys/> after creating an account.

<table><thead><tr><th width="154">Network</th><th>URL</th></tr></thead><tbody><tr><td>Base</td><td>https://gateway-arbitrum.network.thegraph.com/api/[api-key]/subgraphs/id/AEJ5PEDye6Z198HRQBioG6mZ6ZacHenBg2HTopZPsUCi</td></tr><tr><td>Base Sepolia</td><td>https://gateway-arbitrum.network.thegraph.com/api/[api-key]/subgraphs/id/2oKCq3rDwdYPSao4UbDZKSNbawEdhBVf3BxmqJzFe1uj</td></tr><tr><td>Matic</td><td>https://gateway-arbitrum.network.thegraph.com/api/[api-key]/subgraphs/id/FU5APMSSCqcRy9jy56aXJiGV3PQmFQHg2tzukvSJBgwW</td></tr><tr><td>Amoy</td><td>https://gateway-arbitrum.network.thegraph.com/api/[api-key]/subgraphs/id/FKzFZuYHxyHiiDmdW9Qvwtet1Ad1ERsvjWMhhqd9V8pk</td></tr><tr><td>Celo</td><td>https://gateway-arbitrum.network.thegraph.com/api/[api-key]/subgraphs/id/BWmN569zDopYXp3nzDukJsGDHqRstYAFULFPH8rxyVBk</td></tr><tr><td>Celo Alfajores</td><td>https://gateway-arbitrum.network.thegraph.com/api/[api-key]/subgraphs/id/4uY2L3vQW8XKYPrFFk4i6ZuJkgbpJ8SbJayc8wzMBRYw</td></tr></tbody></table>

## Playground

<table><thead><tr><th width="154">Network</th><th>URL</th></tr></thead><tbody><tr><td>Base</td><td><a href="https://thegraph.com/explorer/subgraphs/AEJ5PEDye6Z198HRQBioG6mZ6ZacHenBg2HTopZPsUCi?view=Query&#x26;chain=arbitrum-one">https://thegraph.com/explorer/subgraphs/AEJ5PEDye6Z198HRQBioG6mZ6ZacHenBg2HTopZPsUCi?view=Query&#x26;chain=arbitrum-one</a></td></tr><tr><td>Base Sepolia</td><td><a href="https://thegraph.com/explorer/subgraphs/2oKCq3rDwdYPSao4UbDZKSNbawEdhBVf3BxmqJzFe1uj?view=Query&#x26;chain=arbitrum-one">https://thegraph.com/explorer/subgraphs/2oKCq3rDwdYPSao4UbDZKSNbawEdhBVf3BxmqJzFe1uj?view=Query&#x26;chain=arbitrum-one</a></td></tr><tr><td>Matic</td><td><a href="https://thegraph.com/explorer/subgraphs/FU5APMSSCqcRy9jy56aXJiGV3PQmFQHg2tzukvSJBgwW?view=Query&#x26;chain=arbitrum-one">https://thegraph.com/explorer/subgraphs/FU5APMSSCqcRy9jy56aXJiGV3PQmFQHg2tzukvSJBgwW?view=Query&#x26;chain=arbitrum-one</a></td></tr><tr><td>Amoy</td><td><a href="https://thegraph.com/explorer/subgraphs/FKzFZuYHxyHiiDmdW9Qvwtet1Ad1ERsvjWMhhqd9V8pk?view=Query&#x26;chain=arbitrum-one">https://thegraph.com/explorer/subgraphs/FKzFZuYHxyHiiDmdW9Qvwtet1Ad1ERsvjWMhhqd9V8pk?view=Query&#x26;chain=arbitrum-one</a></td></tr><tr><td>Celo</td><td><a href="https://thegraph.com/explorer/subgraphs/BWmN569zDopYXp3nzDukJsGDHqRstYAFULFPH8rxyVBk?view=Query&#x26;chain=arbitrum-one">https://thegraph.com/explorer/subgraphs/BWmN569zDopYXp3nzDukJsGDHqRstYAFULFPH8rxyVBk?view=Query&#x26;chain=arbitrum-one</a></td></tr><tr><td>Celo Alfajores</td><td><a href="https://thegraph.com/explorer/subgraphs/4uY2L3vQW8XKYPrFFk4i6ZuJkgbpJ8SbJayc8wzMBRYw?view=Query&#x26;chain=arbitrum-one">https://thegraph.com/explorer/subgraphs/4uY2L3vQW8XKYPrFFk4i6ZuJkgbpJ8SbJayc8wzMBRYw?view=Query&#x26;chain=arbitrum-one</a></td></tr></tbody></table>


# Toucan SDK

The Toucan SDK allows developers to build using Toucan's infrastructure tools on [Celo](https://celo.org/) and [Polygon](https://polygon.technology/). It provides a set of functions that allow developers to interact with Toucan Protocol's smart contracts and subgraphs using JavaScript. The SDK was built with Typescript and wraps around [Ethers.js](https://docs.ethers.org/v5/).

{% hint style="success" %}
The Toucan SDK works in web browsers and Node.js applications.
{% endhint %}

## Installation

```
npm i toucan-sdk
```

or

```
yarn add toucan-sdk
```

## Next Steps

* [Set up the Toucan Client](/developers/sdk/quickstart)
* For simple & quick offsetting use the [OffsetHelper functions](/developers/sdk/contract-interactions#offsethelper-related-methods)
* If you want to retire carbon credits from a specific project, you can use the [`redeemMany`](/developers/sdk/contract-interactions#redeemmany) and then the [`retire`](/developers/sdk/contract-interactions#retire) function.


# Quickstart

Quickstart a project with carbon retirements with a few lines of code

## Setting up the client

Instantiate the `ToucanClient` and set a `signer` & `provider` to interact with our smart contracts.

{% hint style="info" %}
We recommend using to use [ethers.js ^5.6.4](https://docs.ethers.org/v5/api/signer/) for the signer and provider.
{% endhint %}

{% tabs %}
{% tab title="ethers.js" %}
Read the [ethers.js `Signer` docs ->](https://docs.ethers.org/v5/api/signer/)&#x20;

<table><thead><tr><th width="260">Network</th><th>JsonRpcProvider</th><th data-hidden>JsonRpcProvider</th><th data-hidden></th></tr></thead><tbody><tr><td>Celo Mainnet</td><td><code>https://forno.celo.org</code></td><td></td><td></td></tr><tr><td>Celo Alfajores Testnet</td><td><code>https://alfajores-forno.celo-testnet.org</code></td><td></td><td></td></tr><tr><td>Polygon Mainnet</td><td><code>https://polygon-rpc.com</code></td><td></td><td></td></tr></tbody></table>

<pre class="language-typescript"><code class="lang-typescript"><strong>import ToucanModule from "toucan-sdk";
</strong>import { ethers } from "ethers";

const ToucanClient = ToucanModule.default;

// ethers signer and provider
const provider = new ethers.providers.JsonRpcProvider(
  "https://rpc.ankr.com/polygon"
);

// make sure to set your private key in your .env file
const signer = new ethers.Wallet(process.env.PRIVATE_KEY, provider);

// set signer &#x26; provider
const toucan = new ToucanClient("polygon", provider, signer);
</code></pre>

{% endtab %}

{% tab title="wagmi" %}
{% hint style="info" %}
Note that when you are considering using [wagmi](https://0.3.x.wagmi.sh/docs/hooks/useSigner), only versions under 1.0 will work as this library has not yet been upgraded to [viem](https://viem.sh/).
{% endhint %}

Read the[ wagmi `useSigner` docs ->](https://0.3.x.wagmi.sh/docs/hooks/useSigner)

```typescript
import ToucanClient from "toucan-sdk";
import { useProvider, useSigner } from "wagmi";

// get signer & provider
const { data: signer } = useSigner();
const provider = useProvider();

// set signer & provider
const toucan = new ToucanClient("alfajores", provider, signer);
```

{% endtab %}
{% endtabs %}

You could also set the `signer` and / or `provider` later if you prefer that, they are optional — but you will need to set them if you want to interact with contracts. The `provider` is read-only, while the `signer` allows both writing to and reading from the blockchain.

```typescript
import ToucanClient from "toucan-sdk";

const toucan = new ToucanClient("polygon");
toucan.setProvider(provider);
toucan.setSigner(signer);
```

If you don't have a signer or a provider set, you can still interact with the subgraph.

## Retire Carbon Credits

To retire carbon credits on mainnet, you will need to have TCO2 tokens in your account. These can be acquired by buying carbon reference tokens from a DEX like [Uniswap](https://uniswap.org/), then [redeeming](/toucan/carbon-pools#so-what-is-a-carbon-pool) the reference tokens for TCO2s. You can then retire these TCO2 tokens through the Toucan app UI, or programmatically with the `ToucanClient.retire()` method.

If you already own NCT tokens, you can follow this example. Get your test tokens at the [Toucan Faucet](https://faucet.toucan.earth). You can find more ways to retire, and mint `RetirementCertificates`, in [this](/developers/sdk/contract-interactions) list of all SDK functions.

**Redeem your Pool Tokens and get an array of redeemed TCO2s**

```typescript
const tco2addresses = await toucan.redeemAuto("NCT", parseEther("1"));
```

**Retire the TCO2 tokens**

```typescript
await toucan.retire(parseEther("1"), tco2addresses[0].address);
```

## Offset Carbon Credits with the OffsetHelper

The functions in the OffsetHelper will bundle the following steps into a single transaction:

* Exchange ERC20 tokens e.g., cUSD or USDC for pool tokens (e.g., NCT) at a DEX like [Uniswap](https://uniswap.org/) or [SushiSwap](https://www.sushi.com), etc. (depending on the network)
* Interact with the pool contract to redeem the tokens for TCO2
* Interact with the TCO2 token contract to retire the TCO2 the amount purchased and redeemed

{% hint style="info" %}
Note that if you're using the swap functionality, the exact number of TCO2 tokens retired will depend on the stablecoin : reference token exchange rate, which can vary moment to moment.
{% endhint %}

Using these functions, you can easily offset TCO2 tokens using other cryptocurrencies and stablecoins. Bear in mind that using these functions will not let you choose a specific project to retire. To specify your the project you want to retire, you'd need to use the [`redeemMany`](/developers/sdk/contract-interactions#redeemmany) function, which is not supported by the OffsetHelper at this point.

```typescript
const cUSD = "0x765DE816845861e75A25fCA122bb6898B8B1282a";
const tx = await toucan.autoOffsetExactInToken(cUSD, "NCT", parseEther("0.01"));
```


# Contract interactions

Interact with Toucan smart contracts using our JavaScript SDK

The Toucan SDK provides you with several useful tools to quickly redeem and retire carbon credits programmatically. In case you can't find the function that you need with the Toucan SDK, you can also directly interact with the [contracts](https://github.com/ToucanProtocol/contracts).

## OffsetHelper related methods

The OffsetHelper combines these steps in each of the following "auto offset" methods to allow carbon credit retirement (offsetting) within one transaction:

1. Obtain a pool token such as NCT (by performing a token swap)
2. Redeem the pool token for a TCO2 token
3. Retire the TCO2 token

### autoOffsetPoolToken

The `autoOffsetPoolToken` retires carbon credits using the lowest quality (oldest) TCO2 tokens available from the specified carbon pool. This method does not include a token swap — the user must already hold reference tokens. All provided reference tokens are consumed for offsetting.

This method may take up to 1 minute to return a result. It returns the redeem transaction.

{% hint style="info" %}
When automatically redeeming pool tokens for the lowest quality TCO2s there are no fees — you receive exactly 1 TCO2 token for 1 reference token.

Also, note that "Pool Token" in the method name refers to "[carbon reference token](/toucan/carbon-pools#so-what-is-a-carbon-pool)".
{% endhint %}

```typescript
function autoOffsetPoolToken(
  pool: PoolSymbol,
  amount: BigNumber
): Promise<ContractReceipt>;
```

#### Params

| Name     | Type         | Description                                                     |
| -------- | ------------ | --------------------------------------------------------------- |
| `pool`   | `PoolSymbol` | symbol of the carbon reference token to offset with, e.g. `NCT` |
| `amount` | `BigNumber`  | amount of TCO2 tokens to redeem and retire                      |

### autoOffsetExactInToken

The `autoOffsetExactInToken` extends the functionality described in `autoOffsetPoolToken` by including a step to swap another token, like USDC, WETH or WMATIC, for the carbon reference tokens.

{% hint style="info" %}
This method allows you to specify exactly how many tokens you want to use to swap and retire — i.e. how many USDC, WETH or WMATIC tokens you want to spend.

The `autoOffsetExactOutToken` allows you to specify exactly how many carbon reference tokens you want to swap for, redeem and retire. The amount of `swapTokens` needed will be found using calculation methods described below.

* With `autoOffsetExactInToken`, you know how much you'll spend, but not how many TCO2 tokens will be retired
* With `autoOffsetExactOutToken`, you know how many TCO2 tokens will be retired, but not how much you'll spend
  {% endhint %}

After the swap is completed, subsequent steps are the same as above. This method may take up to 1 minute to return a result. It returns the redeem transaction.

```typescript
function autoOffsetExactInToken(
  swapToken: string,
  pool: PoolSymbol,
  amount: BigNumber
): Promise<ContractReceipt>;
```

#### Params

| Name        | Type                                  | Description                                                                                             |
| ----------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `swapToken` | `string` — `WETH`, `WMATIC` or `USDC` | The ticker for the token to swap into carbon reference tokens                                           |
| `pool`      | `PoolSymbol` e.g. `NCT`               | symbol of the carbon reference token to use                                                             |
| `amount`    | `BigNumber`                           | the amount of ERC20 token to swap into carbon reference token. Full amount will be used for offsetting. |

### autoOffsetExactOutToken

The `autoOffsetExactOutToken` retires a specified amount of carbon credits using the lowest quality (oldest) TCO2 tokens available from the specified token pool by sending ERC20 tokens (cUSD, USDC, WETH, WMATIC). This method may take up to 1 minute to return a result. It returns the offset transaction.

```typescript
function autoOffsetExactOutToken(
  swapToken: string,
  pool: PoolSymbol,
  amount: BigNumber
): Promise<ContractReceipt>;
```

#### Params

| Name        | Type                                  | Description                                                                            |
| ----------- | ------------------------------------- | -------------------------------------------------------------------------------------- |
| `swapToken` | `string` — `WETH`, `WMATIC` or `USDC` | The ticker for the token to swap into pool tokens (only accepts WETH, WMATIC and USDC) |
| `pool`      | `PoolSymbol` e.g. `NCT`               | Symbol of the carbon reference token to use                                            |
| `amount`    | `BigNumber`                           | Amount of TCO2 tokens to retire                                                        |

### autoOffsetExactInETH

Same as `autoOffsetExactInToken`, but the `autoOffsetExactInETH` swaps the blockchain's native token for carbon reference tokens, instead of allowing you to specify the `swapToken`.

{% hint style="info" %}
**Note:** While this method refers to "ETH", it actually will use WMATIC on Polygon. The function is not currently available on Celo.
{% endhint %}

This method may take up to 1 minute to return a result. It returns the offset transaction.

```typescript
function autoOffsetExactInETH(
  pool: PoolSymbol,
  amount: BigNumber
): Promise<ContractReceipt>;
```

#### Params

| Name     | Type                    | Description                                                                                                                                               |
| -------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pool`   | `PoolSymbol` e.g. `NCT` | Ticker symbol of the carbon reference token to acquire and redeem                                                                                         |
| `amount` | `BigNumber`             | The amount of native tokens e.g., MATIC to swap into Toucan carbon reference tokens. The full amount of redeemed TCO2 tokens will be used for offsetting. |

### autoOffsetExactOutETH

Same as `autoOffsetExactOutToken`, but the `autoOffsetExactOutETH` swaps the blockchain's native token for carbon reference tokens, instead of allowing you to specify the `swapToken`.

{% hint style="info" %}
Note that while this method refers to "ETH", it actually will use WMATIC on Polygon. The function is not currently available on Celo.
{% endhint %}

This method may take up to 1 minute to return a result. It returns the offset transaction.

```typescript
function autoOffsetExactInETH(
  pool: PoolSymbol,
  amount: BigNumber
): Promise<ContractReceipt>;
```

#### Params

| Name     | Type                    | Description                                                       |
| -------- | ----------------------- | ----------------------------------------------------------------- |
| `pool`   | `PoolSymbol` e.g. `NCT` | Ticker symbol of the carbon reference token to acquire and redeem |
| `amount` | `BigNumber`             | The amount of TCO2 tokens to retire                               |

### calculateExpectedPoolTokenForToken

Calculates and returns the expected amount of carbon references tokens that can be acquired by swapping the provided amount of ERC20 token.

```typescript
function calculateExpectedPoolTokenForToken(
  swapToken: string,
  pool: PoolSymbol,
  amount: BigNumber
): Promise<BigNumber>;
```

#### Params

| Name        | Type                                  | Description                                      |
| ----------- | ------------------------------------- | ------------------------------------------------ |
| `swapToken` | `string` — `WETH`, `WMATIC` or `USDC` | The ERC20 token used for the swap                |
| `pool`      | `PoolSymbol` e.g. `NCT`               | Symbol of the carbon reference token to swap for |
| `amount`    | `BigNumber`                           | The amount of ERC20 token to swap                |

### calculateExpectedPoolTokenForETH

Calculates and returns the expected amount of carbon references tokens that can be acquired by swapping the provided amount of native token.

{% hint style="info" %}
Note that while this method refers to "ETH", it actually will use WMATIC on Polygon. The function is not currently available on Celo.
{% endhint %}

```typescript
function calculateExpectedPoolTokenForETH(
  pool: PoolSymbol,
  amount: BigNumber
): Promise<BigNumber>;
```

#### Params

| Name     | Type                    | Description                                       |
| -------- | ----------------------- | ------------------------------------------------- |
| `pool`   | `PoolSymbol` e.g. `NCT` | Symbol of the carbon reference token to swap for  |
| `amount` | `BigNumber`             | Amount of native tokens to swap for, e.g., WMATIC |

### calculateNeededTokenAmount

Calculates how much of the specified ERC20 token is required in order to swap for the desired amount of a specified carbon reference token.

```typescript
function calculateNeededTokenAmount(
  swapToken: string,
  pool: PoolSymbol,
  amount: BigNumber
): Promise<BigNumber>;
```

#### Params

| Name        | Type                                  | Description                                             |
| ----------- | ------------------------------------- | ------------------------------------------------------- |
| `swapToken` | `string` — `WETH`, `WMATIC` or `USDC` | The ERC20 token used for the swap                       |
| `pool`      | `PoolSymbol` e.g. `NCT`               | Symbol of the pool token to swap for                    |
| `amount`    | `BigNumber`                           | The desired amount of carbon reference token to receive |

### calculateNeededETHAmount

Calculates the amount of native tokens (e.g, MATIC) required to swap for the desired amount of a carbon reference token, e.g., NCT.

```typescript
function calculateNeededETHAmount(
  pool: PoolSymbol,
  amount: BigNumber
): Promise<BigNumber>;
```

#### Params

| Name     | Type                    | Description                                              |
| -------- | ----------------------- | -------------------------------------------------------- |
| `pool`   | `PoolSymbol` e.g. `NCT` | Symbol of the pool token to swap for                     |
| `amount` | `BigNumber`             | The desired amount of carbon reference tokens to receive |

## TCO2 related methods

### retire

The `retire` function retires an amount of TCO2 tokens and returns the retirement transaction.

```typescript
function retire(
  amount: BigNumber,
  tco2Address: string
): Promise<ContractReceipt>;
```

#### Params

| Name          | Type        | Description                         |
| ------------- | ----------- | ----------------------------------- |
| `amount`      | `BigNumber` | Amount of TCO2 tokens to retire     |
| `tco2Address` | `string`    | Address of the TCO2 token to retire |

### retireFrom

The `retireFrom` function retires an amount of TCO2 tokens from a different address/wallet. The function requires approval from the address you're trying to retire from. If you don't own any TCO2s you need to buy pool tokens, e.g., NCTs on a DEX and redeem these first. It returns the retirement transaction.

```typescript
function retireFrom(
  amount: BigNumber,
  address: string,
  tco2Address: string
): Promise<ContractReceipt>;
```

#### Params

| Name          | Type        | Description                                  |
| ------------- | ----------- | -------------------------------------------- |
| `amount`      | `BigNumber` | Amount of TCO2 tokens to retire              |
| `address`     | `string`    | Address of the account to retire from        |
| `tco2Address` | `string`    | Contract address of the TCO2 token to retire |

### retireAndMintCertificate

The `retireAndMintCertificate` function retires an amount of TCO2s & mints the NFT `RetirementCertificate` for it within the same transaction. If you don't own any TCO2s you need to buy pool tokens, e.g., NCTs on a DEX and redeem these first. It returns the retirement transaction.

```typescript
function retireAndMintCertificate(
  retirementEntityName: string,
  beneficiaryAddress: string,
  beneficiaryName: string,
  retirementMessage: string,
  amount: BigNumber,
  tco2Address: string
): Promise<ContractReceipt>;
```

#### Params

| Name                   | Type        | Description                                                           |
| ---------------------- | ----------- | --------------------------------------------------------------------- |
| `retirementEntityName` | `string`    | Name of the entity that does the retirement (i.e. you)                |
| `beneficiaryAddress`   | `string`    | Address of the beneficiary (in case you're retiring for someone else) |
| `beneficiaryName`      | `string`    | Name of the beneficiary                                               |
| `retirementMessage`    | `string`    | Retirement message                                                    |
| `amount`               | `BigNumber` | Amount of TCO2 tokens to retire                                       |
| `tco2Address`          | `string`    | Contract address of the TCO2 token to retire                          |

### getDepositCap

The `getDepositCap` function gets the cap for TCO2s based on `totalVintageQuantity`.

```typescript
function getDepositCap(tco2Address: string): Promise<BigNumber>;
```

#### Params

| Name          | Type     | Description                        |
| ------------- | -------- | ---------------------------------- |
| `tco2Address` | `string` | Contract address of the TCO2 token |

### getAttributes

The `getAttributes` function retrieves the attributes of the TCO2 token. It returns an array of attributes including vintage and project details.

```typescript
function getAttributes(tco2Address: string): Promise<Attributes>;
```

#### Params

| Name          | Type     | Description                        |
| ------------- | -------- | ---------------------------------- |
| `tco2Address` | `string` | Contract address of the TCO2 token |

Return values are described in the [smart contract docs for the `getAttributes` function ->](/developers/smart-contracts/tco2#getattributes)

### getTCO2Remaining

The `getTCO2Remaining` function gets the remaining space in TCO2 contract before hitting the deposit cap. It returns a `BigNumber` representing the remaining space.

```typescript
function getTCO2Remaining(tco2Address: string): Promise<BigNumber>;
```

#### Params

| Name          | Type     | Description                        |
| ------------- | -------- | ---------------------------------- |
| `tco2Address` | `string` | Contract address of the TCO2 token |

## Pool related methods

### depositTCO2

The `depositTCO2` function deposits TCO2 tokens from a user's account into a carbon pool and mints and deposits an equivalent number of the pool's reference tokens back into the user's account. It returns returns the deposit transaction.

```typescript
function depositTCO2(
  pool: PoolSymbol,
  amount: BigNumber,
  tco2Address: string
): Promise<ContractReceipt>;
```

#### Params

| Name          | Type                    | Description                        |
| ------------- | ----------------------- | ---------------------------------- |
| `pool`        | `PoolSymbol` e.g. `NCT` | Symbol of the pool (token) to use  |
| `amount`      | `BigNumber`             | Amount of TCO2 tokens to deposit   |
| `tco2Address` | `string`                | Contract address of the TCO2 token |

### checkEligible

The `checkEligible` function checks if a TCO2 is eligible for pool. It returns a boolean.

```typescript
function checkEligible(pool: PoolSymbol, tco2Address: string): Promise<boolean>;
```

#### Params

| Name          | Type                    | Description                                 |
| ------------- | ----------------------- | ------------------------------------------- |
| `pool`        | `PoolSymbol` e.g. `NCT` | Symbol of the pool to check against         |
| `tco2Address` | `string`                | Contract address of the TCO2 token to check |

## redeemAuto

The `redeemAuto` function automatically redeems TCO2 tokens from the pool up to the deposit cap. It returns the redemption transaction, which returns an array containing TCO2 contract addresses (`string`) and amounts (`BigNumber`).

```typescript
function redeemAuto(
  pool: PoolSymbol,
  amount: BigNumber
): Promise<ContractReceipt>;
```

#### Params

| Name     | Type                    | Description                                 |
| -------- | ----------------------- | ------------------------------------------- |
| `pool`   | `PoolSymbol` e.g. `NCT` | Symbol of the pool redeem from              |
| `amount` | `BigNumber`             | Amount of carbon reference tokens to redeem |

## redeemAuto2 \[deprecated]

```typescript
function redeemAuto2(
  pool: PoolSymbol,
  amount: BigNumber
): Promise<ContractReceipt>;
```

This function is deprecated. Use `redeemAuto` instead.

#### Params

| Name     | Type                    | Description                                 |
| -------- | ----------------------- | ------------------------------------------- |
| `pool`   | `PoolSymbol` e.g. `NCT` | Symbol of the pool to redeem from           |
| `amount` | `BigNumber`             | Amount of carbon reference tokens to redeem |

### redeemMany

The `redeemMany` function redeems carbon reference tokens for specified TCO2 tokens in specified amounts in a single transaction. It returns the redeem transaction.

```typescript
function redeemMany(
  pool: PoolSymbol,
  tco2Addresses: string[],
  amounts: BigNumber[]
): Promise<ContractReceipt>;
```

#### Params

| Name            | Type                    | Description                                        |
| --------------- | ----------------------- | -------------------------------------------------- |
| `pool`          | `PoolSymbol` e.g. `NCT` | Symbol of the pool to redeem from                  |
| `tco2Addresses` | `string[]`              | Array of TCO2 contract addresses                   |
| `amounts`       | `BigNumber[]`           | Array of amounts of TCO2 tokens to redeem for each |

{% hint style="success" %}
The `tco2Addresses` and `amounts` arrays must be of equal length, and align based on index, i.e. "Redeem `amounts[4]` tokens from TCO2 contract address `tco2Addresses[4]`."
{% endhint %}

### calculateRedeemFees

The `calculateRedeemFees` function calculates the fees to selectively redeem carbon reference tokens for TCO2s. It returns amount (`BigNumber`) of fees it will cost to redeem. [Fees](/toucan/carbon-pools/char-carbon-pool#pool-health-fee) are levied in the pool's reference token.

```typescript
function calculateRedeemFees(
  pool: PoolSymbol,
  tco2Addresses: string[],
  amounts: BigNumber[]
): Promise<FeeCalculationResult>;
```

#### Params

| Name            | Type                    | Description                               |
| --------------- | ----------------------- | ----------------------------------------- |
| `pool`          | `PoolSymbol` e.g. `NCT` | Symbol of the pool (token) to use         |
| `tco2Addresses` | `string[]`              | Array of TCO2 contract addresses          |
| `amounts`       | `BigNumber[]`           | Array of amounts of TCO2 tokens to redeem |

### getPoolRemaining

The `getPoolRemaining` function gets the remaining space in pool contract before hitting the cap, i.e. `supplyCap - totalSupply`. It returns `BigNumber` representing the remaining space in the pool.

```typescript
function getPoolRemaining(pool: PoolSymbol): Promise<BigNumber>;
```

#### Params

| Name   | Type                    | Description                         |
| ------ | ----------------------- | ----------------------------------- |
| `pool` | `PoolSymbol` e.g. `NCT` | Symbol of the pool (token) to check |

### getScoredTCO2s

The `getScoredTCO2s` function gets an array of TCO2s ordered by score for a specific pool; `scoredTCO2s[0]` is lowest ranked. It returns an array of TCO2 addresses by rank.

```typescript
function getScoredTCO2s(pool: PoolSymbol): Promise<string[]>;
```

#### Params

| Name   | Type                    | Description                       |
| ------ | ----------------------- | --------------------------------- |
| `pool` | `PoolSymbol` e.g. `NCT` | Symbol of the pool (token) to use |

## Contract registry related methods

### checkIfTCO2

The `checkIfTCO2` function checks if an address represents a TCO2. It returns a `boolean`.

```typescript
function checkIfTCO2(address: string): Promise<boolean>;
```

#### Params

| Name      | Type     | Description                            |
| --------- | -------- | -------------------------------------- |
| `address` | `string` | Contract address of the token to check |

## Interact directly with Toucan's contracts

If you need to interact with a method of our [contracts](https://github.com/ToucanProtocol/contracts) that hasn't been implemented in the SDK yet, you can also connect directly to the contract and call the specific function. Learn more about smart contract functions in [Carbon pool contracts](/developers/smart-contracts/pool-contracts), [TCO2 Contracts](/developers/smart-contracts/tco2) and the [OffsetHelper](/developers/smart-contracts/offset-helper) docs.

{% hint style="info" %}
It's important to note that if you want to use write methods you need to have a `signer` set in the Toucan Client!
{% endhint %}

### getPoolAddress

The `getPoolAddress` function returns the address of a Toucan pool.

```typescript
function getPoolAddress(pool: PoolSymbol): string;
```

#### Params

| Name   | Type                    | Description        |
| ------ | ----------------------- | ------------------ |
| `pool` | `PoolSymbol` e.g. `NCT` | Symbol of the pool |

### getPoolContract

The `getPoolContract` function retrieves an `ethers.Contract` object based on the pool symbol.

```typescript
function getPoolContract(pool: PoolSymbol): IToucanPoolToken;
```

#### Params

| Name   | Type                    | Description                       |
| ------ | ----------------------- | --------------------------------- |
| `pool` | `PoolSymbol` e.g. `NCT` | Symbol of the pool (token) to use |

### getTCO2Contract

The `getTCO2Contract` function retrieves an `ethers.Contract` object based on the TCO2 contract address.

```typescript
function getTCO2Contract(tco2Address: string): IToucanCarbonOffsets;
```

#### Params

| Name          | Type     | Description                                                             |
| ------------- | -------- | ----------------------------------------------------------------------- |
| `tco2Address` | `string` | Address of TCO2 contract to instantiate an `ethers.Contract` object for |

### getRegistryContract

The `getRegistryContract` function retrieves an `ethers.Contract` to interact with the contract registry.

```typescript
function getRegistryContract(): IToucanContractRegistry;
```

### Examples

You can always access any method or property of pool and TCO2 contracts by first getting and storing them in a variable, like this:

```typescript
toucan.setSigner(signer);

const nct = await toucan.getPoolContract("NCT");
const tco2 = await toucan.getTCO2Contract(tco2Address);
const registry = await toucan.getRegistryContract();
const remainingTCO2 = await nct.tokenBalances(tco2Address);
```


# Subgraph interactions

SDK functions to read from the Toucan subgraph

Toucan SDK offers a lot of pre-defined queries. Try them out! If you don't find what you are looking for, you can also [create a custom query](#custom-queries).

## fetchTokenPriceOnDex

The `fetchTokenPriceOnDex` function fetches the price of a token on a DEX (decentralized exchange).

```typescript
function fetchTokenPriceOnDex(pool: PoolSymbol): Promise<TokenPrice>;
```

#### Params

| Name   | Type                    | Description                           |
| ------ | ----------------------- | ------------------------------------- |
| `pool` | `PoolSymbol` e.g. `NCT` | The pool token to fetch the price for |

## fetchUserBatches

The `fetchUserBatches` function fetches up to 100 batches owned by user. It returns an array of objects with different properties of the each batch.

```typescript
function fetchUserBatches(walletAddress: string): Promise<Batch[]>;
```

#### Params

| Name            | Type     | Description                                  |
| --------------- | -------- | -------------------------------------------- |
| `walletAddress` | `string` | The address of the user to fetch batches for |

#### Return Values

The query returns an array of objects, each with a batch's `id`, `tx`, `serialNumber`, `quantity`, `confirmationStatus`, `comments` and `creator`.

## fetchTCO2TokenById

The `fetchTCO2TokenById` function fetches the TCO2 token by its ID. It returns a TCO2 Detail object with properties of the TCO2 (name, address, etc).

```typescript
function fetchTCO2TokenById(id: string): Promise<TCO2Token | undefined>;
```

#### Params

| Name | Type     | Description                                                                                                                    |
| ---- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `id` | `string` | ID of the TCO2 to query for; the id happens to be the same as the address e.g.: `"0x004090eef602e024b2a6cb7f0c1edda992382994"` |

## fetchTCO2TokenByFullSymbol

The `fetchTCO2TokenByFullSymbol` function fetches properties of a TCO2 token contract by its full symbol. It returns a `TCO2Detail` object with properties of the TCO2, including `id`, `name`, `symbol`, `address`, and `projectVintage` details.

```typescript
function fetchTCO2TokenByFullSymbol(
  symbol: string
): Promise<TCO2Token | undefined>;
```

#### Params

| Name         | Type     | Description                                                               |
| ------------ | -------- | ------------------------------------------------------------------------- |
| `fullSymbol` | `string` | Full symbol of the TCO2 token to be fetched, e.g.: `"TCO2-VCS-1718-2013"` |

## fetchAllTCO2Tokens

The `fetchAllTCO2Tokens` function fetches TCO2 details of all TCO2 tokens. It returns array of TCO2 Detail objects with properties of the TCO2s, including `id`, `name`, `symbol`, `address`, and `projectVintage` details.

```typescript
function fetchAllTCO2Tokens(): Promise<TCO2Token[]>;
```

## fetchBridgedBatchTokens

The `fetchBridgedBatchTokens` function fetches data about BatchTokens that have been bridged. It returns an array of BatchTokens containing different properties like id, serialNumber or quantity. The `BatchToken` objects returned include `id`, `serialNumber`, `quantity`, `creator`, `timestamp` and `tx`.

```typescript
function fetchBridgedBatchTokens(): Promise<BridgedBatchToken[]>;
```

## fetchUserRetirements

The `fetchUserRetirements` function fetches all retirements made by a user. It returns an array of objects containing retirement properties like `id`, `creationTx`, `amount`, `token` details, `certificate` details and more.

```typescript
function fetchUserRetirements(
  walletAddress,
  first = 100,
  skip = 0
): Promise<Retirement[]>;
```

#### Params

| Name            | Type     | Description                                                   |
| --------------- | -------- | ------------------------------------------------------------- |
| `walletAddress` | `string` | The address of the user to fetch retirements                  |
| `first`         | `number` | How many retirements you want fetched; defaults to 100        |
| `skip`          | `number` | How many (if any) retirements you want skipped; defaults to 0 |

## fetchRedeems

Fetches redemptions from a given pool. It returns an array of objects with properties of the redeems like `id`, `amount`, `timestamp` and more.

```typescript
function fetchRedeems(
  pool: PoolSymbol,
  first = 100,
  skip = 0
): Promise<RedeemEvent[]>;
```

#### Params

| Name    | Type                    | Description                                               |
| ------- | ----------------------- | --------------------------------------------------------- |
| `pool`  | `PoolSymbol` e.g. `NCT` | The pool token to fetch the price for                     |
| `first` | `number`                | How many redeems you want fetched; defaults to 100        |
| `skip`  | `number`                | How many (if any) redeems you want skipped; defaults to 0 |

## fetchUserRedeems

The `fetchUserRedeems` function fetches all redeems from a given pool by a specific user. It returns an array of objects with properties of the redeems like `id`, `amount`, `timestamp` and more.

```typescript
function fetchUserRedeems(
  walletAddress: string,
  pool: PoolSymbol,
  first = 100,
  skip = 0
): Promise<RedeemEvent[]>;
```

#### Params

| Name            | Type                    | Description                                               |
| --------------- | ----------------------- | --------------------------------------------------------- |
| `walletAddress` | `string`                | The address of the user to query for                      |
| `pool`          | `PoolSymbol` e.g. `NCT` | The pool token to fetch the user redeems for              |
| `first`         | `number`                | How many redeems you want fetched; defaults to 100        |
| `skip`          | `number`                | How many (if any) redeems you want skipped; defaults to 0 |

`Promise<RedeemEvent[]>`: An array of all redeem events for the specified user.

## fetchPoolContents

The `fetchPoolContents` function fetches TCO2 tokens that are part of the given pool. It returns an array of objects representing TCO2 tokens and containing properties like `name`, `amount`, `methodology` and more.

```typescript
function fetchPoolContents(
  pool: PoolSymbol,
  first = 1000,
  skip = 0
): Promise<PoolContent[]>;
```

#### Params

| Name    | Type                    | Description                                                                |
| ------- | ----------------------- | -------------------------------------------------------------------------- |
| `pool`  | `PoolSymbol` e.g. `NCT` | The pool to fetch the contents of                                          |
| `first` | `number`                | How many TCO2 tokens you want fetched; defaults to 1000 (i.e. all of them) |
| `skip`  | `number`                | How many (if any) TCO2 tokens you want skipped; defaults to 0              |

## fetchProjectById

The `fetchProjectById` function fetches the project by its Toucan ID (not `projectId`!). The query returns an object with properties of the Project like `projectId`, `region`, standard and more.

{% hint style="info" %}
The Toucan ID refers to the token ID in [Toucan's Carbon Projects contract](https://polygonscan.com/token/0x599a978c43F5cEa1B26a399D28869Ad4690DC07d).
{% endhint %}

```typescript
function fetchProjectById(id: string): Promise<Project | undefined>;
```

#### Params

| Name | Type     | Description                                          |
| ---- | -------- | ---------------------------------------------------- |
| `id` | `string` | Toucan ID of the project to be fetched, e.g.: `"10"` |

## fetchAggregations

The `fetchAggregations` function fetches all protocol-wide aggregations, including, for example, `tco2TotalRetired`, `totalProjectsTokenized`, or `totalCarbonBridged`. It returns an array of Aggregation objects containing properties like `id`, `key`, `value`.

```typescript
function fetchAggregations(): Promise<Aggregation[]>;
```

`RegistryContract`: The registry contract instance.

## Custom queries

In case you don't find what you are looking for in the pre-build queries, you can create your own with the `fetchCustomQuery` method.

This allows you to fetch with your own queries and can be very powerful if you know GraphQL. You can also check out various example queries in our subgraph [playgrounds](/developers/subgraph#playground).

#### Example: Getting all infos on a project on a Carbon Credit

* `region` stands for the country

```typescript
import { gql } from "@urql/core";

const query = gql`
  query ($id: String) {
    project(id: $id) {
      projectId
      region
      standard
      methodology
      vintages {
        id
      }
    }
  }
`;

const result = await toucan.fetchCustomQuery(query, { id: "1" });
```


# Tools + examples

Welcome to the Tools + Examples section.&#x20;

This part of our documentation showcases the practical tools and real-world examples Toucan offers. Our aim is to demonstrate how our technology can effectively support new product development and help scale the voluntary carbon market.

Here, you'll find a range of integration examples and links to tools to help you test code before it goes live. Explore this section to see how our digital solutions are applied in real scenarios, enhancing trust and efficacy in climate finance.


# Integration examples

If you're looking for examples of how to build on top of our protocol, you can find them here.

### Toucan-made examples

The example implementations repo, as of right now, contains all of the Toucan-made integrations. You can find them [here](https://github.com/ToucanProtocol/example-implementations).

### External examples

[Senken](https://app.senken.io/projects) provides an excellent example of a marketplace application that shows the contents of different carbon pools. This use case would leverage the [`fetchPoolContents`](/developers/sdk/subgraph-interactions#fetchpoolcontents) method available via the SDK.

If you'd like to see an example of a carbonised NFT (NFT that sequesters carbon offsets), we think Celostrials are a great example. You can find them [here](https://github.com/Celostrials).

If you want to see an example of an offseting dApp, the flight offsetter from Discarbon is a cool example. You can find it [here](https://flight.discarbon.earth/).

### More ideas

You want to play around? Here are some more ideas!

* On-chain portfolio management attached to reporting and marketing tools! *Quickbooks for on-chain carbon*
* Seamless carbon retirement (with web2 user experience) while leveraging the possibility of fractionalization and transparency made possible through Toucan's tool.
* Carbon credit options markets and pool arbitrage (where community can deposit the credits)
* Launchpad for new carbon projects that use current carbon credits to finance them (trade in NCT now to get the project specific credit in the future).


# Testnet faucets

Get carbon pool and TCO2 tokens testnets

{% hint style="info" %}
Although we suggest you use local forks in your testing environment when developing on Toucan, if you need TCO2 or pool tokens on a testnet, you can use our faucet.
{% endhint %}

<details>

<summary>How to access CHAR and TCO2s on Base Sepolia</summary>

Access CHAR and TCO2s through our faucet on BaseScan. Here’s how:

* Go to [our faucet](https://sepolia.basescan.org/address/0xf2a25a2b3c9652a3eb32f7fe18cbf58e664fd054#writeContract) contract
* Navigate to **Contract** → **Write Contract**
* Connect your wallet
* Scroll to **Withdraw**
* Enter the contract address of the asset that you’d like to receive (see below)
* Enter **amount** of `1`
* Click **Write** and approve the transaction

**Sepolia asset addresses:**

* CHAR: `0xf92f74Dd03f9A9E04773cE5fF3BCeaBB2eB1dDf0` ([link](https://sepolia.basescan.org/address/0xf92f74dd03f9a9e04773ce5ff3bceabb2eb1ddf0))
* TCO2 PUR-229: `0xd0844B61Dcd657EE937D3CD8cF0a4b83a87218cD` ([link](https://sepolia.basescan.org/address/0xd0844B61Dcd657EE937D3CD8cF0a4b83a87218cD))
* TCO2 PUR-21: `0xe682370Cf0F1d62d672eda1C1D0220605602074c` ([link](https://sepolia.basescan.org/address/0xe682370cf0f1d62d672eda1c1d0220605602074c))
* TCO2 PUR 52: `0xF0476e6969fab717f7FCbA931b398e5D498D0f08` ([link](https://sepolia.basescan.org/address/0xf0476e6969fab717f7fcba931b398e5d498d0f08))

</details>

<details>

<summary>How to access NCT, BCT, and TCO2s on Celo Alfajores</summary>

[Toucan's testnet faucet](https://faucet.toucan.earth/) allows you to obtain small amounts of carbon test tokens.&#x20;

* Make sure you are on the [Alfajores](https://chainlist.org/?testnets=true\&search=alfajores) testnet.&#x20;
* Use [Chainlist](https://chainlist.org/) to add the test networks to your [MetaMask](https://metamask.io/) wallet in case you haven't done that.&#x20;
* Make sure you have testnet tokens from the relevant blockchain to be able to pay for the gas when getting Toucan test tokens. For CELO tokens try either the [Celo faucet](https://faucet.celo.org/) the [AllThatNode](https://www.allthatnode.com/faucet/celo.dsrv) faucet.

</details>


# Dune dashboard

Toucan has a community-developed data visualization on Dune, a third-party platform for analyzing onchain transactions. You can find our dashboard at the link below:

{% embed url="<https://dune.com/toucan_protocol/toucan-puro-carbon-bridge-and-char>" %}


# Developer support

Toucan support

Welcome to the Developer Support section.&#x20;

If you get stuck, start by exploring our detailed docs and FAQs, which cover a wide range of topics and common queries. These resources are designed to assist you in navigating and utilizing our tools effectively.&#x20;

If you require further assistance or have specific questions that aren't addressed in the documentation, please don't hesitate to reach out to us at <support@toucan.earth>. Our team is dedicated to helping you make the most out of your experience with Toucan's climate tech solutions.


# Error codes

We use custom error codes (not to be confused with Solidity custom errors) in our pool contracts to keep the size of the contracts as small as possible.

Below you can find the existing error codes and a description for each one.

<table><thead><tr><th width="184">Error code</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>User is not authorized</td></tr><tr><td>2</td><td>Empty array provided as input</td></tr><tr><td>3</td><td>Pool is full of TCO2s</td></tr><tr><td>4</td><td>ERC20 is blacklisted in the pool. This error is returned for TCO2s that have been blacklisted like the HFC-23 project</td></tr><tr><td>5</td><td>ERC20 is not whitelisted in the pool. This error is returned in case the ERC20 is not a TCO2 in which case it has to be manually whitelisted in order to be allowed in the pool</td></tr><tr><td>6</td><td>Vintage start time of a TCO2 is too old</td></tr><tr><td>7</td><td>Region is not accepted in the pool</td></tr><tr><td>8</td><td>Standard is not accepted in the pool</td></tr><tr><td>9</td><td>Methodology is not accepted in the pool</td></tr><tr><td>10</td><td>Provided fee is invalid, not in a basis points format: [0,10000)</td></tr><tr><td>11</td><td>Provided address needs to be non-zero</td></tr><tr><td>12</td><td>Validation check to ensure array lengths match</td></tr><tr><td>13</td><td>TCO2 not exempted from redeem fees</td></tr><tr><td>14</td><td>The pool is paused</td></tr><tr><td>15</td><td>Redemption transaction has leftover unredeemed value. All value needs to be redeemed in order for the transaction to be successfull</td></tr><tr><td>16</td><td>Redemption exceeds deposited TCO2 supply</td></tr><tr><td>17</td><td>User must be a router</td></tr><tr><td>18</td><td>User must be the pool owner</td></tr><tr><td>19</td><td>Zero destination address is invalid for pool token transfers</td></tr><tr><td>20</td><td>Self destination address is invalid for pool token transfers</td></tr><tr><td>21</td><td>Zero amount provided as an input (eg., in redemptions) in invalid</td></tr><tr><td>22</td><td>ERC20 is not eligible to be pooled</td></tr><tr><td>23</td><td>Carbon registry is already supported in COB</td></tr><tr><td>24</td><td>The caller is not granted the VERIFIER_ROLE in COB</td></tr><tr><td>25</td><td>The caller does not own the provided batch</td></tr><tr><td>26</td><td>The caller is not a valid batch owner (not a TCO2 contract or verifier)</td></tr><tr><td>27</td><td>The batch is not in Confirmed status</td></tr><tr><td>28</td><td>The batch is not in a requested status (DetokenizationRequested or RetirementRequested)</td></tr><tr><td>29</td><td>The batch does not exist</td></tr><tr><td>30</td><td>The batch has an invalid status based on the action requested</td></tr><tr><td>31</td><td>The batch is missing an associated project vintage</td></tr><tr><td>32</td><td>The serial number in the batch is already approved</td></tr><tr><td>33</td><td>The batch is not in Pending status</td></tr><tr><td>34</td><td>The batch is already fractionalized</td></tr><tr><td>35</td><td>The batch is not in Rejected status</td></tr><tr><td>36</td><td>The project vintage is already set in the batch</td></tr><tr><td>37</td><td>The transfer is not approved</td></tr><tr><td>38</td><td>The COB contract is paused</td></tr><tr><td>39</td><td>The caller is invalid</td></tr><tr><td>40</td><td>The TCO2 for the batch is not found</td></tr><tr><td>41</td><td>The registry for the provided vintage is not supported</td></tr><tr><td>42</td><td>No TCO2 was minted as part of tokenization</td></tr><tr><td>43</td><td>Only mints are supported for the batch contract to receive an NFT</td></tr><tr><td>44</td><td>New batch status is invalid</td></tr><tr><td>45</td><td>The TCO2 batch amount has a mismatch</td></tr><tr><td>46</td><td>The TCO2 batch amount approval has failed</td></tr><tr><td>47</td><td>The TCO2 batch not confirmed</td></tr><tr><td>48</td><td>The TCO2 batch not whitelisted</td></tr><tr><td>49</td><td>The TCO2 is non matching NFT</td></tr><tr><td>50</td><td>The TCO2 Quantity in batch is higher than total vintages</td></tr><tr><td>51</td><td>The fee to be charged is too high</td></tr><tr><td>52</td><td>The max fee to be paid is invalid</td></tr><tr><td>53</td><td>The pool feature is not supported</td></tr><tr><td>54</td><td>The TCO2 decimals provided to retirement or detokenization requests are invalid</td></tr><tr><td>55</td><td>The TCO2 quantity in the batch is invalid</td></tr><tr><td>56</td><td>Splitting is required on detokenization/retirement finalization, but 2 new serial numbers were not provided</td></tr><tr><td>57</td><td>The score set for the ERC-1155 token in the pool is invalid</td></tr><tr><td>58</td><td>The score of the ERC-1155 token in the pool is not set</td></tr><tr><td>59</td><td>The underlying decimals are too high for the pool</td></tr><tr><td>60</td><td>The provided supply cap is invalid and should match the underlying token decimals, eg, for an ERC-1155 token whose smallest denomination is tonnes, the pool supply cap should not include decimals of lower fidelity than tonnes</td></tr></tbody></table>


