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