diff --git a/gov/xgns/xgns.gno b/gov/xgns/xgns.gno index eaa40404..d01d8f1a 100644 --- a/gov/xgns/xgns.gno +++ b/gov/xgns/xgns.gno @@ -88,7 +88,6 @@ func Render(path string) string { // // This function is restricted to be called only by specific authorized contracts: // - Governance staker contract -// - Launchpad contract // // If the caller is not one of these contracts, the function will panic with an error. // @@ -111,7 +110,40 @@ func Mint(to pusers.AddressOrName, amount uint64) { )) } - checkErr(ledger.Mint(users.Resolve(to), amount)) + mint(users.Resolve(to), amount) +} + +// MintByLaunchPad increases the balance of a specified address by a given amount. +// +// This function is restricted to be called only by specific authorized contracts: +// - Launchpad contract +// +// If the caller is not one of these contracts, the function will panic with an error. +// +// Parameters: +// - to: The address or name of the user whose balance will be increased. +// - amount: The amount of tokens to be minted. +// +// Errors: +// - Panics if the caller is unauthorized. +// - Propagates any error from the ledger.Mint function. +func MintByLaunchPad(to pusers.AddressOrName, amount uint64) { + common.IsHalted() + + caller := std.PrevRealm().Addr() + if caller != consts.LAUNCHPAD_ADDR { + panic(addDetailToError( + errNoPermission, + ufmt.Sprintf("only launchpad(%s) contract can call MintByLaunchPad, called from %s", consts.LAUNCHPAD_ADDR.String(), caller.String()), + )) + } + + mint(users.Resolve(to), amount) +} + +// mint increases the balance of a specified address by a given amount. +func mint(to std.Address, amount uint64) { + checkErr(ledger.Mint(to, amount)) } // Burn reduces the balance of a specified address by a given amount. @@ -141,5 +173,23 @@ func Burn(from pusers.AddressOrName, amount uint64) { )) } - checkErr(ledger.Burn(users.Resolve(from), amount)) + burn(users.Resolve(from), amount) +} + +func BurnByLaunchPad(from pusers.AddressOrName, amount uint64) { + common.IsHalted() + + caller := std.PrevRealm().Addr() + if caller != consts.LAUNCHPAD_ADDR { + panic(addDetailToError( + errNoPermission, + ufmt.Sprintf("only launchpad(%s) contract can call BurnByLaunchPad, called from %s", consts.LAUNCHPAD_ADDR.String(), caller.String()), + )) + } + + burn(users.Resolve(from), amount) +} + +func burn(from std.Address, amount uint64) { + checkErr(ledger.Burn(from, amount)) } diff --git a/gov/xgns/xgns_test.gno b/gov/xgns/xgns_test.gno new file mode 100644 index 00000000..32a71aa3 --- /dev/null +++ b/gov/xgns/xgns_test.gno @@ -0,0 +1,76 @@ +package xgns + +import ( + "std" + "testing" + + "gno.land/r/gnoswap/v1/consts" + + "gno.land/p/demo/uassert" + pusers "gno.land/p/demo/users" +) + +func TestTotalSupply(t *testing.T) { + expectedSupply := uint64(0) + actualSupply := TotalSupply() + if actualSupply != expectedSupply { + t.Errorf("TotalSupply() failed. Expected %d, got %d", expectedSupply, actualSupply) + } +} + +func TestVotingSupply(t *testing.T) { + initialSupply := uint64(1000) + launchpadBalance := uint64(200) + + std.TestSetRealm(std.NewCodeRealm(consts.GOV_STAKER_PATH)) + Mint(pusers.AddressOrName(consts.GOV_STAKER_ADDR), initialSupply-launchpadBalance) + + std.TestSetRealm(std.NewCodeRealm(consts.LAUNCHPAD_PATH)) + MintByLaunchPad(pusers.AddressOrName(consts.LAUNCHPAD_ADDR), launchpadBalance) + + expectedVotingSupply := initialSupply - launchpadBalance + actualVotingSupply := VotingSupply() + if actualVotingSupply != expectedVotingSupply { + t.Errorf("VotingSupply() failed. Expected %d, got %d", expectedVotingSupply, actualVotingSupply) + } + + expectedBalance := launchpadBalance + actualBalance := BalanceOf(pusers.AddressOrName(consts.LAUNCHPAD_ADDR)) + if actualBalance != expectedBalance { + t.Errorf("BalanceOf() failed. Expected %d, got %d", expectedBalance, actualBalance) + } +} + +func TestMintFail(t *testing.T) { + amount := uint64(100) + std.TestSetRealm(std.NewUserRealm(consts.ADMIN)) + uassert.PanicsWithMessage(t, "[GNOSWAP-XGNS-001] caller has no permission || only gov/staker(g17e3ykyqk9jmqe2y9wxe9zhep3p7cw56davjqwa) or launchpad(g122mau2lp2rc0scs8d27pkkuys4w54mdy2tuer3) contract can call Mint, called from g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d", func() { + Mint(pusers.AddressOrName(consts.GOV_STAKER_ADDR), amount) + }) + uassert.PanicsWithMessage(t, "[GNOSWAP-XGNS-001] caller has no permission || only launchpad(g122mau2lp2rc0scs8d27pkkuys4w54mdy2tuer3) contract can call MintByLaunchPad, called from g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d", func() { + MintByLaunchPad(pusers.AddressOrName(consts.GOV_STAKER_ADDR), amount) + }) +} + +func TestBurn(t *testing.T) { + burnAmount := uint64(200) + + std.TestSetRealm(std.NewCodeRealm(consts.LAUNCHPAD_PATH)) + BurnByLaunchPad(pusers.AddressOrName(consts.LAUNCHPAD_ADDR), burnAmount) + expectedBalance := uint64(0) + actualBalance := BalanceOf(pusers.AddressOrName(consts.LAUNCHPAD_ADDR)) + if actualBalance != expectedBalance { + t.Errorf("Burn() failed. Expected %d, got %d", expectedBalance, actualBalance) + } +} + +func TestBurnFail(t *testing.T) { + amount := uint64(100) + std.TestSetRealm(std.NewUserRealm(consts.ADMIN)) + uassert.PanicsWithMessage(t, "[GNOSWAP-XGNS-001] caller has no permission || only gov/staker(g17e3ykyqk9jmqe2y9wxe9zhep3p7cw56davjqwa) or launchpad(g122mau2lp2rc0scs8d27pkkuys4w54mdy2tuer3) contract can call Burn, called from g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d", func() { + Burn(pusers.AddressOrName(consts.GOV_STAKER_ADDR), amount) + }) + uassert.PanicsWithMessage(t, "[GNOSWAP-XGNS-001] caller has no permission || only launchpad(g122mau2lp2rc0scs8d27pkkuys4w54mdy2tuer3) contract can call BurnByLaunchPad, called from g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d", func() { + BurnByLaunchPad(pusers.AddressOrName(consts.GOV_STAKER_ADDR), amount) + }) +}