Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

storagecost_test.gno

4.29 Kb · 138 lines
  1package storagecost
  2
  3import (
  4	"testing"
  5
  6	"gno.land/p/nt/uassert/v0"
  7)
  8
  9func TestRefund(t *testing.T) {
 10	tests := []struct {
 11		name  string
 12		bytes int64
 13		price int64
 14		want  int64
 15	}{
 16		{"one byte at the default price", 1, DefaultStoragePrice, 100},
 17		{"the measured reap", 17835, DefaultStoragePrice, 1783500},
 18		{"the measured compact", 830, DefaultStoragePrice, 83000},
 19		{"zero bytes", 0, DefaultStoragePrice, 0},
 20		{"negative bytes are not a credit", -100, DefaultStoragePrice, 0},
 21		{"a free chain refunds nothing", 1000, 0, 0},
 22		{"a ten-fold price rise", 1000, 1000, 1000000},
 23	}
 24	for _, tt := range tests {
 25		t.Run(tt.name, func(t *testing.T) {
 26			uassert.Equal(t, tt.want, Refund(tt.bytes, tt.price))
 27		})
 28	}
 29}
 30
 31func TestBreakEvenBytes(t *testing.T) {
 32	tests := []struct {
 33		name string
 34		fee  int64
 35		want int64
 36	}{
 37		// A 2.6M gas call at the floor costs 2,600 ugnot, so 26 bytes.
 38		{"the canonical 2.6M gas call", 2600, 26},
 39		{"rounds up, never down", 101, 2},
 40		{"exactly one byte", 100, 1},
 41		{"a fee below one byte still needs a byte", 1, 1},
 42		{"no fee, no threshold", 0, 0},
 43	}
 44	for _, tt := range tests {
 45		t.Run(tt.name, func(t *testing.T) {
 46			got := BreakEvenBytes(tt.fee, DefaultStoragePrice)
 47			uassert.Equal(t, tt.want, got)
 48			// The definition: this many bytes covers the fee, one fewer does not.
 49			if tt.want > 0 {
 50				uassert.True(t, Refund(got, DefaultStoragePrice) >= tt.fee)
 51				uassert.False(t, Refund(got-1, DefaultStoragePrice) >= tt.fee)
 52			}
 53		})
 54	}
 55	uassert.Equal(t, int64(0), BreakEvenBytes(1000, 0))
 56}
 57
 58func TestGasFee(t *testing.T) {
 59	// The floor mainnet has actually accepted: 1 ugnot per 1000 gas.
 60	uassert.Equal(t, int64(5000), FloorGasFee(5_000_000))
 61	uassert.Equal(t, int64(2500), FloorGasFee(2_500_000))
 62	// Rounds up, so a fee is never short.
 63	uassert.Equal(t, int64(1), FloorGasFee(1))
 64	uassert.Equal(t, int64(0), FloorGasFee(0))
 65	// The harness price used in the measurements, 1.2 ugnot per gas.
 66	uassert.Equal(t, int64(6_000_000), GasFee(5_000_000, 12, 10))
 67	uassert.Equal(t, int64(0), GasFee(5_000_000, 0, 10))
 68	uassert.Equal(t, int64(0), GasFee(5_000_000, 1, 0))
 69}
 70
 71func TestEvaluateReproducesTheMeasuredReap(t *testing.T) {
 72	// The measured run: 17,835 bytes freed by a call that used 4,120,876 gas,
 73	// so gas_wanted 5,000,000 at the floor. Net +1,778,500 ugnot.
 74	q := EvaluateAtFloor(17835, 5_000_000)
 75	uassert.Equal(t, int64(1783500), q.Refund)
 76	uassert.Equal(t, int64(5000), q.Fee)
 77	uassert.Equal(t, int64(1778500), q.Net)
 78	uassert.Equal(t, int64(50), q.BreakEven)
 79	uassert.True(t, q.Worth())
 80}
 81
 82func TestEvaluateReproducesTheMeasuredCompact(t *testing.T) {
 83	q := EvaluateAtFloor(830, 2_500_000)
 84	uassert.Equal(t, int64(83000), q.Refund)
 85	uassert.Equal(t, int64(2500), q.Fee)
 86	uassert.Equal(t, int64(80500), q.Net)
 87	uassert.True(t, q.Worth())
 88}
 89
 90func TestEvaluateAtTheHarnessPriceIsALoss(t *testing.T) {
 91	// The same reap priced at 1.2 ugnot/gas, 1200x the floor, loses money.
 92	// This is why the gas price cannot be baked into a contract.
 93	q := Evaluate(17835, DefaultStoragePrice, 5_000_000, 12, 10)
 94	uassert.Equal(t, int64(6_000_000), q.Fee)
 95	uassert.False(t, q.Worth())
 96	uassert.True(t, q.Net < 0)
 97}
 98
 99func TestQuoteString(t *testing.T) {
100	worth := EvaluateAtFloor(17835, 5_000_000)
101	uassert.Equal(t,
102		"17835 bytes, refunds 1.7835 GNOT against 0.005 GNOT of gas, break-even 50 bytes: worth 1.7785 GNOT",
103		worth.String())
104
105	loss := Evaluate(10, DefaultStoragePrice, 5_000_000, 12, 10)
106	uassert.Equal(t,
107		"10 bytes, refunds 0.001 GNOT against 6 GNOT of gas, break-even 60000 bytes: not worth it yet",
108		loss.String())
109}
110
111func TestFormatGNOT(t *testing.T) {
112	tests := []struct {
113		amount int64
114		want   string
115	}{
116		{0, "0 GNOT"},
117		{1, "0.000001 GNOT"},
118		{100, "0.0001 GNOT"},
119		{1_000_000, "1 GNOT"},
120		{1_500_000, "1.5 GNOT"},
121		{1_783_500, "1.7835 GNOT"},
122		{978_743_800, "978.7438 GNOT"},
123		{-2_100, "-0.0021 GNOT"},
124		{1_000_001, "1.000001 GNOT"},
125	}
126	for _, tt := range tests {
127		uassert.Equal(t, tt.want, FormatGNOT(tt.amount))
128	}
129}
130
131func TestEstimateBytes(t *testing.T) {
132	// Measured: a 1,024-byte payload occupied 1,898 bytes of realm state.
133	uassert.Equal(t, int64(1894), EstimateBytes(1024))
134	uassert.Equal(t, int64(0), EstimateBytes(0))
135	uassert.Equal(t, int64(0), EstimateBytes(-5))
136	// Monotonic, which is all a bounty estimate really needs.
137	uassert.True(t, EstimateBytes(2048) > EstimateBytes(1024))
138}