diff --git a/ICOTemplate/ICOTemplate.cs b/ICOTemplate/ICOTemplate.cs
index 09fa416..4d3c6bc 100644
--- a/ICOTemplate/ICOTemplate.cs
+++ b/ICOTemplate/ICOTemplate.cs
@@ -187,7 +187,7 @@ public class ICOTemplate : Framework.SmartContract
/// list NEPs supported by this contract
///
///
- public static string SupportedStandards() => "{\"NEP-5\", \"NEP-10\"}";
+ public static string[] SupportedStandards() => new string[] { "NEP-5", "NEP-10" };
///
/// should whitelisting of TransferFrom transfer/transferFrom methods be checked
@@ -209,11 +209,14 @@ 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"))
+
+ // test if a nep5 method is being invoked
+ foreach (string nepMethod in NEP5.GetNEP5Methods())
{
- Runtime.Log("Smart Contract not Initialised");
- return false;
+ if (nepMethod == operation)
+ {
+ return NEP5.HandleNEP5Operation(operation, args, ExecutionEngine.CallingScriptHash, ExecutionEngine.EntryScriptHash);
+ }
}
if (operation == "admin" && Helpers.VerifyIsAdminAccount())
@@ -230,24 +233,6 @@ public static object Main(string operation, params object[] 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())
{
@@ -257,16 +242,6 @@ public static object Main(string operation, params object[] 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)
{
@@ -274,12 +249,8 @@ public static object Main(string operation, params object[] args)
{
return true;
}
-
- // test if this transaction is allowed
- object[] transactionData = Helpers.GetTransactionAndSaleData();
- return TokenSale.CanUserParticipateInSale(transactionData);
}
-
+
return false;
}
diff --git a/ICOTemplate/ICOTemplate.csproj b/ICOTemplate/ICOTemplate.csproj
index f96e6ac..c4bd5ef 100644
--- a/ICOTemplate/ICOTemplate.csproj
+++ b/ICOTemplate/ICOTemplate.csproj
@@ -32,8 +32,8 @@
4
-
- ..\packages\Neo.SmartContract.Framework.2.7.3\lib\net40\Neo.SmartContract.Framework.dll
+
+ ..\packages\Neo.SmartContract.Framework.2.9.3.1\lib\net40\Neo.SmartContract.Framework.dll
@@ -47,9 +47,7 @@
-
-
diff --git a/ICOTemplate/Token/Administration.cs b/ICOTemplate/Token/Administration.cs
index b58d3c4..648ef7e 100644
--- a/ICOTemplate/Token/Administration.cs
+++ b/ICOTemplate/Token/Administration.cs
@@ -16,7 +16,6 @@ public class Administration : Framework.SmartContract
"LockPrivateSaleAllocation",
"ContractMigrate",
"EnableTransferFromWhitelisting",
- "InitSmartContract",
"UpdateAdminAddress",
"WhitelistTransferFromAdd",
"WhitelistTransferFromRemove",
@@ -72,8 +71,6 @@ public static object HandleAdministrationOperation(string operation, params obje
return false;
}
return ContractMigrate(args);
- case "InitSmartContract":
- return InitSmartContract();
case "LockPrivateSaleAllocation":
return LockPrivateSaleAllocation();
case "UpdateAdminAddress":
@@ -153,51 +150,11 @@ public static bool LockPrivateSaleAllocation()
///
public static bool ContractMigrate(object[] args)
{
- // Contract Migrate(byte[] script, byte[] parameter_list, byte return_type, bool need_storage, string name, string version, string author, string email, string description)
- Contract.Migrate((byte[])args[1], (byte[])args[2], (byte)args[3], (bool)args[4], (string)args[5], (string)args[6], (string)args[7], (string)args[8], (string)args[9]);
+ // Contract Migrate(byte[] script, byte[] parameter_list, byte return_type, ContractPropertyState (using storage), string name, string version, string author, string email, string description)
+ Contract.Migrate((byte[])args[1], (byte[])args[2], (byte)args[3], (ContractPropertyState)args[4], (string)args[5], (string)args[6], (string)args[7], (string)args[8], (string)args[9]);
return true;
}
-
- ///
- /// initialise the smart contract for use
- ///
- ///
- public static bool InitSmartContract()
- {
- if (Helpers.ContractInitialised())
- {
- // contract can only be initialised once
- Runtime.Log("InitSmartContract() contract already initialised");
- return false;
- }
-
-
- uint ContractInitTime = Helpers.GetBlockTimestamp();
- Storage.Put(Storage.CurrentContext, StorageKeys.ContractInitTime(), ContractInitTime);
-
- // assign pre-allocated tokens to the NosProjectKey() (10,000,000 tokens)
- BigInteger immediateProjectAllocationValue = ICOTemplate.ImmediateCompanyReserve() * NEP5.factor;
-
-
- Helpers.SetBalanceOf(ICOTemplate.NosProjectKey, immediateProjectAllocationValue);
- transfer(null, ICOTemplate.NosProjectKey, immediateProjectAllocationValue);
-
- // token allocated to private sale & vested reserves & incentives
- BigInteger presaleAllocationMaxValue = ICOTemplate.LockedTokenAllocationAmount() * NEP5.factor;
-
- // update the total supply to reflect the project allocated tokens
- BigInteger totalSupply = immediateProjectAllocationValue + presaleAllocationMaxValue;
- Helpers.SetTotalSupply(totalSupply);
-
- UpdateAdminAddress(ICOTemplate.InitialAdminAccount);
-
- EnableTransferFromWhitelisting(ICOTemplate.WhitelistTransferFromListings());
-
- Runtime.Log("InitSmartContract() contract initialisation complete");
- return true;
- }
-
-
+
///
/// allow the contract administrator to update the admin address
///
diff --git a/ICOTemplate/Token/EthSale.cs b/ICOTemplate/Token/EthSale.cs
deleted file mode 100644
index 9c96e6d..0000000
--- a/ICOTemplate/Token/EthSale.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-using Neo.SmartContract.Framework;
-using Neo.SmartContract.Framework.Services.Neo;
-using System;
-using System.ComponentModel;
-using System.Numerics;
-
-namespace Neo.SmartContract
-{
- public class EthSale : Framework.SmartContract
- {
-
- [DisplayName("transfer")]
- public static event Action transfer;
-
- [DisplayName("refundEth")]
- public static event Action refundEth;
-
- ///
- /// MintTokensEth is called when a the ETH contribution listener server triggers an Ether receive event
- ///
- ///
- 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;
- }
-
- ///
- /// determine if ETH user can participate in the token sale
- ///
- ///
- ///
- public static bool CanETHUserParticipateInSale(object[] transactionData)
- {
- Transaction tx = (Transaction)transactionData[0];
- byte[] sender = (byte[])transactionData[1];
- byte[] receiver = (byte[])transactionData[2];
- string ethAddress = (string)transactionData[3];
- ulong receivedETH = (ulong)transactionData[4];
- BigInteger whiteListGroupNumber = (BigInteger)transactionData[5];
- BigInteger crowdsaleAvailableAmount = (BigInteger)transactionData[6];
- BigInteger groupMaximumContribution = (BigInteger)transactionData[7];
- BigInteger totalTokensPurchased = (BigInteger)transactionData[8];
- BigInteger totalContributionBalance = (BigInteger)transactionData[9];
-
- if (whiteListGroupNumber <= 0)
- {
- Runtime.Notify("CanUserParticipate() sender is not whitelisted", sender);
- return false;
- }
-
- if (!KYC.GroupParticipationIsUnlocked((int)whiteListGroupNumber))
- {
- Runtime.Notify("CanUserParticipate() sender cannot participate yet", sender);
- return false;
- }
-
- if (crowdsaleAvailableAmount <= 0)
- {
- // total supply has been exhausted
- Runtime.Notify("CanUserParticipate() crowdsaleAvailableAmount is <= 0", crowdsaleAvailableAmount);
- return false;
- }
-
- if (totalContributionBalance > groupMaximumContribution)
- {
- // don't allow this purchase exceed the group cap
- Runtime.Notify("CanUserParticipate() senders purchase in ETH will exceed maxContribution cap", sender, totalContributionBalance, groupMaximumContribution);
- return false;
- }
-
- return true;
- }
-
- }
-}
\ No newline at end of file
diff --git a/ICOTemplate/Token/Helpers.cs b/ICOTemplate/Token/Helpers.cs
index b1ba5cc..4c308c3 100644
--- a/ICOTemplate/Token/Helpers.cs
+++ b/ICOTemplate/Token/Helpers.cs
@@ -98,170 +98,7 @@ public static uint GetContractInitTime()
{
return (uint)Storage.Get(Storage.CurrentContext, StorageKeys.ContractInitTime()).AsBigInteger();
}
-
- ///
- /// retrieve information for the received transaction
- ///
- /// object[] {
- /// (Transaction)tx, (byte[])sender, (byte)receiver, ulong receivedNEO, ulong receivedGAS,
- /// (BigInteger)whiteListGroupNumber, (BigInteger)crowdsaleAvailableAmount, (BigInteger)groupMaximumContribution
- /// (BigInteger)totalTokensPurchased, (BigInteger)neoRemainingAfterPurchase, (BigInteger)gasRemainingAfterPurchase
- /// (BigInteger)totalContributionBalance
- /// }
- ///
- public static object[] GetTransactionAndSaleData()
- {
- Transaction tx = (Transaction)ExecutionEngine.ScriptContainer;
- TransactionOutput[] inputs = tx.GetReferences();
- TransactionOutput reference = inputs[0];
- TransactionOutput[] outputs = tx.GetOutputs();
- byte[] sender = reference.ScriptHash;
- byte[] receiver = ExecutionEngine.ExecutingScriptHash;
- ulong receivedNEO = 0;
- ulong receivedGAS = 0;
-
- foreach (var input in inputs)
- {
- // ensure that the provided inputs are valid
- if (input.ScriptHash == receiver)
- {
- throw new System.Exception();
- }
- }
-
- foreach (TransactionOutput output in outputs)
- {
- if (output.ScriptHash == receiver)
- {
- // only add funds to total received value if receiver is the recipient of the output
- ulong receivedValue = (ulong)output.Value;
- Runtime.Notify("GetTransactionData() Received Deposit type", receiver, reference.AssetId);
- if (reference.AssetId == NEP5.NEO)
- {
- receivedNEO += receivedValue;
- }
- else if (reference.AssetId == NEP5.GAS)
- {
- receivedGAS += receivedValue;
- }
- }
- }
-
- BigInteger whiteListGroupNumber = KYC.GetWhitelistGroupNumber(sender);
- BigInteger crowdsaleAvailableAmount = NEP5.CrowdsaleAvailableAmount();
- BigInteger groupMaximumContribution = KYC.GetGroupMaxContribution(whiteListGroupNumber) * NEP5.factor;
-
- BigInteger totalTokensPurchased = 0;
- BigInteger neoRemainingAfterPurchase = 0;
- BigInteger gasRemainingAfterPurchase = 0;
- BigInteger runningCrowdsaleAmount = crowdsaleAvailableAmount;
-
- if (ICOTemplate.ICOAllowsNEO() && receivedNEO > 0)
- {
- BigInteger neoTokenValue = receivedNEO * ICOTemplate.ICONeoToTokenExchangeRate();
- if (neoTokenValue > runningCrowdsaleAmount)
- {
- // the user is trying to purchase more tokens than are available
- // figure out how much NOS can be purchased without exceeding the cap
- neoRemainingAfterPurchase = (neoTokenValue - runningCrowdsaleAmount) / (ICOTemplate.ICONeoToTokenExchangeRate());
- totalTokensPurchased = runningCrowdsaleAmount;
- }
- else
- {
- // there is enough NOS left for this purchase to complete
- totalTokensPurchased = neoTokenValue;
- }
- // ensure amountAvailable now reflects number of tokens purchased with NEO
- runningCrowdsaleAmount -= totalTokensPurchased;
- }
-
- if (ICOTemplate.ICOAllowsGAS() && receivedGAS > 0)
- {
- BigInteger gasTokenValue = receivedGAS * ICOTemplate.ICOGasToTokenExchangeRate();
- if (gasTokenValue > runningCrowdsaleAmount)
- {
- // the user is trying to purchase more tokens than are available
- // figure out how much NOS can be purchased without exceeding the cap
- gasRemainingAfterPurchase = (gasTokenValue - runningCrowdsaleAmount) / (ICOTemplate.ICOGasToTokenExchangeRate());
- totalTokensPurchased = totalTokensPurchased + runningCrowdsaleAmount;
- }
- else
- {
- totalTokensPurchased = totalTokensPurchased + gasTokenValue;
- }
- }
-
- BigInteger totalContributionBalance = BalanceOfSaleContribution(sender) + totalTokensPurchased;
-
- return new object[] {
- tx, // neo transaction object
- sender, // who initiated the transfer
- receiver, // who the assets were sent to
- receivedNEO, // how many neo were transferred
- receivedGAS, // how many gas were transferred
- whiteListGroupNumber, // what whitelist group is the sender in
- crowdsaleAvailableAmount, // how many tokens are left to be purchased
- groupMaximumContribution, // how many tokens can members of this whitelist group purchase
- totalTokensPurchased, // the total number of tokens purchased in this transaction
- neoRemainingAfterPurchase, // how much neo is left after purchase of tokens
- gasRemainingAfterPurchase, // how much gas is left after purchase of tokens
- totalContributionBalance // the total amount of tokens sender has purchased during public sale
- };
- }
-
- ///
- /// retrieve information for the received transaction
- ///
- /// object[] {
- /// (Transaction)tx, (byte[])sender, (byte)receiver, ulong receivedNEO, ulong receivedGAS,
- /// (BigInteger)whiteListGroupNumber, (BigInteger)crowdsaleAvailableAmount, (BigInteger)groupMaximumContribution
- /// (BigInteger)totalTokensPurchased, (BigInteger)neoRemainingAfterPurchase, (BigInteger)gasRemainingAfterPurchase
- /// (BigInteger)totalContributionBalance
- /// }
- ///
- public static object[] GetEthTransactionAndSaleData(ulong receivedETH, string ethAddress, byte[] neoAddress)
- {
- Transaction tx = (Transaction)ExecutionEngine.ScriptContainer;
- byte[] sender = neoAddress;
- byte[] receiver = neoAddress;
-
- // only add funds to total received value if receiver is the recipient of the output
- Runtime.Notify("GetEthTransactionData() Received ETH Deposit type", receiver);
-
- BigInteger whiteListGroupNumber = KYC.GetWhitelistGroupNumber(sender);
- BigInteger crowdsaleAvailableAmount = NEP5.CrowdsaleAvailableAmount();
- BigInteger groupMaximumContribution = KYC.GetGroupMaxContribution(whiteListGroupNumber) * NEP5.factor;
-
- BigInteger totalTokensPurchased = 0;
-
- //ETH minimum must be 0.1 eth
- if (ICOTemplate.ICOAllowsETH() && receivedETH >= ICOTemplate.EthMinimumContribution())
- {
- //Get the amount of tokens in exchange for contributed ETH. receivedETH is with 18 decimals so divide by 1000000000000000000.
- BigInteger ethTokenValue = receivedETH * ICOTemplate.ICOEthToTokenExchangeRate() / 1000000000000000000;
-
- // there is enough NOS left for this purchase to complete
- totalTokensPurchased = ethTokenValue;
-
- // ensure amountAvailable now reflects number of tokens purchased with ETH
- }
-
- BigInteger totalContributionBalance = BalanceOfSaleContribution(sender) + (totalTokensPurchased * NEP5.factor);
-
- return new object[] {
- tx, // neo transaction object
- sender, // who initiated the transfer
- receiver, // who the assets were sent to
- ethAddress, // ETH address of contributor
- receivedETH, // how many neo were transferred
- whiteListGroupNumber, // what whitelist group is the sender in
- crowdsaleAvailableAmount, // how many tokens are left to be purchased
- groupMaximumContribution, // how many tokens can members of this whitelist group purchase
- totalTokensPurchased, // the total number of tokens purchased in this transaction
- totalContributionBalance // the total amount of tokens sender has purchased during public sale
- };
- }
-
+
///
/// test if a contract address is a whitelisted TransferFrom
///
diff --git a/ICOTemplate/Token/KYC.cs b/ICOTemplate/Token/KYC.cs
deleted file mode 100644
index 57449c0..0000000
--- a/ICOTemplate/Token/KYC.cs
+++ /dev/null
@@ -1,250 +0,0 @@
-using Neo.SmartContract.Framework;
-using Neo.SmartContract.Framework.Services.Neo;
-using System.Numerics;
-
-namespace Neo.SmartContract
-{
- public class KYC : Framework.SmartContract
- {
- public static string[] GetKYCMethods() => new string[] {
- "AddAddress",
- "crowdsale_status",
- "GetBlockHeight",
- "GetGroupMaxContribution",
- "GetGroupNumber",
- "GetGroupUnlockTime",
- "GroupParticipationIsUnlocked",
- "RevokeAddress",
- };
-
- public static object HandleKYCOperation(string operation, params object[] args)
- {
- // neo-compiler doesn't support switch blocks with too many case statements due to c# compiler optimisations
- // * IL_0004 Call System.UInt32 ::ComputeStringHash(System.String) ---> System.Exception: not supported on neovm now.
- // therefore, extra if statements required for more than 6 operations
- if (operation == "crowdsale_status")
- {
- // test if an address is whitelisted
- if (!Helpers.RequireArgumentLength(args, 1))
- {
- return false;
- }
- return AddressIsWhitelisted((byte[])args[0]);
- }
- else if (operation == "GetGroupNumber")
- {
- // allow people to check which group they have been assigned to during the whitelist process
- if (!Helpers.RequireArgumentLength(args, 1))
- {
- return false;
- }
- return GetWhitelistGroupNumber((byte[])args[0]);
- }
- else if (operation == "GroupParticipationIsUnlocked")
- {
- // allow people to check if their group is unlocked (bool)
- if (!Helpers.RequireArgumentLength(args, 1))
- {
- return false;
- }
- return GroupParticipationIsUnlocked((int)args[0]);
- } else if (operation == "GetBlockHeight")
- {
- // expose a method to retrieve current block height
- return Blockchain.GetHeight();
- }
-
- switch (operation)
- {
- case "AddAddress":
- // add an address to the kyc whitelist
- if (!Helpers.RequireArgumentLength(args, 2))
- {
- return false;
- }
- return AddAddress((byte[])args[0], (int)args[1]);
- case "GetGroupMaxContribution":
- // get the maximum amount of NOS that can be purchased for group
- if (!Helpers.RequireArgumentLength(args, 1))
- {
- return false;
- }
- return GetGroupMaxContribution((BigInteger)args[0]);
- case "GetGroupUnlockTime":
- // allow people to check the block height their group will be unlocked (uint)
- if (!Helpers.RequireArgumentLength(args, 1))
- {
- return false;
- }
- return GetGroupUnlockTime((BigInteger)args[0]);
- case "RevokeAddress":
- // remove an address to the kyc whitelist
- if (!Helpers.RequireArgumentLength(args, 1))
- {
- return false;
- }
- return RevokeAddress((byte[])args[0]);
-
- }
-
- return false;
- }
-
- ///
- /// add an address to the kyc whitelist
- ///
- ///
- public static bool AddAddress(byte[] address, int groupNumber)
- {
- if (address.Length != 20 || groupNumber <= 0 || groupNumber > 4)
- {
- return false;
- }
-
- if (Helpers.VerifyWitness(ICOTemplate.KycMiddlewareKey))
- {
- StorageMap kycWhitelist = Storage.CurrentContext.CreateMap(StorageKeys.KYCWhitelistPrefix());
- kycWhitelist.Put(address, groupNumber);
- return true;
- }
- return false;
- }
-
- ///
- /// determine if the given address is whitelisted by testing if group number > 0
- ///
- ///
- ///
- public static bool AddressIsWhitelisted(byte[] address)
- {
- if (address.Length != 20)
- {
- return false;
- }
-
- BigInteger whitelisted = GetWhitelistGroupNumber(address);
- return whitelisted > 0;
- }
-
- ///
- /// get the maximum number of NOS that can be purchased by groupNumber during the public sale
- ///
- ///
- ///
- public static BigInteger GetGroupMaxContribution(BigInteger groupNumber)
- {
- BigInteger maxContribution = 0;
- uint latestTimeStamp = Helpers.GetBlockTimestamp();
- uint publicSaleMaxContribution = (uint)ICOTemplate.MaximumContributionAmount();
- uint publicSaleEndTime = (uint)ICOTemplate.PublicSaleEndTime();
-
- //If latest block timestamp is larger than presale start and smaller than presale end: check presale tier contributions.
- if (latestTimeStamp >= (uint)ICOTemplate.PresaleStartTime() && latestTimeStamp <= (uint)ICOTemplate.PresaleEndTime())
- {
- //Presale has not ended. Only presale can participate.
- if (groupNumber == 1)
- {
- //Pre-sale tier 1.
- maxContribution = (uint)ICOTemplate.PresaleTierOne();
- }
- else if (groupNumber == 2)
- {
- //Pre-sale tier 2.
- maxContribution = (uint)ICOTemplate.PresaleTierTwo();
- }
- else if (groupNumber == 3)
- {
- //Pre-sale tier 3.
- maxContribution = (uint)ICOTemplate.PresaleTierThree();
- }
- else if(groupNumber == 4)
- {
- //Tier 4
- maxContribution = (uint)ICOTemplate.PresaleTierFour();
- }
- }
- //Otherwise we're in the public sale; get the publicSaleMaxContribution
- //publicSaleMaxContribution returns the max contribution based on the presale phase using Helpers.GetPublicSaleMaxContribution()
- else if (groupNumber > 0 && groupNumber <= 4 && latestTimeStamp >= (uint)ICOTemplate.PublicSaleStartTime() && latestTimeStamp <= publicSaleEndTime)
- {
- maxContribution = publicSaleMaxContribution;
- }
-
- return maxContribution;
- }
-
- ///
- /// helper method to retrieve the stored group unlock block height
- ///
- ///
- ///
- public static uint GetGroupUnlockTime(BigInteger groupNumber)
- {
- BigInteger unlockTime = 0;
-
- if (groupNumber <= 0 || groupNumber > 4)
- {
- return 0;
- }
- else if (groupNumber > 0 && groupNumber <= 4)
- {
- unlockTime = (uint)ICOTemplate.PresaleStartTime();
- }
- return (uint)unlockTime;
- }
-
- ///
- /// retrieve the group number the whitelisted address is in
- ///
- ///
- ///
- public static BigInteger GetWhitelistGroupNumber(byte[] address)
- {
- if (address.Length != 20)
- {
- return 0;
- }
-
- StorageMap kycWhitelist = Storage.CurrentContext.CreateMap(StorageKeys.KYCWhitelistPrefix());
- return kycWhitelist.Get(address).AsBigInteger();
- }
-
- ///
- /// determine if groupNumber is eligible to participate in public sale yet
- ///
- ///
- ///
- public static bool GroupParticipationIsUnlocked(int groupNumber)
- {
- if (groupNumber <= 0)
- {
- return false;
- }
-
- uint unlockBlockTime = GetGroupUnlockTime(groupNumber);
- return unlockBlockTime > 0 && unlockBlockTime <= Helpers.GetBlockTimestamp();
- }
-
- ///
- /// remove an address from the whitelist
- ///
- ///
- public static bool RevokeAddress(byte[] address)
- {
- if (address.Length != 20)
- {
- return false;
- }
-
- if (Helpers.VerifyWitness(ICOTemplate.KycMiddlewareKey))
- {
- StorageMap kycWhitelist = Storage.CurrentContext.CreateMap(StorageKeys.KYCWhitelistPrefix());
- kycWhitelist.Delete(address);
- return true;
- }
- return false;
- }
-
-
- }
-}
diff --git a/ICOTemplate/Token/NEP5.cs b/ICOTemplate/Token/NEP5.cs
index 5bc1d88..7a98d12 100644
--- a/ICOTemplate/Token/NEP5.cs
+++ b/ICOTemplate/Token/NEP5.cs
@@ -1,6 +1,5 @@
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
-using Neo.SmartContract.Framework.Services.System;
using System;
using System.ComponentModel;
using System.Numerics;
@@ -9,10 +8,6 @@ namespace Neo.SmartContract
{
public class NEP5 : Framework.SmartContract
{
- // define the global system assets NEO/GAS
- public static readonly byte[] NEO = { 155, 124, 255, 218, 166, 116, 190, 174, 15, 147, 14, 190, 96, 133, 175, 144, 147, 229, 254, 86, 179, 74, 92, 34, 12, 205, 207, 110, 252, 51, 111, 197 };
- public static readonly byte[] GAS = { 231, 45, 40, 105, 121, 238, 108, 177, 183, 230, 93, 253, 223, 178, 227, 132, 16, 11, 141, 20, 142, 119, 88, 222, 66, 228, 22, 139, 113, 121, 44, 96 };
-
///
/// NEP5.1 definition: number of decimals for this token - probably best to leave this as-is
///
@@ -34,8 +29,7 @@ public class NEP5 : Framework.SmartContract
///
public static string[] GetNEP5Methods() => new string[] {
"name", "symbol", "decimals", "totalSupply", "balanceOf",
- "transfer", "transferFrom", "approve", "allowance",
- "crowdsale_available_amount", "mintTokens"
+ "transfer", "transferFrom", "approve", "allowance"
};
[DisplayName("transfer")]
@@ -129,16 +123,6 @@ public static object HandleNEP5Operation(string operation, object[] args, byte[]
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;
}
@@ -264,12 +248,6 @@ public static BigInteger TotalSupply()
///
public static bool Transfer(byte[] from, byte[] to, BigInteger amount, byte[] caller, byte[] entry)
{
- if(Helpers.GetBlockTimestamp() < ICOTemplate.PublicSaleEndTime())
- {
- Runtime.Log("Transfer() not available before ICOTemplate.PublicSaleEndTime()");
- return false;
- }
-
if (caller != entry && !Helpers.IsContractWhitelistedTransferFrom(caller))
{
from = caller;
@@ -334,12 +312,6 @@ public static bool Transfer(byte[] from, byte[] to, BigInteger amount, byte[] ca
///
public static bool TransferFrom(byte[] originator, byte[] from, byte[] to, BigInteger amount, byte[] caller, byte[] entry)
{
- if (Helpers.GetBlockTimestamp() < ICOTemplate.PublicSaleEndTime())
- {
- Runtime.Log("TransferFrom() not available before ICOTemplate.PublicSaleEndTime()");
- return false;
- }
-
if (caller != entry && !Helpers.IsContractWhitelistedTransferFrom(caller))
{
originator = caller;
@@ -389,7 +361,7 @@ public static bool TransferFrom(byte[] originator, byte[] from, byte[] to, BigIn
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(originator), approvedTransferAmount - amount); // deduct transferred amount from allowance
+ Helpers.SetAllowanceAmount(from.Concat(to), approvedTransferAmount - amount); // deduct transferred amount from allowance
transfer(from, to, amount);
return true;
diff --git a/ICOTemplate/Token/TokenSale.cs b/ICOTemplate/Token/TokenSale.cs
index 5fbc546..811a3e4 100644
--- a/ICOTemplate/Token/TokenSale.cs
+++ b/ICOTemplate/Token/TokenSale.cs
@@ -9,126 +9,10 @@ namespace Neo.SmartContract
{
public class TokenSale : Framework.SmartContract
{
- [DisplayName("refund")]
- public static event Action refund;
-
-
-
[DisplayName("transfer")]
public static event Action transfer;
-
- ///
- /// determine if user can participate in the token sale yet
- ///
- ///
- ///
- public static bool CanUserParticipateInSale(object[] transactionData)
- {
- Transaction tx = (Transaction)transactionData[0];
- byte[] sender = (byte[])transactionData[1];
- byte[] receiver = (byte[])transactionData[2];
- ulong receivedNEO = (ulong)transactionData[3];
- ulong receivedGAS = (ulong)transactionData[4];
- BigInteger whiteListGroupNumber = (BigInteger)transactionData[5];
- BigInteger crowdsaleAvailableAmount = (BigInteger)transactionData[6];
- BigInteger groupMaximumContribution = (BigInteger)transactionData[7];
- BigInteger totalTokensPurchased = (BigInteger)transactionData[8];
- BigInteger neoRemainingAfterPurchase = (BigInteger)transactionData[9];
- BigInteger gasRemainingAfterPurchase = (BigInteger)transactionData[10];
- BigInteger totalContributionBalance = (BigInteger)transactionData[11];
-
- if (whiteListGroupNumber <= 0)
- {
- Runtime.Notify("CanUserParticipate() sender is not whitelisted", sender);
- return false;
- }
-
- if (!KYC.GroupParticipationIsUnlocked((int)whiteListGroupNumber))
- {
- Runtime.Notify("CanUserParticipate() sender cannot participate yet", sender);
- return false;
- }
-
- if (crowdsaleAvailableAmount <= 0)
- {
- // total supply has been exhausted
- Runtime.Notify("CanUserParticipate() crowdsaleAvailableAmount is <= 0", crowdsaleAvailableAmount);
- return false;
- }
-
- if (totalContributionBalance > groupMaximumContribution)
- {
- // don't allow this purchase exceed the group cap
- Runtime.Notify("CanUserParticipate() senders purchase will exceed maxContribution cap", sender, totalContributionBalance, groupMaximumContribution);
- refund(sender, receivedNEO, receivedGAS);
- return false;
- }
-
- return true;
- }
-
+
-
- ///
- /// mint tokens is called when a user wishes to purchase tokens
- ///
- ///
- public static bool MintTokens()
- {
- object[] transactionData = Helpers.GetTransactionAndSaleData();
- Transaction tx = (Transaction)transactionData[0];
- byte[] sender = (byte[])transactionData[1];
- byte[] receiver = (byte[])transactionData[2];
- ulong receivedNEO = (ulong)transactionData[3];
- ulong receivedGAS = (ulong)transactionData[4];
- BigInteger whiteListGroupNumber = (BigInteger)transactionData[5];
- BigInteger crowdsaleAvailableAmount = (BigInteger)transactionData[6];
- BigInteger groupMaximumContribution = (BigInteger)transactionData[7];
- BigInteger totalTokensPurchased = (BigInteger)transactionData[8];
- BigInteger neoRemainingAfterPurchase = (BigInteger)transactionData[9];
- BigInteger gasRemainingAfterPurchase = (BigInteger)transactionData[10];
- BigInteger totalContributionBalance = (BigInteger)transactionData[11];
-
- if (Helpers.GetBlockTimestamp() >= ICOTemplate.PublicSaleEndTime())
- {
- Runtime.Notify("MintTokens() failed. Token Sale is closed.", false);
- return false;
- }
-
- if (!CanUserParticipateInSale(transactionData))
- {
- Runtime.Notify("MintTokens() CanUserParticipate failed", false);
- return false;
- }
-
- byte[] lastTransactionHash = Storage.Get(Storage.CurrentContext, StorageKeys.MintTokensLastTX());
- if (lastTransactionHash == tx.Hash)
- {
- // ensure that minTokens doesnt process the same transaction more than once
- Runtime.Notify("MintTokens() not processing duplicate tx.Hash", tx.Hash);
- return false;
- }
-
- Storage.Put(Storage.CurrentContext, StorageKeys.MintTokensLastTX(), tx.Hash);
- Runtime.Notify("MintTokens() receivedNEO / receivedGAS", receivedNEO, receivedGAS);
-
- if (neoRemainingAfterPurchase > 0 || gasRemainingAfterPurchase > 0)
- {
- // this purchase would have exceed the allowed max supply so we spent what we could and will refund the remainder
- refund(sender, neoRemainingAfterPurchase, gasRemainingAfterPurchase);
- }
-
- BigInteger senderAmountSubjectToVesting = 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;
- }
-
///
/// set a vesting schedule, as defined in the whitepaper, for tokens purchased during the presale
///
diff --git a/ICOTemplate/packages.config b/ICOTemplate/packages.config
index eb70bff..93b0079 100644
--- a/ICOTemplate/packages.config
+++ b/ICOTemplate/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/packages/Neo.SmartContract.Framework.2.7.3/.signature.p7s b/packages/Neo.SmartContract.Framework.2.7.3/.signature.p7s
new file mode 100644
index 0000000..1a647b1
Binary files /dev/null and b/packages/Neo.SmartContract.Framework.2.7.3/.signature.p7s differ
diff --git a/packages/Neo.SmartContract.Framework.2.7.3/Neo.SmartContract.Framework.2.7.3.nupkg b/packages/Neo.SmartContract.Framework.2.7.3/Neo.SmartContract.Framework.2.7.3.nupkg
new file mode 100644
index 0000000..d0c2b59
Binary files /dev/null and b/packages/Neo.SmartContract.Framework.2.7.3/Neo.SmartContract.Framework.2.7.3.nupkg differ
diff --git a/packages/Neo.SmartContract.Framework.2.7.3/lib/net40/Neo.SmartContract.Framework.dll b/packages/Neo.SmartContract.Framework.2.7.3/lib/net40/Neo.SmartContract.Framework.dll
new file mode 100644
index 0000000..a68d531
Binary files /dev/null and b/packages/Neo.SmartContract.Framework.2.7.3/lib/net40/Neo.SmartContract.Framework.dll differ
diff --git a/packages/Neo.SmartContract.Framework.2.7.3/lib/netstandard1.6/Neo.SmartContract.Framework.dll b/packages/Neo.SmartContract.Framework.2.7.3/lib/netstandard1.6/Neo.SmartContract.Framework.dll
new file mode 100644
index 0000000..ea6c1c3
Binary files /dev/null and b/packages/Neo.SmartContract.Framework.2.7.3/lib/netstandard1.6/Neo.SmartContract.Framework.dll differ
diff --git a/packages/Neo.SmartContract.Framework.2.9.3.1/.signature.p7s b/packages/Neo.SmartContract.Framework.2.9.3.1/.signature.p7s
new file mode 100644
index 0000000..8b20d32
Binary files /dev/null and b/packages/Neo.SmartContract.Framework.2.9.3.1/.signature.p7s differ
diff --git a/packages/Neo.SmartContract.Framework.2.9.3.1/Neo.SmartContract.Framework.2.9.3.1.nupkg b/packages/Neo.SmartContract.Framework.2.9.3.1/Neo.SmartContract.Framework.2.9.3.1.nupkg
new file mode 100644
index 0000000..ef9de24
Binary files /dev/null and b/packages/Neo.SmartContract.Framework.2.9.3.1/Neo.SmartContract.Framework.2.9.3.1.nupkg differ
diff --git a/packages/Neo.SmartContract.Framework.2.9.3.1/lib/net40/Neo.SmartContract.Framework.dll b/packages/Neo.SmartContract.Framework.2.9.3.1/lib/net40/Neo.SmartContract.Framework.dll
new file mode 100644
index 0000000..8dea8d6
Binary files /dev/null and b/packages/Neo.SmartContract.Framework.2.9.3.1/lib/net40/Neo.SmartContract.Framework.dll differ
diff --git a/packages/Neo.SmartContract.Framework.2.9.3.1/lib/netstandard1.6/Neo.SmartContract.Framework.dll b/packages/Neo.SmartContract.Framework.2.9.3.1/lib/netstandard1.6/Neo.SmartContract.Framework.dll
new file mode 100644
index 0000000..f30ac97
Binary files /dev/null and b/packages/Neo.SmartContract.Framework.2.9.3.1/lib/netstandard1.6/Neo.SmartContract.Framework.dll differ