Ejemplo n.º 1
0
        /// <summary>
        /// allow allocation of presale purchases by contract administrator. this allows the moonlight team to allocate the 25% of LX tokens sold in the private presale.
        /// as we accepted ETH in addition to NEO&GAS, using a mintTokens method here is not practical.
        /// 1. this method will not allow the presale allocation to exceed the defined amount
        /// 2. this method is permanently disabled once the method `LockPresaleAllocation` has been called.
        /// 3. the state of the `LockPresaleAllocation` can be determined by the public using the method `IsPresaleAllocationLocked` (returns timestamp that lock was put in place)
        /// </summary>
        /// <param name="address"></param>
        /// <param name="amountPurchased"></param>
        /// <returns></returns>
        public static bool AllocatePresalePurchase(byte[] address, BigInteger amountPurchased)
        {
            bool presaleLocked = Storage.Get(Storage.CurrentContext, StorageKeys.PresaleAllocationLocked()).AsBigInteger() > 0;

            if (presaleLocked)
            {
                Runtime.Notify("AllocatePresalePurchase() presaleLocked, can't allocate");
                return(false);
            }

            BigInteger presaleAllocationMaxValue = ((ICOContract.TokenMaxSupply * (BigInteger)ICOContract.PresaleAllocationPercentage()) / 100) * NEP5.factor;
            BigInteger presaleAllocatedValue     = Storage.Get(Storage.CurrentContext, StorageKeys.PresaleAllocatedValue()).AsBigInteger();

            if ((presaleAllocatedValue + amountPurchased) > presaleAllocationMaxValue)
            {
                // this purchase will exceed the presale cap.. dont allow
                Runtime.Notify("AllocatePresalePurchase() purchase will exceed presale max allocation");
                return(false);
            }

            TokenSale.SetVestingPeriodForAddress(address, amountPurchased);
            Storage.Put(Storage.CurrentContext, StorageKeys.PresaleAllocatedValue(), presaleAllocatedValue + amountPurchased);
            Runtime.Notify("AllocatePresalePurchase() tokens allocated", address, amountPurchased);

            return(true);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Claims unsold tokens
        /// </summary>
        /// <returns></returns>
        public static bool ClaimUnsoldTokens()
        {
            bool UnsoldTokensClaimed = Storage.Get(Storage.CurrentContext, StorageKeys.UnsoldTokensClaimed()).AsString() == "1";

            //This method can only be executed by the admin account, after the public sale, and can only be called once (use UnsoldTokensClaimed() storage item)
            if (Helpers.GetBlockTimestamp() >= ICOTemplate.PublicSaleEndTime() && UnsoldTokensClaimed == false && Helpers.VerifyIsAdminAccount())
            {
                byte[] address = ICOTemplate.AdditionalCompanyTokenFund;

                //Get amount remaining
                BigInteger amountRemaining = NEP5.CrowdsaleAvailableAmount();

                //Add vested amount to account
                TokenSale.SetVestingPeriodForAddress(address, "company", amountRemaining);

                //Set total supply
                Helpers.SetTotalSupply(amountRemaining);

                //Set the UnsoldTokensClaimed() storage item so ClaimUnsoldTokens() cannot be called again
                Storage.Put(Storage.CurrentContext, StorageKeys.UnsoldTokensClaimed(), "1");

                transfer(null, address, amountRemaining);

                Runtime.Notify("ClaimUnsoldTokens() tokens allocated", address, amountRemaining);

                return(true);
            }

            return(false);
        }
Ejemplo n.º 3
0
        ///<remarks>
        /// END user configurable fields
        ///</remarks>

        /// <summary>
        /// the entry point for smart contract execution
        /// </summary>
        /// <param name="operation">string to determine execution operation performed</param>
        /// <param name="args">optional arguments, context specific depending on operation</param>
        /// <returns></returns>
        public static object Main(string operation, params object[] args)
        {
            if (Runtime.Trigger == TriggerType.Application)
            {
                // test if a nep5 method is being invoked
                foreach (string nepMethod in NEP5.GetNEP5Methods())
                {
                    if (nepMethod == operation)
                    {
                        return(NEP5.HandleNEP5Operation(operation, args, ExecutionEngine.CallingScriptHash, ExecutionEngine.EntryScriptHash));
                    }
                }

                // test if a kyc method is being invoked
                foreach (string kycMethod in KYC.GetKYCMethods())
                {
                    if (kycMethod == operation)
                    {
                        return(KYC.HandleKYCOperation(operation, args));
                    }
                }

                // test if a helper/misc method is being invoked
                foreach (string helperMethod in Helpers.GetHelperMethods())
                {
                    if (helperMethod == operation)
                    {
                        return(Helpers.HandleHelperOperation(operation, args));
                    }
                }

                if (operation == "admin" && Helpers.VerifyIsAdminAccount())
                {
                    // allow access to administration methods
                    string adminOperation = (string)args[0];
                    foreach (string adminMethod in Administration.GetAdministrationMethods())
                    {
                        if (adminMethod == adminOperation)
                        {
                            return(Administration.HandleAdministrationOperation(adminOperation, args));
                        }
                    }
                    return(false);
                }
            }
            else if (Runtime.Trigger == TriggerType.Verification)
            {
                if (Helpers.VerifyIsAdminAccount())
                {
                    return(true);
                }

                // test if this transaction is allowed
                object[] transactionData = Helpers.GetTransactionAndSaleData();
                return(TokenSale.CanUserParticipateInSale(transactionData));
            }

            return(false);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// transfer an amount from the "from" account to the "to" acount if the "spender" has been approved to transfer the requested amount.
        /// </summary>
        /// <param name="spender"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="amount"></param>
        /// <param name="caller"></param>
        /// <param name="entry"></param>
        /// <returns></returns>
        public static bool TransferFrom(byte[] spender, byte[] from, byte[] to, BigInteger amount, byte[] caller, byte[] entry)
        {
            if (caller != entry && !Helpers.IsContractWhitelistedDEX(caller))
            {
                spender = caller;
            }

            if (spender.Length != 20 || from.Length != 20 || to.Length != 20)
            {
                Runtime.Log("TransferFrom() (originator|from|to).Length != 20");
                return(false);
            }

            if (amount < 0 || from == to)
            {
                Runtime.Log("TransferFrom() invalid transfer amount must be >= 0");
                throw new Exception();
            }

            BigInteger approvedTransferAmount = Allowance(from, spender);    // how many tokens is the spender authorised to transfer from the "from" account

            if (!Runtime.CheckWitness(spender))
            {
                // ensure transaction is signed properly by the request originator
                Runtime.Log("TransferFrom() CheckWitness failed");
                return(false);
            }

            //At this point, vesting is complete for all but founders and project.
            //Check if vesting applies and resolve.
            BigInteger recipientAmountSubjectToVesting = 0;
            BigInteger senderAmountSubjectToVesting    = 0;

            // reduce gas usage by only checking vesting criteria if the from address is a project or founders key
            if (Helpers.IsProjectKey(from))
            {
                senderAmountSubjectToVesting = TokenSale.SubjectToVestingPeriod(from);
            }

            BigInteger fromBalance = BalanceOfRaw(from);                  // retrieve balance of authorised account

            if (approvedTransferAmount < amount || fromBalance - senderAmountSubjectToVesting < amount)
            {
                // don't transfer if funds not available
                Runtime.Notify("TransferFrom() (authorisedAmount|fromBalance) < transferValue", approvedTransferAmount, fromBalance, amount);
                return(false);
            }

            BigInteger recipientBalance = BalanceOfRaw(to);

            BigInteger newBalance = fromBalance - amount;

            Helpers.SetBalanceOf(from, newBalance);                                            // remove balance from originating account
            Helpers.SetBalanceOf(to, recipientBalance + amount);                               // set new balance for destination account
            Helpers.SetAllowanceAmount(from.Concat(spender), approvedTransferAmount - amount); // deduct transferred amount from allowance

            transfer(from, to, amount);
            return(true);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// transfer an amount from the "from" account to the "to" acount if the "spender" has been approved to transfer the requested amount.
        /// </summary>
        /// <param name="spender"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="amount"></param>
        /// <param name="caller"></param>
        /// <param name="entry"></param>
        /// <returns></returns>
        public static bool TransferFrom(byte[] spender, byte[] from, byte[] to, BigInteger amount, byte[] caller, byte[] entry)
        {
            if (caller != entry && !Helpers.IsContractWhitelistedDEX(caller))
            {
                spender = caller;
            }

            if (spender.Length != 20 || from.Length != 20 || to.Length != 20)
            {
                Runtime.Log("TransferFrom() (spender|from|to).Length != 20");
                return(false);
            }

            if (amount < 0)
            {
                Runtime.Log("TransferFrom() invalid transfer amount must be >= 0");
                throw new Exception();
            }

            BigInteger approvedTransferAmount = Allowance(from, spender); // how many tokens is this address authorised to transfer
            BigInteger fromBalance            = BalanceOf(from);          // retrieve balance of authorised account

            if (approvedTransferAmount < amount || fromBalance < amount)
            {
                // don't transfer if funds not available
                Runtime.Notify("TransferFrom() (authorisedAmount|fromBalance) < transferValue", approvedTransferAmount, fromBalance, amount);
                return(false);
            }

            BigInteger senderAmountSubjectToVesting = TokenSale.SubjectToVestingPeriod(from);

            if (amount == 0 || from == to || fromBalance - senderAmountSubjectToVesting < amount)
            {
                // don't accept a meaningless value
                Runtime.Log("TransferFrom() empty transfer amount or from==to");
                transfer(from, to, amount);
                return(true);    // as per nep5 standard - return true when amount is 0 or from == to
            }

            if (!Runtime.CheckWitness(spender))
            {
                // ensure transaction is signed properly by the spender
                Runtime.Log("TransferFrom() CheckWitness failed");
                return(false);
            }

            BigInteger recipientBalance = BalanceOf(to);
            BigInteger recipientAmountSubjectToVesting = TokenSale.SubjectToVestingPeriod(to);

            BigInteger newBalance = fromBalance - amount;

            Helpers.SetBalanceOf(from, newBalance + senderAmountSubjectToVesting);                 // remove balance from originating account
            Helpers.SetBalanceOf(to, recipientBalance + recipientAmountSubjectToVesting + amount); // set new balance for destination account
            Helpers.SetAllowanceAmount(from.Concat(spender), approvedTransferAmount - amount);     // deduct transferred amount from allowance

            transfer(from, to, amount);
            return(true);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// NEP5: Transfer tokens from one account to another
        /// </summary>
        /// <param name="from">sender address</param>
        /// <param name="to">recipient address</param>
        /// <param name="amount">number of tokens to transfer</param>
        /// <param name="caller"></param>
        /// <param name="entry"></param>
        /// <returns></returns>
        public static bool Transfer(byte[] from, byte[] to, BigInteger amount, byte[] caller, byte[] entry)
        {
            if (caller != entry && !Helpers.IsContractWhitelistedDEX(caller))
            {
                from = caller;
            }

            if (from.Length != 20 || to.Length != 20)
            {
                Runtime.Log("Transfer() (from|to).Length != 20");
                return(false);
            }

            if (amount < 0 || from == to)
            {
                Runtime.Log("Transfer() invalid transfer amount must be >= 0");
                throw new Exception();
            }

            if (!Runtime.CheckWitness(from))
            {
                // ensure transaction is signed properly by the owner of the tokens
                Runtime.Log("Transfer() CheckWitness failed");
                return(false);
            }

            //At this point, vesting is complete for all but founders and project.
            //Check if vesting applies and resolve.
            BigInteger recipientAmountSubjectToVesting = 0;
            BigInteger senderAmountSubjectToVesting    = 0;

            // reduce gas usage by only checking vesting criteria if the from address is a project or founders key
            if (Helpers.IsProjectKey(from))
            {
                senderAmountSubjectToVesting = TokenSale.SubjectToVestingPeriod(from);
            }

            BigInteger fromBalance = BalanceOfRaw(from);                   // retrieve balance of originating account

            if (fromBalance - senderAmountSubjectToVesting < amount)
            {
                Runtime.Log("Transfer() fromBalance < transferValue");
                // don't transfer if funds not available
                return(false);
            }

            BigInteger recipientBalance = BalanceOfRaw(to);

            BigInteger newBalance = fromBalance - amount;

            Helpers.SetBalanceOf(from, newBalance);               // remove balance from originating account
            Helpers.SetBalanceOf(to, recipientBalance + amount);  // set new balance for destination account

            transfer(from, to, amount);
            return(true);
        }
Ejemplo n.º 7
0
Archivo: NEP5.cs Proyecto: Eluvade/DIVE
        public static bool Transfer(byte[] from, byte[] to, BigInteger amount, byte[] caller, byte[] entry)
        {
            if (caller != entry && !Helpers.IsContractWhitelistedDEX(caller))
            {
                from = caller;
            }

            if (from.Length != 20 || to.Length != 20)
            {
                Runtime.Log("Transfer() (from|to).Length != 20");
                return(false);
            }

            if (amount < 0)
            {
                Runtime.Log("Transfer() invalid transfer amount must be >= 0");
                throw new Exception();
            }

            BigInteger fromBalance = BalanceOf(from);                   // retrieve balance of originating account

            if (fromBalance < amount)
            {
                Runtime.Log("Transfer() fromBalance < transferValue");
                // don't transfer if funds not available
                return(false);
            }

            if (amount == 0 || from == to)
            {
                // don't accept a meaningless value
                Runtime.Log("Transfer() empty transfer amount or from==to");
                transfer(from, to, amount);
                return(true);    // as per nep5 standard - return true when amount is 0 or from == to
            }

            if (!Runtime.CheckWitness(from))
            {
                // ensure transaction is signed properly by the owner of the tokens
                Runtime.Log("Transfer() CheckWitness failed");
                return(false);
            }

            BigInteger recipientBalance = BalanceOf(to);
            BigInteger recipientAmountSubjectToVesting = TokenSale.SubjectToVestingPeriod(to);
            BigInteger senderAmountSubjectToVesting    = TokenSale.SubjectToVestingPeriod(from);

            BigInteger newBalance = fromBalance - amount;

            Helpers.SetBalanceOf(from, newBalance + senderAmountSubjectToVesting);                  // remove balance from originating account
            Helpers.SetBalanceOf(to, recipientBalance + recipientAmountSubjectToVesting + amount);  // set new balance for destination account

            transfer(from, to, amount);
            return(true);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// MintTokensEth is called when a the ETH contribution listener server triggers an Ether receive event
        /// </summary>
        /// <returns></returns>
        public static bool MintTokensEth(string ethAddress, byte[] neoAddress, ulong ethReceived)
        {
            object[]    transactionData = Helpers.GetEthTransactionAndSaleData(ethReceived, ethAddress, neoAddress);
            Transaction tx = (Transaction)transactionData[0];

            byte[]     sender                   = (byte[])transactionData[1];
            byte[]     receiver                 = (byte[])transactionData[2];
            BigInteger whiteListGroupNumber     = (BigInteger)transactionData[5];
            BigInteger crowdsaleAvailableAmount = (BigInteger)transactionData[6];
            BigInteger groupMaximumContribution = (BigInteger)transactionData[7];
            BigInteger totalTokensPurchased     = (BigInteger)transactionData[8] * NEP5.factor;
            BigInteger totalContributionBalance = (BigInteger)transactionData[9];

            if (!CanETHUserParticipateInSale(transactionData))
            {
                refundEth(ethAddress, ethReceived);
                Runtime.Notify("MintTokensEth() CanUserParticipate failed", false);
                return(false);
            }

            if (Helpers.GetBlockTimestamp() >= ICOTemplate.PublicSaleEndTime())
            {
                refundEth(ethAddress, ethReceived);
                Runtime.Notify("MintTokensEth() failed. Token Sale is closed.", false);
                return(false);
            }

            byte[] lastTransactionHash = Storage.Get(Storage.CurrentContext, StorageKeys.MintTokensEthLastTX());
            if (lastTransactionHash == tx.Hash)
            {
                // ensure that minTokens doesnt process the same transaction more than once
                Runtime.Notify("MintTokensEth() not processing duplicate tx.Hash", tx.Hash);
                return(false);
            }

            BigInteger tokenTotalSupply = NEP5.TotalSupply();

            Storage.Put(Storage.CurrentContext, StorageKeys.MintTokensEthLastTX(), tx.Hash);
            Runtime.Notify("MintTokensEth() receivedETH", ethReceived);

            BigInteger senderAmountSubjectToVesting = TokenSale.SubjectToVestingPeriod(sender);
            BigInteger newTokenBalance = NEP5.BalanceOf(sender) + totalTokensPurchased + senderAmountSubjectToVesting;

            Helpers.SetBalanceOf(sender, newTokenBalance);
            Helpers.SetBalanceOfSaleContribution(sender, totalContributionBalance);
            Helpers.SetTotalSupply(totalTokensPurchased);

            transfer(null, sender, totalTokensPurchased);
            return(true);
        }
Ejemplo n.º 9
0
Archivo: NEP5.cs Proyecto: Eluvade/DIVE
        public static BigInteger BalanceOf(byte[] account)
        {
            if (account.Length != 20)
            {
                Runtime.Log("BalanceOf() invalid address supplied");
                return(0);
            }

            StorageMap balances = Storage.CurrentContext.CreateMap(StorageKeys.BalancePrefix());

            BigInteger amountSubjectToVesting = TokenSale.SubjectToVestingPeriod(account);
            BigInteger userBalance            = balances.Get(account).AsBigInteger() - amountSubjectToVesting;

            if (userBalance < 0)
            {
                userBalance = 0;
            }

            return(userBalance.AsByteArray().Concat(new byte[] { }).AsBigInteger());
        }
        /// <summary>
        /// allow allocation of presale purchases by contract administrator. this allows the nOS team to allocate the nOS tokens from the private sale, company reserve, and locked incentive reserve.
        /// This method will not allow the private allocations to exceed the defined amount
        /// the state of the `LockPrivateSaleAllocation` can be determined by the public using the method `IsPrivateSaleAllocationLocked` (returns timestamp that lock was put in place)
        /// </summary>
        /// <param name="address"></param>
        /// <param name="amountPurchased"></param>
        /// <returns></returns>
        public static bool AllocatePrivateSalePurchase(byte[] address, string allocationType, BigInteger amountPurchased)
        {
            amountPurchased = amountPurchased * NEP5.factor;

            bool privateSaleLocked = Storage.Get(Storage.CurrentContext, StorageKeys.PrivateSaleAllocationLocked()).AsBigInteger() > 0;

            if (privateSaleLocked)
            {
                Runtime.Notify("AllocatePrivateSalePurchase() privateSaleLocked, can't allocate");
                return(false);
            }

            if (allocationType != "incentive" && allocationType != "privateSale" && allocationType != "company")
            {
                return(false);
            }

            BigInteger presaleAllocationMaxValue = ICOTemplate.LockedTokenAllocationAmount() * NEP5.factor;
            BigInteger presaleAllocatedValue     = Storage.Get(Storage.CurrentContext, StorageKeys.PresaleAllocatedValue()).AsBigInteger();

            if ((presaleAllocatedValue + amountPurchased) > presaleAllocationMaxValue)
            {
                // this purchase will exceed the presale cap.. dont allow
                Runtime.Notify("AllocatePrivateSalePurchase() purchase will exceed max allocation");
                return(false);
            }

            if (!TokenSale.SetVestingPeriodForAddress(address, allocationType, amountPurchased))
            {
                Runtime.Notify("SetVestingPeriodForAddress() failed.");
                return(false);
            }

            Storage.Put(Storage.CurrentContext, StorageKeys.PresaleAllocatedValue(), presaleAllocatedValue + amountPurchased);
            transfer(null, address, amountPurchased);

            Runtime.Notify("AllocatePrivateSalePurchase() tokens allocated", address, amountPurchased, allocationType);

            return(true);
        }
Ejemplo n.º 11
0
        ///<remarks>
        /// END user configurable fields
        ///</remarks>

        /// <summary>
        /// the entry point for smart contract execution
        /// </summary>
        /// <param name="operation">string to determine execution operation performed</param>
        /// <param name="args">optional arguments, context specific depending on operation</param>
        /// <returns></returns>
        public static object Main(string operation, params object[] args)
        {
            if (Runtime.Trigger == TriggerType.Application)
            {
                //Only allow InitSmartContract if contract not initialized and not calling whitelist/KYC operations
                if(!Helpers.ContractInitialised() && ((operation != "admin" && (string) args[0] != "InitSmartContract") && operation != "AddAddress" && operation != "RevokeAddress" && operation != "GetGroupNumber" && operation != "crowdsale_status"))
                {
                    Runtime.Log("Smart Contract not Initialised");
                    return false;
                }

                if (operation == "admin" && Helpers.VerifyIsAdminAccount())
                {
                    // allow access to administration methods
                    string adminOperation = (string)args[0];
                    foreach (string adminMethod in Administration.GetAdministrationMethods())
                    {
                        if (adminMethod == adminOperation)
                        {
                            return Administration.HandleAdministrationOperation(adminOperation, args);
                        }
                    }
                    return false;
                }

                // test if a nep5 method is being invoked
                foreach (string nepMethod in NEP5.GetNEP5Methods())
                {
                    if (nepMethod == operation)
                    {
                        return NEP5.HandleNEP5Operation(operation, args, ExecutionEngine.CallingScriptHash, ExecutionEngine.EntryScriptHash);
                    }
                }

                // test if a kyc method is being invoked
                foreach (string kycMethod in KYC.GetKYCMethods())
                {
                    if (kycMethod == operation)
                    {
                        return KYC.HandleKYCOperation(operation, args);
                    }
                }

                // test if a helper/misc method is being invoked
                foreach (string helperMethod in Helpers.GetHelperMethods())
                {
                    if (helperMethod == operation)
                    {
                        return Helpers.HandleHelperOperation(operation, args);
                    }
                }

                //If MintTokensEth operation
                if(operation == "MintTokensEth")
                {
                    // Method can only be called by the ETH contributions listener account
                    if (Helpers.VerifyWitness(ICOTemplate.EthContributionListenerKey) && Helpers.RequireArgumentLength(args,3))
                    {
                        return EthSale.MintTokensEth((string)args[0], (byte[])args[1], (ulong)args[2]);
                    }
                }

            }
            else if (Runtime.Trigger == TriggerType.Verification)
            {
                if (Helpers.VerifyIsAdminAccount())
                {
                    return true;
                }

                // test if this transaction is allowed
                object[] transactionData = Helpers.GetTransactionAndSaleData();
                return TokenSale.CanUserParticipateInSale(transactionData);
            }

            return false;
        }
Ejemplo n.º 12
0
Archivo: NEP5.cs Proyecto: Eluvade/DIVE
        public static object HandleNEP5Operation(string operation, object[] args, byte[] caller, byte[] entry)
        {
            //{ "name", "symbol", "decimals", "totalSupply", "balanceOf", "transfer", "transferFrom", "approve", "allowance" };
            if (operation == "name")
            {
                // the name of the token
                return(DIVE.DIVE.name());
            }

            if (operation == "symbol")
            {
                // the symbol of the token
                return(DIVE.DIVE.symbol());
            }

            if (operation == "decimals")
            {
                // decimals to determine fractions of tokens
                return(DIVE.DIVE.decimals());
            }

            if (operation == "totalSupply")
            {
                // the total number of tokens minted
                return(TotalSupply());
            }

            if (operation == "balanceOf")
            {
                // retreive the balance of an address
                if (!Helpers.RequireArgumentLength(args, 1))
                {
                    // BalanceOf() requires at least 1 argument - the address to check the balance of
                    return(false);
                }

                return(BalanceOf((byte[])args[0]));
            }

            if (operation == "transfer")
            {
                // transfer tokens from one address to another
                if (!Helpers.RequireArgumentLength(args, 3))
                {
                    // Transfer() requires 3 arguments: from, to, amount
                    return(false);
                }

                return(Transfer((byte[])args[0], (byte[])args[1], (BigInteger)args[2], caller, entry));
            }


            if (operation == "transferFrom")
            {
                // transfer tokens from one address to another
                if (!Helpers.RequireArgumentLength(args, 4))
                {
                    // TransferFrom() requires 4 arguments: originator, from, to, amount
                    return(false);
                }

                return(TransferFrom((byte[])args[0], (byte[])args[1], (byte[])args[2], (BigInteger)args[3], caller, entry));
            }

            if (operation == "approve")
            {
                // approve a third party to transfer tokens from one address to another
                if (!Helpers.RequireArgumentLength(args, 3))
                {
                    // Approve() requires 3 arguments: originator, to, amount
                    return(false);
                }

                return(Approve((byte[])args[0], (byte[])args[1], (BigInteger)args[2], caller, entry));
            }

            if (operation == "allowance")
            {
                // retreive the authorised balance of an address
                if (!Helpers.RequireArgumentLength(args, 2))
                {
                    // Allowance() requires 2 arguments: from, to
                    return(false);
                }

                return(Allowance((byte[])args[0], (byte[])args[1]));
            }

            // check how many tokens left for purchase
            if (operation == "crowdsale_available_amount")
            {
                return(CrowdsaleAvailableAmount());
            }

            if (operation == "mintTokens")
            {
                return(TokenSale.MintTokens());
            }
            return(false);
        }
        public static object HandleAdministrationOperation(string operation, params object[] args)
        {
            if (operation == "WhitelistTransferFromRemove")
            {
                if (!Helpers.RequireArgumentLength(args, 2))
                {
                    return(false);
                }

                return(WhitelistTransferFromRemove((byte[])args[1]));
            }
            else if (operation == "WhitelistTransferFromAdd")
            {
                if (!Helpers.RequireArgumentLength(args, 2))
                {
                    return(false);
                }
                return(WhitelistTransferFromAdd((byte[])args[1]));
            }
            else if (operation == "EnableTransferFromWhitelisting")
            {
                if (!Helpers.RequireArgumentLength(args, 2))
                {
                    return(false);
                }
                EnableTransferFromWhitelisting((bool)args[1]);
            }
            else if (operation == "ClaimUnsoldTokens")
            {
                if (!Helpers.RequireArgumentLength(args, 1))
                {
                    return(false);
                }
                TokenSale.ClaimUnsoldTokens();
            }


            switch (operation)
            {
            case "AllocatePrivateSalePurchase":
                if (!Helpers.RequireArgumentLength(args, 4))
                {
                    return(false);
                }
                return(AllocatePrivateSalePurchase((byte[])args[1], (string)args[2], (BigInteger)args[3]));

            case "ContractMigrate":
                if (!Helpers.RequireArgumentLength(args, 10))
                {
                    return(false);
                }
                return(ContractMigrate(args));

            case "InitSmartContract":
                return(InitSmartContract());

            case "LockPrivateSaleAllocation":
                return(LockPrivateSaleAllocation());

            case "UpdateAdminAddress":
                if (!Helpers.RequireArgumentLength(args, 2))
                {
                    return(false);
                }
                return(UpdateAdminAddress((byte[])args[1]));
            }

            return(false);
        }