-
Notifications
You must be signed in to change notification settings - Fork 0
Fix UTs and known issue on Neo #3
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
Changes from all commits
2c2f0b5
598451b
af6581a
7ea4ed6
11db118
47fa7b1
5b3bea6
2b9c218
6fa9dc5
9e673e0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -460,9 +460,58 @@ void _OnBalanceChanged(ApplicationEngine engine, UInt160 assetId, UInt160 accoun | |
| async ContractTask _OnTransfer(ApplicationEngine engine, UInt160 assetId, UInt160 from, UInt160 to, BigInteger amount, StackItem data) | ||
| { | ||
| if (assetId != NeoTokenId) return; | ||
| var list = engine.CurrentContext!.GetState<ExecutionContextState>().CallingContext!.GetState<List<GasDistribution>>(); | ||
| foreach (var distribution in list) | ||
| await TokenManagement.MintInternal(engine, GasTokenId, distribution.Account, distribution.Amount, assertOwner: false, callOnBalanceChanged: false, callOnPayment: true, callOnTransfer: false); | ||
| if (amount.IsZero || from == to) | ||
| { | ||
| // Handle unclaimed gas distribution when transferring zero amount | ||
| // This allows claiming unclaimed gas by transferring 0 NEO | ||
| StorageKey key = CreateStorageKey(Prefix_NeoAccount, from); | ||
| var accountState = engine.SnapshotCache.GetAndChange(key)?.GetInteroperable<NeoAccountState>(); | ||
| if (accountState is null) return; | ||
| BigInteger balance = NativeContract.TokenManagement.BalanceOf(engine.SnapshotCache, NeoTokenId, from); | ||
| GasDistribution? distribution = DistributeGas(engine, from, accountState, balance); | ||
| if (distribution is not null) | ||
| await TokenManagement.MintInternal(engine, GasTokenId, distribution.Account, distribution.Amount, assertOwner: false, callOnBalanceChanged: false, callOnPayment: true, callOnTransfer: false); | ||
| } | ||
| else | ||
| { | ||
| var list = engine.CurrentContext!.GetState<ExecutionContextState>().CallingContext!.GetState<List<GasDistribution>>(); | ||
| foreach (var distribution in list) | ||
| await TokenManagement.MintInternal(engine, GasTokenId, distribution.Account, distribution.Amount, assertOwner: false, callOnBalanceChanged: false, callOnPayment: true, callOnTransfer: false); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Handles payment callback for validator registration. | ||
| /// </summary> | ||
| /// <param name="engine">The engine used to process the payment.</param> | ||
| /// <param name="assetId">The asset identifier.</param> | ||
| /// <param name="from">The sender account.</param> | ||
| /// <param name="amount">The amount of tokens sent.</param> | ||
| /// <param name="data">Optional data containing the public key for registration.</param> | ||
| [ContractMethod(CpuFee = 1 << 15, RequiredCallFlags = CallFlags.States | CallFlags.AllowNotify)] | ||
| private async ContractTask _OnPayment(ApplicationEngine engine, UInt160 assetId, UInt160 from, BigInteger amount, StackItem data) | ||
| { | ||
| // Only accept GAS for validator registration, not NEO | ||
| if (assetId != GasTokenId) | ||
| throw new InvalidOperationException($"Only GAS can be accepted for validator registration, got {assetId}"); | ||
|
|
||
| // Check if the amount matches the registration price | ||
| long registerPrice = GetRegisterPrice(engine.SnapshotCache); | ||
| if ((long)amount != registerPrice) | ||
| throw new ArgumentOutOfRangeException(nameof(amount), $"Amount must equal the registration price {registerPrice}, got {amount}"); | ||
|
|
||
| // Extract public key from data | ||
| if (data is not ByteString dataBytes || dataBytes.GetSpan().Length == 0) | ||
| throw new FormatException("Data parameter must contain the public key for registration"); | ||
|
|
||
| ECPoint pubkey = ECPoint.DecodePoint(dataBytes.GetSpan(), ECCurve.Secp256r1); | ||
|
|
||
| // Register the candidate | ||
| if (!RegisterInternal(engine, pubkey)) | ||
| throw new InvalidOperationException("Failed to register candidate. The witness does not match the public key."); | ||
|
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. how about if it is already registered? 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. Maybe it is good to return false as well |
||
|
|
||
| // Burn the registration fee (the GAS sent to this contract) | ||
| await TokenManagement.BurnInternal(engine, GasTokenId, Hash, amount, assertOwner: false, callOnBalanceChanged: false, callOnTransfer: false); | ||
| } | ||
|
|
||
| GasDistribution? DistributeGas(ApplicationEngine engine, UInt160 account, NeoAccountState state, BigInteger balance) | ||
|
|
||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have to keep this?
RegisterCandidatedoesn't work?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both can work. Just keep it compatible. Not bad but more convenient.