diff --git a/gno/p/basedao/basedao.gno b/gno/p/basedao/basedao.gno index 631dfab3d..0cd2007a7 100644 --- a/gno/p/basedao/basedao.gno +++ b/gno/p/basedao/basedao.gno @@ -87,6 +87,7 @@ func New(conf *Config) *DAO { NewUnassignRoleHandler(dao), daokit.NewSetResourceHandler(dao.Core), daokit.NewRemoveResourceHandler(dao.Core), + daokit.NewExecuteLambdaHandler(), } { dao.Core.SetResource(&daokit.Resource{Handler: m, Condition: conf.InitialCondition}) } diff --git a/gno/p/basedao/basedao_test.gno b/gno/p/basedao/basedao_test.gno index 7de13d315..69e08670a 100644 --- a/gno/p/basedao/basedao_test.gno +++ b/gno/p/basedao/basedao_test.gno @@ -57,7 +57,7 @@ func TestNewDAO(t *testing.T) { } } - urequire.Equal(t, 7, dao.Core.ResourcesCount(), "expected 7 resources") + urequire.Equal(t, 8, dao.Core.ResourcesCount(), "expected 7 resources") urequire.Equal(t, dao.Realm.PkgPath(), daoRealm.PkgPath()) // XXX: check realm and profile @@ -754,10 +754,10 @@ func TestAddRemoveResource(t *testing.T) { Condition: daocond.MembersThreshold(0.2, tdao.dao.Members.IsMember, tdao.dao.Members.MembersCount), }), } - urequire.Equal(t, 8, tdao.dao.Core.ResourcesCount(), "expected 8 resources") + urequire.Equal(t, 9, tdao.dao.Core.ResourcesCount(), "expected 9 resources") std.TestSetOrigCaller(alice) tdao.dao.InstantExecute(addResourceProposal) - urequire.Equal(t, 9, tdao.dao.Core.ResourcesCount(), "expected 9 resources") + urequire.Equal(t, 10, tdao.dao.Core.ResourcesCount(), "expected 10 resources") removeResourceProposal := daokit.ProposalRequest{ Title: "My Proposal", @@ -770,7 +770,7 @@ func TestAddRemoveResource(t *testing.T) { tdao.dao.InstantExecute(removeResourceProposal) - urequire.Equal(t, 8, tdao.dao.Core.ResourcesCount(), "expected 8 resources") + urequire.Equal(t, 9, tdao.dao.Core.ResourcesCount(), "expected 9 resources") } func TestAddRemoveResourceInvalidateProposals(t *testing.T) { @@ -847,3 +847,39 @@ func TestAddRemoveResourceInvalidateProposals(t *testing.T) { return false }) } + +func TestAddCustomCallback(t *testing.T) { + members := []Member{ + { + alice.String(), + []string{"admin"}, + }, + { + bob.String(), + []string{"admin"}, + }, + } + tdao := newTestingDAO(t, 0.2, members) + + if !tdao.dao.Members.HasRole(bob.String(), "admin") { + t.Errorf("Expected member %s to have role 'admin'", bob.String()) + } + + std.TestSetOrigCaller(alice) + + if tdao.dao == nil { + t.Error("dao should still be alive") + } + + proposalKillSwitch := daokit.ProposalRequest{ + Message: daokit.NewExecuteLambdaMsg(func() { + tdao.dao = nil + }), + } + + tdao.dao.InstantExecute(proposalKillSwitch) + + if tdao.dao != nil { + t.Error("dao should have been killed") + } +} diff --git a/gno/p/daokit/messages.gno b/gno/p/daokit/messages.gno index ecfdd4922..582c35bc5 100644 --- a/gno/p/daokit/messages.gno +++ b/gno/p/daokit/messages.gno @@ -65,6 +65,22 @@ func (g *genericMessageHandler) Type() string { return g.kind } +const MsgExecuteLambdaKind = "gno.land/p/teritori/daokit.ExecuteLambda" + +func NewExecuteLambdaHandler() MessageHandler { + return NewMessageHandler(MsgExecuteLambdaKind, func(i interface{}) { + cb, ok := i.(func()) + if !ok { + panic(errors.New("invalid msg type")) + } + cb() + }) +} + +func NewExecuteLambdaMsg(cb func()) ExecutableMessage { + return NewMessage(MsgExecuteLambdaKind, cb) +} + const MsgSetResourceKind = "gno.land/p/teritori/daokit.SetResource" func NewSetResourceHandler(d *Core) MessageHandler { @@ -92,7 +108,7 @@ func NewRemoveResourceHandler(d *Core) MessageHandler { panic(errors.New("invalid payload type")) } if d.Resources.getResource(payload.Handler.Type()) == nil { - panic("ressource " + payload.Handler.Type() + " does not exists") + panic("resource " + payload.Handler.Type() + " does not exists") } d.Resources.removeResource(payload) d.ProposalModule.InvalidateWithResource(payload.Handler.Type())