| 
 | 1 | +package tc  | 
 | 2 | + | 
 | 3 | +import (  | 
 | 4 | +	"encoding/gjson"  | 
 | 5 | +	"std"  | 
 | 6 | +	"strconv"  | 
 | 7 | +	"testing"  | 
 | 8 | + | 
 | 9 | +	"gno.land/p/demo/grc/grc20"  | 
 | 10 | +	"gno.land/p/demo/grc/grc721"  | 
 | 11 | +	"gno.land/p/demo/testutils"  | 
 | 12 | + | 
 | 13 | +	"gno.land/r/demo/users"  | 
 | 14 | + | 
 | 15 | +	// swap contract  | 
 | 16 | +	gov "gno.land/r/gov"  | 
 | 17 | +	pl "gno.land/r/pool"  | 
 | 18 | +	pos "gno.land/r/position"  | 
 | 19 | +	rou "gno.land/r/router"  | 
 | 20 | +	stk "gno.land/r/staker"  | 
 | 21 | + | 
 | 22 | +	// token  | 
 | 23 | +	_ "gno.land/r/grc20_wrapper"  | 
 | 24 | + | 
 | 25 | +	bar "gno.land/r/bar"  | 
 | 26 | +	foo "gno.land/r/foo"  | 
 | 27 | +	gns "gno.land/r/gns" // external reward  | 
 | 28 | +	// GRC721 LP Token  | 
 | 29 | +)  | 
 | 30 | + | 
 | 31 | +const (  | 
 | 32 | +	TIMESTAMP_90DAYS int64 = 7776000  | 
 | 33 | +)  | 
 | 34 | + | 
 | 35 | +var (  | 
 | 36 | +	// test address  | 
 | 37 | +	gsa  = testutils.TestAddress("gsa")  // Gnswap Admin  | 
 | 38 | +	pc01 = testutils.TestAddress("pc01") // Pool Creator 01  | 
 | 39 | +	ci01 = testutils.TestAddress("ci01") // Create Incentive Caller 01  | 
 | 40 | +	lp01 = testutils.TestAddress("lp01") // Liquidity Provider 01  | 
 | 41 | +	lp02 = testutils.TestAddress("lp02") // Liquidity Provider 02  | 
 | 42 | +	tr01 = testutils.TestAddress("tr01") // Trader 01  | 
 | 43 | + | 
 | 44 | +	// contract address  | 
 | 45 | +	poolAddr   = pl.GetOrigPkgAddr()  // Pool Contract  | 
 | 46 | +	posAddr    = pos.GetOrigPkgAddr() // Position Contract  | 
 | 47 | +	stakerAddr = stk.GetOrigPkgAddr() // Staker Contract  | 
 | 48 | +	govAddr    = gov.GetOrigPkgAddr() // Gov Contract  | 
 | 49 | +	rouAddr    = rou.GetOrigPkgAddr() // Router Contract  | 
 | 50 | + | 
 | 51 | +	// token path  | 
 | 52 | +	fooPath = "gno.land/r/foo"  | 
 | 53 | +	barPath = "gno.land/r/bar"  | 
 | 54 | +	bazPath = "gno.land/r/baz"  | 
 | 55 | +	quxPath = "gno.land/r/qux"  | 
 | 56 | +	gnsPath = "gno.land/r/gns"  | 
 | 57 | +	oblPath = "gno.land/r/obl"  | 
 | 58 | + | 
 | 59 | +	gnotPath = "gnot"  | 
 | 60 | + | 
 | 61 | +	MIN_TICK bigint = -887272  | 
 | 62 | +	MAX_TICK bigint = 887272  | 
 | 63 | + | 
 | 64 | +	MIN_SQRT_RATIO bigint = 4295128739                                        // same as TickMathGetSqrtRatioAtTick(MIN_TICK)  | 
 | 65 | +	MAX_SQRT_RATIO bigint = 1461446703485210103287273052203988822378723970342 // same as TickMathGetSqrtRatioAtTick(MAX_TICK)  | 
 | 66 | + | 
 | 67 | +	MAX_TIMEOUT bigint = 9999999999  | 
 | 68 | +)  | 
 | 69 | + | 
 | 70 | +// func init() {  | 
 | 71 | +// 	// debug addr  | 
 | 72 | +// 	println(gsa, "// gsa")  | 
 | 73 | +// 	println(pc01, "// pc01")  | 
 | 74 | +// 	println(ci01, "// ci01")  | 
 | 75 | +// 	println(lp01, "// lp01")  | 
 | 76 | +// 	println(lp02, "// lp02")  | 
 | 77 | +// 	println(tr01, "// tr01")  | 
 | 78 | +// 	println(poolAddr, "// pool")  | 
 | 79 | +// 	println(posAddr, "// pos")  | 
 | 80 | +// 	println(rouAddr, "// router")  | 
 | 81 | +// 	println(stakerAddr, "// staker")  | 
 | 82 | +// 	println(govAddr, "// gov")  | 
 | 83 | +// }  | 
 | 84 | + | 
 | 85 | +func TestPoolInitManual(t *testing.T) {  | 
 | 86 | +	std.TestSetOrigCaller(pc01)  | 
 | 87 | + | 
 | 88 | +	pl.InitManual()  | 
 | 89 | +	std.TestSkipHeights(1)  | 
 | 90 | + | 
 | 91 | +	shouldPanicWithMsg(t, func() { pl.InitManual() }, "[POOl] pool_manager.gno__InitManual() || contract must not be initialized")  | 
 | 92 | +}  | 
 | 93 | + | 
 | 94 | +func TestPoolCreatePool(t *testing.T) {  | 
 | 95 | +	std.TestSetOrigCaller(pc01)  | 
 | 96 | + | 
 | 97 | +	gsaOldGnsBalance := gns.BalanceOf(a2u(gsa))  | 
 | 98 | + | 
 | 99 | +	pl.CreatePool(gnotPath, barPath, uint16(100), 112040957517951813098925484553) // tick =  6_931, ratio = x1.99983634019692790850797337043331936001777648925781  | 
 | 100 | +	pl.CreatePool(barPath, bazPath, uint16(100), 112040957517951813098925484553)  // tick =  6_931, ratio = x1.99983634019692790850797337043331936001777648925781  | 
 | 101 | +	pl.CreatePool(bazPath, fooPath, uint16(100), 177157928842132501967358423881)  // tick =  16_095, ratio = x4.99990809049723150536692628520540893077850341796875  | 
 | 102 | +	pl.CreatePool(gnsPath, gnotPath, uint16(100), 79228162514264337593543950337)  // tick =  0, ratio = x1.00000000000000000000000000000000000000000000000000  | 
 | 103 | +	pl.CreatePool(gnsPath, quxPath, uint16(100), 250541420775534450580036817218)  // tick =  23_027, ratio = x9.99999779681069611569910193793475627899169921875000  | 
 | 104 | + | 
 | 105 | +	gsaNewGnsBalance := gns.BalanceOf(a2u(gsa))  | 
 | 106 | + | 
 | 107 | +	shouldEQ(t, len(pl.PoolGetPoolList()), 5)  | 
 | 108 | +	shouldEQ(t, gsaNewGnsBalance-gsaOldGnsBalance, 2500)  | 
 | 109 | +}  | 
 | 110 | + | 
 | 111 | +func TestPositionMintGnotBar(t *testing.T) {  | 
 | 112 | +	std.TestSetOrigCaller(lp01)  | 
 | 113 | + | 
 | 114 | +	// prepare ugnot  | 
 | 115 | +	testBanker := std.GetBanker(std.BankerTypeRealmIssue)  | 
 | 116 | +	testBanker.IssueCoin(std.GetOrigCaller(), "ugnot", 1000)  | 
 | 117 | + | 
 | 118 | +	// simulate transfer & decrase  | 
 | 119 | +	std.TestSetOrigSend(std.Coins{{"ugnot", 1000}}, nil)  | 
 | 120 | +	testBanker.RemoveCoin(std.GetOrigCaller(), "ugnot", 1000)  | 
 | 121 | + | 
 | 122 | +	tokenId, liquidity, amount0, amount1 := pos.Mint(  | 
 | 123 | +		gnotPath,       // token0 ( will be token1 )  | 
 | 124 | +		barPath,        // token1 ( will be token0 )  | 
 | 125 | +		uint16(100),    // fee  | 
 | 126 | +		int32(5932),    // tickLower  | 
 | 127 | +		int32(7932),    // tickUpper  | 
 | 128 | +		bigint(1000),   // amount0Desired  | 
 | 129 | +		bigint(999999), // amount1Desired  | 
 | 130 | +		0,              // amount0Min  | 
 | 131 | +		0,              // amount1Min  | 
 | 132 | +		MAX_TIMEOUT,    // deadline  | 
 | 133 | +	)  | 
 | 134 | +	std.TestSetOrigSend(std.Coins{}, nil)  | 
 | 135 | +	std.TestSkipHeights(1)  | 
 | 136 | + | 
 | 137 | +	shouldEQ(t, tokenId, 1)  | 
 | 138 | +	println("liquidity\t", liquidity)  | 
 | 139 | +	println("amount0(bar)\t", amount0)  | 
 | 140 | +	println("amount1(gnot)\t", amount1)  | 
 | 141 | +}  | 
 | 142 | + | 
 | 143 | +func TestPositionMintBarBaz(t *testing.T) {  | 
 | 144 | +	std.TestSetOrigCaller(lp01)  | 
 | 145 | + | 
 | 146 | +	tokenId, liquidity, amount0, amount1 := pos.Mint(  | 
 | 147 | +		barPath,        // token0  | 
 | 148 | +		bazPath,        // token1  | 
 | 149 | +		uint16(100),    // fee  | 
 | 150 | +		int32(5932),    // tickLower  | 
 | 151 | +		int32(7932),    // tickUpper  | 
 | 152 | +		bigint(1000),   // amount0Desired  | 
 | 153 | +		bigint(999999), // amount1Desired  | 
 | 154 | +		0,              // amount0Min  | 
 | 155 | +		0,              // amount1Min  | 
 | 156 | +		MAX_TIMEOUT,    // deadline  | 
 | 157 | +	)  | 
 | 158 | +	std.TestSkipHeights(1)  | 
 | 159 | + | 
 | 160 | +	shouldEQ(t, tokenId, 2)  | 
 | 161 | +	println("liquidity\t", liquidity)  | 
 | 162 | +	println("amount0(bar)\t", amount0)  | 
 | 163 | +	println("amount1(baz)\t", amount1)  | 
 | 164 | +}  | 
 | 165 | + | 
 | 166 | +func TestPositionMintBazFoo(t *testing.T) {  | 
 | 167 | +	std.TestSetOrigCaller(lp01)  | 
 | 168 | + | 
 | 169 | +	tokenId, liquidity, amount0, amount1 := pos.Mint(  | 
 | 170 | +		bazPath,        // token0  | 
 | 171 | +		fooPath,        // token1  | 
 | 172 | +		uint16(100),    // fee  | 
 | 173 | +		int32(15096),   // tickLower  | 
 | 174 | +		int32(17096),   // tickUpper  | 
 | 175 | +		bigint(1000),   // amount0Desired  | 
 | 176 | +		bigint(999999), // amount1Desired  | 
 | 177 | +		0,              // amount0Min  | 
 | 178 | +		0,              // amount1Min  | 
 | 179 | +		MAX_TIMEOUT,    // deadline  | 
 | 180 | +	)  | 
 | 181 | +	std.TestSkipHeights(1)  | 
 | 182 | + | 
 | 183 | +	shouldEQ(t, tokenId, 3)  | 
 | 184 | +	println("liquidity\t", liquidity)  | 
 | 185 | +	println("amount0(baz)\t", amount0)  | 
 | 186 | +	println("amount1(foo)\t", amount1)  | 
 | 187 | +}  | 
 | 188 | + | 
 | 189 | +func TestPositionMintGnsGnot(t *testing.T) {  | 
 | 190 | +	std.TestSetOrigCaller(lp01)  | 
 | 191 | + | 
 | 192 | +	// prepare ugnot  | 
 | 193 | +	testBanker := std.GetBanker(std.BankerTypeRealmIssue)  | 
 | 194 | +	testBanker.IssueCoin(std.GetOrigCaller(), "ugnot", 1000)  | 
 | 195 | + | 
 | 196 | +	// simulate transfer & decrase  | 
 | 197 | +	std.TestSetOrigSend(std.Coins{{"ugnot", 1000}}, nil)  | 
 | 198 | +	testBanker.RemoveCoin(std.GetOrigCaller(), "ugnot", 1000)  | 
 | 199 | + | 
 | 200 | +	tokenId, liquidity, amount0, amount1 := pos.Mint(  | 
 | 201 | +		gnsPath,      // token0  | 
 | 202 | +		gnotPath,     // token1  | 
 | 203 | +		uint16(100),  // fee  | 
 | 204 | +		int32(-1000), // tickLower  | 
 | 205 | +		int32(1000),  // tickUpper  | 
 | 206 | +		bigint(1000), // amount0Desired  | 
 | 207 | +		bigint(1000), // amount1Desired  | 
 | 208 | +		0,            // amount0Min  | 
 | 209 | +		0,            // amount1Min  | 
 | 210 | +		MAX_TIMEOUT,  // deadline  | 
 | 211 | +	)  | 
 | 212 | +	std.TestSetOrigSend(std.Coins{}, nil)  | 
 | 213 | +	std.TestSkipHeights(1)  | 
 | 214 | + | 
 | 215 | +	shouldEQ(t, tokenId, 4)  | 
 | 216 | +	println("liquidity\t", liquidity)  | 
 | 217 | +	println("amount0(gns)\t", amount0)  | 
 | 218 | +	println("amount1(gnot)\t", amount1)  | 
 | 219 | +}  | 
 | 220 | + | 
 | 221 | +func TestPositionMintGnsQux(t *testing.T) {  | 
 | 222 | +	std.TestSetOrigCaller(lp01)  | 
 | 223 | + | 
 | 224 | +	tokenId, liquidity, amount0, amount1 := pos.Mint(  | 
 | 225 | +		gnsPath,        // token0  | 
 | 226 | +		quxPath,        // token1  | 
 | 227 | +		uint16(100),    // fee  | 
 | 228 | +		int32(22028),   // tickLower  | 
 | 229 | +		int32(24028),   // tickUpper  | 
 | 230 | +		bigint(1000),   // amount0Desired  | 
 | 231 | +		bigint(999999), // amount1Desired  | 
 | 232 | +		0,              // amount0Min  | 
 | 233 | +		0,              // amount1Min  | 
 | 234 | +		MAX_TIMEOUT,    // deadline  | 
 | 235 | +	)  | 
 | 236 | +	std.TestSkipHeights(1)  | 
 | 237 | + | 
 | 238 | +	shouldEQ(t, tokenId, 5)  | 
 | 239 | +	println("liquidity\t", liquidity)  | 
 | 240 | +	println("amount0(gns)\t", amount0)  | 
 | 241 | +	println("amount1(qux)\t", amount1)  | 
 | 242 | +}  | 
 | 243 | + | 
 | 244 | +// TEST RATIOS  | 
 | 245 | +func TestRouterApiGetRatiosFromBase(t *testing.T) {  | 
 | 246 | +	jsonStr := gjson.Parse(rou.ApiGetRatiosFromBase())  | 
 | 247 | +	jsonArr := jsonStr.Get("response.data").Array()  | 
 | 248 | + | 
 | 249 | +	shouldEQ(t, jsonArr[0].String(), "{\"gnot\":79228162514264337593543950336}")             // 1  | 
 | 250 | +	shouldEQ(t, jsonArr[1].String(), "{\"gno.land/r/bar\":158427515811472657639193234591}")  // 1.9996363766  | 
 | 251 | +	shouldEQ(t, jsonArr[2].String(), "{\"gno.land/r/baz\":316829103406906364771139440526}")  // 3.998945493  | 
 | 252 | +	shouldEQ(t, jsonArr[3].String(), "{\"gno.land/r/foo\":1584116397429175401616934621999}") // 19.994359924  | 
 | 253 | +	shouldEQ(t, jsonArr[4].String(), "{\"gno.land/r/gns\":79228162514264337593543950334}")   // 1  | 
 | 254 | +	shouldEQ(t, jsonArr[5].String(), "{\"gno.land/r/qux\":792281450588003167884250659067}")  // 9.9999977968  | 
 | 255 | +}  | 
 | 256 | + | 
 | 257 | +/* UTILS */  | 
 | 258 | +func token0Balance(addr std.Address) bigint {  | 
 | 259 | +	return bigint(foo.BalanceOf(a2u(addr)))  | 
 | 260 | +}  | 
 | 261 | + | 
 | 262 | +func token1Balance(addr std.Address) bigint {  | 
 | 263 | +	return bigint(bar.BalanceOf(a2u(addr)))  | 
 | 264 | +}  | 
 | 265 | + | 
 | 266 | +func a2u(addr std.Address) users.AddressOrName {  | 
 | 267 | +	return users.AddressOrName(addr)  | 
 | 268 | +}  | 
 | 269 | + | 
 | 270 | +func tid(tokenId interface{}) grc721.TokenID {  | 
 | 271 | +	if tokenId == nil {  | 
 | 272 | +		panic("[TC - POSITION] test_helper.gno__tid() || tokenId is nil")  | 
 | 273 | +	}  | 
 | 274 | + | 
 | 275 | +	switch tokenId.(type) {  | 
 | 276 | +	case bigint:  | 
 | 277 | +		return grc721.TokenID(string(tokenId.(bigint)))  | 
 | 278 | +	case string:  | 
 | 279 | +		return grc721.TokenID(tokenId.(string))  | 
 | 280 | +	case int:  | 
 | 281 | +		return grc721.TokenID(strconv.Itoa(tokenId.(int)))  | 
 | 282 | +	case uint64:  | 
 | 283 | +		return grc721.TokenID(strconv.Itoa(int(tokenId.(uint64))))  | 
 | 284 | +	case grc721.TokenID:  | 
 | 285 | +		return tokenId.(grc721.TokenID)  | 
 | 286 | +	default:  | 
 | 287 | +		panic("[TC - STAKER] utils.gno__tid() || unsupported tokenId type")  | 
 | 288 | +	}  | 
 | 289 | +}  | 
 | 290 | + | 
 | 291 | +func BalanceOf(token *grc20.AdminToken, addr std.Address) bigint {  | 
 | 292 | +	balance, err := token.BalanceOf(addr)  | 
 | 293 | +	if err != nil {  | 
 | 294 | +		panic(err)  | 
 | 295 | +	}  | 
 | 296 | +	return bigint(balance)  | 
 | 297 | +}  | 
 | 298 | + | 
 | 299 | +/* HELPERS */  | 
 | 300 | +func shouldEQ(t *testing.T, got, expected interface{}) {  | 
 | 301 | +	if got != expected {  | 
 | 302 | +		t.Errorf("got %v, expected %v", got, expected)  | 
 | 303 | +	}  | 
 | 304 | +}  | 
 | 305 | + | 
 | 306 | +func shouldNEQ(t *testing.T, got, expected interface{}) {  | 
 | 307 | +	if got == expected {  | 
 | 308 | +		t.Errorf("got %v, expected %v", got, expected)  | 
 | 309 | +	}  | 
 | 310 | +}  | 
 | 311 | + | 
 | 312 | +func shouldGT(t *testing.T, l, r interface{}) {  | 
 | 313 | +	if l <= r {  | 
 | 314 | +		t.Errorf("expected %v > %v", l, r)  | 
 | 315 | +	}  | 
 | 316 | +}  | 
 | 317 | + | 
 | 318 | +func shouldLT(t *testing.T, l, r interface{}) {  | 
 | 319 | +	if l >= r {  | 
 | 320 | +		t.Errorf("expected %v < %v", l, r)  | 
 | 321 | +	}  | 
 | 322 | +}  | 
 | 323 | + | 
 | 324 | +func shouldPanicWithMsg(t *testing.T, f func(), msg string) {  | 
 | 325 | +	defer func() {  | 
 | 326 | +		if r := recover(); r == nil {  | 
 | 327 | +			t.Errorf("The code did not panic")  | 
 | 328 | +		} else {  | 
 | 329 | +			if r != msg {  | 
 | 330 | +				t.Errorf("excepted panic(%v), got(%v)", msg, r)  | 
 | 331 | +			}  | 
 | 332 | +		}  | 
 | 333 | +	}()  | 
 | 334 | +	f()  | 
 | 335 | +}  | 
 | 336 | + | 
 | 337 | +func ugnotBalance(addr std.Address) uint64 {  | 
 | 338 | +	testBanker := std.GetBanker(std.BankerTypeRealmIssue)  | 
 | 339 | +	return uint64(testBanker.GetCoins(addr)[0].Amount)  | 
 | 340 | +}  | 
0 commit comments