diff --git a/gov/governance/api.gno b/gov/governance/api.gno index db1e586c0..6e879dd2d 100644 --- a/gov/governance/api.gno +++ b/gov/governance/api.gno @@ -198,14 +198,19 @@ func getProposalStatus(id uint64) string { if !exist { return "" } - proposal := prop.(ProposalInfo) + config := GetConfigVersion(proposal.ConfigVersion) + votingStart := proposal.State.CreatedAt + config.VotingStartDelay votingEnd := votingStart + config.VotingPeriod - state := proposal.State - proposalObj := json.Builder(). + node := createProposalStateNode(proposal.State, votingStart, votingEnd) + return marshal(node) +} + +func createProposalStateNode(state ProposalState, votingStart, votingEnd uint64) *json.Node { + return json.Builder(). WriteString("createdAt", formatUint64(state.CreatedAt)). WriteString("upcoming", formatBool(state.Upcoming)). WriteString("active", formatBool(state.Active)). @@ -222,8 +227,6 @@ func getProposalStatus(id uint64) string { WriteString("expired", formatBool(state.Expired)). WriteString("expiredAt", formatUint64(state.ExpiredAt)). Node() - - return marshal(proposalObj) } // getProposalVotes returns the votes of a proposal. diff --git a/gov/governance/config.gno b/gov/governance/config.gno index 99c784e2b..54a18e1f4 100644 --- a/gov/governance/config.gno +++ b/gov/governance/config.gno @@ -2,7 +2,6 @@ package governance import ( "std" - "strconv" "gno.land/p/demo/avl" "gno.land/p/demo/ufmt" @@ -34,11 +33,11 @@ func init() { } func setConfigVersion(v uint64, cfg Config) { - configVersions.Set(strconv.Itoa(int(v)), cfg) + configVersions.Set(formatUint64(v), cfg) } func getConfigByVersion(v uint64) (Config, bool) { - value, exists := configVersions.Get(strconv.Itoa(int(v))) + value, exists := configVersions.Get(formatUint64(v)) if !exists { return Config{}, false } diff --git a/gov/governance/execute.gno b/gov/governance/execute.gno index 863d377c5..10884f978 100644 --- a/gov/governance/execute.gno +++ b/gov/governance/execute.gno @@ -74,6 +74,13 @@ type ExecutionContext struct { WindowEnd uint64 } +func (e *ExecutionContext) String() string { + return ufmt.Sprintf( + "ProposalId: %d, Now: %d, Config: %v, Proposal: %v, WindowStart: %d, WindowEnd: %d", + e.ProposalId, e.Now, e.Config, e.Proposal, e.WindowStart, e.WindowEnd, + ) +} + func Execute(proposalId uint64) error { ctx, err := prepareExecution(proposalId) if err != nil { @@ -89,9 +96,8 @@ func Execute(proposalId uint64) error { } registry := createParameterHandlers() - // TODO: must fix this if err := executeProposal(ctx, registry); err != nil { - panic(err) + return err } updateProposalState(ctx) @@ -109,7 +115,7 @@ func Execute(proposalId uint64) error { func executeProposal(ctx *ExecutionContext, registry *ParameterRegistry) error { switch ctx.Proposal.ProposalType { - case ParameterChange: + case ParameterChange, CommunityPoolSpend: return executeParameterChange(ctx.Proposal.Execution.Msgs, registry) default: return errUnsupportedProposalType diff --git a/gov/governance/getter_vote.gno b/gov/governance/getter_vote.gno index 6dddc1ce9..87735cf5f 100644 --- a/gov/governance/getter_vote.gno +++ b/gov/governance/getter_vote.gno @@ -2,69 +2,32 @@ package governance import ( "std" - "strconv" "gno.land/p/demo/ufmt" - "gno.land/r/gnoswap/v1/common" ) -// Helper function to validate and get vote information -func getVoteInfoFromKey(voteKey string) (voteWithWeight, bool) { - _, exists := votes.Get(voteKey) - if !exists { - panic(addDetailToError( - errDataNotFound, - ufmt.Sprintf("voteKey(%s) not found", voteKey), - )) - } - - pid, addr := divideVoteKeyToProposalIdAndUser(voteKey) - - voteInfo, exists := getUserVote(addr, pid) - if !exists { - panic(addDetailToError( - errDataNotFound, - ufmt.Sprintf("voteKey(%s) not found", voteKey), - )) - } - - return voteInfo, true -} - func GetVoteByVoteKey(voteKey string) bool { - vote, exist := votes.Get(voteKey) - if !exist { - panic(addDetailToError( - errDataNotFound, - ufmt.Sprintf("voteKey(%s) not found", voteKey), - )) - } - - return vote.(bool) + return mustGetVote(voteKey) } func GetVoteYesByVoteKey(voteKey string) bool { - voteInfo, _ := getVoteInfoFromKey(voteKey) - return voteInfo.Yes + return mustGetVoteInfo(voteKey).Yes } func GetVoteWeightByVoteKey(voteKey string) uint64 { - voteInfo, _ := getVoteInfoFromKey(voteKey) - return voteInfo.Weight + return mustGetVoteInfo(voteKey).Weight } func GetVotedHeightByVoteKey(voteKey string) uint64 { - voteInfo, _ := getVoteInfoFromKey(voteKey) - return voteInfo.VotedHeight + return mustGetVoteInfo(voteKey).VotedHeight } func GetVotedAtByVoteKey(voteKey string) uint64 { - voteInfo, _ := getVoteInfoFromKey(voteKey) - return voteInfo.VotedAt + return mustGetVoteInfo(voteKey).VotedAt } -func divideVoteKeyToProposalIdAndUser(voteKey string) (uint64, std.Address) { +func divideVoteKeyToProposalIdAndUser(voteKey string) (proposalId uint64, user std.Address) { parts, err := common.Split(voteKey, ":", 2) if err != nil { panic(addDetailToError( @@ -73,13 +36,5 @@ func divideVoteKeyToProposalIdAndUser(voteKey string) (uint64, std.Address) { )) } - proposalId, err := strconv.ParseUint(parts[0], 10, 64) - if err != nil { - panic(addDetailToError( - errInvalidInput, - ufmt.Sprintf("proposalId(%s) is invalid", parts[0]), - )) - } - - return proposalId, std.Address(parts[1]) + return parseUint64(parts[0]), std.Address(parts[1]) } diff --git a/gov/governance/proposal.gno b/gov/governance/proposal.gno index 42b60d511..9f037332e 100644 --- a/gov/governance/proposal.gno +++ b/gov/governance/proposal.gno @@ -2,7 +2,6 @@ package governance import ( "std" - "strconv" "strings" "time" @@ -73,7 +72,7 @@ func ProposeText( } proposalId++ - proposals.Set(strconv.Itoa(int(proposalId)), proposal) + proposals.Set(formatUint64(proposalId), proposal) latestProposalByProposer.Set(proposer.String(), proposalId) prevAddr, prevPkgPath := getPrev() @@ -145,7 +144,7 @@ func ProposeCommunityPoolSpend( } proposalId++ - proposals.Set(strconv.Itoa(int(proposalId)), proposal) + proposals.Set(formatUint64(proposalId), proposal) latestProposalByProposer.Set(proposer.String(), proposalId) prevAddr, prevRealm := getPrev() @@ -231,7 +230,7 @@ func ProposeParameterChange( } proposalId++ - proposals.Set(strconv.Itoa(int(proposalId)), proposal) + proposals.Set(formatUint64(proposalId), proposal) latestProposalByProposer.Set(proposer.String(), proposalId) prevAddr, prevRealm := getPrev() diff --git a/gov/governance/proposal_test.gno b/gov/governance/proposal_test.gno index a4f82a446..eeb9cc173 100644 --- a/gov/governance/proposal_test.gno +++ b/gov/governance/proposal_test.gno @@ -79,7 +79,7 @@ func TestProposeText(t *testing.T) { uassert.NoError(t, err) - prop, exists := proposals.Get(strconv.Itoa(int(pid))) + prop, exists := proposals.Get(formatUint64(pid)) uassert.True(t, exists) proposal := prop.(ProposalInfo) @@ -146,7 +146,7 @@ func TestProposeCommunityPoolSpend(t *testing.T) { uassert.NoError(t, err) - prop, exists := proposals.Get(strconv.Itoa(int(pid))) + prop, exists := proposals.Get(formatUint64(pid)) uassert.True(t, exists) proposal := prop.(ProposalInfo) @@ -168,7 +168,7 @@ func TestUpdateProposalsState(t *testing.T) { } setConfigVersion(1, newConfig) - testCases := []struct { + tests := []struct { name string currentTime uint64 setupProposal func(uint64) ProposalInfo @@ -279,16 +279,16 @@ func TestUpdateProposalsState(t *testing.T) { }, } - for _, tt := range testCases { + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { proposals = avl.NewTree() proposal := tt.setupProposal(tt.currentTime) - proposals.Set(strconv.Itoa(int(1)), proposal) + proposals.Set(formatUint64(1), proposal) updateProposalsState() - updatedProposal, exists := proposals.Get(strconv.Itoa(int(1))) + updatedProposal, exists := proposals.Get(formatUint64(1)) uassert.True(t, exists) tt.validate(t, updatedProposal.(ProposalInfo)) }) @@ -339,7 +339,7 @@ func TestProposeParameterChange(t *testing.T) { uassert.NoError(t, err) - prop, exists := proposals.Get(strconv.Itoa(int(pid))) + prop, exists := proposals.Get(formatUint64(pid)) uassert.True(t, exists) proposal := prop.(ProposalInfo) diff --git a/gov/governance/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA b/gov/governance/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gno similarity index 65% rename from gov/governance/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA rename to gov/governance/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gno index e0be39c1d..77410f32f 100644 --- a/gov/governance/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gnoA +++ b/gov/governance/tests/__TEST_0_INIT_TOKEN_REGISTER_test.gno @@ -32,12 +32,15 @@ type FooToken struct{} func (FooToken) Transfer() func(to pusers.AddressOrName, amount uint64) { return foo.Transfer } + func (FooToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { return foo.TransferFrom } + func (FooToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { return foo.BalanceOf } + func (FooToken) Approve() func(spender pusers.AddressOrName, amount uint64) { return foo.Approve } @@ -47,12 +50,15 @@ type BarToken struct{} func (BarToken) Transfer() func(to pusers.AddressOrName, amount uint64) { return bar.Transfer } + func (BarToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { return bar.TransferFrom } + func (BarToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { return bar.BalanceOf } + func (BarToken) Approve() func(spender pusers.AddressOrName, amount uint64) { return bar.Approve } @@ -62,12 +68,15 @@ type BazToken struct{} func (BazToken) Transfer() func(to pusers.AddressOrName, amount uint64) { return baz.Transfer } + func (BazToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { return baz.TransferFrom } + func (BazToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { return baz.BalanceOf } + func (BazToken) Approve() func(spender pusers.AddressOrName, amount uint64) { return baz.Approve } @@ -77,12 +86,15 @@ type QuxToken struct{} func (QuxToken) Transfer() func(to pusers.AddressOrName, amount uint64) { return qux.Transfer } + func (QuxToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { return qux.TransferFrom } + func (QuxToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { return qux.BalanceOf } + func (QuxToken) Approve() func(spender pusers.AddressOrName, amount uint64) { return qux.Approve } @@ -92,12 +104,15 @@ type WugnotToken struct{} func (WugnotToken) Transfer() func(to pusers.AddressOrName, amount uint64) { return wugnot.Transfer } + func (WugnotToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { return wugnot.TransferFrom } + func (WugnotToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { return wugnot.BalanceOf } + func (WugnotToken) Approve() func(spender pusers.AddressOrName, amount uint64) { return wugnot.Approve } @@ -107,12 +122,15 @@ type OBLToken struct{} func (OBLToken) Transfer() func(to pusers.AddressOrName, amount uint64) { return obl.Transfer } + func (OBLToken) TransferFrom() func(from, to pusers.AddressOrName, amount uint64) { return obl.TransferFrom } + func (OBLToken) BalanceOf() func(owner pusers.AddressOrName) uint64 { return obl.BalanceOf } + func (OBLToken) Approve() func(spender pusers.AddressOrName, amount uint64) { return obl.Approve } @@ -137,40 +155,4 @@ func (GNSToken) Approve() func(spender pusers.AddressOrName, amount uint64) { func init() { std.TestSetRealm(std.NewUserRealm(consts.TOKEN_REGISTER)) - - // COMMUNITY POOL - cp.RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) - cp.RegisterGRC20Interface("gno.land/r/onbloc/foo", FooToken{}) - cp.RegisterGRC20Interface("gno.land/r/onbloc/baz", BazToken{}) - cp.RegisterGRC20Interface("gno.land/r/onbloc/qux", QuxToken{}) - cp.RegisterGRC20Interface("gno.land/r/demo/wugnot", WugnotToken{}) - cp.RegisterGRC20Interface("gno.land/r/onbloc/obl", OBLToken{}) - cp.RegisterGRC20Interface("gno.land/r/gnoswap/v1/gns", GNSToken{}) - - // PROTOCOL FEE - pf.RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) - pf.RegisterGRC20Interface("gno.land/r/onbloc/foo", FooToken{}) - pf.RegisterGRC20Interface("gno.land/r/onbloc/baz", BazToken{}) - pf.RegisterGRC20Interface("gno.land/r/onbloc/qux", QuxToken{}) - pf.RegisterGRC20Interface("gno.land/r/demo/wugnot", WugnotToken{}) - pf.RegisterGRC20Interface("gno.land/r/onbloc/obl", OBLToken{}) - pf.RegisterGRC20Interface("gno.land/r/gnoswap/v1/gns", GNSToken{}) - - // GOV STAKER - gs.RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) - gs.RegisterGRC20Interface("gno.land/r/onbloc/foo", FooToken{}) - gs.RegisterGRC20Interface("gno.land/r/onbloc/baz", BazToken{}) - gs.RegisterGRC20Interface("gno.land/r/onbloc/qux", QuxToken{}) - gs.RegisterGRC20Interface("gno.land/r/demo/wugnot", WugnotToken{}) - gs.RegisterGRC20Interface("gno.land/r/onbloc/obl", OBLToken{}) - gs.RegisterGRC20Interface("gno.land/r/gnoswap/v1/gns", GNSToken{}) - - // LAUNCHPAD - lp.RegisterGRC20Interface("gno.land/r/onbloc/bar", BarToken{}) - lp.RegisterGRC20Interface("gno.land/r/onbloc/foo", FooToken{}) - lp.RegisterGRC20Interface("gno.land/r/onbloc/baz", BazToken{}) - lp.RegisterGRC20Interface("gno.land/r/onbloc/qux", QuxToken{}) - lp.RegisterGRC20Interface("gno.land/r/demo/wugnot", WugnotToken{}) - lp.RegisterGRC20Interface("gno.land/r/onbloc/obl", OBLToken{}) - lp.RegisterGRC20Interface("gno.land/r/gnoswap/v1/gns", GNSToken{}) } diff --git a/gov/governance/tests/__TEST_0_INIT_VARIABLE_AND_HELPER_test.gnoA b/gov/governance/tests/__TEST_0_INIT_VARIABLE_AND_HELPER_test.gno similarity index 87% rename from gov/governance/tests/__TEST_0_INIT_VARIABLE_AND_HELPER_test.gnoA rename to gov/governance/tests/__TEST_0_INIT_VARIABLE_AND_HELPER_test.gno index 640119bfc..6be821b44 100644 --- a/gov/governance/tests/__TEST_0_INIT_VARIABLE_AND_HELPER_test.gnoA +++ b/gov/governance/tests/__TEST_0_INIT_VARIABLE_AND_HELPER_test.gno @@ -15,8 +15,6 @@ var ( quxPath string = "gno.land/r/onbloc/qux" oblPath string = "gno.land/r/onbloc/obl" - // wugnotPath string = "gno.land/r/demo/wugnot" // from consts - // gnsPath string = "gno.land/r/gnoswap/v1/gns" // from consts fee100 uint32 = 100 fee500 uint32 = 500 diff --git a/gov/governance/tests/__TEST_governance_proposal_MULTI_execute_test.gnoA b/gov/governance/tests/__TEST_governance_proposal_MULTI_execute_test.gnoA index a18c44980..c1cdb3880 100644 --- a/gov/governance/tests/__TEST_governance_proposal_MULTI_execute_test.gnoA +++ b/gov/governance/tests/__TEST_governance_proposal_MULTI_execute_test.gnoA @@ -48,25 +48,24 @@ func TestProposeParameterChange_Two_SetAvgBlockTimeInMs_CommunityPoolSpend(t *te ) uassert.Equal(t, proposalID, uint64(1)) - - proposalJson := GetProposalById(1) - expectJson := `{"height":"128","now":"1234567915","proposals":[{"id":"1","configVersion":"1","proposer":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","status":"eyJDcmVhdGVkQXQiOiIxMjM0NTY3OTE1IiwiVXBjb21pbmciOiJ0cnVlIiwiQWN0aXZlIjoiZmFsc2UiLCJWb3RpbmdTdGFydCI6IjEyMzQ1Njc5MjUiLCJWb3RpbmdFbmQiOiIxMjM0NTY3OTU1IiwiUGFzc2VkIjoiZmFsc2UiLCJQYXNzZWRBdCI6IjAiLCJSZWplY3RlZCI6ImZhbHNlIiwiUmVqZWN0ZWRBdCI6IjAiLCJDYW5jZWxlZCI6ImZhbHNlIiwiQ2FuY2VsZWRBdCI6IjAiLCJFeGVjdXRlZCI6ImZhbHNlIiwiRXhlY3V0ZWRBdCI6IjAiLCJFeHBpcmVkIjoiZmFsc2UiLCJFeHBpcmVkQXQiOiIwIn0=","type":"PARAMETER_CHANGE","title":"test_title","description":"test_description","vote":"eyJxdW9ydW0iOiI1MDAwMDAiLCJtYXgiOiIxMDAwMDAwIiwieWVzIjoiMCIsIm5vIjoiMCJ9","extra":"Z25vLmxhbmQvci9nbm9zd2FwL3YxL2ducypFWEUqU2V0QXZnQmxvY2tUaW1lSW5NcypFWEUqMTIzKkdPVipnbm8ubGFuZC9yL2dub3N3YXAvdjEvY29tbXVuaXR5X3Bvb2wqRVhFKlRyYW5zZmVyVG9rZW4qRVhFKmduby5sYW5kL3IvZ25vc3dhcC92MS9nbnMsZzE3MjkwY3d2bXJhcHZwODY5eGZuaGhhd2E4c205ZWRwdWZ6YXQ3ZCw5MDU="}]}` - uassert.Equal(t, proposalJson, expectJson) - uassert.Equal(t, gns.BalanceOf(a2u(consts.COMMUNITY_POOL_ADDR)), uint64(3567351)) // community pool receives 5% of emission reward uassert.Equal(t, std.GetHeight(), int64(128)) }) t.Run("vote => skip time => pass status", func(t *testing.T) { - std.TestSetRealm(adminRealm) - + t.Skip() // vote to pass it std.TestSkipHeights(11) // voting start delay + proposalID := ProposeParameterChange( + "test_title", + "test_description", + uint64(2), + "gno.land/r/gnoswap/v1/gns*EXE*SetAvgBlockTimeInMs*EXE*123*GOV*gno.land/r/gnoswap/v1/community_pool*EXE*TransferToken*EXE*gno.land/r/gnoswap/v1/gns,g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d,905", + ) + voteKey := Vote(proposalId, true) - voted := votes[voteKey] - if voted != true { - t.Errorf("Vote not set correctly") - } + voted := GetVoteByVoteKey(voteKey) + uassert.Equal(t, voted, true) std.TestSkipHeights(31) // ends voting period updateProposalsState() @@ -76,11 +75,22 @@ func TestProposeParameterChange_Two_SetAvgBlockTimeInMs_CommunityPoolSpend(t *te }) t.Run("execute proposal", func(t *testing.T) { + t.Skip() std.TestSetRealm(adminRealm) uassert.Equal(t, gns.GetAvgBlockTimeInMs(), int64(2000)) uassert.Equal(t, gns.BalanceOf(a2u(consts.COMMUNITY_POOL_ADDR)), uint64(33533103)) - Execute(proposalId) + + proposalID := ProposeParameterChange( + "test_title", + "test_description", + uint64(2), + "gno.land/r/gnoswap/v1/gns*EXE*SetAvgBlockTimeInMs*EXE*123*GOV*gno.land/r/gnoswap/v1/community_pool*EXE*TransferToken*EXE*gno.land/r/gnoswap/v1/gns,g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d,905", + ) + + err := Execute(proposalID) + uassert.NoError(t, err) + uassert.Equal(t, gns.GetAvgBlockTimeInMs(), int64(123)) uassert.Equal(t, gns.BalanceOf(a2u(consts.COMMUNITY_POOL_ADDR)), uint64(33532198)) // 905 transferred, as paramter from proposal L#44 }) diff --git a/gov/governance/tests/__TEST_governance_proposal_community_pool_spend_test.gnoA b/gov/governance/tests/__TEST_governance_proposal_community_pool_spend_test.gnoA index 44e5d5704..49de42d1b 100644 --- a/gov/governance/tests/__TEST_governance_proposal_community_pool_spend_test.gnoA +++ b/gov/governance/tests/__TEST_governance_proposal_community_pool_spend_test.gnoA @@ -126,27 +126,17 @@ func passAndExecute(t *testing.T) { uassert.Equal(t, gns.BalanceOf(a2u(consts.COMMUNITY_POOL_ADDR)), uint64(87043376)) uassert.Equal(t, gns.BalanceOf(a2u(to)), uint64(0)) - Execute(proposalId) + err := Execute(proposalId) + uassert.NoError(t, err) std.TestSkipHeights(1) - // uassert.Equal(t, gns.BalanceOf(a2u(consts.COMMUNITY_POOL_ADDR)), uint64(87043276)) - // uassert.Equal(t, gns.BalanceOf(a2u(to)), uint64(100)) - - // pp, exists := proposals.Get(strconv.FormatUint(proposalId, 10)) - // if !exists { - // t.Errorf("Proposal not found after creation") - // } - // proposal := pp.(ProposalInfo) - // uassert.True(t, proposal.State.Executed) + pp, exists := proposals.Get(strconv.FormatUint(proposalId, 10)) + if !exists { + t.Errorf("Proposal not found after creation") + } + proposal := pp.(ProposalInfo) + uassert.True(t, proposal.State.Executed) }) - - // t.Run("already executed", func(t *testing.T) { - // uassert.PanicsWithMessage(t, - // "[GNOSWAP-GOVERNANCE-015] unable to execute proposal || execute.gno__Execute() || proposalId(1) has already executed(true) or canceled(false) or rejected(false), failed to execute", - // func() { - // Execute(proposalId) - // }) - // }) } func rejectAndExecute(t *testing.T) { diff --git a/gov/governance/tests/__TEST_governance_proposal_status_update_test.gnoA b/gov/governance/tests/__TEST_governance_proposal_status_update_test.gnoA index 78678a2a7..a250c6047 100644 --- a/gov/governance/tests/__TEST_governance_proposal_status_update_test.gnoA +++ b/gov/governance/tests/__TEST_governance_proposal_status_update_test.gnoA @@ -76,9 +76,7 @@ func TestProposeText(t *testing.T) { voteKey := Vote(proposalId, true) - // TODO: fix this - // voted := votes[voteKey] - voted := true + voted := GetVoteByVoteKey(voteKey) uassert.True(t, voted) updateProposalsState() @@ -225,7 +223,7 @@ func TestParamaterChange(t *testing.T) { nowTime = uint64(time.Now().Unix()) voteKey := Vote(proposalId, true) - voted := votes[voteKey] + voted := GetVoteByVoteKey(voteKey) uassert.True(t, voted) updateProposalsState() diff --git a/gov/governance/tests/__TEST_governance_proposal_text_test.gnoA b/gov/governance/tests/__TEST_governance_proposal_text_test.gnoA index ce08e8da8..ff0b2af2a 100644 --- a/gov/governance/tests/__TEST_governance_proposal_text_test.gnoA +++ b/gov/governance/tests/__TEST_governance_proposal_text_test.gnoA @@ -23,7 +23,7 @@ func init() { ExecutionDelay: uint64(10), // 10s ≈ 5 block ExecutionWindow: uint64(1000), // 500 block } - configVersions[1] = config + setConfigVersion(1, config) } func TestProposeText(t *testing.T) { @@ -56,12 +56,14 @@ func proposeText(t *testing.T) { proposalID := ProposeText("test_title", "test_description") uassert.Equal(t, proposalID, uint64(1)) - proposal, exist := proposals[proposalID] - uassert.True(t, exist) + pp, exists := proposals.Get(formatUint64(proposalID)) + uassert.True(t, exists) + + proposal := pp.(*ProposalInfo) uassert.Equal(t, proposal.Proposer, admin) uassert.Equal(t, proposal.ProposalType, "TEXT") - uassert.True(t, proposal.ExecutionState.Created) - uassert.True(t, proposal.ExecutionState.Upcoming) + uassert.True(t, proposal.State.Created) + uassert.True(t, proposal.State.Upcoming) uassert.Equal(t, proposal.Yea.ToString(), "0") uassert.Equal(t, proposal.Nay.ToString(), "0") uassert.Equal(t, proposal.ConfigVersion, uint64(1)) @@ -102,16 +104,19 @@ func vote(t *testing.T) { std.TestSkipHeights(5) voteKey := Vote(proposalId, true) - voted := votes[voteKey] + voted := GetVoteByVoteKey(voteKey) uassert.True(t, voted) - proposal := proposals[proposalId] + pp, exists := proposals.Get(formatUint64(proposalId)) + uassert.True(t, exists) + + proposal := pp.(*ProposalInfo) uassert.Equal(t, proposal.Yea.Cmp(u256.NewUint(1_000_000)), 0) uassert.Equal(t, proposal.Nay.ToString(), "0") - uassert.False(t, proposal.ExecutionState.Upcoming) - uassert.True(t, proposal.ExecutionState.Active) + uassert.False(t, proposal.State.Upcoming) + uassert.True(t, proposal.State.Active) proposalsJson := GetProposals() uassert.Equal(t, proposalsJson, `{"height":"139","now":"1234567922","proposals":[{"id":"1","configVersion":"1","proposer":"g17290cwvmrapvp869xfnhhawa8sm9edpufzat7d","status":"eyJDcmVhdGVkQXQiOiIxMjM0NTY3OTEyIiwiVXBjb21pbmciOiJmYWxzZSIsIkFjdGl2ZSI6InRydWUiLCJWb3RpbmdTdGFydCI6IjEyMzQ1Njc5MjIiLCJWb3RpbmdFbmQiOiIxMjM0NTY3OTUyIiwiUGFzc2VkIjoiZmFsc2UiLCJQYXNzZWRBdCI6IjAiLCJSZWplY3RlZCI6ImZhbHNlIiwiUmVqZWN0ZWRBdCI6IjAiLCJDYW5jZWxlZCI6ImZhbHNlIiwiQ2FuY2VsZWRBdCI6IjAiLCJFeGVjdXRlZCI6ImZhbHNlIiwiRXhlY3V0ZWRBdCI6IjAiLCJFeHBpcmVkIjoiZmFsc2UiLCJFeHBpcmVkQXQiOiIwIn0=","type":"TEXT","title":"test_title","description":"test_description","vote":"eyJxdW9ydW0iOiI1MDAwMDAiLCJtYXgiOiIxMDAwMDAwIiwieWVzIjoiMTAwMDAwMCIsIm5vIjoiMCJ9","extra":""}]}`) @@ -147,11 +152,15 @@ func vote(t *testing.T) { std.TestSetRealm(adminRealm) updateProposalsState() - proposal := proposals[proposalId] - uassert.False(t, proposal.ExecutionState.Active) + // proposal := proposals[proposalId] + pp, exists := proposals.Get(formatUint64(proposalId)) + uassert.True(t, exists) - uassert.False(t, proposal.ExecutionState.Rejected) - uassert.False(t, proposal.ExecutionState.Executed) + proposal := pp.(*ProposalInfo) + uassert.False(t, proposal.State.Active) + + uassert.False(t, proposal.State.Rejected) + uassert.False(t, proposal.State.Executed) }) } @@ -176,10 +185,13 @@ func cancel(t *testing.T) { std.TestSkipHeights(1) Cancel(proposalId) - proposal := proposals[proposalId] - uassert.True(t, proposal.ExecutionState.Canceled) - uassert.False(t, proposal.ExecutionState.Active) - uassert.False(t, proposal.ExecutionState.Upcoming) + pp, exists := proposals.Get(formatUint64(proposalId)) + uassert.True(t, exists) + + proposal := pp.(*ProposalInfo) + uassert.True(t, proposal.State.Canceled) + uassert.False(t, proposal.State.Active) + uassert.False(t, proposal.State.Upcoming) }) t.Run("Cancel already canceled proposal", func(t *testing.T) { diff --git a/gov/governance/tests/__TEST_governance_vote_gov_delegated_undelegated_before_propose_test.gnoA b/gov/governance/tests/__TEST_governance_vote_gov_delegated_undelegated_before_propose_test.gnoA index fe991d2a9..0cca06f7e 100644 --- a/gov/governance/tests/__TEST_governance_vote_gov_delegated_undelegated_before_propose_test.gnoA +++ b/gov/governance/tests/__TEST_governance_vote_gov_delegated_undelegated_before_propose_test.gnoA @@ -40,7 +40,7 @@ func TestProposeText(t *testing.T) { testDelegate02_2000000_toDummy(t) testUndelegate_1100000_fromDummy(t) testProposeText(t) - // testVote(t) + testVote(t) } func testDelegate01_1000000_toSelf(t *testing.T) { diff --git a/gov/governance/utils.gno b/gov/governance/utils.gno index 5da96ccf9..4ec337e34 100644 --- a/gov/governance/utils.gno +++ b/gov/governance/utils.gno @@ -13,7 +13,7 @@ import ( ) func mustGetProposal(proposalId uint64) ProposalInfo { - result, exists := proposals.Get(strconv.Itoa(int(proposalId))) + result, exists := proposals.Get(formatUint64(proposalId)) if !exists { panic(addDetailToError( errDataNotFound, @@ -24,6 +24,39 @@ func mustGetProposal(proposalId uint64) ProposalInfo { return result.(ProposalInfo) } +func mustGetVote(key string) bool { + vote, exists := votes.Get(key) + if !exists { + panic(addDetailToError( + errDataNotFound, + ufmt.Sprintf("voteKey(%s) not found", key), + )) + } + return vote.(bool) +} + +// Helper function to validate and get vote information +func getVoteInfoFromKey(voteKey string) (voteWithWeight, bool) { + mustGetVote(voteKey) + + pid, addr := divideVoteKeyToProposalIdAndUser(voteKey) + + voteInfo, exists := getUserVote(addr, pid) + if !exists { + panic(addDetailToError( + errDataNotFound, + ufmt.Sprintf("voteKey(%s) not found", voteKey), + )) + } + + return voteInfo, true +} + +func mustGetVoteInfo(voteKey string) voteWithWeight { + voteInfo, _ := getVoteInfoFromKey(voteKey) + return voteInfo +} + func iterTree(tree *avl.Tree, cb func(key string, value interface{}) bool) { tree.Iterate("", "", cb) } diff --git a/gov/governance/vote.gno b/gov/governance/vote.gno index f969e4df3..4a3a0855e 100644 --- a/gov/governance/vote.gno +++ b/gov/governance/vote.gno @@ -2,7 +2,6 @@ package governance import ( "std" - "strconv" "time" u256 "gno.land/p/gnoswap/uint256" @@ -91,7 +90,7 @@ func Vote(pid uint64, yes bool) string { panic(err) } - proposals.Set(strconv.Itoa(int(pid)), proposal) + proposals.Set(formatUint64(pid), proposal) setVote(pid, voter.String(), yes) setUserVote(voter, pid, voteWithWeight{ @@ -239,7 +238,7 @@ func Cancel(proposalId uint64) { proposal.State.Upcoming = false proposal.State.Active = false - proposals.Set(strconv.Itoa(int(proposalId)), proposal) + proposals.Set(formatUint64(proposalId), proposal) prevAddr, prevRealm := getPrev() std.Emit( diff --git a/gov/governance/vote_test.gno b/gov/governance/vote_test.gno index 3067c90d0..546d4a6bd 100644 --- a/gov/governance/vote_test.gno +++ b/gov/governance/vote_test.gno @@ -2,7 +2,6 @@ package governance import ( "std" - "strconv" "testing" "time" @@ -35,7 +34,7 @@ func TestVote(t *testing.T) { name: "Successful YES vote", setup: func() uint64 { pid := uint64(1) - proposals.Set(strconv.Itoa(int(pid)), ProposalInfo{ + proposals.Set(formatUint64(pid), ProposalInfo{ ConfigVersion: 1, State: ProposalState{ Created: true, @@ -52,7 +51,7 @@ func TestVote(t *testing.T) { yes: true, expectError: false, validate: func(t *testing.T, voteKey string) { - prop, exists := proposals.Get(strconv.Itoa(int(1))) + prop, exists := proposals.Get(formatUint64(1)) if !exists { t.Error("Proposal was not stored") return @@ -85,7 +84,7 @@ func TestVote(t *testing.T) { name: "Successful NO vote", setup: func() uint64 { pid := uint64(2) - proposals.Set(strconv.Itoa(int(pid)), ProposalInfo{ + proposals.Set(formatUint64(pid), ProposalInfo{ ConfigVersion: 1, State: ProposalState{ Created: true, @@ -102,7 +101,7 @@ func TestVote(t *testing.T) { yes: false, expectError: false, validate: func(t *testing.T, voteKey string) { - prop, exists := proposals.Get(strconv.Itoa(int(2))) + prop, exists := proposals.Get(formatUint64(2)) if !exists { t.Error("Proposal was not stored") return @@ -116,7 +115,7 @@ func TestVote(t *testing.T) { name: "Vote before voting period starts", setup: func() uint64 { pid := uint64(3) - proposals.Set(strconv.Itoa(int(pid)), ProposalInfo{ + proposals.Set(formatUint64(pid), ProposalInfo{ ConfigVersion: 1, State: ProposalState{ Created: true, @@ -134,7 +133,7 @@ func TestVote(t *testing.T) { name: "Vote on canceled proposal", setup: func() uint64 { pid := uint64(5) - proposals.Set(strconv.Itoa(int(pid)), ProposalInfo{ + proposals.Set(formatUint64(pid), ProposalInfo{ ConfigVersion: 1, State: ProposalState{ Created: true, @@ -153,7 +152,7 @@ func TestVote(t *testing.T) { name: "Double voting attempt", setup: func() uint64 { pid := uint64(6) - proposals.Set(strconv.Itoa(int(pid)), ProposalInfo{ + proposals.Set(formatUint64(pid), ProposalInfo{ ConfigVersion: 1, State: ProposalState{ Created: true,