Ejemplo n.º 1
0
 private async ContractTask OnDeploy(ApplicationEngine engine, ContractState contract, StackItem data, bool update)
 {
     ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy", 2);
     if (md is not null)
         await engine.CallFromNativeContract(Hash, contract.Hash, md.Name, data, update);
     engine.SendNotification(Hash, update ? "Update" : "Deploy", new VM.Types.Array { contract.Hash.ToArray() });
 }
Ejemplo n.º 2
0
        private ContractTask Finish(ApplicationEngine engine)
        {
            if (engine.InvocationStack.Count != 2)
            {
                throw new InvalidOperationException();
            }
            if (engine.GetInvocationCounter() != 1)
            {
                throw new InvalidOperationException();
            }
            Transaction    tx       = (Transaction)engine.ScriptContainer;
            OracleResponse response = tx.GetAttribute <OracleResponse>();

            if (response == null)
            {
                throw new ArgumentException("Oracle response was not found");
            }
            OracleRequest request = GetRequest(engine.Snapshot, response.Id);

            if (request == null)
            {
                throw new ArgumentException("Oracle request was not found");
            }
            engine.SendNotification(Hash, "OracleResponse", new VM.Types.Array(engine.ReferenceCounter)
            {
                response.Id, request.OriginalTxid.ToArray()
            });
            StackItem userData = BinarySerializer.Deserialize(request.UserData, engine.Limits, engine.ReferenceCounter);

            return(engine.CallFromNativeContract(Hash, request.CallbackContract, request.CallbackMethod, request.Url, userData, (int)response.Code, response.Result));
        }
Ejemplo n.º 3
0
        private ContractState Deploy(ApplicationEngine engine, byte[] nefFile, byte[] manifest, StackItem data)
        {
            if (engine.ScriptContainer is not Transaction tx)
            {
                throw new InvalidOperationException();
            }
            if (nefFile.Length == 0)
            {
                throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}");
            }
            if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength)
            {
                throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}");
            }

            engine.AddGas(Math.Max(
                              engine.StoragePrice * (nefFile.Length + manifest.Length),
                              GetMinimumDeploymentFee(engine.Snapshot)
                              ));

            NefFile          nef            = nefFile.AsSerializable <NefFile>();
            ContractManifest parsedManifest = ContractManifest.Parse(manifest);
            UInt160          hash           = Helper.GetContractHash(tx.Sender, nef.CheckSum, parsedManifest.Name);
            StorageKey       key            = CreateStorageKey(Prefix_Contract).Add(hash);

            if (engine.Snapshot.Contains(key))
            {
                throw new InvalidOperationException($"Contract Already Exists: {hash}");
            }
            ContractState contract = new ContractState
            {
                Id            = GetNextAvailableId(engine.Snapshot),
                UpdateCounter = 0,
                Nef           = nef,
                Hash          = hash,
                Manifest      = parsedManifest
            };

            if (!contract.Manifest.IsValid(hash))
            {
                throw new InvalidOperationException($"Invalid Manifest Hash: {hash}");
            }

            engine.Snapshot.Add(key, new StorageItem(contract));

            // Execute _deploy

            ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy", 2);

            if (md != null)
            {
                engine.CallFromNativeContract(Hash, hash, md.Name, data, false);
            }

            engine.SendNotification(Hash, "Deploy", new VM.Types.Array {
                contract.Hash.ToArray()
            });

            return(contract);
        }
