# Overview

Introducing the two tokens and the overall structure of the system.

## Structure and Purpose

The purpose of this page is to provide potential users of the Frankencoin system with everything they need to know to meaningfully interact with it. For a deeper analysis of its economic properties, we refer to [the research publication](https://app.frankencoin.com/thesis-frankencoin.pdf) and for actually interacting with the system, there is a standard [frontend](https://frankencoin.com). The name Frankencoin hints at its self-governing nature, but also the risks associated with releasing an artificial machinery into the wild. If you encounter errors or if things are not clear to you, you can [reach out to us in the Telegram group](https://t.me/frankencoinzchf) or [file a suggestion for improving this page on GitHub](https://github.com/Frankencoin-ZCHF/frankencoin-dapp/issues).

## Frankencoin (ZCHF) and Frankencoin Pool Shares (FPS)

The Frankencoin system comes with two ERC-20 tokens, a stablecoin called [Frankencoin (ZCHF)](https://etherscan.io/address/0xB58E61C3098d85632Df34EecfB899A1Ed80921cB) and a governance token called [Frankencoin Pool Shares (FPS)](https://etherscan.io/address/0x1bA26788dfDe592fec8bcB0Eaff472a42BE341B2). Unlike other collateralized stablecoins, Frankencoin does not depend on external oracles, making it less susceptible to certain attacks and also more versatile with regard to the used collateral. The disadvantage of that approach is its speed, performing liquidations over the course of days whereas oracle-based systems might react within minutes.

The Frankencoin is a collateralized stablecoin that tracks the value of the Swiss franc. There is no hard peg to the Swiss franc, but a set of economic constraints that incentivizes the market to softly push it towards parity from two sides. Most importantly, the system is [over-collateralized](/positions): for each Frankencoin in circulation, there must be other tokens worth at least one Frankencoin backing it. Furthermore, FPS holders have a number of ways to influence the long-term price of the Frankencoin by making it more or less expensive to mint Frankencoins, similarly to how a central bank keeps the exchange rate of its own currency in balance. The underlying assumption here is that the FPS holders recognize that the system (and therefore also their tokens) is the most valuable when the Frankencoin tracks the Swiss franc as reliably as possible, and that they use their power to govern the system accordingly.

Frankencoin Pool Shares are the [governance](/governance) token of the system. Anyone can obtain newly minted FPS by providing equity capital to the system (or later return them again to get their share of capital back). The FPS holders benefit from the earned fees and liquidation profits, but they are also the ones that carry the residual risk of liquidations, similar to the shareholders of a bank. Therefore, FPS holders have an incentive to grow the system and ensure its stability. The governance process is veto-based: anyone can propose new types of collateral or even completely new methods to bring Frankencoin into circulation, but already 2% of the voting power suffices to veto such proposals.

## Use Cases

Like other stablecoins, the Frankencoin primarily serves three use-cases. The only use-case described extensively in this documentation is that of borrowing as it is embedded in the system. To fully leverage the other use-cases, further tools and services such as exchanges and wallets are necessary that are not described herein.

### Payments

The Frankencoin (ZCHF) can be used to make payments in Swiss francs. Please consult the [landing page](https://frankencoin.com) for a list of apps and services that help in using the Frankencoin as a means of payment, as well as a list of bridged Frankencoin token on other networks than Ethereum mainnet. Payments typically concern small amounts and therefore a layer two instance of the token might be preferred over the mainnet instance.

### Store of Wealth

The Swiss franc has an excellent track record of stability relative to other fiat currencies. For example, over the last 50 years, the US Dollar has lost more than 70% of its value against the Swiss Franc. It is often considered a safe haven when the world is in turmoil. So far, crypto investors could not get significant Swiss franc exposure without going off-chain. For this use-case, it is important to be able to trade the ZCHF in high volumes at narrow spreads.

### Borrowing / Seignorage

Anyone can mint new Frankencoins against a collateral using the built-in borrowing mechanism. All borrowing is based on what we refer to as *positions*. In Liquity, these are called *troves* and in the Maker system *vaults*. They all refer to the account of a user within the system that holds a positive balance of a collateral asset and a negative balance of Frankencoins that must be repaid in order to get the collateral back. The Frankencoin system charges a non-refundable interest rate up front when minting new Frankencoins. Some of the minted Frankencoins are also held back as a reserve in case the position has to be liquidated.

## Technical Architecture

The Frankencoin system consists of a set of smart contracts on the Ethereum mainnet. The two token contracts serve as a foundation for everything else. The ZCHF can have an arbitrary number of contracts that have the power to mint and burn ZCHF. Anyone can propose new such contracts and once they passed the governance process, they can start minting and burning ZCHF. Today, there are two such contracts. One is a simple bridge to bootstrap the Frankencoin based on the existing CryptoFranc (XCHF). The other is a contract named minting hub that serves as the central point to manage all debt positions. The FPS token has built-in governance features and holds the equity capital of the system.

<figure><img src="/files/FRaXft2zcj9L5n3eETT9" alt=""><figcaption><p>Components of the Frankencoin System</p></figcaption></figure>


# Bridge to other Chains

How Frankencoins can be transferred acrossdifferent blockchains

\[TODO: Under construction]

\[TODO: Screenshot of /transfer page and how to (including fee explanation)]

\[TODO: list of supported chains and the token contract address on each chain]

### Technical Background

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


# Savings

The savings module allows users to earn an interest on their Frankencoin holdings.

([source code](https://github.com/Frankencoin-ZCHF/FrankenCoin/blob/main/contracts/minting/v2/SavingsV2.sol), [deployed contract](https://etherscan.io/address/0x3bf301b0e2003e75a3e86ab82bd1eff6a9dfb2ae))

The Savings Module ([frontend](https://app.frankencoin.com/savings)) allows users to earn interest on their Frankencoin (ZCHF) holdings by storing them in the protocol.

### Overview

The savings module takes money out of the equity pool and gives it to Frankencoin holders that have stored some of their Frankencoins in the savings module. The transferred amount depends on the currently applicable interest rate.

<figure><img src="/files/Lf8mqW7wTPd4QoQU8wVA" alt=""><figcaption><p>Savers can acquire ZCHF (7), store them in the savings module (8) and earn an interest (9) paid for by the system.</p></figcaption></figure>

### Saving

Anyone can store Frankencoins in the savings module. These Frankencoins are attributable to their owner at all times (i.e. they are fully segregated) and stay in the savings module until their owner withdraws them again. There is no lending or other transfer happening in the background. Also, unlike the minter reserves, the stored Frankencoins cannot be touched to save the system in case of a depeg.

### Delay

Frankencoins can be sent to the Savings module and withdrawn again at any time. However, there is a delay of three days until interest starts to accrue. The purpose of the delay is to discourage users from trying to earn an interest on Frankencoins that are held temporarily for transactional purposes. In case the user already has some Frankencoins in his savings account, the applicable delay is a weighted average between the already stored and the newly added Frankencoins.

### Interest

The applicable interest rate is determined by the [governance process](/governance). The savings rate and the borrow rate are independent values. Proposed interest changes can be enacted after seven days if no veto was cast. For simplicity, the interest is only calculated on the principal amount. There is no interest on the accrued interest. The interest is automatically collected and added to the account whenever funds are added or withdrawn.

## Referral Module

([source code](https://github.com/Frankencoin-ZCHF/FrankenCoin/blob/main/contracts/savings/Savings.sol), [deployed contract](https://etherscan.io/address/0x27d9AD987BdE08a0d083ef7e0e4043C857A17B38))

The **SavingsReferral Module** introduces a referral-based incentive layer on top of Frankencoin's decentralized savings infrastructure. It is designed to help wallets, dApps, and integrators build sustainable revenue models while offering a native Swiss Franc-denominated yield product to their users. Using the SavingsReferral module, builders can get up to 25% of the savings earned by "their" users.

### How It Works

1. A frontend/wallet integrates the savings UI
2. When calling `save()` or `adjust()` methods, a **referrer address** and **referral fee (ppm)** are passed
3. Interest accrues on user deposits after a 3-day delay
4. When interest is claimed, the smart contract:
   * Pays the user
   * Automatically redirects up to 25% of earned interest to the referrer

### Using the Frankencoin App to Refer Users

You can also use the Frankencoin App to share referral links as follows:

```
<https://app.frankencoin.com/savings?referrer=0x123...4&fee=500>
```

This will automatically set the referrer and fee when the user lands on the page and initiates a savings deposit.

### Claiming Accrued Referral Fees

Referral fees are automatically distributed to the referrer whenever a user’s interest is collected. Referrers do not need to actively claim fees — they are transferred on-chain in real-time as interest is paid out to users.

However, **interest collection must be triggered** manually by calling `refresh()` or `refreshBalance()` on the user’s account. This can be done by:

* The user
* The referrer (to collect their share)
* A third party (e.g., a keeper bot)

This means that a referrer can actively call `refresh()` on behalf of their referred users to ensure interest (and thus their fee) is paid out regularly.

### Wallet Implementation Guide

To ensure users of your wallet automatically assign your address as the referrer:

* Add a custom savings integration UI that interfaces with the Frankencoin contract
* In the backend or UI logic, always pass your designated referrer address and chosen referral fee (e.g., 200\_000 ppm) to the `save()` or `adjust()` calls
* Example:

```solidity
savings.save(1_000e18, 0xYourFrontendAddress, 200_000); // 20% referral fee
```

* Optional: Give users the ability to drop/change their referrer, or hide this setting depending on UX goals

### Integration Details

* Call `save(amount, referrer, referralFeePPM)` or `adjust(targetAmount, referrer, referralFeePPM)`
* Max referral fee is **250,000 ppm** (25%)


# Collateralized Minting

Documentation on minting Frankencoins against a collateral.

When someone mints fresh Frankencoins against a collateral, we call the result a [position](https://github.com/Frankencoin-ZCHF/FrankenCoin/blob/main/contracts/Position.sol). At the time of writing, the only smart contract that is approved to create new positions is the [minting hub](https://github.com/Frankencoin-ZCHF/FrankenCoin/blob/main/contracts/MintingHub.sol). The notation is inspired by portfolio theory, where a position denotes an exposure to a specific asset. In the Frankencoin system, a position always belongs to exactly one owner. Initially, this is the user that created the position, but ownership is transferable through the standard functions of ownable contracts. The owner can deposit collateral into the position and mint Frankencoins up to a certain limit defined by the liquidation price. Anyone can challenge a position if they believe that the liquidation price is below the true value of the collateral, triggering an auction that serves the purpose of determining the market price of the collateral. Thanks to this mechanism, the Frankencoin does not depend on oracles and is very flexible with regard to the provided collateral.

There are two ways to initiate a position: one can either create a completely new one with arbitrary parameters or one can clone an existing position. The former is for advanced users and not exposed in the default frontend. The latter is the faster way of obtaining Frankencoin against a collateral and supported in the default frontend.


# Opening New Positions

How to propose completely new positions with any collateral.

You want to mint ZCHF, but your preferred type of collateral is not available yet? In that case, you can propose a new collateral type.

To do so, head over to the [Mint page](https://app.frankencoin.com/mint) and scroll to the bottom until you find the "Propose New Position or Collateral" button.

<figure><img src="/files/BqSRzYPgfhrSM0QQOl9I" alt=""><figcaption><p>Click this button to propose a new position type</p></figcaption></figure>

On the next page are four boxes. Let's take a look at the box in the top left.

<figure><img src="/files/NQkyXyElHRWTiAkP8t7y" alt=""><figcaption><p>Proposal process</p></figcaption></figure>

The proposal fee is fixed at 1 000 ZCHF. This fee is not returned if the position is denied and goes to the equity holders. The price tag of 1 000 ZCHF ensures that each proposal is well thought-out. Having a low fee would likely encourage the proposal of illiquid and/or otherwise unfit tokens. The initialization period has to be at least 3 days. This gives other system participants enough time to veto or to challenge the new position. A veto can only be cast by qualified pool share holders by calling the "deny" method on the position. If a position is denied, it cannot ever be used to mint Frankencoins, but it can still be challenged. New positions can be challenged immediately using the normal challenge mechanism.

Next, we can inspect the box on the bottom left.

<figure><img src="/files/68pJBuTYZ6iRn1hxGDBV" alt=""><figcaption><p>Financial terms</p></figcaption></figure>

The annual interest is charged upfront and can be set by the user. With a maturity of 12 months, this is the entire fee that is charged. Of course, if the maturity is set to 6 months for example, the final interest changes accordingly. The minting limit describes the maximum amount of Frankencoins that can be minted against this position and its clones. When the position is cloned, the remaining amount is split between the original and the clone. The purpose is to limit the exposure of the Frankencoin system to a single collateral. The Frankencoin should be able to withstand the total failure of one or more related collaterals, even if all their positions are maximally minted.

Next, the box on the top right comes into play.

<figure><img src="/files/OXdD3Z0OUH4lPfu6VolY" alt=""><figcaption><p>Collateral</p></figcaption></figure>

First of all, the collateral token needs to be selected by pasting its contract address into the first field, and approve handling of the token. This can be done for example through MetaMask. The chosen collateral should be freely traded on the market and have a somewhat stable value. For criteria that collateral tokens should fulfil, have a look at the [Acceptable Collateral](https://github.com/Frankencoin-ZCHF/FrankenCoin/discussions/11) page. The minimum collateral section is the minimum acceptable amount of collateral and should be set to about 5 000 ZCHF worth of collateral (in this specific case 2 WETH were chosen). It is not possible to decrease the collateral in a position below the minimum without closing it entirely.

The last section is the initial amount of collateral. This will be automatically transferred to the newly created position during the minting. The initial collateral must be equal to or larger than the minimum collateral.

The last remaining box is located on the bottom right. Here, the (potential) liquidation process is discussed.

The liquidation price can be set freely but must result in a position liquidation of at least 5 000 ZCHF. In the previous box, we've set a minimum collateral of 2 WETH. With a minimum collateral liquidation value of 5 000 ZCHF, the liquidation price for each WETH must thus be at least 2 500 ZCHF, as 2 \* 2 500 = 5 000. Had a minimum collateral of 20 WETH been chosen, the minimum liquidation price would thus be (5 000 / 20) 250 ZCHF.

<figure><img src="/files/9TRIDIEm6YnIS50s2mJD" alt=""><figcaption><p>Liquidation</p></figcaption></figure>

If an auction ends at a price below the liquidation price, the position is liquidated.

The "Retained Reserve" should be set to ensure a very high confidence that challenges do not end significantly below the liquidation price, assuming the market price has just fallen slightly below it at the start of the challenge. The more volatile the collateral and the longer the challenge period, the higher the reserve requirement needs to be to mitigate risks.

The last field, the "Auction Duration", describes how long an auction should be. For highly liquid collaterals such as Wrapped ETH, the challenge duration can be quite short, possibly ranging from hours to even minutes, especially with automated bidders in the market. For less liquid collaterals that are harder to evaluate, challenges might last up to two weeks to allow bidders to organize. The longer the challenge duration, the higher the required reserve should be to ensure the position remains economically sound.

Once all parameters are set, you can hit the "Propose Position" at the bottom of the page.

If there's no veto within the initialization process, you will have successfully opened a new position! After that, you can head over to the [My Positions page](https://app.frankencoin.com/mypositions) and mint your new ZCHF.


# Cloning Existing Positions

Immediately mint Frankencoins by cloning an established position that is not maxed out.

This is the standard way to obtain Frankencoins against a collateral. Unlike creating an entirely new position, which takes a lot of time, borrowing by cloning an established position can be done immediately. To do so, [find an existing position](https://app.frankencoin.com/mint) that is based on your collateral of choice and that is not maxed out yet, i.e. where the borrowed total is below the limit. You can spot such a position by searching for the blue "Mint" button. Note the available amount: This shows how many more ZCHF can be minted by cloning this particular position. When looking for a position to clone, make sure to pay attention to the liquidation price.

<figure><img src="/files/21lJwbqUDu2IabKoEN5n" alt=""><figcaption><p>Note the "Available"</p></figcaption></figure>

Once you have chosen your collateral type, simply click the "Mint" button to be taken to the position overview page.

<figure><img src="/files/ucv4Gj8o9fL4ALcKT1Cj" alt=""><figcaption><p>Hit "Approve" to mint</p></figcaption></figure>

Here, you can see a detailed view showing all the relevant parameters. In this example, we are trying to mint an additional 3 000 ZCHF using the WETH position.

The "Limit" value shows how much this position can mint in total. In this case, we can still mint another 997 000 ZCHF. After that, we can set the mint amount, in this case 3 000 ZCHF. The required collateral depends on the parent position and is 2 WETH in this case. The expiration date can be changed but not beyond the expiration date of the parent position.

The right side breaks down what happens with the 3 000 ZCHF. 2 640 are sent to you wallet, 300 ZCHF are retained as reserve (remember the 10% reserve requirement of the parent position) and the interest is charged upfront.

The "Notes" section shows the effective annual interest, the set liquidation price, the current market price of the collateral and the loan-to-value ratio. It also provides a link to the parent position.

Ready to mint your new ZCHF?

Just hit "Approve", confirm the transaction in your wallet and get your new ZCHF!


# Adjusting a Position

Learn how to adjust a position.

Once you are the proud owner of a position whose cool-down period has passed, you can start to adjust it. You can adjust the outstanding amount, the amount of the deposited collateral, and the liquidation price.

To start adjusting your position, head over to the "My Positions" tab. Once there, you can see your existing position(s) at the top of the page. If you don't see your position here, make sure that the wallet that originally created the position is connected. This is crucial: If no wallet or any other wallet is connected, your position will not show up here.

<figure><img src="/files/V3TOjyCepiN6ZINBRdqr" alt=""><figcaption><p>My positions</p></figcaption></figure>

Once you see this, simply click on the "Manage" button. This will take you to the following page:

<figure><img src="/files/EZTzZ05nX3pudwgM1dUc" alt=""><figcaption><p>Adjust your position here</p></figcaption></figure>

When you land on this page, all fields are empty at first. If you have just proposed a new collateral type, note that you haven't actually minted any ZCHF yet!

If the full 2 WETH defined earlier should be used to mint new ZCHF, the parameters would look like this:

<figure><img src="/files/wjOrcNzpOOGroKz5ueHL" alt=""><figcaption><p>Mint new ZCHF</p></figcaption></figure>

The amount is set to 3 000 ZCHF. This was set during the opening of a new position. The liquidation price of 1 500 ZCHF per WETH and two WETH as collateral result in the amount of 3 000 ZCHF.

This is confirmed by the "Outcome" section on the right side. While 3 000 new ZCHF will be minted, the number of ZCHF that will be received is actually lower (2 610 ZCHF). This is because of the minting fee, or the interest, which is charged upfront. This was also set during the proposal of WETH as collateral. Similarly, the amount that is added to the reserve was also set during the proposal, in this case 10%. Both of these are charged upfront. You will not get the fee back, but you will likely get the reserve back when you return and burn the minted Frankencoins. The reserve might be used to cover the system's losses in case there are any. This creates an incentive for you to help looking after the system.

When paying back your loan, meaning decreasing the amount, you need to have some Frankencoins in the wallet, but some are also taken out of the reserve. For example, if the reserve ratio is 10%, it suffices to return 900 ZCHF in order to close a 1 000 ZCHF position as the other 100 ZCHF are taken from the reserve.

If you would like to add more collateral to achieve a lower liquidation point, you can also do this here. There is no limit for how much collateral you can add.

You are also able to increase the liquidation price here. Increasing the liquidation price will allow you to borrow more, but only after the cool-down period has passed again, allowing others to challenge your position at the new price before you can use the higher price to mint Frankencoin.


# Challenges and Auctions

Challenges and the resulting auctions are a mechanism to ensure positions are backed by sound collateral.

## Auction Design

Challenging a position triggers an auction of the collateral. The auction serves two purposes, the determination of the market price and the liquidation of the collateral at that market price. The auction frees the system from the need for an external oracle. The difficulty lies in designing the auction such that it cannot be profitably manipulated.

Traditional auctions are prone to price manipulation by the owner of the auctioned assets. For example, if Alice minted 1 000 ZCHF against a collateral whose value has dropped to 950 ZCHF, she might be tempted to bid 1 001 ZCHF for that collateral in an auction, thereby planting the false believe that the position is still well-collateralized. Frankencoin prevents this by cleverly switching the collateral the bidders are bidding for at the critical price point. For bids below 1 000 ZCHF, the bidders will get Alice's collateral. When bidding above 1 000 ZCHF, the bidders will get the collateral asset from the challenger. Thanks to this approach, price manipulation becomes very expensive for Alice as the 1 001 ZCHF bid would not go to her own pockets, but the pockets of the challenger. In order to prevent her position from being liquidated, she would have to pay 1 001 ZCHF for an asset worth 950 ZCHF as often as the challenger chooses to repeat the challenge.

This example reveals one of the underlying assumptions of the system and a requirement for an asset to be acceptable as a collateral. While it is not necessary that there is a liquid market, it is important that the potential challengers own enough of the collateral asset (or can acquire it somewhere) to repeatedly challenge Alice. Once Alice ends up owning 100% of the collateral asset in circulation, she cannot be challenged anymore and can start minting arbitrary amounts of Frankencoins. That is also why the Frankencoin auction system does not work with non-fungible tokens. It is important that no position is ever accepted that is based on collateral with too limited availability.

One good property about the auction design is that as long as someone is willing to bid the market price for a collateral asset, the maintenance of the position does not require any attention of the owner. Only when the market price is about to fall below the liquidation price, the owner should start thinking about repaying it or making it more sound again by providing more collateral and adjusting the liquidation price downwards.

I the highest bid is below the liquidation price, the challenge is considered successful. After a successful challenge, the minter reserve associated with the position is dissolved and added to the proceeds from the auction. The total proceeds are then used to repay the position and to reward the challenger. If there are not enough funds to do that, equity holders have to jump in and suffer a loss. If there is something left, the remaining amount is sent to the equity holders as a profit. For example, if the minter reserve was 20% and the highest bid for Alice's collateral was 950 ZCHF, the equity holders make a profit of 150 ZCHF, minus the challenger reward. However, if the highest bid was below 800 ZCHF, they will make a loss.

## How to Initiate an Auction

On the [Monitoring page](https://app.frankencoin.com/monitoring) you can find a list of all open positions. If you believe that the conditions are right to challenge a position, you can simply click on the "Challenge" button here.

<figure><img src="/files/SAQ0615elouKRZ8zvBhU" alt=""><figcaption><p>Click on "Challange" to initiate a new challenge</p></figcaption></figure>

After that, you can initiate a new challenge.

<figure><img src="/files/HoyaxpwWisM0Kj5yw8Oy" alt=""><figcaption><p>Initiate a new challenge</p></figcaption></figure>

Here, you can choose the amount of collateral you want to challenge. For that, you need to have the corresponding amount of the collateral asset in your wallet. The "Potential Reward" corresponds to 2%. The challenge itself is divided into two phases. In the first phase, the price remains fixed. In the second phase (in case there is still some collateral left), the price starts to decline towards zero. At this stage, the bidders are buying the original minter's collateral.

## How to Participate in Ongoing Auctions

Under the [Auctions page](https://app.frankencoin.com/challenges), you can find all ongoing challenges. As of writing this page, there are no ongoing challenges.

<figure><img src="/files/HBFhH0zRR8I7cWGm1kOz" alt=""><figcaption><p>No active challenges</p></figcaption></figure>

If there were any ongoing challenge, they would show up under this tab. Here, you will have the chance to participate.


# Investing and Pool Shares

Directly contribute risk capital to the Frankencoin system to get Frankencoin Pool Shares (FPS) in return.

## Reserve Pool Shares

Frankencoin Pool Shares (FPS) are shares in the equity reserve pool of the Frankencoin system. Being an FPS holdes is similar to being a shareholder of a bank. As the Frankencoin system makes profits through fees or liquidations, the price of the pool shares is automatically adjusted upwards. Likewise, when risks materialize and the reserve pool incurs a loss, the value declines. They can be minted at any time and redeemed again after a minimum holding period of three months. Over time, reserve pool shares that are not moved accumulate votes. Shareholders with at least 2% of the votes gain veto power.

## Usage

If you want to acquire or sell some FPS, you can head over to the [Equity page](https://app.frankencoin.com/equity). Once there, you can find two sections. Let's focus on the left one first.

<figure><img src="/files/JkWDao00BZNkNK3N2Grn" alt=""><figcaption><p>Buy new FPS</p></figcaption></figure>

Here, you can buy new FPS or sell the FPS you own. In this example, the user wants to acquire 1 000 ZCHF worth of FPS. The current price of one FPS is 1 016 ZCHF, so 1 000 ZCHF would net the user 0.9812 FPS. Note that the wrapped FPS, or WFPS, can also be traded/wrapped here.

Selling FPS can be done here as well. In this case, the FPS are burned and the corresponding amount of capital is sent to the redeemer. It is important to observe the minimum holding time of 3 months required to redeem FPS.

Below this section, we can see that this address currently owns 7.60 FPS at a value of 7 721 ZCHF and a holding duration of 4 months. At the bottom of the page there's a link to trade WFPS on Polygon.

Next, let's take a look at the right side.

<figure><img src="/files/fpJvwEpaHMiacacC1fDC" alt=""><figcaption><p>FPS stats</p></figcaption></figure>

The top of the sections displays the current price of one FPS and the current supply of all FPS. This is followed by a price chart and another section with various information:

Market Cap: The total value of all the FPS in circulation, calculated by multiplying the number of FPS by the current FPS price. This shows the overall value of the governance tokens in the system.

Total reserve: The total reserve in ZCHF that is held to support the system. This reserve acts as collateral to back the stability of Frankencoins and ensures the system’s solvency.

Equity capital: This represents the value of the equity that FPS holders own in the system. It’s the capital available to cover potential losses within the Frankencoin system.

Minter reserve: The total reserve set aside specifically for positions created by minters. This reserve acts as a safety net.

Total income: The total amount of income generated by the system.

Total losses: This shows the total losses incurred by the system. In this case, it’s at zero, indicating that no losses have been recorded in the system.

## Economics

Anyone can create additional pool shares by depositing reserve capital at any time, or redeem them again after a minimum holding period of 90 days. Therefore, an important design consideration is the pricing mechanism for pool shares. As having a price implies having a valuation, this boils down to evaluating the Frankencoin system.

### Proportional Capital Valuation

In an approach inspired by the research paper "[The Continuous Capital Corporation](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4189472)", the Frankencoin system evaluates itself at a constant multiple of its capital. This multiple is set to three. So if there is 1 million ZCHF in equity capital K, anyone can subscribe to new pool shares at a valuation of 3 million ZCHF, or also redeem old shares at that valuation. Mathematically, valuation V is:

<figure><img src="/files/7PJrVEcQy84JZPDVzW1C" alt=""><figcaption><p>Market cap as a function of capital</p></figcaption></figure>

Whereas V(K) is the market cap of all Frankencoin Pool Shares (FPS) in circulation if there are K Frankencoins in equity capital. Given the number of pool shares s in circulation, the marginal price p per share is given as

<figure><img src="/files/hK9sIE3XqI1PrDUZdeAk" alt=""><figcaption><p>Price per share</p></figcaption></figure>

From the above constraints follow that an investment of additional capital ΔK leads to the following rules for determining the new number of shares given the old number of shares:

<figure><img src="/files/SvRK8HruNfB9vlbo1EuH" alt=""><figcaption><p>New number of shares after investment ΔK</p></figcaption></figure>

Similarly, the same investment ΔK leads to a new price:

<figure><img src="/files/Rl1ACj6tBTNFYK4N2cqh" alt=""><figcaption><p>New price per share after investment ΔK</p></figcaption></figure>

One can verify that the valuation equation still holds after that investment by multiplying the number of shares with their price in order to obtain the new valuation:

<figure><img src="/files/YVYBjh17fmgkfa5aZDkS" alt=""><figcaption><p>Verification</p></figcaption></figure>

In other words: When someone invests into the Frankencoin system, two thirds of the increased market cap come from the price increase and one third comes from the increased number of shares.

### Equilibrium

Consider again the example with 30 million ZCHF in outstanding mints and an interest of 5%, leading to a reserve inflow of 1.5 million per year. Under these circumstances, rational market participants will value the entire pool at 30 million ZCHF and therefore buy additional pool shares until the valuation hits 30 million ZCHF. This valuation is reached at a reserve pool size of 10 million ZCHF, leaving 20 million ZCHF in circulation that can be used for other purposes.

This is at least the simple case without savings. The savings module that was later added splits the income stream into two: one to

This is essentially fractional reserve banking with a reserve of one third. In contrast, the tier 1 equity capital of modern banks is usually much less than that, so the Frankencoin system has considerably higher reserves. However, unlike in the traditional banking system, this reserve requirement is not strictly enforced by a regulator, but more like a carrot that attracts the equilibrium towards the reserve target.

If the effective interest at which new positions can be opened is at 5% and the reserve is below the target of one third of the outstanding balance, then it is possible to do interest arbitrage by minting additional ZCHF at an interest of 5% per year and using those to buy pool shares that yield maybe 6% per year. The opposite is the case if the reserve is higher than one third. In that case, minters should think about selling pool shares to repay their debt (if they are able to).

This leads to the following rule of thumb: if the FPS market cap is higher than the market cap of ZCHF, then that means that the market participants are betting on the system to grow. If the FPS market cap is lower than the ZCHF market cap, then the market is signalling that it expects the Frankencoin system to shrink.

### Limits to Capital Efficiency

What if someone creates a clone of the Frankencoin system with a reserve target of 25%? Would they be able to offer a better deal thanks to better capital efficiency? Here, one needs to be aware that there is a trade-off. It is certainly more attractive for those who mint some ZCHF to buy pool shares and sellthe remaining coins on the market. However, one needs to be aware that this implies that there is a buyer for the other 75% of the ZCHF to keep the system in equilibrium. These buyers are typically users that hold ZCHF for transactional purposes. And for them, stability is key. But stability suffers if one aims for an overly ambitious level of capital efficiency, making the clone less attractive for transactional purposes. It is hard to tell where exactly the right equilibrium is, but this is not a race to the bottom where the system with the lowest capital requirements automatically wins. We believe that aiming for a 33% reserve is a robust middle ground, that still allows for plenty of seigniorage gains.


# Reserve

The Frankencoin system employs a detailed balance sheet framework, featuring three types of reserves to ensure stability and security.

The Frankencoin system features three types of reserves. The first type comprises Swiss franc stablecoins held in a bridge. The second type includes funds provided by borrowers when they mint new Frankencoins. The third type consists of contributions from holders of reserve pool shares. It's important to note that the collateral used to mint Frankencoins is not considered part of the reserve, as it remains outside the Frankencoin system's "balance sheet."

If the Frankencoin system were a company, its balance sheet would appear roughly as depicted below.

## Balance Sheet Diagram

<div data-full-width="true"><figure><img src="/files/d5hEeUHtHm3kzo2iGshF" alt="" width="375"><figcaption><p>The Frankencoin "balance sheet"</p></figcaption></figure></div>

This balance sheet consists of the following components:

## Assets

* **Stablecoins Locked in Bridges:** These are stablecoins like XCHF that are locked within bridge contracts, facilitating the exchange between Frankencoin (ZCHF) and other stablecoins.
* **Minter Repayment Obligations:** This represents the amount borrowers need to repay after minting Frankencoin. It reflects the debt owed by users who have collateralized their assets to mint ZCHF.
* **Reserve:** This includes the funds in the reserve pool contributed by minters and reserve pool share holders. These funds grow over time, providing a buffer.

## Liabilities and Equity

* **Total Frankencoin (ZCHF) Supply:** This is the total amount of Frankencoins in circulation, representing the system's obligations to the holders of ZCHF.
* **Minters Reserve:** The specific reserve funds allocated to cover potential losses from minter defaults, ensuring the stability of the system.
* **Equity:** Owned by reserve pool share holders, this represents the net value of the system after accounting for assets and liabilities. Holders of reserve pool shares play a crucial role in the system's governance and stability, benefiting from a share of the system's profits and having a say in governance decisions .

## Example Scenarios

1. **User Swaps ZCHF for XCHF:**
   * If a user sends 100 ZCHF to the stablecoin bridge to swap them into XCHF, the balance sheet items for stablecoins locked in bridges (x) and the total ZCHF supply (z) both decrease by 100 units. Other balance sheet items remain unaffected.
2. **User Mints New Frankencoins:**
   * Suppose a user mints 500 ZCHF against collateral with a reserve ratio of 20% and a fee of 5%. On the asset side:
     * **Minter Repayment Obligations (m):** Increases by 500 ZCHF.
     * **Reserve (r):** Increases by 125 ZCHF (100 ZCHF into minters reserve and 25 ZCHF as fees).
   * On the liabilities side:
     * **Total ZCHF Supply (z):** Increases by 500 ZCHF.
     * **Minters Reserve (b):** Increases by 100 ZCHF.
     * **Equity (e):** Increases by 25 ZCHF (the fee retained by the system).
   * The minting process thus expands the balance sheet by 625 ZCHF, which reflects both the debt and the new reserves.
3. **Successful Challenge of a Minter's Position:**
   * For a position that minted 5 000 ZCHF and is successfully challenged with a highest bid of 4 500 ZCHF:
     * **Reserve (r):** Decreases by 600 ZCHF to cover the shortfall.
     * **Total ZCHF Supply (z):** Decreases by 5 000 ZCHF as the loan is repaid.
     * **Minter Repayment Obligations (m):** Decreases by 5 000 ZCHF.
     * **Minters Reserve (b):** Adjusts to reflect 400 ZCHF reassigned to equity as liquidation profit.
     * **Equity (e):** Increases by 400 ZCHF.

## Protection Mechanisms During Liquidation:

When a position is liquidated, the system employs three layers of protection to prevent losses:

1. **Borrower's Reserve:** Directly associated with the liquidated position, used first to cover any losses.
2. **Equity:** If the borrower's reserve is insufficient, losses are absorbed by reducing the equity, impacting the value of reserve pool shares.
3. **General Borrower's Reserve:** As a last resort, this reserve is tapped into, potentially requiring other users to repay more than initially anticipated, creating an incentive for all participants to maintain system integrity.

## Equilibrium of Equity:

The system is designed to ensure that in efficient markets, the equity will approximate one third of the Frankencoins not created through a bridge, mathematically represented as 3e=z−x3e = z - x3e=z−x. This equilibrium ensures a robust financial foundation, detailed further in the research paper.


# Governance

Frankencoin's veto-based governance system pushes the boundaries of being scalable and decentralized at the same time.

## Overview

Unlike other decentralized protocols, Frankencoin does not depend on lengthy voting processes. Instead, it's governance revolves around a light-weith veto process. It is formally defined and analyzed on [pages 43 and following of the Frankencoin thesis](https://www.zora.uzh.ch/id/eprint/259657/1/259657.pdf).

Passing a change takes three steps:

1. Someone makes a proposal, paying a proposal fee
2. Frankencoin Pool Share holders are given time to veto the proposal
3. If no veto was cast, the proposal can be enacted by anyone

## Immutable Modularity

All contracts in the Frankencoin system are immutable. Once deployed, they cannot be changed anymore. However, many contracts have adjustable parameters like the savings rate. Also, the main Frankencoin contract offers the possibility to propose new minting modules. These are smart contracts that can arbitrary mint, move, and burn Frankencoins - making them very powerful and allowing for a wide range of potential extensions. The ability to mint Frankencoins against a collateral is based on such an extension. And so is the savings module and the contracts that allow for sending Frankencoins to other blockchains. The [governance page](https://app.frankencoin.com/governance) lists all minting modules ever proposed.

## Community Consensus

The first step before making a proposal is to reach out to the community to sense whether there would be resistance against it. Ideally, there is a broad consensus on what constitutes an acceptable proposal, reducing the need for frequent vetoes. To establish a consensus and increase communication, the [Frankencoin forum](https://github.com/Frankencoin-ZCHF/FrankenCoin/discussions) and the [Frankencoin Telegram channel](https://t.me/frankencoinzchf) can be used. These platforms are vital for discussion, dissemination of information, and community engagement, helping align stakeholders' interests and opinions.

## Proposal Submission

There are different types of proposals that can be submitted in different places. For example, there is a [purpose-built page](https://app.frankencoin.com/mint/create) to propose new types of collateral. Typically, making a proposal is open to anyone. Making a proposal typically costs a fee and comes with a specific veto period. Both can be configured to be higher than the minimum. A longer than minimal proposal period might make sense when the proposal is complex and the community is expected to take additional time to reach a consensus.

## Veto Process

Any participant with more than 2% of the total votes has veto power. A veto can be exercised in a single transaction and has the immediate effect of cancelling the relevant proposal. The system keeps the proposal fee regardless of whether the proposal passes or is denied.

If one address alone does not have a sufficient number of votes, other addresses can help that address by delegating their votes. So if a user has multiple addresses or if multiple users want to cast a veto in collaboration, they can use delegation to bundle their votes, as described in the next section.

## Vote Accumulation

The number of votes of an address is calculated by multiplying their Frankencoin Pool Shares by the duration they have been holding them. This method rewards long-term commitment and prevents short-term manipulative actions. For example someone borroing a lot of FPS in a flash loan has zero votes, because the holding duration is zero. Or someone with 10 FPS that they held onto for two years has more votes than someone with 1000 FPS that they held for a week.

For example, if there is a group of seven FPS holders that delegate their power to each other in a circle, all seven FPS holders gain veto power if they collectively have at least 2% of the votes. Note that the frontend currently ignores delegations when casting a veto. So to actually make use of the delegations, a manual transaction with the help of [etherscan](https://etherscan.io/) or another suitable tool is required for now.

As 2% is quite a low barrier to be able to block all new proposals, there is a mechanism to protect the system against griefing. An altruistic system participant can use the built-in kamikaze function of the FPS contract to sacrifice own votes in order to cancel the same number of votes of one or more target addresses. Doing so reduces the holding duration counter and therefore can also be used to temporarily prevent a target address from redeeming Frankencoin Pool Shares.

## Cross-Chain Governance

Frankencoins are present on a multiture of blockchains, including [Arbitrum](https://arbiscan.io/address/0xD4dD9e2F021BB459D5A5f6c24C12fE09c5D45553?__cf_chl_rt_tk=M23HkA3rE6ZYd.t9KezhFDa.1V0Yw76Ouj4TESenpIQ-1753369514-1.0.1.1-QrlEuenjDfRRGpM3hxOrbypU2Bxy6js0n_YKXxXTsu4), [Base](https://basescan.org/address/0xD4dD9e2F021BB459D5A5f6c24C12fE09c5D45553), and [Gnosis](https://gnosisscan.io/address/0xD4dD9e2F021BB459D5A5f6c24C12fE09c5D45553?__cf_chl_rt_tk=gWbmKrrEbWHR8WcoI9fXYBOmIq7R_CMfWfMVKMIPNf8-1753369529-1.0.1.1-Q.0ND5Bbww60RT.UAZWFMcUM3bO2GYIkt7UCcalvxlg). However, [Frankencoin Pool Shares](https://etherscan.io/address/0x1bA26788dfDe592fec8bcB0Eaff472a42BE341B2) and their vote accumulation mechanism is only present on Ethereum mainnet. Nonetheless, there is a very efficient and light-weight way to mirror the proposal process on all the other chains. This is done by having a function a sync function that sends the currently accumulated number of votes for a specific address to the other chain, together with the current total number of votes. This allows a user to prove that they have veto power on mainnet. Once the proof has been made, they can freely use their veto power on the other chain. Veto power is lost again once they lose it on mainnet and some bothers synchronizing their vote count to the other chain. Anyone can synchronize the votes of any address.

## Exceptional Efficiency

Asymptotically, the Frankencoin governance system achieves the same outcome as a traditional majority vote, but much more efficiently. In the ideal case, if every participant is rational, no veto needs to be ever cast, as no one is stupid enough to make a proposal that will be declined. with fewer interventions, making it more efficient. And even if there is a bad proposal every now and then: the effort to cast a veto is much lower than the effort to hold a fully fledged on-chain vote. This makes Frankencoin one of the most efficient decentralized governance system ever conceived.


# Notification Bot

The Frankencoin API Telegram Bot is a communication tool designed to keep users informed about various activities and updates within the Frankencoin ecosystem.

The Frankencoin API Telegram Bot is a communication tool designed to keep users informed about various activities and updates within the Frankencoin ecosystem.

* Welcome and Help Functions: The bot welcomes new users or groups and provides help information on demand.
* Basic Messages: The bot will inform any user or group about basic updates.
* Subscription Management: Users can subscribe to different types of updates using specific handles like /MintingUpdates.
* Quick Access: The bot provides direct links to the Frankencoin app, blockchain explorer for relevant addresses and transactions, and the GitHub repository.

## How to find it?

Telegram Name: **@FrankencoinApiBot**

<figure><img src="/files/dtVzed8kHYS4ropeaplX" alt=""><figcaption><p>Telegram QR Code</p></figcaption></figure>

You can also find the bot by clicking here: <https://t.me/FrankencoinApiBot>

## Basic Messages

#### Welcome and Environment Information

The bot welcomes new users or groups and provides help information on demand. It shares details about the current API version, blockchain network, and timestamp of messages.

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

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

#### Minter Proposals

The bot announces new minter proposals, including application periods and relevant transaction details.

<br>

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

#### Minter Proposals Vetoed

The bot notifies if a mint proposal got vetoed through the governance process.

<figure><img src="https://github.com/Frankencoin-ZCHF/gitbook/raw/telegram-bot/.gitbook/assets/Screenshot%202024-09-26%20at%2012.13.41%E2%80%AFPM.png" alt=""><figcaption></figcaption></figure>

#### Position Proposals

The bot notifies users about new position proposals, including details such as minting limits, interest rates, and collateral information.

<figure><img src="https://github.com/Frankencoin-ZCHF/gitbook/raw/telegram-bot/.gitbook/assets/Screenshot%202024-09-26%20at%2012.10.32%E2%80%AFPM.png" alt=""><figcaption></figcaption></figure>

#### Challenges Started

It informs users when new challenges are started, providing information about the challenger, challenge size, and auction details.

<figure><img src="https://github.com/Frankencoin-ZCHF/gitbook/raw/telegram-bot/.gitbook/assets/Screenshot%202024-09-26%20at%2012.16.07%E2%80%AFPM.png" alt=""><figcaption></figcaption></figure>

## Subscription Handels

Use the command `/help` to get your subsctiption state. Use and handle to subscribe or unsubscribe, its a toggle function.

<figure><img src="https://github.com/Frankencoin-ZCHF/gitbook/raw/telegram-bot/.gitbook/assets/Screenshot%202024-09-26%20at%2012.25.01%E2%80%AFPM.png" alt=""><figcaption></figcaption></figure>

<figure><img src="https://github.com/Frankencoin-ZCHF/gitbook/raw/telegram-bot/.gitbook/assets/Screenshot%202024-09-26%20at%2012.25.11%E2%80%AFPM.png" alt=""><figcaption></figcaption></figure>

#### Minting Updates

It provides updates on minting activities, including changes in minted amounts, collateral ratios, and fee information.

<figure><img src="https://github.com/Frankencoin-ZCHF/gitbook/raw/telegram-bot/.gitbook/assets/Screenshot%202024-09-26%20at%2012.15.21%E2%80%AFPM.png" alt=""><figcaption></figcaption></figure>


# Risks

A long list of all kind of risks that users of the Frankencoin system are exposed to and how to handle them.

## For Frankencoin Holders

### Fundamental Depeg

The fundamental value of the Frankencoins in circulation rests on the market value of the collateral in the system. If the value of the collateral that backs the Frankencoins drops too much and too fast, the fundamental value of one Frankencoin falls below 1.00 CHF (a downwards depeg).

All collateral in the system is bound to specific positions and belongs to the respective owner of that position. The collateral of one position cannot be used to cover the debt of another position. **This means that the Frankencoin can depeg even if the total collateral exceeds the total amount of Frankencoins in the system.** Also, the Frankencoin system relies on a relatively slow liquidation mechanism that is based on auctions that can last multiple days. Historically, this would have been a strength as sudden crashes - for example due to a cascade of forced liquidations in the overall markets - tend to be followed by technical rebounds. However, there is no technical rebound if the fundamental value of a collateral drops suddenly - for example if a company whose shares are used as a collateral is unexpectedly closed by a regulator or if the main production site of a tokenized company is flooded without having appropriate insurance coverage. While liquidation cascades tend to pull down the whole market at once, idiosyncratic risks of individual collateral assets can often be addressed through diversification. That is why all participants of the Frankencoin ecosystem should favor having a wide range of supported collateral assets.

To mitigate the risk of a deped due to unsound collateral, there are three lines of defense. The first line of defense is the overcollateralization of each individual position — the reserves of a position. If the reserves of a position are 20%, all losses up to 20% below the liquidation price are absorbed by the position owner. The second line of defense is the equity capital of the system. Once the equity capital is depleted, all Frankencoin Pool Shares are worthless. Still, there is a third line of defense, the third line bailout (see the relevant section further below for minter risks), which consumes the reserves of the other positions. Only if all reserves and the equity capital is consumed, there is a depeg of the fundamental value of the Frankencoin below one Swiss franc.

### Collapse of Connected Stablecoins

The collapse of a trusted external Swiss franc stablecoin that is connected to the Frankencoin system through a \[stablecoin bridge]\(<https://app.frankencoin.com/swap>) can lead to a substantial loss for the Frankencoin system. At the time of writing, the only such trusted external stablecoin is the VCHF by \[VNX]\(<https://vnx.li/>). In case of a failure of the issuer to keep adequate reserves, VCHF can become worthless, leading to a loss for the Frankencoin system. This risk is mitigated by having a built-in limit for how much can be minted through a stablecoin bridge as well as an expiration date. For the current VCHF bridge, the expiration date is April 15th 2026. In case of a loss due to the collapse of a connected stablecoin, it is recommended to propose a special purpose minting module to reduce burn the corresponding ZCHF amount from the equity reserve in order to ensure that all ZCHF in circulation enjoy full backing.

### CCIP and Blockchain Hacks

There is a risk that an attacker finds a way to bypass the system's rules to mint large amounts of Frankencoins, thereby rendering all Frankencoins worthless or almost worthless. This can happen due to a governance failure or a technical exploit of the system (see the relevant sections). But it can also happen through an attack on a system the Frankencoin relies on. Such systems are the CCIP protocol as well as all the blockchains the Frankencoin is deployed on.

Frankencoin relies on the \[Cross-Chain Interoperability Protocol by Chainlink]\(<https://chain.link/cross-chain>) to transfer Frankencoins across blockchains, for example from Ethereum mainnet to the Base or Arbitrum network. If any of the chains that Frankencoin is bridged to gets hacked or if the bridge logic itself is compromised, an attacker might gain the ability to mint arbitrary amounts of Frankencoins on the hacked chain and then send them back to mainnet, thereby the Frankencoins worthless due to total oversupply. The bridges between the different blockchains are equipped with flow limits and it is possible to enact an emergency cut-off through swift governance action through a module called \[CCIPAdmin]\(<https://etherscan.io/address/0x2527ec458c863073a303CF0a362Bf78aDD5dFEf8#code>). These functions are \[not yet exposed in the frontend]\(<https://github.com/Frankencoin-ZCHF/frankencoin-dapp/issues/293>) and need to be called directly through a tool like Etherscan.

### Temporary Depeg / Liquidity Risk

There is a risk that you cannot buy or sell ZCHF at its fundamental value because the market is not liquid enough to satisfy the current demand. Academics often measure market liquidity by testing how much slippage a large trade causes. Slippage is the extent to which the price moves when buying or selling. For example, the indicated ZCHF price on an exchange might be 1.00 CHF, but when selling 100'000 ZCHF at once, the price you get might be only 0.98 CHF as your order eats through the order book. In that example, slippage would be 2%. A widespread method to handle this risk is to slice large orders into several smaller one to give the market time to recover. However, obvious slicing can increase frontrunning risks as an attentive market maker might anticipate subsequent trades.

## For Minters (Borrowers)

### Missing Maturity Dates

All minter's positions come with a maturity date that can be years in the future. It is recommended that you mark the due date of your positions in your personal calendar. Furthermore, there is [Notification Bot](/telegram-api-bot) that can notify you about expiring positions in general. When missing the maturity date of a position, it falls into a liquidation mode where the posted collateral is sold to the highest bidder in a Dutch auction, starting at 10x the liquidation price. The proceeds are used to repay the position and you can recover the excess amount, but you will lose the minter's reserve.

### Missing Market Movements

Minter's that do not keep an eye on the market are at risk of being forcefully liquidated when the market price falls below the liquidation price. It is highly recommended to watch the markets and to subscribe to the [Notification Bot](/telegram-api-bot) in order to be notifed when the market price approaches the liquidation price of a position. In the event of a liquidation, the minter loses the minter's reserve.

### Third Line Bailout

The Frankencoin system has three lines of defense to hold the peg of the Frankencoin when collateral falls below the liquidation price. The first line of defense is the reserve of the position itself whose collateral has fallen below the liquidation price, typically 25% or so. If the price falls by more than that, i.e. 40% or so, the minter's reserve of that position does not suffice and the system uses equity capital to cover the loss. But if that does not suffice either, all the minter reserves are collectively used to cover the loss. So even if your position is perfectly sound, you might still have to pay for the losses caused by the unsound position of others. This risk is best addressed by acquiring some Frankencoin Pool Shares (FPS) and to activaly participate in the system's governance. You (or you together with others) only need 2% of the votes to veto collaterals that you deem unsound.

### Swiss Franc Appreciation

By borrowing a Swiss franc stablecoin, you take what trades call a "short" position in Swiss francs. Being short means that your portfolio loses value as the Swiss franc appreciates. And historically, the Swiss franc is the most stable currency in the world. A few years ago, a lot of [home owners in Eastern Europe took mortgages in Swiss francs](https://www.tandfonline.com/doi/full/10.1080/13604813.2023.2229695). They thought they are smart as that allowed them to get mortgages at very low nominal interest rates. However, in the end, this cost them dearly as the price of the Swiss franc appreciated much faster than they anticipated and their debt grew significantly when measured in the local currencies. In efficient markets, the rule of [Uncovered Interest Rate Parity](https://en.wikipedia.org/wiki/Interest_rate_parity) holds. This rule says that if the dollar interest is 5% and the Swiss franc interest is 1%, the market expects the Swiss franc to appreciate 4% per year against the dollar. This rule also means that you don't gain anything at average by taking debt in a different currency. However, markets are often not efficient, especially when there is political interest to keep interest rates artificially low, putting pressure on the Swiss franc to appreciate more than interest rates would suggest, thereby also increasing the risks associated with being short the Swiss franc.

### Short Squeeze (Upwards Depeg)

This risk is similar to the appreciation risk, but with the appreciation being engineered through market manipulation. Since all Frankencoin debt is denominated in Frankencoins and not in Swiss francs, a resourceful attacker might try to do a so-called short-squeeze by cornering the ZCHF market. The attacker might observe the maturity of the outstanding Frankencoin debt and wait for large amounts being due for repayment. Once this is the case, they buy as many Frankencoins as they can ("cornering the market"), causing the price to climb far above 1.00 CHF. So when the borrowers want to repay their debt, they have to do so by buying overpriced Frankencoins from the attacker. This risk can be alleviated by rolling over debt and waiting until the peg is reached again. Also, it makes minting (or borrowing) additional Frankencoins more attractive as they can be sold at a premium to the attacker. A short-squeeze therefore also comes with significant risk also for the attacker and the longer they have to maintain the articifially high price, the more expensive the attack becomes. Nonetheless, borrowers need to be aware that the Frankencoin could trade significantly above parity for extended periods of time. As an example, between June 2022 and January 2023, the [decentralized stablecoin LUSD](https://coinmarketcap.com/currencies/liquity-usd/) traded consistently 2% and sometimes up to 5% above the peg. This was not due to a short squeeze, but due to borrowers wanting to get their ETH collateral back so they could stake them while holders of LUSDs were reluctant to sell them.

### Liquidation Cascades

Liquidation cascades happen when market participants globally are overleveraged, such that a small dip can trigger a widespread sell-off as investors are forced to unwind and liquidate their positions. The presence of well-informed traders that use leverage to increase their returns reduces volatility most of the time, but at the same time creates a risk of rare extreme events. Researchers sometimes refer to this phenomoenon as [clustured volatility](http://dido.econ.yale.edu/~gean/art/p1371.pdf).

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

The chart above shows how the market behaves under the model of Thurner et al. with (blue) and without (green) leverage. One can see that in normal times, the possibility of leverage makes markets more smooth as informed traders can take loans to buy the asset when it is fundamentally underpriced. But if there is too much leverage, a small price distortion can force a cascade of liquidations, pushing the market price way below the fundamental value of the asset. Afterwards, the blue and the green line move very similarly again as the wealth of the leveraging market participants was wiped out and they lack the capital to influence the market much. Even those participants that only took moderate leverage are at risk of forced liquidations as a previously calm market falls off a cliff. This is likely what for example happened on Saturday 2026-01-31, as billions worth of crypto currencies were sold in forced liquidations and the Bitcoin price fell by 6% within hours. Traditional markets have so-called "circuit brakers" and halt trading in extreme events. Crypto markets don't have that and therefore the risk of getting caught in a market sell-off and being liquidated is elevated, especially on weekends, when trading volumes are thin. While those market participants that use leverage in the above theoretical model are those that make the most money in normal times, they suffer disproportionately in stress scenarios.

## General Risks

### Technical Attacks

Despite several security audits, we cannot rule out that the smart contracts of the Frankencoin system can be exploited through an elaborate attack. In the worst case, such an attack would allow someone to print arbitrary amounts of Frankencoins or to get control of other people's Frankencoins.

There are also some potential smaller attacks that were discovered in the security audits that we deemed not worth fixing. These include the potential to be frontrun by bots when interacting with the Frankencoin system. For example, an MEV-bot might frontrun a bid in an auction. One way to address this is to use wallets (like Metamask) that do not send their transactions to the public mempool so your transactions are not visible to others until they are executed.

### Frontend Hacks

Some of the [most spectacular crypto heists](https://www.sygnia.co/blog/sygnia-investigation-bybit-hack/) were done through frontend hacks. If an attacker succeeds in getting access to the frontend servers or succeeds in sneaking malicious code into the frontend, they can manipulate the data shown in the frontend and the actions triggered when interacting with the frontend. For example, clicking the "transfer" button in a hacked Frankencoin frontend might trigger a transfer to a completely different address than what is indicated on the website. The best way to address this is to be very attentive to what is being signed when verifying transactions in your wallet. Unfortunately, the transaction data typically shown in wallets is rather cryptic, especially for non-standard transactions. Some wallets, for example Metamask, simulate and show the anticipated token transfers of a transaction, which helps a lot.

### Human Errors

Many users rely on non-custodial wallets. This brings independence, but also responsibility. A lot of crypto assets have already been lost by users who did not back up their seed phrase or who accidentally sent funds to the wrong account. The best way to address this problem is to store your crypto assets with an intermediary like [Bitcoin Suisse](https://bitcoinsuisse.com/) or [Coinbase](https://www.coinbase.com/). However, that makes you dependent again.

### Governance Failures

The Frankencoin is designed to incentivize all system participants to behave well. Nonetheless, there is a significant risk that system participants turn lazy and inattentive, thinking that others will take care of the governance for them. In such a scenario, the FPS holders might fail to veto an unsound collateral or fail to veto a faulty extension of the system. To address this issue, all system participants are encouraged to actively take part in the governance process. Frankencoin's governance system allows anyone to make proposal and only has a very low entry barrier for casting vetos, making it more decentralized by nature. Nonetheless, a governance failure can lead to the destruction of the whole system within days. For example, if an unsound collateral is approved and used to mint irresponsible amounts of Frankencoins, the Frankencoin and the Frankencoin Pool Shares will lose their value very quickly.

### Regulatory Risks

While there are established rules to [legally classify](https://www.frankencoin.com/compliance#compliance-summary) crypto currencies like the Frankencoin, interacting with decentralized system still comes with regulatory uncertainty. For example, there is uncertainty about when a DeFi user has the duty to identify a counterparty under the travel rule or other potentially applicable laws. Therefore, financial institutions are often hesitant to interact with decentralized finance protocols.

Also, the tax implications of holding crypto assets are often unclear. For the Frankencoin system, one can assume that one Frankencoin has a tax value of one Swiss franc and that interests earned from the savings module are taxable income. To simplify tax reporting, Frankencoin Association has created a [report tool](https://app.frankencoin.com/report) that summarizes your holdings and incomes by the end of each year.

There is a non-negligible risk that the responsible authority arrives at the (wrong) conclusion that the Frankencoin system violates financial market laws, which could lead them to attempting to shut down the system. They could for example try to do so by scaring active ecosystem participants from taking part in the governance process, which could lead to a governance failure and in turn severe financial harm for all participants. Frankencoin Association is mitigating this risk by being responsive to regulatory inquiries and by seeking legal certainty for all system participants.

### Unknown Risks

There are likely additional risks that have not been foreseen (or neglected) by the authors of this page. If you are aware of any such risk, please let us know through the [community channel](https://t.me/frankencoinzchf).


# Background FAQ

Some questions we think might get frequently asked.

### What is this all about?

From a bird's eye perspective, the Frankencoin system resembles a bank that creates money against collateral. In the traditional banking system, this can for example be done with real estate. The bank accepts a house as collateral, and prints the agreed amount of money by adding it to that persons bank account. Then the buyer of the house can transfer the money to the seller, where it ends up as a deposit with maybe the same or another bank, thereby closing the circle. When doing so, banks need to observe some reserve and other legal requirements to ensure the mortgage is well-secured. The Frankencoin system essentially enables users to do the same, printing some money against a (hopefully) valuable collateral. Also, like a bank, the Frankencoin system has a reserve pool that resembles the equity capital of a bank and serves as a buffer to absorb risks. However, in contrast to a bank, there is nothing that qualifies as credit as the users print their money themselves, processes are largely automated and fully transparent, and there is no explicit governance besides a veto mechanism that is open for everyone with enough pool shares.

### Is the Frankencoin ecosystem useful?

If used with the necessary care, most definitely. Most of the usefulness of the Frankencoin comes from its decentralized nature. It is open, fully transparent, and freely interactible by humans and software alike. Thanks to its transparency, anyone can analyze its solvency at any moment. If it is in imbalance, it can be expected to be attacked by speculators who know exactly at which market prices the Frankencoin is not fully backed any more. The goal is not to imitate traditional banking, the goal is to create something immanently better.

### What is the main goal of the Frankencoin?

The primary objective of the Frankencoin is to establish a decentralized financial system that enables individuals to generate currency backed by collateral, akin to traditional banking practices. This initiative is driven by a commitment to transparency, decentralization, and inclusivity, aiming to empower users with the ability to mint their own Swiss Francs. By decentralizing the process of money creation, Frankencoin seeks to foster economic resilience and provide an alternative to conventional centralized financial frameworks.

### How does Frankencoin differ from other stablecoins?

Frankencoin sets itself apart from other stablecoins by employing an auction-based system for collateral determination, eliminating the need for external oracles. This approach prevents price manipulation by switching collateral assets during auctions, ensuring system integrity without relying on third-party sources. Additionally, its emphasis on collateral availability enables ongoing challengeability, while autonomous operation reduces owner intervention. Equity holders bear losses in case of insufficient auction proceeds, ensuring robust risk management within the system.

### What are Frankencoin Pool Share (FPS) tokens?

FPS tokens represent ownership in the equity reserve pool of the Frankencoin system, functioning like shares in a bank. They enable holders to earn profits from system fees, participate in governance through voting rights, and provide liquidity by minting and redeeming tokens. FPS tokens play a crucial role in maintaining stability, governance, and value creation within the Frankencoin ecosystem. Read more here: [Frankencoin Reserve Pool Shares](https://docs.frankencoin.com/reserve/pool-shares#reserve-pool-shares)

### What role do governance token holders play in the Frankencoin ecosystem?

The Frankencoin Pool Shares (FPS) represent a share in the equity capital of the system. The FPS holders get the profits (earned interests and fees) from the system, but are also covering the residual liquidation risk. Furthermore, FPS token holders accumulate voting power over time. Any FPS holder that has 2% of the votes - alone or together with others - can veto proposals.

### What opportunities does Frankencoin offer for preserving purchasing power and investment?

Frankencoin offers a stablecoin pegged to the Swiss franc, preserving purchasing power and providing an alternative to existing stablecoin models. Additionally, it allows users to leverage assets like BTC and ETH to mint new Frankencoins or invest in the future of the project through FPS tokens.

### How can individuals invest in the FPS tokens of the Frankencoin ecosystem?

**Option 1:**

* **Step 1:** Download the Frankencoin App
* **Step 2:** Click on deposit/buy
* **Step 3:** Choose either FPS on ETH or WFPS on Polygon
* **Step 4:** Pay via bank wire or credit card with Apple and Google Pay

**Option 2:**

* **Step 1:** Head over to <https://app.frankencoin.com/equity>
* **Step 2:** Connect your wallet
* **Step 3:** Choose what you would like to trade (ZCHF, FPS or WFPS)
* **Step 4:** Choose the target asset
* **Step 5:** Mint new FPS or redeem your FPS. Observe the minimum holding time of 3 months before FPS can be redeemed

**Option 3:**

* **Step 1:** It’s possible to use the following website: <https://frankencoin.dfx.swiss/>
* **Step 2:** Connect with Metamask
* **Step 3:** Either choose FPS on ETH or WFPS on Polygon
* **Step 4:** Pay via bank wire or credit card with Apple and Google Pay

**Option 4:**

* **Step 1:** Via Uniswap (ZCHF to FPS/FPS)

**Option 5:**

* **Step 1:** Polygon: Via Uniswap (ZCHF to WFPS)

**Tip:** Due to fees, it might be better to use Polygon if the value is below \~1 000 ZCHF.

### How long is the locking period for FPS?

FPS are not locked. FPS can be transferred at any time. FPS can also be sold at any time. FPS can be exchanged for WFPS and sold via Uniswap. All this is possible and there is no lock. If you want to destroy FPS with the smart contract, these FPS must be at least 3 months old. However, this is not a sale but a destruction of the FPS. After that, these FPS no longer exist and the quantity in circulation of all FPS has decreased.

### Is the Frankencoin a security?

No, it neither qualifies formally nor functionally as a security. It does not qualify formally as a security under Swiss law as it does not represent a claim towards an issuer. Also, it does not qualify functionally as a security as it does not serve a financing purpose. For more information, please read the [memorandum](https://github.com/Frankencoin-ZCHF/www/blob/main/documents/ZCHF_FPS_Memo.pdf) by Swiss law firm LEXR.

### Is Frankencoin political?

Yes, to some extent. The Frankencoin addresses issues within the current system of money creation, highlighting how it distorts capital allocation. For example, regulatory constraints may incentivize investments that aren't optimal for society. Traditional capital requirements tend to favor certain sectors like real estate and government bonds over others. By leveraging blockchain technology, Frankencoin offers an alternative outside the traditional financial system. It seeks to empower individuals by allowing them to create their own money, potentially leading to a stronger economy and more growth if used responsibly.

### When obtaining Frankencoin against a collateral, is that really *borrowing*?

We are having an ongoing debate on whether the term "borrow", "mint", or something entirely different should be used. "Borrow" is more intuitively understandable, but it implies the presence of a counterparty and by extension that the Frankencoin system is a legal entity - which it is not as the law does not recognize distributed systems as such. Also, the term "borrow" is usually applied to things that already exist before they are being borrowed. So the alternative term that could be used is simply "mint", which is technically correct as that is what happens when obtaining Frankencoins against a collateral: new tokens are being minted using the mint function of the Frankencoin smart contract. However, the term "mint" does not cover everything that is happening, so while it is more accurate than "borrow", it is less complete. "Borrow" correctly implies that at some point in time, the created Frankencoins need to be returned, which "mint" does not. Given the choice between the more complete but slightly misleading "borrow" and the more accurate but incomplete "mint", we decided to label the according buttons "borrow".

### Are Reserve Pool Shares securities?

Functionally, securities can be used to invest in a system and allow the holders to make capital gains (or losses) as the system grows (or shrinks). This is how the system compensates the FPS holders for their willingness to stabilize the system with their capital. However, the FPS tokens lacks some of the most important economic functions of a security. Most notably, when buying newly issued FPS tokens, no funds are moved into the hands of a third party. Instead, the funds are just locked until used for one of the pre-defined purposes on the blockchain. Swiss law firm LEXR also believes that the FPS does likely not qualify as a security. For more information, please read the [memorandum](https://github.com/Frankencoin-ZCHF/www/blob/main/documents/ZCHF_FPS_Memo.pdf).


# Developers

The Frankencoin API provides comprehensive access to all data within the Frankencoin ecosystem. This RESTful API enables developers to integrate Frankencoin functionality into their applications, build analytics tools, monitor positions, and interact with the protocol programmatically.

## Base URL

```
https://api.frankencoin.com
```

## API Features

The Frankencoin API is organized into several controllers, each serving specific data about different aspects of the ecosystem:

### Core Controllers

* [**Ecosystem**](/api-docs/ecosystem) - Get information about the Frankencoin token, FPS, minters, and collateral
* [**Positions**](/api-docs/positions) - Manage and query collateralized lending positions
* [**Challenges**](/api-docs/challenges) - Access liquidation challenge and auction data
* [**Prices**](/api-docs/prices) - Access price feeds and historical price data for collateral assets
* [**Savings**](/api-docs/savings) - Query savings module data, interest rates, and yields
* [**Transfers**](/api-docs/transfers) - Track ZCHF transfers with custom reference messages
* [**Analytics**](/api-docs/analytics) - Retrieve ecosystem-wide metrics and financial analytics

## Response Format

In general API responses are returned in JSON format. Most list endpoints follow a consistent structure:

```json
{
  "num": 100,
  "list": [...]
}
```

or

```json
{
  "num": 100,
  "addresses": [...],
  "map": {...}
}
```

## Data Precision

Financial amounts in the API are typically represented as strings to preserve precision:

* Token amounts are in **wei** (1e18 precision for 18-decimal tokens)
* Timestamps are **Unix epoch** (seconds)
* Interest rates are in **PPM** (parts per million, e.g., 20000 = 2%)

## Interactive Documentation

For interactive API exploration with request/response examples, visit the Swagger documentation:

```
https://api.frankencoin.com
```

## Rate Limiting

The API currently has no rate limiting, but please use reasonable request rates to ensure fair access for all users.

## Support

For API questions or issues:

* GitHub Smart Contracts: [Frankencoin ZCHF](https://github.com/Frankencoin-ZCHF/FrankenCoin)
* GitHub API NestJS: [Frankencoin API](https://github.com/Frankencoin-ZCHF/frankencoin-api)
* NPM Package for ABIs, Addresses, SupportedChains, ...: [NPM Package Core](https://www.npmjs.com/package/@frankencoin/zchf)
* NPM Package for API Types, Return Types, ...: [NPM Package API Types](https://www.npmjs.com/package/@frankencoin/api)
* Swagger Docs: [api.frankencoin.com](https://api.frankencoin.com)


# Ecosystem API

The Ecosystem API provides access to core protocol data including information about the Frankencoin (ZCHF) token, Frankencoin Pool Shares (FPS), minter contracts, and approved collateral types. This set of controllers offers a comprehensive view of the protocol's infrastructure.

## Overview

The Ecosystem API is organized into four main controllers:

1. **Frankencoin Controller** - ZCHF token information and multichain data
2. **FPS Controller** - Frankencoin Pool Shares token and reserve data
3. **Minter Controller** - Minting hub contracts and their status
4. **Collateral Controller** - Approved collateral types and their properties

## Frankencoin Controller

Access comprehensive information about the ZCHF stablecoin across all supported blockchains.

### Endpoints

* `GET /ecosystem/frankencoin/info` - Complete Frankencoin ecosystem information
* `GET /ecosystem/frankencoin/keyvalues` - Key-value mapping of ecosystem metrics and counters
* `GET /ecosystem/frankencoin/totalsupply` - Historical time series of total supply with multichain allocation

### What It Provides

#### `/info` endpoint:

* **ERC20 Details**: Token name, symbol, decimals
* **Multichain Data**: Supply and contract addresses on each blockchain (Ethereum, Optimism, Base, Arbitrum, Polygon, Gnosis, Avalanche, etc.)
* **Token Metrics**: Current USD price, total supply across all chains
* **FPS Information**: FPS price, supply, and market cap
* **TVL**: Total value locked in USD and CHF

#### `/keyvalues` endpoint:

* Transaction counters and analytics
* Equity metrics (investments, redemptions, profits/losses)
* Minter statistics
* Position and challenge counters
* Savings totals
* Transfer reference counts

#### `/totalsupply` endpoint:

* Historical daily snapshots of total supply (last 1000 days)
* Multichain allocation breakdown per timestamp
* Supply evolution tracking

### Use Cases

* Monitor ZCHF distribution across blockchains
* Track total protocol TVL
* Display current token price and supply
* Build multichain explorers
* Analyze which chains have the most ZCHF activity
* Track ecosystem-wide counters and metrics
* Chart historical supply growth and distribution

## FPS Controller

Query data about the Frankencoin Pool Shares (FPS) token, which represents ownership in the protocol's equity pool.

### Endpoints

* `GET /ecosystem/fps/info` - Complete FPS token information

### What It Provides

* **Token Information**: Name, symbol, decimals, contract address
* **Supply Metrics**: Total supply, circulating supply
* **Pricing Data**: Current FPS price in ZCHF
* **Reserve Data**: Total equity, minting capacity
* **Multichain Deployment**: FPS distribution across chains
* **Market Data**: Market cap, price history

### Use Cases

* Calculate FPS token valuation
* Monitor reserve equity backing
* Track FPS distribution across chains
* Analyze investment returns for FPS holders
* Build FPS price charts and calculators

## Minter Controller

Access information about minter proposals, which are requests to authorize new minting contracts in the Frankencoin ecosystem.

### Endpoints

* `GET /ecosystem/minter/list` - List all minter proposals across all chains
* `GET /ecosystem/minter/list/:chainId` - Get minter proposals filtered by specific chain

### What It Provides

* **Proposal Details**: Minter contract address, application period, application fee
* **Status Information**: Application date, denial status (if any)
* **Proposer Info**: Address of the proposer, suggestor
* **Metadata**: Transaction hash, proposal description, denial reason
* **Chain Info**: Which blockchain the minter operates on

### Use Cases

* Track new minter contract proposals
* Monitor minter approval status
* Filter minters by specific blockchain
* Verify minter contract addresses for integrations
* Analyze minter proposal activity across chains
* View denied proposals and reasons

## Collateral Controller

Query approved collateral types and their properties, usage statistics, and position relationships.

### Endpoints

* `GET /ecosystem/collateral/list` - Array list of all collateral tokens used in positions
* `GET /ecosystem/collateral/mapping` - Collateral information as an address-keyed mapping
* `GET /ecosystem/collateral/positions` - Mapping of collateral addresses to position addresses
* `GET /ecosystem/collateral/positions/details` - Mapping of collateral addresses to complete position details
* `GET /ecosystem/collateral/stats` - Comprehensive statistics for each collateral type

### What It Provides

#### `/list` and `/mapping` endpoints:

* **Token Details**: Address, name, symbol, decimals for each collateral type

#### `/positions` endpoint:

* Collateral token information
* Count of positions using each collateral
* Array of position contract addresses per collateral

#### `/positions/details` endpoint:

* Everything from `/positions` plus:
* Complete position objects for each collateral type
* Full position details including balances, minted amounts, owners

#### `/stats` endpoint:

* **Position Counts**: Total, open, requested, closed, denied, originals, clones
* **Financial Metrics**: Total minted, total limits, collateral balance
* **Pricing**: Current collateral price in USD and CHF
* **TVL**: Total value locked per collateral and overall system TVL

### Use Cases

* Display available collateral options to users
* Validate collateral addresses before position creation
* Show collateral statistics (most popular, highest minted amounts)
* Filter positions by collateral type
* Build collateral comparison and analysis tools
* Monitor TVL distribution across collateral types
* Analyze collateral concentration risk
* Track which collaterals are most actively used

## Integration Examples

### Building a Position Creator UI

1. Fetch approved collateral types: `GET /ecosystem/collateral/list`
2. Get active minters: `GET /ecosystem/minter/list`
3. Display collateral options with current prices from Prices API
4. Use minter address to interact with smart contracts

### Protocol Dashboard

1. Fetch Frankencoin info for total supply and TVL: `GET /ecosystem/frankencoin/info`
2. Get FPS data for equity metrics: `GET /ecosystem/fps/info`
3. Pull analytics for profit/loss: `GET /analytics/profitLossLog`
4. Display collateral breakdown: `GET /ecosystem/collateral/list`

### Multichain Explorer

1. Query Frankencoin info to get all chain deployments
2. For each chain, display supply, contract address, and activity
3. Show total supply sum across all chains
4. Highlight primary vs secondary chains by supply

## Data Structure Notes

### Chain IDs

Common chain IDs in the ecosystem:

* `1` - Ethereum Mainnet
* `10` - Optimism
* `100` - Gnosis Chain
* `137` - Polygon
* `8453` - Base
* `42161` - Arbitrum
* `43114` - Avalanche

### Version Numbers

* **V1**: Original protocol contracts
* **V2**: Current generation with enhanced risk parameters

### Status Values

* **active**: Currently operational and recommended
* **deprecated**: Older version, still functional but not recommended for new positions
* **proposed**: Under governance review
* **denied**: Rejected by governance

## Best Practices

1. **Cache Strategically**: Ecosystem data changes infrequently, cache for 5-10 minutes
2. **Multichain Handling**: Always check chainId to ensure you're using the correct contract
3. **Version Awareness**: Prefer V2 contracts unless specifically working with legacy positions
4. **Status Checks**: Verify active status before allowing users to interact with minters or collateral


# Positions API

The Positions API provides comprehensive access to all collateralized lending positions in the Frankencoin ecosystem. Positions represent borrowing contracts where users lock collateral to mint ZCHF stablecoins.

## Overview

A **position** is a smart contract that holds collateral and allows the owner to mint ZCHF against it. The Positions API enables you to:

* Query all positions and their current state
* Filter positions by status (open, closed, pending)
* Track position ownership and transfers
* Monitor minting activity and history
* Analyze owner debt and fee payments over time

## Key Concepts

### Position Types

* **Original Positions**: Newly proposed positions that undergo a voting period before activation
* **Clone Positions**: Fast-tracked positions based on existing approved collateral types
* **Version 1 vs Version 2**: The protocol has evolved, with V2 positions including additional risk parameters

### Position States

* **Open**: Active positions available for minting
* **Closed**: Positions that have been terminated
* **Denied**: Positions rejected during the voting period
* **Pending**: Newly requested positions awaiting approval (typically within 5 days of creation)

### Minting Updates

Every time a position is adjusted (minting, burning, collateral changes, price adjustments), a **minting update** event is recorded. These provide a complete audit trail of position activity.

## Main Endpoints

### Position Queries

* `GET /positions/list` - Retrieve all positions with complete details
* `GET /positions/mapping` - Get positions as an address-keyed object for efficient lookup
* `GET /positions/open` - Filter for only active, open positions
* `GET /positions/requests` - View recently requested positions awaiting approval
* `GET /positions/owners` - Group positions by owner address

### Minting History

* `GET /positions/mintingupdates/list` - Get latest minting update events across all positions
* `GET /positions/mintingupdates/mapping` - Map minting updates by position address
* `GET /positions/mintingupdates/position/:version/:address` - Get history for a specific position
* `GET /positions/mintingupdates/owner/:address` - Get all minting activity for an owner

### Owner Analytics

* `GET /positions/owner/:address/fees` - Track fee payments over time
* `GET /positions/owner/:address/debt` - View historical debt evolution
* `GET /positions/owner/:address/history` - See which positions were owned when
* `GET /positions/owner/:address/transfers` - Monitor position ownership transfers

## Use Cases

### Portfolio Monitoring

Track all positions owned by a specific address to monitor collateralization ratios, debt levels, and fees paid:

```
GET /positions/mintingupdates/owner/0x963eC454423CD543dB08bc38fC7B3036B425b301
```

### Position Discovery

Find positions available for cloning by filtering for open original positions with specific collateral types:

```
GET /positions/open
```

### Risk Analysis

Monitor newly requested positions to assess protocol risk and participate in governance:

```
GET /positions/requests
```

### Historical Analysis

Track how a position has evolved over time by reviewing all minting updates:

```
GET /positions/mintingupdates/position/2/0x826C54287c0C1E2A4D0fbF81E2e734c85C48d3f4
```

## Data Structure

### Position Object

Each position includes:

* **Identification**: position address, version, owner
* **Collateral Details**: collateral token, balance, decimals, name, symbol
* **Minting Parameters**: limits, available capacity, amount minted, interest rate, fees
* **Status Flags**: isOriginal, isClone, denied, closed
* **Timestamps**: creation, start, cooldown, expiration, challenge period

### Minting Update Object

Each update event contains:

* **Position Info**: position address, owner, collateral details
* **Adjustment Data**: size changed, price adjusted, amount minted/burned
* **Fee Information**: fees paid, timeframe, annual interest rate
* **Metadata**: transaction hash, timestamp, version

## Notes

* All amounts are represented as strings in wei (1e18 for 18-decimal tokens)
* Interest rates are in PPM (parts per million): 20000 PPM = 2% annual
* The API returns up to 1000 most recent records for minting updates and historical queries
* Position addresses are unique identifiers and can be used across endpoints


# Challenges API

The Challenges API provides access to liquidation challenges and auction data within the Frankencoin ecosystem. Challenges are the protocol's mechanism for maintaining system health by allowing anyone to liquidate undercollateralized positions.

## Overview

A **challenge** occurs when someone believes a position is undercollateralized and initiates a liquidation process. The Challenges API enables you to:

* Query all challenges and their outcomes
* Track active and historical auctions
* Monitor bidding activity
* Analyze challenge success rates by position, challenger, or collateral type
* Identify liquidation opportunities

## Key Concepts

### How Challenges Work

1. **Initiation**: Anyone can challenge a position they believe is undercollateralized
2. **Duration**: Challenges run for a fixed period determined by the position's approval method
3. **Bidding**: Other users can bid to take over the collateral by repaying debt
4. **Settlement**: When the challenge period ends, collateral is distributed based on bids received

### Challenge Status

* **Success**: Challenge completed successfully, position was liquidated
* **Failed**: Challenge did not succeed (rare, but possible if position improves)
* **Active**: Challenge currently in progress (bidding open)

## Main Endpoints

### Challenge Queries

* `GET /challenges/list` - Retrieve all challenges with complete details
* `GET /challenges/mapping` - Get challenges as an ID-keyed object
* `GET /challenges/prices` - View challenges grouped by liquidation price
* `GET /challenges/positions` - Group challenges by position address
* `GET /challenges/challengers` - Group challenges by challenger address

### Bid Queries

* `GET /challenges/bids/list` - Get all bids across all challenges
* `GET /challenges/bids/mapping` - Map bids by challenge ID
* `GET /challenges/bids/challenges` - Group bids by challenge
* `GET /challenges/bids/positions` - View bids organized by position
* `GET /challenges/bids/bidders` - Track bidding activity by bidder address

## Use Cases

### Liquidation Monitoring

Track all challenges to understand liquidation events and their outcomes:

```
GET /challenges/list
```

### Challenger Analysis

Identify the most active challengers in the ecosystem:

```
GET /challenges/challengers
```

### Position Risk Assessment

See which positions have been challenged historically to assess risk:

```
GET /challenges/positions
```

### Auction Participation

Monitor active challenges and place bids to acquire collateral at liquidation prices:

```
GET /challenges/bids/list
```

### Market Analysis

Analyze liquidation prices to understand market conditions and collateral value perceptions:

```
GET /challenges/prices
```

## Data Structure

### Challenge Object

Each challenge includes:

* **Identification**: challenge ID, version, challenge number
* **Participants**: position address, challenger address
* **Timing**: start time, creation time, duration
* **Financial Data**: size, liquidation price, filled size, acquired collateral
* **Bidding Info**: number of bids received
* **Outcome**: status (Success, Failed, Active)

### Bid Object

Each bid contains:

* **Challenge Reference**: challenge ID, position, challenger
* **Bidder Info**: bidder address, bid timestamp
* **Bid Details**: bid amount, price, filled amount
* **Collateral**: amount of collateral acquired
* **Metadata**: transaction hash, version

## Notes

* Challenge durations vary based on how the position was approved (common durations are 86400 seconds or 604800 seconds)
* Liquidation prices (`liqPrice`) can be very high, indicating positions that were severely undercollateralized
* The `filledSize` shows how much of the challenge was successfully liquidated through bids
* `acquiredCollateral` represents the total collateral distributed to bidders
* Most challenges result in "Success" status, indicating the liquidation mechanism is working effectively

## Historical Significance

Challenge data provides valuable insights into:

* Protocol health and risk management effectiveness
* Collateral volatility and market stress events
* User participation in liquidation mechanisms
* Position management behavior (frequent challenges may indicate poor risk management)


# Prices API

The Prices API provides access to current and historical price data for all collateral assets in the Frankencoin ecosystem, as well as system-wide collateralization ratios. This is essential for monitoring position health, calculating liquidation thresholds, and displaying accurate financial information.

## Overview

The Prices API enables you to:

* Query current prices for all collateral tokens
* Access historical price data for charting and analysis
* Monitor collateralization ratios across the ecosystem
* Track price feeds for specific collateral assets
* Analyze price trends over time

## Key Concepts

### Price Sources

Prices in the Frankencoin ecosystem come from:

* On-chain oracles (Chainlink, Uniswap TWAP, etc.)
* Position-specific price feeds set during creation
* Aggregated market data

All prices are denominated in CHF (Swiss Francs) or ZCHF.

### Collateralization Ratios

Two key ratios track ecosystem health:

* **Ratio by Free Float**: Collateral value / circulating ZCHF supply
* **Ratio by Total Supply**: Collateral value / total ZCHF supply

These ratios indicate how well-backed the ZCHF stablecoin is by collateral.

## Main Endpoints

### Prices Controller

#### Current Prices

* `GET /prices/ticker/:ticker` - Get price for a specific ticker symbol (e.g., WBTC, WETH, FPS)
* `GET /prices/list` - Get all token prices with metadata
* `GET /prices/mapping` - Get prices as address-keyed mapping for efficient lookup

#### Token Information

* `GET /prices/erc20/mint` - Get Frankencoin (ZCHF) token information
* `GET /prices/erc20/fps` - Get FPS token information
* `GET /prices/erc20/collateral` - Get all collateral token information

#### Owner Analytics

* `GET /prices/owner/:address/valueLocked` - Get historical time series of total value locked by owner

#### Market Data

* `GET /prices/marketChart` - Get Frankencoin market chart data from CoinGecko (prices, market caps, volumes)

### Prices History Controller

#### Price History

* `GET /prices/history/list` - Complete price history for all collateral types with CHF prices
* `GET /prices/history/:address` - Price history for a specific collateral token

The history endpoint for a specific token returns:

* Token metadata (name, symbol, decimals, address)
* Current price in CHF
* Historical prices as a time-series (timestamp → CHF price mapping)

#### Collateralization Ratios

* `GET /prices/history/ratio` - Historical collateralization ratio data

Returns:

* Current timestamp
* `collateralRatioByFreeFloat`: Time series of ratios based on circulating supply
* `collateralRatioBySupply`: Time series of ratios based on total supply

## Use Cases

### Position Health Monitoring

Fetch current prices to calculate if positions are adequately collateralized:

```
GET /prices/list
```

Then compare position collateral value against minted amount.

### Quick Price Lookup by Ticker

Get the price of a specific token by its symbol:

```
GET /prices/ticker/WBTC
```

Returns price in USD and CHF for WBTC.

### Price Charts

Build historical price charts for collateral assets:

```
GET /prices/history/0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599
```

This returns WBTC price history that can be charted over time.

### System Health Dashboard

Monitor ecosystem-wide collateralization:

```
GET /prices/history/ratio
```

Display ratios over time to show protocol health trends.

### Liquidation Alerts

Compare current prices against position liquidation thresholds to alert users of risks:

1. Get current prices: `GET /prices/list`
2. Fetch user's positions: `GET /positions/owner/:address`
3. Calculate collateralization ratios
4. Alert if approaching liquidation levels

### Multi-Asset Analysis

Compare price performance across different collateral types:

```
GET /prices/history/list
```

Analyze which collateral types are most stable or volatile.

### Token Metadata Lookup

Get ERC20 information for system tokens:

```
GET /prices/erc20/mint        # ZCHF token info
GET /prices/erc20/fps         # FPS token info
GET /prices/erc20/collateral  # All collateral tokens
```

### Owner Value Tracking

Track historical value locked by a specific owner across all their positions:

```
GET /prices/owner/0x963eC454423CD543dB08bc38fC7B3036B425b301/valueLocked
```

Returns yearly time series of total collateral value.

### Market Data Integration

Fetch CoinGecko market data for Frankencoin:

```
GET /prices/marketChart
```

Returns prices, market caps, and trading volumes over time.

## Data Structure

### Price List Response

Array of price objects with metadata:

```json
[
  {
    "address": "0x1bA26788dfDe592fec8bcB0Eaff472a42BE341B2",
    "name": "Frankencoin Pool Share",
    "symbol": "FPS",
    "decimals": 18,
    "timestamp": 1768915146172,
    "price": {
      "usd": 1555.45,
      "chf": 1234.49
    }
  }
]
```

### Price Mapping Response

Object mapping addresses to price data:

```json
{
  "0x1ba26788dfde592fec8bcb0eaff472a42be341b2": {
    "address": "0x1bA26788dfDe592fec8bcB0Eaff472a42BE341B2",
    "name": "Frankencoin Pool Share",
    "symbol": "FPS",
    "decimals": 18,
    "timestamp": 1768915146172,
    "price": {
      "usd": 1555.45,
      "chf": 1234.49
    }
  }
}
```

### Historical Price Response (Specific Token)

```json
{
  "address": "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599",
  "name": "Wrapped BTC",
  "symbol": "WBTC",
  "decimals": 8,
  "timestamp": 1768964400003,
  "price": {
    "chf": 70374.6
  },
  "history": {
    "1759158000005": 90567.46,
    "1759161600002": 91163.2,
    ...
  }
}
```

### Collateralization Ratio Response

```json
{
  "timestamp": 1768964400003,
  "collateralRatioByFreeFloat": {
    "1759158000005": 3.138139819821414,
    "1759161600002": 3.142567234521876,
    ...
  },
  "collateralRatioBySupply": {
    "1759158000005": 1.688283955398297,
    "1759161600002": 1.689342187654321,
    ...
  }
}
```

## Understanding Collateral Ratios

### Healthy Ranges

* **Above 1.5**: System is overcollateralized, very healthy
* **1.2 - 1.5**: Normal operating range
* **1.0 - 1.2**: Warning zone, increased risk
* **Below 1.0**: Critical, system is undercollateralized

### Free Float vs Total Supply

* **By Free Float**: More conservative, only counts circulating ZCHF
* **By Supply**: Includes all ZCHF, even locked or uncirculated

The free float ratio is typically higher (more conservative) than the total supply ratio.

## Notes

### Timestamps

* Historical data uses Unix millisecond timestamps as keys
* The main `timestamp` field indicates when data was last updated

### Price Precision

* Prices are in CHF with decimal precision
* Historical endpoints may have varying time intervals between data points

### Performance Considerations

* Price history objects can be large (hundreds of data points)
* Consider caching price data with appropriate TTLs (1-5 minutes for current prices, longer for historical)
* For charting, you may want to downsample historical data client-side

### Integration Best Practices

1. **Poll Current Prices**: Update every 1-5 minutes for position monitoring
2. **Cache Historical Data**: Price history changes infrequently, cache for 15-30 minutes
3. **Handle Missing Data**: Not all timestamps will have data, interpolate when necessary for charts
4. **Monitor Ratios**: Set up alerts when collateralization ratios drop below thresholds
5. **Validate Addresses**: Always validate collateral addresses against the Collateral API before using prices

## Example: Building a Position Monitor

```javascript
// 1. Get current prices
const pricesData = await fetch('https://api.frankencoin.com/prices/mapping').then(r => r.json());

// 2. Get user positions
const positions = await fetch(`https://api.frankencoin.com/positions/owners`).then(r => r.json());
const userPositions = positions.map[address] || [];

// 3. Calculate health for each position
userPositions.forEach(position => {
  const priceInfo = pricesData[position.collateral.toLowerCase()];
  const collateralPrice = priceInfo.price.usd;
  const collateralValue = (position.collateralBalance / Math.pow(10, position.collateralDecimals)) * collateralPrice;
  const mintedValue = position.minted / 1e18;
  const ratio = collateralValue / mintedValue;

  if (ratio < 1.2) {
    console.warn(`Position ${position.position} is at risk! Ratio: ${ratio.toFixed(2)}`);
  }
});
```


# Savings API

The Savings API provides access to the Frankencoin savings module, which allows users to deposit ZCHF and earn interest. The API is organized into three controllers that handle core savings functionality, lead rate calculations, and referrer rewards.

## Overview

The Savings module enables ZCHF holders to earn yield by depositing into savings contracts. The API provides:

* Current savings balances and interest rates across all chains
* Historical interest rate changes and proposals
* Lead rate calculations (the competitive interest rate)
* Referrer information and reward tracking

## Deployed Contracts

Savings modules are deployed across multiple blockchains. The API aggregates data from all chains.

| Chain     | Address                                      | Explorer                                                                                                   |
| --------- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| Ethereum  | `0x27d9AD987BdE08a0d083ef7e0e4043C857A17B38` | [Etherscan](https://etherscan.io/address/0x27d9ad987bde08a0d083ef7e0e4043c857a17b38)                       |
| Polygon   | `0xb519bae359727e69990c27241bef29b394a0acbd` | [Polygonscan](https://polygonscan.com/address/0xb519bae359727e69990c27241bef29b394a0acbd)                  |
| Gnosis    | `0xbf594d0fed79ae56d910cb01b5dd4f4c57b04402` | [Gnosisscan](https://gnosisscan.io/address/0xbf594d0fed79ae56d910cb01b5dd4f4c57b04402)                     |
| Arbitrum  | `0xb41715e54e9f0827821a149ae8ec1af70aa70180` | [Arbiscan](https://arbiscan.io/address/0xb41715e54e9f0827821a149ae8ec1af70aa70180)                         |
| Optimism  | `0x6426324af1b14df3cd03b2d500529083c5ea61bc` | [Optimistic Etherscan](https://optimistic.etherscan.io/address/0x6426324af1b14df3cd03b2d500529083c5ea61bc) |
| Base      | `0x6426324af1b14df3cd03b2d500529083c5ea61bc` | [Basescan](https://basescan.org/address/0x6426324af1b14df3cd03b2d500529083c5ea61bc)                        |
| Avalanche | `0x8e7c2a697751a1ce7a8db51f01b883a27c5c8325` | [Snowtrace](https://snowtrace.io/address/0x8e7c2a697751a1ce7a8db51f01b883a27c5c8325)                       |

## Smart Contract Interaction

In addition to the data API described below, you can interact directly with the savings smart contract on-chain. The source code is available on [GitHub](https://github.com/Frankencoin-ZCHF/FrankenCoin/blob/main/contracts/savings/Savings.sol).

### Reading Balances

Each account's saved balance is stored in the `savings` mapping:

```solidity
mapping(address => Account) public savings;
```

To get the current saved balance (excluding accrued but uncollected interest), read `savings[owner].saved`.

To get the accrued interest that has not yet been collected, call the view function:

```solidity
function accruedInterest(address accountOwner) public view returns (uint192)
```

The total balance of a user is `savings[owner].saved + accruedInterest(owner)`.

### Adding Savings

To deposit ZCHF into the savings module, call one of the `save` functions. The caller must have approved the savings contract to spend ZCHF on their behalf.

```solidity
// Save to your own account
function save(uint192 amount) public

// Save to another account
function save(address owner, uint192 amount) public
```

Alternatively, use `adjust` to set the balance to a target amount. This will deposit or withdraw as needed:

```solidity
function adjust(uint192 targetAmount) public
```

Note that newly deposited funds are subject to a 3-day delay before interest starts accruing.

### Withdrawing Savings

To withdraw ZCHF from the savings module:

```solidity
function withdraw(address target, uint192 amount) public returns (uint256)
```

If the requested amount exceeds the available balance, the entire balance is withdrawn. The function returns the actual amount transferred.

### Refreshing Balances

Interest does not compound automatically. Anyone can trigger an accumulation of accrued interest (together with a payout of any referrer fee) by calling:

```solidity
// Refresh another account's balance
function refreshBalance(address owner) public returns (uint192)

// Shortcut for refreshBalance(msg.sender)
function refreshMyBalance() public returns (uint192)
```

Calling `refreshBalance` collects the accrued interest and adds it to the account balance. It can be beneficial to do so periodically in order to start earning interest on the previously accrued interest. This can be called by anyone — not just the account owner — making it useful for keeper bots or referrers who want to trigger their fee payout.

### Referrer and Referral Fee

Frontends and wallets can earn a share of the interest collected by their users by setting a referrer. The referral fee is capped at **25% (250,000 ppm)** and is deducted from the collected interest.

To save and set a referrer in a single transaction:

```solidity
function save(uint192 amount, address referrer, uint24 referralFeePPM) public
```

The referrer can also be set when adjusting or withdrawing:

```solidity
function adjust(uint192 targetAmount, address referrer, uint24 referralFeePPM) public
function withdraw(uint192 amount, address referrer, uint24 referralFeePPM) public
```

A user can remove their referrer at any time:

```solidity
function dropReferrer() public
```

The referral fee is paid out automatically whenever interest is collected (e.g., via `refreshBalance`). The user can change or drop their referrer at any time, so the fee is not sticky — it depends on the convenience the frontend provides.

## Key Concepts

### How Savings Works

1. Users deposit ZCHF into savings modules on any supported chain
2. Interest accrues based on the current savings rate (with a 3-day initial delay)
3. Rates are adjusted through governance proposals
4. Users can withdraw their balance plus earned interest at any time

### Interest Rate System

* **Savings Rate**: The APY paid to depositors
* **Lead Rate**: A calculated competitive rate based on various protocol metrics
* **Rate Proposals**: Changes to the savings rate must go through a governance process

## Savings Core Controller

Access core savings module data including balances, rates, and transaction history.

### Endpoints

* `GET /savings/core/info` - Complete savings ecosystem information across all chains and modules
* `GET /savings/core/ranked` - Get ranked savings accounts by balance (top 1000)
* `GET /savings/core/balance/:account` - Get savings balance for a specific account
* `GET /savings/core/activity/:account` - Get savings activity history for a specific account

### What It Provides

#### `/info` endpoint:

**Per-Chain and Module Status**:

* Module contract addresses
* Total balance in each module
* Accrued interest
* Total saved and withdrawn amounts
* Current interest rate (in PPM)
* Event counters (interest collections, rate changes, rate proposals, save/withdraw transactions)

**Aggregate Metrics**:

* Total balance across all modules
* Ratio of ZCHF total supply in savings
* Total interest collected system-wide

#### `/ranked` endpoint:

* Latest 1000 savings accounts sorted by balance
* Balance, save/interest/withdraw totals per account
* Transaction counters per account
* Chain and module information

#### `/balance/:account` endpoint:

* Account balance organized by chain ID and module address
* Created and updated timestamps
* Save, interest, and withdraw totals
* Transaction counters

#### `/activity/:account` endpoint:

* Recent activity history (Saved, Withdrawn, InterestCollected, RateChanged events)
* Amounts, balances, timestamps
* Transaction hashes and block heights
* Current rates at time of activity

### Use Cases

#### Savings Dashboard

Display total savings TVL and interest rates:

```
GET /savings/core/info
```

#### User Portfolio

Show a user's savings balance and earned interest:

```
GET /savings/core/balance/0x963eC454423CD543dB08bc38fC7B3036B425b301
```

#### Activity Tracking

View complete transaction history for an account:

```
GET /savings/core/activity/0x963eC454423CD543dB08bc38fC7B3036B425b301
```

#### Leaderboard

Display top savers in the ecosystem:

```
GET /savings/core/ranked
```

## Leadrate Controller

Access lead rate information, proposals, and approved rates across all chains and savings modules.

### Endpoints

* `GET /savings/leadrate/info` - Complete lead rate information including current rates, proposals, and open proposals
* `GET /savings/leadrate/rates` - Currently approved lead rates per chain and module
* `GET /savings/leadrate/proposals` - All lead rate proposals and their history

### What It Provides

#### `/info` endpoint:

**Current Approved Rates** per chain and module:

* Approved interest rate in PPM
* Approval timestamp and transaction hash
* Rate change counter

**Proposed Rate Changes** per chain and module:

* Proposer address
* Next rate to be applied
* Timestamp when rate will change
* Proposal transaction details

**Open Proposals**:

* Pending rate proposals awaiting execution
* Comparison between current and next rates
* Sync status across chains

#### `/rates` endpoint:

* Latest approved rate per module
* Complete historical list of all rate changes
* Rate progression over time

#### `/proposals` endpoint:

* Latest proposal per module
* Complete historical list of all proposals
* Proposer information and timing

### Use Cases

#### Rate Policy Monitoring

View current rates and pending proposals:

```
GET /savings/leadrate/info
```

Track when rate changes will take effect.

#### Rate History Analysis

Review how interest rates have evolved:

```
GET /savings/leadrate/rates
```

Analyze rate adjustment patterns.

#### Governance Participation

Monitor rate proposals to participate in governance:

```
GET /savings/leadrate/proposals
```

View who proposed changes and when they'll be executed.

## Referrer Controller

Access referrer program data for tracking savings accounts that use referrers and their earnings.

### Endpoints

* `GET /savings/referrer/:referrer/mapping` - Get all savings accounts using a specific referrer
* `GET /savings/referrer/:referrer/earnings` - Get total earnings for a specific referrer

### What It Provides

#### `/:referrer/mapping` endpoint:

**Account Mapping** organized by chain ID, module, and account address:

* Account creation and update timestamps
* Current savings balance
* Referrer address and fee percentage (in PPM)
* Total number of accounts using this referrer
* Array of all account addresses

#### `/:referrer/earnings` endpoint:

**Earnings Breakdown**:

* Nested mapping of earnings: chain → module → account → amount
* Total earnings per chain
* Overall total earnings across all chains

### Use Cases

#### Referral Program Dashboard

View all accounts referred by a specific address:

```
GET /savings/referrer/0x0000000000000000000000000000000000000000/mapping
```

For default referrer (zero address), shows unreferred accounts.

#### Referrer Rewards Tracking

Calculate total earnings for a referrer:

```
GET /savings/referrer/0x963eC454423CD543dB08bc38fC7B3036B425b301/earnings
```

Shows breakdown of earnings per account and chain.

#### Referral Performance Analysis

Combine both endpoints to analyze referrer performance:

```
GET /savings/referrer/:address/mapping  # Get account count
GET /savings/referrer/:address/earnings # Get total rewards
```

## Data Structure

### Savings Info Response

```json
{
	"status": {
		"1": {
			// Ethereum
			"0xmodule_address": {
				"chainId": 1,
				"updated": 1768964400,
				"module": "0x...",
				"balance": "1000000000000000000000000",
				"interest": "50000000000000000000000",
				"save": "1200000000000000000000000",
				"withdraw": "200000000000000000000000",
				"rate": "500000000000000000",
				"counter": {
					"interest": 100,
					"rateChanged": 5,
					"rateProposed": 8,
					"save": 1500,
					"withdraw": 300
				}
			}
		},
		// ... other chains
		"totalBalance": 5000000.0,
		"ratioOfSupply": 0.25,
		"totalInterest": 250000.0
	}
}
```

### Account Response

```json
{
	"address": "0x963eC454423CD543dB08bc38fC7B3036B425b301",
	"chains": {
		"1": {
			"balance": "1000000000000000000000",
			"interest": "50000000000000000000"
		}
	},
	"totalBalance": "1000000000000000000000",
	"totalInterest": "50000000000000000000"
}
```

## Understanding Interest Rates

### Rate Format

Interest rates in the API are expressed in PPM (parts per million):

* `40000` = 4% APY (40000 / 1000000 = 0.04)
* `15000` = 1.5% APY (15000 / 1000000 = 0.015)

To convert to percentage: `(rate / 1000000) * 100`

Referrer fees are also in PPM.

### Rate Calculation

The lead rate is calculated using:

* Borrowing costs from positions
* FPS token earnings
* Protocol revenue
* Market conditions

## Integration Examples

### Savings Calculator

```javascript
// Fetch current rate
const savingsInfo = await fetch(
	'https://api.frankencoin.com/savings/core/info',
).then((r) => r.json());

// Get rate from Ethereum mainnet module
const ethModule = Object.values(savingsInfo.status['1'])[0];
const rate = ethModule.rate / 1000000; // Convert from PPM to decimal

// Calculate estimated earnings
const principal = 10000; // ZCHF
const timeYears = 1;
const interest = principal * rate * timeYears;
console.log(`Estimated interest: ${interest.toFixed(2)} ZCHF`);
console.log(`Current APY: ${(rate * 100).toFixed(2)}%`);
```

### Savings Tracker

```javascript
// Get user's current savings
const account = await fetch(
	`https://api.frankencoin.com/savings/core/balance/${userAddress}`,
).then((r) => r.json());

// Display across all chains and modules
Object.entries(account).forEach(([chainId, modules]) => {
	Object.entries(modules).forEach(([moduleAddress, data]) => {
		console.log(`Chain ${chainId}, Module ${moduleAddress}:`);
		console.log(
			`  Balance: ${(BigInt(data.balance) / BigInt(1e18)).toString()} ZCHF`,
		);
		console.log(
			`  Interest earned: ${(BigInt(data.interest) / BigInt(1e18)).toString()} ZCHF`,
		);
	});
});
```

## Notes

### Multichain Considerations

* Savings modules are independent per chain
* Interest rates are typically the same across all chains but can vary
* Users must deposit on each chain separately

### Rate Updates

* Interest rates can change through governance
* Check `rateProposed` vs `rateChanged` counters to see pending changes
* Historical rate data helps predict future rate trends

### Performance

* Savings info is relatively static, cache for 5-10 minutes
* Account data should be fetched more frequently (1-2 minutes) for real-time balance updates
* Referrer data changes infrequently, cache for 10-15 minutes

### Best Practices

1. **Display APY Clearly**: Always convert rates from wei to human-readable percentages
2. **Show All Chains**: Users may have savings on multiple chains
3. **Calculate Returns**: Provide calculators to show estimated earnings
4. **Historical Context**: Show rate history so users understand rate stability
5. **Referral Attribution**: If implementing referrals, always track and display referrer info


# Transfers API

The Transfers API provides access to ZCHF transfer data with custom reference messages. This enables users to attach metadata to their transfers, such as invoice numbers, payment purposes, or notes, creating an on-chain payment reference system.

## Overview

The Transfer Reference system allows ZCHF transfers to include custom string messages that are:

* Stored on-chain and indexed by the API
* Searchable by sender, recipient, reference text, or timestamp
* Useful for accounting, invoicing, and payment tracking
* Supported across all chains where ZCHF is deployed

The Transfers API enables you to:

* Query recent transfers with reference messages
* Search transfers by sender or recipient address
* Filter transfers by reference text (partial matching)
* Track transfers within specific time ranges
* Build complete transfer histories for addresses

## Key Concepts

### Transfer References

A transfer reference is a custom string attached to a ZCHF transfer transaction. Common uses include:

* Invoice numbers: `"Invoice #12345"`
* Payment purposes: `"Salary - December 2024"`
* Order IDs: `"Order-ABC-789"`
* Notes: `"Thanks for the coffee!"`

### Cross-Chain Support

Transfer references work across all chains where ZCHF is deployed:

* The `chainId` field indicates the source chain
* The `targetChain` field indicates the destination chain
* This enables tracking of bridge transfers

### Sequential Counting

Each transfer reference is assigned a unique `count` number, which:

* Increments sequentially for each referenced transfer
* Can be used to retrieve specific transfers by ID
* Helps track the total number of referenced transfers

## Main Endpoints

### List and Count

* `GET /transfer/reference/list` - Get the most recent transfer references
* `GET /transfer/reference/counter` - Get the current count (total number of transfers with references)
* `GET /transfer/reference/by/count/:count` - Retrieve a specific transfer by its count number

### Query by Address

* `GET /transfer/reference/by/from/:from` - Latest transfers sent from an address
* `GET /transfer/reference/by/to/:to` - Latest transfers received by an address
* `GET /transfer/reference/history/by/from/:from` - Complete transfer history sent from an address
* `GET /transfer/reference/history/by/to/:to` - Complete transfer history received by an address

### Query Parameters

All address-based endpoints support optional query parameters:

* `to` / `from` - Filter by the other party in the transaction
* `reference` - Search for transfers containing specific text in the reference
* `start` - Unix timestamp for the beginning of the time range (default: 0)
* `end` - Unix timestamp for the end of the time range (default: current time)

## Use Cases

### Payment Tracking

Track all payments sent or received by an address with reference messages:

```
GET /transfer/reference/by/from/0x963eC454423CD543dB08bc38fC7B3036B425b301
```

### Invoice Verification

Verify that an invoice was paid by searching for the invoice number:

```
GET /transfer/reference/by/from/0x963eC454423CD543dB08bc38fC7B3036B425b301?reference=Invoice%20%2312345
```

### Account Reconciliation

Build a complete payment history for accounting purposes:

```
GET /transfer/reference/history/by/from/0x963eC454423CD543dB08bc38fC7B3036B425b301?start=1704067200&end=1735689600
```

### Payment Explorer

Build a transfer explorer showing recent payments with references:

```
GET /transfer/reference/list
```

### Counterparty Search

Find all transfers between two specific addresses:

```
GET /transfer/reference/by/from/0xabc...?to=0xdef...
```

## Data Structure

### Transfer Reference Object

```json
{
  "amount": "1000000000000000000000",
  "chainId": 1,
  "count": 5234,
  "created": 1768914604,
  "from": "0x963eC454423CD543dB08bc38fC7B3036B425b301",
  "sender": "0x963eC454423CD543dB08bc38fC7B3036B425b301",
  "to": "0x6a4a629d14EC0fc8e2b7DB41949FefaA4F63327F",
  "amount": "1000000000000000000000",
  "reference": "Invoice #12345",
  "targetChain": "1",
  "txHash": "0x1234567890abcdef..."
}
```

### Field Descriptions

* **amount**: Transfer amount (as string in wei, typically 1e18 for ZCHF)
* **chainId**: Source blockchain chain ID
* **count**: Sequential counter for this transfer reference
* **created**: Unix timestamp of the transfer
* **from**: Immediate sender address (may differ from original sender for bridged transfers)
* **sender**: Original sender address
* **to**: Recipient address
* **reference**: Custom reference message (can be empty string)
* **targetChain**: Destination chain ID (for bridge transfers)
* **txHash**: Transaction hash on the source chain

## Understanding Latest vs History

### Latest Endpoints (`/by/from`, `/by/to`)

* Return only the most recent matching transfers
* Optimized for quick lookups
* Useful for displaying recent activity
* Limited results

### History Endpoints (`/history/by/from`, `/history/by/to`)

* Return complete transfer history
* Can be filtered by time range
* Useful for full accounting and reconciliation
* May return larger datasets

## Integration Examples

### Payment Notification System

```javascript
// Poll for new incoming payments
let lastCount = await fetch('https://api.frankencoin.com/transfer/reference/counter')
  .then(r => r.json());

setInterval(async () => {
  const currentCount = await fetch('https://api.frankencoin.com/transfer/reference/counter')
    .then(r => r.json());

  if (currentCount > lastCount) {
    // New transfer(s) occurred
    const transfers = await fetch(`https://api.frankencoin.com/transfer/reference/by/to/${myAddress}`)
      .then(r => r.json());

    transfers.forEach(transfer => {
      if (transfer.count > lastCount) {
        notifyUser(`New payment received: ${transfer.amount / 1e18} ZCHF - ${transfer.reference}`);
      }
    });

    lastCount = currentCount;
  }
}, 10000); // Check every 10 seconds
```

### Invoice Status Checker

```javascript
async function checkInvoicePayment(invoiceNumber, expectedFrom, expectedAmount) {
  const transfers = await fetch(
    `https://api.frankencoin.com/transfer/reference/by/from/${expectedFrom}?reference=${invoiceNumber}`
  ).then(r => r.json());

  const payment = transfers.find(t =>
    t.reference.includes(invoiceNumber) &&
    BigInt(t.amount) >= BigInt(expectedAmount)
  );

  return payment ? 'paid' : 'pending';
}
```

### Account Statement Generator

```javascript
async function generateStatement(address, startDate, endDate) {
  const startTimestamp = Math.floor(startDate.getTime() / 1000);
  const endTimestamp = Math.floor(endDate.getTime() / 1000);

  const sent = await fetch(
    `https://api.frankencoin.com/transfer/reference/history/by/from/${address}?start=${startTimestamp}&end=${endTimestamp}`
  ).then(r => r.json());

  const received = await fetch(
    `https://api.frankencoin.com/transfer/reference/history/by/to/${address}?start=${startTimestamp}&end=${endTimestamp}`
  ).then(r => r.json());

  return {
    sent: sent.map(t => ({
      date: new Date(t.created * 1000),
      to: t.to,
      amount: t.amount / 1e18,
      reference: t.reference,
      txHash: t.txHash
    })),
    received: received.map(t => ({
      date: new Date(t.created * 1000),
      from: t.from,
      amount: t.amount / 1e18,
      reference: t.reference,
      txHash: t.txHash
    }))
  };
}
```

## Notes

### Reference Text Handling

* References can be empty strings (not all transfers include references)
* Reference search is case-sensitive
* Partial matching is supported (searching "Invoice" will match "Invoice #123")
* Special characters should be URL-encoded in query parameters

### Performance Considerations

* Latest endpoints are faster than history endpoints
* Consider caching transfer data for known count ranges
* History endpoints may return large datasets for very active addresses
* Use time range filters to limit result sizes

### Cross-Chain Transfers

* `from` and `sender` may differ for bridged transfers
* `chainId` and `targetChain` indicate bridge operations when they differ
* Same-chain transfers will have identical `chainId` and `targetChain`

### Best Practices

1. **URL Encode**: Always URL-encode reference text in queries
2. **Time Ranges**: Use time ranges to limit history queries
3. **Pagination**: For very active addresses, combine count-based pagination with time ranges
4. **Validation**: Validate address formats before querying
5. **Error Handling**: Handle "Not found" responses gracefully when querying by count
6. **Amount Display**: Always convert amounts from wei (divide by 1e18) for display
7. **Timestamp Conversion**: Convert Unix timestamps to human-readable dates in UI

## Common Patterns

### Finding Payments Between Two Parties

```
GET /transfer/reference/by/from/0xABC...?to=0xDEF...
```

### Searching by Invoice Number

```
GET /transfer/reference/by/from/0xABC...?reference=INV-2024-001
```

### Time-Bound Queries

```
GET /transfer/reference/history/by/from/0xABC...?start=1704067200&end=1735689600
```

### Retrieving Specific Transfer

```
GET /transfer/reference/by/count/5234
```


# Analytics API

The Analytics API provides comprehensive ecosystem-wide metrics, financial analytics, and historical data for the Frankencoin protocol. This controller aggregates data from across the ecosystem to provide insights into protocol performance, FPS token economics, and system health.

## Overview

The Analytics API enables you to:

* Track profit and loss across the ecosystem
* Monitor transaction logs with full financial context
* Analyze daily aggregated metrics
* Understand FPS token collateral exposure
* Break down FPS earnings sources
* Generate historical reports and charts

## Key Concepts

### Profit & Loss Tracking

The protocol tracks all gains (profits) and losses from various sources:

* **Profits**: Minting fees, position fees, investment fees, trade fees
* **Losses**: Liquidation losses, interest paid on savings, redemption costs

These are tracked cumulatively and per FPS token, providing transparency into protocol economics.

### Transaction Logs

Every significant event affecting the Frankencoin supply, equity, or FPS is logged with complete financial metrics at that moment in time. This creates an immutable audit trail of the protocol's financial state.

### Daily Aggregations

End-of-day snapshots provide clean time-series data for charting trends without processing thousands of individual transactions.

## Main Endpoints

### Profit & Loss

* `GET /analytics/profitLossLog` - Complete log of all profit and loss events (limited to 1000 most recent)

Returns cumulative totals and per-event breakdown of gains and losses.

### Transaction Logs

* `GET /analytics/transactionLog/json` - Paginated transaction history with full metrics
* `GET /analytics/transactionLog/csvE18` - Transaction log formatted as CSV with decimal conversion

Transaction logs include:

* Event type (Mint, Burn, Position creation, etc.)
* Total supply, equity, and savings at that moment
* FPS price and supply
* Interest rates and projected earnings
* Minting totals for V1 and V2 positions

### Daily Aggregations

* `GET /analytics/dailyLog/json` - Daily aggregated metrics in JSON format
* `GET /analytics/dailyLog/csvE18` - Daily metrics as CSV with decimal conversion

Daily logs provide end-of-day snapshots of:

* Supply and equity evolution
* FPS pricing over time
* Cumulative inflows and outflows
* Interest rate trends

### FPS Analytics

* `GET /analytics/fps/exposure` - Detailed collateral exposure analysis for FPS token
* `GET /analytics/fps/earnings` - Complete breakdown of FPS earnings sources

## Use Cases

### Protocol Health Monitoring

Track cumulative profits and losses to ensure protocol sustainability:

```
GET /analytics/profitLossLog
```

### Historical Charts

Generate time-series charts of key metrics using daily aggregated data:

```
GET /analytics/dailyLog/json
```

### FPS Valuation

Understand FPS token value by analyzing collateral backing and earnings:

```
GET /analytics/fps/exposure
GET /analytics/fps/earnings
```

### Financial Reporting

Export complete transaction history in CSV format for external analysis:

```
GET /analytics/transactionLog/csvE18
```

### Risk Assessment

Analyze collateral exposure to understand concentration risk:

```
GET /analytics/fps/exposure
```

## Data Structure

### Profit/Loss Log Entry

* Event details: timestamp, count, event type
* Financial impact: amount gained/lost
* Cumulative totals: running profit and loss totals
* Per-FPS metrics: gains/losses per token

### Transaction Log Entry

* Event identification: timestamp, type, transaction hash
* Supply metrics: total supply, equity, savings
* FPS data: price, supply, market cap
* Minting data: V1 and V2 totals, limits
* Interest rates: current rates, projected earnings
* Borrowing rates: annual rates for V1 and V2

### Daily Log Entry

Similar to transaction logs but aggregated once per day, providing cleaner time-series data.

### FPS Exposure Analysis

* **General Metrics**: FPS price, supply, market cap, earnings, P/E ratio
* **Per-Collateral Exposure**:
  * Collateral details (address, name, symbol)
  * Position counts (open, original, clones)
  * Minting totals and interest averages
  * Risk metrics and loss scenarios

### FPS Earnings Breakdown

Detailed accounting of all revenue sources:

* Minter proposal fees
* Position proposal fees
* Investment and redemption fees
* Other profit claims and contributions
* Savings interest costs (expenses)
* Other loss claims

## Notes

### Data Formats

* **JSON endpoints**: Return structured data for programmatic access
* **CSV endpoints**: Return comma-separated values with all amounts converted from wei to decimal (÷ 1e18)
* Pagination is available on transaction logs using `firstItem`, `limit`, and `after` parameters

### Precision

* All amounts in JSON are in wei (strings)
* CSV exports automatically convert to human-readable decimals
* Interest rates are in wei representation (divide by 1e18 for percentage)

### Performance

* Daily logs are more efficient than transaction logs for charting
* Transaction logs support pagination for managing large datasets
* Profit/loss logs and FPS analytics are limited to relevant recent data

## Example Workflow

### Building a Dashboard

1. Fetch daily logs for historical charts
2. Get FPS exposure for current risk assessment
3. Pull profit/loss log for income statement
4. Use FPS earnings for detailed revenue breakdown

This provides a complete picture of protocol performance and health.


# Wallet Integration

Developer guide for integrating Frankencoin and the Savings Module into wallets and applications

This guide provides developers with the technical details needed to integrate Frankencoin (ZCHF) and its native savings module into wallets, applications, and services.

## Frankencoin Token (ZCHF)

### ERC-20 Standard

Frankencoin is a standard ERC-20 token that implements all standard functions:

* `balanceOf(address account)`
* `totalSupply()`
* `transfer(address to, uint256 amount)`
* `transferFrom(address from, address to, uint256 amount)`
* `allowance(address owner, address spender)`
* `approve(address spender, uint256 amount)`

### Multi-chain Support

Frankencoin is deployed across multiple blockchain networks, allowing users to interact with ZCHF on their preferred chain. When integrating, ensure your wallet supports the relevant chain IDs.

### Interface Reference

The complete ERC-20 interface can be found in the official repository: [IERC20.sol](https://github.com/Frankencoin-ZCHF/Frankencoin/blob/main/contracts/erc20/IERC20.sol)

## Savings Module Integration

The Frankencoin savings module allows users to lock up Frankencoins to earn yield. This feature can be integrated natively into wallets to provide users with seamless access to earning opportunities.

### Core Concepts

The savings module uses an `Account` structure that tracks:

* `saved`: Amount of ZCHF currently saved
* `ticks`: Internal counter for interest calculation
* `referrer`: Optional address for referral fees
* `referralFeePPM`: Referral fee in parts per million (ppm)

### Events

The savings module emits three primary events:

```solidity
event Saved(address indexed account, uint192 amount);
event InterestCollected(address indexed account, uint256 interest, uint256 referrerFee);
event Withdrawn(address indexed account, uint192 amount);
```

### Key Constants

```solidity
uint64 public immutable INTEREST_DELAY = uint64(3 days);
```

Interest accrues after a 3-day delay from when funds are saved.

### Data Structure

```solidity
mapping(address => Account) public savings;

struct Account {
    uint192 saved;
    uint64 ticks;
    address referrer;
    uint32 referralFeePPM;
}
```

### Core Functions

#### Query Functions

```solidity
// Refresh and return the current balance for an account
function refreshBalance(address owner) public returns (uint192);

// View accrued interest for an account at current time
function accruedInterest(address accountOwner) public view returns (uint192);

// View accrued interest for an account at a specific timestamp
function accruedInterest(address accountOwner, uint256 timestamp) public view returns (uint192);
```

#### Basic Operations

```solidity
// Save ZCHF from caller's wallet
function save(uint192 amount) public;

// Save ZCHF on behalf of another address
function save(address owner, uint192 amount) public;

// Withdraw ZCHF to a target address
function withdraw(address target, uint192 amount) public returns (uint256);

// Adjust savings to a target amount (save or withdraw as needed)
function adjust(uint192 targetAmount) public;
```

#### Referral Functions

The savings module includes a referral system that allows wallets and frontends to earn fees by facilitating user interactions:

```solidity
// Save with referrer
function save(uint192 amount, address referrer, uint24 referralFeePPM) public;

// Withdraw with referrer
function withdraw(uint192 amount, address referrer, uint24 referralFeePPM) public;

// Adjust with referrer
function adjust(uint192 targetAmount, address referrer, uint24 referralFeePPM) public;

// Drop the current referrer
function dropReferrer() public;
```

### Referral Logic

The referral system allows wallets and frontends to monetize their integration:

* Referral fees can be up to **25%** (250,000 ppm) of earned interest
* Fees are deducted from the collected interest, not the principal
* Users can drop or change referrers at any time
* The fee represents convenience value - users pay for easier interaction with the protocol

**Important**: The referral fee is not sticky. Users retain full control and can modify or remove referrers, so the fee depends on the convenience and value your wallet provides.

## API Helper Endpoints

Frankencoin provides REST API endpoints to simplify integration without requiring direct blockchain queries.

### Base URL

```
https://api.frankencoin.com
```

### 1. Module Info

Get comprehensive information about all savings modules across all chains.

**Endpoint**: `GET https://api.frankencoin.com/savings/core/info`

**Example Response**:

```json
{
	"status": {
		"1": {
			"0x27d9ad987bde08a0d083ef7e0e4043c857a17b38": {
				"chainId": 1,
				"updated": 1768146791,
				"module": "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38",
				"balance": "3252713131296817909181865",
				"interest": "17606356382481561618851",
				"save": "9066019386383589628122254",
				"withdraw": "5830912611469253280559240",
				"rate": 40000,
				"counter": {
					"interest": 350,
					"rateChanged": 2,
					"rateProposed": 1,
					"save": 436,
					"withdraw": 177
				}
			}
		},
		"10": {
			"0x6426324af1b14df3cd03b2d500529083c5ea61bc": {
				"chainId": 10,
				"updated": 1765391881,
				"module": "0x6426324af1b14df3cd03b2d500529083c5ea61bc",
				"balance": "0",
				"interest": "0",
				"save": "0",
				"withdraw": "0",
				"rate": 40000,
				"counter": {
					"interest": 0,
					"rateChanged": 3,
					"rateProposed": 0,
					"save": 0,
					"withdraw": 0
				}
			}
		}
	}
}
```

**Note**: The `rate` is expressed in basis points (e.g., 40000 = 4% annual rate).

**TypeScript Interface**:

```typescript
export type ApiSavingsInfo = {
	status: SavingsStatusMapping;
	totalBalance: number;
	ratioOfSupply: number;
	totalInterest: number;
};

export type SavingsStatusMapping = {
	[K in ChainId]: {
		[module: Address]: SavingsStatus;
	};
};

export type SavingsStatus = {
	chainId: ChainId;
	updated: number;
	module: Address;
	balance: string;
	interest: string;
	save: string;
	withdraw: string;
	rate: number;
	counter: {
		interest: number;
		rateChanged: number;
		rateProposed: number;
		save: number;
		withdraw: number;
	};
};
```

### 2. Ranked Accounts

Get a ranked list of accounts by savings balance across all chains.

**Endpoint**: `GET https://api.frankencoin.com/savings/core/ranked`

**Example Response**:

```json
[
	{
		"chainId": 1,
		"account": "0x963ec454423cd543db08bc38fc7b3036b425b301",
		"module": "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38",
		"balance": "800000000000000000000000",
		"created": 1751307767,
		"updated": 1767025931,
		"save": "2999417071917808219178083",
		"interest": "4424985059912480974118",
		"withdraw": "2203842056977720700152201",
		"counter": {
			"save": 4,
			"interest": 9,
			"withdraw": 9
		}
	}
]
```

**TypeScript Interface**:

```typescript
export type ApiSavingsRanked = SavingsBalance[];

export type SavingsBalance = {
	chainId: ChainId;
	account: Address;
	module: Address;
	balance: string;
	created: number;
	updated: number;
	interest: string;
	save: string;
	withdraw: string;
	counter: {
		save: number;
		interest: number;
		withdraw: number;
	};
};
```

### 3. Account Balance

Get savings information for a specific account across all chains and modules.

**Endpoint**: `GET https://api.frankencoin.com/savings/core/balance/<account>`

**Example**: `GET https://api.frankencoin.com/savings/core/balance/0x963ec454423cd543db08bc38fc7b3036b425b301`

**Example Response**:

```json
{
	"1": {
		"0x27d9ad987bde08a0d083ef7e0e4043c857a17b38": {
			"chainId": 1,
			"account": "0x963ec454423cd543db08bc38fc7b3036b425b301",
			"module": "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38",
			"balance": "800000000000000000000000",
			"created": 1751307767,
			"updated": 1767025931,
			"save": "2999417071917808219178083",
			"interest": "4424985059912480974118",
			"withdraw": "2203842056977720700152201",
			"counter": {
				"save": 4,
				"interest": 9,
				"withdraw": 9
			}
		}
	}
}
```

**TypeScript Interface**:

```typescript
export type ApiSavingsBalance = {
	[K in ChainId]: {
		[module: Address]: SavingsBalance;
	};
};
```

### 4. Account Activities

Get the latest transaction history for an account's savings activities (limited to 1000 entries).

**Endpoint**: `GET https://api.frankencoin.com/savings/core/activity/<account>`

**Example**: `GET https://api.frankencoin.com/savings/core/activity/0x963ec454423cd543db08bc38fc7b3036b425b301`

**Example Response**:

```json
[
	{
		"chainId": 1,
		"account": "0x963ec454423cd543db08bc38fc7b3036b425b301",
		"module": "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38",
		"created": 1767025931,
		"blockheight": 24119513,
		"count": 22,
		"balance": "800000000000000000000000",
		"save": "2999417071917808219178083",
		"interest": "4424985059912480974118",
		"withdraw": "2203842056977720700152201",
		"kind": "Withdrawn",
		"amount": "101791599315068493150684",
		"rate": 40000,
		"txHash": "0xe0d225c67bdc434da108bf359a40d5a6586b03d93a1843897810aa75cf9ae313"
	},
	{
		"chainId": 1,
		"account": "0x963ec454423cd543db08bc38fc7b3036b425b301",
		"module": "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38",
		"created": 1767025931,
		"blockheight": 24119513,
		"count": 21,
		"balance": "901791599315068493150684",
		"save": "2999417071917808219178083",
		"interest": "4424985059912480974118",
		"withdraw": "2102050457662652207001517",
		"kind": "InterestCollected",
		"amount": "1791599315068493150684",
		"rate": 40000,
		"txHash": "0xe0d225c67bdc434da108bf359a40d5a6586b03d93a1843897810aa75cf9ae313"
	}
]
```

**Activity kinds**: `Saved`, `Withdrawn`, `InterestCollected`

**TypeScript Interface**:

```typescript
export type ApiSavingsActivity = SavingsActivityQuery[];

export type SavingsActivityQuery = {
	chainId: ChainId;
	account: Address;
	module: Address;
	created: number;
	blockheight: number;
	count: number;
	balance: string;
	save: string;
	interest: string;
	withdraw: string;
	kind: string;
	amount: string;
	rate: number;
	txHash: string;
};
```

### 5. Referrer Mapping

Get detailed information about all accounts that have set a specific address as their referrer.

**Endpoint**: `GET https://api.frankencoin.com/savings/referrer/<refferer>/mapping`

**Example**: `GET https://api.frankencoin.com/savings/referrer/0x963ec454423cd543db08bc38fc7b3036b425b301/mapping`

**Example Response**:

```json
{
  "num": 1,
  "accounts": ["0x637f00cab9665cb07d91bfb9c6f3fa8fabfef8bc"],
  "map": {
    "1": {
      "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38": {
        "0x637f00cab9665cb07d91bfb9c6f3fa8fabfef8bc": {
          "created": 1751307767,
          "updated": 1767025931,
          "balance": 250000000000000000000000,
          "referrer": "0x963ec454423cd543db08bc38fc7b3036b425b301",
          "referrerFee": 100000
        }
      }
    }
  }
}
```

**TypeScript Interface**:

```typescript
export type ApiSavingsReferrerMapping = {
	num: number;
	accounts: Address[];
	map: SavingsReferrerMapping;
};

export type SavingsReferrerMapping = {
	[K in ChainId]: {
		[module: Address]: {
			[account: Address]: SavingsReferrerAccountItem;
		};
	};
};

export type SavingsReferrerAccountItem = {
	created: number;
	updated: number;
	balance: number;
	referrer: Address;
	referrerFee: number;
};
```

**Use Case**: Referrers can use this endpoint to monitor their referred accounts. They can also trigger the `refreshBalance()` function for these accounts to collect accrued interest and receive their referral fee split.

### 6. Referrer Earnings

Get aggregated earnings information for a referrer across all chains and modules.

**Endpoint**: `GET https://api.frankencoin.com/savings/referrer/<referrer>/earnings`

**Example**: `GET https://api.frankencoin.com/savings/referrer/0x5f238e89F3ba043CF202E1831446cA8C5cd40846/earnings`

**Example Response**:

```json
{
  "earnings": {
    "1": {
      "0x27d9ad987bde08a0d083ef7e0e4043c857a17b38": {
        "0x637f00cab9665cb07d91bfb9c6f3fa8fabfef8bc": 32.78471424721345
      }
    }
  },
  "chains": {
    "1": 32.78471424721345
  },
  "total": 32.78471424721345
}
```

**TypeScript Interface**:

```typescript
export type ApiSavingsReferrerEarnings = {
	earnings: SavingsReferrerEarnings;
	chains: {
		[K in ChainId]: number;
	};
	total: number;
};

export type SavingsReferrerEarnings = {
	[K in ChainId]: {
		[module: Address]: {
			[account: Address]: number;
		};
	};
};
```

**Use Case**: This endpoint provides referrers with a complete view of their earnings across all chains, making it easy to display total revenue from the referral program.

## NPM Package

For faster integration, use the official Frankencoin API package:

```bash
npm install @frankencoin/api
# or
yarn add @frankencoin/api
```

**Package**: [@frankencoin/api](https://www.npmjs.com/package/@frankencoin/api)

This package provides typed API clients and utilities for interacting with the Frankencoin API endpoints, including all the savings module endpoints described above. All TypeScript types are included, making integration type-safe and easier.

## Integration Best Practices

### For Wallet Developers

1. **Display Savings Balance**: Show users their total ZCHF savings balance alongside their regular ZCHF balance
2. **Accrued Interest**: Use the `accruedInterest()` function to display pending interest in real-time
3. **Simple UX**: Provide one-click "Save" and "Withdraw" buttons with amount inputs
4. **Interest Collection**: Remind users that interest accrues after a 3-day delay
5. **Referral Integration**: Set your wallet address as the referrer to earn a portion of user interest

### For Frontend Developers

1. **Use API Endpoints**: Leverage the REST API for faster queries instead of direct contract calls
2. **Multi-chain Support**: Display savings across all supported chains in a unified interface
3. **Activity History**: Show users their complete savings history using the activity endpoint
4. **Rate Display**: Convert the rate from basis points to a user-friendly percentage (e.g., 40000 → "4% APY")

### Referral Program Recommendations

* Set a reasonable referral fee (typically 5-15%) to balance user value and wallet revenue
* Clearly communicate to users that they pay a small convenience fee
* Allow power users to easily drop the referrer if they prefer direct interaction
* Use the referrer mapping endpoint to trigger `refreshBalance()` for your referred accounts periodically

## Smart Contract Addresses

For the latest contract addresses across all supported chains, please refer to the [official Frankencoin Landing Page](https://frankencoin.com) or the [GitHub repository](https://github.com/Frankencoin-ZCHF/Frankencoin).

## Support and Resources

* [Frankencoin GitHub](https://github.com/Frankencoin-ZCHF/Frankencoin)
* [Telegram Community](https://t.me/frankencoinzchf)
* [API Documentation](https://api.frankencoin.com/)


