Transaction

8D52A7594278B0…B755E8A8056B

Block 77,256 · index 1 · indexed

Summary

Hash
8D52A7594278B0F6F2BFDA29B73B0EC175654C7872566C386EBDB755E8A8056B
Block
77,256
Size
62193 bytes
Gas used
74,923,160 / 89,907,756
Fee
89908ugnot
Status
success

Messages

#1AddPackagegno.land/r/gnoswap/position24 arguments

Arguments · 24

  1. #1position
  2. #2README.md
  3. #3# Position NFT-based liquidity position management for concentrated liquidity. ## Overview Each liquidity position is a unique GRC721 NFT. Stored state includes the pool key, price range, liquidity, fee-growth checkpoints, tokens owed, burned marker, and operator. Current token balances are derived from the current pool price, range, and liquidity; they are not permanently stored balances. The pool accounting key encodes only the lower/upper tick pair and is scoped by pool. NFTs with the same range in one pool share the pool-level accounting entry. ## Gnoweb The root `Render("")` delegates to the active implementation and shows realm identity, halt flags, stored position count, and the next position ID. Stored records include burned positions, so the count does not represent active liquidity positions. Supported routes: - `""`: the root summary. It reads only aggregate position-store metadata. - `id/<id>`: one position record, selected by a single keyed lookup. The `<id>` must be an unsigned decimal `uint64`; malformed, overflowing, missing, and extra-segment paths return `404`. For example, `/r/gnoswap/position:id/1` shows position 1. Detail pages show the ID, burn status, NFT owner when available, token realm links, fee tier, tick range, liquidity, and stored fee accounting. The composite pool key is inline code; each token reference links to its defining realm rather than a `.SYMBOL` URL. Rendering does not enumerate positions or recompute claimable fees and current token balances. Burned records remain addressable even when their NFT owner is unavailable. ## Configuration - **Withdrawal Fee**: 1% by default on fee-bearing swap-fee collection - **Max Position Size**: No separate position-level cap; pool tick limits apply - **Transfers**: Unstaked NFTs follow GRC721 owner/approval/operator rules; staked NFTs are locked to staker-mediated transfers ## Core Functions ### `Mint` Creates new position NFT with initial liquidity. - Validates tick range alignment - Calculates optimal token ratio - Returns actual amounts used ### `IncreaseLiquidity` Adds liquidity to an existing position. - Maintains the existing price range - Uses the current-price token ratio - Can clear a burned marker when the position is used again ### `DecreaseLiquidity` Removes liquidity while keeping the NFT. - One atomic public operation: internally collects swap fees, burns liquidity, then collects principal through the pool's fee-free `Collect` path - Returns fee amounts net of the withdrawal fee and collected principal - Amount-minimum checks apply to the principal actually collected ### `CollectFee` Claims accumulated swap fees without removing liquidity. - No liquidity removal required - Returns net collected amounts plus the raw pre-withdrawal-fee amounts - The configured withdrawal fee applies only to this fee-bearing path ### `Reposition` Updates an existing position's price range. - Requires the position to be clear first (zero liquidity and tokens owed) - Reuses the same position ID and NFT - Adds new liquidity to the updated range and clears the burned marker ## Technical Details ### Tick Alignment Ticks must align with pool's tick spacing: ``` 0.01% fee: every 1 tick 0.05% fee: every 10 ticks 0.3% fee: every 60 ticks 1% fee: every 200 ticks ``` ### Optimal Range Width **Stable Pairs (USDC/USDT)**: - Narrow: ±0.05% (max efficiency) - Medium: ±0.1% (balanced) - Wide: ±0.5% (safety) **Correlated Pairs (WETH/stETH)**: - Narrow: ±0.5% - Medium: ±1% - Wide: ±2% **Volatile Pairs (WETH/USDC)**: - Narrow: ±5% - Medium: ±10% - Wide: ±25% ### Capital Efficiency Concentration factor vs infinite range: ``` Range ±0.1% → 2000x efficient Range ±1% → 200x efficient Range ±10% → 20x efficient Range ±50% → 4x efficient ``` ### Token Calculations For liquidity `L` and square-root prices `sqrtLower`, `sqrtCurrent`, and `sqrtUpper`: **Below range (`current < lower`, token0 only)**: ``` amount0 = L * (sqrtUpper - sqrtLower) / (sqrtUpper * sqrtLower) amount1 = 0 ``` **In range (`lower <= current < upper`, both tokens)**: ``` amount0 = L * (sqrtUpper - sqrtCurrent) / (sqrtUpper * sqrtCurrent) amount1 = L * (sqrtCurrent - sqrtLower) ``` **Above range (`current >= upper`, token1 only)**: ``` amount0 = 0 amount1 = L * (sqrtUpper - sqrtLower) ``` ## Approval and Transfer Requirements `Mint`, `IncreaseLiquidity`, and `Reposition` pull token0 and token1 from the caller inside the **pool** realm, so the approved spender is the pool realm address, not the position realm. - Approve the pool realm for both token contracts before calling a liquidity-adding function. - Approving the position realm alone is not sufficient; the position realm never holds or pulls the pair tokens itself. - Approve at least `amount0Desired` / `amount1Desired`. Any desired amount the pool does not consume stays with the caller. - `DecreaseLiquidity` and `CollectFee` pay out to the caller and require no approval. ```go // Approve the pool realm for both pair tokens before minting poolAddress := access.MustGetAddress(prabc.ROLE_POOL.String()) weth.Approve(cross(cur), poolAddress, 1000000) usdc.Approve(cross(cur), poolAddress, 2000000000) ``` ## Usage These snippets call the public domain proxy from a realm function with a current `cur` token. Import the proxy package and qualify its function names in integrating code. ```go // Mint new position tokenId, liquidity, amount0, amount1 := Mint( cross(cur), "gno.land/r/gnoland/wugnot.wugnot", // token0 "gno.land/r/gnoswap/gns.GNS", // token1 3000, // fee -887220, // tickLower 887220, // tickUpper "1000000", // amount0Desired "2000000000", // amount1Desired "950000", // amount0Min "1900000000", // amount1Min deadline, recipient, // mintTo "", // referrer ) // Add liquidity positionId, liquidity, amount0, amount1, poolPath := IncreaseLiquidity( cross(cur), tokenId, "500000", "1000000000", "475000", "950000000", deadline, ) // Collect fees positionId, collected0, collected1, poolPath, rawAmount0, rawAmount1 := CollectFee( cross(cur), tokenId, ) // Reposition to new range (requires cleared position) positionId, liquidity, tickLower, tickUpper, amount0, amount1 := Reposition( cross(cur), tokenId, -443610, // new tickLower 443610, // new tickUpper "1000000", // amount0Desired "2000000000", // amount1Desired "950000", // amount0Min "1900000000", // amount1Min deadline, ) ``` ## Lifecycle A full decrease that leaves zero liquidity and zero tokens owed sets the `burned` marker but does not destroy the NFT. `IncreaseLiquidity` and `Reposition` clear the marker when the position is used again; the marker does not by itself block an increase. ## Security - Tick range validation prevents invalid positions - Slippage protection applies to liquidity-changing operations; fee collection has no amount-minimum parameter - Deadlines prevent stale liquidity-changing transactions - Unstaked NFTs follow standard GRC721 transfer authorization; staked NFTs can move only through staker-mediated flows - Liquidity changes and repositioning require the owner; fee collection also permits the position's approved operator where applicable
  4. #4errors.gno
  5. #5package position const ErrSpoofedRealm = "rlm does not match the current crossing frame"
  6. #6getter.gno
  7. #7package position import ( rotree "gno.land/p/nt/bptree/rotree/v0" ) // GetPositions returns a read-only view of all positions. // // Returns: // - positions: read-only tree keyed by decimal position ID; callers paginate with IterateByOffset func GetPositions() *rotree.ReadOnlyTree { return getImplementation().GetPositions() } // IsBurned reports whether the position's empty-position marker is set. // // Parameters: // - positionId: position NFT token ID // // Returns: // - burned: whether the position's empty-position marker is set // - err: non-nil when positionId cannot be resolved func IsBurned(positionId uint64) (bool, error) { return getImplementation().IsBurned(positionId) } // IsInRange reports whether a position's ticks contain the current pool tick. // // Parameters: // - positionId: position NFT token ID // // Returns: // - inRange: whether the position is currently in range // - err: non-nil when positionId cannot be resolved or the associated pool tick cannot be read func IsInRange(positionId uint64) (bool, error) { return getImplementation().IsInRange(positionId) } // GetPositionTokenBalances calculates the current token0/token1 balances for // a position from its liquidity, tick range, and pool price. // // These are derived balances, not permanently stored token amounts. // // Parameters: // - positionId: position NFT token ID // // Returns: // - balance0: current token0 balance // - balance1: current token1 balance // - err: non-nil when positionId cannot be resolved func GetPositionTokenBalances(positionId uint64) (int64, int64, error) { return getImplementation().GetPositionTokenBalances(positionId) } // GetPositionToken0Balance returns the token0 balance associated with a position. // // Parameters: // - positionId: position NFT token ID // // Returns: // - balance: token0 balance // - err: non-nil when positionId cannot be resolved func GetPositionToken0Balance(positionId uint64) (int64, error) { balance0, _, err := GetPositionTokenBalances(positionId) if err != nil { return 0, err } return balance0, nil } // GetPositionToken1Balance returns the token1 balance associated with a position. // // Parameters: // - positionId: position NFT token ID // // Returns: // - balance: token1 balance // - err: non-nil when positionId cannot be resolved func GetPositionToken1Balance(positionId uint64) (int64, error) { _, balance1, err := GetPositionTokenBalances(positionId) if err != nil { return 0, err } return balance1, nil } // GetPositionFeeGrowthInside0LastX128 returns the last fee-growth checkpoint inside the position's range for token0. // // Parameters: // - positionId: position NFT token ID whose token0 fee-growth checkpoint is queried // // Returns: // - feeGrowthInside0LastX128: token0 fee-growth checkpoint, represented as a decimal string // - err: non-nil when positionId cannot be resolved func GetPositionFeeGrowthInside0LastX128(positionId uint64) (string, error) { return getImplementation().GetPositionFeeGrowthInside0LastX128(positionId) } // GetPositionFeeGrowthInside1LastX128 returns the last fee-growth checkpoint inside the position's range for token1. // // Parameters: // - positionId: position NFT token ID whose token1 fee-growth checkpoint is queried // // Returns: // - feeGrowthInside1LastX128: token1 fee-growth checkpoint, represented as a decimal string // - err: non-nil when positionId cannot be resolved func GetPositionFeeGrowthInside1LastX128(positionId uint64) (string, error) { return getImplementation().GetPositionFeeGrowthInside1LastX128(positionId) } // GetPositionFeeGrowthInsideLastX128 returns the last fee-growth checkpoints inside the position's range for both tokens. // // Parameters: // - positionId: position NFT token ID whose fee-growth checkpoints are queried // // Returns: // - feeGrowthInside0LastX128: token0 fee-growth checkpoint, represented as a decimal string // - feeGrowthInside1LastX128: token1 fee-growth checkpoint, represented as a decimal string // - err: non-nil when positionId cannot be resolved func GetPositionFeeGrowthInsideLastX128(positionId uint64) (string, string, error) { return getImplementation().GetPositionFeeGrowthInsideLastX128(positionId) } // GetPositionLiquidity returns the stored liquidity amount of a position. // // Parameters: // - positionId: position NFT token ID whose liquidity is queried // // Returns: // - liquidity: position liquidity, represented as a decimal string // - err: non-nil when positionId cannot be resolved func GetPositionLiquidity(positionId uint64) (string, error) { return getImplementation().GetPositionLiquidity(positionId) } // GetPositionOperator returns the approved operator address for a position. // // Parameters: // - positionId: position NFT token ID whose operator is queried // // Returns: // - operator: approved operator address; the zero address means no operator is set // - err: non-nil when positionId cannot be resolved func GetPositionOperator(positionId uint64) (address, error) { return getImplementation().GetPositionOperator(positionId) } // GetPositionPoolKey returns the pool key associated with a position. // // Parameters: // - positionId: position NFT token ID whose pool association is queried // // Returns: // - poolKey: canonical pool key used by the position // - err: non-nil when positionId cannot be resolved func GetPositionPoolKey(positionId uint64) (string, error) { return getImplementation().GetPositionPoolKey(positionId) } // GetPositionTickLower returns the lower tick boundary of a position. // // Parameters: // - positionId: position NFT token ID whose lower tick is queried // // Returns: // - tickLower: lower tick boundary of the position's price range // - err: non-nil when positionId cannot be resolved func GetPositionTickLower(positionId uint64) (int32, error) { return getImplementation().GetPositionTickLower(positionId) } // GetPositionTickUpper returns the upper tick boundary of a position. // // Parameters: // - positionId: position NFT token ID whose upper tick is queried // // Returns: // - tickUpper: upper tick boundary of the position's price range // - err: non-nil when positionId cannot be resolved func GetPositionTickUpper(positionId uint64) (int32, error) { return getImplementation().GetPositionTickUpper(positionId) } // GetPositionTicks returns the lower and upper tick boundaries of a position. // // Parameters: // - positionId: position NFT token ID whose tick range is queried // // Returns: // - tickLower: lower tick boundary of the position's price range // - tickUpper: upper tick boundary of the position's price range // - err: non-nil when positionId cannot be resolved func GetPositionTicks(positionId uint64) (int32, int32, error) { return getImplementation().GetPositionTicks(positionId) } // GetPositionTokensOwed0 returns the token0 amount accrued and owed to a position. // // Parameters: // - positionId: position NFT token ID whose token0 debt is queried // // Returns: // - tokensOwed0: token0 amount currently owed to the position // - err: non-nil when positionId cannot be resolved func GetPositionTokensOwed0(positionId uint64) (int64, error) { return getImplementation().GetPositionTokensOwed0(positionId) } // GetPositionTokensOwed1 returns the token1 amount accrued and owed to a position. // // Parameters: // - positionId: position NFT token ID whose token1 debt is queried // // Returns: // - tokensOwed1: token1 amount currently owed to the position // - err: non-nil when positionId cannot be resolved func GetPositionTokensOwed1(positionId uint64) (int64, error) { return getImplementation().GetPositionTokensOwed1(positionId) } // GetPositionTokensOwed returns the token0 and token1 amounts accrued and owed to a position. // // Parameters: // - positionId: position NFT token ID whose accrued token debt is queried // // Returns: // - tokensOwed0: token0 amount currently owed to the position // - tokensOwed1: token1 amount currently owed to the position // - err: non-nil when positionId cannot be resolved func GetPositionTokensOwed(positionId uint64) (int64, int64, error) { return getImplementation().GetPositionTokensOwed(positionId) } // GetUnclaimedFee returns the unclaimed fees for both tokens of a position as decimal strings. // // Parameters: // - positionId: position NFT token ID whose unclaimed fees are queried // // Returns: // - fee0: unclaimed token0 fee amount, represented as a decimal string // - fee1: unclaimed token1 fee amount, represented as a decimal string // - err: non-nil when positionId or the associated pool fee-growth data cannot be resolved func GetUnclaimedFee(positionId uint64) (string, string, error) { fee0, fee1, err := getImplementation().GetUnclaimedFee(positionId) if err != nil { return "", "", err } return fee0.ToString(), fee1.ToString(), nil } // GetPositionOwner returns the owner address of a position NFT. // // Parameters: // - positionId: position NFT token ID whose owner is queried // // Returns: // - owner: address that owns the position NFT // - err: non-nil when the NFT owner lookup fails func GetPositionOwner(positionId uint64) (address, error) { return getImplementation().GetPositionOwner(positionId) }
  8. #8getter_utils.gno
  9. #9package position
  10. #10gnomod.toml
  11. #11module = "gno.land/r/gnoswap/position" gno = "0.9"
  12. #12position.gno
  13. #13package position import bptree "gno.land/p/nt/bptree/v0" // Position represents a liquidity position in a pool. // Each position tracks liquidity, fee-growth checkpoints, tokens owed, and a // burned marker for the position NFT. // All uint256 fields are stored as decimal strings to reduce realm object overhead. type Position struct { operator address // address that is approved for spending this token poolKey string // poolPath of the pool which this has lp token tickLower int32 // the lower tick of the position, bounds are included tickUpper int32 // the upper tick of the position liquidity string // liquidity of the position // fee growth of the aggregate position as of the last action on the individual position feeGrowthInside0LastX128 string feeGrowthInside1LastX128 string // how many uncollected tokens are owed to the position, as of the last computation tokensOwed0 int64 tokensOwed1 int64 burned bool // empty-position marker; the NFT itself is not burned } // PoolKey returns the pool identifier associated with the position. // // Returns: // - poolKey: pool key encoding the position's token pair and fee tier func (p *Position) PoolKey() string { return p.poolKey } // SetPoolKey stores the pool identifier associated with the position. // // Parameters: // - poolKey: pool key encoding the position's token pair and fee tier func (p *Position) SetPoolKey(poolKey string) { p.poolKey = poolKey } // Liquidity returns the position's stored liquidity amount. // // Returns: // - liquidity: decimal-encoded liquidity currently held by the position func (p *Position) Liquidity() string { return p.liquidity } // SetLiquidity stores the position's liquidity amount. // // Parameters: // - liquidity: decimal string representing the position's liquidity func (p *Position) SetLiquidity(liquidity string) { p.liquidity = liquidity } // TickLower returns the lower tick boundary of the position's range. // // Returns: // - tickLower: lower tick boundary, inclusive in range checks func (p *Position) TickLower() int32 { return p.tickLower } // SetTickLower stores the lower tick boundary of the position's range. // // Parameters: // - tickLower: lower tick boundary used for the position's range func (p *Position) SetTickLower(tickLower int32) { p.tickLower = tickLower } // TickUpper returns the upper tick boundary of the position's range. // // Returns: // - tickUpper: upper tick boundary, used as the exclusive end in range checks func (p *Position) TickUpper() int32 { return p.tickUpper } // SetTickUpper stores the upper tick boundary of the position's range. // // Parameters: // - tickUpper: upper tick boundary used for the position's range func (p *Position) SetTickUpper(tickUpper int32) { p.tickUpper = tickUpper } // TokensOwed0 returns the stored amount of token0 owed to the position. // // Returns: // - tokensOwed0: accrued token0 amount awaiting collection, in token units func (p *Position) TokensOwed0() int64 { return p.tokensOwed0 } // SetTokensOwed0 stores the amount of token0 owed to the position. // // Parameters: // - tokensOwed0: accrued token0 amount awaiting collection, in token units func (p *Position) SetTokensOwed0(tokensOwed0 int64) { p.tokensOwed0 = tokensOwed0 } // TokensOwed1 returns the stored amount of token1 owed to the position. // // Returns: // - tokensOwed1: accrued token1 amount awaiting collection, in token units func (p *Position) TokensOwed1() int64 { return p.tokensOwed1 } // SetTokensOwed1 stores the amount of token1 owed to the position. // // Parameters: // - tokensOwed1: accrued token1 amount awaiting collection, in token units func (p *Position) SetTokensOwed1(tokensOwed1 int64) { p.tokensOwed1 = tokensOwed1 } // FeeGrowthInside0LastX128 returns the token0 fee-growth checkpoint. // // Returns: // - feeGrowthInside0LastX128: decimal-encoded Q128 fee growth inside the position's range at its last update func (p *Position) FeeGrowthInside0LastX128() string { return p.feeGrowthInside0LastX128 } // SetFeeGrowthInside0LastX128 stores the token0 fee-growth checkpoint. // // Parameters: // - feeGrowthInside0LastX128: decimal-encoded Q128 fee growth inside the position's range func (p *Position) SetFeeGrowthInside0LastX128(feeGrowthInside0LastX128 string) { p.feeGrowthInside0LastX128 = feeGrowthInside0LastX128 } // FeeGrowthInside1LastX128 returns the token1 fee-growth checkpoint. // // Returns: // - feeGrowthInside1LastX128: decimal-encoded Q128 fee growth inside the position's range at its last update func (p *Position) FeeGrowthInside1LastX128() string { return p.feeGrowthInside1LastX128 } // SetFeeGrowthInside1LastX128 stores the token1 fee-growth checkpoint. // // Parameters: // - feeGrowthInside1LastX128: decimal-encoded Q128 fee growth inside the position's range func (p *Position) SetFeeGrowthInside1LastX128(feeGrowthInside1LastX128 string) { p.feeGrowthInside1LastX128 = feeGrowthInside1LastX128 } // Burned reports the position's empty-position marker. // // Returns: // - burned: true when the position is marked empty after its balances clear; the position NFT itself is not burned func (p *Position) Burned() bool { return p.burned } // SetBurned stores the position's empty-position marker. // // Parameters: // - burned: marker indicating whether the position is considered empty func (p *Position) SetBurned(burned bool) { p.burned = burned } // Operator returns the address approved to operate on the position. // // Returns: // - operator: approved operator address, or the empty address when no operator is set func (p *Position) Operator() address { return p.operator } // SetOperator stores the address approved to operate on the position. // // Parameters: // - operator: approved operator address; the empty address removes the operator func (p *Position) SetOperator(operator address) { p.operator = operator } // IsClear reports whether liquidity and tokens owed are all zero; it does not // describe the burned marker. // // Returns: // - clear: true when stored liquidity and both token-owed counters are zero, regardless of the burned marker func (p *Position) IsClear() bool { return isZeroStr(p.liquidity) && p.tokensOwed0 == 0 && p.tokensOwed1 == 0 } func isZeroStr(s string) bool { return s == "" || s == "0" } // NewPosition constructs a position from its persisted pool, range, liquidity, // fee-growth, owed-token, marker, and operator values. // // Parameters: // - poolKey: pool key encoding the position's token pair and fee tier // - tickLower: lower tick boundary of the position's range // - tickUpper: upper tick boundary of the position's range // - liquidity: decimal string representing the position's liquidity // - feeGrowthInside0LastX128: decimal-encoded Q128 token0 fee-growth checkpoint // - feeGrowthInside1LastX128: decimal-encoded Q128 token1 fee-growth checkpoint // - tokensOwed0: accrued token0 amount awaiting collection, in token units // - tokensOwed1: accrued token1 amount awaiting collection, in token units // - burned: empty-position marker to store // - operator: approved operator address; the empty address means no operator // // Returns: // - position: pointer to a position initialized with all supplied values func NewPosition( poolKey string, tickLower int32, tickUpper int32, liquidity string, feeGrowthInside0LastX128, feeGrowthInside1LastX128 string, tokensOwed0, tokensOwed1 int64, burned bool, operator address, ) *Position { return &Position{ poolKey: poolKey, tickLower: tickLower, tickUpper: tickUpper, liquidity: liquidity, feeGrowthInside0LastX128: feeGrowthInside0LastX128, feeGrowthInside1LastX128: feeGrowthInside1LastX128, tokensOwed0: tokensOwed0, tokensOwed1: tokensOwed1, burned: burned, operator: operator, } } // NewPositionsTree allocates an empty BP-tree for position entries under the // position realm context. // // Returns: // - positionsTree: empty position BP-tree allocated with fanout 16 func NewPositionsTree() *bptree.BPTree { return bptree.NewBPTreeN(16) }
  14. #14proxy.gno
  15. #15package position // Mint creates a new liquidity position NFT. // // Parameters: // - cur: current realm context; callers use cross(cur) when crossing into this realm // - token0: path of the first token in the pool // - token1: path of the second token in the pool // - fee: pool fee tier used to identify the pool // - tickLower: lower tick boundary of the position's price range // - tickUpper: upper tick boundary of the position's price range // - amount0Desired: desired amount of token0 to provide // - amount1Desired: desired amount of token1 to provide // - amount0Min: minimum acceptable amount of token0 after price/slippage calculation // - amount1Min: minimum acceptable amount of token1 after price/slippage calculation // - deadline: transaction expiration timestamp // - mintTo: recipient address of the position NFT // - referrer: referrer identifier used for reward tracking // // Returns: // - positionId: newly minted position NFT token ID // - liquidity: liquidity minted into the position, represented as a decimal string // - amount0: actual amount of token0 added to the position, represented as a decimal string // - amount1: actual amount of token1 added to the position, represented as a decimal string // // Halt check: reverts while the Position halt scope is active. func Mint( cur realm, token0 string, token1 string, fee uint32, tickLower int32, tickUpper int32, amount0Desired string, amount1Desired string, amount0Min string, amount1Min string, deadline int64, mintTo address, referrer string, ) (uint64, string, string, string) { return getImplementation().Mint(0, cur, token0, token1, fee, tickLower, tickUpper, amount0Desired, amount1Desired, amount0Min, amount1Min, deadline, mintTo, referrer) } // IncreaseLiquidity adds liquidity to an existing position. // // Parameters: // - cur: current realm context; callers use cross(cur) when crossing into this realm // - positionId: position NFT token ID to increase // - amount0DesiredStr: desired token0 amount, represented as a decimal string // - amount1DesiredStr: desired token1 amount, represented as a decimal string // - amount0MinStr: minimum acceptable token0 amount for slippage protection // - amount1MinStr: minimum acceptable token1 amount for slippage protection // - deadline: transaction expiration timestamp // // Returns: // - positionId: position NFT token ID that received the liquidity // - liquidity: liquidity amount added to the position (the delta), represented as a decimal string // - amount0: actual token0 amount added, represented as a decimal string // - amount1: actual token1 amount added, represented as a decimal string // - poolKey: canonical pool key for the position // // Halt check: reverts while the Position halt scope is active. func IncreaseLiquidity( cur realm, positionId uint64, amount0DesiredStr string, amount1DesiredStr string, amount0MinStr string, amount1MinStr string, deadline int64, ) (uint64, string, string, string, string) { return getImplementation().IncreaseLiquidity(0, cur, positionId, amount0DesiredStr, amount1DesiredStr, amount0MinStr, amount1MinStr, deadline) } // DecreaseLiquidity removes liquidity from a position. // // Parameters: // - cur: current realm context; callers use cross(cur) when crossing into this realm // - positionId: position NFT token ID to decrease // - liquidityStr: liquidity amount to remove, represented as a decimal string // - amount0MinStr: minimum acceptable token0 amount for slippage protection // - amount1MinStr: minimum acceptable token1 amount for slippage protection // - deadline: transaction expiration timestamp // // The accrued swap fees are collected first, so the returned fee amounts are // net of the withdrawal fee while the returned principal is not subject to it. // // Returns: // - positionId: position NFT token ID that had liquidity removed // - liquidity: removed liquidity amount, represented as a decimal string // - fee0: token0 fees collected, net of the withdrawal fee // - fee1: token1 fees collected, net of the withdrawal fee // - amount0: principal amount of token0 returned to the caller // - amount1: principal amount of token1 returned to the caller // - poolKey: canonical pool key for the position // // Halt check: reverts while the Withdraw halt scope is active. func DecreaseLiquidity( cur realm, positionId uint64, liquidityStr string, amount0MinStr string, amount1MinStr string, deadline int64, ) (uint64, string, string, string, string, string, string) { return getImplementation().DecreaseLiquidity(0, cur, positionId, liquidityStr, amount0MinStr, amount1MinStr, deadline) } // Reposition changes the tick range of a position. // // Parameters: // - cur: current realm context; callers use cross(cur) when crossing into this realm // - positionId: position NFT token ID to reposition // - tickLower: new lower tick boundary of the position's price range // - tickUpper: new upper tick boundary of the position's price range // - amount0DesiredStr: desired token0 amount for the new range, represented as a decimal string // - amount1DesiredStr: desired token1 amount for the new range, represented as a decimal string // - amount0MinStr: minimum acceptable token0 amount for slippage protection // - amount1MinStr: minimum acceptable token1 amount for slippage protection // - deadline: transaction expiration timestamp // // Returns: // - positionId: position NFT token ID that was repositioned // - liquidity: new liquidity amount, represented as a decimal string // - tickLower: new lower tick boundary // - tickUpper: new upper tick boundary // - amount0: actual token0 amount added to the new range, represented as a decimal string // - amount1: actual token1 amount added to the new range, represented as a decimal string // // Halt check: reverts while the Position halt scope is active. func Reposition( cur realm, positionId uint64, tickLower int32, tickUpper int32, amount0DesiredStr string, amount1DesiredStr string, amount0MinStr string, amount1MinStr string, deadline int64, ) (uint64, string, int32, int32, string, string) { return getImplementation().Reposition(0, cur, positionId, tickLower, tickUpper, amount0DesiredStr, amount1DesiredStr, amount0MinStr, amount1MinStr, deadline) } // CollectFee collects accumulated fees from a position. // // Parameters: // - cur: current realm context; callers use cross(cur) when crossing into this realm // - positionId: position NFT token ID whose fees are collected // // Returns: // - positionId: position NFT token ID whose fees were collected // - tokensCollected0: token0 fees paid out to the caller, net of the withdrawal fee // - tokensCollected1: token1 fees paid out to the caller, net of the withdrawal fee // - poolKey: canonical pool key for the position // - totalAmount0: token0 fees collected before the withdrawal fee // - totalAmount1: token1 fees collected before the withdrawal fee // // Halt check: reverts while the Withdraw halt scope is active. func CollectFee( cur realm, positionId uint64, ) (uint64, string, string, string, string, string) { return getImplementation().CollectFee(0, cur, positionId) } // SetPositionOperator sets an operator for a position. // // Parameters: // - cur: current realm context; callers use cross(cur) when crossing into this realm // - positionId: position NFT token ID whose operator is changed // - operator: operator address to approve; the zero address removes the operator func SetPositionOperator( cur realm, positionId uint64, operator address, ) { getImplementation().SetPositionOperator(0, cur, positionId, operator) }
  16. #16render.gno
  17. #17package position // Render delegates web rendering to the active implementation. func Render(path string) string { return getImplementation().Render(path) }
  18. #18state.gno
  19. #19package position import ( "errors" _ "gno.land/r/gnoswap/rbac/v1" // initialize readable contract role(s) "gno.land/p/gnoswap/store/v1" "gno.land/p/gnoswap/version_manager/v1" ) var ( domainPath = "gno.land/r/gnoswap/position" kvStore store.KVStore versionManager version_manager.VersionManager implementation IPosition ) func init(cur realm) { // Create a new KV store instance for this domain kvStore = store.NewKVStore(cur.Address()) // Initialize the initializers map to store implementation registration functions versionManager = version_manager.NewVersionManager( cur.PkgPath(), kvStore, initializeDomainStore, ) implementation = nil } func initializeDomainStore(_ int, rlm realm, kvStore store.KVStore) any { return NewPositionStore(kvStore) } func getImplementation() IPosition { if implementation == nil { panic("implementation is not initialized") } return implementation } func updateImplementation() error { result := versionManager.GetCurrentImplementation() if result == nil { return errors.New("implementation is not initialized") } impl, ok := result.(IPosition) if !ok { return errors.New("impl is not an IPosition") } implementation = impl return nil }
  20. #20store.gno
  21. #21package position import ( "errors" "gno.land/p/gnoswap/store/v1" "gno.land/p/gnoswap/utils/v1" bptree "gno.land/p/nt/bptree/v0" ufmt "gno.land/p/nt/ufmt/v0" ) type StoreKey string // String returns the textual storage-key value. // // Returns: // - key: storage key represented as a string func (s StoreKey) String() string { return string(s) } const ( StoreKeyPositions StoreKey = "positions" // Positions StoreKeyPositionNextID StoreKey = "positionNextID" // Position next ID ) type positionStore struct { kvStore store.KVStore } // HasPositionsStoreKey reports whether the positions tree is present in the KV store. // // Returns: // - exists: true when the positions storage key is present func (s *positionStore) HasPositionsStoreKey() bool { return s.kvStore.Has(StoreKeyPositions.String()) } // GetPositions loads the stored tree containing all positions. // // Returns: // - positions: mutable positions tree keyed by decimal position ID; panics when the key is missing or has an unexpected type func (s *positionStore) GetPositions() *bptree.BPTree { result, err := s.kvStore.Get(StoreKeyPositions.String()) if err != nil { panic(err) } positions, ok := result.(*bptree.BPTree) if !ok { panic(ufmt.Sprintf("failed to cast result to *bptree.BPTree: %T", result)) } return positions } // SetPositions stores the positions tree after validating the realm context. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; the store requires it to be the current realm // - positions: positions tree to persist under the positions storage key // // Returns: // - err: nil when the tree is stored; non-nil when rlm is spoofed or the KV write fails func (s *positionStore) SetPositions(_ int, rlm realm, positions *bptree.BPTree) error { if !rlm.IsCurrent() { return errors.New(ErrSpoofedRealm) } return s.kvStore.Set(0, rlm, StoreKeyPositions.String(), positions) } // HasPositionNextIDStoreKey reports whether the next-position-ID value is present in the KV store. // // Returns: // - exists: true when the next-position-ID storage key is present func (s *positionStore) HasPositionNextIDStoreKey() bool { return s.kvStore.Has(StoreKeyPositionNextID.String()) } // GetPositionNextID loads the next position NFT ID to allocate. // // Returns: // - nextID: next position ID stored by the position manager; panics when the key is missing or has an unexpected type func (s *positionStore) GetPositionNextID() uint64 { result, err := s.kvStore.Get(StoreKeyPositionNextID.String()) if err != nil { panic(err) } nextID, ok := result.(uint64) if !ok { panic(ufmt.Sprintf("failed to cast result to uint64: %T", result)) } return nextID } // SetPositionNextID stores the next position NFT ID after validating the realm context. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; the store requires it to be the current realm // - nextID: next position ID to persist for the next mint // // Returns: // - err: nil when nextID is stored; non-nil when rlm is spoofed or the KV write fails func (s *positionStore) SetPositionNextID(_ int, rlm realm, nextID uint64) error { if !rlm.IsCurrent() { return errors.New(ErrSpoofedRealm) } return s.kvStore.Set(0, rlm, StoreKeyPositionNextID.String(), nextID) } // HasPosition reports whether a position is stored for the supplied NFT ID. // // Parameters: // - positionId: position NFT token ID to look up // // Returns: // - exists: true when the decimal positionId key exists in the positions tree func (s *positionStore) HasPosition(positionId uint64) bool { positions := s.GetPositions() return positions.Has(utils.Uint64ToString(positionId)) } // GetPosition loads a position by NFT ID. // // Parameters: // - positionId: position NFT token ID to look up // // Returns: // - position: stored position value when present, or the zero Position when absent // - exists: true when positionId is present; false when no position is stored for that ID func (s *positionStore) GetPosition(positionId uint64) (Position, bool) { positions := s.GetPositions() result := positions.Get(utils.Uint64ToString(positionId)) if result == nil { return Position{}, false } position, ok := result.(Position) if !ok { panic(ufmt.Sprintf("failed to cast result to Position: %T", result)) } return position, true } // SetPosition inserts or replaces a position after validating the realm context. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; the store requires it to be the current realm // - positionId: position NFT token ID used as the tree key // - position: position value to persist // // Returns: // - err: nil when the position is stored; non-nil when rlm is spoofed, the positions key is missing, or the KV write fails func (s *positionStore) SetPosition(_ int, rlm realm, positionId uint64, position Position) error { if !rlm.IsCurrent() { return errors.New(ErrSpoofedRealm) } if !s.HasPositionsStoreKey() { return errors.New("positions store key not found") } positions := s.GetPositions() positions.Set(utils.Uint64ToString(positionId), position) return s.kvStore.Set(0, rlm, StoreKeyPositions.String(), positions) } // RemovePosition deletes a position after validating the realm context. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; the store requires it to be the current realm // - positionId: position NFT token ID to remove from the positions tree // // Returns: // - err: nil when the position is removed and the tree is stored; non-nil when rlm is spoofed, the positions key is missing, or the KV write fails func (s *positionStore) RemovePosition(_ int, rlm realm, positionId uint64) error { if !rlm.IsCurrent() { return errors.New(ErrSpoofedRealm) } if !s.HasPositionsStoreKey() { return errors.New("positions store key not found") } positions := s.GetPositions() positions.Remove(utils.Uint64ToString(positionId)) return s.kvStore.Set(0, rlm, StoreKeyPositions.String(), positions) } // NewPositionStore creates a position store backed by the provided KV store. // The upgrade system uses it to construct storage instances for each implementation. // // Parameters: // - kvStore: Domain-owned KV store shared by position implementations. // // Returns: // - IPositionStore: Position storage wrapper backed by the supplied store. func NewPositionStore(kvStore store.KVStore) IPositionStore { return &positionStore{ kvStore: kvStore, } }
  22. #22types.gno
  23. #23package position import ( u256 "gno.land/p/gnoswap/uint256/v1" rotree "gno.land/p/nt/bptree/rotree/v0" bptree "gno.land/p/nt/bptree/v0" ) type IPosition interface { IPositionManager IPositionGetter Render(path string) string } type IPositionManager interface { // Mint creates a new liquidity position NFT. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; implementations validate it as current before changing state // - token0: path of the first token in the pool // - token1: path of the second token in the pool // - fee: pool fee tier used to identify the pool // - tickLower: lower tick boundary of the position's price range // - tickUpper: upper tick boundary of the position's price range // - amount0Desired: desired amount of token0 to provide // - amount1Desired: desired amount of token1 to provide // - amount0Min: minimum acceptable token0 amount for slippage protection // - amount1Min: minimum acceptable token1 amount for slippage protection // - deadline: transaction expiration timestamp // - mintTo: recipient address of the position NFT // - referrer: referrer identifier used for reward tracking // // Returns: // - positionId: newly minted position NFT token ID // - liquidity: liquidity minted into the position, represented as a decimal string // - amount0: actual amount of token0 added, represented as a decimal string // - amount1: actual amount of token1 added, represented as a decimal string Mint( _ int, rlm realm, token0 string, token1 string, fee uint32, tickLower int32, tickUpper int32, amount0Desired string, amount1Desired string, amount0Min string, amount1Min string, deadline int64, mintTo address, referrer string, ) (uint64, string, string, string) // IncreaseLiquidity adds liquidity to an existing position. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; implementations validate it as current before changing state // - positionId: position NFT token ID to increase // - amount0DesiredStr: desired token0 amount, represented as a decimal string // - amount1DesiredStr: desired token1 amount, represented as a decimal string // - amount0MinStr: minimum acceptable token0 amount for slippage protection // - amount1MinStr: minimum acceptable token1 amount for slippage protection // - deadline: transaction expiration timestamp // // Returns: // - positionId: position NFT token ID that received the liquidity // - liquidity: liquidity amount added to the position (the delta), represented as a decimal string // - amount0: actual token0 amount added, represented as a decimal string // - amount1: actual token1 amount added, represented as a decimal string // - poolKey: canonical pool key for the position IncreaseLiquidity( _ int, rlm realm, positionId uint64, amount0DesiredStr string, amount1DesiredStr string, amount0MinStr string, amount1MinStr string, deadline int64, ) (uint64, string, string, string, string) // DecreaseLiquidity removes liquidity from a position. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; implementations validate it as current before changing state // - positionId: position NFT token ID to decrease // - liquidityStr: liquidity amount to remove, represented as a decimal string // - amount0MinStr: minimum acceptable token0 amount for slippage protection // - amount1MinStr: minimum acceptable token1 amount for slippage protection // - deadline: transaction expiration timestamp // // Returns: // - positionId: position NFT token ID that had liquidity removed // - liquidity: removed liquidity amount, represented as a decimal string // - fee0: token0 fees collected, net of the withdrawal fee // - fee1: token1 fees collected, net of the withdrawal fee // - amount0: principal amount of token0 returned to the caller // - amount1: principal amount of token1 returned to the caller // - poolKey: canonical pool key for the position DecreaseLiquidity( _ int, rlm realm, positionId uint64, liquidityStr string, amount0MinStr string, amount1MinStr string, deadline int64, ) (uint64, string, string, string, string, string, string) // Reposition changes the tick range of an existing position. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; implementations validate it as current before changing state // - positionId: position NFT token ID to reposition // - tickLower: new lower tick boundary of the position's price range // - tickUpper: new upper tick boundary of the position's price range // - amount0DesiredStr: desired token0 amount for the new range, represented as a decimal string // - amount1DesiredStr: desired token1 amount for the new range, represented as a decimal string // - amount0MinStr: minimum acceptable token0 amount for slippage protection // - amount1MinStr: minimum acceptable token1 amount for slippage protection // - deadline: transaction expiration timestamp // // Returns: // - positionId: position NFT token ID that was repositioned // - liquidity: new liquidity amount, represented as a decimal string // - tickLower: lower tick boundary applied to the position // - tickUpper: upper tick boundary applied to the position // - amount0: actual token0 amount added to the new range, represented as a decimal string // - amount1: actual token1 amount added to the new range, represented as a decimal string Reposition( _ int, rlm realm, positionId uint64, tickLower int32, tickUpper int32, amount0DesiredStr string, amount1DesiredStr string, amount0MinStr string, amount1MinStr string, deadline int64, ) (uint64, string, int32, int32, string, string) // CollectFee collects accumulated fees from a position. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; implementations validate it as current before changing state // - positionId: position NFT token ID whose fees are collected // // Returns: // - positionId: position NFT token ID whose fees were collected // - tokensCollected0: token0 fees paid out to the caller, net of the withdrawal fee // - tokensCollected1: token1 fees paid out to the caller, net of the withdrawal fee // - poolKey: canonical pool key for the position // - totalAmount0: token0 fees collected before the withdrawal fee // - totalAmount1: token1 fees collected before the withdrawal fee CollectFee( _ int, rlm realm, positionId uint64, ) (uint64, string, string, string, string, string) // SetPositionOperator sets or removes the approved operator for a position. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; implementations validate it as current before changing state // - positionId: position NFT token ID whose operator is changed // - operator: operator address to approve; the zero address removes the operator SetPositionOperator( _ int, rlm realm, positionId uint64, operator address, ) } type IPositionGetter interface { // GetPositions returns a read-only view of all positions. // // Returns: // - positions: read-only tree keyed by decimal position ID GetPositions() *rotree.ReadOnlyTree // IsBurned reports whether a position's empty-position marker is set. // // Parameters: // - positionId: position NFT token ID whose burned marker is queried // // Returns: // - burned: true when the position's empty-position marker is set // - err: non-nil when positionId cannot be resolved IsBurned(positionId uint64) (bool, error) // IsInRange reports whether a position's tick range contains the current pool tick. // // Parameters: // - positionId: position NFT token ID whose range is checked // // Returns: // - inRange: true when the current pool tick lies within the position's tick range // - err: non-nil when positionId cannot be resolved or the associated pool tick cannot be read IsInRange(positionId uint64) (bool, error) // GetPositionOperator returns the approved operator address for a position. // // Parameters: // - positionId: position NFT token ID whose operator is queried // // Returns: // - operator: approved operator address; the zero address means no operator is set // - err: non-nil when positionId cannot be resolved GetPositionOperator(positionId uint64) (address, error) // GetPositionPoolKey returns the pool key associated with a position. // // Parameters: // - positionId: position NFT token ID whose pool is queried // // Returns: // - poolKey: canonical pool key used by the position // - err: non-nil when positionId cannot be resolved GetPositionPoolKey(positionId uint64) (string, error) // GetPositionTickLower returns the lower tick boundary of a position. // // Parameters: // - positionId: position NFT token ID whose lower tick is queried // // Returns: // - tickLower: lower tick boundary of the position's price range // - err: non-nil when positionId cannot be resolved GetPositionTickLower(positionId uint64) (int32, error) // GetPositionTickUpper returns the upper tick boundary of a position. // // Parameters: // - positionId: position NFT token ID whose upper tick is queried // // Returns: // - tickUpper: upper tick boundary of the position's price range // - err: non-nil when positionId cannot be resolved GetPositionTickUpper(positionId uint64) (int32, error) // GetPositionLiquidity returns the stored liquidity amount of a position. // // Parameters: // - positionId: position NFT token ID whose liquidity is queried // // Returns: // - liquidity: position liquidity represented as a decimal string // - err: non-nil when positionId cannot be resolved GetPositionLiquidity(positionId uint64) (string, error) // GetPositionTokenBalances returns current token0 and token1 balances derived for a position. // // Parameters: // - positionId: position NFT token ID whose balances are queried // // Returns: // - balance0: current token0 balance derived from liquidity, ticks, and pool price // - balance1: current token1 balance derived from liquidity, ticks, and pool price // - err: non-nil when positionId cannot be resolved GetPositionTokenBalances(positionId uint64) (int64, int64, error) // GetPositionFeeGrowthInside0LastX128 returns the last fee-growth checkpoint inside a position's range for token0. // // Parameters: // - positionId: position NFT token ID whose token0 fee-growth checkpoint is queried // // Returns: // - feeGrowthInside0LastX128: token0 fee-growth checkpoint as a decimal string // - err: non-nil when positionId cannot be resolved GetPositionFeeGrowthInside0LastX128(positionId uint64) (string, error) // GetPositionFeeGrowthInside1LastX128 returns the last fee-growth checkpoint inside a position's range for token1. // // Parameters: // - positionId: position NFT token ID whose token1 fee-growth checkpoint is queried // // Returns: // - feeGrowthInside1LastX128: token1 fee-growth checkpoint as a decimal string // - err: non-nil when positionId cannot be resolved GetPositionFeeGrowthInside1LastX128(positionId uint64) (string, error) // GetPositionFeeGrowthInsideLastX128 returns the last fee-growth checkpoints inside a position's range for both tokens. // // Parameters: // - positionId: position NFT token ID whose fee-growth checkpoints are queried // // Returns: // - feeGrowthInside0LastX128: token0 fee-growth checkpoint as a decimal string // - feeGrowthInside1LastX128: token1 fee-growth checkpoint as a decimal string // - err: non-nil when positionId cannot be resolved GetPositionFeeGrowthInsideLastX128(positionId uint64) (string, string, error) // GetPositionTicks returns the lower and upper tick boundaries of a position. // // Parameters: // - positionId: position NFT token ID whose tick range is queried // // Returns: // - tickLower: lower tick boundary of the position's price range // - tickUpper: upper tick boundary of the position's price range // - err: non-nil when positionId cannot be resolved GetPositionTicks(positionId uint64) (int32, int32, error) // GetPositionTokensOwed0 returns the token0 amount accrued and owed to a position. // // Parameters: // - positionId: position NFT token ID whose token0 debt is queried // // Returns: // - tokensOwed0: token0 amount currently owed to the position // - err: non-nil when positionId cannot be resolved GetPositionTokensOwed0(positionId uint64) (int64, error) // GetPositionTokensOwed1 returns the token1 amount accrued and owed to a position. // // Parameters: // - positionId: position NFT token ID whose token1 debt is queried // // Returns: // - tokensOwed1: token1 amount currently owed to the position // - err: non-nil when positionId cannot be resolved GetPositionTokensOwed1(positionId uint64) (int64, error) // GetPositionTokensOwed returns token0 and token1 amounts accrued and owed to a position. // // Parameters: // - positionId: position NFT token ID whose accrued token debt is queried // // Returns: // - tokensOwed0: token0 amount currently owed to the position // - tokensOwed1: token1 amount currently owed to the position // - err: non-nil when positionId cannot be resolved GetPositionTokensOwed(positionId uint64) (int64, int64, error) // GetUnclaimedFee returns unclaimed fees for both tokens of a position. // // Parameters: // - positionId: position NFT token ID whose unclaimed fees are queried // // Returns: // - fee0: unclaimed token0 fee amount as a uint256 value // - fee1: unclaimed token1 fee amount as a uint256 value // - err: non-nil when positionId or the associated pool fee-growth data cannot be resolved GetUnclaimedFee(positionId uint64) (*u256.Uint, *u256.Uint, error) // GetPositionOwner returns the owner address of a position NFT. // // Parameters: // - positionId: position NFT token ID whose owner is queried // // Returns: // - owner: address that owns the position NFT // - err: non-nil when the NFT owner lookup fails GetPositionOwner(positionId uint64) (address, error) } type IPositionStore interface { // HasPositionsStoreKey reports whether the positions tree exists in storage. // // Returns: // - exists: true when the positions storage key is present HasPositionsStoreKey() bool // GetPositions returns the mutable positions tree. // // Returns: // - positions: positions tree keyed by decimal position ID GetPositions() *bptree.BPTree // SetPositions stores the complete positions tree. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; implementations require it to be current for storage writes // - positions: positions tree to persist, keyed by decimal position ID // // Returns: // - err: nil when the tree is stored; non-nil when the realm is spoofed or the write fails SetPositions(_ int, rlm realm, positions *bptree.BPTree) error // HasPositionNextIDStoreKey reports whether the next-position-ID value exists. // // Returns: // - exists: true when the next-position-ID storage key is present HasPositionNextIDStoreKey() bool // GetPositionNextID returns the next position NFT ID to allocate. // // Returns: // - nextID: next position ID stored for minting GetPositionNextID() uint64 // SetPositionNextID stores the next position NFT ID. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; implementations require it to be current for storage writes // - nextID: next position ID to persist for the next mint // // Returns: // - err: nil when nextID is stored; non-nil when the realm is spoofed or the write fails SetPositionNextID(_ int, rlm realm, nextID uint64) error // HasPosition reports whether an NFT ID is present in the positions tree. // // Parameters: // - positionId: position NFT token ID to look up // // Returns: // - exists: true when positionId has a stored position HasPosition(positionId uint64) bool // GetPosition loads a position by NFT ID. // // Parameters: // - positionId: position NFT token ID to look up // // Returns: // - position: stored position value, or the zero Position when absent // - exists: true when positionId is present; false when no position is stored GetPosition(positionId uint64) (Position, bool) // SetPosition inserts or replaces a position in storage. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; implementations require it to be current for storage writes // - positionId: position NFT token ID used as the storage key // - position: complete position value to persist // // Returns: // - err: nil when the position tree is updated; non-nil when the realm is spoofed, storage is missing, or the write fails SetPosition(_ int, rlm realm, positionId uint64, position Position) error // RemovePosition deletes a position from storage. // // Parameters: // - _: leading integer discriminator; callers pass 0 // - rlm: propagated realm context; implementations require it to be current for storage writes // - positionId: position NFT token ID to remove // // Returns: // - err: nil when the position tree is updated; non-nil when the realm is spoofed, storage is missing, or the write fails RemovePosition(_ int, rlm realm, positionId uint64) error }
  24. #24upgrade.gno

Result log

msg:0,success:true,log:,events:[]

← Back to block 77,256