コード例 #1
0
        public void Abort(ulong proposalIndex)
        {
            var proposalQueue = GetProposalQueue();

            Assert(proposalIndex < (ulong)proposalQueue.Length, "Moloch::abort - proposal does not exist");
            Proposal proposal = proposalQueue[proposalIndex];

            Assert(Message.Sender == proposal.Applicant, "Moloch::abort - msg.sender must be applicant");
            Assert(GetCurrentPeriod() < proposal.StartingPeriod.Add(AbortWindow), "Moloch::abort - abort window must not have passed");
            Assert(!proposal.Aborted, "Moloch::abort - proposal must not have already been aborted");

            ulong tokensToAbort = proposal.TokenTribute;

            proposal.TokenTribute = 0;
            proposal.Aborted      = true;

            proposalQueue[proposalIndex] = proposal;
            SetProposalQueue(proposalQueue);

            // return all tokens to the applicant
            Assert(
                ApprovedStandardToken.TransferTo(proposal.Applicant, tokensToAbort),
                "Moloch::processProposal - failed to return tribute to applicant"
                );

            LogAbort(proposalIndex, Message.Sender);
        }
コード例 #2
0
        public void ProcessProposal(ulong proposalIndex)
        {
            var proposalQueue = GetProposalQueue();

            Assert(proposalIndex < (uint)proposalQueue.Length, "Moloch::processProposal - proposal does not exist");
            Proposal proposal = proposalQueue[proposalIndex];

            Assert(GetCurrentPeriod() >= proposal.StartingPeriod.Add(VotingPeriodLength).Add(GracePeriodLength), "Moloch::processProposal - proposal is not ready to be processed");
            Assert(proposal.Processed == false, "Moloch::processProposal - proposal has already been processed");
            Assert(proposalIndex == 0 || proposalQueue[proposalIndex.Sub(1)].Processed, "Moloch::processProposal - previous proposal must be processed");

            proposal.Processed   = true;
            TotalSharesRequested = TotalSharesRequested.Sub(proposal.SharesRequested);

            bool didPass = proposal.YesVotes > proposal.NoVotes;

            // Make the proposal fail if the dilutionBound is exceeded
            if (TotalShares.Mul(DilutionBound) < proposal.MaxTotalSharesAtYesVote)
            {
                didPass = false;
            }

            // PROPOSAL PASSED
            if (didPass && !proposal.Aborted)
            {
                proposal.DidPass = true;

                // todo: null check on many of the serialization getters and setters?
                // if the applicant is already a member, add to their existing shares
                if (GetMember(proposal.Applicant).Exists)
                {
                    var applicant = GetMember(proposal.Applicant);
                    applicant.Shares = applicant.Shares.Add(proposal.SharesRequested);

                    SetMember(proposal.Applicant, applicant);
                    // the applicant is a new member, create a new record for them
                }
                else
                {
                    // if the applicant address is already taken by a member's delegateKey, reset it to their member address
                    var delegateAddress = GetMemberAddressByDelegateKey(proposal.Applicant);
                    var applicant       = GetMember(delegateAddress);
                    if (applicant.Exists)
                    {
                        Address memberToOverride = delegateAddress;
                        SetMemberAddressByDelegateKey(memberToOverride, memberToOverride);
                        var member = GetMember(memberToOverride);
                        member.DelegateKey = memberToOverride;
                        SetMember(memberToOverride, member);
                    }

                    // use applicant address as delegateKey by default
                    SetMember(proposal.Applicant, new Member()
                    {
                        DelegateKey = proposal.Applicant, Shares = proposal.SharesRequested, Exists = true, HighestIndexYesVote = 0
                    });
                    SetMemberAddressByDelegateKey(proposal.Applicant, proposal.Applicant);
                }

                // mint new shares
                TotalShares = TotalShares.Add(proposal.SharesRequested);

                // transfer tokens to guild bank
                Assert(
                    ApprovedStandardToken.TransferTo(GuildBank.GetAddress(), proposal.TokenTribute),
                    "Moloch::processProposal - token transfer to guild bank failed"
                    );

                // PROPOSAL FAILED OR ABORTED
            }
            else
            {
                // return all tokens to the applicant
                Assert(
                    ApprovedStandardToken.TransferTo(proposal.Applicant, proposal.TokenTribute),
                    "Moloch::processProposal - failing vote token transfer failed"
                    );
            }

            // send msg.sender the processingReward
            Assert(
                ApprovedStandardToken.TransferTo(Message.Sender, ProcessingReward),
                "Moloch::processProposal - failed to send processing reward to msg.sender"
                );

            // return deposit to proposer (subtract processing reward)
            Assert(
                ApprovedStandardToken.TransferTo(proposal.Proposer, ProposalDeposit.Sub(ProcessingReward)),
                "Moloch::processProposal - failed to return proposal deposit to proposer"
                );

            LogProcessProposal(
                proposalIndex,
                proposal.Applicant,
                proposal.Proposer,
                proposal.TokenTribute,
                proposal.SharesRequested,
                didPass
                );
        }
