Staking Mechanics
Deep dive into Pupas Protocol's AI-powered staking system
Understanding the technical mechanics behind Pupas Protocol helps you maximize returns and make informed staking decisions. Our system combines traditional LP token mechanics with AI-driven investment strategies.
Core Staking Process
Smart Contract Functions
Provide Function (Staking)
@Callable(i)
func provide() = {
  let pmt = i.payments[0]
  
  # Validate supported tokens (USDTu or USDT-ERC20)
  if (pmt.assetId != usdtId && pmt.assetId != usdtuId) then
    throw("please attach USDT: " + usdtIdStr + ", " + usdtuIdStr)
  else
    # Calculate protocol fee (0.3% of stake)
    let feeAmount = fraction(pmt.amount, MintFee, Scale6)
    let cleanAmount = pmt.amount - feeAmount
    
    # Calculate LP tokens to mint based on current price
    let lpAmount = fraction(cleanAmount, Scale6, tryGetInteger("global_lpPrice"))
    
    [
      Reissue(lpId, lpAmount, true),
      ScriptTransfer(i.caller, lpAmount, lpId),
      ScriptTransfer(FeeAddress, feeAmount, pmt.assetId)
    ]
}Withdraw Function
@Callable(i)
func withdraw(assetIdStr: String, lendMarketStr: String) = {
  let pmt = i.payments[0]
  
  # Validate LP token attachment
  if (pmt.assetId != lpId) then
    throw("please attach LP: " + lpIdStr)
  else
    # Validate withdrawal asset (USDTu or USDT-ERC20 only)
    if (assetIdStr != usdtIdStr && assetIdStr != usdtuIdStr) then
      throw("you can only withdraw USDT: " + usdtIdStr + ", " + usdtuIdStr)
    else
      let lpAmount = pmt.amount
      
      # Calculate USDT amount based on current LP price
      let amountToWithdraw = fraction(lpAmount, tryGetInteger("global_lpPrice"), Scale6)
      
      [
        Burn(lpId, lpAmount),
        ScriptTransfer(i.caller, amountToWithdraw, fromBase58String(assetIdStr))
      ]
}LP Token Price Mechanism
Price Update Frequency
- Interval: Every 60 minutes (3,600 seconds) 
- Oracle Function: - updateLpPrice()called by authorized address
- Validation: Price change limits prevent manipulation 
- Transparency: All updates recorded on-chain 
Oracle Price Update
@Callable(i)
func updateLpPrice(lpPrice: Int) = {
  let currentOraclePrice = valueOrElse(getInteger("global_lpPrice"), Scale6)
  let oracleChangeDelta = abs(max(
    fraction(currentOraclePrice, Scale6, lpPrice),
    fraction(lpPrice, Scale6, currentOraclePrice)
  ) - Scale6)
  
  # Validate caller authorization
  if (i.caller != this) then
    throw("available for self invoke only")
  else
    # Check volatility tolerance
    if (oracleChangeDelta > OracleVolatilityTolerance) then
      throw("max change for oracle is " + toString(fraction(OracleVolatilityTolerance / 100, Scale6)) + "%")
    else
      [IntegerEntry("global_lpPrice", lpPrice)]
}Investment Flow
Fund Allocation Process
- Pool Aggregation: Staked USDTu/USDT-ERC20 collected in main pool 
- AI Analysis: Investment agents analyze market conditions 
- Strategy Selection: AI choose optimal investment pools 
- Fund Deployment: Portion of pool allocated to selected strategies 
- Return Calculation: Profits/losses calculated and recorded 
- Price Update: New LP token price reflects pool performance and account balance 
Investment Strategies
Lending Protocol Integration
func withdrawFromLend(amount: Int, assetIdStr: String, market: Address) = {
  let inv = invoke(market, "withdraw", [assetIdStr, [amount]], [])
  
  if (inv == inv) then [] 
  else throw("Strict value is not equal to itself.")
}Risk Management System
Position Limits
# Risk management constants
let OracleVolatilityTolerance = 100000  # 10% max price change per update
let MintFee = 3000                      # 0.3% protocol fee
let Scale6 = 1000000                    # 6 decimal precisionDiversification Rules
- Maximum volatility tolerance: 10% per price update 
- Protocol fee: 0.3% of stake amount 
- Automated position management via AI agents 
Token Economics
LP Token Supply Management
Minting Process
# LP tokens minted = (stake amount - fee) / current LP price
let lpAmount = fraction(cleanAmount, Scale6, tryGetInteger("global_lpPrice"))Burning Process
# USDT returned = LP tokens × current LP price
let amountToWithdraw = fraction(lpAmount, tryGetInteger("global_lpPrice"), Scale6)Fee Structure
Protocol Fee (0.3% of stake)
# Applied at staking time, sent to treasury
let feeAmount = fraction(pmt.amount, MintFee, Scale6)  # 0.3% of initial stake
let cleanAmount = pmt.amount - feeAmount
# Send fee to treasury and mint LP tokens based on net stake
[
  ScriptTransfer(FeeAddress, feeAmount, pmt.assetId),
  Reissue(lpId, lpAmount, true),
  ScriptTransfer(i.caller, lpAmount, lpId)
]Withdrawal Mechanics
Instant Withdrawal
- No Lock Period: Withdraw anytime without penalties 
- Current Price: Always withdraw at latest LP price 
- Automated Processing: Smart contract handles transfers 
LP Token Burning
# Burn LP tokens and transfer corresponding USDT amount
[
  Burn(lpId, lpAmount),
  ScriptTransfer(i.caller, amountToWithdraw, fromBase58String(assetIdStr))
]Performance Tracking
Price Calculation
# Current LP price stored as integer with 6 decimal precision
let currentPrice = tryGetInteger("global_lpPrice")
# Helper function to safely get integer values
func tryGetInteger(key: String) = {
  match getInteger(this, key) {
    case a: Int => a
    case _ => 0
  }
}Performance Metrics
- LP Price History: Tracked via oracle updates 
- Total Value Locked: Sum of all staked assets 
- Active Strategies: Monitored by AI agents 
- Fee Collection: Protocol revenue tracking 
Emergency Procedures
Access Control
# Only contract itself can update LP prices
if (i.caller != this) then
  throw("available for self invoke only")Initialization Security
