TAN Issuance Calculation Specification
Invariants
Stakers
must both post a nonzero TEL stake && be a Referee
to be eligible for rewards
Stakers'
own user fees are eligible for rewards
Referrers
are Stakers
who have referred one or more Referees
. They are eligible for their Referees’ user fees in addition to their own fees
- Thus,
eligible users
for TAN rewards issuance comprises Stakers
and Referrers
- Support any custom time period, provided via input
Referrer <-> Referee
relationships will be provided by a TAN app backend doc (can also be identified by SimplePlugin::increaseClaimableBy()
events)
Rewards Caps
: rewards for a given period are capped by the lowest stake held by the Staker/Referrer
during the period, less rewards already earned. Ie: rewardsCap = stakeAmtTrough - cumulativePrevReward
.
An individual’s maximum reward amount must be less than or equal to their fee spend.
- As a result, historical rewards must be persisted for future rewards cap derivations
- User fees can be identified as the TEL sent to Amirx from aggregator. This fee is deducted a
claimableStakeReward
and then forwarded to fees safe
Note that the claimableStakeReward
is a separate staking reward which accrues per swap rather than per TAN issuance period. It is derived based on the Staker’s stake amount with various percentage tiers as detailed in the Telcoin app.
Proposed Flow
- Provide a time period for the distribution
- Identify total amount of user fees for eligible Stakers and Referrers over the time period
- Calculate the pro-rata share for each Staker and Referrer of total fees for the time period
- Apply rewards caps to values derived in #3
- Split total issuance amount for the time period along #4’s resulting capped pro-rata proportions
To accomplish the above:
Numbering refers to the spec steps above
-
Pull all transactions involving users in TAN app document and derive total sum of their user fees
-
User fees can be identified by txs with a tel transfer to AmirX from aggregators. Must enforce aggregator as src address here to prevent unrelated/rogue txs from being included in calc
-
Store these transactions and note their executor, fee amt, and referrer & Referee (if applicable)
Stored data structure example using Viem types:
interface RewardableTX {
txHash: 0x${string}
; // bytes32
executor: 0x${string}
; // address
userFee: BigInt; // uint256
user: 0x${string}
; // address
referrer: null || 0x${string}
; // optional address
}
-
Calculate total eligible fee sum for each eligible user (Stakers and Referrers) and its pro-rata weight against the total sum of user fees from #2
-
Using relationships from TAN app doc:
(eligible user’s fees + Referees’ fees)
Remember that each tx’s user fee can be identified by the TEL amount sent to AmirX by the aggregator
- Assign pro-rata weight to each eligible user, based on their proportion of the total fee amount identified in #2:
(referrerFees + RefereeFees) / totalFeeAmt
- Calculate rewards caps for all eligible users, derived as follows:
rewardsCap = stakeAmtTrough - cumulativePrevReward
- Identify referrer’s amount staked at the last final block:
StakingModule::stakedByAt(referrer, lastFinalBlock)
- Identify stake changes within the period via
StakingModule::stakeChanged(account, oldStake, newStake)
- If stake changes found, set referrer rewards cap as the lowest stake amount within the period
- Check historical rewards and subtract historical reward amount from rewards cap
Note that this cap results in an opportunity cost: ie funds a referrer would have earned had they staked more. The opportunity cost is intended to incentivize stakers to lock more TEL to open the door for more rewards.
Now we have calculated each referrer’s pro-rata share of total fees generated over the time period, and their current rewards cap. The final step is to apply the rewards cap.
- Divide this period’s total issuance distribution along the pro-rata proportions derived in #3 and then apply rewards caps to output a map:
(eligibleUser => weightedDistribution)
- Map is used to distribute rewards
- The derived weightedDistribution amount must be added to a persistent store of cumulativePrevReward which will be used in the future for #4
Example Scenario: Alice, Bob, and Charlie
To illustrate the above requirements, consider the following scenario:
Setup
• Alice is a referrer who invites Bob and Charlie to the system.
• Bob and Charlie execute trades, generating fees.
• Alice is eligible for a portion of the fees as a referrer.
Events
1. Referral Relationships
• Alice refers Bob and Charlie.
• This establishes a one-to-many relationship between Alice (referrer) and Bob/Charlie (referees).
2. Fee Generation
• Alice generates $50 in fees.
• Bob generates $100 in fees.
• Charlie generates $200 in fees.
• Total fees for Alice: $350.
3. Reimbursement Eligibility
• Alice is eligible for fees as she referred Bob and Charlie.
4. Stake and Rewards
• Assume Alice’s stake fluctuates during the reward period:
• Day 1: 50 tokens
• Day 2: 30 tokens
• Day 3: 40 tokens
• Alice’s reward cap for the period is determined by her lowest stake (30 tokens).
• If Alice previously earned 10 tokens in rewards, her new reward cap becomes:
Lowest Stake (30) - Previous Rewards (10) = 20 tokens
5. Reward Distribution
• Rewards are distributed based on Alice’s portion of total fees.
• Calculation considers the custom reward period (e.g., start time t1 to end time t2).
• Output in a blockchain friendly format
Addresses
- Executor
- Address: 0x0082CaF47363bD42917947d81f4d4E0395257267
- Address: 0xA64B745351EC40bdb3147FF99db2ae21cf93E6E3
- Gas Sponsor for all trades
- Aggregator
- Address: 0x1111111254EEB25477B68fb85Ed929f73A960582
- Address: 0xDef1C0ded9bec7F1a1670819833240f027b25EfF
- Performs DeFi trades
- ProxyFactory
- Address: 0x1FF89677646bfc4189475fC4eCfC7cF7a3b10F3e
- Address: 0x6FE6d75634E3f79B591d1B358835846b7abb6c4D
- Can provide record of wallets
- event Deployed(address indexed proxy, bytes32 salt)
- AmirX
- Address: 0x4eB4A35257458C1a87A4124CE02B3329Ed6b8D5a
- All trades are routed through contract
- Transfer Events
- To be Deprecated
- 0x5c4Bb7067199f91a432Ae5F90C742967CfDF7E50
- 0xfBBB07E82c771489f2256f82060CAB17DB14c18f
- Staking Contract
- Address: 0x92e43Aec69207755CB1E6A8Dc589aAE630476330
- Provides value of stake
- event StakeChanged(address indexed account, uint256 oldStake, uint256 newStake)
- Staking Plugin
- Address: 0xDb0e60A38Bf7d04c8ae0B396A65E5aa550f9885A
- Rewards provided to referrer to build relationship
- event ClaimableIncreased(address indexed account, uint256 oldClaimable, uint256 newClaimable)
- To be Deprecated
- 0x2f3378850a8fD5a0428a3967c2Ef6aAA025a4E1D
- 0xe24f8d36405704e85945a639fdaCEc47bA2a7c88
- Fees Safes
- Address: 0x8Eb6bBBF0fEe93ADC3A992d3DD54ED5294961237
- Address: 0xd796d81170645fdd1EFC1c1b1090969B11008D9C
- Destination address for fees
- Transfer Events
- Wallet Implementation
- Address: 0xb60c857742c2a93bbccb69dde3fa48a4af92db65