zoukankan      html  css  js  c++  java
  • 发行NEO的NEP-5合约代币

    NEO常见的资产有三种

    1. TOKEN (全局资产)
    2. Share (全局资产,股份 )
    3. NEP-5 (合约代币,相当于ETH的ERC20)
    NEP-5 合约代码

    https://github.com/ANDIT-Solutions/NEO-NEP5.1

    这里发行Name为Five的代币,代币Symbol为FFF. 共发行1000000000个单位。

    using Neo.SmartContract.Framework;
    using Neo.SmartContract.Framework.Services.Neo;
    using System;
    using System.ComponentModel;
    using System.Numerics;
    
    namespace Neo.SmartContract
    {
        public class ICO_Template : Framework.SmartContract
        {
    
            //Token Settings
            public static string Name() => "Five";
            public static string Symbol() => "FFF";
            public static readonly byte[] Owner = "AdNjgXiDU1imfKoCSQcgcd4HmBSn2qsHfe".ToScriptHash();//translates 
            //to: 0x20f0a44d41c659a49651823ac19794dda45bd4d9., it's the ScriptHash of your public address ,you can view it in neo-gui(for example)
            public static byte Decimals() => 8;
            private const ulong factor = 100000000; //decided by Decimals()
            //Since we don't want to deal with floating points sending 555 tokens with 8 Decimals (100000000) 
            //would actually mean that you want to  send 55500000000 tokens.
            private const ulong total_amount = 1000000000 * factor; //token amount
    
            [DisplayName("transfer")]
            public static event Action<byte[], byte[], BigInteger> Transferred;
    
    
            public static Object Main(string operation, params object[] args)
            {
                if (Runtime.Trigger == TriggerType.Verification)
                {
                    if (Owner.Length == 20)
                    {
                        // if param Owner is script hash
                        return Runtime.CheckWitness(Owner);
                    }
                    else if (Owner.Length == 33)
                    {
                        // if param Owner is public key
                        byte[] signature = operation.AsByteArray();
                        return VerifySignature(signature, Owner);
                    }
                }
                else if (Runtime.Trigger == TriggerType.Application)
                {
                    if (operation == "deploy") return Deploy();
                    if (operation == "totalSupply") return TotalSupply();
                    if (operation == "name") return Name();
                    if (operation == "symbol") return Symbol();
                    if (operation == "decimals") return Decimals();
                    if (operation == "approve") if (args.Length >= 3) return Approve((byte[])args[0], (byte[])args[1], (BigInteger)args[2]); else return NotifyErrorAndReturn0("argument count must be atleast 3");
                    if (operation == "allowance") if (args.Length >= 2) return Allowance((byte[])args[0], (byte[])args[1]); else return NotifyErrorAndReturn0("argument count must be atleast 2");
                    if (operation == "transferFrom") if (args.Length >= 4) return TransferFrom((byte[])args[0], (byte[])args[1], (byte[])args[2], (BigInteger)args[3]); else return NotifyErrorAndReturn0("argument count must be atleast 4");
                    if (operation == "transfer")
                    {
                        if (args.Length != 3 || args[0] == null || ((byte[])args[0]).Length == 0 || args[1] == null || ((byte[])args[1]).Length == 0) return NotifyErrorAndReturnFalse("argument count must be 3 and they must not be null");
                        byte[] from = (byte[])args[0];
                        byte[] to = (byte[])args[1];
                        BigInteger value = (BigInteger)args[2];
                        return Transfer(from, to, value, false);
                    }
                    if (operation == "balanceOf")
                    {
                        if (args.Length != 1 || args[0] == null || ((byte[])args[0]).Length == 0) return NotifyErrorAndReturn0("argument count must be 1 and they must not be null");
                        byte[] account = (byte[])args[0];
                        return BalanceOf(account);
                    }
                }
                return NotifyErrorAndReturnFalse("Operation not found");
            }
    
            /// <summary>
            /// Can only be called by the Owner
            /// Puts total_amount value under "totalSupply" key and ,this function can be used only once ,unless the total amount is 0.
            /// </summary>
            /// <returns></returns>
            public static bool Deploy()
            {
                if (!Runtime.CheckWitness(Owner)) //ensure that it is the owner calling this method
                    return NotifyErrorAndReturnFalse("You are not the Owner of this Smart Contract");
    
                byte[] total_supply = Storage.Get(Storage.CurrentContext, "totalSupply");
    
                if (total_supply.Length != 0)
                    return NotifyErrorAndReturnFalse("Looks like this method has been allready used");
    
                Storage.Put(Storage.CurrentContext, Owner, total_amount);
                Storage.Put(Storage.CurrentContext, "totalSupply", total_amount);
                Transferred(null, Owner, total_amount);
                return true;
            }
            /// <summary>
            /// Returns the Total Supply of Tokens
            /// </summary>
            /// <returns></returns>
            public static BigInteger TotalSupply()
            {
                return Storage.Get(Storage.CurrentContext, "totalSupply").AsBigInteger();
            }
            /// <summary>
            ///   Checks the TransferFrom approval of two accounts.
            /// </summary>
            /// <param name="from">
            ///   The account which funds can be transfered from.
            /// </param>
            /// <param name="to">
            ///   The account which is granted usage of the account.
            /// </param>
            /// <returns>
            ///   The amount allocated for TransferFrom.
            /// </returns>
            public static BigInteger Allowance(byte[] from, byte[] to)
            {
                if (from == null || from.Length != 20)
                    return NotifyErrorAndReturn0("From value must not be empty and have size of 20");
    
                if (to == null || to.Length != 20)
                    return NotifyErrorAndReturn0("To value must not be empty and have size of 20");
    
                return Storage.Get(Storage.CurrentContext, from.Concat(to)).AsBigInteger();
            }
            /// <summary>
            ///   Approves another user to use the TransferFrom
            ///   function on the invoker's account.
            ///   TransferFrom 
            /// </summary>
            /// <param name="originator">
            ///   The contract invoker.
            /// </param>
            /// <param name="to">
            ///   The account to grant TransferFrom access to.
            ///   所批准的账户
            /// </param>
            /// <param name="amount">
            ///   The amount to grant TransferFrom access for.
            /// </param>
            /// <returns>
            ///   Transaction Successful?
            /// </returns>
            public static bool Approve(byte[] originator, byte[] to, BigInteger amount)
            {
                if (to == null || to.Length != 20)
                    return NotifyErrorAndReturnFalse("To value must not be empty and have size of 20");
    
                if (originator == null || originator.Length != 20)
                    return NotifyErrorAndReturnFalse("Originator value must not be empty and have size of 20");
    
                if (amount < 0)
                    return NotifyErrorAndReturnFalse("Amount is lower than zero");
    
                if (!(Runtime.CheckWitness(originator)))
                    return NotifyErrorAndReturnFalse("Originator isn't associated with this invoke");
    
    
                Storage.Put(Storage.CurrentContext, originator.Concat(to), amount);
                return true;
    
            }
            /// <summary>
            ///   Transfers a balance from one account to another
            ///   on behalf of the account owner.
            /// </summary>
            /// <param name="originator">
            ///   The contract invoker.
            /// </param>
            /// <param name="from">
            ///   The account to transfer a balance from.
            /// </param>
            /// <param name="to">
            ///   The account to transfer a balance to.
            /// </param>
            /// <param name="amount">
            ///   The amount to transfer.
            /// </param>
            /// <returns>
            ///   Transaction successful?
            /// </returns>
            public static bool TransferFrom(byte[] originator, byte[] from, byte[] to, BigInteger amountToSend)
            {
    
                if (originator == null || originator.Length != 20)
                    return NotifyErrorAndReturnFalse("Originator value must not be empty and have size of 20");
                if (from == null || from.Length != 20)
                    return NotifyErrorAndReturnFalse("From value must not be empty and have size of 20");
                if (to == null || to.Length != 20)
                    return NotifyErrorAndReturnFalse("To value must not be empty and have size of 20");
    
                if (!(Runtime.CheckWitness(originator)))
                    return NotifyErrorAndReturnFalse("Originator isn't associated with this invoke");
    
                if (amountToSend <= 0)
                    return NotifyErrorAndReturnFalse("You need to send more than 0 tokens");
    
                BigInteger ownerAmount = BalanceOf(from);
    
                if (ownerAmount < amountToSend)
                    return NotifyErrorAndReturnFalse("Owner doesn't have this kind amount of tokens");
    
                if (ownerAmount <= 0)
                    return NotifyErrorAndReturnFalse("Owner doesn't have positive balance");
    
                BigInteger allowedAmount = Allowance(from, originator);
    
                if (allowedAmount < amountToSend)
                    return NotifyErrorAndReturnFalse("You are trying to send more than you are allowed to");
    
                if (!(Transfer(from, to, amountToSend, true)))//This does the actual transfer.
                    return NotifyErrorAndReturnFalse("Failed to Transfer");
    
    
    
                BigInteger amountLeft = allowedAmount - amountToSend;
                if (amountLeft <= 0)//There should not be an situation where someone holds an negative ballance ,but for safety sake I did add this.
                {
                    Storage.Delete(Storage.CurrentContext, from.Concat(originator));
                }
                else
                {
                    Storage.Put(Storage.CurrentContext, from.Concat(originator), amountLeft);
                }
                return true;
            }
            /// <summary>
            /// function that is always called when someone wants to transfer tokens.
            /// </summary>
            /// <param name="from"></param>
            /// wallet from which we send the tokens.
            /// <param name="to"></param>
            /// wallet to which we send the tokens.
            /// <param name="value"></param>
            /// amount that we will send
            /// <param name="transferFrom"></param>
            /// Checks if the function is called from TransferFrom methods ,if so then there is no need to Check Witness.
            /// <returns>
            /// Returns if the tranfer process has succeded or not.
            /// </returns>
            public static bool Transfer(byte[] from, byte[] to, BigInteger value, bool transferFrom)
            {
                if (to == null || to.Length != 20)
                    return NotifyErrorAndReturnFalse("To value must not be empty and have size of 20");
    
                if (from == null || from.Length != 20)
                    return NotifyErrorAndReturnFalse("From value must not be empty and have size of 20");
    
                if (value <= 0) return NotifyErrorAndReturnFalse("Try to send more than 0 tokens");
                if (!transferFrom && !Runtime.CheckWitness(from)) return NotifyErrorAndReturnFalse("Owner of the wallet is not involved in this invoke");
                if (from == to) return true;
                BigInteger from_value = Storage.Get(Storage.CurrentContext, from).AsBigInteger();
                if (from_value < value) return NotifyErrorAndReturnFalse("Insufficient funds");
                if (from_value == value)
                    Storage.Delete(Storage.CurrentContext, from);
                else
                    Storage.Put(Storage.CurrentContext, from, from_value - value);
                BigInteger to_value = Storage.Get(Storage.CurrentContext, to).AsBigInteger();
                Storage.Put(Storage.CurrentContext, to, to_value + value);
                Transferred(from, to, value);
                return true;
            }
            /// <summary>
            /// Get the account balance of another account with address,uses wallets address scripthash.
            /// </summary>
            /// <param name="address"></param>
            /// The Adress that we want to know blance of
            /// <returns>
            /// Amount of tokens associated with this address
            /// </returns>
            public static BigInteger BalanceOf(byte[] address)
            {
                return Storage.Get(Storage.CurrentContext, address).AsBigInteger();
            }
            /// <summary>
            /// Used when we want to Notify Error for debbuging and return false
            /// </summary>
            /// <param name="value"></param>
            /// String that will be notified
            /// <returns>
            /// Allways False
            /// </returns>
            public static bool NotifyErrorAndReturnFalse(string value)
            {
                Runtime.Notify(value);
                return false;
            }
            /// <summary>
            /// Used when we want to Notify Error for debbuging and return 0
            /// </summary>
            /// <param name="value"></param>
            /// String that will be notified
            /// <returns>
            /// Allways 0
            /// </returns>
            public static int NotifyErrorAndReturn0(string value)
            {
                Runtime.Notify(value);
                return 0;
            }
        }
    }
    
    需要定义的参数:

    参数说明:
    • Owner 合约部署后,代币所有者
    • factor 小数位数,Decimal
    • total_amount 总发行量
    • Name 合约名称
    • Sympol 代币名称
    编译部署

    把C#代码放到https://neocompiler.io/#/ecolab,线上编译即可

    下载AVM的16进制格式编码和Script hash:

    hex code:

    54c56b6c766b00527ac46c766b51527ac46168164e656f2e52756e74696d652e47657454726967676572639a006114ecf28d2236dab6c09da8352821780215e890d7cfc00114907c907c9e6339006114ecf28d2236dab6c09da8352821780215e890d7cf6168184e656f2e52756e74696d652e436865636b5769746e657373616c75666114ecf28d2236dab6c09da8352821780215e890d7cfc00121907c907c9e6357036c766b00c36114ecf28d2236dab6c09da8352821780215e890d7cfac616c75666168164e656f2e52756e74696d652e4765745472696767657260907c907c9e6315036c766b00c3066465706c6f7987640b0061653c03616c75666c766b00c30b746f74616c537570706c7987640b006165d304616c75666c766b00c3046e616d6587640b006165ea02616c75666c766b00c30673796d626f6c87640b006165de02616c75666c766b00c308646563696d616c7387640b006165cf02616c75666c766b00c307617070726f7665876456006c766b51c3c0539f6322006c766b51c300c36c766b51c351c36c766b51c352c3615272657305616c756620617267756d656e7420636f756e74206d7573742062652061746c65617374203361658a0d616c75666c766b00c309616c6c6f77616e636587644e006c766b51c3c0529f631a006c766b51c300c36c766b51c351c3617c653104616c756620617267756d656e7420636f756e74206d7573742062652061746c65617374203261652c0d616c75666c766b00c30c7472616e7366657246726f6d87646f006c766b51c3c0549f633b006c766b51c300c36c766b51c351c36c766b51c352c36c766b51c353c3615379517955727551727552795279547275527275650f06616c756620617267756d656e7420636f756e74206d7573742062652061746c6561737420346165aa0c616c75666c766b00c3087472616e736665728764c1006c766b51c3c053907c907c9e632d006c766b51c300c36423006c766b51c300c3c06418006c766b51c351c3640e006c766b51c351c3c0633e0032617267756d656e7420636f756e74206d757374206265203320616e642074686579206d757374206e6f74206265206e756c6c6165f60b616c75666c766b51c300c36c766b51c351c36c766b52527ac46c766b51c352c36c766b53527ac46c766b52c36c766b53c300615379517955727551727552795279547275527275657908616c75666c766b00c30962616c616e63654f66876471006c766b51c3c051907c907c9e6318006c766b51c300c3640e006c766b51c300c3c0633e0032617267756d656e7420636f756e74206d757374206265203120616e642074686579206d757374206e6f74206265206e756c6c6165680b616c75666c766b51c300c36165ec0a616c7566134f7065726174696f6e206e6f7420666f756e6461650f0b616c756600c56b0446697665616c756600c56b03464646616c756600c56b58616c756600c56b6114ecf28d2236dab6c09da8352821780215e890d7cf6168184e656f2e52756e74696d652e436865636b5769746e6573736338002c596f7520617265206e6f7420746865204f776e6572206f66207468697320536d61727420436f6e74726163746165840a616c75666168164e656f2e53746f726167652e476574436f6e746578740b746f74616c537570706c79617c680f4e656f2e53746f726167652e476574c06439002d4c6f6f6b73206c696b652074686973206d6574686f6420686173206265656e20616c6c726561647920757365646165120a616c75666168164e656f2e53746f726167652e476574436f6e746578746114ecf28d2236dab6c09da8352821780215e890d7cf0800008a5d78456301615272680f4e656f2e53746f726167652e5075746168164e656f2e53746f726167652e476574436f6e746578740b746f74616c537570706c790800008a5d78456301615272680f4e656f2e53746f726167652e50757461006114ecf28d2236dab6c09da8352821780215e890d7cf0800008a5d78456301615272087472616e7366657254c168124e656f2e52756e74696d652e4e6f7469667951616c756600c56b6168164e656f2e53746f726167652e476574436f6e746578740b746f74616c537570706c79617c680f4e656f2e53746f726167652e476574616c756652c56b6c766b00527ac46c766b51527ac46c766b00c3640f006c766b00c3c001149c633c003046726f6d2076616c7565206d757374206e6f7420626520656d70747920616e6420686176652073697a65206f662032306165cd08616c75666c766b51c3640f006c766b51c3c001149c633a002e546f2076616c7565206d757374206e6f7420626520656d70747920616e6420686176652073697a65206f6620323061658208616c75666168164e656f2e53746f726167652e476574436f6e746578746c766b00c36c766b51c37e617c680f4e656f2e53746f726167652e476574616c756653c56b6c766b00527ac46c766b51527ac46c766b52527ac46c766b51c3640f006c766b51c3c001149c633a002e546f2076616c7565206d757374206e6f7420626520656d70747920616e6420686176652073697a65206f662032306165b607616c75666c766b00c3640f006c766b00c3c001149c634200364f726967696e61746f722076616c7565206d757374206e6f7420626520656d70747920616e6420686176652073697a65206f6620323061656307616c75666c766b52c3009f64250019416d6f756e74206973206c6f776572207468616e207a65726f61653707616c75666c766b00c36168184e656f2e52756e74696d652e436865636b5769746e6573736338002c4f726967696e61746f722069736e2774206173736f6369617465642077697468207468697320696e766f6b656165df06616c75666168164e656f2e53746f726167652e476574436f6e746578746c766b00c36c766b51c37e6c766b52c3615272680f4e656f2e53746f726167652e50757451616c756657c56b6c766b00527ac46c766b51527ac46c766b52527ac46c766b53527ac46c766b00c3640f006c766b00c3c001149c634200364f726967696e61746f722076616c7565206d757374206e6f7420626520656d70747920616e6420686176652073697a65206f6620323061652b06616c75666c766b51c3640f006c766b51c3c001149c633c003046726f6d2076616c7565206d757374206e6f7420626520656d70747920616e6420686176652073697a65206f662032306165de05616c75666c766b52c3640f006c766b52c3c001149c633a002e546f2076616c7565206d757374206e6f7420626520656d70747920616e6420686176652073697a65206f6620323061659305616c75666c766b00c36168184e656f2e52756e74696d652e436865636b5769746e6573736338002c4f726967696e61746f722069736e2774206173736f6369617465642077697468207468697320696e766f6b6561653b05616c75666c766b53c300a1642f0023596f75206e65656420746f2073656e64206d6f7265207468616e203020746f6b656e7361650505616c75666c766b51c36165b9046c766b54527ac46c766b54c36c766b53c39f6439002d4f776e657220646f65736e277420686176652074686973206b696e6420616d6f756e74206f6620746f6b656e736165b104616c75666c766b54c300a1642f00234f776e657220646f65736e2774206861766520706f7369746976652062616c616e636561657b04616c75666c766b51c36c766b00c3617c6572fb6c766b55527ac46c766b55c36c766b53c39f643f0033596f752061726520747279696e6720746f2073656e64206d6f7265207468616e20796f752061726520616c6c6f77656420746f61651b04616c75666c766b51c36c766b52c36c766b53c35161537951795572755172755279527954727552727565bc00631e00124661696c656420746f205472616e736665726165d503616c75666c766b55c36c766b53c3946c766b56527ac46c766b56c300a16440006168164e656f2e53746f726167652e476574436f6e746578746c766b51c36c766b00c37e617c68124e656f2e53746f726167652e44656c6574656240006168164e656f2e53746f726167652e476574436f6e746578746c766b51c36c766b00c37e6c766b56c3615272680f4e656f2e53746f726167652e50757451616c756656c56b6c766b00527ac46c766b51527ac46c766b52527ac46c766b53527ac46c766b51c3640f006c766b51c3c001149c633a002e546f2076616c7565206d757374206e6f7420626520656d70747920616e6420686176652073697a65206f662032306165d002616c75666c766b00c3640f006c766b00c3c001149c633c003046726f6d2076616c7565206d757374206e6f7420626520656d70747920616e6420686176652073697a65206f6620323061658302616c75666c766b52c300a1642a001e54727920746f2073656e64206d6f7265207468616e203020746f6b656e7361655202616c75666c766b53c36361006c766b00c36168184e656f2e52756e74696d652e436865636b5769746e657373633e00324f776e6572206f66207468652077616c6c6574206973206e6f7420696e766f6c76656420696e207468697320696e766f6b656165ec01616c75666c766b00c36c766b51c3907c907c9e63080051616c75666168164e656f2e53746f726167652e476574436f6e746578746c766b00c3617c680f4e656f2e53746f726167652e4765746c766b54527ac46c766b54c36c766b52c39f641e0012496e73756666696369656e742066756e647361657401616c75666c766b54c36c766b52c39c643a006168164e656f2e53746f726167652e476574436f6e746578746c766b00c3617c68124e656f2e53746f726167652e44656c6574656240006168164e656f2e53746f726167652e476574436f6e746578746c766b00c36c766b54c36c766b52c394615272680f4e656f2e53746f726167652e5075746168164e656f2e53746f726167652e476574436f6e746578746c766b51c3617c680f4e656f2e53746f726167652e4765746c766b55527ac46168164e656f2e53746f726167652e476574436f6e746578746c766b51c36c766b55c36c766b52c393615272680f4e656f2e53746f726167652e507574616c766b00c36c766b51c36c766b52c3615272087472616e7366657254c168124e656f2e52756e74696d652e4e6f7469667951616c756651c56b6c766b00527ac46168164e656f2e53746f726167652e476574436f6e746578746c766b00c3617c680f4e656f2e53746f726167652e476574616c756651c56b6c766b00527ac451c576006c766b00c3c46168124e656f2e52756e74696d652e4e6f7469667900616c756651c56b6c766b00527ac451c576006c766b00c3c46168124e656f2e52756e74696d652e4e6f7469667900616c7566
    

    ####### Script Hash

    b2e50c6a25fdc5c690992c36d9b9f2978b7062fd 
    
    部署合约

    高级-部署合约

    部署NEP-5合约花费490GAS 交易类型为InvocationTransaction

    高级-合约调用-调用合约内deploy函数

    NEP-5 转账

    先在neo-gui添加代币资产

    Advanced
    Options
    Add Five Scripthash: b2e50c6a25fdc5c690992c36d9b9f2978b7062fd
    Apply/Ok

    可以看到资产中有刚才发行的Five代币

    NEP-5 代币转账

    交易所对接NEP-5
    1. 节点开启log日志
    dotnet neo-cli.dll --rpc --log --nopeers
    
    
    1. 解析log中NEP-5交易
    root@test:/data/app/neo-cli/ApplicationLogs_74746E41# cat 0x5a59e800a82ca8baabd4dad7fcd8b6690eb475c539651f0e3d54034f419efdf3.json  
    {"txid":"0x5a59e800a82ca8baabd4dad7fcd8b6690eb475c539651f0e3d54034f419efdf3","vmstate":"HALT, BREAK","gas_consumed":"2.739","stack":[],"notifications":[{"contract":"0xb2e50c6a25fdc5c690992c36d9b9f2978b7062fd","state":{"type":"Array","value":[{"type":"ByteArray","value":"7472616e73666572"},{"type":"ByteArray","value":"ecf28d2236dab6c09da8352821780215e890d7cf"},{"type":"ByteArray","value":"586853337b382a817c163b965eb57c1b57046519"},{"type":"ByteArray","value":"00e8764817"}]}}]}
    
    1. 调用NEP-5合约balaceOf() 函数确认余额
  • 相关阅读:
    单元测试乱弹(一):悲剧的测试工具
    Android 4.2中sqlite操作问题(二):某些情况下显式启用事务能提高操作效率
    some code of debug mode
    asp .NET弹出窗口 汇总
    if (!IsPostBack)
    Asp.Net中清空所有textbox的几种方法
    ASP.NET验证控件详解
    正则表达式限制文本框只能输入数字
    颜色
    gridview 根据条件更改链接的可用和颜色
  • 原文地址:https://www.cnblogs.com/xiaoxiaoleo/p/9445390.html
Copyright © 2011-2022 走看看