PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/moul/x/grc20wrap/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
moul / x / grc20wrap
Files
8 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/moul/x/grc20wrap/v0
gno
0.9

Files (8)

  • README.mdmarkdown
  • gnomod.tomltoml
  • basket.gnogno
  • policy.gnogno
  • wrap.gnogno
  • basket_test.gnogno
  • policy_test.gnogno
  • wrap_test.gnogno
  • policy_test.gnogno
    1package grc20wrap23import (4	"math"5	"testing"67	"gno.land/p/nt/uassert/v0"8

    Functions

    not supported for pure packages by the node (vm/qfuncs)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    )
    9
    10// Every policy here is stateless, so it prices correctly against a nil vault.
    11// Pool is the one that reads the vault, and it is covered end to end in
    12// TestPoolSharesAppreciate.
    13func TestStatelessRates(t *testing.T) {
    14 cases := []struct {
    15 name string
    16 pol Policy
    17 wrapIn int64
    18 wrapOut int64
    19 unwrapIn int64
    20 unwrapOut int64
    21 }{
    22 {"one to one", OneToOne{}, 7, 7, 7, 7},
    23 {"kilo", Ratio{Num: 1_000, Den: 1}, 7, 7_000, 7_000, 7},
    24 {"kilo truncates on the way out", Ratio{Num: 1_000, Den: 1}, 1, 1_000, 2_500, 2},
    25 {"milli", Ratio{Num: 1, Den: 1_000}, 7_000, 7, 7, 7_000},
    26 {"two for three", Ratio{Num: 2, Den: 3}, 9, 6, 6, 9},
    27 {"soulbound keeps its base rate", Soulbound{Base: Ratio{Num: 2, Den: 1}}, 5, 10, 10, 5},
    28 {"soulbound with no base is 1:1", Soulbound{}, 5, 5, 5, 5},
    29 {"one percent both ways", Fee{WrapBPS: 100, UnwrapBPS: 100}, 1_000, 990, 1_000, 990},
    30 {"a haircut under one unit rounds to nothing", Fee{WrapBPS: 100}, 55, 55, 55, 55},
    31 }
    32
    33 for _, tc := range cases {
    34 got, err := tc.pol.WrapRate(nil, tc.wrapIn)
    35 uassert.NoError(t, err, tc.name)
    36 uassert.Equal(t, tc.wrapOut, got, tc.name+" (wrap)")
    37
    38 got, err = tc.pol.UnwrapRate(nil, tc.unwrapIn)
    39 uassert.NoError(t, err, tc.name)
    40 uassert.Equal(t, tc.unwrapOut, got, tc.name+" (unwrap)")
    41 }
    42}
    43
    44func TestRateErrors(t *testing.T) {
    45 cases := []struct {
    46 name string
    47 pol Policy
    48 in int64
    49 wrapErr error
    50 unwrapErr error
    51 }{
    52 {"zero numerator", Ratio{Num: 0, Den: 1}, 5, ErrBadRatio, ErrBadRatio},
    53 {"negative denominator", Ratio{Num: 2, Den: -1}, 5, ErrBadRatio, ErrBadRatio},
    54 // Only the multiplying direction can overflow; the dividing one
    55 // just returns a very small number.
    56 {"overflowing numerator", Ratio{Num: math.MaxInt64, Den: 1}, 3, ErrOverflow, nil},
    57 {"basis points above 100%", Fee{WrapBPS: 10_001, UnwrapBPS: 10_001}, 100, ErrBadBPS, ErrBadBPS},
    58 {"negative basis points", Fee{WrapBPS: -1, UnwrapBPS: -1}, 100, ErrBadBPS, ErrBadBPS},
    59 }
    60
    61 for _, tc := range cases {
    62 _, err := tc.pol.WrapRate(nil, tc.in)
    63 if tc.wrapErr == nil {
    64 uassert.NoError(t, err, tc.name+" (wrap)")
    65 } else {
    66 uassert.ErrorIs(t, err, tc.wrapErr, tc.name+" (wrap)")
    67 }
    68
    69 _, err = tc.pol.UnwrapRate(nil, tc.in)
    70 if tc.unwrapErr == nil {
    71 uassert.NoError(t, err, tc.name+" (unwrap)")
    72 } else {
    73 uassert.ErrorIs(t, err, tc.unwrapErr, tc.name+" (unwrap)")
    74 }
    75 }
    76}
    77
    78func TestPolicyNames(t *testing.T) {
    79 uassert.Equal(t, "1:1", OneToOne{}.Name())
    80 uassert.Equal(t, "1000:1", Ratio{Num: 1_000, Den: 1}.Name())
    81 uassert.Equal(t, "pool", Pool{}.Name())
    82 uassert.Equal(t, "soulbound/1:1", Soulbound{}.Name())
    83 uassert.Equal(t, "soulbound/pool", Soulbound{Base: Pool{}}.Name())
    84 uassert.Equal(t, "fee(0/100bps)/pool", Fee{Base: Pool{}, UnwrapBPS: 100}.Name())
    85}
    86
    87func TestOnlySoulboundVetoes(t *testing.T) {
    88 uassert.NoError(t, OneToOne{}.CanMove(nil, alice, bob, 1))
    89 uassert.NoError(t, Ratio{Num: 1, Den: 1}.CanMove(nil, alice, bob, 1))
    90 uassert.NoError(t, Pool{}.CanMove(nil, alice, bob, 1))
    91 uassert.NoError(t, Fee{Base: Pool{}}.CanMove(nil, alice, bob, 1))
    92 uassert.ErrorIs(t, Soulbound{}.CanMove(nil, alice, bob, 1), ErrSoulbound)
    93 // A fee over a soulbound base inherits the veto.
    94 uassert.ErrorIs(t, Fee{Base: Soulbound{}}.CanMove(nil, alice, bob, 1), ErrSoulbound)
    95}
    96