From f731db3eb2ff7e018b3d63f2a9703c65ecafd0d6 Mon Sep 17 00:00:00 2001 From: 0xTopaz <myunghwan@onbloc.xyz> Date: Tue, 15 Oct 2024 18:39:54 +0900 Subject: [PATCH 1/2] fix : sync with gnoswap main branch - last commit of gnoswap is 3361e994757821a312de2340474988e649e5a9c4 --- .../gnoswap/v2/launchpad/_RPC_api_project.gno | 82 ++++++++ .../v2/launchpad/__TEST_RPC_api_test.gnoA | 36 ++++ ...e_deposit_reward_by_proejct_tier_test.gnoA | 42 ++-- ...e_deposit_01_deposit_collect_gns_test.gnoA | 24 +-- ...two_tier_two_deposit_collect_gns_test.gnoA | 179 +++++++++++++++++ .../v2/launchpad/launchpad_deposit.gno | 178 ++++++++++++++++- .../r/gnoswap/v2/launchpad/launchpad_init.gno | 5 +- .../gnoswap/v2/launchpad/launchpad_reward.gno | 187 +----------------- .../gno.land/r/gnoswap/v2/launchpad/type.gno | 10 +- 9 files changed, 515 insertions(+), 228 deletions(-) create mode 100644 examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_two_project_two_tier_two_deposit_collect_gns_test.gnoA diff --git a/examples/gno.land/r/gnoswap/v2/launchpad/_RPC_api_project.gno b/examples/gno.land/r/gnoswap/v2/launchpad/_RPC_api_project.gno index ad163141f61..d3364f618c2 100644 --- a/examples/gno.land/r/gnoswap/v2/launchpad/_RPC_api_project.gno +++ b/examples/gno.land/r/gnoswap/v2/launchpad/_RPC_api_project.gno @@ -8,6 +8,46 @@ import ( "gno.land/p/demo/ufmt" ) +func ApiGetProjectAndTierStatisticsByProjectId(projectId string) string { + project, exist := projects[projectId] + if !exist { + return "" + } + + totalDepositAmount := project.totalDepositAmount + actualDepositAmount := project.actualDepositAmount + + totalParticipant := project.totalParticipant + actualParticipant := project.actualParticipant + + totalCollectedAmount := project.totalCollectedAmount + + projectObj := metaNode() + projectObj.AppendObject("projectId", json.StringNode("projectId", projectId)) + projectObj.AppendObject("totalDepositAmount", json.StringNode("totalDepositAmount", ufmt.Sprintf("%d", totalDepositAmount))) + projectObj.AppendObject("actualDepositAmount", json.StringNode("actualDepositAmount", ufmt.Sprintf("%d", actualDepositAmount))) + projectObj.AppendObject("totalParticipant", json.StringNode("totalParticipant", ufmt.Sprintf("%d", totalParticipant))) + projectObj.AppendObject("actualParticipant", json.StringNode("actualParticipant", ufmt.Sprintf("%d", actualParticipant))) + projectObj.AppendObject("totalCollectedAmount", json.StringNode("totalCollectedAmount", ufmt.Sprintf("%d", totalCollectedAmount))) + + projectObj.AppendObject("tier30TotalDepositAmount", json.StringNode("tier30TotalDepositAmount", ufmt.Sprintf("%d", project.tier30.totalDepositAmount))) + projectObj.AppendObject("tier30ActualDepositAmount", json.StringNode("tier30ActualDepositAmount", ufmt.Sprintf("%d", project.tier30.actualDepositAmount))) + projectObj.AppendObject("tier30TotalParticipant", json.StringNode("tier30TotalParticipant", ufmt.Sprintf("%d", project.tier30.totalParticipant))) + projectObj.AppendObject("tier30ActualParticipant", json.StringNode("tier30ActualParticipant", ufmt.Sprintf("%d", project.tier30.actualParticipant))) + + projectObj.AppendObject("tier90TotalDepositAmount", json.StringNode("tier90TotalDepositAmount", ufmt.Sprintf("%d", project.tier90.totalDepositAmount))) + projectObj.AppendObject("tier90ActualDepositAmount", json.StringNode("tier90ActualDepositAmount", ufmt.Sprintf("%d", project.tier90.actualDepositAmount))) + projectObj.AppendObject("tier90TotalParticipant", json.StringNode("tier90TotalParticipant", ufmt.Sprintf("%d", project.tier90.totalParticipant))) + projectObj.AppendObject("tier90ActualParticipant", json.StringNode("tier90ActualParticipant", ufmt.Sprintf("%d", project.tier90.actualParticipant))) + + projectObj.AppendObject("tier180TotalDepositAmount", json.StringNode("tier180TotalDepositAmount", ufmt.Sprintf("%d", project.tier180.totalDepositAmount))) + projectObj.AppendObject("tier180ActualDepositAmount", json.StringNode("tier180ActualDepositAmount", ufmt.Sprintf("%d", project.tier180.actualDepositAmount))) + projectObj.AppendObject("tier180TotalParticipant", json.StringNode("tier180TotalParticipant", ufmt.Sprintf("%d", project.tier180.totalParticipant))) + projectObj.AppendObject("tier180ActualParticipant", json.StringNode("tier180ActualParticipant", ufmt.Sprintf("%d", project.tier180.actualParticipant))) + + return marshal(projectObj) +} + func ApiGetProjectStatisticsByProjectId(projectId string) string { project, exist := projects[projectId] if !exist { @@ -23,6 +63,7 @@ func ApiGetProjectStatisticsByProjectId(projectId string) string { totalCollectedAmount := project.totalCollectedAmount projectObj := metaNode() + projectObj.AppendObject("projectId", json.StringNode("projectId", projectId)) projectObj.AppendObject("totalDepositAmount", json.StringNode("totalDepositAmount", ufmt.Sprintf("%d", totalDepositAmount))) projectObj.AppendObject("actualDepositAmount", json.StringNode("actualDepositAmount", ufmt.Sprintf("%d", actualDepositAmount))) projectObj.AppendObject("totalParticipant", json.StringNode("totalParticipant", ufmt.Sprintf("%d", totalParticipant))) @@ -32,6 +73,47 @@ func ApiGetProjectStatisticsByProjectId(projectId string) string { return marshal(projectObj) } +func ApiGetProjectStatisticsByProjectTierId(tierId string) string { + projectId, tierStr := getProjectIdAndTierFromTierId(tierId) + project, exist := projects[projectId] + if !exist { + println("NO PROJECT FOR THIS ID", projectId) + return "" + } + + var tier Tier + switch tierStr { + case "30": + tier = project.tier30 + case "90": + tier = project.tier90 + case "180": + tier = project.tier180 + default: + println("NO TIER FOR THIS ID", tierId) + return "" + } + + tierAmount := tier.tierAmount // project token allocation + + tierTotalDepositAmount := tier.totalDepositAmount + tierActualDepositAmount := tier.actualDepositAmount + + tierTotalParticipant := tier.totalParticipant + tierActualParticipant := tier.actualParticipant + + projectTierObj := metaNode() + projectTierObj.AppendObject("projectId", json.StringNode("projectId", projectId)) + projectTierObj.AppendObject("tierId", json.StringNode("tierId", tierId)) + projectTierObj.AppendObject("tierAmount", json.StringNode("tierAmount", ufmt.Sprintf("%d", tierAmount))) + projectTierObj.AppendObject("tierTotalDepositAmount", json.StringNode("tierTotalDepositAmount", ufmt.Sprintf("%d", tierTotalDepositAmount))) + projectTierObj.AppendObject("tierActualDepositAmount", json.StringNode("tierActualDepositAmount", ufmt.Sprintf("%d", tierActualDepositAmount))) + projectTierObj.AppendObject("tierTotalParticipant", json.StringNode("tierTotalParticipant", ufmt.Sprintf("%d", tierTotalParticipant))) + projectTierObj.AppendObject("tierActualParticipant", json.StringNode("tierActualParticipant", ufmt.Sprintf("%d", tierActualParticipant))) + + return marshal(projectTierObj) +} + func metaNode() *json.Node { height := std.GetHeight() now := time.Now().Unix() diff --git a/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_RPC_api_test.gnoA b/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_RPC_api_test.gnoA index 9a2be941925..c726dda2b97 100644 --- a/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_RPC_api_test.gnoA +++ b/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_RPC_api_test.gnoA @@ -199,3 +199,39 @@ func TestApiGetClaimableDepositByAddress(t *testing.T) { shouldEQ(t, claimed, uint64(0)) }) } + +func TestApiGetProjectAndTierStatisticsByProjectId(t *testing.T) { + t.Run("not existing project", func(t *testing.T) { + got := ApiGetProjectAndTierStatisticsByProjectId("gno.land/r") + shouldEQ(t, got, ``) + }) + + t.Run("existing project", func(t *testing.T) { + got := ApiGetProjectAndTierStatisticsByProjectId("gno.land/r/onbloc/obl:124") + shouldEQ(t, got, `{"height":"1296142","now":"1237159928","projectId":"gno.land/r/onbloc/obl:124","totalDepositAmount":"1000000","actualDepositAmount":"0","totalParticipant":"1","actualParticipant":"0","totalCollectedAmount":"0","tier30TotalDepositAmount":"1000000","tier30ActualDepositAmount":"0","tier30TotalParticipant":"1","tier30ActualParticipant":"0","tier90TotalDepositAmount":"0","tier90ActualDepositAmount":"0","tier90TotalParticipant":"0","tier90ActualParticipant":"0","tier180TotalDepositAmount":"0","tier180ActualDepositAmount":"0","tier180TotalParticipant":"0","tier180ActualParticipant":"0"}`) + }) +} + +func TestApiGetProjectStatisticsByProjectId(t *testing.T) { + t.Run("not existing project", func(t *testing.T) { + got := ApiGetProjectStatisticsByProjectId("gno.land/r") + shouldEQ(t, got, ``) + }) + + t.Run("existing project", func(t *testing.T) { + got := ApiGetProjectStatisticsByProjectId("gno.land/r/onbloc/obl:124") + shouldEQ(t, got, `{"height":"1296142","now":"1237159928","projectId":"gno.land/r/onbloc/obl:124","totalDepositAmount":"1000000","actualDepositAmount":"0","totalParticipant":"1","actualParticipant":"0","totalCollectedAmount":"0"}`) + }) +} + +func TestApiGetProjectStatisticsByProjectTierId(t *testing.T) { + t.Run("not existing tier", func(t *testing.T) { + got := ApiGetProjectStatisticsByProjectTierId("gno.land/r/onbloc/obl:124:31") + shouldEQ(t, got, ``) + }) + + t.Run("existing tier", func(t *testing.T) { + got := ApiGetProjectStatisticsByProjectTierId("gno.land/r/onbloc/obl:124:30") + shouldEQ(t, got, `{"height":"1296142","now":"1237159928","projectId":"gno.land/r/onbloc/obl:124","tierId":"gno.land/r/onbloc/obl:124:30","tierAmount":"100000000","tierTotalDepositAmount":"1000000","tierActualDepositAmount":"0","tierTotalParticipant":"1","tierActualParticipant":"0"}`) + }) +} diff --git a/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_tier180_single_deposit_reward_by_proejct_tier_test.gnoA b/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_tier180_single_deposit_reward_by_proejct_tier_test.gnoA index 237250854c1..2e662f965b4 100644 --- a/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_tier180_single_deposit_reward_by_proejct_tier_test.gnoA +++ b/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_tier180_single_deposit_reward_by_proejct_tier_test.gnoA @@ -49,7 +49,7 @@ func TestCreateProject(t *testing.T) { std.TestSkipHeights(1) } -func TestDepositGnsToTier90(t *testing.T) { +func TestDepositGnsToTier180(t *testing.T) { std.TestSetRealm(gsaRealm) gns.Transfer(a2u(user01), uint64(1_000_000)) // to deposit // transfer some grc20 tokens to bypass project condition @@ -61,59 +61,59 @@ func TestDepositGnsToTier90(t *testing.T) { // skip some blocks to make project active std.TestSkipHeights(4) - depositId := DepositGns("gno.land/r/onbloc/obl:124:90", uint64(1_000_000)) - shouldEQ(t, depositId, `gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) + depositId := DepositGns("gno.land/r/onbloc/obl:124:180", uint64(1_000_000)) + shouldEQ(t, depositId, `gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) std.TestSkipHeights(1) } func TestCollectRewardByDepositId(t *testing.T) { std.TestSetRealm(user01Realm) - t.Run("claim reward before 7 days(for 90day tier's init reward)", func(t *testing.T) { - reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) + t.Run("claim reward before 14 days(for 180day tier's init reward)", func(t *testing.T) { + reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) shouldEQ(t, reward, uint64(0)) std.TestSkipHeights(1) println() }) - t.Run("claim reward before 7 days(for 90day tier's init reward)", func(t *testing.T) { + t.Run("claim reward before 14 days(for 180day tier's init reward)", func(t *testing.T) { std.TestSkipHeights(123) - reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) + reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) shouldEQ(t, reward, uint64(0)) std.TestSkipHeights(1) println() }) - t.Run("claim after 7 days", func(t *testing.T) { - std.TestSkipHeights(int64(TIMESTAMP_7DAYS) / 2) - reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) - shouldEQ(t, reward, uint64(15562035)) + t.Run("claim after 14 days", func(t *testing.T) { + std.TestSkipHeights(int64(TIMESTAMP_14DAYS) / 2) + reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) + shouldEQ(t, reward, uint64(54455786)) println() }) t.Run("no more claim in same block", func(t *testing.T) { - reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) + reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) shouldEQ(t, reward, uint64(0)) println() }) t.Run("wait 1 more block, then claim", func(t *testing.T) { std.TestSkipHeights(1) - reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) - shouldEQ(t, reward, uint64(51)) + reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) + shouldEQ(t, reward, uint64(90)) println() }) - t.Run("90day tier is over", func(t *testing.T) { - std.TestSkipHeights(int64(TIMESTAMP_90DAYS) / 2) - reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) - shouldEQ(t, reward, uint64(184437911)) + t.Run("180day tier is over", func(t *testing.T) { + std.TestSkipHeights(int64(TIMESTAMP_180DAYS) / 2) + reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) + shouldEQ(t, reward, uint64(645544122)) println() }) - t.Run("more block after 90 days", func(t *testing.T) { - std.TestSkipHeights(int64(TIMESTAMP_90DAYS) / 2) - reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) + t.Run("more block after 180 days", func(t *testing.T) { + std.TestSkipHeights(int64(TIMESTAMP_180DAYS) / 2) + reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`) shouldEQ(t, reward, uint64(0)) println() }) diff --git a/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_tier30_single_deposit_01_deposit_collect_gns_test.gnoA b/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_tier30_single_deposit_01_deposit_collect_gns_test.gnoA index 9fa3b38f8bd..9d7f3668e83 100644 --- a/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_tier30_single_deposit_01_deposit_collect_gns_test.gnoA +++ b/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_tier30_single_deposit_01_deposit_collect_gns_test.gnoA @@ -76,8 +76,8 @@ func TestCreateProject(t *testing.T) { shouldEQ(t, tier30.tierAmount, uint64(100000000)) shouldNEQ(t, tier30.tierAmountPerBlockX96.ToString(), `0`) shouldEQ(t, tier30.endTime, project.startTime+TIMESTAMP_30DAYS) - shouldEQ(t, tier30.depositAmount, uint64(0)) - shouldEQ(t, tier30.participant, uint64(0)) + shouldEQ(t, tier30.actualDepositAmount, uint64(0)) + shouldEQ(t, tier30.actualParticipant, uint64(0)) shouldEQ(t, project.tier90Ratio, uint64(20)) tier90 := project.tier90 @@ -86,8 +86,8 @@ func TestCreateProject(t *testing.T) { shouldEQ(t, tier90.tierAmount, uint64(200000000)) shouldNEQ(t, tier90.tierAmountPerBlockX96.ToString(), `0`) shouldEQ(t, tier90.endTime, project.startTime+TIMESTAMP_90DAYS) - shouldEQ(t, tier90.depositAmount, uint64(0)) - shouldEQ(t, tier90.participant, uint64(0)) + shouldEQ(t, tier90.actualDepositAmount, uint64(0)) + shouldEQ(t, tier90.actualParticipant, uint64(0)) shouldEQ(t, project.tier180Ratio, uint64(70)) tier180 := project.tier180 @@ -96,8 +96,8 @@ func TestCreateProject(t *testing.T) { shouldEQ(t, tier180.tierAmount, uint64(700000000)) shouldNEQ(t, tier180.tierAmountPerBlockX96.ToString(), `0`) shouldEQ(t, tier180.endTime, project.startTime+TIMESTAMP_180DAYS) - shouldEQ(t, tier180.depositAmount, uint64(0)) - shouldEQ(t, tier180.participant, uint64(0)) + shouldEQ(t, tier180.actualDepositAmount, uint64(0)) + shouldEQ(t, tier180.actualParticipant, uint64(0)) shouldEQ(t, project.createdHeight, uint64(124)) shouldEQ(t, project.createdTime, uint64(1234567892)) @@ -135,8 +135,8 @@ func TestDepositGnsToTier30(t *testing.T) { shouldEQ(t, tier30.tierAmount, uint64(100000000)) shouldNEQ(t, tier30.tierAmountPerBlockX96.ToString(), `0`) shouldEQ(t, tier30.endTime, project.startTime+TIMESTAMP_30DAYS) - shouldEQ(t, tier30.depositAmount, uint64(0)) - shouldEQ(t, tier30.participant, uint64(0)) + shouldEQ(t, tier30.actualDepositAmount, uint64(0)) + shouldEQ(t, tier30.actualParticipant, uint64(0)) shouldEQ(t, len(deposits), 0) shouldEQ(t, len(depositsByProject), 0) @@ -162,8 +162,8 @@ func TestDepositGnsToTier30(t *testing.T) { shouldEQ(t, tier30.tierAmount, uint64(100000000)) shouldNEQ(t, tier30.tierAmountPerBlockX96.ToString(), `0`) shouldEQ(t, tier30.endTime, project.startTime+TIMESTAMP_30DAYS) - shouldEQ(t, tier30.depositAmount, uint64(1000000)) - shouldEQ(t, tier30.participant, uint64(1)) + shouldEQ(t, tier30.actualDepositAmount, uint64(1000000)) + shouldEQ(t, tier30.actualParticipant, uint64(1)) // shouldEQ(t, len(deposits), 1) @@ -247,6 +247,6 @@ func TestCollectDepositGns(t *testing.T) { tier30 := project.tier30 shouldEQ(t, tier30.id, `gno.land/r/onbloc/obl:124:30`) shouldEQ(t, tier30.tierAmount, uint64(100000000)) - shouldEQ(t, tier30.depositAmount, uint64(0)) - shouldEQ(t, tier30.participant, uint64(0)) + shouldEQ(t, tier30.actualDepositAmount, uint64(0)) + shouldEQ(t, tier30.actualParticipant, uint64(0)) } diff --git a/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_two_project_two_tier_two_deposit_collect_gns_test.gnoA b/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_two_project_two_tier_two_deposit_collect_gns_test.gnoA new file mode 100644 index 00000000000..d08916b7551 --- /dev/null +++ b/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_two_project_two_tier_two_deposit_collect_gns_test.gnoA @@ -0,0 +1,179 @@ +package launchpad + +import ( + "std" + "testing" + "time" + + "gno.land/p/demo/testutils" + + "gno.land/r/gnoswap/v2/consts" + + "gno.land/r/gnoswap/v2/gns" + "gno.land/r/onbloc/bar" + "gno.land/r/onbloc/obl" +) + +var ( + projectAddr = testutils.TestAddress("projectAddr") + user01 = testutils.TestAddress("user01") + + projectRealm = std.NewUserRealm(projectAddr) + user01Realm = std.NewUserRealm(user01) +) + +func init() { + println("test_init") +} + +func TestCreateProjectObl(t *testing.T) { + std.TestSetRealm(gsaRealm) + + obl.Approve(a2u(consts.LAUNCHPAD_ADDR), uint64(1_000_000_000)) + std.TestSkipHeights(1) + + projectId := CreateProject( + oblPath, + projectAddr, + uint64(1_000_000_000), // 1000000000 + "", + "", + uint64(10), // 100000000 + uint64(20), // 200000000 + uint64(70), // 700000000 + uint64(time.Now().Unix()+10), // 10s later + ) + shouldEQ(t, projectId, `gno.land/r/onbloc/obl:124`) + std.TestSkipHeights(1) +} + +func TestCreateProjectBar(t *testing.T) { + std.TestSetRealm(gsaRealm) + + bar.Approve(a2u(consts.LAUNCHPAD_ADDR), uint64(1_000_000_000)) + std.TestSkipHeights(1) + + projectId := CreateProject( + barPath, + projectAddr, + uint64(1_000_000_000), // 1000000000 + "", + "", + uint64(10), // 100000000 + uint64(20), // 200000000 + uint64(70), // 700000000 + uint64(time.Now().Unix()+10), // 10s later + ) + shouldEQ(t, projectId, `gno.land/r/onbloc/bar:126`) + std.TestSkipHeights(1) +} + +func TestDepositGnsToOblTier30First(t *testing.T) { + std.TestSetRealm(gsaRealm) + gns.Transfer(a2u(user01), uint64(1_000_000)) // to deposit + + std.TestSetRealm(user01Realm) + gns.Approve(a2u(consts.LAUNCHPAD_ADDR), uint64(1_000_000)) + + // skip some blocks to make project active + std.TestSkipHeights(4) + + depositId := DepositGns("gno.land/r/onbloc/obl:124:30", uint64(1_000_000)) // 1000000 + shouldEQ(t, depositId, `gno.land/r/onbloc/obl:124:30:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:131`) + std.TestSkipHeights(1) +} + +func TestDepositGnsToOblTier30Second(t *testing.T) { + std.TestSetRealm(gsaRealm) + gns.Transfer(a2u(user01), uint64(1_000_000)) // to deposit + + std.TestSetRealm(user01Realm) + gns.Approve(a2u(consts.LAUNCHPAD_ADDR), uint64(1_000_000)) + + depositId := DepositGns("gno.land/r/onbloc/obl:124:30", uint64(1_000_000)) // 1000000 + shouldEQ(t, depositId, `gno.land/r/onbloc/obl:124:30:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:132`) + std.TestSkipHeights(1) +} + +func TestDepositGnsToOblTier90First(t *testing.T) { + std.TestSetRealm(gsaRealm) + gns.Transfer(a2u(user01), uint64(1_000_000)) // to deposit + + std.TestSetRealm(user01Realm) + gns.Approve(a2u(consts.LAUNCHPAD_ADDR), uint64(1_000_000)) + + depositId := DepositGns("gno.land/r/onbloc/obl:124:90", uint64(1_000_000)) // 1000000 + shouldEQ(t, depositId, `gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:133`) + std.TestSkipHeights(1) +} + +func TestDepositGnsToOblTier90Second(t *testing.T) { + std.TestSetRealm(gsaRealm) + gns.Transfer(a2u(user01), uint64(2_000_000)) // to deposit + + std.TestSetRealm(user01Realm) + gns.Approve(a2u(consts.LAUNCHPAD_ADDR), uint64(2_000_000)) + + depositId := DepositGns("gno.land/r/onbloc/obl:124:90", uint64(2_000_000)) // 2000000 + shouldEQ(t, depositId, `gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:134`) + std.TestSkipHeights(1) +} + +func TestDepositGnsToBarTier30(t *testing.T) { + std.TestSetRealm(gsaRealm) + gns.Transfer(a2u(user01), uint64(1_000_000)) // to deposit + + std.TestSetRealm(user01Realm) + gns.Approve(a2u(consts.LAUNCHPAD_ADDR), uint64(1_000_000)) + + depositId := DepositGns("gno.land/r/onbloc/bar:126:30", uint64(1_000_000)) // 1000000 + shouldEQ(t, depositId, `gno.land/r/onbloc/bar:126:30:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:135`) + std.TestSkipHeights(1) +} + +func TestCollectDepositGnsByProjectIdObl_Tier30(t *testing.T) { + std.TestSetRealm(user01Realm) + + t.Run("claim before 30 tier ends", func(t *testing.T) { + claimed := CollectDepositGnsByProjectId("gno.land/r/onbloc/obl:124") + std.TestSkipHeights(1) + shouldEQ(t, claimed, uint64(0)) + }) + + t.Run("claim after 30 tier ends from entire obl project's deposit", func(t *testing.T) { + std.TestSkipHeights(int64(TIMESTAMP_30DAYS) / 2) + claimed := CollectDepositGnsByProjectId("gno.land/r/onbloc/obl:124") + std.TestSkipHeights(1) + shouldEQ(t, claimed, uint64(2000000)) + }) +} + +func TestCollectDepositGnsByProjectIdObl_Tier90(t *testing.T) { + std.TestSetRealm(user01Realm) + + t.Run("claim before 90 tier ends", func(t *testing.T) { + claimed := CollectDepositGnsByProjectId("gno.land/r/onbloc/obl:124") + std.TestSkipHeights(1) + shouldEQ(t, claimed, uint64(0)) + }) + + t.Run("claim after 90 tier ends, from certain deposit (first deposit)", func(t *testing.T) { + std.TestSkipHeights(int64(TIMESTAMP_90DAYS) / 2) + claimed := CollectDepositGnsByDepositId("gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:133") + std.TestSkipHeights(1) + shouldEQ(t, claimed, uint64(1000000)) + }) + + t.Run("claim after 90 tier ends, from certain deposit (second deposit)", func(t *testing.T) { + std.TestSkipHeights(int64(TIMESTAMP_90DAYS) / 2) + claimed := CollectDepositGnsByDepositId("gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:134") + std.TestSkipHeights(1) + shouldEQ(t, claimed, uint64(2000000)) + }) + + t.Run("claim after 90 tier ends, from entire obl project's deposit", func(t *testing.T) { + claimed := CollectDepositGnsByProjectId("gno.land/r/onbloc/obl:124") + std.TestSkipHeights(1) + shouldEQ(t, claimed, uint64(0)) + }) +} diff --git a/examples/gno.land/r/gnoswap/v2/launchpad/launchpad_deposit.gno b/examples/gno.land/r/gnoswap/v2/launchpad/launchpad_deposit.gno index 62eac030427..a7a32b09d18 100644 --- a/examples/gno.land/r/gnoswap/v2/launchpad/launchpad_deposit.gno +++ b/examples/gno.land/r/gnoswap/v2/launchpad/launchpad_deposit.gno @@ -77,8 +77,10 @@ func DepositGns( gs.SetAmountByProjectWallet(project.recipient, amount, true) // true == add // update tier - tier.depositAmount += amount - tier.participant += 1 + tier.totalDepositAmount += amount + tier.actualDepositAmount += amount + tier.totalParticipant += 1 + tier.actualParticipant += 1 project = setTier(project, tierStr, tier) // update project @@ -143,7 +145,7 @@ func DepositGns( // // returns collected gns amount func CollectDepositGns() uint64 { - calculateDepositReward() // uncomment this line if L#208 `CollectReward` is removed + calculateDepositReward() caller := std.PrevRealm().Addr() userDeposits := depositsByUser[caller] @@ -179,8 +181,8 @@ func CollectDepositGns() uint64 { gs.SetAmountByProjectWallet(project.recipient, deposit.amount, false) // subtract // update tier - tier.depositAmount -= deposit.amount - tier.participant -= 1 + tier.actualDepositAmount -= deposit.amount + tier.actualParticipant -= 1 // update project project = setTier(project, deposit.tier, tier) @@ -201,8 +203,90 @@ func CollectDepositGns() uint64 { xgns.Burn(a2u(consts.LAUNCHPAD_ADDR), gnsToUser) gns.Transfer(a2u(caller), gnsToUser) - // umcomment L#147 `calculateDepositReward()` - // CollectReward() + return gnsToUser // return accumulated gns amount being withdrawn + } + + return 0 +} + +// CollectDepositGnsByProjectId collect deposited gns of certain project by caller +// - gns will be transfered from the `launchpad` to caller +// - launchpad's xgns will be burned +// +// returns collected gns amount +func CollectDepositGnsByProjectId(projectId string) uint64 { + _, exist := projects[projectId] + if !exist { + println("NO PROJECT FOR THIS ID", projectId) + return 0 + } + + caller := std.PrevRealm().Addr() + if _, exist := depositsByUserByProject[caller]; !exist { + println("NO DEPOSIT FOR THIS USER", caller) + return 0 + } + + depositIds, exist := depositsByUserByProject[caller][projectId] + if !exist { + println("NO DEPOSIT FOR THIS PROJECT", projectId, " FOR UESR", caller) + return 0 + } + + calculateDepositReward() + + gnsToUser := uint64(0) + for _, depositId := range depositIds { + deposit := deposits[depositId] + + // check active + project, exist := projects[deposit.projectId] + if !exist { + panic(ufmt.Sprintf("SHOULD_NOT_HAPPEN__project not found: %s", deposit.projectId)) + } + + tier := getTier(project, deposit.tier) + if checkTierActive(project, tier) { + println("CollectDepositGns()_STILL ACTIVE TIER", deposit.tier) + continue + } + + // collected + if deposit.depositCollectHeight != 0 { + continue + } + + deposit.depositCollectHeight = uint64(std.GetHeight()) + deposit.depositCollectTime = uint64(time.Now().Unix()) + deposits[deposit.id] = deposit + + gnsToUser += deposit.amount + + // update gov_staker contract's variable to calculate proejct's recipient's reward + gs.SetAmountByProjectWallet(project.recipient, deposit.amount, false) // subtract + + // update tier + tier.actualDepositAmount -= deposit.amount + tier.actualParticipant -= 1 + + // update project + project = setTier(project, deposit.tier, tier) + project.actualDepositAmount -= deposit.amount + project.actualParticipant -= 1 + projects[deposit.projectId] = project + + // emit event for each deposit + std.Emit( + "CollectDepositGns", + "m_prevRealm", prevRealm(), + "depositId", depositId, + "amount", ufmt.Sprintf("%d", deposit.amount), + ) + } + + if gnsToUser > 0 { + xgns.Burn(a2u(consts.LAUNCHPAD_ADDR), gnsToUser) + gns.Transfer(a2u(caller), gnsToUser) return gnsToUser // return accumulated gns amount being withdrawn } @@ -210,6 +294,79 @@ func CollectDepositGns() uint64 { return 0 } +// CollectDepositGnsByDepositId collect deposited gns of certain deposit +// - gns will be transfered from the `launchpad` to caller +// - launchpad's xgns will be burned +// +// returns collected gns amount +func CollectDepositGnsByDepositId(depositId string) uint64 { + deposit, exist := deposits[depositId] + if !exist { + println("DEPOSIT NOT FOUND", depositId) + return 0 + } + + project, exist := projects[deposit.projectId] + if !exist { + println("NO PROJECT FOR THIS ID", deposit.projectId) + return 0 + } + + caller := std.PrevRealm().Addr() + if _, exist := depositsByUserByProject[caller]; !exist { + println("NO DEPOSIT FOR THIS USER", caller) + return 0 + } + + calculateDepositReward() + + // check active + tier := getTier(project, deposit.tier) + if checkTierActive(project, tier) { + println("CollectDepositGns()_STILL ACTIVE TIER", deposit.tier) + return 0 + } + + // collected + if deposit.depositCollectHeight != 0 { + return 0 + } + + deposit.depositCollectHeight = uint64(std.GetHeight()) + deposit.depositCollectTime = uint64(time.Now().Unix()) + deposits[deposit.id] = deposit + + // update gov_staker contract's variable to calculate proejct's recipient's reward + gs.SetAmountByProjectWallet(project.recipient, deposit.amount, false) // subtract + + // update tier + tier.actualDepositAmount -= deposit.amount + tier.actualParticipant -= 1 + + // update project + project = setTier(project, deposit.tier, tier) + project.actualDepositAmount -= deposit.amount + project.actualParticipant -= 1 + projects[deposit.projectId] = project + + // emit event for each deposit + std.Emit( + "CollectDepositGns", + "m_prevRealm", prevRealm(), + "p_depositId", depositId, + "amount", ufmt.Sprintf("%d", deposit.amount), + ) + + if deposit.amount > 0 { + xgns.Burn(a2u(consts.LAUNCHPAD_ADDR), deposit.amount) + gns.Transfer(a2u(caller), deposit.amount) + + return deposit.amount // + } + + return 0 +} + func getProjectIdFromTierId(tierId string) string { // input: gno.land/r/gnoswap/gns:123:30 // output: gno.land/r/gnoswap/gns:123 @@ -241,7 +398,12 @@ func checkDepositConditions(project Project) { continue } else { // check balance - balance := balanceOfByRegisterCall(condition.tokenPath, std.PrevRealm().Addr()) + var balance uint64 + if condition.tokenPath == consts.GOV_XGNS_PATH { + balance = xgns.BalanceOf(a2u(std.PrevRealm().Addr())) + } else { + balance = balanceOfByRegisterCall(condition.tokenPath, std.PrevRealm().Addr()) + } if balance < condition.minAmount { panic(ufmt.Sprintf("insufficient balance(%d) for token(%s)", balance, condition.tokenPath)) } diff --git a/examples/gno.land/r/gnoswap/v2/launchpad/launchpad_init.gno b/examples/gno.land/r/gnoswap/v2/launchpad/launchpad_init.gno index 878b44b1bea..79e8898a6b7 100644 --- a/examples/gno.land/r/gnoswap/v2/launchpad/launchpad_init.gno +++ b/examples/gno.land/r/gnoswap/v2/launchpad/launchpad_init.gno @@ -63,6 +63,9 @@ func CreateProject( if strings.Contains(conditionsToken, "*PAD*") { tokensToCheck := strings.Split(conditionsToken, "*PAD*") for _, token := range tokensToCheck { + if token == consts.GOV_XGNS_PATH { + continue + } if _, exist := registered[token]; !exist { panic(ufmt.Sprintf("condition token(%s) not registered", token)) } @@ -186,8 +189,8 @@ func CreateProject( "p_tier30Ratio", ufmt.Sprintf("%d", tier30Ratio), "p_tier90Ratio", ufmt.Sprintf("%d", tier90Ratio), "p_tier180Ratio", ufmt.Sprintf("%d", tier180Ratio), - "p_startHeight", ufmt.Sprintf("%d", startHeight), "p_startTime", ufmt.Sprintf("%d", startTime), + "startHeight", ufmt.Sprintf("%d", startHeight), "projectId", projectId, "tier30Amount", ufmt.Sprintf("%d", tier30Amount), diff --git a/examples/gno.land/r/gnoswap/v2/launchpad/launchpad_reward.gno b/examples/gno.land/r/gnoswap/v2/launchpad/launchpad_reward.gno index 210d90ab885..edc692e115e 100644 --- a/examples/gno.land/r/gnoswap/v2/launchpad/launchpad_reward.gno +++ b/examples/gno.land/r/gnoswap/v2/launchpad/launchpad_reward.gno @@ -17,7 +17,7 @@ func CollectProtocolFee() { caller := std.PrevRealm().Addr() gs.CollectRewardFromLaunchPad(caller) - // XXX: emit event + // event will be emitted in gov/staker CollectRewardFromLaunchPad() } var ( @@ -28,82 +28,6 @@ func init() { lastCalculatedHeight = uint64(std.GetHeight()) } -// CollectReward collects reward from entire deposit by caller -func CollectReward() { - calculateDepositReward() - - caller := std.PrevRealm().Addr() - depositIds, exist := depositsByUser[caller] - if !exist { - println("NO DEPOSIT FOR THIS USER", caller) - return - } - - // project token -> reward amount - toUser := make(map[string]uint64) - - for _, depositId := range depositIds { - deposit := deposits[depositId] - if deposit.rewardAmount == 0 { - println("NO REWARD FOR THIS DEPOSIT", depositId) - continue - } - - project := projects[deposit.projectId] - projectToken := project.tokenPath - - if deposit.rewardAmount > 0 { // deposit has some reward - if deposit.rewardCollectTime != 0 { // this collect is not first collect - println("(N)th collect") - toUser[projectToken] += deposit.rewardAmount - } else { - // if fisrt collect, then check tier's collect wait duration - collectableAfter := uint64(0) - switch deposit.tier { - case "30": - collectableAfter = project.startHeight + project.tier30.collectWaitDuration - case "90": - collectableAfter = project.startHeight + project.tier90.collectWaitDuration - case "180": - collectableAfter = project.startHeight + project.tier180.collectWaitDuration - } - - if uint64(std.GetHeight()) < collectableAfter { - println("NOT CLAIMABLE YET") - continue - } - - println("token:", projectToken, "reward:", deposit.rewardAmount) - toUser[projectToken] += deposit.rewardAmount - } - - std.Emit( - "CollectReward", - "m_prevRealm", prevRealm(), - "depositId", depositId, - "amount", ufmt.Sprintf("%d", deposit.rewardAmount), - ) - } - - // update project - project.totalCollectedAmount += deposit.rewardAmount - projects[deposit.projectId] = project - - // update deposit - deposit.rewardAmount = 0 - deposit.rewardCollectHeight = uint64(std.GetHeight()) - deposit.rewardCollectTime = uint64(time.Now().Unix()) - deposits[depositId] = deposit - } - - // transfer reward to user - for tokenPath, amount := range toUser { - // println("tokenPath:", tokenPath) - // println("amount:", amount) - transferByRegisterCall(tokenPath, std.PrevRealm().Addr(), amount) - } -} - // CollectRewardByProjectId collects reward from entire deposit of certain project by caller // // returns collected reward amount @@ -157,7 +81,7 @@ func CollectRewardByProjectId(projectId string) uint64 { } if uint64(std.GetHeight()) < collectableAfter { - println("NOT CLAIMABLE YET") + println("NOT CLAIMABLE YET", std.GetHeight(), "<", collectableAfter) continue } @@ -185,107 +109,9 @@ func CollectRewardByProjectId(projectId string) uint64 { deposits[depositId] = deposit } - // transfer reward to user - - transferByRegisterCall(project.tokenPath, std.PrevRealm().Addr(), toUser) - - // XXX: emit event - - return toUser -} - -// CollectRewardByProjectTier collects reward from entire deposit of certain project tier by caller -// -// returns collected reward amount -func CollectRewardByProjectTier(tierId string) uint64 { - projectId, tierStr := getProjectIdAndTierFromTierId(tierId) - project, exist := projects[projectId] - if !exist { - println("NO PROJECT FOR THIS ID", projectId) - return 0 - } - - caller := std.PrevRealm().Addr() - if _, exist := depositsByUserByProject[caller]; !exist { - println("NO DEPOSIT FOR THIS USER", caller) - return 0 - } - depositIds, exist := depositsByUserByProject[caller][projectId] - if !exist { - println("NO DEPOSIT FOR THIS PROJECT", projectId) - return 0 - } - - calculateDepositReward() - - toUser := uint64(0) - for _, depositId := range depositIds { - println("depositId:", depositId) - deposit := deposits[depositId] - - // matching tier - if deposit.projectId == projectId && deposit.tier == tierStr { - if deposit.rewardAmount == 0 { - println("NO REWARD FOR THIS DEPOSIT", depositId) - continue - } - - project := projects[deposit.projectId] - if project.id != projectId { - println("PROJECT ID MISMATCH", project.id, projectId) - continue - } - - if deposit.rewardAmount > 0 { - if deposit.rewardCollectTime != 0 { - println("(N)th collect") - toUser += deposit.rewardAmount - } else { - collectableAfter := uint64(0) - switch deposit.tier { - case "30": - collectableAfter = project.startHeight + project.tier30.collectWaitDuration - case "90": - collectableAfter = project.startHeight + project.tier90.collectWaitDuration - case "180": - collectableAfter = project.startHeight + project.tier180.collectWaitDuration - } - - if uint64(std.GetHeight()) < collectableAfter { - println("NOT CLAIMABLE YET") - continue - } - - println("token:", project.tokenPath, "reward:", deposit.rewardAmount) - toUser += deposit.rewardAmount - } - } - - std.Emit( - "CollectRewardByProjectTier", - "m_prevRealm", prevRealm(), - "p_tierId", tierId, - "depositId", depositId, - "amount", ufmt.Sprintf("%d", deposit.rewardAmount), - ) - } - - // update project - project.totalCollectedAmount += deposit.rewardAmount - projects[deposit.projectId] = project - - // update deposit - deposit.rewardAmount = 0 - deposit.rewardCollectHeight = uint64(std.GetHeight()) - deposit.rewardCollectTime = uint64(time.Now().Unix()) - deposits[depositId] = deposit - } - // transfer reward to user transferByRegisterCall(project.tokenPath, std.PrevRealm().Addr(), toUser) - // XXX: emit event - return toUser } @@ -293,7 +119,6 @@ func CollectRewardByProjectTier(tierId string) uint64 { // // returns collected reward amount func CollectRewardByDepositId(depositId string) uint64 { - println("CollectRewardByDepositId", depositId) deposit, exist := deposits[depositId] if !exist { panic("deposit not found") @@ -332,7 +157,7 @@ func CollectRewardByDepositId(depositId string) uint64 { } if uint64(std.GetHeight()) < collectableAfter { - println("NOT CLAIMABLE YET") + println("NOT CLAIMABLE YET", std.GetHeight(), "<", collectableAfter) return 0 } @@ -433,9 +258,9 @@ func calculateDepositReward() { // calculate deposit ratio // loop with each tier (30 90 180) - tier30Deposit := project.tier30.depositAmount - tier90Deposit := project.tier90.depositAmount - tier180Deposit := project.tier180.depositAmount + tier30Deposit := project.tier30.actualDepositAmount + tier90Deposit := project.tier90.actualDepositAmount + tier180Deposit := project.tier180.actualDepositAmount // println("tier30.id", project.tier30.id) // println("tier30Deposit", tier30Deposit) // println("tier90Deposit", tier90Deposit) diff --git a/examples/gno.land/r/gnoswap/v2/launchpad/type.gno b/examples/gno.land/r/gnoswap/v2/launchpad/type.gno index 2567e34defa..8e749322e69 100644 --- a/examples/gno.land/r/gnoswap/v2/launchpad/type.gno +++ b/examples/gno.land/r/gnoswap/v2/launchpad/type.gno @@ -50,11 +50,11 @@ type Tier struct { endHeight uint64 endTime uint64 - // actual data - // unlikely projects' totalDepositAmount or totalParticipant - // below data will be decreased - depositAmount uint64 - participant uint64 + totalDepositAmount uint64 + actualDepositAmount uint64 + + totalParticipant uint64 + actualParticipant uint64 } type Condition struct { From c7940047da7d14d1ed890410aee790ad1b9fc8ff Mon Sep 17 00:00:00 2001 From: 0xTopaz <myunghwan@onbloc.xyz> Date: Tue, 15 Oct 2024 21:25:48 +0900 Subject: [PATCH 2/2] test : add createProject Test - when project have a condition that account has balance of xgns, DepositGns function should check balance of xgns --- .../__TEST_0_INIT_TOKEN_REGISTER_test.gno | 23 +++- .../__TEST_launchpad_create_project_test.gno | 103 ++++++++++++++++++ 2 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_create_project_test.gno diff --git a/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_0_INIT_TOKEN_REGISTER_test.gno b/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_0_INIT_TOKEN_REGISTER_test.gno index 4fb135a1925..051a2915701 100644 --- a/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_0_INIT_TOKEN_REGISTER_test.gno +++ b/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_0_INIT_TOKEN_REGISTER_test.gno @@ -15,6 +15,8 @@ import ( "gno.land/r/onbloc/obl" + "gno.land/r/onbloc/usdc" + "gno.land/r/gnoswap/v2/gns" "gno.land/r/gnoswap/v2/consts" @@ -120,19 +122,31 @@ type GNSToken struct{} func (GNSToken) Transfer() func(to pusers.AddressOrName, amount uint64) { return gns.Transfer } - func (GNSToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { return gns.TransferFrom } - func (GNSToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { return gns.BalanceOf } - func (GNSToken) Approve() func(spender pusers.AddressOrName, amount uint64) { return gns.Approve } +type USDCToken struct{} + +func (USDCToken) Transfer() func(to pusers.AddressOrName, amount uint64) { + return usdc.Transfer +} +func (USDCToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { + return usdc.TransferFrom +} +func (USDCToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { + return usdc.BalanceOf +} +func (USDCToken) Approve() func(spender pusers.AddressOrName, amount uint64) { + return usdc.Approve +} + func init() { std.TestSetRealm(std.NewUserRealm(consts.TOKEN_REGISTER)) @@ -144,6 +158,7 @@ func init() { pf.RegisterGRC20Interface("gno.land/r/demo/wugnot", WugnotToken{}) pf.RegisterGRC20Interface("gno.land/r/onbloc/obl", OBLToken{}) pf.RegisterGRC20Interface("gno.land/r/gnoswap/v2/gns", GNSToken{}) + pf.RegisterGRC20Interface("gno.land/r/onbloc/usdc", USDCToken{}) // gov_staker gs.RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) @@ -153,6 +168,7 @@ func init() { gs.RegisterGRC20Interface("gno.land/r/demo/wugnot", WugnotToken{}) gs.RegisterGRC20Interface("gno.land/r/onbloc/obl", OBLToken{}) gs.RegisterGRC20Interface("gno.land/r/gnoswap/v2/gns", GNSToken{}) + gs.RegisterGRC20Interface("gno.land/r/onbloc/usdc", USDCToken{}) RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) RegisterGRC20Interface("gno.land/r/onbloc/foo", FooToken{}) @@ -161,4 +177,5 @@ func init() { RegisterGRC20Interface("gno.land/r/demo/wugnot", WugnotToken{}) RegisterGRC20Interface("gno.land/r/onbloc/obl", OBLToken{}) RegisterGRC20Interface("gno.land/r/gnoswap/v2/gns", GNSToken{}) + RegisterGRC20Interface("gno.land/r/onbloc/usdc", USDCToken{}) } diff --git a/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_create_project_test.gno b/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_create_project_test.gno new file mode 100644 index 00000000000..170d4cb082b --- /dev/null +++ b/examples/gno.land/r/gnoswap/v2/launchpad/__TEST_launchpad_create_project_test.gno @@ -0,0 +1,103 @@ +package launchpad + +import ( + "std" + "testing" + "time" + + "gno.land/p/demo/testutils" + + "gno.land/r/gnoswap/v2/consts" + "gno.land/r/gnoswap/v2/gns" + gov_staker "gno.land/r/gnoswap/v2/gov/staker" + xgns "gno.land/r/gnoswap/v2/gov/xgns" + "gno.land/r/onbloc/obl" + "gno.land/r/onbloc/usdc" +) + +var ( + projectAddr = testutils.TestAddress("projectAddr") + user01 = testutils.TestAddress("user01") + + projectRealm = std.NewUserRealm(projectAddr) + user01Realm = std.NewUserRealm(user01) +) + +func init() { + println("test_init") +} + +func TestCreateProject(t *testing.T) { + var allocationTokenAmount uint64 = 1_000_000_000_000 // 1000000000000 + std.TestSetRealm(gsaRealm) + + obl.Approve(a2u(consts.LAUNCHPAD_ADDR), allocationTokenAmount) + std.TestSkipHeights(1) + + projectId := CreateProject( + oblPath, + projectAddr, + allocationTokenAmount, + "gno.land/r/gnoswap/v2/gov/xgns*PAD*gno.land/r/onbloc/usdc", + "100000000*PAD*200000000", + uint64(50), // 50% + uint64(30), // 30% + uint64(20), // 20% + uint64(time.Now().Unix()+10), // 10s later + ) + shouldEQ(t, projectId, `gno.land/r/onbloc/obl:124`) + std.TestSkipHeights(1) +} + +func TestMockProtocolFee(t *testing.T) { + std.TestSetRealm(gsaRealm) + usdc.Transfer(a2u(consts.PROTOCOL_FEE_ADDR), 1_000_000_000) + gns.Transfer(a2u(consts.PROTOCOL_FEE_ADDR), 2_500_000_000) + + shouldEQ(t, usdc.BalanceOf(a2u(consts.PROTOCOL_FEE_ADDR)), uint64(1_000_000_000)) + shouldEQ(t, usdc.BalanceOf(a2u(consts.DEV_OPS)), uint64(0)) + shouldEQ(t, usdc.BalanceOf(a2u(consts.GOV_STAKER_ADDR)), uint64(0)) + + shouldEQ(t, gns.BalanceOf(a2u(consts.PROTOCOL_FEE_ADDR)), uint64(2_500_000_000)) + shouldEQ(t, gns.BalanceOf(a2u(consts.DEV_OPS)), uint64(0)) + shouldEQ(t, gns.BalanceOf(a2u(consts.GOV_STAKER_ADDR)), uint64(0)) +} + +func TestDepositGnsToTier30Failure(t *testing.T) { + var usdcConditionAmount uint64 = 200_000_000 + var oblDepositAmount uint64 = 1_000_000 + std.TestSetRealm(gsaRealm) + usdc.Transfer(a2u(user01), usdcConditionAmount) + std.TestSetRealm(user01Realm) + gns.Approve(a2u(consts.LAUNCHPAD_ADDR), oblDepositAmount) + + std.TestSkipHeights(4) + shouldPanicWithMsg( + t, + func() { + DepositGns("gno.land/r/onbloc/obl:124:30", oblDepositAmount) + }, + `insufficient balance(0) for token(gno.land/r/gnoswap/v2/gov/xgns)`, + ) + std.TestSkipHeights(1) +} + +func TestDepositGnsToTier30WithCondition(t *testing.T) { + var xGNSConditionAmount uint64 = 100_000_000 + var gnsDepositAmount uint64 = 1_000_000 + std.TestSetRealm(gsaRealm) + gns.Transfer(a2u(user01), xGNSConditionAmount+gnsDepositAmount) + shouldEQ(t, gns.BalanceOf(a2u(user01)), xGNSConditionAmount+gnsDepositAmount) // admin has initial gns + shouldEQ(t, xgns.BalanceOf(a2u(user01)), uint64(0)) + + std.TestSetRealm(user01Realm) + gns.Approve(a2u(consts.GOV_STAKER_ADDR), xGNSConditionAmount) + gov_staker.Delegate(user01, xGNSConditionAmount) + shouldEQ(t, xgns.BalanceOf(a2u(user01)), xGNSConditionAmount) + std.TestSkipHeights(4) + + var beforeDepositGns uint64 = gns.BalanceOf(a2u(consts.LAUNCHPAD_ADDR)) + DepositGns("gno.land/r/onbloc/obl:124:30", gnsDepositAmount) + shouldEQ(t, gns.BalanceOf(a2u(consts.LAUNCHPAD_ADDR)), beforeDepositGns+gnsDepositAmount) + std.TestSkipHeights(1) +}