From b9a89fa18c3ffbcfc446922f9e15734a4b9566a1 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Thu, 4 Nov 2021 09:57:13 +0800 Subject: [PATCH 01/30] Preliminary BurgerGov for governance token --- BurgerGov.cs | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 BurgerGov.cs diff --git a/BurgerGov.cs b/BurgerGov.cs new file mode 100644 index 0000000..daf9c7c --- /dev/null +++ b/BurgerGov.cs @@ -0,0 +1,172 @@ +using System.Numerics; +using Neo; +using Neo.SmartContract; +using Neo.SmartContract.Framework; +using Neo.SmartContract.Framework.Native; +using Neo.SmartContract.Framework.Services; +using Neo.SmartContract.Framework.Attributes; + +//vote; store a call to contract to be voted +//delegate others to vote for me; +//default delegate + +//storage: +//proposal[i]: the contract scripthash to call +//proposal[i]voting_period +//proposal[i]method +//proposal[i]argcount +//proposal[i]arg[j] + +//delegate[UInt160 from] == to +//[DEPRECATED]//delegate_count[UInt160 to] == how many people delegated their votes to `to` +//[DEPRECATED]//delegate_to[UInt160 to][k] == UInt160 from +//[DEPRECATED]//delegate_from_index[UInt160 to][UInt160 from] == k +//vote[from][i] == True/False + + +namespace NeoBurger +{ + [ManifestExtra("Author", "NEOBURGER")] + [ManifestExtra("Email", "developer@neo.org")] + [ManifestExtra("Description", "NeoBurger Governance Token")] + [SupportedStandards("NEP-17")] + [ContractPermission("*", "*")] + public class BurgerGov : Nep17Token + { + // DO NOT USE the prefix 0x14, because this is the key prefix for NEP-17 token account balance + [InitialValue("Nb2CHYY5wTh2ac58mTue5S3wpG6bQv5hSY", ContractParameterType.Hash160)] + private static readonly UInt160 DEFAULT_OWNER = default; + private static readonly byte PREFIX_OWNER = 0xff; + private static readonly byte PREFIX_PROPOSAL = 0x01; + private static readonly byte PREFIX_PROPOSAL_SCRIPT_HASH = 0x02; + private static readonly byte PREFIX_PROPOSAL_ID = 0x03; + private static readonly byte PREFIX_PROPOSAL_METHOD = 0x04; + private static readonly byte PREFIX_PROPOSAL_ARG = 0x05; + private static readonly byte PREFIX_PROPOSAL_ARG_COUNT = 0x06; + private static readonly byte PREFIX_PROPOSAL_VOTING_DEADLINE = 0x07; + private static readonly byte PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING = 0x08; + private static readonly byte PREFIX_DELEGATE = 0x81; + private static readonly byte PREFIX_VOTE = 0xc1; + + public override byte Decimals() => 8; + public override string Symbol() => "bNEOg"; + public static UInt160 Owner() => (UInt160)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_OWNER }); + public static BigInteger MinimalTimePeriodForVoting() => + (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }); + // milliseconds; 86400000 for one day + + public static void _deploy(object data, bool update) + { + if (!update) + { + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_OWNER }, DEFAULT_OWNER); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, 1); // initial proposal ID + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }, 86400000 * 7); + } + } + + public static void SetOwner(UInt160 owner) + { + ExecutionEngine.Assert(Runtime.CheckWitness(Owner())); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_OWNER }, owner); + } + public static void SetMinimalTimePeriodForVoting(BigInteger minimal_time_period) + { + ExecutionEngine.Assert(Runtime.CheckWitness(Owner())); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }, minimal_time_period); + } + public static object[] ProposalAttributes(BigInteger id) + { + StorageMap proposal_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id); + UInt160 scripthash = (UInt160)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_SCRIPT_HASH }); + ByteString method = proposal_map.Get(new byte[] { PREFIX_PROPOSAL_METHOD }); + BigInteger arg_count = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_ARG_COUNT }); + ByteString[] args = new ByteString[(int)arg_count]; + StorageMap arg_map = new StorageMap(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id + PREFIX_PROPOSAL_ARG); + for(BigInteger j = 1; j <= arg_count; j++) + { + args[(int)j - 1] = arg_map.Get((ByteString)j); + } + BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); + return new object[] { scripthash, method, args, voting_deadline }; + } + + public static BigInteger NewProposal(UInt160 scripthash, string method, ByteString[] args, BigInteger voting_period) + { + ExecutionEngine.Assert(Runtime.CheckWitness(Owner())); + if (voting_period < MinimalTimePeriodForVoting()) + throw new System.Exception("Too short voting period"); + BigInteger proposal_id = (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, proposal_id + 1); + StorageMap proposal_id_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_id); + proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_SCRIPT_HASH }, scripthash); + proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }, voting_period + Runtime.Time); + proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_METHOD }, method); + proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_ARG_COUNT }, args.Length); + StorageMap arg_map = new StorageMap(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_id + PREFIX_PROPOSAL_ARG); + for(BigInteger j = 1; j <= args.Length; j++) + { + arg_map.Put((ByteString)j, args[(int)j - 1]); + } + return proposal_id; + } + + public static void Delegate(UInt160 from, UInt160 to) + { + ExecutionEngine.Assert(Runtime.CheckWitness(from)); + StorageMap delegate_map = new(Storage.CurrentContext, PREFIX_DELEGATE); + if (to == UInt160.Zero || to == from) + { + delegate_map.Delete(from); + } + else + { + delegate_map.Put(from, to); + } + } + + public static UInt160 GetDelegate(UInt160 from) + { + StorageMap delegate_map = new(Storage.CurrentContext, PREFIX_DELEGATE); + return (UInt160)delegate_map.Get(from); + } + + public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_against) + { + ExecutionEngine.Assert(Runtime.CheckWitness(from)); + StorageMap proposal_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_index); + BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); + if(Runtime.Time > voting_deadline) + { + throw new System.Exception("Cannot vote after the deadline"); + } + StorageMap vote_map = new(Storage.CurrentContext, PREFIX_VOTE); + ByteString key = from + (ByteString)proposal_index; + if (for_or_against) + { + vote_map.Put(key, 1); + } + else + { + vote_map.Delete(key); + } + } + public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) + { + StorageMap vote_map = new(Storage.CurrentContext, PREFIX_VOTE); + ByteString key = from + (ByteString)proposal_index; + return (BigInteger)vote_map.Get(key); + } + + public static void OnNEP17Payment(UInt160 from, BigInteger amount, object data) + { + throw new System.Exception("Not implemented for now"); + } + + public static void Update(ByteString nefFile, string manifest) + { + ExecutionEngine.Assert(Runtime.CheckWitness(Owner())); + ContractManagement.Update(nefFile, manifest, null); + } + } +} From a1a155c7d623f6ea2b328a801583aa5e446e9e27 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Thu, 4 Nov 2021 11:59:40 +0800 Subject: [PATCH 02/30] throw "The proposal does not exist" when voting_deadline == 0 --- BurgerGov.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/BurgerGov.cs b/BurgerGov.cs index daf9c7c..8ae3d63 100644 --- a/BurgerGov.cs +++ b/BurgerGov.cs @@ -136,6 +136,10 @@ public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_aga ExecutionEngine.Assert(Runtime.CheckWitness(from)); StorageMap proposal_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_index); BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); + if (voting_deadline == 0) + { + throw new System.Exception("The proposal does not exist"); + } if(Runtime.Time > voting_deadline) { throw new System.Exception("Cannot vote after the deadline"); From 138228a99beb64af95219a81a946a35220cbdede Mon Sep 17 00:00:00 2001 From: vang1ong7ang Date: Thu, 4 Nov 2021 00:07:53 -0400 Subject: [PATCH 03/30] Update BurgerGov.cs --- BurgerGov.cs | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/BurgerGov.cs b/BurgerGov.cs index 8ae3d63..1a20030 100644 --- a/BurgerGov.cs +++ b/BurgerGov.cs @@ -1,4 +1,4 @@ -using System.Numerics; +using System.Numerics; using Neo; using Neo.SmartContract; using Neo.SmartContract.Framework; @@ -6,23 +6,6 @@ using Neo.SmartContract.Framework.Services; using Neo.SmartContract.Framework.Attributes; -//vote; store a call to contract to be voted -//delegate others to vote for me; -//default delegate - -//storage: -//proposal[i]: the contract scripthash to call -//proposal[i]voting_period -//proposal[i]method -//proposal[i]argcount -//proposal[i]arg[j] - -//delegate[UInt160 from] == to -//[DEPRECATED]//delegate_count[UInt160 to] == how many people delegated their votes to `to` -//[DEPRECATED]//delegate_to[UInt160 to][k] == UInt160 from -//[DEPRECATED]//delegate_from_index[UInt160 to][UInt160 from] == k -//vote[from][i] == True/False - namespace NeoBurger { From de82d6ab022797bbf54aae75bbe287c1dd2eb618 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Thu, 4 Nov 2021 12:45:46 +0800 Subject: [PATCH 04/30] Change filename, class name and token symbol; remove owner; remove `if (!update)`; allow NEP17Payment; on-line readonly methods --- BurgerGov.cs => NeoBurgerGovernanceToken.cs | 69 +++++---------------- 1 file changed, 17 insertions(+), 52 deletions(-) rename BurgerGov.cs => NeoBurgerGovernanceToken.cs (66%) diff --git a/BurgerGov.cs b/NeoBurgerGovernanceToken.cs similarity index 66% rename from BurgerGov.cs rename to NeoBurgerGovernanceToken.cs index 8ae3d63..c4657c5 100644 --- a/BurgerGov.cs +++ b/NeoBurgerGovernanceToken.cs @@ -31,12 +31,9 @@ namespace NeoBurger [ManifestExtra("Description", "NeoBurger Governance Token")] [SupportedStandards("NEP-17")] [ContractPermission("*", "*")] - public class BurgerGov : Nep17Token + public class NeoBurgerGovernanceToken : Nep17Token { // DO NOT USE the prefix 0x14, because this is the key prefix for NEP-17 token account balance - [InitialValue("Nb2CHYY5wTh2ac58mTue5S3wpG6bQv5hSY", ContractParameterType.Hash160)] - private static readonly UInt160 DEFAULT_OWNER = default; - private static readonly byte PREFIX_OWNER = 0xff; private static readonly byte PREFIX_PROPOSAL = 0x01; private static readonly byte PREFIX_PROPOSAL_SCRIPT_HASH = 0x02; private static readonly byte PREFIX_PROPOSAL_ID = 0x03; @@ -49,51 +46,31 @@ public class BurgerGov : Nep17Token private static readonly byte PREFIX_VOTE = 0xc1; public override byte Decimals() => 8; - public override string Symbol() => "bNEOg"; - public static UInt160 Owner() => (UInt160)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_OWNER }); - public static BigInteger MinimalTimePeriodForVoting() => - (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }); + public override string Symbol() => "NOBUG"; + // public static UInt160 Owner() => Runtime.ExecutingScriptHash; + public static BigInteger MinimalTimePeriodForVoting() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }); // milliseconds; 86400000 for one day + public static object[] ProposalAttributes(BigInteger id) {StorageMap proposal_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id);UInt160 scripthash = (UInt160)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_SCRIPT_HASH });ByteString method = proposal_map.Get(new byte[] { PREFIX_PROPOSAL_METHOD });BigInteger arg_count = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_ARG_COUNT });ByteString[] args = new ByteString[(int)arg_count];StorageMap arg_map = new StorageMap(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id + PREFIX_PROPOSAL_ARG);for (BigInteger j = 1; j <= arg_count; j++){args[(int)j - 1] = arg_map.Get((ByteString)j);}BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE });return new object[] { scripthash, method, args, voting_deadline };} + public static UInt160 GetDelegate(UInt160 from) => (UInt160)new StorageMap(Storage.CurrentContext, PREFIX_DELEGATE).Get(from); + public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, PREFIX_VOTE).Get(from + (ByteString)proposal_index); + + public static void _deploy(object data, bool update) { - if (!update) - { - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_OWNER }, DEFAULT_OWNER); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, 1); // initial proposal ID - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }, 86400000 * 7); - } + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, 1); // initial proposal ID + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }, 86400000 * 7); } - public static void SetOwner(UInt160 owner) - { - ExecutionEngine.Assert(Runtime.CheckWitness(Owner())); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_OWNER }, owner); - } public static void SetMinimalTimePeriodForVoting(BigInteger minimal_time_period) { - ExecutionEngine.Assert(Runtime.CheckWitness(Owner())); + ExecutionEngine.Assert(Runtime.CheckWitness(Runtime.ExecutingScriptHash)); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }, minimal_time_period); } - public static object[] ProposalAttributes(BigInteger id) - { - StorageMap proposal_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id); - UInt160 scripthash = (UInt160)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_SCRIPT_HASH }); - ByteString method = proposal_map.Get(new byte[] { PREFIX_PROPOSAL_METHOD }); - BigInteger arg_count = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_ARG_COUNT }); - ByteString[] args = new ByteString[(int)arg_count]; - StorageMap arg_map = new StorageMap(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id + PREFIX_PROPOSAL_ARG); - for(BigInteger j = 1; j <= arg_count; j++) - { - args[(int)j - 1] = arg_map.Get((ByteString)j); - } - BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); - return new object[] { scripthash, method, args, voting_deadline }; - } - public static BigInteger NewProposal(UInt160 scripthash, string method, ByteString[] args, BigInteger voting_period) { - ExecutionEngine.Assert(Runtime.CheckWitness(Owner())); + // Anyone can launch new proposal! + // ExecutionEngine.Assert(Runtime.CheckWitness(Owner())); if (voting_period < MinimalTimePeriodForVoting()) throw new System.Exception("Too short voting period"); BigInteger proposal_id = (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }); @@ -125,12 +102,6 @@ public static void Delegate(UInt160 from, UInt160 to) } } - public static UInt160 GetDelegate(UInt160 from) - { - StorageMap delegate_map = new(Storage.CurrentContext, PREFIX_DELEGATE); - return (UInt160)delegate_map.Get(from); - } - public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_against) { ExecutionEngine.Assert(Runtime.CheckWitness(from)); @@ -155,21 +126,15 @@ public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_aga vote_map.Delete(key); } } - public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) - { - StorageMap vote_map = new(Storage.CurrentContext, PREFIX_VOTE); - ByteString key = from + (ByteString)proposal_index; - return (BigInteger)vote_map.Get(key); - } - public static void OnNEP17Payment(UInt160 from, BigInteger amount, object data) { - throw new System.Exception("Not implemented for now"); + //do nothing for now + //throw new System.Exception("Not implemented for now"); } public static void Update(ByteString nefFile, string manifest) { - ExecutionEngine.Assert(Runtime.CheckWitness(Owner())); + ExecutionEngine.Assert(Runtime.CheckWitness(Runtime.ExecutingScriptHash)); ContractManagement.Update(nefFile, manifest, null); } } From 5102dd8e64926cc625a852434433d1dff72dcb60 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Thu, 4 Nov 2021 14:49:32 +0800 Subject: [PATCH 05/30] remove comments --- NeoBurgerGovernanceToken.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 7defd90..924907f 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -1,6 +1,5 @@ using System.Numerics; using Neo; -using Neo.SmartContract; using Neo.SmartContract.Framework; using Neo.SmartContract.Framework.Native; using Neo.SmartContract.Framework.Services; @@ -16,7 +15,6 @@ namespace NeoBurger [ContractPermission("*", "*")] public class NeoBurgerGovernanceToken : Nep17Token { - // DO NOT USE the prefix 0x14, because this is the key prefix for NEP-17 token account balance private static readonly byte PREFIX_PROPOSAL = 0x01; private static readonly byte PREFIX_PROPOSAL_SCRIPT_HASH = 0x02; private static readonly byte PREFIX_PROPOSAL_ID = 0x03; @@ -30,9 +28,7 @@ public class NeoBurgerGovernanceToken : Nep17Token public override byte Decimals() => 8; public override string Symbol() => "NOBUG"; - // public static UInt160 Owner() => Runtime.ExecutingScriptHash; public static BigInteger MinimalTimePeriodForVoting() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }); - // milliseconds; 86400000 for one day public static object[] ProposalAttributes(BigInteger id) {StorageMap proposal_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id);UInt160 scripthash = (UInt160)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_SCRIPT_HASH });ByteString method = proposal_map.Get(new byte[] { PREFIX_PROPOSAL_METHOD });BigInteger arg_count = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_ARG_COUNT });ByteString[] args = new ByteString[(int)arg_count];StorageMap arg_map = new StorageMap(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id + PREFIX_PROPOSAL_ARG);for (BigInteger j = 1; j <= arg_count; j++){args[(int)j - 1] = arg_map.Get((ByteString)j);}BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE });return new object[] { scripthash, method, args, voting_deadline };} public static UInt160 GetDelegate(UInt160 from) => (UInt160)new StorageMap(Storage.CurrentContext, PREFIX_DELEGATE).Get(from); @@ -41,7 +37,7 @@ public class NeoBurgerGovernanceToken : Nep17Token public static void _deploy(object data, bool update) { - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, 1); // initial proposal ID + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, 1); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }, 86400000 * 7); } @@ -52,8 +48,6 @@ public static void SetMinimalTimePeriodForVoting(BigInteger minimal_time_period) } public static BigInteger NewProposal(UInt160 scripthash, string method, ByteString[] args, BigInteger voting_period) { - // Anyone can launch new proposal! - // ExecutionEngine.Assert(Runtime.CheckWitness(Owner())); if (voting_period < MinimalTimePeriodForVoting()) throw new System.Exception("Too short voting period"); BigInteger proposal_id = (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }); @@ -111,8 +105,7 @@ public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_aga } public static void OnNEP17Payment(UInt160 from, BigInteger amount, object data) { - //do nothing for now - //throw new System.Exception("Not implemented for now"); + return; } public static void Update(ByteString nefFile, string manifest) From f9e385b5cbe00529e4de0ab2e2818a30e8f76b9e Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Thu, 4 Nov 2021 17:06:17 +0800 Subject: [PATCH 06/30] NOT PRODUCTION READY. Examine votes on chain with delegation and default delegate. --- NeoBurgerGovernanceToken.cs | 99 +++++++++++++++++++++++++++++++++---- 1 file changed, 89 insertions(+), 10 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 924907f..8751068 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -1,3 +1,4 @@ +using System; using System.Numerics; using Neo; using Neo.SmartContract.Framework; @@ -22,25 +23,68 @@ public class NeoBurgerGovernanceToken : Nep17Token private static readonly byte PREFIX_PROPOSAL_ARG = 0x05; private static readonly byte PREFIX_PROPOSAL_ARG_COUNT = 0x06; private static readonly byte PREFIX_PROPOSAL_VOTING_DEADLINE = 0x07; - private static readonly byte PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING = 0x08; + private static readonly byte PREFIX_PROPOSAL_EXECUTED_TIME = 0x08; private static readonly byte PREFIX_DELEGATE = 0x81; + private static readonly byte PREFIX_DEFAULT_DELEGATE = 0x82; + private static readonly byte PREFIX_DELEGATE_THRESHOLD = 0x83; private static readonly byte PREFIX_VOTE = 0xc1; + private static readonly byte PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING = 0xc2; public override byte Decimals() => 8; public override string Symbol() => "NOBUG"; public static BigInteger MinimalTimePeriodForVoting() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }); - public static object[] ProposalAttributes(BigInteger id) {StorageMap proposal_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id);UInt160 scripthash = (UInt160)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_SCRIPT_HASH });ByteString method = proposal_map.Get(new byte[] { PREFIX_PROPOSAL_METHOD });BigInteger arg_count = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_ARG_COUNT });ByteString[] args = new ByteString[(int)arg_count];StorageMap arg_map = new StorageMap(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id + PREFIX_PROPOSAL_ARG);for (BigInteger j = 1; j <= arg_count; j++){args[(int)j - 1] = arg_map.Get((ByteString)j);}BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE });return new object[] { scripthash, method, args, voting_deadline };} + public static object[] ProposalAttributes(BigInteger id) + { + StorageMap proposal_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id); + UInt160 scripthash = (UInt160)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_SCRIPT_HASH }); + string method = proposal_map.Get(new byte[] { PREFIX_PROPOSAL_METHOD }); + BigInteger arg_count = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_ARG_COUNT }); + ByteString[] args = new ByteString[(int)arg_count]; + StorageMap arg_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id + PREFIX_PROPOSAL_ARG); + for (BigInteger j = 1; j <= arg_count; j++) + args[(int)j - 1] = arg_map.Get((ByteString)j); + BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); + BigInteger executed_time = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }); + return new object[] { scripthash, method, args, voting_deadline, executed_time }; + } + public static UInt160 GetDelegate(UInt160 from) => (UInt160)new StorageMap(Storage.CurrentContext, PREFIX_DELEGATE).Get(from); + public static UInt160 GetDefaultDelegate() => (UInt160)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }); + public static BigInteger GetDelegateThreshold() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }); + public static bool IsValidDelegate(UInt160 account) => account != UInt160.Zero && (BalanceOf(account) > GetDelegateThreshold()); public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, PREFIX_VOTE).Get(from + (ByteString)proposal_index); public static void _deploy(object data, bool update) { - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, 1); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }, 86400000 * 7); + if (!update) + { + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, 1); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }, 86400000 * 7); + Mint(Runtime.ExecutingScriptHash, 10_000_000_000_000_000); + // And it is not easy to let this contract vote for anything in the beginning + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, Runtime.ExecutingScriptHash); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }, 100_000_000_000_000); + } + } + + public static new bool Transfer(UInt160 from, UInt160 to, BigInteger amount, object data) + { + // If the current default holder sends NOBUG to others, the qualification of default holder is not automatically deprived of + bool transfer_result = Nep17Token.Transfer(from, to, amount, data); + if (transfer_result) + { + UInt160 default_delegate = (UInt160)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }); + BigInteger to_account_balance = BalanceOf(to); + if (to_account_balance > BalanceOf(default_delegate) && to_account_balance > GetDelegateThreshold()) + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, to); + return true; + } + return false; } + public static void SetMinimalTimePeriodForVoting(BigInteger minimal_time_period) { ExecutionEngine.Assert(Runtime.CheckWitness(Runtime.ExecutingScriptHash)); @@ -49,7 +93,7 @@ public static void SetMinimalTimePeriodForVoting(BigInteger minimal_time_period) public static BigInteger NewProposal(UInt160 scripthash, string method, ByteString[] args, BigInteger voting_period) { if (voting_period < MinimalTimePeriodForVoting()) - throw new System.Exception("Too short voting period"); + throw new Exception("Too short voting period"); BigInteger proposal_id = (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, proposal_id + 1); StorageMap proposal_id_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_id); @@ -57,11 +101,9 @@ public static BigInteger NewProposal(UInt160 scripthash, string method, ByteStri proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }, voting_period + Runtime.Time); proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_METHOD }, method); proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_ARG_COUNT }, args.Length); - StorageMap arg_map = new StorageMap(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_id + PREFIX_PROPOSAL_ARG); + StorageMap arg_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_id + PREFIX_PROPOSAL_ARG); for(BigInteger j = 1; j <= args.Length; j++) - { arg_map.Put((ByteString)j, args[(int)j - 1]); - } return proposal_id; } @@ -86,11 +128,11 @@ public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_aga BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); if (voting_deadline == 0) { - throw new System.Exception("The proposal does not exist"); + throw new Exception("The proposal does not exist"); } if(Runtime.Time > voting_deadline) { - throw new System.Exception("Cannot vote after the deadline"); + throw new Exception("Cannot vote after the deadline"); } StorageMap vote_map = new(Storage.CurrentContext, PREFIX_VOTE); ByteString key = from + (ByteString)proposal_index; @@ -103,6 +145,43 @@ public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_aga vote_map.Delete(key); } } + + public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) + { + object[] attributes = ProposalAttributes(proposal_id); + UInt160 scripthash = (UInt160)attributes[0]; + string method = (string)attributes[1]; + ByteString[] args = (ByteString[])attributes[2]; + BigInteger voting_deadline = (BigInteger)attributes[3]; + BigInteger proposal_executed = (BigInteger)attributes[4]; + if (Runtime.Time > voting_deadline) + throw new Exception("Cannot execute proposal after voting deadline"); + if (proposal_executed > 0) + throw new Exception("Proposal already executed"); + BigInteger sum_votes = 0; + BigInteger voter_count = voters.Length; + bool default_delegate_voted = GetVote(GetDefaultDelegate(), proposal_id) > 0; + for (BigInteger i=0;i 0 || + (IsValidDelegate(current_delegate) && GetVote(current_delegate, proposal_id) > 0) || + default_delegate_voted + ) + sum_votes += BalanceOf(current_voter); + } + if (sum_votes > TotalSupply() / 2) + { + new StorageMap(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_id) + .Put(new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }, Runtime.Time); + return Contract.Call(scripthash, method, CallFlags.All, args); + } + else + throw new Exception((ByteString)sum_votes); + } + public static void OnNEP17Payment(UInt160 from, BigInteger amount, object data) { return; From 56e58a40e6a8aca96ccd2dfcf112da237782931c Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Thu, 4 Nov 2021 17:19:34 +0800 Subject: [PATCH 07/30] mint tokens to a given address when deployed --- NeoBurgerGovernanceToken.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 8751068..3012c0c 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -5,7 +5,7 @@ using Neo.SmartContract.Framework.Native; using Neo.SmartContract.Framework.Services; using Neo.SmartContract.Framework.Attributes; - +using Neo.SmartContract; namespace NeoBurger { @@ -16,6 +16,8 @@ namespace NeoBurger [ContractPermission("*", "*")] public class NeoBurgerGovernanceToken : Nep17Token { + [InitialValue("[TODO]: ARGS", ContractParameterType.Hash160)] + private static readonly UInt160 INITIAL_HOLDER = default; private static readonly byte PREFIX_PROPOSAL = 0x01; private static readonly byte PREFIX_PROPOSAL_SCRIPT_HASH = 0x02; private static readonly byte PREFIX_PROPOSAL_ID = 0x03; @@ -62,16 +64,17 @@ public static void _deploy(object data, bool update) { Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, 1); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }, 86400000 * 7); - Mint(Runtime.ExecutingScriptHash, 10_000_000_000_000_000); - // And it is not easy to let this contract vote for anything in the beginning - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, Runtime.ExecutingScriptHash); + Mint(INITIAL_HOLDER, 10_000_000_000_000_000); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, INITIAL_HOLDER); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }, 100_000_000_000_000); } } public static new bool Transfer(UInt160 from, UInt160 to, BigInteger amount, object data) { - // If the current default holder sends NOBUG to others, the qualification of default holder is not automatically deprived of + // If the current default delegate sends NOBUG to others, and became not the largest holder, + // the qualification of default holder is not automatically deprived of. + // The new largest holder should transfer some to herself/himself to become the default delegate bool transfer_result = Nep17Token.Transfer(from, to, amount, data); if (transfer_result) { @@ -112,13 +115,9 @@ public static void Delegate(UInt160 from, UInt160 to) ExecutionEngine.Assert(Runtime.CheckWitness(from)); StorageMap delegate_map = new(Storage.CurrentContext, PREFIX_DELEGATE); if (to == UInt160.Zero || to == from) - { delegate_map.Delete(from); - } else - { delegate_map.Put(from, to); - } } public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_against) From 79dfa84dee03634effe033888d112ac3e612b1d1 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Thu, 4 Nov 2021 17:28:39 +0800 Subject: [PATCH 08/30] BecomeDefaultDelegate manually --- NeoBurgerGovernanceToken.cs | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 3012c0c..dcbc928 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -70,24 +70,18 @@ public static void _deploy(object data, bool update) } } - public static new bool Transfer(UInt160 from, UInt160 to, BigInteger amount, object data) + public static void BecomeDefaultDelegate(UInt160 account) { - // If the current default delegate sends NOBUG to others, and became not the largest holder, - // the qualification of default holder is not automatically deprived of. - // The new largest holder should transfer some to herself/himself to become the default delegate - bool transfer_result = Nep17Token.Transfer(from, to, amount, data); - if (transfer_result) - { - UInt160 default_delegate = (UInt160)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }); - BigInteger to_account_balance = BalanceOf(to); - if (to_account_balance > BalanceOf(default_delegate) && to_account_balance > GetDelegateThreshold()) - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, to); - return true; - } - return false; + ExecutionEngine.Assert(Runtime.CheckWitness(account)); + UInt160 default_delegate = (UInt160)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }); + BigInteger to_account_balance = BalanceOf(account); + BigInteger default_delegate_balance = BalanceOf(default_delegate); + if (to_account_balance > default_delegate_balance && to_account_balance > GetDelegateThreshold()) + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, account); + else + throw new Exception((ByteString)default_delegate_balance); } - public static void SetMinimalTimePeriodForVoting(BigInteger minimal_time_period) { ExecutionEngine.Assert(Runtime.CheckWitness(Runtime.ExecutingScriptHash)); From 55bc1bcecd57a9ed7da679ead53916a594d9bdcd Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Thu, 4 Nov 2021 17:34:57 +0800 Subject: [PATCH 09/30] GetDefaultDelegateBalance --- NeoBurgerGovernanceToken.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index dcbc928..6a41f57 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -53,6 +53,7 @@ public static object[] ProposalAttributes(BigInteger id) public static UInt160 GetDelegate(UInt160 from) => (UInt160)new StorageMap(Storage.CurrentContext, PREFIX_DELEGATE).Get(from); public static UInt160 GetDefaultDelegate() => (UInt160)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }); + public static BigInteger GetDefaultDelegateBalance() => BalanceOf(GetDefaultDelegate()); public static BigInteger GetDelegateThreshold() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }); public static bool IsValidDelegate(UInt160 account) => account != UInt160.Zero && (BalanceOf(account) > GetDelegateThreshold()); public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, PREFIX_VOTE).Get(from + (ByteString)proposal_index); From b8680cf75bce3463f836664ba89c628c7babfa2c Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Thu, 4 Nov 2021 18:11:16 +0800 Subject: [PATCH 10/30] vote[proposal_id][from_account] == True/False; --- NeoBurgerGovernanceToken.cs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 6a41f57..e02ca20 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -56,7 +56,8 @@ public static object[] ProposalAttributes(BigInteger id) public static BigInteger GetDefaultDelegateBalance() => BalanceOf(GetDefaultDelegate()); public static BigInteger GetDelegateThreshold() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }); public static bool IsValidDelegate(UInt160 account) => account != UInt160.Zero && (BalanceOf(account) > GetDelegateThreshold()); - public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, PREFIX_VOTE).Get(from + (ByteString)proposal_index); + public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, PREFIX_VOTE + (ByteString)proposal_index).Get(from); + public static Iterator GetVotersOfProposal(BigInteger proposal_id) => new StorageMap(Storage.CurrentContext, PREFIX_VOTE + (ByteString)proposal_id).Find(); public static void _deploy(object data, bool update) @@ -121,23 +122,14 @@ public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_aga StorageMap proposal_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_index); BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); if (voting_deadline == 0) - { throw new Exception("The proposal does not exist"); - } if(Runtime.Time > voting_deadline) - { throw new Exception("Cannot vote after the deadline"); - } - StorageMap vote_map = new(Storage.CurrentContext, PREFIX_VOTE); - ByteString key = from + (ByteString)proposal_index; + StorageMap vote_map = new(Storage.CurrentContext, PREFIX_VOTE + (ByteString)proposal_index); if (for_or_against) - { - vote_map.Put(key, 1); - } + vote_map.Put(from, 1); else - { - vote_map.Delete(key); - } + vote_map.Delete(from); } public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) @@ -149,7 +141,7 @@ public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) BigInteger voting_deadline = (BigInteger)attributes[3]; BigInteger proposal_executed = (BigInteger)attributes[4]; if (Runtime.Time > voting_deadline) - throw new Exception("Cannot execute proposal after voting deadline"); + throw new Exception("Cannot execute proposal after the deadline"); if (proposal_executed > 0) throw new Exception("Proposal already executed"); BigInteger sum_votes = 0; From 86b79a6c2cb2c392bfbf57a198fa36336d402287 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Fri, 5 Nov 2021 11:06:00 +0800 Subject: [PATCH 11/30] Preliminarily tested convenient method `CountVote`; robust method `IsValidDelegate` --- NeoBurgerGovernanceToken.cs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index e02ca20..1707a37 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -55,7 +55,7 @@ public static object[] ProposalAttributes(BigInteger id) public static UInt160 GetDefaultDelegate() => (UInt160)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }); public static BigInteger GetDefaultDelegateBalance() => BalanceOf(GetDefaultDelegate()); public static BigInteger GetDelegateThreshold() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }); - public static bool IsValidDelegate(UInt160 account) => account != UInt160.Zero && (BalanceOf(account) > GetDelegateThreshold()); + public static bool IsValidDelegate(UInt160 account) => account is not null && account.IsValid && (BalanceOf(account) > GetDelegateThreshold()); public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, PREFIX_VOTE + (ByteString)proposal_index).Get(from); public static Iterator GetVotersOfProposal(BigInteger proposal_id) => new StorageMap(Storage.CurrentContext, PREFIX_VOTE + (ByteString)proposal_id).Find(); @@ -132,6 +132,25 @@ public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_aga vote_map.Delete(from); } + public static BigInteger CountVote(BigInteger proposal_id) + { + BigInteger sum_votes = 0; + Iterator voters = new StorageMap(Storage.CurrentContext, PREFIX_VOTE + (ByteString)proposal_id).Find(); + bool default_delegate_voted = GetVote(GetDefaultDelegate(), proposal_id) > 0; + while (voters.Next()) + { + UInt160 current_voter = (UInt160)(((object[])voters.Value)[0]); + UInt160 current_delegate = GetDelegate(current_voter); + if (current_voter is not null && current_voter.IsValid && ( + GetVote(current_voter, proposal_id) > 0 || + (IsValidDelegate(current_delegate) && GetVote(current_delegate, proposal_id) > 0) || + default_delegate_voted + )) + sum_votes += BalanceOf(current_voter); + } + return sum_votes; + } + public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) { object[] attributes = ProposalAttributes(proposal_id); @@ -151,11 +170,11 @@ public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) { UInt160 current_voter = voters[(int)i]; UInt160 current_delegate = GetDelegate(current_voter); - if ( + if (current_voter is not null && current_voter.IsValid && ( GetVote(current_voter, proposal_id) > 0 || (IsValidDelegate(current_delegate) && GetVote(current_delegate, proposal_id) > 0) || default_delegate_voted - ) + )) sum_votes += BalanceOf(current_voter); } if (sum_votes > TotalSupply() / 2) From 139527d4ef2dacf92f40564c32378d48394d11f7 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Fri, 5 Nov 2021 11:20:49 +0800 Subject: [PATCH 12/30] Let `ExecuteProposal` reuse `CountVote` if no voter list provided --- NeoBurgerGovernanceToken.cs | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 1707a37..3131fdd 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -142,9 +142,9 @@ public static BigInteger CountVote(BigInteger proposal_id) UInt160 current_voter = (UInt160)(((object[])voters.Value)[0]); UInt160 current_delegate = GetDelegate(current_voter); if (current_voter is not null && current_voter.IsValid && ( + default_delegate_voted || GetVote(current_voter, proposal_id) > 0 || - (IsValidDelegate(current_delegate) && GetVote(current_delegate, proposal_id) > 0) || - default_delegate_voted + (IsValidDelegate(current_delegate) && GetVote(current_delegate, proposal_id) > 0) )) sum_votes += BalanceOf(current_voter); } @@ -163,19 +163,25 @@ public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) throw new Exception("Cannot execute proposal after the deadline"); if (proposal_executed > 0) throw new Exception("Proposal already executed"); - BigInteger sum_votes = 0; + BigInteger voter_count = voters.Length; - bool default_delegate_voted = GetVote(GetDefaultDelegate(), proposal_id) > 0; - for (BigInteger i=0;i 0 || - (IsValidDelegate(current_delegate) && GetVote(current_delegate, proposal_id) > 0) || - default_delegate_voted - )) - sum_votes += BalanceOf(current_voter); + bool default_delegate_voted = GetVote(GetDefaultDelegate(), proposal_id) > 0; + for (BigInteger i = 0; i < voter_count; i++) + { + UInt160 current_voter = voters[(int)i]; + UInt160 current_delegate = GetDelegate(current_voter); + if (current_voter is not null && current_voter.IsValid && ( + default_delegate_voted || + GetVote(current_voter, proposal_id) > 0 || + (IsValidDelegate(current_delegate) && GetVote(current_delegate, proposal_id) > 0) + )) + sum_votes += BalanceOf(current_voter); + } } if (sum_votes > TotalSupply() / 2) { From 8fd45157651b42eec13f4b1cf07ede7ac1c55469 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Fri, 5 Nov 2021 12:00:07 +0800 Subject: [PATCH 13/30] More robust and efficient `CountVote` and `ExecuteProposal` --- NeoBurgerGovernanceToken.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 3131fdd..2cdbe9c 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -139,13 +139,14 @@ public static BigInteger CountVote(BigInteger proposal_id) bool default_delegate_voted = GetVote(GetDefaultDelegate(), proposal_id) > 0; while (voters.Next()) { - UInt160 current_voter = (UInt160)(((object[])voters.Value)[0]); + byte[] current_vote_bytes = (byte[])((object[])voters.Value)[0]; + UInt160 current_voter = (UInt160)current_vote_bytes[^20..]; UInt160 current_delegate = GetDelegate(current_voter); - if (current_voter is not null && current_voter.IsValid && ( + if ( default_delegate_voted || GetVote(current_voter, proposal_id) > 0 || (IsValidDelegate(current_delegate) && GetVote(current_delegate, proposal_id) > 0) - )) + ) sum_votes += BalanceOf(current_voter); } return sum_votes; @@ -174,12 +175,14 @@ public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) for (BigInteger i = 0; i < voter_count; i++) { UInt160 current_voter = voters[(int)i]; + //if (current_voter is null || !current_voter.IsValid) + // throw new Exception(current_voter); UInt160 current_delegate = GetDelegate(current_voter); - if (current_voter is not null && current_voter.IsValid && ( + if ( default_delegate_voted || GetVote(current_voter, proposal_id) > 0 || (IsValidDelegate(current_delegate) && GetVote(current_delegate, proposal_id) > 0) - )) + ) sum_votes += BalanceOf(current_voter); } } From 8bd71d41ecb6e76b950cfbb1695d7cfa32bb1862 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Fri, 5 Nov 2021 13:06:15 +0800 Subject: [PATCH 14/30] Attempt to regularize keys to raw bytes --- NeoBurgerGovernanceToken.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 2cdbe9c..73590e2 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -38,12 +38,12 @@ public class NeoBurgerGovernanceToken : Nep17Token public static object[] ProposalAttributes(BigInteger id) { - StorageMap proposal_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id); + StorageMap proposal_map = new(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_PROPOSAL } + (ByteString)id); UInt160 scripthash = (UInt160)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_SCRIPT_HASH }); string method = proposal_map.Get(new byte[] { PREFIX_PROPOSAL_METHOD }); BigInteger arg_count = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_ARG_COUNT }); ByteString[] args = new ByteString[(int)arg_count]; - StorageMap arg_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)id + PREFIX_PROPOSAL_ARG); + StorageMap arg_map = new(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_PROPOSAL } + (ByteString)id + (ByteString)new byte[] { PREFIX_PROPOSAL_ARG }); for (BigInteger j = 1; j <= arg_count; j++) args[(int)j - 1] = arg_map.Get((ByteString)j); BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); @@ -56,8 +56,8 @@ public static object[] ProposalAttributes(BigInteger id) public static BigInteger GetDefaultDelegateBalance() => BalanceOf(GetDefaultDelegate()); public static BigInteger GetDelegateThreshold() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }); public static bool IsValidDelegate(UInt160 account) => account is not null && account.IsValid && (BalanceOf(account) > GetDelegateThreshold()); - public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, PREFIX_VOTE + (ByteString)proposal_index).Get(from); - public static Iterator GetVotersOfProposal(BigInteger proposal_id) => new StorageMap(Storage.CurrentContext, PREFIX_VOTE + (ByteString)proposal_id).Find(); + public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_index).Get(from); + public static Iterator GetVotersOfProposal(BigInteger proposal_id) => new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_id).Find(); public static void _deploy(object data, bool update) @@ -95,12 +95,12 @@ public static BigInteger NewProposal(UInt160 scripthash, string method, ByteStri throw new Exception("Too short voting period"); BigInteger proposal_id = (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, proposal_id + 1); - StorageMap proposal_id_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_id); + StorageMap proposal_id_map = new(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_PROPOSAL } + (ByteString)proposal_id); proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_SCRIPT_HASH }, scripthash); proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }, voting_period + Runtime.Time); proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_METHOD }, method); proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_ARG_COUNT }, args.Length); - StorageMap arg_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_id + PREFIX_PROPOSAL_ARG); + StorageMap arg_map = new(Storage.CurrentContext, (ByteString)new byte[]{ PREFIX_PROPOSAL } + (ByteString)proposal_id + (ByteString)new byte[] { PREFIX_PROPOSAL_ARG }); for(BigInteger j = 1; j <= args.Length; j++) arg_map.Put((ByteString)j, args[(int)j - 1]); return proposal_id; @@ -119,13 +119,13 @@ public static void Delegate(UInt160 from, UInt160 to) public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_against) { ExecutionEngine.Assert(Runtime.CheckWitness(from)); - StorageMap proposal_map = new(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_index); + StorageMap proposal_map = new(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_PROPOSAL } + (ByteString)proposal_index); BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); if (voting_deadline == 0) throw new Exception("The proposal does not exist"); if(Runtime.Time > voting_deadline) throw new Exception("Cannot vote after the deadline"); - StorageMap vote_map = new(Storage.CurrentContext, PREFIX_VOTE + (ByteString)proposal_index); + StorageMap vote_map = new(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_index); if (for_or_against) vote_map.Put(from, 1); else @@ -135,7 +135,7 @@ public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_aga public static BigInteger CountVote(BigInteger proposal_id) { BigInteger sum_votes = 0; - Iterator voters = new StorageMap(Storage.CurrentContext, PREFIX_VOTE + (ByteString)proposal_id).Find(); + Iterator voters = new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_id).Find(); bool default_delegate_voted = GetVote(GetDefaultDelegate(), proposal_id) > 0; while (voters.Next()) { @@ -188,7 +188,7 @@ public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) } if (sum_votes > TotalSupply() / 2) { - new StorageMap(Storage.CurrentContext, PREFIX_PROPOSAL + (ByteString)proposal_id) + new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_PROPOSAL } + (ByteString)proposal_id) .Put(new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }, Runtime.Time); return Contract.Call(scripthash, method, CallFlags.All, args); } From db4d4b5c9d8de4cadf60235df66b97863ff47426 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Fri, 5 Nov 2021 13:44:27 +0800 Subject: [PATCH 15/30] vote couting logic: I voted || I have valid delegate and delegate voted || I have invalid delegate but default delegate voted --- NeoBurgerGovernanceToken.cs | 41 ++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 73590e2..9525649 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -141,13 +141,21 @@ public static BigInteger CountVote(BigInteger proposal_id) { byte[] current_vote_bytes = (byte[])((object[])voters.Value)[0]; UInt160 current_voter = (UInt160)current_vote_bytes[^20..]; - UInt160 current_delegate = GetDelegate(current_voter); - if ( - default_delegate_voted || - GetVote(current_voter, proposal_id) > 0 || - (IsValidDelegate(current_delegate) && GetVote(current_delegate, proposal_id) > 0) - ) + if (GetVote(current_voter, proposal_id) > 0) sum_votes += BalanceOf(current_voter); + else { + UInt160 current_delegate = GetDelegate(current_voter); + if (IsValidDelegate(current_delegate)) + { + if (GetVote(current_delegate, proposal_id) > 0) + sum_votes += BalanceOf(current_voter); + } + else + { + if (default_delegate_voted) + sum_votes += BalanceOf(current_voter); + } + } } return sum_votes; } @@ -177,13 +185,22 @@ public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) UInt160 current_voter = voters[(int)i]; //if (current_voter is null || !current_voter.IsValid) // throw new Exception(current_voter); - UInt160 current_delegate = GetDelegate(current_voter); - if ( - default_delegate_voted || - GetVote(current_voter, proposal_id) > 0 || - (IsValidDelegate(current_delegate) && GetVote(current_delegate, proposal_id) > 0) - ) + if (GetVote(current_voter, proposal_id) > 0) sum_votes += BalanceOf(current_voter); + else + { + UInt160 current_delegate = GetDelegate(current_voter); + if (IsValidDelegate(current_delegate)) + { + if (GetVote(current_delegate, proposal_id) > 0) + sum_votes += BalanceOf(current_voter); + } + else + { + if (default_delegate_voted) + sum_votes += BalanceOf(current_voter); + } + } } } if (sum_votes > TotalSupply() / 2) From c47cb40b57970d4e6cd51fa50d62c68cf3d8a0e2 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Fri, 5 Nov 2021 16:22:28 +0800 Subject: [PATCH 16/30] optimized `GetVotersOfProposal` and `CountVote` using FindOptions --- NeoBurgerGovernanceToken.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 9525649..85c287a 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -57,7 +57,7 @@ public static object[] ProposalAttributes(BigInteger id) public static BigInteger GetDelegateThreshold() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }); public static bool IsValidDelegate(UInt160 account) => account is not null && account.IsValid && (BalanceOf(account) > GetDelegateThreshold()); public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_index).Get(from); - public static Iterator GetVotersOfProposal(BigInteger proposal_id) => new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_id).Find(); + public static Iterator GetVotersOfProposal(BigInteger proposal_id) => new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_id).Find((FindOptions)((byte)FindOptions.KeysOnly + (byte)FindOptions.RemovePrefix)); public static void _deploy(object data, bool update) @@ -135,12 +135,12 @@ public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_aga public static BigInteger CountVote(BigInteger proposal_id) { BigInteger sum_votes = 0; - Iterator voters = new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_id).Find(); + Iterator voters = new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_id) + .Find((FindOptions)((byte)FindOptions.KeysOnly + (byte)FindOptions.RemovePrefix)); bool default_delegate_voted = GetVote(GetDefaultDelegate(), proposal_id) > 0; while (voters.Next()) { - byte[] current_vote_bytes = (byte[])((object[])voters.Value)[0]; - UInt160 current_voter = (UInt160)current_vote_bytes[^20..]; + UInt160 current_voter = (UInt160)(byte[])voters.Value; if (GetVote(current_voter, proposal_id) > 0) sum_votes += BalanceOf(current_voter); else { From 5929488052dedbe2372a16b1c0da9f60a693f1cc Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Mon, 8 Nov 2021 11:25:55 +0800 Subject: [PATCH 17/30] arg count starts from 0; optimzed GAS with args[(uint)j] --- NeoBurgerGovernanceToken.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 85c287a..7f16486 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -42,10 +42,10 @@ public static object[] ProposalAttributes(BigInteger id) UInt160 scripthash = (UInt160)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_SCRIPT_HASH }); string method = proposal_map.Get(new byte[] { PREFIX_PROPOSAL_METHOD }); BigInteger arg_count = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_ARG_COUNT }); - ByteString[] args = new ByteString[(int)arg_count]; + ByteString[] args = new ByteString[(uint)arg_count]; StorageMap arg_map = new(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_PROPOSAL } + (ByteString)id + (ByteString)new byte[] { PREFIX_PROPOSAL_ARG }); - for (BigInteger j = 1; j <= arg_count; j++) - args[(int)j - 1] = arg_map.Get((ByteString)j); + for (BigInteger j = 0; j < arg_count; j++) + args[(uint)j] = arg_map.Get((ByteString)j); BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); BigInteger executed_time = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }); return new object[] { scripthash, method, args, voting_deadline, executed_time }; @@ -101,8 +101,9 @@ public static BigInteger NewProposal(UInt160 scripthash, string method, ByteStri proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_METHOD }, method); proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_ARG_COUNT }, args.Length); StorageMap arg_map = new(Storage.CurrentContext, (ByteString)new byte[]{ PREFIX_PROPOSAL } + (ByteString)proposal_id + (ByteString)new byte[] { PREFIX_PROPOSAL_ARG }); - for(BigInteger j = 1; j <= args.Length; j++) - arg_map.Put((ByteString)j, args[(int)j - 1]); + BigInteger args_length = args.Length; + for (BigInteger j = 0; j < args_length; j++) + arg_map.Put((ByteString)j, args[(uint)j]); return proposal_id; } @@ -182,7 +183,7 @@ public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) bool default_delegate_voted = GetVote(GetDefaultDelegate(), proposal_id) > 0; for (BigInteger i = 0; i < voter_count; i++) { - UInt160 current_voter = voters[(int)i]; + UInt160 current_voter = voters[(uint)i]; //if (current_voter is null || !current_voter.IsValid) // throw new Exception(current_voter); if (GetVote(current_voter, proposal_id) > 0) From 6abfa3ca65d2a4c76ba4912567e9e81a74beef51 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Mon, 8 Nov 2021 13:55:19 +0800 Subject: [PATCH 18/30] clearer exceptions --- NeoBurgerGovernanceToken.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 7f16486..9934674 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -81,7 +81,7 @@ public static void BecomeDefaultDelegate(UInt160 account) if (to_account_balance > default_delegate_balance && to_account_balance > GetDelegateThreshold()) Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, account); else - throw new Exception((ByteString)default_delegate_balance); + throw new Exception("No enough tokens. You need "+(ByteString)default_delegate_balance+" NOBUGs to be the default delegate"); } public static void SetMinimalTimePeriodForVoting(BigInteger minimal_time_period) @@ -211,7 +211,10 @@ public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) return Contract.Call(scripthash, method, CallFlags.All, args); } else - throw new Exception((ByteString)sum_votes); + if(sum_votes != 0) + throw new Exception("Not enough votes. Got "+(ByteString)sum_votes+ " votes from given array `UInt160[] voters`"); + else + throw new Exception("No vote counted from given array `UInt160[] voters`"); } public static void OnNEP17Payment(UInt160 from, BigInteger amount, object data) From 807cb158fc928a3bc25dade742bd7538d128a734 Mon Sep 17 00:00:00 2001 From: vang1ong7ang Date: Mon, 8 Nov 2021 01:12:49 -0500 Subject: [PATCH 19/30] Update NeoBurgerGovernanceToken.cs --- NeoBurgerGovernanceToken.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 9934674..d8a29da 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -219,7 +219,6 @@ public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) public static void OnNEP17Payment(UInt160 from, BigInteger amount, object data) { - return; } public static void Update(ByteString nefFile, string manifest) From f17807cf820630450f3a784331d27d43d8e5086b Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Mon, 8 Nov 2021 15:40:02 +0800 Subject: [PATCH 20/30] proposal attributes stored as structs --- NeoBurgerGovernanceToken.cs | 68 +++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 9934674..86c9391 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -18,37 +18,29 @@ public class NeoBurgerGovernanceToken : Nep17Token { [InitialValue("[TODO]: ARGS", ContractParameterType.Hash160)] private static readonly UInt160 INITIAL_HOLDER = default; - private static readonly byte PREFIX_PROPOSAL = 0x01; - private static readonly byte PREFIX_PROPOSAL_SCRIPT_HASH = 0x02; - private static readonly byte PREFIX_PROPOSAL_ID = 0x03; - private static readonly byte PREFIX_PROPOSAL_METHOD = 0x04; - private static readonly byte PREFIX_PROPOSAL_ARG = 0x05; - private static readonly byte PREFIX_PROPOSAL_ARG_COUNT = 0x06; - private static readonly byte PREFIX_PROPOSAL_VOTING_DEADLINE = 0x07; - private static readonly byte PREFIX_PROPOSAL_EXECUTED_TIME = 0x08; + private static readonly byte PREFIX_PROPOSAL_ID = 0x02; + private static readonly byte PREFIX_PROPOSAL = 0x03; + private static readonly byte PREFIX_PROPOSAL_VOTING_DEADLINE = 0x04; + private static readonly byte PREFIX_PROPOSAL_EXECUTED_TIME = 0x05; private static readonly byte PREFIX_DELEGATE = 0x81; private static readonly byte PREFIX_DEFAULT_DELEGATE = 0x82; private static readonly byte PREFIX_DELEGATE_THRESHOLD = 0x83; private static readonly byte PREFIX_VOTE = 0xc1; - private static readonly byte PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING = 0xc2; + private static readonly byte PREFIX_VOTING_PERIOD = 0xc2; public override byte Decimals() => 8; public override string Symbol() => "NOBUG"; - public static BigInteger MinimalTimePeriodForVoting() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }); + public static BigInteger GetVotingPeriod() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_VOTING_PERIOD }); public static object[] ProposalAttributes(BigInteger id) { - StorageMap proposal_map = new(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_PROPOSAL } + (ByteString)id); - UInt160 scripthash = (UInt160)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_SCRIPT_HASH }); - string method = proposal_map.Get(new byte[] { PREFIX_PROPOSAL_METHOD }); - BigInteger arg_count = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_ARG_COUNT }); - ByteString[] args = new ByteString[(uint)arg_count]; - StorageMap arg_map = new(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_PROPOSAL } + (ByteString)id + (ByteString)new byte[] { PREFIX_PROPOSAL_ARG }); - for (BigInteger j = 0; j < arg_count; j++) - args[(uint)j] = arg_map.Get((ByteString)j); - BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); - BigInteger executed_time = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }); - return new object[] { scripthash, method, args, voting_deadline, executed_time }; + StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); + ProposalAttributesStruct proposal_attributes = (ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)id); + StorageMap proposal_voting_deadline_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); + BigInteger voting_end_time = (BigInteger)proposal_voting_deadline_map.Get((ByteString)id); + StorageMap proposal_executed_time_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }); + BigInteger executed_time = (BigInteger)proposal_executed_time_map.Get(new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }); + return new object[] { proposal_attributes.scripthash, proposal_attributes.method, proposal_attributes.args, voting_end_time, executed_time }; } public static UInt160 GetDelegate(UInt160 from) => (UInt160)new StorageMap(Storage.CurrentContext, PREFIX_DELEGATE).Get(from); @@ -59,13 +51,19 @@ public static object[] ProposalAttributes(BigInteger id) public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_index).Get(from); public static Iterator GetVotersOfProposal(BigInteger proposal_id) => new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_id).Find((FindOptions)((byte)FindOptions.KeysOnly + (byte)FindOptions.RemovePrefix)); + struct ProposalAttributesStruct + { + public UInt160 scripthash; + public string method; + public ByteString[] args; + } public static void _deploy(object data, bool update) { if (!update) { Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, 1); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }, 86400000 * 7); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_VOTING_PERIOD }, 86400000 * 7); Mint(INITIAL_HOLDER, 10_000_000_000_000_000); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, INITIAL_HOLDER); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }, 100_000_000_000_000); @@ -84,26 +82,23 @@ public static void BecomeDefaultDelegate(UInt160 account) throw new Exception("No enough tokens. You need "+(ByteString)default_delegate_balance+" NOBUGs to be the default delegate"); } - public static void SetMinimalTimePeriodForVoting(BigInteger minimal_time_period) + public static void SetMinimalTimePeriodForVoting(BigInteger time_period) { ExecutionEngine.Assert(Runtime.CheckWitness(Runtime.ExecutingScriptHash)); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_MINIMAL_TIME_PERIOD_FOR_VOTING }, minimal_time_period); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_VOTING_PERIOD }, time_period); } - public static BigInteger NewProposal(UInt160 scripthash, string method, ByteString[] args, BigInteger voting_period) + public static BigInteger NewProposal(UInt160 scripthash, string method, ByteString[] args) { - if (voting_period < MinimalTimePeriodForVoting()) - throw new Exception("Too short voting period"); BigInteger proposal_id = (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, proposal_id + 1); - StorageMap proposal_id_map = new(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_PROPOSAL } + (ByteString)proposal_id); - proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_SCRIPT_HASH }, scripthash); - proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }, voting_period + Runtime.Time); - proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_METHOD }, method); - proposal_id_map.Put(new byte[] { PREFIX_PROPOSAL_ARG_COUNT }, args.Length); - StorageMap arg_map = new(Storage.CurrentContext, (ByteString)new byte[]{ PREFIX_PROPOSAL } + (ByteString)proposal_id + (ByteString)new byte[] { PREFIX_PROPOSAL_ARG }); - BigInteger args_length = args.Length; - for (BigInteger j = 0; j < args_length; j++) - arg_map.Put((ByteString)j, args[(uint)j]); + StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); + ProposalAttributesStruct proposal_attributes = new(); + proposal_attributes.scripthash = scripthash; + proposal_attributes.method = method; + proposal_attributes.args = args; + proposal_id_map.PutObject((ByteString)proposal_id, proposal_attributes); + StorageMap proposal_voting_end_time_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); + proposal_voting_end_time_map.Put((ByteString)proposal_id, Runtime.Time + GetVotingPeriod()); return proposal_id; } @@ -219,7 +214,6 @@ public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) public static void OnNEP17Payment(UInt160 from, BigInteger amount, object data) { - return; } public static void Update(ByteString nefFile, string manifest) From a9d0ec551ab9a7c47b26dc2e1a062c0e66b67f51 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Mon, 8 Nov 2021 15:53:00 +0800 Subject: [PATCH 21/30] check voting deadline in refactored storage --- NeoBurgerGovernanceToken.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 86c9391..12bc5e0 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -115,8 +115,8 @@ public static void Delegate(UInt160 from, UInt160 to) public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_against) { ExecutionEngine.Assert(Runtime.CheckWitness(from)); - StorageMap proposal_map = new(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_PROPOSAL } + (ByteString)proposal_index); - BigInteger voting_deadline = (BigInteger)proposal_map.Get(new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); + StorageMap proposal_voting_deadline_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); + BigInteger voting_deadline = (BigInteger)proposal_voting_deadline_map.Get((ByteString)proposal_index); if (voting_deadline == 0) throw new Exception("The proposal does not exist"); if(Runtime.Time > voting_deadline) From 0b662d091d8c49cb4e05af7bbf6c1b44e8c201df Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Mon, 8 Nov 2021 16:24:10 +0800 Subject: [PATCH 22/30] method GetNextProposalID --- NeoBurgerGovernanceToken.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 12bc5e0..5a49ae8 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -31,6 +31,7 @@ public class NeoBurgerGovernanceToken : Nep17Token public override byte Decimals() => 8; public override string Symbol() => "NOBUG"; public static BigInteger GetVotingPeriod() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_VOTING_PERIOD }); + public static BigInteger GetNextProposalID() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }); public static object[] ProposalAttributes(BigInteger id) { From 623ed8180c7c8ac856f237f1e4273843ca8e424f Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Mon, 8 Nov 2021 17:02:53 +0800 Subject: [PATCH 23/30] proposal id given by user --- NeoBurgerGovernanceToken.cs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 5a49ae8..3720ac7 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -18,7 +18,6 @@ public class NeoBurgerGovernanceToken : Nep17Token { [InitialValue("[TODO]: ARGS", ContractParameterType.Hash160)] private static readonly UInt160 INITIAL_HOLDER = default; - private static readonly byte PREFIX_PROPOSAL_ID = 0x02; private static readonly byte PREFIX_PROPOSAL = 0x03; private static readonly byte PREFIX_PROPOSAL_VOTING_DEADLINE = 0x04; private static readonly byte PREFIX_PROPOSAL_EXECUTED_TIME = 0x05; @@ -31,17 +30,14 @@ public class NeoBurgerGovernanceToken : Nep17Token public override byte Decimals() => 8; public override string Symbol() => "NOBUG"; public static BigInteger GetVotingPeriod() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_VOTING_PERIOD }); - public static BigInteger GetNextProposalID() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }); public static object[] ProposalAttributes(BigInteger id) { StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); ProposalAttributesStruct proposal_attributes = (ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)id); - StorageMap proposal_voting_deadline_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); - BigInteger voting_end_time = (BigInteger)proposal_voting_deadline_map.Get((ByteString)id); StorageMap proposal_executed_time_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }); BigInteger executed_time = (BigInteger)proposal_executed_time_map.Get(new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }); - return new object[] { proposal_attributes.scripthash, proposal_attributes.method, proposal_attributes.args, voting_end_time, executed_time }; + return new object[] { proposal_attributes.scripthash, proposal_attributes.method, proposal_attributes.args, proposal_attributes.voting_deadline, executed_time }; } public static UInt160 GetDelegate(UInt160 from) => (UInt160)new StorageMap(Storage.CurrentContext, PREFIX_DELEGATE).Get(from); @@ -54,16 +50,21 @@ public static object[] ProposalAttributes(BigInteger id) struct ProposalAttributesStruct { + public BigInteger id; public UInt160 scripthash; public string method; public ByteString[] args; + public BigInteger voting_deadline; } public static void _deploy(object data, bool update) { if (!update) { - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, 1); + StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); + ProposalAttributesStruct proposal_attributes = new(); + proposal_attributes.id = 0; + proposal_id_map.PutObject((ByteString)(BigInteger)0, proposal_attributes); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_VOTING_PERIOD }, 86400000 * 7); Mint(INITIAL_HOLDER, 10_000_000_000_000_000); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, INITIAL_HOLDER); @@ -88,18 +89,18 @@ public static void SetMinimalTimePeriodForVoting(BigInteger time_period) ExecutionEngine.Assert(Runtime.CheckWitness(Runtime.ExecutingScriptHash)); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_VOTING_PERIOD }, time_period); } - public static BigInteger NewProposal(UInt160 scripthash, string method, ByteString[] args) + public static BigInteger NewProposal(BigInteger proposal_id, UInt160 scripthash, string method, ByteString[] args) { - BigInteger proposal_id = (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_ID }, proposal_id + 1); StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); + if (proposal_id_map.GetObject((ByteString)proposal_id) is not null || ((ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)(proposal_id - 1))).id != proposal_id - 1) + throw new Exception("Invalid proposal id"); ProposalAttributesStruct proposal_attributes = new(); + proposal_attributes.id = proposal_id; proposal_attributes.scripthash = scripthash; proposal_attributes.method = method; proposal_attributes.args = args; + proposal_attributes.voting_deadline = Runtime.Time + GetVotingPeriod(); proposal_id_map.PutObject((ByteString)proposal_id, proposal_attributes); - StorageMap proposal_voting_end_time_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); - proposal_voting_end_time_map.Put((ByteString)proposal_id, Runtime.Time + GetVotingPeriod()); return proposal_id; } From 0aae44f0a9a34025ac305395bed9894005d7d3bb Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Mon, 8 Nov 2021 17:45:01 +0800 Subject: [PATCH 24/30] robust check for `NewProposal` --- NeoBurgerGovernanceToken.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 3720ac7..b4138f7 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -71,7 +71,6 @@ public static void _deploy(object data, bool update) Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }, 100_000_000_000_000); } } - public static void BecomeDefaultDelegate(UInt160 account) { ExecutionEngine.Assert(Runtime.CheckWitness(account)); @@ -92,7 +91,7 @@ public static void SetMinimalTimePeriodForVoting(BigInteger time_period) public static BigInteger NewProposal(BigInteger proposal_id, UInt160 scripthash, string method, ByteString[] args) { StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); - if (proposal_id_map.GetObject((ByteString)proposal_id) is not null || ((ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)(proposal_id - 1))).id != proposal_id - 1) + if ((BigInteger)proposal_id_map.Get((ByteString)proposal_id) != 0 || ((ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)(proposal_id - 1))).id != proposal_id - 1) throw new Exception("Invalid proposal id"); ProposalAttributesStruct proposal_attributes = new(); proposal_attributes.id = proposal_id; From 95db3f7ec144750bfe2e81a8b4a531e83cfcd648 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Mon, 8 Nov 2021 18:33:23 +0800 Subject: [PATCH 25/30] fix method `Vote` --- NeoBurgerGovernanceToken.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index b4138f7..0f695d7 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -19,7 +19,6 @@ public class NeoBurgerGovernanceToken : Nep17Token [InitialValue("[TODO]: ARGS", ContractParameterType.Hash160)] private static readonly UInt160 INITIAL_HOLDER = default; private static readonly byte PREFIX_PROPOSAL = 0x03; - private static readonly byte PREFIX_PROPOSAL_VOTING_DEADLINE = 0x04; private static readonly byte PREFIX_PROPOSAL_EXECUTED_TIME = 0x05; private static readonly byte PREFIX_DELEGATE = 0x81; private static readonly byte PREFIX_DEFAULT_DELEGATE = 0x82; @@ -116,8 +115,9 @@ public static void Delegate(UInt160 from, UInt160 to) public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_against) { ExecutionEngine.Assert(Runtime.CheckWitness(from)); - StorageMap proposal_voting_deadline_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_VOTING_DEADLINE }); - BigInteger voting_deadline = (BigInteger)proposal_voting_deadline_map.Get((ByteString)proposal_index); + StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); + ProposalAttributesStruct proposal_attributes = (ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)proposal_index); + BigInteger voting_deadline = proposal_attributes.voting_deadline; if (voting_deadline == 0) throw new Exception("The proposal does not exist"); if(Runtime.Time > voting_deadline) From 525c015ecd8f52e48b3e892d24e8b8f0d1b504c4 Mon Sep 17 00:00:00 2001 From: vang1ong7ang Date: Mon, 8 Nov 2021 07:46:16 -0500 Subject: [PATCH 26/30] Update NeoBurgerGovernanceToken.cs --- NeoBurgerGovernanceToken.cs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 0f695d7..98e094a 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -58,17 +58,14 @@ struct ProposalAttributesStruct public static void _deploy(object data, bool update) { - if (!update) - { - StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); - ProposalAttributesStruct proposal_attributes = new(); - proposal_attributes.id = 0; - proposal_id_map.PutObject((ByteString)(BigInteger)0, proposal_attributes); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_VOTING_PERIOD }, 86400000 * 7); - Mint(INITIAL_HOLDER, 10_000_000_000_000_000); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, INITIAL_HOLDER); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }, 100_000_000_000_000); - } + StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); + ProposalAttributesStruct proposal_attributes = new(); + proposal_attributes.id = 0; + proposal_id_map.PutObject((ByteString)(BigInteger)0, proposal_attributes); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_VOTING_PERIOD }, 86400000 * 7); + Mint(INITIAL_HOLDER, 10_000_000_000_000_000); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, INITIAL_HOLDER); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }, 100_000_000_000_000); } public static void BecomeDefaultDelegate(UInt160 account) { From 149ddee9ad12aac775e360d329f59e02e4ff680f Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Tue, 9 Nov 2021 09:38:17 +0800 Subject: [PATCH 27/30] leave VOTING_PERIOD a readonly const --- NeoBurgerGovernanceToken.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 98e094a..cf8196c 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -18,17 +18,17 @@ public class NeoBurgerGovernanceToken : Nep17Token { [InitialValue("[TODO]: ARGS", ContractParameterType.Hash160)] private static readonly UInt160 INITIAL_HOLDER = default; + private static readonly BigInteger VOTING_PERIOD = 86400000 * 7; private static readonly byte PREFIX_PROPOSAL = 0x03; private static readonly byte PREFIX_PROPOSAL_EXECUTED_TIME = 0x05; private static readonly byte PREFIX_DELEGATE = 0x81; private static readonly byte PREFIX_DEFAULT_DELEGATE = 0x82; private static readonly byte PREFIX_DELEGATE_THRESHOLD = 0x83; private static readonly byte PREFIX_VOTE = 0xc1; - private static readonly byte PREFIX_VOTING_PERIOD = 0xc2; public override byte Decimals() => 8; public override string Symbol() => "NOBUG"; - public static BigInteger GetVotingPeriod() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_VOTING_PERIOD }); + public static BigInteger GetVotingPeriod() => VOTING_PERIOD; public static object[] ProposalAttributes(BigInteger id) { @@ -62,7 +62,6 @@ public static void _deploy(object data, bool update) ProposalAttributesStruct proposal_attributes = new(); proposal_attributes.id = 0; proposal_id_map.PutObject((ByteString)(BigInteger)0, proposal_attributes); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_VOTING_PERIOD }, 86400000 * 7); Mint(INITIAL_HOLDER, 10_000_000_000_000_000); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, INITIAL_HOLDER); Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }, 100_000_000_000_000); @@ -79,11 +78,6 @@ public static void BecomeDefaultDelegate(UInt160 account) throw new Exception("No enough tokens. You need "+(ByteString)default_delegate_balance+" NOBUGs to be the default delegate"); } - public static void SetMinimalTimePeriodForVoting(BigInteger time_period) - { - ExecutionEngine.Assert(Runtime.CheckWitness(Runtime.ExecutingScriptHash)); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_VOTING_PERIOD }, time_period); - } public static BigInteger NewProposal(BigInteger proposal_id, UInt160 scripthash, string method, ByteString[] args) { StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); @@ -94,7 +88,7 @@ public static BigInteger NewProposal(BigInteger proposal_id, UInt160 scripthash, proposal_attributes.scripthash = scripthash; proposal_attributes.method = method; proposal_attributes.args = args; - proposal_attributes.voting_deadline = Runtime.Time + GetVotingPeriod(); + proposal_attributes.voting_deadline = Runtime.Time + VOTING_PERIOD; proposal_id_map.PutObject((ByteString)proposal_id, proposal_attributes); return proposal_id; } From 2ed8b81d6af8b7cccdb9d4e2182ffc04d5022dee Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Tue, 9 Nov 2021 12:29:00 +0800 Subject: [PATCH 28/30] initially set readonly byte[] for prefixes --- NeoBurgerGovernanceToken.cs | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index cf8196c..88ac323 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -19,12 +19,12 @@ public class NeoBurgerGovernanceToken : Nep17Token [InitialValue("[TODO]: ARGS", ContractParameterType.Hash160)] private static readonly UInt160 INITIAL_HOLDER = default; private static readonly BigInteger VOTING_PERIOD = 86400000 * 7; - private static readonly byte PREFIX_PROPOSAL = 0x03; - private static readonly byte PREFIX_PROPOSAL_EXECUTED_TIME = 0x05; - private static readonly byte PREFIX_DELEGATE = 0x81; - private static readonly byte PREFIX_DEFAULT_DELEGATE = 0x82; - private static readonly byte PREFIX_DELEGATE_THRESHOLD = 0x83; - private static readonly byte PREFIX_VOTE = 0xc1; + private static readonly byte[] PREFIX_PROPOSAL = new byte[] { 0x03 }; + private static readonly byte[] PREFIX_PROPOSAL_EXECUTED_TIME = new byte[] { 0x05 }; + private static readonly byte[] PREFIX_DELEGATE = new byte[] { 0x81 }; + private static readonly byte[] PREFIX_DEFAULT_DELEGATE = new byte[] { 0x82 }; + private static readonly byte[] PREFIX_DELEGATE_THRESHOLD = new byte[] { 0x83 }; + private static readonly byte[] PREFIX_VOTE = new byte[] { 0xc1 }; public override byte Decimals() => 8; public override string Symbol() => "NOBUG"; @@ -32,20 +32,20 @@ public class NeoBurgerGovernanceToken : Nep17Token public static object[] ProposalAttributes(BigInteger id) { - StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); + StorageMap proposal_id_map = new(Storage.CurrentContext, PREFIX_PROPOSAL); ProposalAttributesStruct proposal_attributes = (ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)id); - StorageMap proposal_executed_time_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }); - BigInteger executed_time = (BigInteger)proposal_executed_time_map.Get(new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }); + StorageMap proposal_executed_time_map = new(Storage.CurrentContext, PREFIX_PROPOSAL_EXECUTED_TIME); + BigInteger executed_time = (BigInteger)proposal_executed_time_map.Get(PREFIX_PROPOSAL_EXECUTED_TIME); return new object[] { proposal_attributes.scripthash, proposal_attributes.method, proposal_attributes.args, proposal_attributes.voting_deadline, executed_time }; } public static UInt160 GetDelegate(UInt160 from) => (UInt160)new StorageMap(Storage.CurrentContext, PREFIX_DELEGATE).Get(from); - public static UInt160 GetDefaultDelegate() => (UInt160)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }); + public static UInt160 GetDefaultDelegate() => (UInt160)Storage.Get(Storage.CurrentContext, PREFIX_DEFAULT_DELEGATE); public static BigInteger GetDefaultDelegateBalance() => BalanceOf(GetDefaultDelegate()); - public static BigInteger GetDelegateThreshold() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }); + public static BigInteger GetDelegateThreshold() => (BigInteger)Storage.Get(Storage.CurrentContext, PREFIX_DELEGATE_THRESHOLD); public static bool IsValidDelegate(UInt160 account) => account is not null && account.IsValid && (BalanceOf(account) > GetDelegateThreshold()); - public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_index).Get(from); - public static Iterator GetVotersOfProposal(BigInteger proposal_id) => new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_id).Find((FindOptions)((byte)FindOptions.KeysOnly + (byte)FindOptions.RemovePrefix)); + public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, (ByteString)PREFIX_VOTE + (ByteString)proposal_index).Get(from); + public static Iterator GetVotersOfProposal(BigInteger proposal_id) => new StorageMap(Storage.CurrentContext, (ByteString)PREFIX_VOTE + (ByteString)proposal_id).Find((FindOptions)((byte)FindOptions.KeysOnly + (byte)FindOptions.RemovePrefix)); struct ProposalAttributesStruct { @@ -58,29 +58,29 @@ struct ProposalAttributesStruct public static void _deploy(object data, bool update) { - StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); + StorageMap proposal_id_map = new(Storage.CurrentContext, PREFIX_PROPOSAL); ProposalAttributesStruct proposal_attributes = new(); proposal_attributes.id = 0; proposal_id_map.PutObject((ByteString)(BigInteger)0, proposal_attributes); Mint(INITIAL_HOLDER, 10_000_000_000_000_000); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, INITIAL_HOLDER); - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }, 100_000_000_000_000); + Storage.Put(Storage.CurrentContext, PREFIX_DEFAULT_DELEGATE, INITIAL_HOLDER); + Storage.Put(Storage.CurrentContext, PREFIX_DELEGATE_THRESHOLD, 100_000_000_000_000); } public static void BecomeDefaultDelegate(UInt160 account) { ExecutionEngine.Assert(Runtime.CheckWitness(account)); - UInt160 default_delegate = (UInt160)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }); + UInt160 default_delegate = (UInt160)Storage.Get(Storage.CurrentContext, PREFIX_DEFAULT_DELEGATE); BigInteger to_account_balance = BalanceOf(account); BigInteger default_delegate_balance = BalanceOf(default_delegate); if (to_account_balance > default_delegate_balance && to_account_balance > GetDelegateThreshold()) - Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, account); + Storage.Put(Storage.CurrentContext, PREFIX_DEFAULT_DELEGATE, account); else throw new Exception("No enough tokens. You need "+(ByteString)default_delegate_balance+" NOBUGs to be the default delegate"); } public static BigInteger NewProposal(BigInteger proposal_id, UInt160 scripthash, string method, ByteString[] args) { - StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); + StorageMap proposal_id_map = new(Storage.CurrentContext, PREFIX_PROPOSAL); if ((BigInteger)proposal_id_map.Get((ByteString)proposal_id) != 0 || ((ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)(proposal_id - 1))).id != proposal_id - 1) throw new Exception("Invalid proposal id"); ProposalAttributesStruct proposal_attributes = new(); @@ -106,14 +106,14 @@ public static void Delegate(UInt160 from, UInt160 to) public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_against) { ExecutionEngine.Assert(Runtime.CheckWitness(from)); - StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); + StorageMap proposal_id_map = new(Storage.CurrentContext, PREFIX_PROPOSAL); ProposalAttributesStruct proposal_attributes = (ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)proposal_index); BigInteger voting_deadline = proposal_attributes.voting_deadline; if (voting_deadline == 0) throw new Exception("The proposal does not exist"); if(Runtime.Time > voting_deadline) throw new Exception("Cannot vote after the deadline"); - StorageMap vote_map = new(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_index); + StorageMap vote_map = new(Storage.CurrentContext, (ByteString)PREFIX_VOTE + (ByteString)proposal_index); if (for_or_against) vote_map.Put(from, 1); else @@ -123,7 +123,7 @@ public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_aga public static BigInteger CountVote(BigInteger proposal_id) { BigInteger sum_votes = 0; - Iterator voters = new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_id) + Iterator voters = new StorageMap(Storage.CurrentContext, (ByteString)PREFIX_VOTE + (ByteString)proposal_id) .Find((FindOptions)((byte)FindOptions.KeysOnly + (byte)FindOptions.RemovePrefix)); bool default_delegate_voted = GetVote(GetDefaultDelegate(), proposal_id) > 0; while (voters.Next()) @@ -193,8 +193,8 @@ public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) } if (sum_votes > TotalSupply() / 2) { - new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_PROPOSAL } + (ByteString)proposal_id) - .Put(new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }, Runtime.Time); + new StorageMap(Storage.CurrentContext, (ByteString)PREFIX_PROPOSAL + (ByteString)proposal_id) + .Put(PREFIX_PROPOSAL_EXECUTED_TIME, Runtime.Time); return Contract.Call(scripthash, method, CallFlags.All, args); } else From 95c7b873eb1f5f39d91b7c7954480c37e5f1bfa6 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Tue, 9 Nov 2021 12:41:17 +0800 Subject: [PATCH 29/30] remove useless `if (voting_deadline == 0)` --- NeoBurgerGovernanceToken.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 88ac323..4b3357a 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -109,8 +109,6 @@ public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_aga StorageMap proposal_id_map = new(Storage.CurrentContext, PREFIX_PROPOSAL); ProposalAttributesStruct proposal_attributes = (ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)proposal_index); BigInteger voting_deadline = proposal_attributes.voting_deadline; - if (voting_deadline == 0) - throw new Exception("The proposal does not exist"); if(Runtime.Time > voting_deadline) throw new Exception("Cannot vote after the deadline"); StorageMap vote_map = new(Storage.CurrentContext, (ByteString)PREFIX_VOTE + (ByteString)proposal_index); From bed39839a54cf04f48c706426a4f5b4564d76dd3 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Tue, 9 Nov 2021 13:14:09 +0800 Subject: [PATCH 30/30] use const instead of bytearray --- NeoBurgerGovernanceToken.cs | 54 +++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/NeoBurgerGovernanceToken.cs b/NeoBurgerGovernanceToken.cs index 4b3357a..567dff1 100644 --- a/NeoBurgerGovernanceToken.cs +++ b/NeoBurgerGovernanceToken.cs @@ -17,14 +17,14 @@ namespace NeoBurger public class NeoBurgerGovernanceToken : Nep17Token { [InitialValue("[TODO]: ARGS", ContractParameterType.Hash160)] - private static readonly UInt160 INITIAL_HOLDER = default; - private static readonly BigInteger VOTING_PERIOD = 86400000 * 7; - private static readonly byte[] PREFIX_PROPOSAL = new byte[] { 0x03 }; - private static readonly byte[] PREFIX_PROPOSAL_EXECUTED_TIME = new byte[] { 0x05 }; - private static readonly byte[] PREFIX_DELEGATE = new byte[] { 0x81 }; - private static readonly byte[] PREFIX_DEFAULT_DELEGATE = new byte[] { 0x82 }; - private static readonly byte[] PREFIX_DELEGATE_THRESHOLD = new byte[] { 0x83 }; - private static readonly byte[] PREFIX_VOTE = new byte[] { 0xc1 }; + private const UInt160 INITIAL_HOLDER = default; + private const ulong VOTING_PERIOD = 86400000 * 7; + private const byte PREFIX_PROPOSAL = 0x03; + private const byte PREFIX_PROPOSAL_EXECUTED_TIME = 0x05; + private const byte PREFIX_DELEGATE = 0x81; + private const byte PREFIX_DEFAULT_DELEGATE = 0x82; + private const byte PREFIX_DELEGATE_THRESHOLD = 0x83; + private const byte PREFIX_VOTE = 0xc1; public override byte Decimals() => 8; public override string Symbol() => "NOBUG"; @@ -32,20 +32,21 @@ public class NeoBurgerGovernanceToken : Nep17Token public static object[] ProposalAttributes(BigInteger id) { - StorageMap proposal_id_map = new(Storage.CurrentContext, PREFIX_PROPOSAL); + StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); ProposalAttributesStruct proposal_attributes = (ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)id); - StorageMap proposal_executed_time_map = new(Storage.CurrentContext, PREFIX_PROPOSAL_EXECUTED_TIME); - BigInteger executed_time = (BigInteger)proposal_executed_time_map.Get(PREFIX_PROPOSAL_EXECUTED_TIME); + byte[] proposal_executed_time_bytearray = new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }; + StorageMap proposal_executed_time_map = new(Storage.CurrentContext, proposal_executed_time_bytearray); + BigInteger executed_time = (BigInteger)proposal_executed_time_map.Get((ByteString)id); return new object[] { proposal_attributes.scripthash, proposal_attributes.method, proposal_attributes.args, proposal_attributes.voting_deadline, executed_time }; } public static UInt160 GetDelegate(UInt160 from) => (UInt160)new StorageMap(Storage.CurrentContext, PREFIX_DELEGATE).Get(from); - public static UInt160 GetDefaultDelegate() => (UInt160)Storage.Get(Storage.CurrentContext, PREFIX_DEFAULT_DELEGATE); + public static UInt160 GetDefaultDelegate() => (UInt160)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }); public static BigInteger GetDefaultDelegateBalance() => BalanceOf(GetDefaultDelegate()); - public static BigInteger GetDelegateThreshold() => (BigInteger)Storage.Get(Storage.CurrentContext, PREFIX_DELEGATE_THRESHOLD); + public static BigInteger GetDelegateThreshold() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }); public static bool IsValidDelegate(UInt160 account) => account is not null && account.IsValid && (BalanceOf(account) > GetDelegateThreshold()); - public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, (ByteString)PREFIX_VOTE + (ByteString)proposal_index).Get(from); - public static Iterator GetVotersOfProposal(BigInteger proposal_id) => new StorageMap(Storage.CurrentContext, (ByteString)PREFIX_VOTE + (ByteString)proposal_id).Find((FindOptions)((byte)FindOptions.KeysOnly + (byte)FindOptions.RemovePrefix)); + public static BigInteger GetVote(UInt160 from, BigInteger proposal_index) => (BigInteger)new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_index).Get(from); + public static Iterator GetVotersOfProposal(BigInteger proposal_id) => new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_id).Find((FindOptions)((byte)FindOptions.KeysOnly + (byte)FindOptions.RemovePrefix)); struct ProposalAttributesStruct { @@ -58,29 +59,30 @@ struct ProposalAttributesStruct public static void _deploy(object data, bool update) { - StorageMap proposal_id_map = new(Storage.CurrentContext, PREFIX_PROPOSAL); + StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); ProposalAttributesStruct proposal_attributes = new(); proposal_attributes.id = 0; proposal_id_map.PutObject((ByteString)(BigInteger)0, proposal_attributes); Mint(INITIAL_HOLDER, 10_000_000_000_000_000); - Storage.Put(Storage.CurrentContext, PREFIX_DEFAULT_DELEGATE, INITIAL_HOLDER); - Storage.Put(Storage.CurrentContext, PREFIX_DELEGATE_THRESHOLD, 100_000_000_000_000); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DEFAULT_DELEGATE }, INITIAL_HOLDER); + Storage.Put(Storage.CurrentContext, new byte[] { PREFIX_DELEGATE_THRESHOLD }, 100_000_000_000_000); } public static void BecomeDefaultDelegate(UInt160 account) { ExecutionEngine.Assert(Runtime.CheckWitness(account)); - UInt160 default_delegate = (UInt160)Storage.Get(Storage.CurrentContext, PREFIX_DEFAULT_DELEGATE); + byte[] default_delegate_bytearray = new byte[] { PREFIX_DEFAULT_DELEGATE }; + UInt160 default_delegate = (UInt160)Storage.Get(Storage.CurrentContext, default_delegate_bytearray); BigInteger to_account_balance = BalanceOf(account); BigInteger default_delegate_balance = BalanceOf(default_delegate); if (to_account_balance > default_delegate_balance && to_account_balance > GetDelegateThreshold()) - Storage.Put(Storage.CurrentContext, PREFIX_DEFAULT_DELEGATE, account); + Storage.Put(Storage.CurrentContext, default_delegate_bytearray, account); else throw new Exception("No enough tokens. You need "+(ByteString)default_delegate_balance+" NOBUGs to be the default delegate"); } public static BigInteger NewProposal(BigInteger proposal_id, UInt160 scripthash, string method, ByteString[] args) { - StorageMap proposal_id_map = new(Storage.CurrentContext, PREFIX_PROPOSAL); + StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); if ((BigInteger)proposal_id_map.Get((ByteString)proposal_id) != 0 || ((ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)(proposal_id - 1))).id != proposal_id - 1) throw new Exception("Invalid proposal id"); ProposalAttributesStruct proposal_attributes = new(); @@ -106,12 +108,12 @@ public static void Delegate(UInt160 from, UInt160 to) public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_against) { ExecutionEngine.Assert(Runtime.CheckWitness(from)); - StorageMap proposal_id_map = new(Storage.CurrentContext, PREFIX_PROPOSAL); + StorageMap proposal_id_map = new(Storage.CurrentContext, new byte[] { PREFIX_PROPOSAL }); ProposalAttributesStruct proposal_attributes = (ProposalAttributesStruct)proposal_id_map.GetObject((ByteString)proposal_index); BigInteger voting_deadline = proposal_attributes.voting_deadline; if(Runtime.Time > voting_deadline) throw new Exception("Cannot vote after the deadline"); - StorageMap vote_map = new(Storage.CurrentContext, (ByteString)PREFIX_VOTE + (ByteString)proposal_index); + StorageMap vote_map = new(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_index); if (for_or_against) vote_map.Put(from, 1); else @@ -121,7 +123,7 @@ public static void Vote(UInt160 from, BigInteger proposal_index, bool for_or_aga public static BigInteger CountVote(BigInteger proposal_id) { BigInteger sum_votes = 0; - Iterator voters = new StorageMap(Storage.CurrentContext, (ByteString)PREFIX_VOTE + (ByteString)proposal_id) + Iterator voters = new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_VOTE } + (ByteString)proposal_id) .Find((FindOptions)((byte)FindOptions.KeysOnly + (byte)FindOptions.RemovePrefix)); bool default_delegate_voted = GetVote(GetDefaultDelegate(), proposal_id) > 0; while (voters.Next()) @@ -191,8 +193,8 @@ public static object ExecuteProposal(BigInteger proposal_id, UInt160[] voters) } if (sum_votes > TotalSupply() / 2) { - new StorageMap(Storage.CurrentContext, (ByteString)PREFIX_PROPOSAL + (ByteString)proposal_id) - .Put(PREFIX_PROPOSAL_EXECUTED_TIME, Runtime.Time); + new StorageMap(Storage.CurrentContext, (ByteString)new byte[] { PREFIX_PROPOSAL } + (ByteString)proposal_id) + .Put(new byte[] { PREFIX_PROPOSAL_EXECUTED_TIME }, Runtime.Time); return Contract.Call(scripthash, method, CallFlags.All, args); } else