Pure package detail
ammmathv2
gno.land/p/g1mv0052e7r6s09f5t9xsqf00nj3tqsgt9dg52jr/gnomemepad/ammmathv2
Indexed deployment identity with independently loaded latest RPC source. Functions and Render are realm-only RPC capabilities.
Indexed deployment
Identity
- Package path
- gno.land/p/g1mv0052e7r6s09f5t9xsqf00nj3tqsgt9dg52jr/gnomemepad/ammmathv2
- Block
- 88113
- Deployed (UTC)
- Transaction
- Lb9NyZdgZRqupX/je0Xhe4eBoAjzhVcnUoELkRQTE6o=
Latest RPC state
Source
// Package ammmath implements integer bonding-curve and constant-product AMM
// helpers for the gnomemepad factory (Pump-style virtual CPMM + real CPMM pool).
package ammmathv2
import "math/overflow"
// FeeResult is the split of a gross trade fee.
type FeeResult struct {
Gross int64
Net int64
Fee int64
Creator int64
Protocol int64
Remainder int64
}
// ApplyFee takes gross quote paid by the user and feeBPS (e.g. 120 = 1.20%).
func ApplyFee(gross, feeBPS, creatorShareBPS, protocolShareBPS int64) FeeResult {
if gross <= 0 {
panic("ammmath: gross must be positive")
}
if feeBPS < 0 || feeBPS >= 10000 {
panic("ammmath: feeBPS out of range")
}
if creatorShareBPS < 0 || protocolShareBPS < 0 || creatorShareBPS+protocolShareBPS > 10000 {
panic("ammmath: fee share BPS invalid")
}
fee := gross * feeBPS / 10000
net := gross - fee
creator := fee * creatorShareBPS / 10000
protocol := fee * protocolShareBPS / 10000
remainder := fee - creator - protocol
return FeeResult{
Gross: gross,
Net: net,
Fee: fee,
Creator: creator,
Protocol: protocol,
Remainder: remainder,
}
}
// ApplyFeeOnOutput charges fee on assets leaving the pool/curve.
func ApplyFeeOnOutput(grossOut, feeBPS, creatorShareBPS, protocolShareBPS int64) FeeResult {
if grossOut <= 0 {
panic("ammmath: grossOut must be positive")
}
if feeBPS < 0 || feeBPS >= 10000 {
panic("ammmath: feeBPS out of range")
}
if creatorShareBPS < 0 || protocolShareBPS < 0 || creatorShareBPS+protocolShareBPS > 10000 {
panic("ammmath: fee share BPS invalid")
}
fee := grossOut * feeBPS / 10000
net := grossOut - fee
if net <= 0 {
panic("ammmath: fee consumes entire output")
}
creator := fee * creatorShareBPS / 10000
protocol := fee * protocolShareBPS / 10000
remainder := fee - creator - protocol
return FeeResult{
Gross: grossOut,
Net: net,
Fee: fee,
Creator: creator,
Protocol: protocol,
Remainder: remainder,
}
}
// BuyTokens quotes a virtual constant-product buy (net ugnot in).
func BuyTokens(virtualUgnot, virtualToken, ugnotIn int64) (tokensOut, newVU, newVT int64) {
if ugnotIn <= 0 {
panic("ammmath: ugnotIn must be positive")
}
if virtualUgnot <= 0 || virtualToken <= 0 {
panic("ammmath: invalid virtual reserves")
}
newVU, ok := overflow.Add64(virtualUgnot, ugnotIn)
if !ok {
panic("ammmath: virtual ugnot overflow")
}
k, ok := overflow.Mul64(virtualUgnot, virtualToken)
if !ok {
panic("ammmath: k overflow")
}
newVT = k / newVU
if newVT <= 0 {
panic("ammmath: empty virtual token reserve")
}
if newVT >= virtualToken {
panic("ammmath: zero tokens out")
}
tokensOut = virtualToken - newVT
return tokensOut, newVU, newVT
}
// MaxNetInForTokenOut is the largest net ugnot in that yields tokensOut <= maxTokensOut
// (integer CPMM, same floor rules as BuyTokens). Used to fill the last curve tokens
// without panicking when the user sends too much GNOT.
func MaxNetInForTokenOut(virtualUgnot, virtualToken, maxTokensOut int64) int64 {
if maxTokensOut <= 0 || virtualUgnot <= 0 || virtualToken <= 0 {
return 0
}
if maxTokensOut >= virtualToken {
return 0
}
targetNewVT := virtualToken - maxTokensOut
k, ok := overflow.Mul64(virtualUgnot, virtualToken)
if !ok {
panic("ammmath: k overflow")
}
// tokensOut <= max ⇔ k/(vu+net) >= targetNewVT ⇔ vu+net <= k/targetNewVT (floor)
maxNewVU := k / targetNewVT
if maxNewVU <= virtualUgnot {
return 0
}
return maxNewVU - virtualUgnot
}
// SellTokens quotes a virtual constant-product sell (gross ugnot out).
func SellTokens(virtualUgnot, virtualToken, tokensIn int64) (ugnotOut, newVU, newVT int64) {
if tokensIn <= 0 {
panic("ammmath: tokensIn must be positive")
}
if virtualUgnot <= 0 || virtualToken <= 0 {
panic("ammmath: invalid virtual reserves")
}
newVT, ok := overflow.Add64(virtualToken, tokensIn)
if !ok {
panic("ammmath: virtual token overflow")
}
k, ok := overflow.Mul64(virtualUgnot, virtualToken)
if !ok {
panic("ammmath: k overflow")
}
newVU = k / newVT
if newVU <= 0 {
panic("ammmath: empty virtual ugnot reserve")
}
if newVU >= virtualUgnot {
panic("ammmath: zero ugnot out")
}
ugnotOut = virtualUgnot - newVU
return ugnotOut, newVU, newVT
}
// PoolSwapUgnotForToken swaps net ugnot for tokens; remainderToPool adds to ugnot reserve.
func PoolSwapUgnotForToken(poolUgnot, poolToken, ugnotIn, remainderToPool int64) (tokensOut, newPU, newPT int64) {
if ugnotIn <= 0 {
panic("ammmath: ugnotIn must be positive")
}
if poolUgnot <= 0 || poolToken <= 0 {
panic("ammmath: invalid pool reserves")
}
if remainderToPool < 0 {
panic("ammmath: negative remainder")
}
addU, ok := overflow.Add64(ugnotIn, remainderToPool)
if !ok {
panic("ammmath: add overflow")
}
newPU, ok = overflow.Add64(poolUgnot, addU)
if !ok {
panic("ammmath: pool ugnot overflow")
}
tokensOut = poolToken * ugnotIn / (poolUgnot + ugnotIn)
if tokensOut <= 0 {
panic("ammmath: zero tokens out of pool")
}
if tokensOut >= poolToken {
panic("ammmath: would drain pool tokens")
}
newPT = poolToken - tokensOut
return tokensOut, newPU, newPT
}
// PoolSwapTokenForUgnot swaps tokens for gross ugnot out.
func PoolSwapTokenForUgnot(poolUgnot, poolToken, tokensIn int64) (ugnotOut, newPU, newPT int64) {
if tokensIn <= 0 {
panic("ammmath: tokensIn must be positive")
}
if poolUgnot <= 0 || poolToken <= 0 {
panic("ammmath: invalid pool reserves")
}
newPT, ok := overflow.Add64(poolToken, tokensIn)
if !ok {
panic("ammmath: pool token overflow")
}
ugnotOut = poolUgnot * tokensIn / (poolToken + tokensIn)
if ugnotOut <= 0 {
panic("ammmath: zero ugnot out of pool")
}
if ugnotOut >= poolUgnot {
panic("ammmath: would drain pool ugnot")
}
newPU = poolUgnot - ugnotOut
return ugnotOut, newPU, newPT
}
// CanGraduate reports whether raised net ugnot meets the threshold.
func CanGraduate(raisedUgnot, threshold int64) bool {
return raisedUgnot >= threshold && threshold > 0
}
// SpotPriceUgnotPerToken returns ugnot per token scaled by 1e6 (display only).
func SpotPriceUgnotPerToken(ugnotReserve, tokenReserve int64) int64 {
if tokenReserve <= 0 {
return 0
}
return ugnotReserve * 1000000 / tokenReserve
}
The verified vm/qfuncs operation accepts realm paths only.
Pure packages expose source files but do not have Realm Render.