@Callable(i)
func init(usdtIdStr: String, usdtuIdStr: String) = {
  if (i.caller != this) then
    throw("available for self invoke only")
  else
    # Initialize protocol with supported tokens
    let newLp = Issue("PUPAS LP", "PUPAS AI TREASURY LP", 0, 6, true)
    let newLpId = toBase58String(calculateAssetId(newLp))
    
    [
      newLp,
      StringEntry("setup_lpId", newLpId),
      StringEntry("setup_usdtId", usdtIdStr),
      StringEntry("setup_usdtuId", usdtuIdStr)
    ]
}Waves Blockchain Benefits
Transaction Efficiency
- Low Fees: ~0.005 WAVES per transaction 
- Fast Finality: ~1 minute confirmation 
- Predictable Costs: No gas price volatility 
- RIDE Language: Secure, predictable smart contracts 
Data Storage
# Protocol configuration stored on-chain
func tryGetString(key: String) = {
  match getString(this, key) {
    case a: String => a
    case _ => ""
  }
}
# Access stored values
let usdtIdStr = tryGetString("setup_usdtId")
let usdtuIdStr = valueOrElse(getString("setup_usdtuId"), "B45iYkZVC9cudR2yxrsJnrM75StiTrwphbfQ7xkyisip")
let lpIdStr = tryGetString("setup_lpId")Monitoring and Alerts
Real-time Monitoring
- Price Deviations: Oracle volatility tolerance enforced 
- Strategy Performance: AI agent monitoring 
- Liquidity Levels: Automated withdrawal processing 
- System Health: Smart contract state validation 
Error Handling
# Comprehensive error messages for user guidance
if (pmt.assetId != usdtId && pmt.assetId != usdtuId) then
  throw("please attach USDT: " + usdtIdStr + ", " + usdtuIdStr)
# Volatility protection
if (oracleChangeDelta > OracleVolatilityTolerance) then
  throw("max change for oracle is " + toString(fraction(OracleVolatilityTolerance / 100, Scale6)) + "%")Important: LP token prices can go down as well as up. AI strategies don't guarantee profits and may result in losses during adverse market conditions.
Next Steps
- Understand LP Token mechanics in detail 
- Learn about Protocol Features to see AI capabilities 
- Explore Yield Sources for profit generation 
Last updated