Transaction
EAE032A6D7B1C5…309C49A2EFD3
Block 77,271 · index 0 · indexed
Summary
- Hash
- EAE032A6D7B1C56B2E1D20D5CB3A40DCB39C731837CC94938604309C49A2EFD3
- Block
- 77,271
- Size
- 103261 bytes
- Gas used
- 131,248,212 / 157,497,795
- Fee
- 157498 ugnot
- Status
- success
Messages
Arguments · 24
- #1launchpad
- #2README.md
- #3# Launchpad Token distribution platform for launching projects with time-locked GNS deposits and project-token rewards. ## Overview The launchpad supports projects with three lock tiers: 30, 90, and 180 days. Project creators configure the project-token reward allocation for each tier, and depositors receive rewards according to the selected tier. ## Configuration - **Pool Tiers**: 30 days, 90 days, and 180 days - **Minimum Start Delay**: 3 days from project creation - **Minimum Deposit**: 1 GNS (1,000,000 base units) and integer multiples of that amount - **Reward Claim Delay**: 1 day after each deposit, capped at the selected tier's end time - **Condition Delimiter**: Use `*PAD*` between condition expressions - **Auto-Delegation**: Project deposits can be reflected in governance-staker accounting ## Core Features - **Project Creation**: Admin or governance creates a project and its tiers - **GNS Deposits**: Users deposit GNS into a selected project tier - **Time-Locked Withdrawals**: A depositor can withdraw the original GNS only after the tier ends - **Project-Token Rewards**: Rewards accrue over the tier duration and can be claimed after the claim delay - **Administrative Refund**: Admin can transfer the remaining refundable project-token balance from an ended project to a supplied recipient; active depositor claims remain reserved ## Key Functions ### `CreateProject` Creates a new project with token address, reward amount, tier configuration, and optional `*PAD*`-separated conditions. Only admin or governance may call it. ### `DepositGns` Deposits GNS into a project tier. The deposit amount must meet the minimum and multiple rules. ### `CollectRewardByDepositId` Claims the project-token reward for a deposit. Only the deposit owner can call it, and the reward is claimable one day after deposit creation, capped by the tier end time. ### `CollectDepositGns` Settles any claimable project-token reward and then returns the original GNS deposit. Only the deposit owner can call it, and the current time must be strictly after the selected tier's end time. ### `TransferLeftFromProjectByAdmin` Transfers the remaining refundable project-token balance from an ended project to the supplied recipient. Only admin may call it; amounts reserved for active depositor claims are not transferred. ## Approval Requirements - `DepositGns` pulls GNS from the caller into the launchpad realm, so approve the launchpad realm for at least the deposit amount before calling. - `CollectRewardByDepositId` and `CollectDepositGns` pay out to the caller and require no approval. ```go // Approve the launchpad realm before depositing launchpadAddress := access.MustGetAddress(prabc.ROLE_LAUNCHPAD.String()) gns.Approve(cross(cur), launchpadAddress, 10_000_000) ``` ## Usage ```go // Create a project (admin or governance; start must be at least 3 days away) projectID := CreateProject( cross(cur), "Example Project", "gno.land/r/demo/projecttoken", recipientAddr, 1_000_000_000, "", // no condition tokens "", // no condition amounts 10, // 30-day tier ratio 20, // 90-day tier ratio 70, // 180-day tier ratio futureStartTimestamp, ) // Deposit GNS into a 30-day tier; referrer is optional depositID := DepositGns(cross(cur), projectID+":30", 10_000_000, "") // Claim after the one-day delay CollectRewardByDepositId(cross(cur), depositID) // After the tier has ended, settle reward and withdraw principal CollectDepositGns(cross(cur), depositID) // Admin refund of the remaining project-token balance TransferLeftFromProjectByAdmin(cross(cur), projectID, recipientAddr) ``` ## Security - Admin or governance authorization is required for project creation - Deposits are locked until strictly after the selected tier's end time - Project-token rewards are claimable only by the deposit owner and only after the one-day delay - Withdrawal settles any claimable project-token reward before returning principal - Administrative refunds require an ended project and preserve active depositor claims - Conditions are evaluated for each deposit when configured - Depositor and reward recipient addresses are validated
- #4assert.gno
- #5package launchpad import ( ufmt "gno.land/p/nt/ufmt/v0" ) // assertIsDepositOwner asserts that the caller is the owner of the deposit. // Panics if the caller is not the owner of the deposit. func (lp *launchpadV1) assertIsDepositOwner(depositID string, caller address) { deposit, err := lp.getDeposit(depositID) if err != nil { panic(err.Error()) } if !deposit.IsDepositor(caller) { panic(makeErrorWithDetails(errInvalidOwner, ufmt.Sprintf("(%s)", caller.String())).Error()) } } // assertIsValidAmount panics if the amount is zero. func assertIsValidAmount(amount int64) { if amount < minimumDepositAmount { panic(makeErrorWithDetails( errInvalidAmount, ufmt.Sprintf("amount(%d) should greater than minimum deposit amount(%d)", amount, minimumDepositAmount), )) } if (amount % minimumDepositAmount) != 0 { panic(makeErrorWithDetails( errInvalidAmount, ufmt.Sprintf("amount(%d) must be a multiple of 1_000_000", amount), )) } } // assertHasProject asserts that the caller is the owner of at least one project. // Panics if the caller is not the owner of any project. func (lp *launchpadV1) assertHasProject(caller address) { if !lp.store.GetProjectRecipients().Has(caller.String()) { panic(makeErrorWithDetails( errInvalidOwner, ufmt.Sprintf("caller %s is not the owner of any project", caller.String()), )) } } func assertNotImplementYet() { panic("NotImplementYet") }
- #6consts.gno
- #7package launchpad const ( projectTier30 = int64(30) projectTier90 = int64(90) projectTier180 = int64(180) dayTime = int64(24 * 60 * 60) // 86400 minimumDepositAmount = int64(1_000_000) stringSplitterPad = "*PAD*" maxProjectConditionCount = 5 projectMinimumStartDelayTime = dayTime * 3 // 3 days ) // contract paths const ( GOV_XGNS_PATH string = "gno.land/r/gnoswap/gov/xgns" GNS_TOKEN_KEY string = "gno.land/r/gnoswap/gns.GNS" ) // MUST BE IMMUTABLE, DO NOT MODIFY. var projectTierDurations = []int64{ projectTier30, projectTier90, projectTier180, } // MUST BE IMMUTABLE, DO NOT MODIFY. var projectTierDurationTimes = map[int64]int64{ projectTier30: dayTime * projectTier30, // 30 days projectTier90: dayTime * projectTier90, // 90 days projectTier180: dayTime * projectTier180, // 180 days } // MUST BE IMMUTABLE, DO NOT MODIFY. var projectTierRewardCollectableDuration = map[int64]int64{ projectTier30: dayTime * 1, // 1 days projectTier90: dayTime * 1, // 1 days projectTier180: dayTime * 1, // 1 days }
- #8deposit.gno
- #9package launchpad import "gno.land/r/gnoswap/launchpad" func withdrawDeposit(d launchpad.Deposit, currentHeight, currentTime int64) (launchpad.Deposit, int64) { d.SetWithdrawn(currentHeight, currentTime) previousDepositAmount := d.DepositAmount() d.SetDepositAmount(0) return d, previousDepositAmount }
- #10emits.gno
- #11package launchpad import ( "chain" "gno.land/p/gnoswap/utils/v1" "gno.land/r/gnoswap/launchpad" ) // emitUpdateLaunchpadRewardAccumulation emits the persisted per-tier reward // accumulation state so that off-chain indexers can consume the authoritative // accumulator instead of re-deriving it. It must be emitted after every path that // calls updateRewardPerDepositX128 (deposit/withdraw/collect/admin-reclaim), // otherwise the off-chain accumulator drifts from the contract. // // The reward manager is keyed by projectTierId, so it is included to identify which // tier's accumulator this update belongs to. totalDepositAmount is the current tier // deposit total after the stake change (the divisor for the next accumulation delta), // and distributeAmountPerSecondX128 lets indexers project the accumulator forward. func emitUpdateLaunchpadRewardAccumulation(projectTierID string, r *launchpad.RewardManager, totalDepositAmount int64) { chain.Emit( "UpdateLaunchpadRewardAccumulation", "projectTierId", projectTierID, "totalDepositAmount", utils.FormatInt(totalDepositAmount), "accumulatedRewardPerDepositX128", r.AccumulatedRewardPerDepositX128().ToString(), "distributeAmountPerSecondX128", r.DistributeAmountPerSecondX128().ToString(), "accumulatedTime", utils.FormatInt(r.AccumulatedTime()), ) }
- #12errors.gno
- #13package launchpad import ( ufmt "gno.land/p/nt/ufmt/v0" ) const ( errNoLeftReward = "[GNOSWAP-LAUNCHPAD-001] no left reward" errInvalidAddress = "[GNOSWAP-LAUNCHPAD-002] invalid address" errDataNotFound = "[GNOSWAP-LAUNCHPAD-003] requested data not found" errInactiveProject = "[GNOSWAP-LAUNCHPAD-004] project is inactive" errInvalidInput = "[GNOSWAP-LAUNCHPAD-005] invalid input data" errDuplicateProject = "[GNOSWAP-LAUNCHPAD-006] cannot create same project in same block" errInvalidTier = "[GNOSWAP-LAUNCHPAD-007] invalid tier" errInsufficientBalance = "[GNOSWAP-LAUNCHPAD-008] insufficient balance" errInvalidData = "[GNOSWAP-LAUNCHPAD-009] invalid data" errInvalidAmount = "[GNOSWAP-LAUNCHPAD-010] invalid amount" errInvalidRewardState = "[GNOSWAP-LAUNCHPAD-011] invalid reward state" errNotExistDeposit = "[GNOSWAP-LAUNCHPAD-012] not exist deposit" errAlreadyCollected = "[GNOSWAP-LAUNCHPAD-013] already collected" errInvalidOwner = "[GNOSWAP-LAUNCHPAD-014] invalid owner" errInvalidTime = "[GNOSWAP-LAUNCHPAD-015] invalid time" errNotYetEndedProject = "[GNOSWAP-LAUNCHPAD-016] project lock period is not over yet" errOverflow = "[GNOSWAP-LAUNCHPAD-017] overflow" errSpoofedRealm = "[GNOSWAP-LAUNCHPAD-018] rlm does not match the current crossing frame" ) // makeErrorWithDetails creates an error with additional context. func makeErrorWithDetails(message string, details string) error { return ufmt.Errorf("%s || %s", message, details) }
- #14getter.gno
- #15package launchpad import ( "errors" "time" rotree "gno.land/p/nt/bptree/rotree/v0" ufmt "gno.land/p/nt/ufmt/v0" "gno.land/p/gnoswap/uint256/v1" "gno.land/r/gnoswap/launchpad" ) // GetProjects returns a read-only view of every project, keyed by project ID. // // Returns: // - projects: read-only tree keyed by project ID; project entries are cloned before being exposed. func (lp *launchpadV1) GetProjects() *rotree.ReadOnlyTree { return rotree.Wrap(lp.store.GetProjects(), cloneProjectEntry) } // GetProjectName returns the name of a project by its ID. // Returns empty string and error if project not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // // Returns: // - name: configured project name; empty when the project is absent. // - err: nil when found; non-nil when projectId is not present in state. func (lp *launchpadV1) GetProjectName(projectId string) (string, error) { project, err := lp.getProject(projectId) if err != nil { return "", err } return project.Name(), nil } // GetProjectTokenPath returns the token path of a project by its ID. // Returns empty string and error if project not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // // Returns: // - tokenPath: reward-token contract path configured for the project; empty when absent. // - err: nil when found; non-nil when projectId is not present in state. func (lp *launchpadV1) GetProjectTokenPath(projectId string) (string, error) { project, err := lp.getProject(projectId) if err != nil { return "", err } return project.TokenPath(), nil } // GetProjectDepositAmount returns the deposit amount of a project by its ID. // Returns 0 and error if project not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // // Returns: // - amount: project-level token amount deposited for distribution; zero when absent. // - err: nil when found; non-nil when projectId is not present in state. func (lp *launchpadV1) GetProjectDepositAmount(projectId string) (int64, error) { project, err := lp.getProject(projectId) if err != nil { return 0, err } return project.DepositAmount(), nil } // GetProjectRecipient returns the recipient address of a project by its ID. // Returns empty address and error if project not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // // Returns: // - recipient: address configured to receive the project's tokens; empty address when absent. // - err: nil when found; non-nil when projectId is not present in state. func (lp *launchpadV1) GetProjectRecipient(projectId string) (address, error) { project, err := lp.getProject(projectId) if err != nil { return address(""), err } return project.Recipient(), nil } // GetProjectCondition retrieves a specific condition of a project. // Returns nil and error if project or condition not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // - tokenPath: condition-token contract path used as the project's condition key. // // Returns: // - condition: matching project condition; nil when the project or condition is absent. // - err: nil when found; non-nil when projectId or tokenPath is not present. func (lp *launchpadV1) GetProjectCondition(projectId string, tokenPath string) (*launchpad.ProjectCondition, error) { project, err := lp.getProject(projectId) if err != nil { return nil, err } conditions := project.Conditions() condition, exists := conditions[tokenPath] if !exists { return nil, makeErrorWithDetails(errDataNotFound, ufmt.Sprintf("condition(%s) not found", tokenPath)) } return condition, nil } // GetProjectTiersRatios returns the tiers ratios map of a project by its ID. // Returns nil and error if project not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // // Returns: // - ratios: map from tier duration (30, 90, or 180) to its allocation percentage; nil when the project is absent. // - err: nil when found; non-nil when projectId is not present in state. func (lp *launchpadV1) GetProjectTiersRatios(projectId string) (map[int64]int64, error) { project, err := lp.getProject(projectId) if err != nil { return nil, err } return project.TiersRatios(), nil } // GetProjectCreatedHeight returns the created height of a project by its ID. // Returns 0 and error if project not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // // Returns: // - height: project creation block height; zero when the project is absent. // - err: nil when found; non-nil when projectId is not present in state. func (lp *launchpadV1) GetProjectCreatedHeight(projectId string) (int64, error) { project, err := lp.getProject(projectId) if err != nil { return 0, err } return project.CreatedHeight(), nil } // GetProjectCreatedAt returns the created time of a project by its ID. // Returns 0 and error if project not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // // Returns: // - createdAt: project creation timestamp in Unix seconds; zero when the project is absent. // - err: nil when found; non-nil when projectId is not present in state. func (lp *launchpadV1) GetProjectCreatedAt(projectId string) (int64, error) { project, err := lp.getProject(projectId) if err != nil { return 0, err } return project.CreatedAt(), nil } // GetProjectTier retrieves a specific tier of a project. // Returns nil and error if project or tier not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // - tier: tier duration in days; launchpad tiers use 30, 90, or 180. // // Returns: // - projectTier: matching project tier; nil when the project or tier is absent. // - err: nil when found; non-nil when projectId or tier is not present. func (lp *launchpadV1) GetProjectTier(projectId string, tier int64) (*launchpad.ProjectTier, error) { project, err := lp.getProject(projectId) if err != nil { return nil, err } projectTier, err := getProjectTier(project, tier) if err != nil { return nil, err } return projectTier, nil } // GetProjectTierDistributeAmountPerSecondX128 returns the distribute amount per second (Q128) of a project tier. // Returns nil and error if project or tier not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // - tier: tier duration in days; launchpad tiers use 30, 90, or 180. // // Returns: // - amountPerSecondX128: per-second distribution rate encoded as a Q128 fixed-point value; nil when lookup fails. // - err: nil when found; non-nil when projectId or tier is not present. func (lp *launchpadV1) GetProjectTierDistributeAmountPerSecondX128(projectId string, tier int64) (*uint256.Uint, error) { projectTier, err := lp.GetProjectTier(projectId, tier) if err != nil { return nil, err } return projectTier.DistributeAmountPerSecondX128(), nil } // GetProjectTierTotalDistributeAmount returns the total distribute amount of a project tier. // Returns 0 and error if project or tier not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // - tier: tier duration in days; launchpad tiers use 30, 90, or 180. // // Returns: // - amount: total token amount allocated for distribution by the tier; zero when lookup fails. // - err: nil when found; non-nil when projectId or tier is not present. func (lp *launchpadV1) GetProjectTierTotalDistributeAmount(projectId string, tier int64) (int64, error) { projectTier, err := lp.GetProjectTier(projectId, tier) if err != nil { return 0, err } return projectTier.TotalDistributeAmount(), nil } // GetProjectTierTotalDepositAmount returns the total deposit amount of a project tier. // Returns 0 and error if project or tier not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // - tier: tier duration in days; launchpad tiers use 30, 90, or 180. // // Returns: // - amount: aggregate token amount deposited into the tier; zero when lookup fails. // - err: nil when found; non-nil when projectId or tier is not present. func (lp *launchpadV1) GetProjectTierTotalDepositAmount(projectId string, tier int64) (int64, error) { projectTier, err := lp.GetProjectTier(projectId, tier) if err != nil { return 0, err } return projectTier.TotalDepositAmount(), nil } // GetProjectTierTotalWithdrawAmount returns the total withdraw amount of a project tier. // Returns 0 and error if project or tier not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // - tier: tier duration in days; launchpad tiers use 30, 90, or 180. // // Returns: // - amount: aggregate token amount withdrawn from the tier; zero when lookup fails. // - err: nil when found; non-nil when projectId or tier is not present. func (lp *launchpadV1) GetProjectTierTotalWithdrawAmount(projectId string, tier int64) (int64, error) { projectTier, err := lp.GetProjectTier(projectId, tier) if err != nil { return 0, err } return projectTier.TotalWithdrawAmount(), nil } // GetProjectTierTotalDepositCount returns the total deposit count of a project tier. // Returns 0 and error if project or tier not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // - tier: tier duration in days; launchpad tiers use 30, 90, or 180. // // Returns: // - count: number of deposits recorded for the tier; zero when lookup fails. // - err: nil when found; non-nil when projectId or tier is not present. func (lp *launchpadV1) GetProjectTierTotalDepositCount(projectId string, tier int64) (int64, error) { projectTier, err := lp.GetProjectTier(projectId, tier) if err != nil { return 0, err } return projectTier.TotalDepositCount(), nil } // GetProjectTierTotalWithdrawCount returns the total withdraw count of a project tier. // Returns 0 and error if project or tier not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // - tier: tier duration in days; launchpad tiers use 30, 90, or 180. // // Returns: // - count: number of withdrawals recorded for the tier; zero when lookup fails. // - err: nil when found; non-nil when projectId or tier is not present. func (lp *launchpadV1) GetProjectTierTotalWithdrawCount(projectId string, tier int64) (int64, error) { projectTier, err := lp.GetProjectTier(projectId, tier) if err != nil { return 0, err } return projectTier.TotalWithdrawCount(), nil } // GetProjectTierTotalCollectedAmount returns the total collected amount of a project tier. // Returns 0 and error if project or tier not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // - tier: tier duration in days; launchpad tiers use 30, 90, or 180. // // Returns: // - amount: aggregate reward amount collected from the tier; zero when lookup fails. // - err: nil when found; non-nil when projectId or tier is not present. func (lp *launchpadV1) GetProjectTierTotalCollectedAmount(projectId string, tier int64) (int64, error) { projectTier, err := lp.GetProjectTier(projectId, tier) if err != nil { return 0, err } return projectTier.TotalCollectedAmount(), nil } // GetProjectTierStartTime returns the start time of a project tier. // Returns 0 and error if project or tier not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // - tier: tier duration in days; launchpad tiers use 30, 90, or 180. // // Returns: // - startTime: tier start timestamp in Unix seconds; zero when lookup fails. // - err: nil when found; non-nil when projectId or tier is not present. func (lp *launchpadV1) GetProjectTierStartTime(projectId string, tier int64) (int64, error) { projectTier, err := lp.GetProjectTier(projectId, tier) if err != nil { return 0, err } return projectTier.StartTime(), nil } // GetProjectTierEndTime returns the end time of a project tier. // Returns 0 and error if project or tier not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // - tier: tier duration in days; launchpad tiers use 30, 90, or 180. // // Returns: // - endTime: tier end timestamp in Unix seconds; zero when lookup fails. // - err: nil when found; non-nil when projectId or tier is not present. func (lp *launchpadV1) GetProjectTierEndTime(projectId string, tier int64) (int64, error) { projectTier, err := lp.GetProjectTier(projectId, tier) if err != nil { return 0, err } return projectTier.EndTime(), nil } // GetDepositCount returns the total number of deposits. // // Returns: // - count: number of deposit entries currently stored. func (lp *launchpadV1) GetDepositCount() int { deposits := lp.store.GetDeposits() return deposits.Size() } // GetCurrentDepositId returns the current deposit counter value. // // Returns: // - depositID: current int64 deposit counter used to generate subsequent deposit identifiers. func (lp *launchpadV1) GetCurrentDepositId() int64 { counter := lp.store.GetDepositCounter() return counter.Get() } // GetProjectTierRewards returns a read-only view of a project tier's reward // states, keyed by deposit ID. nil is returned when the project tier does not // exist. // // Parameters: // - projectId: unique launchpad project identifier used to form the tier ID. // - tier: tier duration in days; launchpad tiers use 30, 90, or 180. // // Returns: // - rewards: read-only tree of reward states keyed by deposit ID; nil when the tier's reward manager lookup fails. func (lp *launchpadV1) GetProjectTierRewards(projectId string, tier int64) *rotree.ReadOnlyTree { projectTierID := launchpad.MakeProjectTierID(projectId, tier) rewardManager, err := lp.getProjectTierRewardManager(projectTierID) if err != nil { return nil } return rotree.Wrap(rewardManager.Rewards(), cloneRewardStateEntry) } // GetDeposit retrieves the value payload of a deposit by its ID. // // Parameters: // - depositId: unique deposit identifier to look up. // // Returns: // - deposit: stored deposit value; zero-valued when the entry is missing or has an invalid type. // - err: nil for a valid stored deposit; non-nil when the entry is missing or has an invalid type. func (lp *launchpadV1) GetDeposit(depositId string) (launchpad.Deposit, error) { return lp.getDepositValue(depositId) } // GetDepositProjectID returns the project ID of a deposit by its ID. // // Parameters: // - depositId: unique deposit identifier to look up. // // Returns: // - projectID: project identifier recorded on the deposit; empty when the entry is missing or invalid. // - err: nil for a valid stored deposit; non-nil when the entry is missing or has an invalid type. func (lp *launchpadV1) GetDepositProjectID(depositId string) (string, error) { deposit, err := lp.getDepositValue(depositId) if err != nil { return "", err } return deposit.ProjectID(), nil } // GetDepositTier returns the tier of a deposit by its ID. // // Parameters: // - depositId: unique deposit identifier to look up. // // Returns: // - tier: tier duration recorded on the deposit; zero when the entry is missing or invalid. // - err: nil for a valid stored deposit; non-nil when the entry is missing or has an invalid type. func (lp *launchpadV1) GetDepositTier(depositId string) (int64, error) { deposit, err := lp.getDepositValue(depositId) if err != nil { return 0, err } return deposit.Tier(), nil } // GetDepositProjectTierID returns the project tier ID of a deposit by its ID. // // Parameters: // - depositId: unique deposit identifier to look up. // // Returns: // - projectTierID: composite project-tier identifier derived from the deposit; empty when the entry is missing or invalid. // - err: nil for a valid stored deposit; non-nil when the entry is missing or has an invalid type. func (lp *launchpadV1) GetDepositProjectTierID(depositId string) (string, error) { deposit, err := lp.getDepositValue(depositId) if err != nil { return "", err } return deposit.ProjectTierID(), nil } // GetDepositAmount returns the deposit amount of a deposit by its ID. // // Parameters: // - depositId: unique deposit identifier to look up. // // Returns: // - amount: GNS amount recorded on the deposit; zero when the entry is missing or invalid. // - err: nil for a valid stored deposit; non-nil when the entry is missing or has an invalid type. func (lp *launchpadV1) GetDepositAmount(depositId string) (int64, error) { deposit, err := lp.getDepositValue(depositId) if err != nil { return 0, err } return deposit.DepositAmount(), nil } // GetDepositWithdrawnHeight returns the withdrawn height of a deposit by its ID. // // Parameters: // - depositId: unique deposit identifier to look up. // // Returns: // - withdrawnHeight: withdrawal block height recorded on the deposit; zero when the entry is missing or invalid. // - err: nil for a valid stored deposit; non-nil when the entry is missing or has an invalid type. func (lp *launchpadV1) GetDepositWithdrawnHeight(depositId string) (int64, error) { deposit, err := lp.getDepositValue(depositId) if err != nil { return 0, err } return deposit.WithdrawnHeight(), nil } // GetDepositWithdrawnTime returns the withdrawn time of a deposit by its ID. // // Parameters: // - depositId: unique deposit identifier to look up. // // Returns: // - withdrawnTime: withdrawal timestamp in Unix seconds; zero when the entry is missing or invalid. // - err: nil for a valid stored deposit; non-nil when the entry is missing or has an invalid type. func (lp *launchpadV1) GetDepositWithdrawnTime(depositId string) (int64, error) { deposit, err := lp.getDepositValue(depositId) if err != nil { return 0, err } return deposit.WithdrawnTime(), nil } // GetDepositCreatedHeight returns the created height of a deposit by its ID. // // Parameters: // - depositId: unique deposit identifier to look up. // // Returns: // - createdHeight: creation block height recorded on the deposit; zero when the entry is missing or invalid. // - err: nil for a valid stored deposit; non-nil when the entry is missing or has an invalid type. func (lp *launchpadV1) GetDepositCreatedHeight(depositId string) (int64, error) { deposit, err := lp.getDepositValue(depositId) if err != nil { return 0, err } return deposit.CreatedHeight(), nil } // GetDepositCreatedAt returns the created time of a deposit by its ID. // // Parameters: // - depositId: unique deposit identifier to look up. // // Returns: // - createdAt: creation timestamp in Unix seconds; zero when the entry is missing or invalid. // - err: nil for a valid stored deposit; non-nil when the entry is missing or has an invalid type. func (lp *launchpadV1) GetDepositCreatedAt(depositId string) (int64, error) { deposit, err := lp.getDepositValue(depositId) if err != nil { return 0, err } return deposit.CreatedAt(), nil } // GetDepositEndTime returns the end time of a deposit by its ID. // // Parameters: // - depositId: unique deposit identifier to look up. // // Returns: // - endTime: tier end timestamp in Unix seconds; zero when the entry is missing or invalid. // - err: nil for a valid stored deposit; non-nil when the entry is missing or has an invalid type. func (lp *launchpadV1) GetDepositEndTime(depositId string) (int64, error) { deposit, err := lp.getDepositValue(depositId) if err != nil { return 0, err } return deposit.EndTime(), nil } // GetTotalGNSStakedAmount returns the total amount of GNS currently staked across all launchpad deposits. // // Returns: // - amount: aggregate GNS amount currently staked across all launchpad deposits. func (lp *launchpadV1) GetTotalGNSStakedAmount() int64 { return lp.store.GetTotalGNSStakedAmount() } // GetProjectTierRewardManagerCount returns the total number of reward managers. // // Returns: // - count: number of project-tier reward-manager entries currently stored. func (lp *launchpadV1) GetProjectTierRewardManagerCount() int { managers := lp.store.GetProjectTierRewardManagers() return managers.Size() } // GetProjectTierRewardManager retrieves a reward manager by project tier ID. // Returns nil and error if reward manager not found. // // Parameters: // - projectTierId: composite project-tier identifier whose reward manager is requested. // // Returns: // - manager: matching reward manager; nil when no entry exists or its value has an invalid type. // - err: nil for a valid manager; non-nil when the entry is absent or has an invalid type. func (lp *launchpadV1) GetProjectTierRewardManager(projectTierId string) (*launchpad.RewardManager, error) { managers := lp.store.GetProjectTierRewardManagers() value := managers.Get(projectTierId) if value == nil { return nil, makeErrorWithDetails(errDataNotFound, "reward manager not found") } manager, ok := value.(*launchpad.RewardManager) if !ok { return nil, errors.New("invalid reward manager type") } return manager, nil } // GetProjectTierRewardDistributeAmountPerSecondX128 returns the distribute amount per second (Q128) of a reward manager. // Returns nil and error if reward manager not found. // // Parameters: // - projectTierId: composite project-tier identifier whose reward manager is requested. // // Returns: // - amountPerSecondX128: per-second distribution rate encoded as a Q128 fixed-point value; nil when lookup fails. // - err: nil when found; non-nil when the reward manager is absent or has an invalid type. func (lp *launchpadV1) GetProjectTierRewardDistributeAmountPerSecondX128(projectTierId string) (*uint256.Uint, error) { manager, err := lp.GetProjectTierRewardManager(projectTierId) if err != nil { return nil, err } return manager.DistributeAmountPerSecondX128(), nil } // GetProjectTierRewardAccumulatedRewardPerDepositX128 returns the accumulated reward per deposit (Q128) of a reward manager. // Returns nil and error if reward manager not found. // // Parameters: // - projectTierId: composite project-tier identifier whose reward manager is requested. // // Returns: // - accumulatedRewardPerDepositX128: accumulated reward index per deposited GNS, encoded as Q128; nil when lookup fails. // - err: nil when found; non-nil when the reward manager is absent or has an invalid type. func (lp *launchpadV1) GetProjectTierRewardAccumulatedRewardPerDepositX128(projectTierId string) (*uint256.Uint, error) { manager, err := lp.GetProjectTierRewardManager(projectTierId) if err != nil { return nil, err } return manager.AccumulatedRewardPerDepositX128(), nil } // GetProjectTierRewardTotalDistributeAmount returns the total distribute amount of a reward manager. // Returns 0 and error if reward manager not found. // // Parameters: // - projectTierId: composite project-tier identifier whose reward manager is requested. // // Returns: // - amount: total token amount allocated to the reward manager; zero when lookup fails. // - err: nil when found; non-nil when the reward manager is absent or has an invalid type. func (lp *launchpadV1) GetProjectTierRewardTotalDistributeAmount(projectTierId string) (int64, error) { manager, err := lp.GetProjectTierRewardManager(projectTierId) if err != nil { return 0, err } return manager.TotalDistributeAmount(), nil } // GetProjectTierRewardTotalClaimedAmount returns the total claimed amount of a reward manager. // Returns 0 and error if reward manager not found. // // Parameters: // - projectTierId: composite project-tier identifier whose reward manager is requested. // // Returns: // - amount: total token amount already claimed from the reward manager; zero when lookup fails. // - err: nil when found; non-nil when the reward manager is absent or has an invalid type. func (lp *launchpadV1) GetProjectTierRewardTotalClaimedAmount(projectTierId string) (int64, error) { manager, err := lp.GetProjectTierRewardManager(projectTierId) if err != nil { return 0, err } return manager.TotalClaimedAmount(), nil } // GetProjectTierRewardDistributeStartTime returns the distribute start time of a reward manager. // Returns 0 and error if reward manager not found. // // Parameters: // - projectTierId: composite project-tier identifier whose reward manager is requested. // // Returns: // - startTime: reward distribution start timestamp in Unix seconds; zero when lookup fails. // - err: nil when found; non-nil when the reward manager is absent or has an invalid type. func (lp *launchpadV1) GetProjectTierRewardDistributeStartTime(projectTierId string) (int64, error) { manager, err := lp.GetProjectTierRewardManager(projectTierId) if err != nil { return 0, err } return manager.DistributeStartTime(), nil } // GetProjectTierRewardDistributeEndTime returns the distribute end time of a reward manager. // Returns 0 and error if reward manager not found. // // Parameters: // - projectTierId: composite project-tier identifier whose reward manager is requested. // // Returns: // - endTime: reward distribution end timestamp in Unix seconds; zero when lookup fails. // - err: nil when found; non-nil when the reward manager is absent or has an invalid type. func (lp *launchpadV1) GetProjectTierRewardDistributeEndTime(projectTierId string) (int64, error) { manager, err := lp.GetProjectTierRewardManager(projectTierId) if err != nil { return 0, err } return manager.DistributeEndTime(), nil } // GetProjectTierRewardAccumulatedDistributeAmount returns a legacy reward-manager field. // The v1 reward paths do not maintain it, so normal reads return zero unless it // was explicitly set. // // Parameters: // - projectTierId: composite project-tier identifier whose reward manager is requested. // // Returns: // - amount: legacy accumulated-distribution amount, normally zero in v1 unless explicitly set. // - err: nil when found; non-nil when the reward manager is absent or has an invalid type. func (lp *launchpadV1) GetProjectTierRewardAccumulatedDistributeAmount(projectTierId string) (int64, error) { manager, err := lp.GetProjectTierRewardManager(projectTierId) if err != nil { return 0, err } return manager.AccumulatedDistributeAmount(), nil } // GetProjectTierRewardAccumulatedTime returns the accumulated time of a reward manager. // Returns 0 and error if reward manager not found. // // Parameters: // - projectTierId: composite project-tier identifier whose reward manager is requested. // // Returns: // - accumulatedTime: timestamp in Unix seconds at which reward accumulation was last updated; zero before an update. // - err: nil when found; non-nil when the reward manager is absent or has an invalid type. func (lp *launchpadV1) GetProjectTierRewardAccumulatedTime(projectTierId string) (int64, error) { manager, err := lp.GetProjectTierRewardManager(projectTierId) if err != nil { return 0, err } return manager.AccumulatedTime(), nil } // GetProjectTierRewardClaimableDuration returns the reward claimable duration of a reward manager. // Returns 0 and error if reward manager not found. // // Parameters: // - projectTierId: composite project-tier identifier whose reward manager is requested. // // Returns: // - duration: configured period during which rewards remain claimable, in the manager's timestamp units; zero when lookup fails. // - err: nil when found; non-nil when the reward manager is absent or has an invalid type. func (lp *launchpadV1) GetProjectTierRewardClaimableDuration(projectTierId string) (int64, error) { manager, err := lp.GetProjectTierRewardManager(projectTierId) if err != nil { return 0, err } return manager.RewardClaimableDuration(), nil } // GetRewardState retrieves a reward state by project tier ID and deposit ID. // Returns nil and error if reward manager or reward state not found. // // Parameters: // - projectTierId: composite project-tier identifier whose reward manager contains the state. // - depositId: unique deposit identifier whose reward state is requested. // // Returns: // - rewardState: matching reward state; nil when the manager or state is absent or has an invalid type. // - err: nil when found; non-nil when the manager or state is absent or has an invalid type. func (lp *launchpadV1) GetRewardState(projectTierId string, depositId string) (*launchpad.RewardState, error) { managers := lp.store.GetProjectTierRewardManagers() value := managers.Get(projectTierId) if value == nil { return nil, makeErrorWithDetails(errDataNotFound, "reward manager not found") } manager, ok := value.(*launchpad.RewardManager) if !ok { return nil, errors.New("invalid reward manager type") } rewards := manager.Rewards() rewardValue := rewards.Get(depositId) if rewardValue == nil { return nil, makeErrorWithDetails(errDataNotFound, "reward state not found") } rewardState, ok := rewardValue.(*launchpad.RewardState) if !ok { return nil, errors.New("invalid reward state type") } return rewardState, nil } // GetProjectActiveStatus returns whether a project is currently active. // Returns false and error if project not found. // // Parameters: // - projectId: unique launchpad project identifier to look up. // // Returns: // - active: true when the project's standard 180-day tier is active at the current Unix time; false when inactive. // - err: nil when found; non-nil when projectId is not present in state. func (lp *launchpadV1) GetProjectActiveStatus(projectId string) (bool, error) { project, err := lp.getProject(projectId) if err != nil { return false, err } currentTime := time.Now().Unix() return isProjectActive(project, currentTime), nil }
- #16getter_utils.gno
- #17package launchpad import ( "gno.land/r/gnoswap/launchpad" ) // The functions below are makeEntrySafeFn transformations handed to // rotree.Wrap. They run on every read through a read-only view, so each one // returns a value the caller may hold without reaching realm-owned state. // cloneProjectEntry is the transformation for the project tree. Project is // mutable and its setters are declared in /r/gnoswap/launchpad, so an external // holder of the stored pointer could write realm state through it. // // Project.Clone leaves the project's maps nil; see it for which lookups read // them instead. func cloneProjectEntry(value any) any { project, ok := value.(*launchpad.Project) if !ok { return nil } return project.Clone() } // cloneRewardStateEntry is the transformation for a project tier's reward // tree. RewardState is mutable and its setters are declared in // /r/gnoswap/launchpad, so an external holder of the stored pointer could // write realm state through it. func cloneRewardStateEntry(value any) any { rewardState, ok := value.(*launchpad.RewardState) if !ok { return nil } return rewardState.Clone() }
- #18gnomod.toml
- #19module = "gno.land/r/gnoswap/launchpad/v1" gno = "0.9"
- #20init.gno
- #21package launchpad import "gno.land/r/gnoswap/launchpad" func init(cur realm) { registerLaunchpadV1(cur) } func registerLaunchpadV1(cur realm) { launchpad.RegisterInitializer(cross(cur), func(_ int, rlm realm, launchpadStore launchpad.ILaunchpadStore) launchpad.ILaunchpad { err := initStoreData(0, rlm, launchpadStore) if err != nil { panic(err) } return NewLaunchpadV1(launchpadStore) }) } func initStoreData(_ int, rlm realm, launchpadStore launchpad.ILaunchpadStore) error { if !launchpadStore.HasProjectsKey() { err := launchpadStore.SetProjects(0, rlm, launchpad.NewBPTreeN(16)) if err != nil { return err } } if !launchpadStore.HasProjectRecipientsKey() { err := launchpadStore.SetProjectRecipients(0, rlm, launchpad.NewBPTreeN(16)) if err != nil { return err } } if !launchpadStore.HasProjectTierRewardManagersKey() { err := launchpadStore.SetProjectTierRewardManagers(0, rlm, launchpad.NewBPTreeN(16)) if err != nil { return err } } if !launchpadStore.HasDepositCounterStoreKey() { err := launchpadStore.SetDepositCounter(0, rlm, launchpad.NewCounter()) if err != nil { return err } } if !launchpadStore.HasDepositsKey() { err := launchpadStore.SetDeposits(0, rlm, launchpad.NewBPTreeN(16)) if err != nil { return err } } if !launchpadStore.HasTotalGNSStakedAmountKey() { err := launchpadStore.SetTotalGNSStakedAmount(0, rlm, 0) if err != nil { return err } } return nil }
- #22instance.gno
- #23package launchpad import ( "gno.land/r/gnoswap/launchpad" ) type launchpadV1 struct { store launchpad.ILaunchpadStore } // NewLaunchpadV1 constructs a version-one launchpad implementation backed by launchpadStore. // // Parameters: // - launchpadStore: store implementation used for all launchpad state reads and writes. // // Returns: // - launchpad: launchpad implementation that delegates persistence to launchpadStore. func NewLaunchpadV1(launchpadStore launchpad.ILaunchpadStore) launchpad.ILaunchpad { return &launchpadV1{ store: launchpadStore, } }
- #24launchpad_deposit.gno
Result log
msg:0,success:true,log:,events:[]