Ejemplo n.º 4
0
        private void Update(ApplicationEngine engine, byte[] nefFile, byte[] manifest, StackItem data)
        {
            if (nefFile is null && manifest is null)
            {
                throw new ArgumentException();
            }

            engine.AddGas(engine.StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0)));

            var contract = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable <ContractState>();

            if (contract is null)
            {
                throw new InvalidOperationException($"Updating Contract Does Not Exist: {engine.CallingScriptHash}");
            }

            if (nefFile != null)
            {
                if (nefFile.Length == 0)
                {
                    throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}");
                }

                // Update nef
                contract.Nef = nefFile.AsSerializable <NefFile>();
            }
            if (manifest != null)
            {
                if (manifest.Length == 0)
                {
                    throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}");
                }
                ContractManifest manifest_new = ContractManifest.Parse(manifest);
                if (manifest_new.Name != contract.Manifest.Name)
                {
                    throw new InvalidOperationException("The name of the contract can't be changed.");
                }
                if (!manifest_new.IsValid(contract.Hash))
                {
                    throw new InvalidOperationException($"Invalid Manifest Hash: {contract.Hash}");
                }
                contract.Manifest = manifest_new;
            }
            Check(contract.Nef.Script, contract.Manifest.Abi);
            contract.UpdateCounter++; // Increase update counter
            if (nefFile != null)
            {
                ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy", 2);
                if (md != null)
                {
                    engine.CallFromNativeContract(Hash, contract.Hash, md.Name, data, true);
                }
            }
            engine.SendNotification(Hash, "Update", new VM.Types.Array {
                contract.Hash.ToArray()
            });
        }
Ejemplo n.º 5
0
        private void PostTransfer(ApplicationEngine engine, UInt160 from, UInt160 to, byte[] tokenId)
        {
            engine.SendNotification(Hash, "Transfer",
                                    new Array {
                from?.ToArray() ?? StackItem.Null, to?.ToArray() ?? StackItem.Null, 1, tokenId
            });

            if (to is not null && ContractManagement.GetContract(engine.Snapshot, to) is not null)
            {
                engine.CallFromNativeContract(Hash, to, "onNEP11Payment", from?.ToArray() ?? StackItem.Null, 1, tokenId);
            }
        }
Ejemplo n.º 6
0
        private ContractState Deploy(ApplicationEngine engine, byte[] nefFile, byte[] manifest)
        {
            if (!(engine.ScriptContainer is Transaction tx))
            {
                throw new InvalidOperationException();
            }
            if (nefFile.Length == 0)
            {
                throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}");
            }
            if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength)
            {
                throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}");
            }

            engine.AddGas(engine.StoragePrice * (nefFile.Length + manifest.Length));

            NefFile    nef  = nefFile.AsSerializable <NefFile>();
            UInt160    hash = Helper.GetContractHash(tx.Sender, nef.Script);
            StorageKey key  = CreateStorageKey(Prefix_Contract).Add(hash);

            if (engine.Snapshot.Storages.Contains(key))
            {
                throw new InvalidOperationException($"Contract Already Exists: {hash}");
            }
            ContractState contract = new ContractState
            {
                Id            = GetNextAvailableId(engine.Snapshot),
                UpdateCounter = 0,
                Script        = nef.Script,
                Hash          = hash,
                Manifest      = ContractManifest.Parse(manifest)
            };

            if (!contract.Manifest.IsValid(hash))
            {
                throw new InvalidOperationException($"Invalid Manifest Hash: {hash}");
            }

            engine.Snapshot.Storages.Add(key, new StorageItem(contract));

            // Execute _deploy

            ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy");

            if (md != null)
            {
                engine.CallFromNativeContract(Hash, hash, md.Name, false);
            }

            return(contract);
        }
Ejemplo n.º 7
0
        private void Update(ApplicationEngine engine, byte[] nefFile, byte[] manifest)
        {
            if (nefFile is null && manifest is null)
            {
                throw new ArgumentException();
            }

            engine.AddGas(engine.StoragePrice * ((nefFile?.Length ?? 0) + (manifest?.Length ?? 0)));

            var contract = engine.Snapshot.Storages.GetAndChange(CreateStorageKey(Prefix_Contract).Add(engine.CallingScriptHash))?.GetInteroperable <ContractState>();

            if (contract is null)
            {
                throw new InvalidOperationException($"Updating Contract Does Not Exist: {engine.CallingScriptHash}");
            }

            if (nefFile != null)
            {
                if (nefFile.Length == 0)
                {
                    throw new ArgumentException($"Invalid NefFile Length: {nefFile.Length}");
                }

                NefFile nef = nefFile.AsSerializable <NefFile>();

                // Update script
                contract.Script = nef.Script;
            }
            if (manifest != null)
            {
                if (manifest.Length == 0 || manifest.Length > ContractManifest.MaxLength)
                {
                    throw new ArgumentException($"Invalid Manifest Length: {manifest.Length}");
                }
                contract.Manifest = ContractManifest.Parse(manifest);
                if (!contract.Manifest.IsValid(contract.Hash))
                {
                    throw new InvalidOperationException($"Invalid Manifest Hash: {contract.Hash}");
                }
            }
            contract.UpdateCounter++; // Increase update counter
            if (nefFile != null)
            {
                ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy");
                if (md != null)
                {
                    engine.CallFromNativeContract(Hash, contract.Hash, md.Name, true);
                }
            }
        }
