/ synthesizer / program / src / resources / governance.delta
governance.delta
  1  // Copyright (c) 2025 ALPHA/DELTA Network
  2  // This file is part of the DeltaVM library.
  3  
  4  // Licensed under the Apache License, Version 2.0 (the "License");
  5  // you may not use this file except in compliance with the License.
  6  // You may obtain a copy of the License at:
  7  
  8  // http://www.apache.org/licenses/LICENSE-2.0
  9  
 10  // Unless required by applicable law or agreed to in writing, software
 11  // distributed under the License is distributed on an "AS IS" BASIS,
 12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  // See the License for the specific language governing permissions and
 14  // limitations under the License.
 15  
 16  /**********************************************************************************************************************/
 17  // DELTA Governance Program
 18  //
 19  // Provides DX token voting and protocol governance:
 20  // - Proposal threshold: 1,000,000 DX to submit
 21  // - Voting threshold: 10,000 DX minimum to participate
 22  // - Approval thresholds:
 23  //   - Standard proposals: >50% with 10% quorum
 24  //   - Critical proposals: >67% with 20% quorum
 25  // - Critical proposal types: Governor add/remove, emergency actions, P/E ratio changes
 26  // - Timelock: 48 hours standard, 7 days for critical (with emergency veto at 80% opposition)
 27  //
 28  // DX Token Properties:
 29  // - Supply: Fixed 1,000,000,000 tokens at genesis
 30  // - Decimals: 0 (whole tokens only)
 31  // - Minting: None after genesis
 32  // - Staking: Default-staked (opt-out for transfers)
 33  /**********************************************************************************************************************/
 34  
 35  program delta.governance;
 36  
 37  /**********************************************************************************************************************/
 38  // CONSTANTS (represented as literals in code)
 39  /**********************************************************************************************************************/
 40  
 41  // PROPOSAL_THRESHOLD = 1_000_000 DX
 42  // VOTING_THRESHOLD = 10_000 DX
 43  // STANDARD_QUORUM_BPS = 1000 (10%)
 44  // CRITICAL_QUORUM_BPS = 2000 (20%)
 45  // STANDARD_APPROVAL_BPS = 5000 (50%)
 46  // CRITICAL_APPROVAL_BPS = 6700 (67%)
 47  // VETO_THRESHOLD_BPS = 8000 (80%)
 48  // STANDARD_TIMELOCK_BLOCKS = 17280 (48 hours at 10s blocks)
 49  // CRITICAL_TIMELOCK_BLOCKS = 60480 (7 days at 10s blocks)
 50  // VOTING_PERIOD_BLOCKS = 30240 (84 hours at 10s blocks)
 51  
 52  /**********************************************************************************************************************/
 53  // STRUCTS
 54  /**********************************************************************************************************************/
 55  
 56  // A governance proposal.
 57  struct proposal:
 58      // Proposal ID (unique).
 59      proposal_id as u128;
 60      // Proposer's address.
 61      proposer as address;
 62      // Proposal type: 0 = Standard, 1 = Critical.
 63      proposal_type as u8;
 64      // Action type (see action_type enum).
 65      action_type as u8;
 66      // Action parameter (context-dependent).
 67      action_param as field;
 68      // Total yes votes.
 69      yes_votes as u128;
 70      // Total no votes.
 71      no_votes as u128;
 72      // Block when proposal was created.
 73      created_at as u32;
 74      // Block when voting ends.
 75      voting_ends_at as u32;
 76      // Block when timelock ends (if passed).
 77      timelock_ends_at as u32;
 78      // Status: 0 = Pending, 1 = Active, 2 = Passed, 3 = Failed, 4 = Executed, 5 = Vetoed, 6 = Expired.
 79      status as u8;
 80  
 81  // Vote record for a user on a proposal.
 82  struct vote_record:
 83      // Proposal ID.
 84      proposal_id as u128;
 85      // Voter address.
 86      voter as address;
 87      // Vote: 0 = No, 1 = Yes.
 88      vote as u8;
 89      // Voting power used.
 90      power as u128;
 91      // Block when vote was cast.
 92      voted_at as u32;
 93  
 94  // DX holder status.
 95  struct dx_holder:
 96      // Total DX balance.
 97      balance as u128;
 98      // Staked (locked) DX.
 99      staked as u128;
