forked from neo-project/neo
-
Notifications
You must be signed in to change notification settings - Fork 1
RPX_ICO
tanyuan edited this page Aug 14, 2017
·
28 revisions
using Neo.SmartContract.Framework;
using Neo.SmartContract.Framework.Services.Neo;
using Neo.SmartContract.Framework.Services.System;
using System;
using System.Numerics;
namespace RPX
{
public class RPX : FunctionCode
{
public static Object Main(string operation, params object[] args)
{
string name = "RPX";
string symbol = "PRX";
BigInteger decimals = 8;
if (!VerifyWithdrawal(operation)) return false;
if(operation == "mintTokens") return MintTokens();
if(operation == "totalSupply") return TotalSupply();
if(operation == "name") return name;
if(operation == "symbol") return symbol;
if(operation == "transfer") return Transfer(args);
if(operation == "balanceOf") return BalanceOf(args);
if (operation == "deploy") return Deploy();
if (operation == "refund") return Refund();
if (operation == "withdrawal") return Withdrawal(args);
if (operation == "decimals") return decimals;
return false;
}
// initialization parameters, only once
// 初始化参数
private static bool Deploy()
{
byte[] owner = new byte[] { 2, 133, 234, 182, 95, 74, 1, 38, 228, 184, 91, 78, 93, 139, 126, 48, 58, 255, 126, 251, 54, 13, 89, 95, 46, 49, 137, 187, 144, 72, 122, 213, 170 };
BigInteger pre_ico_cap = 30000000;
uint decimals_rate = 100000000;
byte[] total_supply = Storage.Get(Storage.CurrentContext, "totalSupply");
if (total_supply.Length != 0)
{
return false;
}
Storage.Put(Storage.CurrentContext, owner, IntToBytes(pre_ico_cap * decimals_rate));
Storage.Put(Storage.CurrentContext, "totalSupply", IntToBytes(pre_ico_cap * decimals_rate));
return true;
}
// The function Withdrawal is only usable when contract owner want
// to transfer neo from contract
// 从智能合约提取neo币时,验证是是否是智能合约所有者
private static bool Withdrawal(object[] args)
{
if(args.Length != 1)
{
return false;
}
byte[] signature = (byte[])args[0];
byte[] owner = Storage.Get(Storage.CurrentContext, "owner");
return VerifySignature(owner, signature);
}
// The function MintTokens is only usable by the chosen wallet
// contract to mint a number of tokens proportional to the
// amount of neo sent to the wallet contract. The function
// can only be called during the tokenswap period
// 将众筹的neo转化为等价的prx tokens
private static bool MintTokens()
{
uint decimals_rate = 100000000;
byte[] neo_asset_id = new byte[] { 197, 111, 51, 252, 110, 207, 205, 12, 34, 92, 74, 179, 86, 254, 229, 147, 144, 175, 133, 96, 190, 14, 147, 15, 174, 190, 116, 166, 218, 255, 124, 155 };
Transaction trans = (Transaction)ExecutionEngine.ScriptContainer;
TransactionInput trans_input = trans.GetInputs()[0];
byte[] prev_hash = trans_input.PrevHash;
if(!BytesEqual(prev_hash, neo_asset_id))
{
return false;
}
Transaction prev_trans = Blockchain.GetTransaction(prev_hash);
TransactionOutput pre_trans_output = prev_trans.GetOutputs()[trans_input.PrevIndex];
byte[] sender = pre_trans_output.ScriptHash;
TransactionOutput[] trans_outputs = trans.GetOutputs();
byte[] receiver = ExecutionEngine.ExecutingScriptHash;
long value = 0;
foreach (TransactionOutput trans_output in trans_outputs)
{
if (BytesEqual(trans_output.ScriptHash, receiver))
{
value += trans_output.Value;
}
}
uint swap_rate = CurrentSwapRate();
if (swap_rate == 0)
{
byte[] refund = Storage.Get(Storage.CurrentContext, "refund");
byte[] sender_value = IntToBytes(value);
byte[] new_refund = refund.Concat(sender.Concat(IntToBytes(sender_value.Length).Concat(sender_value)));
Storage.Put(Storage.CurrentContext, "refund", new_refund);
return false;
}
long token = value * swap_rate * decimals_rate;
BigInteger total_token = BytesToInt(Storage.Get(Storage.CurrentContext, sender));
Storage.Put(Storage.CurrentContext, sender, IntToBytes(token + total_token));
byte[] totalSypply = Storage.Get(Storage.CurrentContext, "totalSypply");
Storage.Put(Storage.CurrentContext, "totalSypply", IntToBytes(token + BytesToInt(totalSypply)));
return true;
}
private static byte[] Refund()
{
return Storage.Get(Storage.CurrentContext, "refund");
}
private static BigInteger TotalSupply()
{
byte[] totalSupply = Storage.Get(Storage.CurrentContext, "totalSypply");
return BytesToInt(totalSupply);
}
private static bool Transfer(object[] args)
{
if (args.Length != 3) return false;
byte[] from = (byte[])args[0];
if (!Runtime.CheckWitness(from)) return false;
byte[] to = (byte[])args[1];
BigInteger value = BytesToInt((byte[])args[2]);
if (value < 0) return false;
byte[] from_value = Storage.Get(Storage.CurrentContext, from);
byte[] to_value = Storage.Get(Storage.CurrentContext, to);
BigInteger n_from_value = BytesToInt(from_value) - value;
if (n_from_value < 0) return false;
BigInteger n_to_value = BytesToInt(to_value) + value;
Storage.Put(Storage.CurrentContext, from, IntToBytes(n_from_value));
Storage.Put(Storage.CurrentContext, to, IntToBytes(n_to_value));
Transferred(args);
return true;
}
private static void Transferred(object[] args)
{
Runtime.Notify(args);
}
private static BigInteger BalanceOf(object[] args)
{
if (args.Length != 1) return 0;
byte[] address = (byte[])args[0];
byte[] balance = Storage.Get(Storage.CurrentContext, address);
return BytesToInt(balance);
}
private static BigInteger BytesToInt(byte[] array)
{
var buffer = new BigInteger(array);
return buffer;
}
private static byte[] IntToBytes(BigInteger value)
{
byte[] buffer = value.ToByteArray();
return buffer;
}
private static bool BytesEqual(byte[] b1, byte[] b2)
{
if (b1.Length != b2.Length) return false;
for (int i = 0; i < b1.Length; i++)
if (b1[i] != b2[i])
return false;
return true;
}
// transfer neo in smart contract can only invoke
// the function Withdrawal
// 当从智能合约中转出neo时,限定方法只能为WithDrawal方法
private static bool VerifyWithdrawal(string operation)
{
if(operation == "withdrawal")
{
return true;
}
Transaction trans = (Transaction)ExecutionEngine.ScriptContainer;
TransactionInput trans_input = trans.GetInputs()[0];
Transaction prev_trans = Blockchain.GetTransaction(trans_input.PrevHash);
TransactionOutput prev_trans_output = prev_trans.GetOutputs()[trans_input.PrevIndex];
byte[] script_hash = ExecutionEngine.ExecutingScriptHash;
if (BytesEqual(prev_trans_output.ScriptHash, script_hash))
{
return false;
}
return true;
}
// The function CurrentSwapRate() returns the current exchange rate
// between rpx tokens and neo during the token swap period
private static uint CurrentSwapRate()
{
BigInteger ico_start_time = 1505048400;
BigInteger ico_end_time = 1506258000;
uint exchange_rate = 1000;
BigInteger total_amount = 1000000000;
byte[] total_supply = Storage.Get(Storage.CurrentContext, "totalSupply");
if(BytesToInt(total_supply) > total_amount)
{
return 0;
}
uint height = Blockchain.GetHeight();
uint now = Blockchain.GetHeader(height).Timestamp;
uint time = (uint)ico_start_time - now;
if (time < 0)
{
return 0;
}else if (time <= 86400)
{
return (uint)exchange_rate * 130 /100;
}
else if (time <= 259200)
{
return exchange_rate * 120 /100;
}
else if (time <= 604800)
{
return exchange_rate * 110 / 100;
}
else if (time <= 1209600)
{
return exchange_rate;
}
else
{
return 0;
}
}
}
}