-
Notifications
You must be signed in to change notification settings - Fork 1k
[N3] Request blocked funds #4328
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
Open
shargon
wants to merge
38
commits into
neo-project:master-n3
Choose a base branch
from
shargon:request-blocked-funds
base: master-n3
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+185
−7
Open
Changes from 34 commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
c9662dc
Request blocked funds
shargon 45c442c
fake witness to allow transfers in any NEP17
shargon a10011f
Use Treasury hash
shargon 7be6d38
6 months
shargon 3f5dc7c
Merge remote-tracking branch 'origin/master-n3' into request-blocked-…
shargon cbcdfeb
Merge branch 'master-n3' into request-blocked-funds
shargon bbb20d6
Update src/Neo/SmartContract/Native/PolicyContract.cs
shargon aacebf6
Merge branch 'master-n3' into request-blocked-funds
shargon 2939a5c
One year time
shargon 6c2ab43
Fix improve
shargon a59d9cb
Clean code
shargon 9d0974f
Ensure NativeCallingScriptHash change
shargon 0b3e3d8
format
shargon 083f41e
Fix ut
shargon d85f6c5
Merge branch 'master-n3' into request-blocked-funds
shargon a73bb20
dotnet format
shargon 50532ee
Fix compilation
ajara87 f9416b1
Merge pull request #19 from ajara87/pr-4328
shargon 8f70d78
Update src/Neo/SmartContract/Native/PolicyContract.cs
shargon 04febb0
Add events
shargon 364df1f
Anna's and superboy's feedback
shargon f3341bf
Fix one node network
shargon ab2e5b3
Superboy and Erik's feedback
shargon 83805d4
Avoid Expect integer type
shargon 6b25341
Invoke manually
shargon b0f2897
avoid multiple debuggers
shargon 04bb62f
Update tests/Neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs
shargon 1f15256
Update src/Neo/SmartContract/Native/NativeContract.cs
shargon 0e8fd58
Roman's feedback
shargon b673923
Unify tests
shargon cefe1f2
Use block for start recover
shargon f40f1a0
Fix UT
shargon af77c5d
Merge branch 'master-n3' into request-blocked-funds
shargon 9b51e77
Use current registry for store time
shargon 7a8bec6
Update src/Neo/SmartContract/Native/PolicyContract.cs
shargon 295b29a
Update tests/Neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs
shargon f773720
One token
shargon 604cdfa
Update src/Neo/SmartContract/Native/NativeContract.cs
shargon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,8 +16,10 @@ | |
| using Neo.Persistence; | ||
| using Neo.SmartContract.Iterators; | ||
| using Neo.SmartContract.Manifest; | ||
| using Neo.VM.Types; | ||
| using System; | ||
| using System.Buffers.Binary; | ||
| using System.Collections.Generic; | ||
| using System.Diagnostics.CodeAnalysis; | ||
| using System.Linq; | ||
| using System.Numerics; | ||
|
|
@@ -103,12 +105,13 @@ public sealed class PolicyContract : NativeContract | |
| private readonly StorageKey _millisecondsPerBlock; | ||
| private readonly StorageKey _maxValidUntilBlockIncrement; | ||
| private readonly StorageKey _maxTraceableBlocks; | ||
| private const ulong RequiredTimeForRecoverFunds = 365 * 24 * 60 * 60 * 1_000UL; // 1 year in milliseconds | ||
|
|
||
| /// <summary> | ||
| /// The event name for the block generation time changed. | ||
| /// </summary> | ||
| private const string MillisecondsPerBlockChangedEventName = "MillisecondsPerBlockChanged"; | ||
|
|
||
| private const string RecoveredFundsEventName = "RecoveredFunds"; | ||
| private const string WhitelistChangedEventName = "WhitelistFeeChanged"; | ||
|
|
||
| [ContractEvent(Hardfork.HF_Echidna, 0, name: MillisecondsPerBlockChangedEventName, | ||
|
|
@@ -121,6 +124,7 @@ public sealed class PolicyContract : NativeContract | |
| "argCount", ContractParameterType.Integer, | ||
| "fee", ContractParameterType.Any | ||
| )] | ||
| [ContractEvent(Hardfork.HF_Faun, 3, name: RecoveredFundsEventName, "account", ContractParameterType.Hash160)] | ||
shargon marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| internal PolicyContract() : base() | ||
| { | ||
| _feePerByte = CreateStorageKey(Prefix_FeePerByte); | ||
|
|
@@ -583,12 +587,27 @@ internal async ContractTask<bool> BlockAccountInternal(ApplicationEngine engine, | |
|
|
||
| var key = CreateStorageKey(Prefix_BlockedAccount, account); | ||
|
|
||
| if (engine.SnapshotCache.Contains(key)) return false; | ||
| var blockData = engine.SnapshotCache.TryGet(key); | ||
| if (blockData != null) | ||
| { | ||
| // Check if it is stored the recover funds time | ||
| if (blockData.Value.Length == 0 && engine.IsHardforkEnabled(Hardfork.HF_Faun)) | ||
| { | ||
| // Don't modify it if already exists | ||
| blockData.Set(engine.GetTime()); | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| if (engine.IsHardforkEnabled(Hardfork.HF_Faun)) | ||
| await NEO.VoteInternal(engine, account, null); | ||
|
|
||
| engine.SnapshotCache.Add(key, new StorageItem([])); | ||
| engine.SnapshotCache.Add(key, | ||
| // Set request time for recover funds | ||
| engine.IsHardforkEnabled(Hardfork.HF_Faun) ? new StorageItem(engine.GetTime()) | ||
| : new StorageItem([])); | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
|
|
@@ -597,7 +616,6 @@ private bool UnblockAccount(ApplicationEngine engine, UInt160 account) | |
| { | ||
| AssertCommittee(engine); | ||
|
|
||
|
|
||
| var key = CreateStorageKey(Prefix_BlockedAccount, account); | ||
| if (!engine.SnapshotCache.Contains(key)) return false; | ||
|
|
||
|
|
@@ -615,6 +633,76 @@ private StorageIterator GetBlockedAccounts(DataCache snapshot) | |
| return new StorageIterator(enumerator, 1, options); | ||
| } | ||
|
|
||
| [ContractMethod(Hardfork.HF_Faun, CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] | ||
| internal async ContractTask RecoverFunds(ApplicationEngine engine, UInt160 account, VM.Types.Array extraTokens) | ||
| { | ||
| var committeeMultiSigAddr = AssertAlmostFullCommittee(engine); | ||
|
|
||
| // Set request time | ||
|
|
||
| var key = CreateStorageKey(Prefix_BlockedAccount, account); | ||
| var entry = engine.SnapshotCache.GetAndChange(key, null) | ||
| ?? throw new InvalidOperationException("Request not found."); | ||
| if (engine.GetTime() - (BigInteger)entry < RequiredTimeForRecoverFunds) | ||
| throw new InvalidOperationException("Request must be signed at least 1 year ago."); | ||
|
|
||
| // Validate and collect extra NEP17 tokens | ||
|
|
||
| var validatedTokens = new HashSet<UInt160> | ||
| { | ||
| NEO.Hash, | ||
| GAS.Hash | ||
| }; | ||
|
|
||
| foreach (var tokenItem in extraTokens) | ||
shargon marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| var span = tokenItem.GetSpan(); | ||
| if (span.Length != UInt160.Length) | ||
| throw new ArgumentException($"Invalid token hash length: expected {UInt160.Length} bytes, got {span.Length} bytes."); | ||
|
|
||
| var contractHash = new UInt160(span); | ||
|
|
||
| // Validate contract exists | ||
| var contract = ContractManagement.GetContract(engine.SnapshotCache, contractHash); | ||
| if (contract == null) | ||
| throw new InvalidOperationException($"Contract {contractHash} does not exist."); | ||
|
|
||
| // Validate contract implements NEP-17 standard | ||
| if (!contract.Manifest.SupportedStandards.Contains("NEP-17")) | ||
| throw new InvalidOperationException($"Contract {contractHash} does not implement NEP-17 standard."); | ||
|
|
||
| // Prevent NEO and GAS from being in extraTokens | ||
| if (contractHash == NEO.Hash || contractHash == GAS.Hash) | ||
| throw new InvalidOperationException($"NEO and GAS should not be included in extraTokens. They are automatically processed."); | ||
|
|
||
| // Prevent duplicate tokens | ||
| if (!validatedTokens.Add(contractHash)) | ||
| throw new InvalidOperationException($"Duplicate token {contractHash} in extraTokens."); | ||
| } | ||
|
|
||
| // Remove and notify | ||
|
|
||
| engine.SendNotification(Hash, RecoveredFundsEventName, [new ByteString(account.ToArray())]); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't it be sent after the transter? |
||
|
|
||
| // Transfer funds, NEO, GAS and extra NEP17 tokens | ||
|
|
||
| foreach (var contractHash in validatedTokens) | ||
| { | ||
| // Check balance | ||
| var balance = await engine.CallFromNativeContractAsync<BigInteger>(account, contractHash, "balanceOf", account.ToArray()); | ||
|
|
||
| if (balance > 0) | ||
| { | ||
| // transfer | ||
| var result = await engine.CallFromNativeContractAsync<bool>(account, contractHash, "transfer", | ||
shargon marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| account.ToArray(), NativeContract.Treasury.Hash.ToArray(), balance, StackItem.Null); | ||
|
|
||
| if (!result) | ||
| throw new InvalidOperationException($"Transfer of {balance} from {account} to {committeeMultiSigAddr} failed in contract {contractHash}."); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| [ContractMethod(Hardfork.HF_Faun, CpuFee = 1 << 15, RequiredCallFlags = CallFlags.ReadStates)] | ||
| internal StorageIterator GetWhitelistFeeContracts(DataCache snapshot) | ||
| { | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.