100      // Available for transfer.
101      available as u128;
102      // Delegated voting power (from others).
103      delegated_power as u128;
104      // Address this holder delegates to (if any).
105      delegate as address;
106  
107  // Governance configuration.
108  struct gov_config:
109      // Proposal submission threshold.
110      proposal_threshold as u128;
111      // Voting participation threshold.
112      voting_threshold as u128;
113      // Standard quorum in bps.
114      standard_quorum_bps as u16;
115      // Critical quorum in bps.
116      critical_quorum_bps as u16;
117      // Standard approval threshold in bps.
118      standard_approval_bps as u16;
119      // Critical approval threshold in bps.
120      critical_approval_bps as u16;
121      // Veto threshold in bps.
122      veto_threshold_bps as u16;
123      // Standard timelock in blocks.
124      standard_timelock_blocks as u32;
125      // Critical timelock in blocks.
126      critical_timelock_blocks as u32;
127      // Voting period in blocks.
128      voting_period_blocks as u32;
129  
130  /**********************************************************************************************************************/
131  // MAPPINGS
132  /**********************************************************************************************************************/
133  
134  // Proposals by ID.
135  mapping proposals:
136      key as u128.public;
137      value as proposal.public;
138  
139  // Vote records by hash(proposal_id, voter).
140  mapping votes:
141      key as field.public;
142      value as vote_record.public;
143  
144  // DX holder balances and status.
145  mapping dx_holders:
146      key as address.public;
147      value as dx_holder.public;
148  
149  // Governance configuration.
150  mapping config:
151      key as u8.public;
152      value as gov_config.public;
153  
154  // Total DX supply (should be 1,000,000,000).
155  mapping total_supply:
156      key as u8.public;
157      value as u128.public;
158  
159  // Total staked DX.
160  mapping total_staked:
161      key as u8.public;
162      value as u128.public;
163  
164  // Proposal counter.
165  mapping counters:
166      key as u8.public;
167      value as u128.public;
168  
169  // Executed proposals (for cross-chain attestation).
170  mapping executed_proposals:
171      key as u128.public;
172      value as u32.public; // Block height when executed
173  
174  // Governor registry (for ALPHA chain governance).
175  mapping governors:
176      key as address.public;
177      value as boolean.public;
178  
179  /**********************************************************************************************************************/
180  // ACTION TYPES
181  /**********************************************************************************************************************/
182  
183  // Action types for proposals:
184  // 0 = UpdateParameter - Update a protocol parameter
185  // 1 = AddGovernor - Add a new Governor (critical)
186  // 2 = RemoveGovernor - Remove a Governor (critical)
187  // 3 = EmergencyPauseMinting - Pause minting on ALPHA (critical)
188  // 4 = EmergencyResumeMinting - Resume minting on ALPHA (critical)
189  // 5 = UpdateMintingRate - Change minting rate parameters
190  // 6 = UpdateFees - Update exchange/perpetuals fee structure
191  // 7 = TransferTreasury - Transfer from governance treasury
192  // 8 = UpgradeContract - Contract upgrade (critical)
193  
194  /**********************************************************************************************************************/
195  // FUNCTIONS
196  /**********************************************************************************************************************/
197  
198  // Submit a new proposal.
199  function submit_proposal:
200      // Input the proposal type (0 = Standard, 1 = Critical).
201      input r0 as u8.public;
202      // Input the action type.
203      input r1 as u8.public;
204      // Input the action parameter.
205      input r2 as field.public;
206  
207      // Validate proposal type.
208      lte r0 1u8 into r3;
209      assert.eq r3 true;
210  
211      // Validate action type (0-8).
212      lte r1 8u8 into r4;
213      assert.eq r4 true;
214  
215      async submit_proposal self.caller r0 r1 r2 into r5;
216      output r5 as delta.governance/submit_proposal.future;
217  
218  finalize submit_proposal:
219      // Input the proposer.
220      input r0 as address.public;
221      // Input the proposal type.
222      input r1 as u8.public;
223      // Input the action type.
224      input r2 as u8.public;
225      // Input the action parameter.
226      input r3 as field.public;
227  
228      // Get proposer's DX balance.
229      cast 0u128 0u128 0u128 0u128 r0 into r4 as dx_holder;
230      get.or_use dx_holders[r0] r4 into r5;
231  
232      // Check proposal threshold (1,000,000 DX).
233      gte r5.staked 1000000u128 into r6;
234      assert.eq r6 true;
235  
236      // Validate critical actions require critical proposal type.
237      // Actions 1, 2, 3, 4, 8 are critical.
238      is.eq r2 1u8 into r7;
239      is.eq r2 2u8 into r8;
240      is.eq r2 3u8 into r9;
241      is.eq r2 4u8 into r10;
242      is.eq r2 8u8 into r11;
243      or r7 r8 into r12;
244      or r12 r9 into r13;
245      or r13 r10 into r14;
246      or r14 r11 into r15; // r15 = action is critical
247  
248      // If action is critical, proposal type must be 1.
249      not r15 into r16;
250      is.eq r1 1u8 into r17;
251      or r16 r17 into r18; // Either not critical action, or critical proposal type
252      assert.eq r18 true;
253  
254      // Get config.
255      cast 1000000u128 10000u128 1000u16 2000u16 5000u16 6700u16 8000u16 17280u32 60480u32 30240u32 into r19 as gov_config;
256      get.or_use config[0u8] r19 into r20;
257  
258      // Calculate voting end and timelock.
259      add block.height r20.voting_period_blocks into r21; // Voting ends
260  
261      // Timelock based on proposal type.
262      is.eq r1 0u8 into r22;
263      ternary r22 r20.standard_timelock_blocks r20.critical_timelock_blocks into r23;
264      add r21 r23 into r24; // Timelock ends
265  
266      // Get next proposal ID.
267      get.or_use counters[0u8] 1u128 into r25;
268  
269      // Create proposal.
270      cast r25 r0 r1 r2 r3 0u128 0u128 block.height r21 r24 1u8 into r26 as proposal;
271  
272      // Store proposal.
273      set r26 into proposals[r25];
274  
275      // Increment counter.
276      add r25 1u128 into r27;
277      set r27 into counters[0u8];
278  
279  /**********************************************************************************************************************/
280  
281  // Cast a vote on a proposal.
282  function vote:
283      // Input the proposal ID.
284      input r0 as u128.public;
285      // Input the vote (0 = No, 1 = Yes).
286      input r1 as u8.public;
287  
288      // Validate vote.
289      lte r1 1u8 into r2;
290      assert.eq r2 true;
291  
292      async vote self.caller r0 r1 into r3;
293      output r3 as delta.governance/vote.future;
294  
295  finalize vote:
296      // Input the voter.
297      input r0 as address.public;
298      // Input the proposal ID.
299      input r1 as u128.public;
300      // Input the vote.
301      input r2 as u8.public;
302  
303      // Get proposal.
304      get proposals[r1] into r3;
305  
306      // Verify proposal is active.
307      assert.eq r3.status 1u8;
308  
309      // Verify voting period hasn't ended.
310      lt block.height r3.voting_ends_at into r4;
311      assert.eq r4 true;
312  
313      // Get voter's DX holdings.
314      cast 0u128 0u128 0u128 0u128 r0 into r5 as dx_holder;
315      get.or_use dx_holders[r0] r5 into r6;
316  
317      // Check voting threshold (10,000 DX).
318      add r6.staked r6.delegated_power into r7; // Total voting power
319      gte r7 10000u128 into r8;
320      assert.eq r8 true;
321  
322      // Check if already voted.
323      // Compute vote key: hash(proposal_id || voter).
324      hash.bhp256 r1 into r9;
325      hash.bhp256 r0 into r10;
326      add r9 r10 into r11;
327  
328      contains votes[r11] into r12;
329      assert.eq r12 false; // Must not have voted
330  
331      // Record vote.
332      cast r1 r0 r2 r7 block.height into r13 as vote_record;
333      set r13 into votes[r11];
334  
335      // Update proposal vote counts.
336      is.eq r2 1u8 into r14; // Is yes vote?
337      ternary r14 r7 0u128 into r15; // Add to yes if yes
338      ternary r14 0u128 r7 into r16; // Add to no if no
339  
340      add r3.yes_votes r15 into r17;
341      add r3.no_votes r16 into r18;
342  
343      cast r3.proposal_id r3.proposer r3.proposal_type r3.action_type r3.action_param r17 r18 r3.created_at r3.voting_ends_at r3.timelock_ends_at r3.status into r19 as proposal;
344      set r19 into proposals[r1];
345  
346  /**********************************************************************************************************************/
347  
348  // Finalize a proposal after voting ends.
349  function finalize_proposal:
350      // Input the proposal ID.
351      input r0 as u128.public;
352  
353      async finalize_proposal r0 into r1;
354      output r1 as delta.governance/finalize_proposal.future;
355  
356  finalize finalize_proposal:
357      // Input the proposal ID.
358      input r0 as u128.public;
359  
360      // Get proposal.
361      get proposals[r0] into r1;
362  
363      // Verify proposal is active.
364      assert.eq r1.status 1u8;
365  
366      // Verify voting period has ended.
367      gte block.height r1.voting_ends_at into r2;
368      assert.eq r2 true;
369  
370      // Get total staked for quorum calculation.
371      get.or_use total_staked[0u8] 1000000000u128 into r3;
372  
373      // Get config.
374      cast 1000000u128 10000u128 1000u16 2000u16 5000u16 6700u16 8000u16 17280u32 60480u32 30240u32 into r4 as gov_config;
375      get.or_use config[0u8] r4 into r5;
376  
377      // Calculate total votes.
378      add r1.yes_votes r1.no_votes into r6;
379  
380      // Calculate quorum requirement.
381      is.eq r1.proposal_type 0u8 into r7;
382      ternary r7 r5.standard_quorum_bps r5.critical_quorum_bps into r8;
383      cast r8 into r9 as u128;
384      mul r3 r9 into r10;
385      div r10 10000u128 into r11; // Required quorum
386  
387      // Check if quorum met.
388      gte r6 r11 into r12;
389  
390      // Calculate approval percentage (in bps).
391      mul r1.yes_votes 10000u128 into r13;
392      div r13 r6 into r14; // Yes percentage in bps
393  
394      // Get required approval threshold.
395      ternary r7 r5.standard_approval_bps r5.critical_approval_bps into r15;
396      cast r15 into r16 as u128;
397  
398      // Check if approved.
399      gt r14 r16 into r17;
400  
401      // Check for veto (>80% no votes for critical).
402      mul r1.no_votes 10000u128 into r18;
403      div r18 r6 into r19; // No percentage in bps
404      cast r5.veto_threshold_bps into r20 as u128;
405      gt r19 r20 into r21;
406      is.eq r1.proposal_type 1u8 into r22;
407      and r21 r22 into r23; // Vetoed if critical and >80% no
408  
409      // Determine final status.
410      // 2 = Passed, 3 = Failed, 5 = Vetoed
411      ternary r23 5u8 3u8 into r24; // Vetoed or Failed
412      and r12 r17 into r25; // Quorum met AND approved
413      ternary r25 2u8 r24 into r26; // Final status
414  
415      // Update proposal.
416      cast r1.proposal_id r1.proposer r1.proposal_type r1.action_type r1.action_param r1.yes_votes r1.no_votes r1.created_at r1.voting_ends_at r1.timelock_ends_at r26 into r27 as proposal;
417      set r27 into proposals[r0];
418  
419  /**********************************************************************************************************************/
420  
421  // Execute a passed proposal after timelock.
422  function execute_proposal:
423      // Input the proposal ID.
424      input r0 as u128.public;
425  
426      async execute_proposal self.caller r0 into r1;
427      output r1 as delta.governance/execute_proposal.future;
428  
429  finalize execute_proposal:
430      // Input the caller.
431      input r0 as address.public;
432      // Input the proposal ID.
433      input r1 as u128.public;
434  
435      // Get proposal.
436      get proposals[r1] into r2;
437  
438      // Verify proposal passed.
439      assert.eq r2.status 2u8;
440  
441      // Verify timelock has ended.
442      gte block.height r2.timelock_ends_at into r3;
443      assert.eq r3 true;
444  
445      // Mark as executed.
446      cast r2.proposal_id r2.proposer r2.proposal_type r2.action_type r2.action_param r2.yes_votes r2.no_votes r2.created_at r2.voting_ends_at r2.timelock_ends_at 4u8 into r4 as proposal;
447      set r4 into proposals[r1];
448  
449      // Record execution for cross-chain attestation.
450      set block.height into executed_proposals[r1];
451  
452      // Execute action based on type.
453      // Note: Actual execution logic would be more complex.
454      // For Governor add/remove, we update the governors mapping
455      // and emit attestation for ALPHA chain.
456  
457      is.eq r2.action_type 1u8 into r5; // AddGovernor
458      branch.eq r5 true to add_governor;
459  
460      is.eq r2.action_type 2u8 into r6; // RemoveGovernor
461      branch.eq r6 true to remove_governor;
462  
463      branch.eq true true to end;
464  
465      position add_governor;
466      // action_param contains the governor address (as field, need to convert).
467      // In production, would properly decode the address.
468      // For now, this is a placeholder.
469      branch.eq true true to end;
470  
471      position remove_governor;
472      // Similar to add_governor.
473      branch.eq true true to end;
474  
475      position end;
476  
477  /**********************************************************************************************************************/
478  
479  // Delegate voting power to another address.
480  function delegate:
481      // Input the delegate address.
482      input r0 as address.public;
483  
484      async delegate self.caller r0 into r1;
485      output r1 as delta.governance/delegate.future;
486  
487  finalize delegate:
488      // Input the delegator.
489      input r0 as address.public;
490      // Input the delegate.
491      input r1 as address.public;
492  
493      // Cannot delegate to self.
494      assert.neq r0 r1;
495  
496      // Get delegator's holdings.
497      cast 0u128 0u128 0u128 0u128 r0 into r2 as dx_holder;
498      get.or_use dx_holders[r0] r2 into r3;
499  
500      // Remove power from old delegate if any.
501      is.neq r3.delegate r0 into r4; // Has existing delegate
502      branch.eq r4 true to remove_old_delegate;
503      branch.eq true true to add_new_delegate;
504  
505      position remove_old_delegate;
506      cast 0u128 0u128 0u128 0u128 r3.delegate into r5 as dx_holder;
507      get.or_use dx_holders[r3.delegate] r5 into r6;
508      sub r6.delegated_power r3.staked into r7;
509      cast r6.balance r6.staked r6.available r7 r6.delegate into r8 as dx_holder;
510      set r8 into dx_holders[r3.delegate];
511  
512      position add_new_delegate;
513      // Add power to new delegate.
514      cast 0u128 0u128 0u128 0u128 r1 into r9 as dx_holder;
515      get.or_use dx_holders[r1] r9 into r10;
516      add r10.delegated_power r3.staked into r11;
517      cast r10.balance r10.staked r10.available r11 r10.delegate into r12 as dx_holder;
518      set r12 into dx_holders[r1];
519  
520      // Update delegator.
521      cast r3.balance r3.staked r3.available 0u128 r1 into r13 as dx_holder;
522      set r13 into dx_holders[r0];
523  
524  /**********************************************************************************************************************/
525  
526  // Stake DX tokens (default state - opt-out for transfers).
527  function stake_dx:
528      // Input the amount to stake.
529      input r0 as u128.public;
530  
531      gt r0 0u128 into r1;
532      assert.eq r1 true;
533  
534      async stake_dx self.caller r0 into r2;
535      output r2 as delta.governance/stake_dx.future;
536  
537  finalize stake_dx:
538      // Input the staker.
539      input r0 as address.public;
540      // Input the amount.
541      input r1 as u128.public;
542  
543      // Get holder status.
544      cast 0u128 0u128 0u128 0u128 r0 into r2 as dx_holder;
545      get.or_use dx_holders[r0] r2 into r3;
546  
547      // Check available balance.
548      gte r3.available r1 into r4;
549      assert.eq r4 true;
550  
551      // Update balances.
552      add r3.staked r1 into r5;
553      sub r3.available r1 into r6;
554  
555      cast r3.balance r5 r6 r3.delegated_power r3.delegate into r7 as dx_holder;
556      set r7 into dx_holders[r0];
557  
558      // Update total staked.
559      get.or_use total_staked[0u8] 0u128 into r8;
560      add r8 r1 into r9;
561      set r9 into total_staked[0u8];
562  
563  /**********************************************************************************************************************/
564  
565  // Unstake DX tokens (for transfers).
566  function unstake_dx:
567      // Input the amount to unstake.
568      input r0 as u128.public;
569  
570      gt r0 0u128 into r1;
571      assert.eq r1 true;
572  
573      async unstake_dx self.caller r0 into r2;
574      output r2 as delta.governance/unstake_dx.future;
575  
576  finalize unstake_dx:
577      // Input the unstaker.
578      input r0 as address.public;
579      // Input the amount.
580      input r1 as u128.public;
581  
582      // Get holder status.
583      get dx_holders[r0] into r2;
584  
585      // Check staked balance.
586      gte r2.staked r1 into r3;
587      assert.eq r3 true;
588  
589      // Update balances.
590      sub r2.staked r1 into r4;
591      add r2.available r1 into r5;
592  
593      cast r2.balance r4 r5 r2.delegated_power r2.delegate into r6 as dx_holder;
594      set r6 into dx_holders[r0];
595  
596      // Update total staked.
597      get total_staked[0u8] into r7;
598      sub r7 r1 into r8;
599      set r8 into total_staked[0u8];
600  
601      // Note: If delegated, need to update delegate's power too.
602      // Simplified for now.
603  
604  /**********************************************************************************************************************/
605  
606  // Initialize governance (called once at genesis).
607  function initialize:
608      // Input the initial DX distribution recipients (simplified - single address for demo).
609      input r0 as address.public;
610      // Input the initial amount.
611      input r1 as u128.public;
612  
613      async initialize self.caller r0 r1 into r2;
614      output r2 as delta.governance/initialize.future;
615  
616  finalize initialize:
617      // Input the caller.
618      input r0 as address.public;
619      // Input the recipient.
620      input r1 as address.public;
621      // Input the amount.
622      input r2 as u128.public;
623  
624      // Check if already initialized.
625      contains total_supply[0u8] into r3;
626      assert.eq r3 false;
627  
628      // Set total supply (1 billion DX).
629      set 1000000000u128 into total_supply[0u8];
630  
631      // Initialize config with defaults.
632      cast 1000000u128 10000u128 1000u16 2000u16 5000u16 6700u16 8000u16 17280u32 60480u32 30240u32 into r4 as gov_config;
633      set r4 into config[0u8];
634  
635      // Initialize counters.
636      set 1u128 into counters[0u8];
637  
638      // Give initial allocation to recipient (staked by default).
639      cast r2 r2 0u128 0u128 r1 into r5 as dx_holder;
640      set r5 into dx_holders[r1];
641  
642      // Update total staked.
643      set r2 into total_staked[0u8];
644  
645  /**********************************************************************************************************************/