diff --git a/_deploy/r/demo/gnoswap/consts/consts.gno b/_deploy/r/demo/gnoswap/consts/consts.gno index e60aad64..61e7ebb2 100644 --- a/_deploy/r/demo/gnoswap/consts/consts.gno +++ b/_deploy/r/demo/gnoswap/consts/consts.gno @@ -50,6 +50,9 @@ const ( GNFT_PATH string = "gno.land/r/demo/gnft" GNFT_ADDR std.Address = std.DerivePkgAddr(GNFT_PATH) + + WUGNOT_PATH string = "gno.land/r/demo/wugnot" + WUGNOT_ADDR std.Address = std.DerivePkgAddr(WUGNOT_PATH) ) // NUMBER diff --git a/gov/z_proposal_filetest.gno b/gov/z_proposal_filetest.gno deleted file mode 100644 index 58b97991..00000000 --- a/gov/z_proposal_filetest.gno +++ /dev/null @@ -1,97 +0,0 @@ -package main - -import ( - "fmt" - "time" - - "gno.land/r/demo/gov" -) - -func main() { - TestSubmitProposal() - - // CANNOT TEST THE FOLLOWING DUE TO THE LACK OF `process` FUNCTION in the integration filetest - // TestSubmitProposalFailedDeposit() - // TestSubmitProposalRejected(nil) - // TestSubmitProposalCommunityPoolSpend(nil) - // TestSubmitProposalMint(nil) - // TestProposalParameterChange(nil) - // TestProposalTally(nil) -} - -func TestSubmitProposal() { - gov.Init() - - id := gov.SubmitProposalText( - "title", // title - "summary", // summary - "metadata", // metadata - 0, // initial deposit - ) - - now := uint64(time.Now().Unix()) - - if id != 1 { - panic("proposal id should be 1") - } - - proposal := gov.GetProposalById(id) - - if proposal.Title != "title" { - panic("proposal title should be title") - } - - if proposal.Summary != "summary" { - panic("proposal summary should be summary") - } - - if proposal.Metadata != "metadata" { - panic("proposal metadata should be metadata") - } - - if proposal.ProposalStatus != gov.ProposalStatusDepositPeriod { - panic("proposal status should be deposit period") - } - - if proposal.SubmitTime != now { - panic("proposal submit time should be now") - } - - // 86400 == getDepositPeriod() - if proposal.DepositEndTime != now+86400 { - panic(fmt.Sprintf("proposal deposit end time should be now + deposit period, %d, %d", proposal.DepositEndTime, now+86400)) - } - - if proposal.VotingEndTime != 0 { - panic("proposal voting end time should be 0") - } - - if proposal.TotalDeposit != 0 { - panic("proposal total deposits should be 0") - } - - // 10_000_000 == getDepositMinimum() - // force advance to voting period - proposal.TotalDeposit = 10_000_000 + 1 - - /* - CAN NOT `process` in the integration filetest - - // 86400 == getDepositPeriod() - if proposal.process(now + 86400 + 1) { - panic("proposal process should not halt") - } - - // force advance to voting passed - proposal.YesVotes = 100 - proposal.NoVotes = 0 - - // 259200 == getVotePeriod() - if proposal.process(now + 86400 + 1 + 259200 + 1) { - panic("proposal process should not halt") - } - */ -} - -// OUTPUT: -// diff --git a/position/_TEST_/_TEST_position_ZZ_increase_decrease_native_test.gno b/position/_TEST_/_TEST_position_ZZ_increase_decrease_native_test.gno new file mode 100644 index 00000000..c9e3749e --- /dev/null +++ b/position/_TEST_/_TEST_position_ZZ_increase_decrease_native_test.gno @@ -0,0 +1,227 @@ +package position + +import ( + "std" + "testing" + + "gno.land/r/demo/gnoswap/common" + "gno.land/r/demo/gnoswap/consts" + + "gno.land/r/demo/gns" + "gno.land/r/demo/wugnot" + + pl "gno.land/r/demo/pool" +) + +// 1. Create Pool +func TestPoolInitCreatePool(t *testing.T) { + std.TestSetPrevAddr(gsa) + + gns.Approve(a2u(consts.POOL_ADDR), consts.POOL_CREATION_FEE) + pl.CreatePool(consts.GNS_PATH, consts.GNOT, fee500, common.TickMathGetSqrtRatioAtTick(10000).ToString()) // x2.71814592682522526700950038502924144268035888671875 + // event: {GNOSWAP gno.land/r/demo/pool CreatePool [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_poolPath gno.land/r/demo/gns:gno.land/r/demo/wugnot:500}]} +} + +func TestMintPosition(t *testing.T) { + std.TestSetPrevAddr(gsa) + + gns.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) + wugnot.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) + + wugnot.Approve(a2u(consts.POSITION_ADDR), consts.UINT64_MAX) // WRAP + + // prepare 50000005ugnot (5 for refund test) + testBanker := std.GetBanker(std.BankerTypeRealmIssue) + testBanker.IssueCoin(gsa, "ugnot", 50000005) + + // simulate transfer & decrase + gsaNativeBalance := ugnotBalanceOf(gsa) + shouldEQ(t, gsaNativeBalance, 50000005) + + std.TestSetOrigSend(std.Coins{{"ugnot", 50000005}}, nil) + testBanker.RemoveCoin(std.GetOrigCaller(), "ugnot", -50000005) + + gsaNativeBalance = ugnotBalanceOf(gsa) + shouldEQ(t, gsaNativeBalance, 0) + + gsaOldWugnotBalance := wugnot.BalanceOf(a2u(gsa)) + shouldEQ(t, gsaOldWugnotBalance, 0) + + tokenId, liquidity, amount0, amount1 := Mint( + consts.GNS_PATH, + consts.GNOT, + fee500, + 8000, + 12000, + "50000000", + "50000000", + "0", + "0", + max_timeout, + gsa.String(), + ) + // event: {GNOSWAP gno.land/r/demo/position Mint [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_poolPath gno.land/r/demo/gns:gno.land/r/demo/wugnot:500} {p_tickLower 8000} {p_tickUpper 12000} {tokenId 1} {liquidity 318704392} {amount0 18394892} {amount1 50000000}]} + + shouldEQ(t, tokenId, 1) + shouldEQ(t, getNextId(), 2) + shouldEQ(t, amount0, "18394892") + shouldEQ(t, amount1, "50000000") + + position := positions[tokenId] + shouldEQ(t, position.poolKey, "gno.land/r/demo/gns:gno.land/r/demo/wugnot:500") + + // SPEND ALL WUGNOT + newOldWugnotBalance := wugnot.BalanceOf(a2u(gsa)) + shouldEQ(t, gsaOldWugnotBalance, newOldWugnotBalance) + + gsaNativeBalance = ugnotBalanceOf(gsa) + shouldEQ(t, gsaNativeBalance, 5) + // 1. 50000005 ugnot sent + // 2. 50000005 ugnot wrapped to wugnot + // 3. 50000000 wugnot spent to mint (amount1) + // 4. refund 50000005 - 50000000 = 5 + +} + +func TestIncreaseLiquidity(t *testing.T) { + std.TestSetPrevAddr(gsa) + + gns.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) + wugnot.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) + + wugnot.Approve(a2u(consts.POSITION_ADDR), consts.UINT64_MAX) // WRAP + + pool := getPoolFromLpTokenId(uint64(1)) + oldLiquidity := pool.PoolGetLiquidity() + + // prepare 10000005ugnot (5 for refund test) + testBanker := std.GetBanker(std.BankerTypeRealmIssue) + testBanker.IssueCoin(gsa, "ugnot", 10000005) + + // simulate transfer & decrase + gsaNativeBalance := ugnotBalanceOf(gsa) + shouldEQ(t, gsaNativeBalance, 10000010) + + std.TestSetOrigSend(std.Coins{{"ugnot", 10000005}}, nil) + testBanker.RemoveCoin(std.GetOrigCaller(), "ugnot", -10000005) + + gsaNativeBalance = ugnotBalanceOf(gsa) + shouldEQ(t, gsaNativeBalance, 5) + + gsaOldWugnotBalance := wugnot.BalanceOf(a2u(gsa)) + shouldEQ(t, gsaOldWugnotBalance, 0) + + _, _, m0, m1, _ := IncreaseLiquidity( // tokenId, liq, a0, a1, poolPath + uint64(1), // tokenId + "10000000", // amount0Desired + "10000000", // amount1Desired + "0", // amount0Min + "0", // amount1Min + max_timeout, // deadline + ) + // event: {GNOSWAP gno.land/r/demo/position IncreaseLiquidity [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_tokenId 1} {poolPath gno.land/r/demo/gns:gno.land/r/demo/wugnot:500} {liquidity 63740878} {amount0 3678979} {amount1 10000000}]} + shouldEQ(t, m0, "3678979") + shouldEQ(t, m1, "10000000") + + newLiquidity := pool.PoolGetLiquidity() + + shouldEQ(t, newLiquidity.Gt(oldLiquidity), true) + + // SPEND ALL WUGNOT + newOldWugnotBalance := wugnot.BalanceOf(a2u(gsa)) + shouldEQ(t, gsaOldWugnotBalance, newOldWugnotBalance) + + gsaNativeBalance = ugnotBalanceOf(gsa) + shouldEQ(t, gsaNativeBalance, 10) + // 1. 10000005 ugnot sent + // 2. 10000005 ugnot wrapped to wugnot + // 3. 10000000 wugnot spent to mint (amount1) + // 4. refund 10000005 - 10000000 = 5 + // 5. user already had 5 ugnot = 5 + 5 +} + +func TestDecreaseLiquidityWrapped(t *testing.T) { + std.TestSetPrevRealm("") + std.TestSetOrigCaller(gsa) + + oldLiquidity := getPoolFromLpTokenId(uint64(1)).PoolGetLiquidity() + + userWugnotBalance := wugnot.BalanceOf(a2u(gsa)) + shouldEQ(t, userWugnotBalance, 0) + + userUgnotBalance := ugnotBalanceOf(gsa) + shouldEQ(t, userUgnotBalance, 10) + + _, _, _, _, a0, a1, _ := DecreaseLiquidity( // tokenId, liquidity, fee0, fee1, amount0, amount1, poolPath + uint64(1), // tokenId + 20, // liquidityRatio + "0", // amount0Min + "0", // amount1Min + max_timeout, // deadline + false, // unwrapResult + ) + // --- event: {GNOSWAP gno.land/r/demo/pool HandleWithdrawalFee [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm gno.land/r/demo/position} {p_tokenId 1} {p_token0Path gno.land/r/demo/gns} {p_token1Path gno.land/r/demo/wugnot} {fee0Amount 0} {fee1Amount 0}]} + // --- event: {GNOSWAP gno.land/r/demo/position CollectFee [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_tokenId 1} {fee0 0} {fee1 0} {poolPath gno.land/r/demo/gns:gno.land/r/demo/wugnot:500}]} + // --- event: {GNOSWAP gno.land/r/demo/position DecreaseLiquidity [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_tokenId 1} {p_liquidityRatio 20} {poolPath gno.land/r/demo/gns:gno.land/r/demo/wugnot:500} {liquidity 76489054} {fee0 0} {fee1 0} {amount0 4414773} {amount1 11999999}]} + + userWugnotBalance = wugnot.BalanceOf(a2u(gsa)) // wrapped result, so wunogt increased + shouldEQ(t, userWugnotBalance, 11999999) + + userUgnotBalance = ugnotBalanceOf(gsa) // wrapped result, so ugnot didn't change + shouldEQ(t, userUgnotBalance, 10) + + newLiquidity := getPoolFromLpTokenId(uint64(1)).PoolGetLiquidity() + shouldEQ(t, true, newLiquidity.Lt(oldLiquidity)) + + // check fee left + tokenId, fee0, fee1, poolPath := CollectFee(1) + // --- event: {GNOSWAP gno.land/r/demo/pool HandleWithdrawalFee [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm gno.land/r/demo/position} {p_tokenId 1} {p_token0Path gno.land/r/demo/gns} {p_token1Path gno.land/r/demo/wugnot} {fee0Amount 0} {fee1Amount 0}]} + // --- event: {GNOSWAP gno.land/r/demo/position CollectFee [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_tokenId 1} {fee0 0} {fee1 0} {poolPath gno.land/r/demo/gns:gno.land/r/demo/wugnot:500}]} + + shouldEQ(t, tokenId, uint64(1)) + shouldEQ(t, fee0, "0") + shouldEQ(t, fee1, "0") +} + +func TestDecreaseLiquidityUnwrapped(t *testing.T) { + std.TestSetPrevRealm("") + std.TestSetOrigCaller(gsa) + + oldLiquidity := getPoolFromLpTokenId(uint64(1)).PoolGetLiquidity() + + userWugnotBalance := wugnot.BalanceOf(a2u(gsa)) + shouldEQ(t, userWugnotBalance, 11999999) + + userUgnotBalance := ugnotBalanceOf(gsa) + shouldEQ(t, userUgnotBalance, 10) + + _, _, _, _, a0, a1, _ := DecreaseLiquidity( // tokenId, liquidity, fee0, fee1, amount0, amount1, poolPath + uint64(1), // tokenId + 50, // liquidityRatio + "0", // amount0Min + "0", // amount1Min + max_timeout, // deadline + true, // unwrapResult + ) + // --- event: {GNOSWAP gno.land/r/demo/pool HandleWithdrawalFee [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm gno.land/r/demo/position} {p_tokenId 1} {p_token0Path gno.land/r/demo/gns} {p_token1Path gno.land/r/demo/wugnot} {fee0Amount 0} {fee1Amount 0}]} + // --- event: {GNOSWAP gno.land/r/demo/position CollectFee [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_tokenId 1} {fee0 0} {fee1 0} {poolPath gno.land/r/demo/gns:gno.land/r/demo/wugnot:500}]} + // --- event: {GNOSWAP gno.land/r/demo/position DecreaseLiquidity [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_tokenId 1} {p_liquidityRatio 20} {poolPath gno.land/r/demo/gns:gno.land/r/demo/wugnot:500} {liquidity 76489054} {fee0 0} {fee1 0} {amount0 4414773} {amount1 11999999}]} + + userWugnotBalance = wugnot.BalanceOf(a2u(gsa)) // unwrapped result, so wugnot didn't change + shouldEQ(t, userWugnotBalance, 11999999) + + userUgnotBalance = ugnotBalanceOf(gsa) // unwrapped result, so ugnot decreased + shouldEQ(t, userUgnotBalance, 24000009) + + newLiquidity := getPoolFromLpTokenId(uint64(1)).PoolGetLiquidity() + shouldEQ(t, true, newLiquidity.Lt(oldLiquidity)) + + // check fee left + tokenId, fee0, fee1, poolPath := CollectFee(1) + // --- event: {GNOSWAP gno.land/r/demo/pool HandleWithdrawalFee [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm gno.land/r/demo/position} {p_tokenId 1} {p_token0Path gno.land/r/demo/gns} {p_token1Path gno.land/r/demo/wugnot} {fee0Amount 0} {fee1Amount 0}]} + // --- event: {GNOSWAP gno.land/r/demo/position CollectFee [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_tokenId 1} {fee0 0} {fee1 0} {poolPath gno.land/r/demo/gns:gno.land/r/demo/wugnot:500}]} + + shouldEQ(t, tokenId, uint64(1)) + shouldEQ(t, fee0, "0") + shouldEQ(t, fee1, "0") +} diff --git a/position/_TEST_/_TEST_position_ZZ_test.gnoBB b/position/_TEST_/_TEST_position_ZZ_test.gnoBB new file mode 100644 index 00000000..d4020153 --- /dev/null +++ b/position/_TEST_/_TEST_position_ZZ_test.gnoBB @@ -0,0 +1,131 @@ +package position + +import ( + "std" + "testing" + + "gno.land/r/demo/gnoswap/common" + "gno.land/r/demo/gnoswap/consts" + + i256 "gno.land/p/demo/gnoswap/int256" + + pl "gno.land/r/demo/pool" + + "gno.land/r/demo/bar" + "gno.land/r/demo/foo" + "gno.land/r/demo/gns" +) + +func TestPoolInitCreatePool(t *testing.T) { + std.TestSetPrevAddr(gsa) + + gns.Approve(a2u(consts.POOL_ADDR), consts.POOL_CREATION_FEE) + pl.CreatePool(barPath, fooPath, fee500, "130621891405341611593710811006") // tick = 10000 + // event: {GNOSWAP gno.land/r/demo/pool CreatePool [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_poolPath gno.land/r/demo/bar:gno.land/r/demo/foo:500}]} + + println("POOL_BAR:", bar.BalanceOf(a2u(consts.POOL_ADDR))) // 0 + println("POOL_FOO:", foo.BalanceOf(a2u(consts.POOL_ADDR))) // 0 +} + +func TestMintPosition01InRange(t *testing.T) { + std.TestSetPrevAddr(gsa) + bar.Approve(a2u(consts.POOL_ADDR), 18394892) + foo.Approve(a2u(consts.POOL_ADDR), 50000000) + + tokenId, liquidity, amount0, amount1 := Mint( + barPath, + fooPath, + fee500, + 8000, + 12000, + "50000000", + "50000000", + "0", + "0", + max_timeout, + gsa.String(), + ) + // event: {GNOSWAP gno.land/r/demo/position Mint [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_poolPath gno.land/r/demo/bar:gno.land/r/demo/foo:500} {p_tickLower 8000} {p_tickUpper 12000} {tokenId 1} {liquidity 318704392} {amount0 18394892} {amount1 50000000}]} + + shouldEQ(t, tokenId, 1) + shouldEQ(t, getNextId(), 2) + shouldEQ(t, amount0, "18394892") + shouldEQ(t, amount1, "50000000") + + println("POOL_BAR:", bar.BalanceOf(a2u(consts.POOL_ADDR))) // 18394892 + println("POOL_FOO:", foo.BalanceOf(a2u(consts.POOL_ADDR))) // 50000000 + + position := positions[tokenId] + pool := pl.GetPoolFromPoolPath(position.poolKey) + currentX96 := pool.PoolGetSlot0SqrtPriceX96() + lowerX96 := common.TickMathGetSqrtRatioAtTick(position.tickLower) + upperX96 := common.TickMathGetSqrtRatioAtTick(position.tickUpper) + token0Balance, token1Balance := common.GetAmountsForLiquidity( + currentX96, + lowerX96, + upperX96, + i256.FromUint256(position.liquidity), + ) + println("POSITION_BAR:", token0Balance) // 18394892 + println("POSITION_FOO:", token1Balance) // 50000000 +} + +func TestSwap(t *testing.T) { + std.TestSetPrevAddr(gsa) + bar.Approve(a2u(consts.POOL_ADDR), 1234567) + + std.TestSetPrevRealm(consts.ROUTER_PATH) + std.TestSetOrigCaller(gsa) + amount0, amount1 := pl.Swap( + barPath, + fooPath, + fee500, + gsa.String(), + true, + "1234567", + consts.MIN_PRICE, + gsa.String(), + ) + // event: {GNOSWAP gno.land/r/demo/pool Swap [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm gno.land/r/demo/router} {p_poolPath gno.land/r/demo/bar:gno.land/r/demo/foo:500} {p_zeroForOne true} {p_amountSpecified 1234567} {p_sqrtPriceLimitX96 4295128740} {p_payer g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {p_recipient g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {amount0 1234567} {amount1 -3332779} {protocol_fee0 0} {protocol_fee1 0}]} + + shouldEQ(t, amount0, "1234567") + shouldEQ(t, amount1, "-3332779") + + // check balances + println("POOL_BAR:", bar.BalanceOf(a2u(consts.POOL_ADDR))) // 19629459 || 18394892 + 1234567 + println("POOL_FOO:", foo.BalanceOf(a2u(consts.POOL_ADDR))) // 46667221 || 50000000 - 3332779 + + position := positions[1] + pool := pl.GetPoolFromPoolPath(position.poolKey) + currentX96 := pool.PoolGetSlot0SqrtPriceX96() + lowerX96 := common.TickMathGetSqrtRatioAtTick(position.tickLower) + upperX96 := common.TickMathGetSqrtRatioAtTick(position.tickUpper) + token0Balance, token1Balance := common.GetAmountsForLiquidity( + currentX96, + lowerX96, + upperX96, + i256.FromUint256(position.liquidity), + ) + println("POSITION_BAR:", token0Balance) // 19628841 || POOL(19629459) - POS(19628841) = 618 + println("POSITION_FOO:", token1Balance) // 46667221 || SAME WITH POOL_FOO + + fee0, fee1 := unclaimedFee(1) + println("POSITION_FEE_BAR:", fee0.ToString()) // 617 + println("POSITION_FEE_FOO:", fee1.ToString()) // 0 + +} + +func TestCollectFeeAfterSwap(t *testing.T) { + std.TestSetPrevAddr(gsa) + foo.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) // COLLECT_FEE + bar.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) // COLLECT_FEE + + tokenId, fee0, fee1, poolPath := CollectFee(1) + // event: {GNOSWAP gno.land/r/demo/pool HandleWithdrawalFee [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm gno.land/r/demo/position} {p_tokenId 1} {p_token0Path gno.land/r/demo/bar} {p_token1Path gno.land/r/demo/foo} {fee0Amount 6} {fee1Amount 0}]} + // event: {GNOSWAP gno.land/r/demo/position CollectFee [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_tokenId 1} {fee0 611} {fee1 0} {poolPath gno.land/r/demo/bar:gno.land/r/demo/foo:500}]} + + shouldEQ(t, tokenId, uint64(1)) + shouldEQ(t, fee0, "611") // this is input token + shouldEQ(t, fee1, "0") // this it output token + shouldEQ(t, poolPath, "gno.land/r/demo/bar:gno.land/r/demo/foo:500") +} diff --git a/position/position.gno b/position/position.gno index e1040845..edcba841 100644 --- a/position/position.gno +++ b/position/position.gno @@ -217,8 +217,31 @@ func IncreaseLiquidity( deadline: deadline, } + // wrap if target pool has wugnot + position := positions[tokenId] + pToken0, pToken1, _ := poolKeyDivide(position.poolKey) + + isToken0Wugnot := pToken0 == consts.WRAPPED_WUGNOT + isToken1Wugnot := pToken1 == consts.WRAPPED_WUGNOT + + userOldWugnotBalance := wugnot.BalanceOf(a2u(std.GetOrigCaller())) // before wrap, user's origin wugnot balance + if isToken0Wugnot || isToken1Wugnot { + sent := std.GetOrigSend() + ugnotSent := uint64(sent.AmountOf("ugnot")) + wrap(ugnotSent) + } + + // INCREASE tokneId, liquidity, amount0, amount1, poolPath := increaseLiquidity(increaseLiquidityParams) + // unwrap left + if isToken0Wugnot || isToken1Wugnot { + userNewWugnotBalance := wugnot.BalanceOf(a2u(std.GetOrigCaller())) + + leftOver := userNewWugnotBalance - userOldWugnotBalance + unwrap(leftOver) + } + std.Emit( "GNOSWAP", "m_origCaller", origCaller(), @@ -542,8 +565,8 @@ func CollectFee(tokenId uint64) (uint64, string, string, string) { // tokenId, t "m_origCaller", origCaller(), "m_prevRealm", prevRealm(), "p_tokenId", uint64ToStr(tokenId), - "fee0", tokensOwed0.ToString(), - "fee1", tokensOwed1.ToString(), + "fee0", withoutFee0, + "fee1", withoutFee1, "poolPath", position.poolKey, ) diff --git a/router/_TEST_/_TEST_0_INIT_VARS_HELPERS_test.gno b/router/_TEST_/_TEST_0_INIT_VARS_HELPERS_test.gno index a7402d4c..ee72a056 100644 --- a/router/_TEST_/_TEST_0_INIT_VARS_HELPERS_test.gno +++ b/router/_TEST_/_TEST_0_INIT_VARS_HELPERS_test.gno @@ -60,3 +60,14 @@ func shouldPanic(t *testing.T, f func()) { }() f() } + +func ugnotBalanceOf(addr std.Address) uint64 { + testBanker := std.GetBanker(std.BankerTypeRealmIssue) + + coins := testBanker.GetCoins(addr) + if len(coins) == 0 { + return 0 + } + + return uint64(testBanker.GetCoins(addr)[0].Amount) +} diff --git a/router/_TEST_/_TEST_router_swap_route_1route_1hop_native_in_out_test.gnoA b/router/_TEST_/_TEST_router_swap_route_1route_1hop_native_in_out_test.gno similarity index 64% rename from router/_TEST_/_TEST_router_swap_route_1route_1hop_native_in_out_test.gnoA rename to router/_TEST_/_TEST_router_swap_route_1route_1hop_native_in_out_test.gno index 43b998af..a5407e88 100644 --- a/router/_TEST_/_TEST_router_swap_route_1route_1hop_native_in_out_test.gnoA +++ b/router/_TEST_/_TEST_router_swap_route_1route_1hop_native_in_out_test.gno @@ -18,6 +18,14 @@ import ( "gno.land/r/demo/wugnot" ) +/* DEBUG +func TestEnables(t *testing.T) { + // testBanker := std.GetBanker(std.BankerTypeRealmIssue) + // testBanker.IssueCoin(consts.POSITION_ADDR, "ugnot", 1) + // testBanker.IssueCoin(consts.WUGNOT_ADDR, "ugnot", 1) +} +*/ + func TestCreatePool(t *testing.T) { std.TestSetPrevAddr(gsa) @@ -29,7 +37,7 @@ func TestCreatePool(t *testing.T) { pl.CreatePool(bazPath, quxPath, fee500, "130621891405341611593710811006") // tick = 10_000, ratio = 2.71814592682522526700950038502924144268035888671875 // event: {GNOSWAP gno.land/r/demo/pool CreatePool [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_poolPath gno.land/r/demo/baz:gno.land/r/demo/qux:500}]} - pl.CreatePool(quxPath, consts.WRAPPED_WUGNOT, fee500, "130621891405341611593710811006") // tick = 10_000, ratio = 2.71814592682522526700950038502924144268035888671875 + pl.CreatePool(quxPath, consts.GNOT, fee500, "130621891405341611593710811006") // tick = 10_000, ratio = 2.71814592682522526700950038502924144268035888671875 // event: {GNOSWAP gno.land/r/demo/pool CreatePool [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_poolPath gno.land/r/demo/qux:gno.land/r/demo/wugnot:500}]} // 1 bar ≈ 19.683 gnot @@ -81,16 +89,16 @@ func TestPositionMintQuxGnot(t *testing.T) { std.TestIssueCoins(gsa, std.Coins{{"ugnot", 1000009}}) std.TestSetOrigSend(std.Coins{{"ugnot", 1000009}}, nil) testBanker := std.GetBanker(std.BankerTypeRealmIssue) - testBanker.RemoveCoin(std.GetOrigCaller(), "ugnot", 1000009) + testBanker.RemoveCoin(std.GetOrigCaller(), "ugnot", -1000009) - // Deposit(wrap) - std.TestSetPrevAddr(gsa) - wugnot.Deposit() + // MOCK POSITION TO HAVE UGNOT + testBanker.IssueCoin(consts.POSITION_ADDR, "ugnot", 1000009) qux.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) wugnot.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) + wugnot.Approve(a2u(consts.POSITION_ADDR), consts.UINT64_MAX) // wrap unwrap - tokenId, liquidity, amount0, amount1 := pn.Mint(quxPath, consts.WRAPPED_WUGNOT, fee500, int32(9000), int32(11000), "100000", "100000", "0", "0", max_timeout, gsa.String()) + tokenId, liquidity, amount0, amount1 := pn.Mint(quxPath, consts.GNOT, fee500, int32(9000), int32(11000), "100000", "100000", "0", "0", max_timeout, gsa.String()) // event: {GNOSWAP gno.land/r/demo/position Mint [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_poolPath gno.land/r/demo/qux:gno.land/r/demo/wugnot:500} {p_tickLower 9000} {p_tickUpper 11000} {tokenId 3} {liquidity 1243732} {amount0 36790} {amount1 100000}]} shouldEQ(t, tokenId, uint64(3)) @@ -98,58 +106,104 @@ func TestPositionMintQuxGnot(t *testing.T) { shouldEQ(t, amount1, "100000") } +// DRY BUY NATIVE func TestDrySwapRouteBarGnotExactIn(t *testing.T) { std.TestSetOrigCaller(gsa) dryResult := DrySwapRoute( - barPath, // inputToken - consts.WRAPPED_WUGNOT, // outputToken - "1000", // amountSpecified - "EXACT_IN", // swapType + barPath, // inputToken + consts.GNOT, // outputToken + "1000", // amountSpecified + "EXACT_IN", // swapType "gno.land/r/demo/bar:gno.land/r/demo/baz:500*POOL*gno.land/r/demo/baz:gno.land/r/demo/qux:500*POOL*gno.land/r/demo/qux:gno.land/r/demo/wugnot:500", // strRouteArr "100", // quoteArr ) shouldEQ(t, dryResult, "19740") } -func TestDrySwapRouteBarGnotExactOut(t *testing.T) { - std.TestSetOrigCaller(gsa) +// BUY NATIVE +func TestSwapRouteBarGnotExactIn(t *testing.T) { + std.TestSetPrevAddr(gsa) - dryResult := DrySwapRoute( - barPath, // inputToken - consts.WRAPPED_WUGNOT, // outputToken - "20000", // amountSpecified - "EXACT_OUT", // swapType + bar.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) + wugnot.Approve(a2u(consts.ROUTER_ADDR), consts.UINT64_MAX) // for output + wugnot.Approve(a2u(consts.ROUTER_ADDR), consts.UINT64_MAX) // for unwrap + + oldWugnot := wugnot.BalanceOf(a2u(gsa)) + shouldEQ(t, oldWugnot, 0) + + oldUgnot := ugnotBalanceOf(gsa) + shouldEQ(t, oldUgnot, 900009) + + std.TestSetOrigCaller(gsa) + amountIn, amountOut := SwapRoute( + barPath, // inputToken + consts.GNOT, // outputToken + "1000", // amountSpecified + "EXACT_IN", // swapType "gno.land/r/demo/bar:gno.land/r/demo/baz:500*POOL*gno.land/r/demo/baz:gno.land/r/demo/qux:500*POOL*gno.land/r/demo/qux:gno.land/r/demo/wugnot:500", // strRouteArr "100", // quoteArr + "0", // tokenAmountLimit ) - shouldEQ(t, dryResult, "1014") + shouldEQ(t, amountIn, "1000") + shouldEQ(t, amountOut, "-19711") + + newWugnot := wugnot.BalanceOf(a2u(gsa)) + shouldEQ(t, newWugnot, 0) + + newUgnot := ugnotBalanceOf(gsa) + shouldEQ(t, newUgnot, 919720) // 900009 + 19711 } +// DRY SELL NATIVE func TestDrySwapRouteGnotBarExactIn(t *testing.T) { std.TestSetOrigCaller(gsa) dryResult := DrySwapRoute( - consts.WRAPPED_WUGNOT, // intputToken - barPath, // outputToken - "5000", // amountSpecified - "EXACT_IN", // swapType + consts.GNOT, // intputToken + barPath, // outputToken + "5000", // amountSpecified + "EXACT_IN", // swapType "gno.land/r/demo/wugnot:gno.land/r/demo/qux:500*POOL*gno.land/r/demo/qux:gno.land/r/demo/baz:500*POOL*gno.land/r/demo/baz:gno.land/r/demo/bar:500", // strRouteArr "100", // quoteArr ) - shouldEQ(t, dryResult, "247") + shouldEQ(t, dryResult, "254") } -func TestDrySwapRouteGnotBarExactOut(t *testing.T) { +// SELL NATIVE +func TestSwapRouteGnotBarExactIn(t *testing.T) { std.TestSetOrigCaller(gsa) - dryResult := DrySwapRoute( - consts.WRAPPED_WUGNOT, // intputToken - barPath, // outputToken - "100", // amountSpecified - "EXACT_OUT", // swapType + wugnot.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) // for input + bar.Approve(a2u(consts.ROUTER_ADDR), consts.UINT64_MAX) // for output + + oldWugnot := wugnot.BalanceOf(a2u(gsa)) + shouldEQ(t, oldWugnot, 0) + + oldUgnot := ugnotBalanceOf(gsa) + shouldEQ(t, oldUgnot, 919720) + + // send + std.TestSetOrigSend(std.Coins{{"ugnot", 5000}}, nil) + testBanker := std.GetBanker(std.BankerTypeRealmIssue) + testBanker.RemoveCoin(std.GetOrigCaller(), "ugnot", -5000) + + amountIn, amountOut := SwapRoute( + consts.GNOT, // intputToken + barPath, // outputToken + "5000", // amountSpecified + "EXACT_IN", // swapType "gno.land/r/demo/wugnot:gno.land/r/demo/qux:500*POOL*gno.land/r/demo/qux:gno.land/r/demo/baz:500*POOL*gno.land/r/demo/baz:gno.land/r/demo/bar:500", // strRouteArr "100", // quoteArr + "0", ) - shouldEQ(t, dryResult, "2027") + shouldEQ(t, amountIn, "5000") + shouldEQ(t, amountOut, "-254") + + newWugnot := wugnot.BalanceOf(a2u(gsa)) + shouldEQ(t, newWugnot, 0) + + newUgnot := ugnotBalanceOf(gsa) + shouldEQ(t, newUgnot, 915720) + } diff --git a/staker/_TEST_/_TEST_0_INIT_VARIABLE_AND_HELPER_test.gno b/staker/_TEST_/_TEST_0_INIT_VARIABLE_AND_HELPER_test.gno index 9a28b234..f0b3ee74 100644 --- a/staker/_TEST_/_TEST_0_INIT_VARIABLE_AND_HELPER_test.gno +++ b/staker/_TEST_/_TEST_0_INIT_VARIABLE_AND_HELPER_test.gno @@ -27,6 +27,17 @@ var ( ) /* HELPER */ +func ugnotBalanceOf(addr std.Address) uint64 { + testBanker := std.GetBanker(std.BankerTypeRealmIssue) + + coins := testBanker.GetCoins(addr) + if len(coins) == 0 { + return 0 + } + + return uint64(testBanker.GetCoins(addr)[0].Amount) +} + func shouldEQ(t *testing.T, got, expected interface{}) { if got != expected { t.Errorf("got %v, expected %v", got, expected) diff --git a/staker/_TEST_/_TEST_staker_mint_and_stake_test.gn b/staker/_TEST_/_TEST_staker_mint_and_stake_test.gn deleted file mode 100644 index ed19a6e0..00000000 --- a/staker/_TEST_/_TEST_staker_mint_and_stake_test.gn +++ /dev/null @@ -1,92 +0,0 @@ -package staker - -import ( - "std" - "testing" - - pl "gno.land/r/demo/pool" - pn "gno.land/r/demo/position" - - "gno.land/r/demo/bar" - "gno.land/r/demo/gnft" - "gno.land/r/demo/gns" - "gno.land/r/demo/qux" - - "gno.land/r/demo/gnoswap/consts" -) - -func init() { - // init pool tiers - // tier 1 - poolTiers["gno.land/r/demo/bar:gno.land/r/demo/qux:500"] = 1 // DEV - - // tier 2 - poolTiers["GNS/USDT_500"] = 2 - poolTiers["ATOM/GNS_500"] = 2 - - // tier 3 - poolTiers["ATOM/GNOT_500"] = 3 - poolTiers["ATOM/USDT_500"] = 3 - poolTiers["ATOM/WETH_500"] = 3 -} - -func TestPoolInitCreatePool(t *testing.T) { - std.TestSetPrevAddr(test1) - for i := 0; i < (5 * 1); i++ { - gns.Faucet() - } - gns.Approve(a2u(consts.POOL_ADDR), consts.POOL_CREATION_FEE) - std.TestSkipHeights(1) - - pl.CreatePool(barPath, quxPath, 500, "130621891405341611593710811006") // tick 10_000 ≈ x2.7 - std.TestSkipHeights(1) -} - -func TestMintAndStake(t *testing.T) { - std.TestSetPrevAddr(test1) - bar.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) - qux.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) - std.TestSkipHeights(2) - - lpTokenId, liquidity, amount0, amount1, poolPath := MintAndStake( - barPath, // token0 - quxPath, // token1 - fee500, // fee - int32(9000), // tickLower - int32(11000), // tickUpper - "1000", // amount0Desired - "1000", // amount1Desired - "1", // amount0Min - "1", // amount1Min - max_timeout, - ) - std.TestSkipHeights(1) -} - -func TestPositionCollectFee(t *testing.T) { - std.TestSetPrevAddr(test1) - pn.CollectFee(1) // lpTokenId - std.TestSkipHeights(1) -} - -func TestCollectReward(t *testing.T) { - // internal reward distribution - std.TestSetPrevAddr(consts.INTERNAL_REWARD_ACCOUNT) - gns.Approve(a2u(consts.STAKER_ADDR), consts.UINT64_MAX) - - std.TestSetPrevAddr(test1) - CollectReward(1) // lpTokenId - std.TestSkipHeights(1) -} - -func TestUnstakeToken(t *testing.T) { - ownerOfLp1 := gnft.OwnerOf(tid(1)) - shouldEQ(t, ownerOfLp1, a2u(consts.STAKER_ADDR)) - - std.TestSetPrevAddr(test1) - UnstakeToken(1) // lpTokenId - std.TestSkipHeights(1) - - ownerOfLp1 = gnft.OwnerOf(tid(1)) - shouldEQ(t, ownerOfLp1, a2u(test1)) -} diff --git a/staker/_TEST_/_TEST_staker_mint_and_stake_test.gno b/staker/_TEST_/_TEST_staker_mint_and_stake_test.gno new file mode 100644 index 00000000..fc384250 --- /dev/null +++ b/staker/_TEST_/_TEST_staker_mint_and_stake_test.gno @@ -0,0 +1,156 @@ +package staker + +import ( + "std" + "testing" + + pl "gno.land/r/demo/pool" + + "gno.land/r/demo/bar" + "gno.land/r/demo/gns" + "gno.land/r/demo/qux" + "gno.land/r/demo/wugnot" + + "gno.land/r/demo/gnoswap/consts" +) + +func init() { + // init pool tiers + // tier 1 + poolTiers["gno.land/r/demo/bar:gno.land/r/demo/qux:500"] = 1 // DEV + + // tier 2 + poolTiers["GNS/USDT_500"] = 2 + poolTiers["ATOM/GNS_500"] = 2 + + // tier 3 + poolTiers["ATOM/GNOT_500"] = 3 + poolTiers["ATOM/USDT_500"] = 3 + poolTiers["ATOM/WETH_500"] = 3 +} + +func TestPoolInitCreatePool(t *testing.T) { + std.TestSetPrevAddr(gsa) + + gns.Approve(a2u(consts.POOL_ADDR), consts.POOL_CREATION_FEE) + std.TestSkipHeights(1) + + pl.CreatePool(barPath, quxPath, 500, "130621891405341611593710811006") // tick 10_000 ≈ x2.7 + // --- event: {GNOSWAP gno.land/r/demo/pool CreatePool [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_poolPath gno.land/r/demo/bar:gno.land/r/demo/qux:500}]} + + pl.CreatePool(consts.GNOT, consts.GNS_PATH, 500, "130621891405341611593710811006") // tick 10_000 ≈ x2.7 + // --- event: {GNOSWAP gno.land/r/demo/pool CreatePool [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm } {p_poolPath gno.land/r/demo/gns:gno.land/r/demo/wugnot:500}]} + + std.TestSkipHeights(1) +} + +func TestMintAndStakeGRC20Pair(t *testing.T) { + std.TestSetPrevAddr(gsa) + bar.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) + qux.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) + std.TestSkipHeights(2) + + lpTokenId, liquidity, amount0, amount1, poolPath := MintAndStake( + barPath, // token0 + quxPath, // token1 + fee500, // fee + int32(9000), // tickLower + int32(11000), // tickUpper + "1000", // amount0Desired + "1000", // amount1Desired + "1", // amount0Min + "1", // amount1Min + max_timeout, + ) + // event: {GNOSWAP gno.land/r/demo/position Mint [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm gno.land/r/demo/staker} {p_poolPath gno.land/r/demo/bar:gno.land/r/demo/qux:500} {p_tickLower 9000} {p_tickUpper 11000} {tokenId 1} {liquidity 12437} {amount0 368} {amount1 1000}]} + // event: {GNOSWAP gno.land/r/demo/staker StakeToken [{p_tokenId 1} {poolPath gno.land/r/demo/bar:gno.land/r/demo/qux:500} {amount0 368} {amount1 1000}]} + shouldEQ(t, lpTokenId, uint64(1)) + + std.TestSkipHeights(1) +} + +func TestMintAndStakeNative(t *testing.T) { + std.TestSetPrevAddr(gsa) + gns.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) + wugnot.Approve(a2u(consts.POOL_ADDR), consts.UINT64_MAX) + wugnot.Approve(a2u(consts.POSITION_ADDR), consts.UINT64_MAX) + std.TestSkipHeights(2) + + // prepare 100005ugnot (5 for refund test) + testBanker := std.GetBanker(std.BankerTypeRealmIssue) + testBanker.IssueCoin(gsa, "ugnot", 100005) + + // simulate transfer & decrase + gsaNativeBalance := ugnotBalanceOf(gsa) + shouldEQ(t, gsaNativeBalance, 100005) + + std.TestSetOrigSend(std.Coins{{"ugnot", 100005}}, nil) + testBanker.RemoveCoin(std.GetOrigCaller(), "ugnot", -100005) + + gsaNativeBalance = ugnotBalanceOf(gsa) + shouldEQ(t, gsaNativeBalance, 0) + + gsaOldWugnotBalance := wugnot.BalanceOf(a2u(gsa)) + shouldEQ(t, gsaOldWugnotBalance, 0) + + lpTokenId, liquidity, amount0, amount1, poolPath := MintAndStake( + consts.GNOT, // token0 + consts.GNS_PATH, // token1 + fee500, // fee + int32(9000), // tickLower + int32(11000), // tickUpper + "100000", // amount0Desired + "100000", // amount1Desired + "1", // amount0Min + "1", // amount1Min + max_timeout, + ) + // event: {GNOSWAP gno.land/r/demo/position Mint [{m_origCaller g13f63ua8uhmuf9mgc0x8zfz04yrsaqh7j78vcgq} {m_prevRealm gno.land/r/demo/staker} {p_poolPath gno.land/r/demo/gns:gno.land/r/demo/wugnot:500} {p_tickLower -11000} {p_tickUpper -9000} {tokenId 2} {liquidity 1243732} {amount0 100000} {amount1 36790}]} + // event: {GNOSWAP gno.land/r/demo/staker StakeToken [{p_tokenId 2} {poolPath gno.land/r/demo/gns:gno.land/r/demo/wugnot:500} {amount0 100000} {amount1 36790}]} + + shouldEQ(t, lpTokenId, uint64(2)) + std.TestSkipHeights(1) + + // SPEND ALL WUGNOT + newOldWugnotBalance := wugnot.BalanceOf(a2u(gsa)) + shouldEQ(t, gsaOldWugnotBalance, 0) + + gsaNativeBalance = ugnotBalanceOf(gsa) + shouldEQ(t, gsaNativeBalance, 63215) + // 1. 100005 ugnot sent + // 2. 100005 ugnot wrapped to wugnot + // 3. 36790 wugnot spent to mint (amount1) + // 4. refund 100005 - 36790 = 63215 + +} + +/* +func TestPositionCollectFee(t *testing.T) { + std.TestSetPrevAddr(gsa) + pn.CollectFee(1) // lpTokenId + std.TestSkipHeights(1) +} + +func TestCollectReward(t *testing.T) { + // internal reward distribution + std.TestSetPrevAddr(consts.INTERNAL_REWARD_ACCOUNT) + gns.Approve(a2u(consts.STAKER_ADDR), consts.UINT64_MAX) + + std.TestSetPrevAddr(gsa) + CollectReward(1) // lpTokenId + std.TestSkipHeights(1) +} + +func TestUnstakeToken(t *testing.T) { + ownerOfLp1 := gnft.OwnerOf(tid(1)) + shouldEQ(t, ownerOfLp1, a2u(consts.STAKER_ADDR)) + + std.TestSetPrevAddr(gsa) + UnstakeToken(1) // lpTokenId + std.TestSkipHeights(1) + + ownerOfLp1 = gnft.OwnerOf(tid(1)) + shouldEQ(t, ownerOfLp1, a2u(gsa)) +} + +*/ diff --git a/staker/mint_stake.gno b/staker/mint_stake.gno index 7645b4c1..bbbd5169 100644 --- a/staker/mint_stake.gno +++ b/staker/mint_stake.gno @@ -1,8 +1,12 @@ package staker import ( + "std" + pn "gno.land/r/demo/position" + "gno.land/p/demo/ufmt" + "gno.land/r/demo/gnoswap/consts" ) @@ -20,6 +24,23 @@ func MintAndStake( amount1Min string, // *u256.Uint deadline int64, ) (uint64, string, string, string, string) { // tokenId, liquidity, amount0, amount1, poolPath ( *u256.Uint x3) + + // if one click native + if token0 == consts.GNOT || token1 == consts.GNOT { + // check sent ugnot + sent := std.GetOrigSend() + ugnotSent := uint64(sent.AmountOf("ugnot")) + + // not enough ugnot sent + if ugnotSent < consts.UGNOT_MINT_DEPOSIT_TO_WRAP { + panic(ufmt.Sprintf("[STAKER] mint_stake.gno__MintAndStake() || too less(%d) ugnot sent (minimum:%d)", ugnotSent, consts.UGNOT_MINT_DEPOSIT_TO_WRAP)) + } + + // send it over to position to wrap + banker := std.GetBanker(std.BankerTypeRealmSend) + banker.SendCoins(consts.STAKER_ADDR, consts.POSITION_ADDR, std.Coins{{"ugnot", int64(ugnotSent)}}) + } + tokenId, liquidity, amount0, amount1 := pn.Mint( token0, token1, diff --git a/staker/utils.gno b/staker/utils.gno index ce01a082..2a305fb5 100644 --- a/staker/utils.gno +++ b/staker/utils.gno @@ -81,6 +81,16 @@ func uint64ToStr(i uint64) string { return strconv.FormatInt(int64(i), 10) } +func strToUint64(s string) uint64 { + i, err := strconv.Atoi(s) + + if err != nil { + panic(ufmt.Sprintf("[STAKER] utils.gno__strToUint64() || failed to convert string(%s) to uint64", s)) + } + + return uint64(i) +} + func boolToStr(b bool) string { if b { return "true"