Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Call-If-Exists with new syscalls #2023

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions src/neo/SmartContract/ApplicationEngine.Contract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ partial class ApplicationEngine
public static readonly InteropDescriptor System_Contract_Destroy = Register("System.Contract.Destroy", nameof(DestroyContract), 0_01000000, CallFlags.AllowModifyStates, false);
public static readonly InteropDescriptor System_Contract_Call = Register("System.Contract.Call", nameof(CallContract), 0_01000000, CallFlags.AllowCall, false);
public static readonly InteropDescriptor System_Contract_CallEx = Register("System.Contract.CallEx", nameof(CallContractEx), 0_01000000, CallFlags.AllowCall, false);
public static readonly InteropDescriptor System_Contract_CallIfExists = Register("System.Contract.CallIfExists", nameof(CallIfExistsContract), 0_01000000, CallFlags.AllowCall, false);
public static readonly InteropDescriptor System_Contract_CallCallIfExistsEx = Register("System.Contract.CallIfExistsEx", nameof(CallIfExistsContractEx), 0_01000000, CallFlags.AllowCall, false);
public static readonly InteropDescriptor System_Contract_IsStandard = Register("System.Contract.IsStandard", nameof(IsStandardContract), 0_00030000, CallFlags.AllowStates, true);
public static readonly InteropDescriptor System_Contract_GetCallFlags = Register("System.Contract.GetCallFlags", nameof(GetCallFlags), 0_00030000, CallFlags.None, false);
/// <summary>
Expand Down Expand Up @@ -120,24 +122,44 @@ protected internal void DestroyContract()

protected internal void CallContract(UInt160 contractHash, string method, Array args)
{
CallContractInternal(contractHash, method, args, CallFlags.All);
CallContractInternal(contractHash, method, args, CallFlags.All, true);
}

protected internal void CallIfExistsContract(UInt160 contractHash, string method, Array args)
{
CallContractInternal(contractHash, method, args, CallFlags.All, false);
}

protected internal void CallContractEx(UInt160 contractHash, string method, Array args, CallFlags callFlags)
{
if ((callFlags & ~CallFlags.All) != 0)
throw new ArgumentOutOfRangeException(nameof(callFlags));
CallContractInternal(contractHash, method, args, callFlags);
CallContractInternal(contractHash, method, args, callFlags, true);
}

protected internal void CallIfExistsContractEx(UInt160 contractHash, string method, Array args, CallFlags callFlags)
{
if ((callFlags & ~CallFlags.All) != 0)
throw new ArgumentOutOfRangeException(nameof(callFlags));
CallContractInternal(contractHash, method, args, callFlags, false);
}

private void CallContractInternal(UInt160 contractHash, string method, Array args, CallFlags flags)
private void CallContractInternal(UInt160 contractHash, string method, Array args, CallFlags flags, bool mustExists)
{
if (method.StartsWith('_')) throw new ArgumentException($"Invalid Method Name: {method}");

ContractState contract = Snapshot.Contracts.TryGet(contractHash);
if (contract is null) throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}");
if (contract is null)
{
if (!mustExists) return;
throw new InvalidOperationException($"Called Contract Does Not Exist: {contractHash}");
}
ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(method);
if (md is null) throw new InvalidOperationException($"Method {method} Does Not Exist In Contract {contractHash}");
if (md is null)
{
if (!mustExists) return;
throw new InvalidOperationException($"Method {method} Does Not Exist In Contract {contractHash}");
}

ContractManifest currentManifest = Snapshot.Contracts.TryGet(CurrentScriptHash)?.Manifest;
if (currentManifest != null && !currentManifest.CanCall(contract.Manifest, method))
Expand Down