diff --git a/src/Neo/SmartContract/Native/NativeContract.cs b/src/Neo/SmartContract/Native/NativeContract.cs
index dc514468a4..e512a3d1ce 100644
--- a/src/Neo/SmartContract/Native/NativeContract.cs
+++ b/src/Neo/SmartContract/Native/NativeContract.cs
@@ -105,6 +105,11 @@ public CacheEntry GetAllowedMethods(NativeContract native, ApplicationEngine eng
///
public static Notary Notary { get; } = new();
+ ///
+ /// Gets the instance of the class.
+ ///
+ public static Treasury Treasury { get; } = new();
+
#endregion
///
diff --git a/src/Neo/SmartContract/Native/NeoToken.cs b/src/Neo/SmartContract/Native/NeoToken.cs
index 5032aeb409..3bc21d35fa 100644
--- a/src/Neo/SmartContract/Native/NeoToken.cs
+++ b/src/Neo/SmartContract/Native/NeoToken.cs
@@ -164,17 +164,17 @@ private BigInteger CalculateBonus(DataCache snapshot, NeoAccountState state, uin
// Compute Neo holder reward
// In the unit of datoshi, 1 GAS = 10^8 datoshi
- BigInteger sumNeoHold = 0;
+ BigInteger sumGasPerBlock = 0;
foreach (var (index, gasPerBlock) in GetSortedGasRecords(snapshot, end - 1))
{
if (index > start)
{
- sumNeoHold += gasPerBlock * (end - index);
+ sumGasPerBlock += gasPerBlock * (end - index);
end = index;
}
else
{
- sumNeoHold += gasPerBlock * (end - start);
+ sumGasPerBlock += gasPerBlock * (end - start);
break;
}
}
@@ -190,7 +190,7 @@ private BigInteger CalculateBonus(DataCache snapshot, NeoAccountState state, uin
voteReward = state.Balance * (latestGasPerVote - state.LastGasPerVote) / VoteFactor;
}
- return (state.Balance * sumNeoHold * NeoHolderRewardRatio / 100 / TotalAmount, voteReward);
+ return (state.Balance * sumGasPerBlock * NeoHolderRewardRatio / 100 / TotalAmount, voteReward);
}
private void CheckCandidate(DataCache snapshot, ECPoint pubkey, CandidateState candidate)
diff --git a/src/Neo/SmartContract/Native/Treasury.cs b/src/Neo/SmartContract/Native/Treasury.cs
new file mode 100644
index 0000000000..9aaff4ef7c
--- /dev/null
+++ b/src/Neo/SmartContract/Native/Treasury.cs
@@ -0,0 +1,66 @@
+// Copyright (C) 2015-2025 The Neo Project.
+//
+// Treasury.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.
+
+#nullable enable
+#pragma warning disable IDE0051
+
+using Neo.SmartContract.Manifest;
+using Neo.VM.Types;
+using System.Numerics;
+
+namespace Neo.SmartContract.Native
+{
+ ///
+ /// The Treasury native contract used for manage the treasury funds.
+ ///
+ public sealed class Treasury : NativeContract
+ {
+ internal Treasury() : base() { }
+
+ public override Hardfork? ActiveIn => Hardfork.HF_Faun;
+
+ protected override void OnManifestCompose(IsHardforkEnabledDelegate hfChecker, uint blockHeight, ContractManifest manifest)
+ {
+ manifest.SupportedStandards = ["NEP-26", "NEP-27"];
+ }
+
+ ///
+ /// Verify checks whether the transaction is signed by the committee.
+ ///
+ /// ApplicationEngine
+ /// Whether transaction is valid.
+ [ContractMethod(CpuFee = 1 << 5, RequiredCallFlags = CallFlags.ReadStates)]
+ private bool Verify(ApplicationEngine engine) => CheckCommittee(engine);
+
+ ///
+ /// OnNEP17Payment callback.
+ ///
+ /// ApplicationEngine
+ /// GAS sender
+ /// The amount of GAS sent
+ /// Optional data
+ [ContractMethod(CpuFee = 1 << 5, RequiredCallFlags = CallFlags.None)]
+ private void OnNEP17Payment(ApplicationEngine engine, UInt160 from, BigInteger amount, StackItem data) { }
+
+ ///
+ /// OnNEP11Payment callback.
+ ///
+ /// ApplicationEngine
+ /// GAS sender
+ /// The amount of GAS sent
+ /// Nep11 token Id
+ /// Optional data
+ [ContractMethod(CpuFee = 1 << 5, RequiredCallFlags = CallFlags.None)]
+ private void OnNEP11Payment(ApplicationEngine engine, UInt160 from, BigInteger amount, byte[] tokenId, StackItem data) { }
+ }
+}
+
+#nullable disable
diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs
index 03f58a8dbd..a364b638ad 100644
--- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs
+++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs
@@ -51,7 +51,8 @@ public void TestSetup()
{"PolicyContract", """{"id":-7,"updatecounter":0,"hash":"0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":2208257578},"manifest":{"name":"PolicyContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"blockAccount","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":0,"safe":false},{"name":"getAttributeFee","parameters":[{"name":"attributeType","type":"Integer"}],"returntype":"Integer","offset":7,"safe":true},{"name":"getBlockedAccounts","parameters":[],"returntype":"InteropInterface","offset":14,"safe":true},{"name":"getExecFeeFactor","parameters":[],"returntype":"Integer","offset":21,"safe":true},{"name":"getFeePerByte","parameters":[],"returntype":"Integer","offset":28,"safe":true},{"name":"getMaxTraceableBlocks","parameters":[],"returntype":"Integer","offset":35,"safe":true},{"name":"getMaxValidUntilBlockIncrement","parameters":[],"returntype":"Integer","offset":42,"safe":true},{"name":"getMillisecondsPerBlock","parameters":[],"returntype":"Integer","offset":49,"safe":true},{"name":"getStoragePrice","parameters":[],"returntype":"Integer","offset":56,"safe":true},{"name":"isBlocked","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":63,"safe":true},{"name":"setAttributeFee","parameters":[{"name":"attributeType","type":"Integer"},{"name":"value","type":"Integer"}],"returntype":"Void","offset":70,"safe":false},{"name":"setExecFeeFactor","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":77,"safe":false},{"name":"setFeePerByte","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":84,"safe":false},{"name":"setMaxTraceableBlocks","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":91,"safe":false},{"name":"setMaxValidUntilBlockIncrement","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":98,"safe":false},{"name":"setMillisecondsPerBlock","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":105,"safe":false},{"name":"setStoragePrice","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":112,"safe":false},{"name":"unblockAccount","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","offset":119,"safe":false}],"events":[{"name":"MillisecondsPerBlockChanged","parameters":[{"name":"old","type":"Integer"},{"name":"new","type":"Integer"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""},
{"RoleManagement", """{"id":-8,"updatecounter":0,"hash":"0x49cf4e5378ffcd4dec034fd98a174c5491e395e2","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0A=","checksum":983638438},"manifest":{"name":"RoleManagement","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"designateAsRole","parameters":[{"name":"role","type":"Integer"},{"name":"nodes","type":"Array"}],"returntype":"Void","offset":0,"safe":false},{"name":"getDesignatedByRole","parameters":[{"name":"role","type":"Integer"},{"name":"index","type":"Integer"}],"returntype":"Array","offset":7,"safe":true}],"events":[{"name":"Designation","parameters":[{"name":"Role","type":"Integer"},{"name":"BlockIndex","type":"Integer"},{"name":"Old","type":"Array"},{"name":"New","type":"Array"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""},
{"OracleContract", """{"id":-9,"updatecounter":0,"hash":"0xfe924b7cfe89ddd271abaf7210a80a7e11178758","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2663858513},"manifest":{"name":"OracleContract","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"finish","parameters":[],"returntype":"Void","offset":0,"safe":false},{"name":"getPrice","parameters":[],"returntype":"Integer","offset":7,"safe":true},{"name":"request","parameters":[{"name":"url","type":"String"},{"name":"filter","type":"String"},{"name":"callback","type":"String"},{"name":"userData","type":"Any"},{"name":"gasForResponse","type":"Integer"}],"returntype":"Void","offset":14,"safe":false},{"name":"setPrice","parameters":[{"name":"price","type":"Integer"}],"returntype":"Void","offset":21,"safe":false},{"name":"verify","parameters":[],"returntype":"Boolean","offset":28,"safe":true}],"events":[{"name":"OracleRequest","parameters":[{"name":"Id","type":"Integer"},{"name":"RequestContract","type":"Hash160"},{"name":"Url","type":"String"},{"name":"Filter","type":"String"}]},{"name":"OracleResponse","parameters":[{"name":"Id","type":"Integer"},{"name":"OriginalTx","type":"Hash256"}]}]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""},
- {"Notary", """{"id":-10,"updatecounter":0,"hash":"0xc1e14f19c3e60d0b9244d06dd7ba9b113135ec3b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"Notary","groups":[],"features":{},"supportedstandards":["NEP-27"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"expirationOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":7,"safe":true},{"name":"getMaxNotValidBeforeDelta","parameters":[],"returntype":"Integer","offset":14,"safe":true},{"name":"lockDepositUntil","parameters":[{"name":"account","type":"Hash160"},{"name":"till","type":"Integer"}],"returntype":"Boolean","offset":21,"safe":false},{"name":"onNEP17Payment","parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","offset":28,"safe":false},{"name":"setMaxNotValidBeforeDelta","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":35,"safe":false},{"name":"verify","parameters":[{"name":"signature","type":"ByteArray"}],"returntype":"Boolean","offset":42,"safe":true},{"name":"withdraw","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"}],"returntype":"Boolean","offset":49,"safe":false}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}
+ {"Notary", """{"id":-10,"updatecounter":0,"hash":"0xc1e14f19c3e60d0b9244d06dd7ba9b113135ec3b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"Notary","groups":[],"features":{},"supportedstandards":["NEP-27"],"abi":{"methods":[{"name":"balanceOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":0,"safe":true},{"name":"expirationOf","parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","offset":7,"safe":true},{"name":"getMaxNotValidBeforeDelta","parameters":[],"returntype":"Integer","offset":14,"safe":true},{"name":"lockDepositUntil","parameters":[{"name":"account","type":"Hash160"},{"name":"till","type":"Integer"}],"returntype":"Boolean","offset":21,"safe":false},{"name":"onNEP17Payment","parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","offset":28,"safe":false},{"name":"setMaxNotValidBeforeDelta","parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","offset":35,"safe":false},{"name":"verify","parameters":[{"name":"signature","type":"ByteArray"}],"returntype":"Boolean","offset":42,"safe":true},{"name":"withdraw","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"}],"returntype":"Boolean","offset":49,"safe":false}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""},
+ {"Treasury", """{"id":-11,"updatecounter":0,"hash":"0x156326f25b1b5d839a4d326aeaa75383c9563ac1","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dA","checksum":1592866325},"manifest":{"name":"Treasury","groups":[],"features":{},"supportedstandards":["NEP-26","NEP-27"],"abi":{"methods":[{"name":"onNEP11Payment","parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"tokenId","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Void","offset":0,"safe":true},{"name":"onNEP17Payment","parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","offset":7,"safe":true},{"name":"verify","parameters":[],"returntype":"Boolean","offset":14,"safe":true}],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"extra":null}}"""}
};
}
@@ -163,9 +164,10 @@ public void TestNativeContractId()
Assert.AreEqual(-7, NativeContract.Policy.Id);
Assert.AreEqual(-8, NativeContract.RoleManagement.Id);
Assert.AreEqual(-9, NativeContract.Oracle.Id);
+ Assert.AreEqual(-10, NativeContract.Notary.Id);
+ Assert.AreEqual(-11, NativeContract.Treasury.Id);
}
-
class TestSpecialParameter
{
[ContractMethod]