Realm detail
incentives
gno.land/r/g1mv0052e7r6s09f5t9xsqf00nj3tqsgt9dg52jr/zdex/incentives/v2
Indexed deployment identity with independently loaded latest RPC source, functions, and Render.
Indexed deployment
Identity
- Package path
- gno.land/r/g1mv0052e7r6s09f5t9xsqf00nj3tqsgt9dg52jr/zdex/incentives/v2
- Block
- 241019
- Deployed (UTC)
- Transaction
- Yra1c8LyEdXww2YPGXGvHEx6hZpuOyMWZiEzOgIyYKI=
Latest RPC state
Source
package incentives
import (
"chain"
"chain/banker"
"chain/runtime/unsafe"
"gno.land/p/g1mv0052e7r6s09f5t9xsqf00nj3tqsgt9dg52jr/zdex/amm/v1"
"gno.land/r/g1mv0052e7r6s09f5t9xsqf00nj3tqsgt9dg52jr/zdex/v2"
)
func takeFund(cur realm, poolID string) (sent int64, g *Gauge) {
require(cur.Previous().IsUserCall(), "zdex: ugnot is EOA-only")
require(!paused, "zdex: paused")
os := unsafe.OriginSend()
require(len(os) == 1 && os[0].Denom == nativeDenom, "zdex: only ugnot")
sent = os.AmountOf(nativeDenom)
require(sent >= minFundUgnot, "zdex: min 1 GNOT")
_, _, _, totalLP, _ := zdex.PoolInfo(poolID)
require(totalLP > minLiquidity, "zdex: empty pool")
g = ensureGauge(poolID, true)
require(g.On, "zdex: gauge off")
accrue(g)
return sent, g
}
// Fund deposits OriginSend ugnot into the pool gauge as a lump (duration 0).
// Anyone EOA may incentivize. Does not call zdex swap or LP — PoolInfo only.
func Fund(cur realm, poolID string) {
sent, g := takeFund(cur, poolID)
_, _, _, totalLP, _ := zdex.PoolInfo(poolID)
delta := amm.MulDiv(sent, scale, totalLP)
require(delta > 0, "zdex: dust fund")
g.Acc = add64(g.Acc, delta)
g.TotalFunded = add64(g.TotalFunded, sent)
chain.Emit("Fund", "pool", poolID, "amount", itoa(sent), "acc", itoa(g.Acc))
}
// FundProgram streams OriginSend ugnot over durationBlocks. Acc is not
// increased until accrue. durationBlocks >= 28800.
func FundProgram(cur realm, poolID string, durationBlocks int64) {
require(durationBlocks >= minProgramBlocks, "zdex: duration")
sent, g := takeFund(cur, poolID)
rpb := sent / durationBlocks
require(rpb > 0, "zdex: dust fund")
now := height()
g.EndH = add64(now, durationBlocks)
g.RewardPerBlock = rpb
g.Remaining = sent
g.LastH = now
g.TotalFunded = add64(g.TotalFunded, sent)
chain.Emit("FundProgram", "pool", poolID, "amount", itoa(sent), "duration", itoa(durationBlocks), "rpb", itoa(rpb))
}
// accrue applies pending program emission to Acc. lastH becomes now, or endH
// if the window has closed.
func accrue(g *Gauge) {
if g == nil || g.RewardPerBlock <= 0 {
return
}
now := height()
if now <= g.LastH {
return
}
until := g.EndH
if now < until {
until = now
}
dt := until - g.LastH
if dt > 0 && g.Remaining > 0 {
pay := mul64(g.RewardPerBlock, dt)
if pay > g.Remaining {
pay = g.Remaining
}
if pay > 0 {
_, _, _, totalLP, _ := zdex.PoolInfo(g.ID)
if totalLP > 0 {
g.Acc = add64(g.Acc, amm.MulDiv(pay, scale, totalLP))
}
g.Remaining = sub64(g.Remaining, pay)
}
}
g.LastH = until
}
func pendingOf(poolID string, owner address) int64 {
if g := tryGauge(poolID); g != nil {
accrue(g)
}
st := tryStake(poolID, owner)
if st == nil || st.LastLP <= 0 {
return 0
}
acc := int64(0)
if g := tryGauge(poolID); g != nil {
acc = g.Acc
}
if acc <= st.LastAcc {
return 0
}
live := zdex.PositionOf(poolID, owner)
eligible := st.LastLP
if live < eligible {
eligible = live
}
if eligible <= 0 {
return 0
}
return amm.MulDiv(eligible, acc-st.LastAcc, scale)
}
// Sync pays min(LastLP, live PositionOf) against Acc, then snapshots.
// RemoveLiquidity on v2 without Claim forfeits unclaimed gauge (insolvency).
func Sync(cur realm, poolID string) int64 {
if g := tryGauge(poolID); g != nil {
accrue(g)
}
caller := cur.Previous().Address()
earned := pendingOf(poolID, caller)
st := getOrCreateStake(poolID, caller)
acc := int64(0)
if g := tryGauge(poolID); g != nil {
acc = g.Acc
}
st.LastLP = zdex.PositionOf(poolID, caller)
st.LastAcc = acc
if earned > 0 {
sendUgnot(0, cur, caller, earned)
}
chain.Emit("Sync", "pool", poolID, "to", caller.String(), "earned", itoa(earned))
return earned
}
func Claim(cur realm, poolID string) int64 {
return Sync(cur, poolID)
}
func SetGauge(cur realm, poolID string, on bool) {
mustOwner(cur)
require(poolID != "", "zdex: pool")
g := ensureGauge(poolID, on)
g.On = on
chain.Emit("SetGauge", "pool", poolID, "on", itoa(btoi(on)))
}
func SetPaused(cur realm, v bool) {
mustOwner(cur)
paused = v
chain.Emit("Pause", "paused", itoa(btoi(v)))
}
func sendUgnot(_ int, rlm realm, to address, amount int64) {
if !rlm.IsCurrent() {
panic("zdex: spoofed realm")
}
bk := banker.NewBanker(banker.BankerTypeRealmSend, rlm)
bk.SendCoins(rlm.Address(), to, chain.Coins{{Denom: nativeDenom, Amount: amount}})
}
Latest RPC state
Exported functions
- Fund(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, poolID string)
- FundProgram(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, poolID string, durationBlocks int64)
- Sync(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, poolID string) int64
- Claim(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, poolID string) int64
- SetGauge(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, poolID string, on bool)
- SetPaused(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, v bool)
- Version() string
- DexPkg() string
- Admin() string
- Paused() bool
- GaugeSnapshot(poolID string) string
- GaugeList() string
- Claimable(poolID string, owner string) int64
Latest RPC state · Realm Render
zdex incentives v2
Sidecar gauges on DexPkg. Native ugnot via OriginSend. Lump Fund or timed FundProgram. LP Claim uses LastLP; does not call zdex swap or LP.
- Version: 2
- Dex:
gno.land/r/g1mv0052e7r6s09f5t9xsqf00nj3tqsgt9dg52jr/zdex/v2 - Admin:
g1mv0052e7r6s09f5t9xsqf00nj3tqsgt9dg52jr
Gauges
None yet.
Fund
Attach ugnot with the tx. Lump credit to Acc (duration 0). Any EOA can incentivize a live pool (totalLP > 0).
FundProgram
Timed emission. durationBlocks >= 28800. Acc grows on accrue, not at deposit.
Claim
Settles LastLP then snapshots current PositionOf. Works when paused or gauge off.