## AO Yield Delegation & PI Index
[TOC]
---
## 1. Introduction
This document addresses all matters related to **AO yield delegation** and the **PI index**.
---
## 2. AO Yield Delegation
### 2.1. **Introduction**
Users and **AO processes** must have the ability to delegate their **AO Yield**, which is received approximately every **X minutes** as part of the minting process. Delegation can occur either **partially** or **fully**, providing flexibility in how yield is assigned to other entities.
The implementation should be closely integrated with the $AO **minting process**, as this process already operates on a **X-minute interval**, making it the most efficient point to execute delegations. The proposed solution involves maintaining a **delegation graph** for each ledger. This graph records all delegation relationships, including the delegation amounts and recipients. Every **5 minutes**, delegations are executed based on the stored graph, while updates to delegation weights and relationships occur **asynchronously** to ensure efficiency and scalability.
---
### 2.2. **Additional Considerations**
#### 2.2.3 Risks
While the system should allow for **partial delegation**, unrestricted granularity could potentially lead to **spam attacks**, as nearly infinite delegation entries could overwhelm the ledger. Therefore, the system must balance **flexibility** with safeguards against abuse.
1. **Cycles**
Delegation loops (e.g., A → B → C → A) can create infinite recursion or require iterative convergence
2. **Combinatorial Explosion**
Delegation chains with many wallets (e.g., A → B → C → … → Z) could require traversing large graphs every X minutes.
3. **Fairness**: Cycles could allow artificial inflation of weights (e.g., mutual delegation to amplify rewards unfairly).
#### 2.2.4 Developer Friendliness
1. **Transparency and Ease of retrieval**
It must be simple to track **who delegated how much to whom** to ensure transparency. This is particularly critical if delegation recipients offer rewards to the delegators for their contributions. The design should enable easy reflection of these relationships for **accountability**.
---
### 2.3. **Delegation Algorithm**
The **delegation algorithm** outlines the process for managing and executing yield delegation within the $AO minting system. This includes the **base algorithm flow**, a **mathematical explanation**, and **data structure recommendations**, with the design grounded in principles that ensure efficiency, accuracy.
:::warning
This algorithm does not mitigate the potential risks associated with **cycles** and **nested delegation**. These issues do not appear to have a solution that guarantees a global optimum, and thus require trade-offs at the requirements level. For a detailed discussion of the potential risks and available options, refer to [5.0 Risks: Details & Solutions](#5.0).
:::
#### 2.3.1. **Key Principles**
- **Delta-Based Updates**: Calculations are only performed for wallets whose holdings, multipliers, or delegations have changed, along with their immediate neighbors in the delegation graph.
- **Single-Threaded Design**: Sequential updates avoid complex locking mechanisms, ensuring simplicity and efficiency.
- **Normalization**: If a wallet’s total delegation fraction exceeds 1, all fractions are proportionally scaled down to maintain validity.
- **Non-Negative Weights**: Final weights are clamped to zero to prevent negative values during distribution.
- **Clarity and Efficiency**: By separating **base weight** calculations from **delegation adjustments**, the system avoids redundant re-processing, keeping operations streamlined.
### 3. **Delegation Algorithm Overview**
1. **Fetch Data from DB**
- **Token Multipliers**: From a `TokenMultiplier` table (e.g., `SELECT token_type, multiplier FROM TokenMultiplier`).
- **Wallet Holdings**: From a `WalletHoldings` table, keyed by `(wallet_address, token_type, quantity)`.
- **Delegations**: From a `Delegation` table, keyed by `(from_wallet, to_wallet, fraction)`.
2. **Compute or Update Base Weights**
- For each affected wallet (i.e., one whose holdings changed or where a relevant multiplier changed):
1. Sum `(quantity × multiplier)` across all tokens it holds.
2. Store/update that total in a `DistributionState` table, e.g., `UPDATE DistributionState SET base_weight=? WHERE wallet_address=?`.
3. **Apply Delegations**
- Read delegation rows for each wallet, e.g., `SELECT to_wallet, fraction FROM Delegation WHERE from_wallet=?`.
- Multiply the delegator’s base weight by each fraction to find how much weight is delegated out.
- Add that delegated amount to the receiving wallet’s “in_delegated” and track how much was subtracted as “out_delegated” for the sender.
- If total fractions exceed 1, normalize them on the fly (divide each fraction by the sum).
4. **Calculate Final Weights**
- For each wallet, `final_weight = base_weight + in_delegated - out_delegated`.
- If the result is negative, clamp it to 0 (to avoid negative weights).
5. **Distribute Minted AO**
- Sum all `final_weight` values to get a total.
- For each wallet, compute a proportional share of the minted AO based on `(final_weight / total_final_weight)`.
- Use integer allocation (e.g., via `floor`) and handle leftover AO tokens with a largest-remainder or similar method to ensure the total minted supply matches perfectly.
---
## 4. **Delegation Algorithm Breakdown**
### 4.1 Data Structures & Tables
An overview of the suggested tables to enhance read/write separation in the algorithm and make it easier to reference columns and fields in the algorithm definition.
### **TokenMultiplier**
```sql
CREATE TABLE IF NOT EXISTS TokenMultiplier (
token_type TEXT PRIMARY KEY,
multiplier REAL NOT NULL,
last_updated INTEGER NOT NULL
);
```
- Stores each token’s AO weight multiplier that determines the yield for 1 unit.
- We only update multiplier when a token’s yield ratio changes.
- Updates needs to be atomic
### **1.2 WalletHoldings**
```sql
CREATE TABLE IF NOT EXISTS WalletHoldings (
wallet_address TEXT NOT NULL,
token_type TEXT NOT NULL,
quantity REAL NOT NULL,
last_updated INTEGER NOT NULL,
PRIMARY KEY (wallet_address, token_type)
);
CREATE INDEX IF NOT EXISTS idx_holdings_wallet
ON WalletHoldings(wallet_address);
```
- Each (wallet_address, token_type) pair shows how many tokens the wallet holds.
- Updates occur when tokens deposit/withdraw.
1.3 DistributionState
```sql
CREATE TABLE IF NOT EXISTS DistributionState (
wallet_address TEXT PRIMARY KEY,
base_weight REAL NOT NULL,
final_weight REAL NOT NULL,
last_updated INTEGER NOT NULL
);
```
- `base_weight` = sum of (quantity * multiplier) across all tokens the wallet holds.
- `final_weight` =` base_weight + delegated-in − delegated-out.`1.4
1.4 Delegation
```sql
CREATE TABLE IF NOT EXISTS Delegation (
from_wallet TEXT NOT NULL,
to_wallet TEXT NOT NULL,
fraction REAL NOT NULL, -- 0 <= fraction <= 1
last_updated INTEGER NOT NULL,
PRIMARY KEY (from_wallet, to_wallet)
);
CREATE INDEX IF NOT EXISTS idx_delegation_from
ON Delegation(from_wallet);
```
- A row means `from_wallet` delegates a fraction of its `base_weight` to `to_wallet`.
- Multiple delegations per address are allowed (e.g., 20% to one address, 15% to another, etc.).
## 4.2. Core Algorithmic Steps
### 4.2.1 Base Weight Updates
Whenever the multiplier for a token changes or a wallet's token holdings change, we recalculate only that wallet's `base_weight`:
1. **Fetch wallet's tokens** from `WalletHoldings`.
2. For each token \( T \), fetch `multiplier(T)` from `TokenMultiplier`.
3. Sum up:
$$
\text{base_weight}(W) = \sum_{\text{all tokens } T \text{ held by } W} (\text{quantity}_{W,T} \times \text{multiplier}(T))
$$
4. Store into `DistributionState(W).base_weight`.
**Example (Real Numbers)**:
- Wallet A holds 10 AR (multiplier=0.2) and 5 DAI (multiplier=0.5):
$$
\text{base_weight(A)} = (10 * 0.2) + (5 * 0.5) = 2 + 2.5 = 4.5.
$$
## 4.2.2 Delegations & Final Weight
Each wallet's `final_weight` depends on how much it delegates out and how much is delegated in:
$$
\text{final_weight}(W) = max(\text{base_weight}(W) + \text{in_delegated}(W) - \text{out_delegated}(W),0)
$$
where:
$$
\text{in_delegated}(W) = \sum_{(Y \rightarrow W) \in \text{Delegation}} \left( \text{fraction}_{Y \rightarrow W} \times \text{base_weight}(Y) \right),
$$
and
$$
\text{out_delegated}(W) = \sum_{(W \rightarrow Z) \in \text{Delegation}} \left( \text{fraction}_{W \rightarrow Z} \times \text{base_weight}(W) \right).
$$
In practice, we update these values only for the affected wallets and their immediate delegation neighbors after any `fraction` or `base_weight` changes.
**Concrete Example**
```
Wallet B:
base_weight(B) = 3 (already computed)
Delegates 20% = 0.20 of its base_weight to A → out_delegated(B) = 0.20 * 3 = 0.6
final_weight(B) = 3 - 0.6 = 2.4
Wallet A:
base_weight(A) = 4.5
in_delegated(A) from B = 0.6
final_weight(A) = 4.5 + 0.6 = 5.1
```
### **4.3 Minting AO**
If we have \(N\) wallets, and the total minted AO at this cycle is \(M\), then each wallet’s minted AO is:
$$
\text{AO_mint}(W) = \frac{\text{final_weight}(W)}{\sum_{i=1}^{N} \text{final_weight}(i)} \times M.
$$
**Concrete Example**
Suppose we have two wallets, `A` and `B` and `M` is $AO Minted this cycle:
- $$\text{final_weight}(A) = 5.1$$
- $$\text{final_weight}(B) = 2.4$$
- $$\text{total_final_weight} = 5.1 + 2.4 = 7.5$$
- $$M = 75 $$
Then:
$$
\text{AO_mint}(A) = \frac{5.1}{7.5} \times 75 \approx 51,
$$
$$
\text{AO_mint}(B) = \frac{2.4}{7.5} \times 75 \approx 24.
$$
:::warning
Even if a token is divisible to 12 decimal places (like AO), some rounding is still required when you want the supply
minted total to match a specific supply number—especially if you insist on no “phantom decimals” beyond 12 places.
The largest remainder (or Hamilton) method is a formal solution to “How do I distribute the leftover exactly in the fairest possible way?” If you truly want:
Zero mismatch in total minted supply, and
An equitable approach to that leftover rounding,
then you can treat the 12-decimal amounts exactly like you would integer amounts—just thinking in “micro-units” or “planck units” (10⁻¹², in your case) instead of whole tokens. You end up with the same logic:
1.Compute raw fractions.
2.Floor (or round down) to the nearest 10⁻¹².
3. Calculate leftover.
4. Give leftover planck-units to addresses with the largest fractional remainders.
:::
---
## 5.0 Risks: Details & Solutions
### 5.1 Large or Nested Delegation Graphs
Without constraints (cycle prevention, max depth, or fan-out limits), a wallet could delegate to many others, each of which delegates further. This can lead to an exponential explosion in the number of edges.
Imagine a “fan-out” of 10 at each level, with depth 4. Then a single initial wallet could lead to $$10^4 = 10.000$$
Delegations. Every X-minute mint cycle must process them, causing severe performance issues.
### 5.2 Repeated Traversal at Mint Time
If the system must recalculate final_weight for every wallet during each X-minute interval and re-walk an entire subgraph, complexity grows with the graph size.
If 1,000 wallets each have 20 delegates, naive recalculation might process 20,000 edges. If done every 5 minutes, that’s 240,000 edges/hour. Scale that to 1 million wallets, and it becomes infeasible.
### 5.3 Cycles Causing Infinite Loops (If Not Prevented)
A cycle (A → B, B → C, C → A) can cause the algorithm to never converge in naive implementations or cause repeated double counting.
Example: If each wallet had base_weight=10 and 100% delegation, a naive system might attempt to keep adding 10 from each, recursively inflating the final weights.
Result: Potential infinite recursion or extremely long run times per cycle.
### 5.4 I Delegate to You, You Delegate to Me
When you and I both delegate 100% of our yield to each other, two odd outcomes can happen depending on how the system processes the cycle:
- **Odd Depth (2k+1)**: Potentially, your final weight includes all of my delegated weight, and my final weight includes all of yours. That can cause bizarre “double counting” if not prevented.
- **Even Depth (2k)**: Everything cancels out, so we each end up just getting our own yield, plus we might each appear to get some fraction from the other—again, a scenario that often leads to unexpected inflation or zero net effect.
From an economic standpoint, it’s hard to justify who benefits from a pure 100%-back-to-you loop. Typically, if I want to support you, it’s because you have some project or cause I want to fund. If you want to support me, it’s for the same reason. A pure 100%-back cycle is effectively “do-nothing.” So either we get:
No net difference (we just keep what was ours), or
Possible exploitation or “weird inflation” if the system’s naive algorithm double-counts delegated weight.
Hence, real participants usually have no practical incentive to set up such loops. It’s effectively an attempt to game the formula or do something circular that introduces overhead and potential miscalculations.
### 5.5 Spam attack with yield bearing assets OR delegation fractions
If you hold a yield-bearing asset like qAR, wAR, or wDAI, you could potentially exploit the network by dividing a single unit of qAR into 10^12 parts and distributing them to 10^12 wallets. Each of these wallets would then qualify for yield, significantly increasing the number of entries in the delegation table. If each of these wallets further delegates to just one other wallet, the number of entries would double, compounding the issue.
### 5.5 Solutions
There are various algorithms and techniques available to address the problems described above. These include cycle detection algorithms, graph flattening methods, and simple graph constraints such as limiting maximum depth.
However, implementing these solutions comes with its own set of user and product-related implications. For example:
- **Cycle Detection:** While effective, this is a non-trivial algorithm that adds significant complexity to the system.
- **Maximum Depth Constraint:** Limiting the depth of delegations can lead to unexpected failures.
Consider the following scenario:
1. The system enforces a maximum delegation depth of **5**.
2. User **A** attempts to delegate authority to User **B**.
3. However, User **B** already has a delegation depth of **5**.
4. Since this exceeds the allowed limit, the delegation request is **rejected**.
Such constraints, while necessary for system stability, can introduce unintended usability challenges.
#### 5.5.1 A potential approach
- Always forbid cycles: “If adding an edge (W → X) would create a path X → … → W, reject.”
- Adopt a moderate max_depth if needed (e.g., 3 or 4). This ensures no deeply nested “delegation-chains.”
- Impose a fan-out cap (like 10 addresses per wallet). This preserves computational resources.
- Introduce a delegation fee OR
- Introduce a minimal amount of yield bearing assets to hold, to qualify for yield bearing of AO
# **Application Layer**
## **Problem: Dynamic Yield Allocation on the Application Layer**
The **qAR** and **wAR** assets are yield-bearing and receive **delegated AO yield** at regular intervals. The challenge lies in dynamically distributing these yields, especially when these assets are locked in DeFi protocols or handled by autonomous agents.
### **Challenges in AO DeFi**
#### **1. Handling AO Yield for Locked Assets**
When **qAR** or **wAR** are locked into **autonomous agents**, issues arise because these agents can hold assets longer than the distribution intervals, potentially claiming rewards meant for the actual owner.
**Proposed Solution:**
- Implement a **forward mechanism** where any AO rewards received by an agent are immediately forwarded to a central **register**, allowing the rightful owner to claim them.
- Introduce a **protocol-level rule** ensuring agents cannot wrongfully accumulate rewards. This rule should be enforced universally across all agents.
#### **2. Yield Distribution in DeFi Processes**
DeFi mechanisms such as **liquidity pools** and **lending pools** introduce additional complexities.
**Key Concerns:**
- Locked assets may face risks like **impermanent loss**, reducing their value and complicating reward calculations.
- For example, users withdrawing from **V2 liquidity pools** may receive a different amount than they deposited.
**Proposed Solution:**
- Deploy **reward tracking mechanisms** that allocate AO based on the actual **ownership shares** in DeFi pools.
- Ensure **risk-adjusted AO accounting**, factoring in potential losses from DeFi processes.
---
### **Special Cases and Further Considerations**
#### **1. Handling AO Yield in V2 Liquidity Pools**
Tracking yields in **V2 liquidity pools** is complex due to constant balance fluctuations caused by trading activity.
**Proposed Solution:**
- Use **snapshots** at every AO distribution interval to record pool shares.
- Distribute AO proportionally based on the user's actual share at the snapshot time.
- Account for **liquidity risks** to ensure rewards reflect real ownership dynamics.
#### **2. Special Case: Autonomous Agents**
Autonomous agents often become inactive or abandoned after completing their tasks, potentially leaving rewards stranded.
**Proposed Solution:**
- Implement an **auto-forward mechanism** where agents automatically send received AO to the original user.
- Introduce a **centralized claim process** for scenarios where rewards cannot be forwarded, enabling users to retrieve their AO yield later.
---
**Rewritten and Improved Summary of the Index Implementation**
Below is a structured overview of the components and their interactions in an on-chain index system involving fair launches, delegation mechanics, and an index token called “PI.” The goal is to improve clarity, formalize the description, reduce ambiguity, and provide real-world examples where helpful.
---
## 6. Introduction PI Index
The system consists of several on-chain components that enable:
1. **Fair Launch Creation**: A factory contract that spawns individual “Fair Launch” processes.
3. **Index Token Creation (PI Index)**: A synthetic token (PI) pegged to a basket of assets ($AO, $AR, and all Fair Launch tokens), with mechanisms for rebalancing.
4. Price discovery auctions (TBD.)
---
## 7. Key Components
### 7.1 Fair Launch Factory
- **Purpose**: The Fair Launch Factory is a master process that can create `N` Fair Launch processes.
- **Function**:
1. **Creation**: When a user wants to initiate a fair launch, they submit the necessary configuration parameters (e.g., token type, token amount, distribution curve, timeline).
2. **Record-Keeping**: Maintains a registry of every Fair Launch process it has spawned, including references to their state and associated data.
### 7.2 Fair Launch Process
- **Purpose**: A Fair Launch Process (FLP) is created by users or projects that want a transparent and equitable token launch.
- **Key Parameters**:
1. **Token Allocation**: The total token amount allocated to be sold or distributed.
2. **Distribution Curve**: A decay curve factor that controls how tokens are released over time.
3. **Launch Duration**: The length of time the fair launch will run.
4. **Beneficiary**: A designated address or process (e.g., a treasury or the “PI token beneficiary process”) that receives proceeds or tokens.
5. **Start Time**: When the fair launch campaign officially begins.
- **Operation**:
1. **Token Reception**: The FLP contract receives the tokens designated for the fair launch and records the total supply at the moment of allocation.
2. **Tracking**: Maintains data that can be queried by the AO Delegation Platform (ao.arweave.net) or any on-chain interface to see details such as how many tokens remain, how many have been sold, and how much AO has been delegated.
#### 7.2.1 Exponential Emission Schedule: FLP Decay Curve algorithm
We define the emission per period as:
$$
E(n) = E_0 \times r^{(n-1)}
$$
where:
- $E_0$ is the initial emission.
- $r$ is the decay factor (with $0 < r < 1$).
- $n$ is the period number.
## Simple Algorithm
1. For each period $n = 1, 2, \dots, N$, compute:
$$
E(n) = E_0 \times r^{(n-1)}
$$
2. If no delegators exist, add $E(n)$ to a rollover pool.
3. When delegators are present, distribute the total available tokens (current period's $E(n)$ plus any rollover).
## Parameter Comparison
- **Aggressive Decay:**
Use a lower $r$ (e.g. $r = 0.90$) for a steep drop-off.
- **Moderate Decay:**
Use an intermediate value (e.g. $r = 0.95$).
- **Linear-like Decay:**
To approximate a full linear decline from $E_0$ at period 1 to 0 at period $N$, set:
$$
r = 1 - \frac{1}{N-1}
$$
For example, with $N = 180$,
$$
r = 1 - \frac{1}{179} \approx 0.9944
$$
- Comparison over 180 days:

### 7.3.1 Fair Launch Process Parameters
When setting up a Fair Launch Process (FLP), the user (or team) must provide the following input parameters. Note that some fields (such as Socials & Website) are **optional**, and the underlying data structure is designed to accommodate these optional fields.
1. **Fair Launch Name**
- A unique name for your fair launch project.
2. **Socials & Website (Optional)**
- **X (Twitter) Handle:** Your project's Twitter (X) account (optional).
- **Website URL:** The official website for your project (optional).
- *These fields can be omitted if not available, but the data structure supports them for enhanced project visibility.*
3. **Token Allocation**
- The share or percentage of your existing token supply that will be allocated to the FLP.
- Example: Enter `10%` or an absolute token amount (e.g. `1,000,000 tokens`).
- *The FLP process should capture the total amount of existing tokens in the token smart contract to ensure transparency in case the token creator decides to mint more tokens in the future*
4. **Fair Launch Duration**
- The total number of days you wish the fair launch to run.
5. **Decay Factor (r)**
- A fixed decay factor used in the emission schedule.
- Must be a decimal value between 0 and 1.
- For example, use `0.95` for a moderately aggressive decay or `0.9944` to approximate a linear decline.
- *For the FrontEnd we should consider a slider and a dynamically adjusting curve animation*
6. **Start Date**
- The calendar date when the fair launch begins (format: YYYY-MM-DD).
7. **Treasury Wallet**
- The wallet address for the FLP creator’s treasury.
- This wallet will autonomously receive the delegated funds from the FLP process.
---
## Derived and Displayed Parameters
- **End Date**
Automatically computed from the Start Date and the Fair Launch Duration:
$\text{End Date} = \text{Start Date} + \text{Duration (in days)}$
*Important consideration is that eventually the rewards will be just a small fraction of a coin and in that case the FLP creator might want to round-up to ensure the Fair Launch ends after X distributions.*
- **Emission Schedule**
The emission per period is calculated using the decay formula:
$$
E(n) = E_0 \times r^{(n-1)}
$$
where:
- $E_0$ is determined by the total token allocation for the FLP.
- $r$ is the decay factor.
- $n$ is the period number (from 1 to Duration).
- **Delegated AO**
- This value represents the approximate amount of AO tokens currently delegated to the FLP.
- **Note:** This is **not** an input; it is automatically computed and displayed on the FrontEnd by the delegation state process. It may be synchronized with the FLP process to show real-time delegated balances.
- **Period Duration**
- The length of each distribution period. (24 hours by default, determined by the AO mint and only used for the curve calculation)
---
## Example Input Summary
- **Fair Launch Name:** "MyProject Fair Launch"
- **Socials & Website (Optional):**
- Twitter: @MyProjectX
- Website: https://www.myproject.com
- Other key-value params like TG etc...
- **Token Allocation:** 10% of total supply (e.g., 1,000,000 tokens)
- **Duration:** 180 days
- **Decay Factor:** 0.95
- **Start Date:** 2025-03-01
### 7.3 AO Delegation Platform and Oracle
- **AO Delegation Platform**: An official component responsible for orchestrating delegation logic.
- **AO Delegation Oracle**:
1. **Delegation Processing**: All requests to delegate AO tokens (to a person, contract, or process like a Fair Launch) go through this oracle, ensuring a consistent mechanism to track “who delegated what to whom.”
2. **Reporting**: When anyone wants to find out the delegation power of a user or contract, they query the oracle for an authoritative response.
### 7.4 Types of Delegation into Fair Launch Processes
1. **Direct AO Token Delegation**:
- A user sends their AO tokens to the Fair Launch Process.
- In return, the Fair Launch Process may mint some representation of the newly delegated stake (FLR Token) or otherwise update its internal accounting to reflect the user’s contribution.
2. **Synthetic Delegation via PI Index**:
- Instead of direct AO token delegation, the user can deposit tokens of the Fair Launch Process into the PI Index system.
- The PI Index then issues a synthetic “PI token” in return. This token’s value is composed of:
- **1/3 AO token**
- **1/3 AR token**
- **1/3 a basket of all Fair Launch tokens** (the composition is predefined by some formula or standard).
- This mechanism is akin to a decentralized index fund, where multiple assets collectively back a single token. -- THIS IS TBD
---
## 8. PI Index Mechanics
### 8.1 Composition of the PI Token
- **Tranche Split**: The PI token holds a portfolio with 1/3 in AO tokens, 1/3 in AR tokens, and 1/3 in an aggregated pool of Fair Launch tokens.
- **Valuation**: When you deposit the relevant Fair Launch token or other underlying assets, you receive PI tokens proportional to the contribution value relative to the entire index.
### 8.2 Rebalancing Function
- **Goal**: Maintain the 1/3–1/3–1/3 distribution across AO, AR, and the basket of Fair Launch tokens.
- **Method**:
1. **Auctioning Excess Assets**: If the index has too much of one asset, it may auction it off to acquire the deficient asset.
2. **Buying from Public Sources**: The index can tap into external liquidity on the AO network to purchase whichever asset it is lacking.
---