Пример #1
0
        public override Empty AddProfits(AddProfitsInput input)
        {
            var profitItem = State.ProfitItemsMap[input.ProfitId];

            Assert(profitItem != null, "Profit item not found.");

            if (profitItem == null)
            {
                return(new Empty());
            }

            var virtualAddress = Context.ConvertVirtualAddressToContractAddress(input.ProfitId);

            if (input.Period == 0)
            {
                State.TokenContract.TransferFrom.Send(new TransferFromInput
                {
                    From   = Context.Sender,
                    To     = virtualAddress,
                    Symbol = profitItem.TokenSymbol,
                    Amount = input.Amount,
                    Memo   = $"Add dividends for {input.ProfitId}."
                });
                profitItem.TotalAmount += input.Amount;
                State.ProfitItemsMap[input.ProfitId] = profitItem;
            }
            else
            {
                var releasedProfitsVirtualAddress =
                    GetReleasedPeriodProfitsVirtualAddress(virtualAddress, input.Period);
                State.TokenContract.TransferFrom.Send(new TransferFromInput
                {
                    From   = Context.Sender,
                    To     = releasedProfitsVirtualAddress,
                    Symbol = profitItem.TokenSymbol,
                    Amount = input.Amount,
                    Memo   = $"Add dividends for {input.ProfitId} (period {input.Period})."
                });
                var releasedProfitsInformation = State.ReleasedProfitsMap[releasedProfitsVirtualAddress];
                if (releasedProfitsInformation == null)
                {
                    releasedProfitsInformation = new ReleasedProfitsInformation
                    {
                        ProfitsAmount = input.Amount
                    };
                }
                else
                {
                    releasedProfitsInformation.ProfitsAmount += input.Amount;
                }

                State.ReleasedProfitsMap[releasedProfitsVirtualAddress] = releasedProfitsInformation;
            }

            return(new Empty());
        }
Пример #2
0
        /// <summary>
        /// There should be at least one pre-condition to release profits if this is a sub profit item:
        /// Higher level profit item has already released.
        /// Otherwise this profit item maybe has nothing to release.
        /// This pre-condition should be met before calling this method.
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override Empty ReleaseProfit(ReleaseProfitInput input)
        {
            var profitItem = State.ProfitItemsMap[input.ProfitId];

            Assert(profitItem != null, "Profit item not found.");

            if (profitItem == null)
            {
                return(new Empty());
            }

            Assert(Context.Sender == profitItem.Creator, "Only creator can release profits.");

            // Update current_period.
            var releasingPeriod = profitItem.CurrentPeriod;

            Assert(input.Period == releasingPeriod, "Invalid period.");

            Assert(profitItem.TotalWeight > 0, "Invalid total weight.");

            var profitVirtualAddress = Context.ConvertVirtualAddressToContractAddress(input.ProfitId);

            var balance = State.TokenContract.GetBalance.Call(new GetBalanceInput
            {
                Owner  = profitVirtualAddress,
                Symbol = profitItem.TokenSymbol
            }).Balance;

            Assert(input.Amount <= balance, "Insufficient profits amount.");

            var profitsReceivingVirtualAddress =
                GetReleasedPeriodProfitsVirtualAddress(profitVirtualAddress, releasingPeriod);

            var releasedProfitInformation = State.ReleasedProfitsMap[profitsReceivingVirtualAddress];

            if (releasedProfitInformation == null)
            {
                releasedProfitInformation = new ReleasedProfitsInformation
                {
                    TotalWeight   = profitItem.TotalWeight,
                    ProfitsAmount = input.Amount,
                    IsReleased    = true
                };
            }
            else
            {
                releasedProfitInformation.TotalWeight    = profitItem.TotalWeight;
                releasedProfitInformation.ProfitsAmount += input.Amount;
                releasedProfitInformation.IsReleased     = true;
            }

            State.ReleasedProfitsMap[profitsReceivingVirtualAddress] = releasedProfitInformation;

            // Start releasing.

            var remainAmount = input.Amount;

            foreach (var subProfitItem in profitItem.SubProfitItems)
            {
                var subItemVirtualAddress = Context.ConvertVirtualAddressToContractAddress(subProfitItem.ProfitId);

                var amount = subProfitItem.Weight.Mul(input.Amount).Div(profitItem.TotalWeight);
                if (amount != 0)
                {
                    State.TokenContract.TransferFrom.Send(new TransferFromInput
                    {
                        From   = profitVirtualAddress,
                        To     = subItemVirtualAddress,
                        Amount = amount,
                        Symbol = profitItem.TokenSymbol
                    });
                }

                remainAmount -= amount;

                var subItem = State.ProfitItemsMap[subProfitItem.ProfitId];
                subItem.TotalAmount += amount;
                State.ProfitItemsMap[subProfitItem.ProfitId] = subItem;

                // Update current_period of detail of sub profit item.
                var subItemDetail = State.ProfitDetailsMap[input.ProfitId][subItemVirtualAddress];
                foreach (var detail in subItemDetail.Details)
                {
                    detail.LastProfitPeriod = profitItem.CurrentPeriod;
                }

                State.ProfitDetailsMap[input.ProfitId][subItemVirtualAddress] = subItemDetail;
            }

            if (remainAmount != 0)
            {
                State.TokenContract.TransferFrom.Send(new TransferFromInput
                {
                    From   = profitVirtualAddress,
                    To     = profitsReceivingVirtualAddress,
                    Amount = remainAmount,
                    Symbol = profitItem.TokenSymbol
                });
            }

            profitItem.CurrentPeriod            += 1;
            State.ProfitItemsMap[input.ProfitId] = profitItem;

            return(new Empty());
        }