Beispiel #1
0
        /// <summary>
        /// allow an administrator to request the unlocking of founder tokens
        /// </summary>
        /// <param name="address">founders script hash</param>
        /// <param name="roundNumber">1-7</param>
        /// <returns></returns>
        public static bool UnlockFoundersTokens(byte[] address, int roundNumber)
        {
            if (address.Length != 20)
            {
                Runtime.Log("UnlockFoundersTokens() invalid address supplied");
                return(false);
            }

            byte[]     roundKey       = address.Concat(((BigInteger)roundNumber).AsByteArray());
            StorageMap unlockedRounds = Storage.CurrentContext.CreateMap(StorageKeys.FounderTokenUnlockRound());

            bool roundPreviouslyUnlocked = unlockedRounds.Get(roundKey).AsBigInteger() > 0;

            if (roundPreviouslyUnlocked)
            {
                Runtime.Log("UnlockFoundersTokens() round already unlocked");
                return(false);
            }

            object[] foundersVestingPeriod = GetCoreTeamVestingSchedule();

            uint currentTimestamp = Helpers.GetBlockTimestamp();
            int  roundIndex       = (roundNumber * 2) - 2;
            int  roundValueIndex  = roundIndex + 1;

            if (roundIndex < 0)
            {
                Runtime.Log("UnlockFoundersTokens() invalid round index (<0)");
                return(false);
            }

            uint       roundReleaseDate   = (uint)foundersVestingPeriod[roundIndex];
            BigInteger roundReleaseAmount = (BigInteger)foundersVestingPeriod[roundValueIndex];

            if (currentTimestamp < roundReleaseDate)
            {
                Runtime.Log("UnlockFoundersTokens() not scheduled for release");
                return(false);
            }


            object[] founderKeys = ICOTemplate.MoonlightFounderKeys();
            for (int i = 0; i < founderKeys.Length; i++)
            {
                byte[] founderKey = (byte[])founderKeys[i];
                if (founderKey == address)
                {
                    Runtime.Notify("UnlockFoundersTokens() releasing funds. currentTimestamp / roundReleaseDate / roundReleaseAmount", currentTimestamp, roundReleaseDate, roundReleaseAmount);
                    Helpers.SetBalanceOf(founderKey, NEP5.BalanceOf(founderKey) + roundReleaseAmount);            // set new balance for destination account
                    unlockedRounds.Put(roundKey, "1");
                    return(true);
                }
            }
            return(false);
        }
Beispiel #2
0
        /// <summary>
        /// the core teams token allocation follow a linear quarterly maturation over 18 months beginning after 6 months
        /// </summary>
        /// <returns></returns>
        public static object[] GetCoreTeamVestingSchedule()
        {
            // calculate the allocation given to each team member
            object[]   founderKeys            = ICOTemplate.MoonlightFounderKeys();
            BigInteger founderTokenAllocation = ((ICOTemplate.TokenMaxSupply * (BigInteger)ICOTemplate.MoonlightFoundersAllocationPercentage()) / 100) * NEP5.factor;
            BigInteger individualAllocation   = founderTokenAllocation / founderKeys.Length;

            uint ContractInitTime = Helpers.GetContractInitTime();
            // determine vesting schedule details for core teams token allocation
            // there will be 7 releases, one each quarter ending 2 years from contract init
            int        numberOfTokenReleases = 7;
            BigInteger tokensPerRelease      = individualAllocation / numberOfTokenReleases;

            object[] vestingPeriod          = new object[14];
            object[] founderReleaseSchedule = ICOTemplate.MoonlightFoundersAllocationReleaseSchedule();
            uint     initialReleaseDate     = ContractInitTime + (uint)founderReleaseSchedule[0];
            uint     releaseFrequency       = (uint)founderReleaseSchedule[1];

            BigInteger tokensReleased = tokensPerRelease;

            // this is not the nicest way to populate the vesting schedule array, but it is much cheaper (in terms of processing/gas price) than looping
            vestingPeriod[0] = initialReleaseDate;
            vestingPeriod[1] = tokensPerRelease;
            // 3 months later release another batch of tokens
            tokensReleased  += tokensPerRelease;
            vestingPeriod[2] = initialReleaseDate + (releaseFrequency * 1);
            vestingPeriod[3] = tokensPerRelease;
            // 3 months later release another batch of tokens
            tokensReleased  += tokensPerRelease;
            vestingPeriod[4] = initialReleaseDate + (releaseFrequency * 2);
            vestingPeriod[5] = tokensPerRelease;
            // 3 months later release another batch of tokens
            tokensReleased  += tokensPerRelease;
            vestingPeriod[6] = initialReleaseDate + (releaseFrequency * 3);
            vestingPeriod[7] = tokensPerRelease;
            // 3 months later release another batch of tokens
            tokensReleased  += tokensPerRelease;
            vestingPeriod[8] = initialReleaseDate + (releaseFrequency * 4);
            vestingPeriod[9] = tokensPerRelease;
            // 3 months later release another batch of tokens
            tokensReleased   += tokensPerRelease;
            vestingPeriod[10] = initialReleaseDate + (releaseFrequency * 5);
            vestingPeriod[11] = tokensPerRelease;
            // 3 months later release the last of the tokens
            vestingPeriod[12] = initialReleaseDate + (releaseFrequency * 6);
            vestingPeriod[13] = individualAllocation - tokensReleased;

            /*
             * Runtime.Notify("VestingSchedule", Helpers.SerializeArray(vestingPeriod));
             * a serialised copy of this array ends up with values such as (dates subject to change):
             *  0e
             *  04 292cf05b          5bf02c29            1542466601         Saturday, November 17, 2018 2:56:41 PM
             *  07 6ddb810adb0301    0103db0a81db6d      285714285714285
             *  04 0979685c	         5c687909            1550350601         Saturday, February 16, 2019 8:56:41 PM
             *  07 dab60315b60702    0207b61503b6da      571428571428570
             *  04 e9c5e05c          5ce0c5e9            1558234601         Sunday, May 19, 2019 2:56:41 AM
             *  07 4792851f910b03    030b911f859247      857142857142855
             *  04 c912595d          5d5912c9            1566118601         Sunday, August 18, 2019 8:56:41 AM
             *  07 b46d072a6c0f04    040f6c2a076db4      1142857142857140
             *  04 a95fd15d          5dd15fa9            1574002601         Sunday, November 17, 2019 2:56:41 PM
             *  07 21498934471305    05134734894921      1428571428571425
             *  04 89ac495e          5e49ac89            1581886601         Sunday, February 16, 2020 8:56:41 PM
             *  07 8e240b3f221706    0617223f0b248e      1714285714285710
             *  04 69f9c15e          5ec1f969            1589770601         Monday, May 18, 2020 2:56:41 AM
             *  07 00008d49fd1a07    071afd498d0000      2000000000000000
             */
            return(vestingPeriod);
        }