コード例 #3
0
        public void SubmitProposal(
            Address applicant,
            ulong tokenTribute,
            ulong sharesRequested,
            string details)
        {
            AssertOnlyDelegate();

            Assert(applicant != Address.Zero, "Moloch::submitProposal - applicant cannot be 0");

            // Make sure we won't run into overflows when doing calculations with shares.
            // Note that totalShares + totalSharesRequested + sharesRequested is an upper bound
            // on the number of shares that can exist until this proposal has been processed.
            Assert(TotalShares.Add(TotalSharesRequested).Add(sharesRequested) <= MAX_NUMBER_OF_SHARES, "Moloch::submitProposal - too many shares requested");

            TotalSharesRequested = TotalSharesRequested.Add(sharesRequested);

            Address memberAddress = GetMemberAddressByDelegateKey(Message.Sender);

            // todo: correct equivalent of address(this)?
            // collect proposal deposit from proposer and store it in the Moloch until the proposal is processed
            Assert(ApprovedStandardToken.TransferFrom(Message.Sender, this.Address, ProposalDeposit), "Moloch::submitProposal - proposal deposit token transfer failed");

            // todo: correct equivalent of address(this)?
            // collect tribute from applicant and store it in the Moloch until the proposal is processed
            Assert(ApprovedStandardToken.TransferFrom(applicant, this.Address, tokenTribute), "Moloch::submitProposal - tribute token transfer failed");

            // compute startingPeriod for proposal
            ulong startingPeriod = Max(
                GetCurrentPeriod(),
                GetProposalQueueLength() == 0 ? 0 : GetProposalQueue()[GetProposalQueueLength().Sub(1)].StartingPeriod
                ).Add(1);

            // create proposal ...
            Proposal proposal = new Proposal()
            {
                Proposer                = memberAddress,
                Applicant               = applicant,
                SharesRequested         = sharesRequested,
                StartingPeriod          = startingPeriod,
                YesVotes                = 0,
                NoVotes                 = 0,
                Processed               = false,
                DidPass                 = false,
                Aborted                 = false,
                TokenTribute            = tokenTribute,
                Details                 = details,
                MaxTotalSharesAtYesVote = 0
            };

            // ... and append it to the queue
            var proposalQueue = GetProposalQueue();

            Array.Resize(ref proposalQueue, proposalQueue.Length + 1);
            proposalQueue[proposalQueue.GetUpperBound(0)] = proposal;

            SetProposalQueue(proposalQueue);

            ulong proposalIndex = ((ulong)proposalQueue.Length).Sub(1);

            LogSubmitProposal(proposalIndex, Message.Sender, memberAddress, applicant, tokenTribute, sharesRequested);
        }