Search Apps Documentation Source Content File Folder Download Copy Actions Download

doc.gno

5.51 Kb · 144 lines
  1// Package referral implements a referral system on Gno. It allows
  2// authorized contracts to register, update, or remove referral
  3// relationships. A referral link is defined as a mapping from one
  4// address (the "user") to another address (the "referrer").
  5//
  6// ## Overview
  7//
  8// The referral package is composed of the following components:
  9//
 10//  1. **errors.gno**: Defines error types for various failure scenarios
 11//     such as invalid address, unauthorized caller, self-referral,
 12//     rate limit exceeded, and referral not found.
 13//  2. **utils.gno**: Contains the isValidCaller function that checks
 14//     if the caller has an authorized role (governance, router, position,
 15//     staker, or launchpad contracts).
 16//  3. **type.gno**: Defines the ReferralKeeper interface and event type
 17//     constants for register, update, and remove operations.
 18//  4. **keeper.gno**: Implements the ReferralKeeper interface using an
 19//     tree for storage. Includes rate limiting (24-hour cooldown)
 20//     to prevent abuse of referral operations.
 21//  5. **global_keeper.gno**: Exposes the public API functions that
 22//     external contracts can use to interact with the referral system.
 23//
 24// ## Public API
 25//
 26// The package exposes the following public functions:
 27//
 28//   - GetReferral(addr string) string: Returns the referrer address for
 29//     the given user address. Returns empty string if not found.
 30//   - HasReferral(addr string) bool: Returns true if the user has a
 31//     registered referrer.
 32//   - IsEmpty() bool: Returns true if no referral relationships exist.
 33//   - GetLastOpTimestamp(addr string) (int64, error): Returns the last
 34//     referral operation timestamp for the given user address.
 35//   - TryRegister(cur realm, addr address, referral string) string:
 36//     Attempts to register a new referral and returns the effective referrer.
 37//     Empty input returns the user's stored referral without attempting registration.
 38//
 39// ## Workflow
 40//
 41// Typical usage of this contract follows these steps:
 42//
 43//  1. An authorized contract (router, staker, etc.) calls TryRegister
 44//     to resolve the effective referrer and optionally create a referral relationship.
 45//  2. The keeper validates the caller's permissions via isValidCaller.
 46//  3. Address validation ensures both addresses are valid and not
 47//     self-referencing.
 48//  4. Rate limiting checks prevent operations more than once per 24 hours.
 49//  5. The referral is stored in the tree and an event is emitted when registration occurs.
 50//
 51// ## Authorized Callers
 52//
 53// Only contracts with the following roles can modify referral data:
 54//
 55//   - ROLE_GOVERNANCE: Governance contracts
 56//   - ROLE_GOV_STAKER: Governance staker contracts
 57//   - ROLE_ROUTER: Router contracts
 58//   - ROLE_POSITION: Position manager contracts
 59//   - ROLE_STAKER: Staker contracts
 60//   - ROLE_LAUNCHPAD: Launchpad contracts
 61//
 62// ## Rate Limiting
 63//
 64// To prevent abuse, the system enforces a 24-hour cooldown period between
 65// operations for each address. This means:
 66//
 67//   - A new referral can only be registered once per 24 hours per address
 68//   - Updates and removals are also subject to the same rate limit
 69//   - Attempting operations within the cooldown period returns ErrTooManyRequests
 70//
 71// ## Events
 72//
 73// The package emits the following events:
 74//
 75//   - RegisterReferral: Emitted when a new referral is created
 76//   - ReferralRegistrationFailed: Emitted when non-empty referral registration fails
 77//
 78// ## Error Handling
 79//
 80// The package defines several error types:
 81//   - `ErrInvalidAddress`: Returned when an address format is invalid
 82//   - `ErrSelfReferral`: Returned when attempting to set self as referrer
 83//   - `ErrUnauthorized`: Returned when the caller lacks permission
 84//   - `ErrTooManyRequests`: Returned when rate limit is exceeded (24-hour cooldown)
 85//   - `ErrNotFound`: Returned when attempting to get a non-existent referral
 86//   - `ErrInvalidTime`: Returned when the stored timestamp format is invalid
 87//
 88// ## Example: Integration with Router Contract
 89//
 90// The router contract can register referrals during swap operations:
 91//
 92// ```go
 93//
 94//	import (
 95//	    "gno.land/r/gnoswap/referral"
 96//	)
 97//
 98//	func SwapWithReferral(cur realm, referralCode string, ...) {
 99//	    // Get the caller address
100//	    caller := cur.Previous().Address()
101//
102//	    actualReferrer := referral.TryRegister(cross(cur), caller, referralCode)
103//
104//	    // Continue with swap logic...
105//	}
106//
107// ```
108//
109// ## Example: Checking Referral for Rewards
110//
111// Other contracts can check referral relationships for reward distribution:
112//
113// ```go
114//
115//	import (
116//	    "gno.land/r/gnoswap/referral"
117//	)
118//
119//	func DistributeRewards(user address, amount uint64) {
120//	    // Check if user has a referrer
121//	    if referral.HasReferral(user.String()) {
122//	        referrerAddr := referral.GetReferral(user.String())
123//	        // Calculate and distribute referral bonus
124//	        referrerBonus := amount * referralRate / 100
125//	        sendReward(address(referrerAddr), referrerBonus)
126//	    }
127//	}
128//
129// ```
130//
131// ## Limitations and Constraints
132//
133//   - A user can have only one referrer at a time
134//   - Self-referral is not allowed
135//   - Operations are rate-limited to once per 24 hours per address
136//   - Only authorized contracts can register/update/remove referrals
137//   - Zero address as referrer triggers removal of the referral
138//
139// ## Notes
140//
141//   - The contract uses RBAC (Role-Based Access Control) for authorization
142//   - Rate limiting state persists across transactions
143//   - Events are emitted for all state changes for off-chain tracking
144package referral