示例#1
0
        private bool API_Deploy(ExecutionEngine engine, NativeNEP5State state)
        {
            // 创世块里的全局资产不做检查
            if (Snapshot.PersistingBlock.Index != 0)
            {
                // 检查管理员的签名
                if (state.Admin.Equals(UInt160.Zero) || !Service.CheckWitness(engine, state.Admin))
                {
                    return(false);
                }
            }

            // 全局资产只在根链上做初始分配,暂时注释掉,等跨链兑换完成后再打开检查
            //if (Snapshot.PersistingBlock.Index == 0 && !Snapshot.Blockchain.ChainHash.Equals(UInt160.Zero))
            //    return false;

            byte[] total_supply = NativeAPI.StorageGet(Snapshot, state.AssetId, Encoding.ASCII.GetBytes("totalSupply"));
            if (total_supply.Length != 0)
            {
                return(false);
            }

            // 创世块里的全局资产,使用创世块的共识多签地址作为初始地址
            UInt160 scriptHash = Snapshot.PersistingBlock.Index == 0 ? Snapshot.PersistingBlock.NextConsensus : state.Admin;
            var     keyAdmin = new byte[] { 0x11 }.Concat(scriptHash.ToArray());

            NativeAPI.StoragePut(Snapshot, state.AssetId, keyAdmin.ToArray(), state.TotalSupply);
            NativeAPI.StoragePut(Snapshot, state.AssetId, Encoding.ASCII.GetBytes("totalSupply"), state.TotalSupply);

            Service.AddTransferNotification(engine, state.AssetId, UInt160.Zero, state.Admin, state.TotalSupply);
            return(true);
        }
示例#2
0
        private bool API_MintToken(ExecutionEngine engine, NativeNEP5State state)
        {
            // 只有创建时总量设为0的货币才能调用发币接口
            if (state.TotalSupply.GetData() != 0)
            {
                return(false);
            }

            // 检查管理员的签名
            if (state.Admin.Equals(UInt160.Zero) || !Service.CheckWitness(engine, state.Admin))
            {
                return(false);
            }

            UInt160 address = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());
            Fixed8  amount  = new Fixed8((long)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger());

            // 变更货币总量
            BigInteger totalSupply = NativeAPI.StorageGet(Snapshot, state.AssetId, Encoding.ASCII.GetBytes("totalSupply")).AsBigInteger();

            NativeAPI.StoragePut(Snapshot, state.AssetId, Encoding.ASCII.GetBytes("totalSupply"), totalSupply + amount.GetData());

            // 发放货币
            NativeAPI.AddBalance(Snapshot, state.AssetId, address, amount);

            if (engine.ScriptContainer is Transaction tx)
            {
                NativeAPI.SaveTransferLog(Snapshot, state.AssetId, tx.Hash, UInt160.Zero, address, amount);
            }

            Service.AddTransferNotification(engine, state.AssetId, UInt160.Zero, address, amount);
            return(true);
        }
示例#3
0
        private bool API_TransferApp(ExecutionEngine engine, NativeNEP5State state)
        {
            UInt160 from  = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());
            UInt160 to    = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());
            Fixed8  value = new Fixed8((long)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger());

            if (from != new UInt160(engine.CurrentContext.ScriptHash))
            {
                return(false);
            }

            bool result = NativeAPI.Transfer(Snapshot, state.AssetId, from, to, value);

            if (result)
            {
                if (engine.ScriptContainer is Transaction tx)
                {
                    NativeAPI.SaveTransferLog(Snapshot, state.AssetId, tx.Hash, from, to, value);
                }

                Service.AddTransferNotification(engine, state.AssetId, from, to, value);
            }

            engine.CurrentContext.EvaluationStack.Push(result);

            return(result);
        }
示例#4
0
        private bool API_Approve(ExecutionEngine engine, NativeNEP5State state)
        {
            UInt160 from  = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());
            UInt160 to    = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());
            Fixed8  value = new Fixed8((long)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger());

            if (!Service.CheckWitness(engine, from))
            {
                return(false);
            }

            if (engine.EntryContext.ScriptHash != engine.CurrentContext.ScriptHash)
            {
                return(false);
            }

            bool result = NativeAPI.Approve(Snapshot, state.AssetId, from, to, value);

            if (result)
            {
                Service.AddApproveNotification(engine, state.AssetId, from, to, value);
            }

            engine.CurrentContext.EvaluationStack.Push(result);

            return(result);
        }
示例#5
0
        private bool API_BalanceOf(ExecutionEngine engine, NativeNEP5State state)
        {
            UInt160 address = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());
            var     key = new byte[] { 0x11 }.Concat(address.ToArray()).ToArray();

            engine.CurrentContext.EvaluationStack.Push(NativeAPI.StorageGet(Snapshot, state.AssetId, key).AsBigInteger());
            return(true);
        }
示例#6
0
        private bool API_Allowance(ExecutionEngine engine, NativeNEP5State state)
        {
            UInt160 from    = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());
            UInt160 spender = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());

            var keyApprove = from.ToArray().Concat(spender.ToArray()).ToArray();

            engine.CurrentContext.EvaluationStack.Push(NativeAPI.StorageGet(Snapshot, state.AssetId, keyApprove).AsBigInteger());
            return(true);
        }
示例#7
0
        public bool GetTransferLog(ExecutionEngine engine)
        {
            UInt160         assetId = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());
            NativeNEP5State state   = Snapshot.NativeNEP5s.TryGet(assetId);

            if (state == null)
            {
                return(false);
            }

            return(API_GetTransferLog(engine, state));
        }
