/// <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); }
/// <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); }
/// <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); }
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); }
/// <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); }
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()); }