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 /**********************************************************************************************************************/