示例#8
0
        private bool API_GetTransferLog(ExecutionEngine engine, NativeNEP5State state)
        {
            byte[] hash = engine.CurrentContext.EvaluationStack.Pop().GetByteArray();

            TransferLog transferLog = NativeAPI.GetTransferLog(Snapshot, state.AssetId, hash);

            if (transferLog == null)
            {
                return(false);
            }

            engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(transferLog));
            return(true);
        }
示例#9
0
        public bool Create(ExecutionEngine engine)
        {
            if (Trigger != TriggerType.Application)
            {
                return(false);
            }

            // 全名
            if (engine.CurrentContext.EvaluationStack.Peek().GetByteArray().Length > 1024)
            {
                return(false);
            }
            string name = Encoding.UTF8.GetString(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());

            // 简写名
            if (engine.CurrentContext.EvaluationStack.Peek().GetByteArray().Length > 252)
            {
                return(false);
            }
            string symbol = Encoding.UTF8.GetString(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());

            // 货币总量
            Fixed8 amount = new Fixed8((long)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger());

            if (amount < Fixed8.Zero)
            {
                return(false);
            }

            // 货币精度
            byte precision = (byte)engine.CurrentContext.EvaluationStack.Pop().GetBigInteger();

            if (precision > 8)
            {
                return(false);
            }
            if (amount.GetData() % (long)Math.Pow(10, precision) != 0)
            {
                return(false);
            }

            // 发行人
            ECPoint owner = ECPoint.DecodePoint(engine.CurrentContext.EvaluationStack.Pop().GetByteArray(), ECCurve.Secp256r1);

            // 创世块不做检查
            if (Snapshot.PersistingBlock.Index != 0)
            {
                // 检查发行人的签名
                if (owner.IsInfinity)
                {
                    return(false);
                }
                if (!Service.CheckWitness(engine, owner))
                {
                    return(false);
                }
            }

            // 管理员
            UInt160 admin = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());

            // 创世块不做检查
            if (Snapshot.PersistingBlock.Index != 0)
            {
                // 检查管理员的Hash
                if (admin.Equals(UInt160.Zero))
                {
                    return(false);
                }
            }

            UInt160 assetId;

            if (Snapshot.PersistingBlock.Index == 0)
            {
                // 只有在创世块里可以自定义assetId
                assetId = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());
            }
            else
            {
                // 用ScriptHash作为assetId
                assetId = new UInt160(engine.CurrentContext.ScriptHash);
            }

            NativeNEP5State state = Snapshot.NativeNEP5s.TryGet(assetId);

            if (state == null)
            {
                state = new NativeNEP5State
                {
                    AssetId     = assetId,
                    Name        = name,
                    Symbol      = symbol,
                    TotalSupply = amount,
                    Decimals    = precision,
                    Owner       = owner,
                    Admin       = admin,
                    BlockIndex  = Snapshot.Height + 1,
                    IsFrozen    = false
                };

                // 保存到数据库
                Snapshot.NativeNEP5s.Add(assetId, state);
            }

            // 设置脚本的返回值
            engine.CurrentContext.EvaluationStack.Push(StackItem.FromInterface(state));
            return(true);
        }
示例#10
0
 private bool API_Decimals(ExecutionEngine engine, NativeNEP5State state)
 {
     engine.CurrentContext.EvaluationStack.Push((int)state.Decimals);
     return(true);
 }
示例#11
0
 private bool API_TotalSupply(ExecutionEngine engine, NativeNEP5State state)
 {
     engine.CurrentContext.EvaluationStack.Push(NativeAPI.StorageGet(Snapshot, state.AssetId, Encoding.ASCII.GetBytes("totalSupply")).AsBigInteger());
     return(true);
 }
示例#12
0
 private bool API_Symbol(ExecutionEngine engine, NativeNEP5State state)
 {
     engine.CurrentContext.EvaluationStack.Push(state.Symbol);
     return(true);
 }
示例#13
0
        public bool Call(ExecutionEngine engine)
        {
            if (Trigger != TriggerType.Application)
            {
                return(false);
            }

            if (engine.CurrentContext.EvaluationStack.Peek().GetByteArray().Length > 252)
            {
                return(false);
            }
            string method = Encoding.UTF8.GetString(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());

            // 兼容用json数组来打包的参数
            StackItem stackItem = engine.CurrentContext.EvaluationStack.Peek();

            if (stackItem is Neo.VM.Types.Array array)
            {
                engine.CurrentContext.EvaluationStack.Pop();

                int count = array.Count();
                for (int i = count - 1; i >= 0; i--)
                {
                    engine.CurrentContext.EvaluationStack.Push(array[i]);
                }
            }

            UInt160         assetId = new UInt160(engine.CurrentContext.EvaluationStack.Pop().GetByteArray());
            NativeNEP5State state   = Snapshot.NativeNEP5s.TryGet(assetId);

            if (state == null)
            {
                return(false);
            }

            switch (method)
            {
            case "Name":
                return(API_Name(engine, state));

            case "Symbol":
                return(API_Symbol(engine, state));

            case "TotalSupply":
                return(API_TotalSupply(engine, state));

            case "Decimals":
                return(API_Decimals(engine, state));

            case "BalanceOf":
                return(API_BalanceOf(engine, state));

            case "Transfer":
                return(API_Transfer(engine, state));

            case "TransferApp":
                return(API_TransferApp(engine, state));

            case "Approve":
                return(API_Approve(engine, state));

            case "TransferFrom":
                return(API_TransferFrom(engine, state));

            case "Allowance":
                return(API_Allowance(engine, state));

            case "GetTransferLog":
                return(API_GetTransferLog(engine, state));

            case "Deploy":
                return(API_Deploy(engine, state));

            case "MintToken":
                return(API_MintToken(engine, state));
            }

            return(false);
        }