Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion src/Neo/SmartContract/ApplicationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ public ExecutionContext LoadContract(ContractState contract, ContractMethodDescr
});

// Call initialization
var init = contract.Manifest.Abi.GetMethod("_initialize", 0);
var init = contract.Manifest.Abi.GetMethod(ContractBasicMethod.Initialize, ContractBasicMethod.InitializePCount);
if (init != null)
{
LoadContext(context.Clone(init.Offset));
Expand Down
122 changes: 122 additions & 0 deletions src/Neo/SmartContract/ContractBasicMethod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Copyright (C) 2015-2024 The Neo Project.
//
// ContractBasicMethod.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

namespace Neo.SmartContract
{
/// <summary>
/// This class provides a guideline for basic methods used in the Neo blockchain, offering
/// a generalized interaction mechanism for smart contract deployment, verification, updates, and destruction.
/// </summary>
public record ContractBasicMethod
Comment thread
shargon marked this conversation as resolved.
{
/// <summary>
/// The verification method. This must be called when withdrawing tokens from the contract.
/// If the contract address is included in the transaction signature, this method verifies the signature.
/// Example:
/// <code>
/// public static bool Verify() => Runtime.CheckWitness(Owner);
/// </code>
/// <code>
/// {
/// "name": "verify",
/// "safe": false,
/// "parameters": [],
/// "returntype": "bool"
/// }
/// </code>
/// </summary>
public static string Verify { get; } = "verify";

/// <summary>
/// The initialization method. Compiled into the <see cref="Manifest"/> file if any function uses the initialize statement.
/// These functions are executed first when loading the contract.
/// Example:
/// <code>
/// private static readonly UInt160 owner = "NdUL5oDPD159KeFpD5A9zw5xNF1xLX6nLT";
/// </code>
/// </summary>
public static string Initialize { get; } = "_initialize";

/// <summary>
/// The deployment method. Automatically executed by the ContractManagement contract when a contract is first deployed or updated.
/// <code>
/// {
/// "name": "_deploy",
/// "safe": false,
/// "parameters": [
/// {
/// "name": "data",
/// "type": "Any"
/// },
/// {
/// "name": "update",
/// "type": "Boolean"
/// }
/// ],
/// "returntype": "Void"
/// }
/// </code>
/// </summary>
public static string Deploy { get; } = "_deploy";

/// <summary>
/// The update method. Requires <see cref="NefFile"/> or <see cref="Manifest"/>, or both, and is passed to _deploy.
/// Should verify the signer's address using SYSCALL <code>Neo.Runtime.CheckWitness</code>.
/// <code>
/// {
/// "name": "update",
/// "safe": false,
/// "parameters": [
/// {
/// "name": "nefFile",
/// "type": "ByteArray"
/// },
/// {
/// "name": "manifest",
/// "type": "ByteArray"
/// },
/// {
/// "name": "data",
/// "type": "Any"
/// }
/// ],
/// "returntype": "Void"
/// }
/// </code>
/// </summary>
public static string Update { get; } = "update";

/// <summary>
/// The destruction method. Deletes all the storage of the contract.
/// Should verify the signer's address using SYSCALL <code>Neo.Runtime.CheckWitness</code>.
/// Any tokens in the contract must be transferred before destruction.
/// <code>
/// {
/// "name": "destroy",
/// "safe": false,
/// "parameters": [],
/// "returntype": "Void"
/// }
/// </code>
/// </summary>
public static string Destroy { get; } = "destroy";

/// <summary>
/// Parameter counts for the methods.
/// -1 represents the method can take arbitrary parameters.
/// </summary>
public static int VerifyPCount { get; } = -1;
Comment thread
shargon marked this conversation as resolved.
public static int InitializePCount { get; } = 0;
public static int DeployPCount { get; } = 2;
public static int UpdatePCount { get; } = 3;
public static int DestroyPCount { get; } = 0;
}
}
2 changes: 1 addition & 1 deletion src/Neo/SmartContract/DeployedContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public DeployedContract(ContractState contract)

Script = null;
ScriptHash = contract.Hash;
ContractMethodDescriptor descriptor = contract.Manifest.Abi.GetMethod("verify", -1);
ContractMethodDescriptor descriptor = contract.Manifest.Abi.GetMethod(ContractBasicMethod.Verify, ContractBasicMethod.VerifyPCount);
if (descriptor is null) throw new NotSupportedException("The smart contract haven't got verify method.");

ParameterList = descriptor.Parameters.Select(u => u.Type).ToArray();
Expand Down
2 changes: 1 addition & 1 deletion src/Neo/SmartContract/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ internal static bool VerifyWitness(this IVerifiable verifiable, ProtocolSettings
{
ContractState cs = NativeContract.ContractManagement.GetContract(snapshot, hash);
if (cs is null) return false;
ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod("verify", -1);
ContractMethodDescriptor md = cs.Manifest.Abi.GetMethod(ContractBasicMethod.Verify, ContractBasicMethod.VerifyPCount);
if (md?.ReturnType != ContractParameterType.Boolean) return false;
engine.LoadContract(cs, md, CallFlags.ReadOnly);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Neo/SmartContract/Native/ContractManagement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ internal override ContractTask InitializeAsync(ApplicationEngine engine, Hardfor

private async ContractTask OnDeployAsync(ApplicationEngine engine, ContractState contract, StackItem data, bool update)
{
ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod("_deploy", 2);
ContractMethodDescriptor md = contract.Manifest.Abi.GetMethod(ContractBasicMethod.Deploy, ContractBasicMethod.DeployPCount);
if (md is not null)
await engine.CallFromNativeContractAsync(Hash, contract.Hash, md.Name, data, update);
engine.SendNotification(Hash, update ? "Update" : "Deploy", new VM.Types.Array(engine.ReferenceCounter) { contract.Hash.ToArray() });
Expand Down
2 changes: 1 addition & 1 deletion src/Neo/Wallets/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public static long CalculateNetworkFee(this Transaction tx, DataCache snapshot,
var contract = NativeContract.ContractManagement.GetContract(snapshot, hash);
if (contract is null)
throw new ArgumentException($"The smart contract or address {hash} is not found");
var md = contract.Manifest.Abi.GetMethod("verify", -1);
var md = contract.Manifest.Abi.GetMethod(ContractBasicMethod.Verify, ContractBasicMethod.VerifyPCount);
if (md is null)
throw new ArgumentException($"The smart contract {contract.Hash} haven't got verify method");
if (md.ReturnType != ContractParameterType.Boolean)
Expand Down
2 changes: 1 addition & 1 deletion src/Plugins/OracleService/OracleService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ public static Transaction CreateResponseTx(DataCache snapshot, OracleRequest req

var oracleContract = NativeContract.ContractManagement.GetContract(snapshot, NativeContract.Oracle.Hash);
var engine = ApplicationEngine.Create(TriggerType.Verification, tx, snapshot.CreateSnapshot(), settings: settings);
ContractMethodDescriptor md = oracleContract.Manifest.Abi.GetMethod("verify", -1);
ContractMethodDescriptor md = oracleContract.Manifest.Abi.GetMethod(ContractBasicMethod.Verify, ContractBasicMethod.VerifyPCount);
engine.LoadContract(oracleContract, md, CallFlags.None);
if (engine.Execute() != VMState.HALT) return null;
tx.NetworkFee += engine.FeeConsumed;
Expand Down
2 changes: 1 addition & 1 deletion src/Plugins/RpcServer/RpcServer.Wallet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ private JObject GetVerificationResult(UInt160 scriptHash, ContractParameter[] ar
{
using var snapshot = system.GetSnapshot();
var contract = NativeContract.ContractManagement.GetContract(snapshot, scriptHash).NotNull_Or(RpcError.UnknownContract);
var md = contract.Manifest.Abi.GetMethod("verify", -1).NotNull_Or(RpcErrorFactory.InvalidContractVerification(contract.Hash));
var md = contract.Manifest.Abi.GetMethod(ContractBasicMethod.Verify, ContractBasicMethod.VerifyPCount).NotNull_Or(RpcErrorFactory.InvalidContractVerification(contract.Hash));
(md.ReturnType == ContractParameterType.Boolean).True_Or(RpcErrorFactory.InvalidContractVerification("The verify method doesn't return boolean value."));
Transaction tx = new()
{
Expand Down