Пример #1
0
        public void Stake(Address from, BigInteger stakeAmount)
        {
            Runtime.Expect(stakeAmount >= MinimumValidStake, "invalid amount");
            Runtime.Expect(IsWitness(from), "witness failed");

            var stakeBalances = new BalanceSheet(Nexus.StakingTokenSymbol);
            var balance       = stakeBalances.Get(this.Storage, from);

            var currentStake = _stakes.Get <Address, EnergyAction>(from);

            var newStake = stakeAmount + currentStake.totalAmount;

            Runtime.Expect(balance >= stakeAmount, "not enough balance");

            Runtime.Expect(stakeBalances.Subtract(this.Storage, from, stakeAmount), "balance subtract failed");
            Runtime.Expect(stakeBalances.Add(this.Storage, Runtime.Chain.Address, stakeAmount), "balance add failed");

            var entry = new EnergyAction()
            {
                unclaimedPartials = stakeAmount + GetLastAction(from).unclaimedPartials,
                totalAmount       = newStake,
                timestamp         = this.Runtime.Time,
            };

            _stakes.Set(from, entry);

            var logEntry = new VotingLogEntry()
            {
                timestamp = this.Runtime.Time,
                amount    = stakeAmount
            };

            var votingLogbook = _voteHistory.Get <Address, StorageList>(from);

            votingLogbook.Add(logEntry);

            var masterAccountThreshold = GetMasterThreshold();

            if (Runtime.Nexus.GenesisAddress != from && newStake >= masterAccountThreshold && !IsMaster(from))
            {
                var nextClaim = GetMasterClaimDate(2);

                _mastersList.Add(new EnergyMaster()
                {
                    address = from, claimDate = nextClaim
                });
                Runtime.Notify(EventKind.RolePromote, from, new RoleEventData()
                {
                    role = "master", date = nextClaim
                });
            }

            Runtime.Notify(EventKind.TokenStake, from, new TokenEventData()
            {
                chainAddress = Runtime.Chain.Address, symbol = Nexus.StakingTokenSymbol, value = stakeAmount
            });
        }
        private BigInteger CalculateEntryVotingPower(VotingLogEntry entry, Timestamp currentTime)
        {
            BigInteger baseMultiplier = 100;

            BigInteger votingMultiplier = baseMultiplier;
            var        diff             = (currentTime - entry.timestamp) / 86400;

            var votingBonus = diff < MaxVotingPowerBonus ? diff : MaxVotingPowerBonus;

            votingMultiplier += DailyVotingBonus * votingBonus;

            var votingPower = (entry.amount * votingMultiplier) / 100;

            return(votingPower);
        }