Ejemplo n.º 8
0
        private void PostTransfer(ApplicationEngine engine, UInt160 from, UInt160 to, BigInteger amount, StackItem data, bool callOnPayment)
        {
            // Send notification

            engine.SendNotification(Hash, "Transfer",
                new Array { from?.ToArray() ?? StackItem.Null, to?.ToArray() ?? StackItem.Null, amount });

            // Check if it's a wallet or smart contract

            if (!callOnPayment || to is null || ContractManagement.GetContract(engine.Snapshot, to) is null) return;

            // Call onNEP17Payment method

            engine.CallFromNativeContract(Hash, to, "onNEP17Payment", from?.ToArray() ?? StackItem.Null, amount, data);
        }
Ejemplo n.º 9
0
        private void Finish(ApplicationEngine engine)
        {
            Transaction    tx       = (Transaction)engine.ScriptContainer;
            OracleResponse response = tx.GetAttribute <OracleResponse>();

            if (response == null)
            {
                throw new ArgumentException("Oracle response was not found");
            }
            OracleRequest request = GetRequest(engine.Snapshot, response.Id);

            if (request == null)
            {
                throw new ArgumentException("Oracle request was not found");
            }
            StackItem userData = BinarySerializer.Deserialize(request.UserData, engine.MaxStackSize, engine.MaxItemSize, engine.ReferenceCounter);

            engine.CallFromNativeContract(null, request.CallbackContract, request.CallbackMethod, request.Url, userData, (int)response.Code, response.Result);
        }
Ejemplo n.º 10
0
        private void PostTransfer(ApplicationEngine engine, UInt160 from, UInt160 to, BigInteger amount, StackItem data)
        {
            // Send notification

            engine.SendNotification(Hash, "Transfer",
                                    new Array {
                from?.ToArray() ?? StackItem.Null, to?.ToArray() ?? StackItem.Null, amount
            });

            // Check if it's a wallet or smart contract

            if (to is null || engine.Snapshot.Contracts.TryGet(to) is null)
            {
                return;
            }

            // Call onPayment method (NEP-17)

            engine.CallFromNativeContract(null, to, "onPayment", from?.ToArray() ?? StackItem.Null, amount, data);
        }
Ejemplo n.º 11
0
        private void Finish(ApplicationEngine engine)
        {
            Transaction    tx       = (Transaction)engine.ScriptContainer;
            OracleResponse response = tx.GetAttribute <OracleResponse>();

            if (response == null)
            {
                throw new ArgumentException("Oracle response was not found");
            }
            OracleRequest request = GetRequest(engine.Snapshot, response.Id);

            if (request == null)
            {
                throw new ArgumentException("Oracle request was not found");
            }
            engine.SendNotification(Hash, "OracleResponse", new VM.Types.Array {
                response.Id, request.OriginalTxid.ToArray()
            });
            StackItem userData = BinarySerializer.Deserialize(request.UserData, engine.Limits.MaxStackSize, engine.Limits.MaxItemSize, engine.ReferenceCounter);

            engine.CallFromNativeContract(() => { }, request.CallbackContract, request.CallbackMethod, request.Url, userData, (int)response.Code, response.Result);
        }