From eec24c148f7456897c65b52f7e91513994c6034f Mon Sep 17 00:00:00 2001 From: friedger Date: Wed, 4 Dec 2024 17:25:59 +0100 Subject: [PATCH 1/2] fix: add ccip016 (WIP) --- .../proposals/ccip016-missed-payouts.clar | 326 ++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 contracts/proposals/ccip016-missed-payouts.clar diff --git a/contracts/proposals/ccip016-missed-payouts.clar b/contracts/proposals/ccip016-missed-payouts.clar new file mode 100644 index 0000000..979726c --- /dev/null +++ b/contracts/proposals/ccip016-missed-payouts.clar @@ -0,0 +1,326 @@ +;; TRAITS + +(impl-trait .proposal-trait.proposal-trait) +(impl-trait .ccip015-trait.ccip015-trait) + +;; ERRORS + +(define-constant ERR_PANIC (err u22000)) +(define-constant ERR_SAVING_VOTE (err u22001)) +(define-constant ERR_VOTED_ALREADY (err u22002)) +(define-constant ERR_NOTHING_STACKED (err u22003)) +(define-constant ERR_USER_NOT_FOUND (err u22004)) +(define-constant ERR_PROPOSAL_NOT_ACTIVE (err u22005)) +(define-constant ERR_PROPOSAL_STILL_ACTIVE (err u22006)) +(define-constant ERR_VOTE_FAILED (err u22007)) + +;; CONSTANTS + +(define-constant SELF (as-contract tx-sender)) +(define-constant CCIP_016 { + name: "CityCoins Treasury Redemption (NYC)", + link: "https://github.com/citycoins/governance/blob/feat/add-ccip-022/ccips/ccip-022/ccip-022-citycoins-treasury-redemption-nyc.md", + hash: "", +}) + +(define-constant VOTE_SCALE_FACTOR (pow u10 u16)) ;; 16 decimal places + +;; set city ID +(define-constant NYC_ID (default-to u2 (contract-call? .ccd004-city-registry get-city-id "nyc"))) + +;; DATA VARS + +;; vote block heights +(define-data-var voteActive bool true) +(define-data-var voteStart uint u0) +(define-data-var voteEnd uint u0) + +;; start the vote when deployed +(var-set voteStart block-height) + +;; DATA MAPS + +(define-map CityVotes + uint ;; city ID + { ;; vote + totalAmountYes: uint, + totalAmountNo: uint, + totalVotesYes: uint, + totalVotesNo: uint, + } +) + +(define-map UserVotes + uint ;; user ID + { ;; vote + vote: bool, + nyc: uint, + } +) +;; PUBLIC FUNCTIONS + +(define-public (execute (sender principal)) + (let ((miaMissedStxAmount (stx-get-balance .ccd002-treasury-nyc-mining-v2))) + ;; check vote is complete/passed + (try! (is-executable)) + ;; update vote variables + (var-set voteEnd block-height) + (var-set voteActive false) + ;; transfer funds to this contract + (try! (contract-call? .ccd002-treasury-mia-mining-v2 withdraw-stx 1092453541 (as-contract tx-sender))) + ;; initialize redemption extension + (try! (contract-call? .ccd012-redemption-nyc initialize-redemption)) + (ok true)) +) + +(define-public (vote-on-proposal (vote bool)) + (let + ( + (voterId (unwrap! (contract-call? .ccd003-user-registry get-user-id contract-caller) ERR_USER_NOT_FOUND)) + (voterRecord (map-get? UserVotes voterId)) + ) + ;; check if vote is active + (asserts! (var-get voteActive) ERR_PROPOSAL_NOT_ACTIVE) + ;; check if vote record exists for user + (match voterRecord record + ;; if the voterRecord exists + (let + ( + (oldVote (get vote record)) + (nycVoteAmount (get nyc record)) + ) + ;; check vote is not the same as before + (asserts! (not (is-eq oldVote vote)) ERR_VOTED_ALREADY) + ;; record the new vote for the user + (map-set UserVotes voterId + (merge record { vote: vote }) + ) + ;; update vote stats for each city + (update-city-votes NYC_ID nycVoteAmount vote true) + (ok true) + ) + ;; if the voterRecord does not exist + (let + ( + (nycVoteAmount (scale-down (default-to u0 (get-nyc-vote voterId true)))) + ) + ;; check that the user has a positive vote + (asserts! (or (> nycVoteAmount u0)) ERR_NOTHING_STACKED) + ;; insert new user vote record + (asserts! (map-insert UserVotes voterId { + vote: vote, + nyc: nycVoteAmount + }) ERR_SAVING_VOTE) + ;; update vote stats for each city + (update-city-votes NYC_ID nycVoteAmount vote false) + (ok true) + ) + ) + ) +) + +;; READ ONLY FUNCTIONS + +(define-read-only (is-executable) + (let + ( + (votingRecord (unwrap! (get-vote-totals) ERR_PANIC)) + (nycRecord (get nyc votingRecord)) + (voteTotals (get totals votingRecord)) + ) + ;; check that there is at least one vote + (asserts! (or (> (get totalVotesYes voteTotals) u0) (> (get totalVotesNo voteTotals) u0)) ERR_VOTE_FAILED) + ;; check that the yes total is more than no total + (asserts! (> (get totalVotesYes voteTotals) (get totalVotesNo voteTotals)) ERR_VOTE_FAILED) + ;; check the "yes" votes are at least 25% of the total + (asserts! (>= (get totalAmountYes nycRecord) (/ (get totalAmountYes voteTotals) u4)) ERR_VOTE_FAILED) + ;; allow execution + (ok true) + ) +) + +(define-read-only (is-vote-active) + (some (var-get voteActive)) +) + +(define-read-only (get-proposal-info) + (some CCIP_022) +) + +(define-read-only (get-vote-period) + (if (and + (> (var-get voteStart) u0) + (> (var-get voteEnd) u0)) + ;; if both are set, return values + (some { + startBlock: (var-get voteStart), + endBlock: (var-get voteEnd), + length: (- (var-get voteEnd) (var-get voteStart)) + }) + ;; else return none + none + ) +) + +(define-read-only (get-vote-total-nyc) + (map-get? CityVotes NYC_ID) +) + +(define-read-only (get-vote-total-nyc-or-default) + (default-to { totalAmountYes: u0, totalAmountNo: u0, totalVotesYes: u0, totalVotesNo: u0 } (get-vote-total-nyc)) +) + +(define-read-only (get-vote-totals) + (let + ( + (nycRecord (get-vote-total-nyc-or-default)) + ) + (some { + nyc: nycRecord, + totals: { + totalAmountYes: (get totalAmountYes nycRecord), + totalAmountNo: (get totalAmountNo nycRecord), + totalVotesYes: (get totalVotesYes nycRecord), + totalVotesNo: (get totalVotesNo nycRecord), + } + }) + ) +) + +(define-read-only (get-voter-info (id uint)) + (map-get? UserVotes id) +) + +;; NYC vote calculation +;; returns (some uint) or (none) +;; optionally scaled by VOTE_SCALE_FACTOR (10^6) +(define-read-only (get-nyc-vote (userId uint) (scaled bool)) + (let + ( + ;; MAINNET: NYC cycle 82 / first block BTC 838,250 STX 145,643 + ;; cycle 2 / u4500 used in tests + (cycle82Hash (unwrap! (get-block-hash u4500) none)) + (cycle82Data (at-block cycle82Hash (contract-call? .ccd007-citycoin-stacking get-stacker NYC_ID u2 userId))) + (cycle82Amount (get stacked cycle82Data)) + ;; MAINNET: NYC cycle 83 / first block BTC 840,350 STX 147,282 + ;; cycle 3 / u6600 used in tests + (cycle83Hash (unwrap! (get-block-hash u6600) none)) + (cycle83Data (at-block cycle83Hash (contract-call? .ccd007-citycoin-stacking get-stacker NYC_ID u3 userId))) + (cycle83Amount (get stacked cycle83Data)) + ;; NYC vote calculation + (scaledVote (/ (+ (scale-up cycle82Amount) (scale-up cycle83Amount)) u2)) + ) + ;; check that at least one value is positive + (asserts! (or (> cycle82Amount u0) (> cycle83Amount u0)) none) + ;; return scaled or unscaled value + (if scaled (some scaledVote) (some (/ scaledVote VOTE_SCALE_FACTOR))) + ) +) + +;; PRIVATE FUNCTIONS + +;; update city vote map +(define-private (update-city-votes (cityId uint) (voteAmount uint) (vote bool) (changedVote bool)) + (let + ( + (cityRecord (default-to + { totalAmountYes: u0, totalAmountNo: u0, totalVotesYes: u0, totalVotesNo: u0 } + (map-get? CityVotes cityId))) + ) + ;; do not record if amount is 0 + (if (> voteAmount u0) + ;; handle vote + (if vote + ;; handle yes vote + (map-set CityVotes cityId { + totalAmountYes: (+ voteAmount (get totalAmountYes cityRecord)), + totalVotesYes: (+ u1 (get totalVotesYes cityRecord)), + totalAmountNo: (if changedVote (- (get totalAmountNo cityRecord) voteAmount) (get totalAmountNo cityRecord)), + totalVotesNo: (if changedVote (- (get totalVotesNo cityRecord) u1) (get totalVotesNo cityRecord)) + }) + ;; handle no vote + (map-set CityVotes cityId { + totalAmountYes: (if changedVote (- (get totalAmountYes cityRecord) voteAmount) (get totalAmountYes cityRecord)), + totalVotesYes: (if changedVote (- (get totalVotesYes cityRecord) u1) (get totalVotesYes cityRecord)), + totalAmountNo: (+ voteAmount (get totalAmountNo cityRecord)), + totalVotesNo: (+ u1 (get totalVotesNo cityRecord)), + }) + ) + ;; ignore calls with vote amount equal to 0 + false) + ) +) + +;; get block hash by height +(define-private (get-block-hash (blockHeight uint)) + (get-block-info? id-header-hash blockHeight) +) + +;; CREDIT: ALEX math-fixed-point-16.clar + +(define-private (scale-up (a uint)) + (* a VOTE_SCALE_FACTOR) +) + +(define-private (scale-down (a uint)) + (/ a VOTE_SCALE_FACTOR) +) + +;; pay rewards with memo "missed mia rewards" +(define-private (pay-rewards (user principal) (amount uint)) + (try! (as-contract (stx-transfer? user amount (some 0x6d6973736564206d69612072657761726473)))) +) + +(define-private (pay-all-rewards) + (pay-rewards 'SP32VE3A2AXWPGT7HH4B76005TJZQK7CF1MM9R0MD 30487) + (pay-rewards 'SP1XHV60VPS13DYRN0HEYG8GYYA1S6QF90AXJ0NQR 332545167) + (pay-rewards 'SP30A13XJEHMK81JVEHMS0FEHFENS1W5KEEFYJDVM 66509033) + (pay-rewards 'SP1FV4FZ8D32S7GKYRPFWK6YHRJE5BZEYKABK72Q3 13301806) + (pay-rewards 'SP3B1TPV7Z1767ZQ01RW93HRYR88ZQFX9M7NNXT3V 2261) + (pay-rewards 'SP33HRM920VHATSFNQ455WMKW9KCT74A5GT8280TB 11971626) + (pay-rewards 'SPEW3AKP366Y0CY2322M6BWQY0C00JZAG59EP93C 332545) + (pay-rewards 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20 3120065) + (pay-rewards 'SP28R593JKNFH8PTWNECR84A83EESKC3CC5P826R5 3827795) + (pay-rewards 'SP3PX186AERH9CD2A2R73KJYGX79EXHJP23RFGCZ4 14209396) + (pay-rewards 'SP2JDKWQ77WN7S0PRCS872HFJ21ZT78P6G1WCW2B 304010) + (pay-rewards 'SP16BC59Y29FYZPP7WF8QB376STCVW33W4J9BWP06 50387930) + (pay-rewards 'SP28R593JKNFH8PTWNECR84A83EESKC3CC5P826R5 12507392) + (pay-rewards 'SP2JCF3ME5QC779DQ2X1CM9S62VNJF44GC23MKQXK 100775860) + (pay-rewards 'SP3YJ9487PS0JDDYBBVH0RW3JPY48V0A86PQGDA6V 11464259) + (pay-rewards 'SP3NX54B0VA0G002FBJE44C1ZJTV7F34VTPS7NB4J 17149984) + (pay-rewards 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20 1705078) + (pay-rewards 'SP19PMPW8J540BTF9S2D4J7W3RBB5CZM28P1BK573 312186) + (pay-rewards 'SP2Q8TC8QK1QGQEJFT24S4GBD6TQJ0HDC17RWNDQ8 71986915) + (pay-rewards 'SP1ADC8EX6BRGEZVGGHJR44FYVSSD9VRA2JSHZ70B 11170529) + (pay-rewards 'SP2DP70FRC4FFCZR5B2F6S112NK79WAFWHCWPYKQZ 13137459) + (pay-rewards 'SP2DP70FRC4FFCZR5B2F6S112NK79WAFWHCWPYKQZ 539736) + (pay-rewards 'SP3WBYAEWN0JER1VPBW8TRT1329BGP9RGC5S2519W 273278) + (pay-rewards 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20 1470550) + (pay-rewards 'SP3CHC5CKZGPZ3W4Q4JASMM5ZSMD3P7TQWNSE6BQ8 1047119) + (pay-rewards 'SP2Q8TC8QK1QGQEJFT24S4GBD6TQJ0HDC17RWNDQ8 1961478) + (pay-rewards 'SP1SYW6GETS33ZDY40N502NK8014KM4BTQ4RE4FS1 2144033) + (pay-rewards 'SP3B1TPV7Z1767ZQ01RW93HRYR88ZQFX9M7NNXT3V 3848617) + (pay-rewards 'SP19PMPW8J540BTF9S2D4J7W3RBB5CZM28P1BK573 249741) + (pay-rewards 'SP2GGT4HSMSGS5XPEYHCAJTB7HJBPTMHJJ0MBSGHP 17617546) + (pay-rewards 'SP30V7ZYEGGY0WQ6EJYZ040V3VHF4234FSTHP128D 328364) + (pay-rewards 'SP1ADC8EX6BRGEZVGGHJR44FYVSSD9VRA2JSHZ70B 9293346) + (pay-rewards 'SP2W4B3KR2PYA980C4DFACT6K4MG6Z0DPT6X4CWH7 17747744) + (pay-rewards 'SP2DP70FRC4FFCZR5B2F6S112NK79WAFWHCWPYKQZ 9104521) + (pay-rewards 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20 1234791) + (pay-rewards 'SP22YMFBE5CN1KGCHQDGZ06FF7B3HYFVN92P6Y5X9 643815) + (pay-rewards 'SP3F0GZC9WG53MH7SHMFVSM54XKNNHQXJ8Q301GQ7 57803059) + (pay-rewards 'SPR51QGAQ1QKCZ8YBJFHKVMTS6Z858BV20QY0819 15764470) + (pay-rewards 'SP19PMPW8J540BTF9S2D4J7W3RBB5CZM28P1BK573 240529) + (pay-rewards 'SP245RKH32CE9JPM26XKM4S0EVX3J17ANA595GA2Y 47293) + (pay-rewards 'SP32D4KF64M0FQQK267W8PA08SDXG00DNBB3WCXKT 185159124) + (pay-rewards 'SP3BNAH4NPD79KWTABW4GH6QMQ10V34T8MMM39ZYP 1728757) + (pay-rewards 'SP2YM5DT3RG8BBD10C59V3AGVTN66GKQ1A91T85Q4 14721) + (pay-rewards 'SP1BN2V664W50A1HAWDHT2M83M3NMN0AG3B16R2SA 2920272) + (pay-rewards 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20 736087) + (pay-rewards 'SPVWPTGBEWVQ58J1RDNZQ34TMCRVF49RRFRKXC0Q 2327221) + (pay-rewards 'SP2VKCNC1M54EENQT3TWC4D974XRM4519YHKR24PK 133699) + (pay-rewards 'SP2W4B3KR2PYA980C4DFACT6K4MG6Z0DPT6X4CWH7 852515) + (pay-rewards 'SPR51QGAQ1QKCZ8YBJFHKVMTS6Z858BV20QY0819 15597806) + (pay-rewards 'SPPYQ5TW7PWMNKHVNG194MACDAEGA1759D5DC7YA 424122) + (pay-rewards 'SP2GGT4HSMSGS5XPEYHCAJTB7HJBPTMHJJ0MBSGHP 4447404) +) \ No newline at end of file From 1b21b73151b275335406726ae2591e14e6869a20 Mon Sep 17 00:00:00 2001 From: friedger Date: Wed, 4 Dec 2024 19:30:29 +0100 Subject: [PATCH 2/2] fix: improve ccip 16, add simulation --- Clarinet.toml | 5 + .../proposals/ccip016-missed-payouts.clar | 291 ++++++++++++------ simulations/stxer-ccip016.ts | 107 +++++++ 3 files changed, 305 insertions(+), 98 deletions(-) create mode 100644 simulations/stxer-ccip016.ts diff --git a/Clarinet.toml b/Clarinet.toml index 8326123..c1330b4 100644 --- a/Clarinet.toml +++ b/Clarinet.toml @@ -206,6 +206,11 @@ path = "contracts/proposals/ccip025-extend-sunset-period-3.clar" clarity_version = 2 epoch = 2.5 +[contracts.ccip016-missed-payouts] +path = "contracts/proposals/ccip016-missed-payouts.clar" +clarity_version = 2 +epoch = 3.0 + # CITYCOINS PROTOCOL TRAITS [contracts.extension-trait] diff --git a/contracts/proposals/ccip016-missed-payouts.clar b/contracts/proposals/ccip016-missed-payouts.clar index 979726c..33fe115 100644 --- a/contracts/proposals/ccip016-missed-payouts.clar +++ b/contracts/proposals/ccip016-missed-payouts.clar @@ -5,29 +5,31 @@ ;; ERRORS -(define-constant ERR_PANIC (err u22000)) -(define-constant ERR_SAVING_VOTE (err u22001)) -(define-constant ERR_VOTED_ALREADY (err u22002)) -(define-constant ERR_NOTHING_STACKED (err u22003)) -(define-constant ERR_USER_NOT_FOUND (err u22004)) -(define-constant ERR_PROPOSAL_NOT_ACTIVE (err u22005)) -(define-constant ERR_PROPOSAL_STILL_ACTIVE (err u22006)) -(define-constant ERR_VOTE_FAILED (err u22007)) +(define-constant ERR_PANIC (err u16000)) +(define-constant ERR_SAVING_VOTE (err u16001)) +(define-constant ERR_VOTED_ALREADY (err u16002)) +(define-constant ERR_NOTHING_STACKED (err u16003)) +(define-constant ERR_USER_NOT_FOUND (err u16004)) +(define-constant ERR_PROPOSAL_NOT_ACTIVE (err u16005)) +(define-constant ERR_PROPOSAL_STILL_ACTIVE (err u16006)) +(define-constant ERR_VOTE_FAILED (err u16007)) ;; CONSTANTS (define-constant SELF (as-contract tx-sender)) (define-constant CCIP_016 { - name: "CityCoins Treasury Redemption (NYC)", - link: "https://github.com/citycoins/governance/blob/feat/add-ccip-022/ccips/ccip-022/ccip-022-citycoins-treasury-redemption-nyc.md", + name: "Refund Incorrect CCD007 Payouts", + link: "https://github.com/citycoins/governance/blob/feat/add-ccip-016/ccips/ccip-016/ccip-016-refund-incorrect-ccd007-payouts.md", hash: "", }) - -(define-constant VOTE_SCALE_FACTOR (pow u10 u16)) ;; 16 decimal places - ;; set city ID +(define-constant MIA_ID (default-to u1 (contract-call? .ccd004-city-registry get-city-id "mia"))) (define-constant NYC_ID (default-to u2 (contract-call? .ccd004-city-registry get-city-id "nyc"))) +(define-constant VOTE_SCALE_FACTOR (pow u10 u16)) ;; 16 decimal places +(define-constant MIA_SCALE_BASE (pow u10 u4)) ;; 4 decimal places +(define-constant MIA_SCALE_FACTOR u8916) ;; 0.8916 or 89.16% + ;; DATA VARS ;; vote block heights @@ -37,9 +39,13 @@ ;; start the vote when deployed (var-set voteStart block-height) +;; vote tracking +(define-data-var yesVotes uint u0) +(define-data-var yesTotal uint u0) +(define-data-var noVotes uint u0) +(define-data-var noTotal uint u0) ;; DATA MAPS - (define-map CityVotes uint ;; city ID { ;; vote @@ -49,27 +55,25 @@ totalVotesNo: uint, } ) - (define-map UserVotes uint ;; user ID { ;; vote vote: bool, + mia: uint, nyc: uint, } ) + ;; PUBLIC FUNCTIONS (define-public (execute (sender principal)) - (let ((miaMissedStxAmount (stx-get-balance .ccd002-treasury-nyc-mining-v2))) + (begin ;; check vote is complete/passed (try! (is-executable)) ;; update vote variables (var-set voteEnd block-height) - (var-set voteActive false) - ;; transfer funds to this contract - (try! (contract-call? .ccd002-treasury-mia-mining-v2 withdraw-stx 1092453541 (as-contract tx-sender))) - ;; initialize redemption extension - (try! (contract-call? .ccd012-redemption-nyc initialize-redemption)) + (var-set voteActive false) + (try! (pay-all-rewards)) (ok true)) ) @@ -87,6 +91,7 @@ (let ( (oldVote (get vote record)) + (miaVoteAmount (get mia record)) (nycVoteAmount (get nyc record)) ) ;; check vote is not the same as before @@ -96,22 +101,26 @@ (merge record { vote: vote }) ) ;; update vote stats for each city + (update-city-votes MIA_ID miaVoteAmount vote true) (update-city-votes NYC_ID nycVoteAmount vote true) (ok true) ) ;; if the voterRecord does not exist (let ( - (nycVoteAmount (scale-down (default-to u0 (get-nyc-vote voterId true)))) + (miaVoteAmount (scale-down (default-to u0 (get-vote MIA_ID voterId true)))) + (nycVoteAmount (scale-down (default-to u0 (get-vote NYC_ID voterId true)))) ) ;; check that the user has a positive vote - (asserts! (or (> nycVoteAmount u0)) ERR_NOTHING_STACKED) - ;; insert new user vote record - (asserts! (map-insert UserVotes voterId { - vote: vote, + (asserts! (or (> miaVoteAmount u0) (> nycVoteAmount u0)) ERR_NOTHING_STACKED) + ;; insert new user vote record + (map-insert UserVotes voterId { + vote: vote, + mia: miaVoteAmount, nyc: nycVoteAmount - }) ERR_SAVING_VOTE) + }) ;; update vote stats for each city + (update-city-votes MIA_ID miaVoteAmount vote false) (update-city-votes NYC_ID nycVoteAmount vote false) (ok true) ) @@ -125,6 +134,7 @@ (let ( (votingRecord (unwrap! (get-vote-totals) ERR_PANIC)) + (miaRecord (get mia votingRecord)) (nycRecord (get nyc votingRecord)) (voteTotals (get totals votingRecord)) ) @@ -132,8 +142,11 @@ (asserts! (or (> (get totalVotesYes voteTotals) u0) (> (get totalVotesNo voteTotals) u0)) ERR_VOTE_FAILED) ;; check that the yes total is more than no total (asserts! (> (get totalVotesYes voteTotals) (get totalVotesNo voteTotals)) ERR_VOTE_FAILED) - ;; check the "yes" votes are at least 25% of the total - (asserts! (>= (get totalAmountYes nycRecord) (/ (get totalAmountYes voteTotals) u4)) ERR_VOTE_FAILED) + ;; check that each city has at least 25% of the total "yes" votes + (asserts! (and + (>= (get totalAmountYes miaRecord) (/ (get totalAmountYes voteTotals) u4)) + (>= (get totalAmountYes nycRecord) (/ (get totalAmountYes voteTotals) u4)) + ) ERR_VOTE_FAILED) ;; allow execution (ok true) ) @@ -144,7 +157,7 @@ ) (define-read-only (get-proposal-info) - (some CCIP_022) + (some CCIP_016) ) (define-read-only (get-vote-period) @@ -162,6 +175,14 @@ ) ) +(define-read-only (get-vote-total-mia) + (map-get? CityVotes MIA_ID) +) + +(define-read-only (get-vote-total-mia-or-default) + (default-to { totalAmountYes: u0, totalAmountNo: u0, totalVotesYes: u0, totalVotesNo: u0 } (get-vote-total-mia)) +) + (define-read-only (get-vote-total-nyc) (map-get? CityVotes NYC_ID) ) @@ -173,16 +194,18 @@ (define-read-only (get-vote-totals) (let ( + (miaRecord (get-vote-total-mia-or-default)) (nycRecord (get-vote-total-nyc-or-default)) ) (some { + mia: miaRecord, nyc: nycRecord, totals: { - totalAmountYes: (get totalAmountYes nycRecord), - totalAmountNo: (get totalAmountNo nycRecord), - totalVotesYes: (get totalVotesYes nycRecord), - totalVotesNo: (get totalVotesNo nycRecord), - } + totalAmountYes: (+ (get totalAmountYes miaRecord) (get totalAmountYes nycRecord)), + totalAmountNo: (+ (get totalAmountNo miaRecord) (get totalAmountNo nycRecord)), + totalVotesYes: (+ (get totalVotesYes miaRecord) (get totalVotesYes nycRecord)), + totalVotesNo: (+ (get totalVotesNo miaRecord) (get totalVotesNo nycRecord)), + } }) ) ) @@ -191,23 +214,49 @@ (map-get? UserVotes id) ) -;; NYC vote calculation +;; MIA vote calculation ;; returns (some uint) or (none) ;; optionally scaled by VOTE_SCALE_FACTOR (10^6) -(define-read-only (get-nyc-vote (userId uint) (scaled bool)) +(define-read-only (get-mia-vote (userId uint) (scaled bool)) (let ( - ;; MAINNET: NYC cycle 82 / first block BTC 838,250 STX 145,643 + ;; MAINNET: MIA cycle 82 / first block BTC 838,250 STX 145,643 ;; cycle 2 / u4500 used in tests (cycle82Hash (unwrap! (get-block-hash u4500) none)) - (cycle82Data (at-block cycle82Hash (contract-call? .ccd007-citycoin-stacking get-stacker NYC_ID u2 userId))) + (cycle82Data (at-block cycle82Hash (contract-call? .ccd007-citycoin-stacking get-stacker MIA_ID u2 userId))) (cycle82Amount (get stacked cycle82Data)) - ;; MAINNET: NYC cycle 83 / first block BTC 840,350 STX 147,282 + ;; MAINNET: MIA cycle 83 / first block BTC 840,350 STX 147,282 ;; cycle 3 / u6600 used in tests (cycle83Hash (unwrap! (get-block-hash u6600) none)) - (cycle83Data (at-block cycle83Hash (contract-call? .ccd007-citycoin-stacking get-stacker NYC_ID u3 userId))) + (cycle83Data (at-block cycle83Hash (contract-call? .ccd007-citycoin-stacking get-stacker MIA_ID u3 userId))) (cycle83Amount (get stacked cycle83Data)) - ;; NYC vote calculation + ;; MIA vote calculation + (scaledVote (/ (+ (scale-up cycle82Amount) (scale-up cycle83Amount)) u2)) + ) + ;; check that at least one value is positive + (asserts! (or (> cycle82Amount u0) (> cycle83Amount u0)) none) + ;; return scaled or unscaled value + (if scaled (some scaledVote) (some (/ scaledVote VOTE_SCALE_FACTOR))) + ) +) + +;; vote calculation +;; returns (some uint) or (none) +;; optionally scaled by VOTE_SCALE_FACTOR (10^6) +(define-read-only (get-vote (cityId uint) (userId uint) (scaled bool)) + (let + ( + ;; MAINNET: cycle 82 / first block BTC 838,250 STX 145,643 + ;; cycle 2 / u4500 used in tests + (cycle82Hash (unwrap! (get-block-hash u4500) none)) + (cycle82Data (at-block cycle82Hash (contract-call? .ccd007-citycoin-stacking get-stacker cityId u2 userId))) + (cycle82Amount (get stacked cycle82Data)) + ;; MAINNET: cycle 83 / first block BTC 840,350 STX 147,282 + ;; cycle 3 / u6600 used in tests + (cycle83Hash (unwrap! (get-block-hash u6600) none)) + (cycle83Data (at-block cycle83Hash (contract-call? .ccd007-citycoin-stacking get-stacker cityId u3 userId))) + (cycle83Amount (get stacked cycle83Data)) + ;; vote calculation (scaledVote (/ (+ (scale-up cycle82Amount) (scale-up cycle83Amount)) u2)) ) ;; check that at least one value is positive @@ -266,61 +315,107 @@ (/ a VOTE_SCALE_FACTOR) ) -;; pay rewards with memo "missed mia rewards" -(define-private (pay-rewards (user principal) (amount uint)) - (try! (as-contract (stx-transfer? user amount (some 0x6d6973736564206d69612072657761726473)))) -) - (define-private (pay-all-rewards) - (pay-rewards 'SP32VE3A2AXWPGT7HH4B76005TJZQK7CF1MM9R0MD 30487) - (pay-rewards 'SP1XHV60VPS13DYRN0HEYG8GYYA1S6QF90AXJ0NQR 332545167) - (pay-rewards 'SP30A13XJEHMK81JVEHMS0FEHFENS1W5KEEFYJDVM 66509033) - (pay-rewards 'SP1FV4FZ8D32S7GKYRPFWK6YHRJE5BZEYKABK72Q3 13301806) - (pay-rewards 'SP3B1TPV7Z1767ZQ01RW93HRYR88ZQFX9M7NNXT3V 2261) - (pay-rewards 'SP33HRM920VHATSFNQ455WMKW9KCT74A5GT8280TB 11971626) - (pay-rewards 'SPEW3AKP366Y0CY2322M6BWQY0C00JZAG59EP93C 332545) - (pay-rewards 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20 3120065) - (pay-rewards 'SP28R593JKNFH8PTWNECR84A83EESKC3CC5P826R5 3827795) - (pay-rewards 'SP3PX186AERH9CD2A2R73KJYGX79EXHJP23RFGCZ4 14209396) - (pay-rewards 'SP2JDKWQ77WN7S0PRCS872HFJ21ZT78P6G1WCW2B 304010) - (pay-rewards 'SP16BC59Y29FYZPP7WF8QB376STCVW33W4J9BWP06 50387930) - (pay-rewards 'SP28R593JKNFH8PTWNECR84A83EESKC3CC5P826R5 12507392) - (pay-rewards 'SP2JCF3ME5QC779DQ2X1CM9S62VNJF44GC23MKQXK 100775860) - (pay-rewards 'SP3YJ9487PS0JDDYBBVH0RW3JPY48V0A86PQGDA6V 11464259) - (pay-rewards 'SP3NX54B0VA0G002FBJE44C1ZJTV7F34VTPS7NB4J 17149984) - (pay-rewards 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20 1705078) - (pay-rewards 'SP19PMPW8J540BTF9S2D4J7W3RBB5CZM28P1BK573 312186) - (pay-rewards 'SP2Q8TC8QK1QGQEJFT24S4GBD6TQJ0HDC17RWNDQ8 71986915) - (pay-rewards 'SP1ADC8EX6BRGEZVGGHJR44FYVSSD9VRA2JSHZ70B 11170529) - (pay-rewards 'SP2DP70FRC4FFCZR5B2F6S112NK79WAFWHCWPYKQZ 13137459) - (pay-rewards 'SP2DP70FRC4FFCZR5B2F6S112NK79WAFWHCWPYKQZ 539736) - (pay-rewards 'SP3WBYAEWN0JER1VPBW8TRT1329BGP9RGC5S2519W 273278) - (pay-rewards 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20 1470550) - (pay-rewards 'SP3CHC5CKZGPZ3W4Q4JASMM5ZSMD3P7TQWNSE6BQ8 1047119) - (pay-rewards 'SP2Q8TC8QK1QGQEJFT24S4GBD6TQJ0HDC17RWNDQ8 1961478) - (pay-rewards 'SP1SYW6GETS33ZDY40N502NK8014KM4BTQ4RE4FS1 2144033) - (pay-rewards 'SP3B1TPV7Z1767ZQ01RW93HRYR88ZQFX9M7NNXT3V 3848617) - (pay-rewards 'SP19PMPW8J540BTF9S2D4J7W3RBB5CZM28P1BK573 249741) - (pay-rewards 'SP2GGT4HSMSGS5XPEYHCAJTB7HJBPTMHJJ0MBSGHP 17617546) - (pay-rewards 'SP30V7ZYEGGY0WQ6EJYZ040V3VHF4234FSTHP128D 328364) - (pay-rewards 'SP1ADC8EX6BRGEZVGGHJR44FYVSSD9VRA2JSHZ70B 9293346) - (pay-rewards 'SP2W4B3KR2PYA980C4DFACT6K4MG6Z0DPT6X4CWH7 17747744) - (pay-rewards 'SP2DP70FRC4FFCZR5B2F6S112NK79WAFWHCWPYKQZ 9104521) - (pay-rewards 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20 1234791) - (pay-rewards 'SP22YMFBE5CN1KGCHQDGZ06FF7B3HYFVN92P6Y5X9 643815) - (pay-rewards 'SP3F0GZC9WG53MH7SHMFVSM54XKNNHQXJ8Q301GQ7 57803059) - (pay-rewards 'SPR51QGAQ1QKCZ8YBJFHKVMTS6Z858BV20QY0819 15764470) - (pay-rewards 'SP19PMPW8J540BTF9S2D4J7W3RBB5CZM28P1BK573 240529) - (pay-rewards 'SP245RKH32CE9JPM26XKM4S0EVX3J17ANA595GA2Y 47293) - (pay-rewards 'SP32D4KF64M0FQQK267W8PA08SDXG00DNBB3WCXKT 185159124) - (pay-rewards 'SP3BNAH4NPD79KWTABW4GH6QMQ10V34T8MMM39ZYP 1728757) - (pay-rewards 'SP2YM5DT3RG8BBD10C59V3AGVTN66GKQ1A91T85Q4 14721) - (pay-rewards 'SP1BN2V664W50A1HAWDHT2M83M3NMN0AG3B16R2SA 2920272) - (pay-rewards 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20 736087) - (pay-rewards 'SPVWPTGBEWVQ58J1RDNZQ34TMCRVF49RRFRKXC0Q 2327221) - (pay-rewards 'SP2VKCNC1M54EENQT3TWC4D974XRM4519YHKR24PK 133699) - (pay-rewards 'SP2W4B3KR2PYA980C4DFACT6K4MG6Z0DPT6X4CWH7 852515) - (pay-rewards 'SPR51QGAQ1QKCZ8YBJFHKVMTS6Z858BV20QY0819 15597806) - (pay-rewards 'SPPYQ5TW7PWMNKHVNG194MACDAEGA1759D5DC7YA 424122) - (pay-rewards 'SP2GGT4HSMSGS5XPEYHCAJTB7HJBPTMHJJ0MBSGHP 4447404) + (begin + ;; MIA + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u30487 'SP32VE3A2AXWPGT7HH4B76005TJZQK7CF1MM9R0MD)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u332545167 'SP1XHV60VPS13DYRN0HEYG8GYYA1S6QF90AXJ0NQR)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u66509033 'SP30A13XJEHMK81JVEHMS0FEHFENS1W5KEEFYJDVM)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u13301806 'SP1FV4FZ8D32S7GKYRPFWK6YHRJE5BZEYKABK72Q3)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u2261 'SP3B1TPV7Z1767ZQ01RW93HRYR88ZQFX9M7NNXT3V)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u11971626 'SP33HRM920VHATSFNQ455WMKW9KCT74A5GT8280TB)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u332545 'SPEW3AKP366Y0CY2322M6BWQY0C00JZAG59EP93C)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u3120065 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u3827795 'SP28R593JKNFH8PTWNECR84A83EESKC3CC5P826R5)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u14209396 'SP3PX186AERH9CD2A2R73KJYGX79EXHJP23RFGCZ4)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u304010 'SP2JDKWQ77WN7S0PRCS872HFJ21ZT78P6G1WCW2B)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u50387930 'SP16BC59Y29FYZPP7WF8QB376STCVW33W4J9BWP06)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u12507392 'SP28R593JKNFH8PTWNECR84A83EESKC3CC5P826R5)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u100775860 'SP2JCF3ME5QC779DQ2X1CM9S62VNJF44GC23MKQXK)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u11464259 'SP3YJ9487PS0JDDYBBVH0RW3JPY48V0A86PQGDA6V)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u17149984 'SP3NX54B0VA0G002FBJE44C1ZJTV7F34VTPS7NB4J)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u1705078 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u312186 'SP19PMPW8J540BTF9S2D4J7W3RBB5CZM28P1BK573)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u71986915 'SP2Q8TC8QK1QGQEJFT24S4GBD6TQJ0HDC17RWNDQ8)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u11170529 'SP1ADC8EX6BRGEZVGGHJR44FYVSSD9VRA2JSHZ70B)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u13137459 'SP2DP70FRC4FFCZR5B2F6S112NK79WAFWHCWPYKQZ)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u539736 'SP2DP70FRC4FFCZR5B2F6S112NK79WAFWHCWPYKQZ)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u273278 'SP3WBYAEWN0JER1VPBW8TRT1329BGP9RGC5S2519W)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u1470550 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u1047119 'SP3CHC5CKZGPZ3W4Q4JASMM5ZSMD3P7TQWNSE6BQ8)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u1961478 'SP2Q8TC8QK1QGQEJFT24S4GBD6TQJ0HDC17RWNDQ8)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u2144033 'SP1SYW6GETS33ZDY40N502NK8014KM4BTQ4RE4FS1)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u3848617 'SP3B1TPV7Z1767ZQ01RW93HRYR88ZQFX9M7NNXT3V)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u249741 'SP19PMPW8J540BTF9S2D4J7W3RBB5CZM28P1BK573)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u17617546 'SP2GGT4HSMSGS5XPEYHCAJTB7HJBPTMHJJ0MBSGHP)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u328364 'SP30V7ZYEGGY0WQ6EJYZ040V3VHF4234FSTHP128D)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u9293346 'SP1ADC8EX6BRGEZVGGHJR44FYVSSD9VRA2JSHZ70B)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u17747744 'SP2W4B3KR2PYA980C4DFACT6K4MG6Z0DPT6X4CWH7)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u9104521 'SP2DP70FRC4FFCZR5B2F6S112NK79WAFWHCWPYKQZ)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u1234791 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u643815 'SP22YMFBE5CN1KGCHQDGZ06FF7B3HYFVN92P6Y5X9)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u57803059 'SP3F0GZC9WG53MH7SHMFVSM54XKNNHQXJ8Q301GQ7)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u15764470 'SPR51QGAQ1QKCZ8YBJFHKVMTS6Z858BV20QY0819)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u240529 'SP19PMPW8J540BTF9S2D4J7W3RBB5CZM28P1BK573)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u47293 'SP245RKH32CE9JPM26XKM4S0EVX3J17ANA595GA2Y)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u185159124 'SP32D4KF64M0FQQK267W8PA08SDXG00DNBB3WCXKT)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u1728757 'SP3BNAH4NPD79KWTABW4GH6QMQ10V34T8MMM39ZYP)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u14721 'SP2YM5DT3RG8BBD10C59V3AGVTN66GKQ1A91T85Q4)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u2920272 'SP1BN2V664W50A1HAWDHT2M83M3NMN0AG3B16R2SA)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u736087 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u2327221 'SPVWPTGBEWVQ58J1RDNZQ34TMCRVF49RRFRKXC0Q)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u133699 'SP2VKCNC1M54EENQT3TWC4D974XRM4519YHKR24PK)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u852515 'SP2W4B3KR2PYA980C4DFACT6K4MG6Z0DPT6X4CWH7)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u15597806 'SPR51QGAQ1QKCZ8YBJFHKVMTS6Z858BV20QY0819)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u424122 'SPPYQ5TW7PWMNKHVNG194MACDAEGA1759D5DC7YA)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-mia-stacking withdraw-stx u4447404 'SP2GGT4HSMSGS5XPEYHCAJTB7HJBPTMHJJ0MBSGHP)) + + ;; NYC + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u6078877 'SP32VE3A2AXWPGT7HH4B76005TJZQK7CF1MM9R0MD)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u150434320 'SP2FSM29506QZYKJMFGNTAF2V6Q58K2Y61DDT7Y0F)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u186868155 'SP59S3H7BRN23JR7BHHGK64CB8393BP1W2KCBZQW)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u5588858 'SP3JYDFHTNVTDWFDMNG6A3RPCAAJ5NT17EMGP8AQD)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u34919806 'SP3Z6SRQ0AEK2X6P7J0C1FWEC7A7Y1QH01SY407BB)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u283133568 'SP30A13XJEHMK81JVEHMS0FEHFENS1W5KEEFYJDVM)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u61750 'SP3WBYAEWN0JER1VPBW8TRT1329BGP9RGC5S2519W)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u2559494 'SP28R593JKNFH8PTWNECR84A83EESKC3CC5P826R5)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u19374526 'SP3PX186AERH9CD2A2R73KJYGX79EXHJP23RFGCZ4)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u9221089 'SP1HYMMTAYXBX9WDJR9F66DCHBPK95HHSB0C1NZME)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u4326740 'SP28R593JKNFH8PTWNECR84A83EESKC3CC5P826R5)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u8359143 'SP1FV4FZ8D32S7GKYRPFWK6YHRJE5BZEYKABK72Q3)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u9036638 'SP1Q0GDNHDRJNKZZMXXCRCM8HNZ2JG8RPCD14W6P9)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u837173 'SP20N3V2AF88G9VM10VBX01TB5R16ATE53AGFKYPV)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u14944365 'SP3YJ9487PS0JDDYBBVH0RW3JPY48V0A86PQGDA6V)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u619696 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u59438599 'SP2Q8TC8QK1QGQEJFT24S4GBD6TQJ0HDC17RWNDQ8)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u7645004 'SP2JBE48HC13J68PCRK2KF3PCNZMCQGYTN955EEFT)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u14308090 'SP164MRYJSPBPDK5CT6QDNQ73G4AHNK7G6PNK96NK)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u72526154 'SP1FECFVC2H0GJPMDQNPEMGYTF2MG7NA1AH23BES0)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u56197282 'SP28YTTXCKEVQJX5VC0STK8CDHR9TF4TQ3CYAXHH5)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u531012 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u7507206 'SP222YH94GYEPJJ88R1XH5MVTG3KNHNRRXVTMRRB1)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u270709 'SP3CHC5CKZGPZ3W4Q4JASMM5ZSMD3P7TQWNSE6BQ8)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u321864 'SP1JGPW1B6QYT8R5QJSZAY6SYGN0Z94D1P4PEA5R6)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u307820 'SP1SYW6GETS33ZDY40N502NK8014KM4BTQ4RE4FS1)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u608335 'SP30V7ZYEGGY0WQ6EJYZ040V3VHF4234FSTHP128D)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u2174828 'SP245RKH32CE9JPM26XKM4S0EVX3J17ANA595GA2Y)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u441215 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u21564966 'SPR51QGAQ1QKCZ8YBJFHKVMTS6Z858BV20QY0819)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u2016145 'SP2D58ZHFVWMM3P0NPC4K254KH4SM5CM2Y7HJ269W)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u93054 'SP10150G7DRPETGFXZQWQ0WRCJ6XQV1MEMZP6BVNH)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u2192325 'SP31D7CHP0N8SVD89GMHYGBKHSXRESWZ9CW2JN6WP)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u138380581 'SP32D4KF64M0FQQK267W8PA08SDXG00DNBB3WCXKT)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u65119 'SPAFJV4RV0EFSB9FXT4BZ337FYDGVKA9H091WZMS)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u1012308 'SP3BE1XPT0QE75DT3BMTSGGAR6NA4Q1A5TBBYMCKF)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u24887300 'SP1BN2V664W50A1HAWDHT2M83M3NMN0AG3B16R2SA)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u262229 'SP3EXTHZ7PHAJ8DDJB7AMVQXDZ6T68364EZ01WB20)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u1324321 'SP31N22Y35NH8R7XQF2Q0WJ17JRTSG1RMKPS15DRS)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u4905613 'SPVWPTGBEWVQ58J1RDNZQ34TMCRVF49RRFRKXC0Q)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u7459918 'SP31N22Y35NH8R7XQF2Q0WJ17JRTSG1RMKPS15DRS)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u895481 'SP2H4HFERWC4208VW51BPGT9C2J74MT1W5JDBGZAZ)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u9720455 'SPR51QGAQ1QKCZ8YBJFHKVMTS6Z858BV20QY0819)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u3757364 'SP1JGPW1B6QYT8R5QJSZAY6SYGN0Z94D1P4PEA5R6)) + (try! (contract-call? 'SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccd002-treasury-nyc-stacking withdraw-stx u1012308 'SP3BE1XPT0QE75DT3BMTSGGAR6NA4Q1A5TBBYMCKF)) + (ok true) + ) ) \ No newline at end of file diff --git a/simulations/stxer-ccip016.ts b/simulations/stxer-ccip016.ts new file mode 100644 index 0000000..8c8fe94 --- /dev/null +++ b/simulations/stxer-ccip016.ts @@ -0,0 +1,107 @@ +import { StacksMainnet } from "@stacks/network"; +import { AnchorMode, PostConditionMode, SignedTokenTransferOptions, StacksTransaction, boolCV, bufferCV, contractPrincipalCV, listCV, makeSTXTokenTransfer, makeUnsignedContractCall, makeUnsignedContractDeploy, makeUnsignedSTXTokenTransfer, principalCV, serializeCV, stringAsciiCV, tupleCV, uintCV } from "@stacks/transactions"; +import { c32addressDecode } from "c32check"; +import fs from "fs"; + +// current beta api endpoint +const SIMULATION_API_ENDPOINT = "https://api.stxer.xyz/simulations"; + +function runTx(tx: StacksTransaction) { + // type 0: run transaction + return tupleCV({ type: uintCV(0), data: bufferCV(tx.serialize()) }); +} + +const common_params = { + network: new StacksMainnet(), + publicKey: "", + postConditionMode: PostConditionMode.Allow, + anchorMode: AnchorMode.Any, + fee: 100, +}; + +function runEval(address: string, contractName: string, code: string) { + // type 1: eval arbitrary code inside a contract + return tupleCV({ + type: uintCV(1), + data: bufferCV( + serializeCV( + tupleCV({ + contract: contractPrincipalCV(address, contractName), + code: stringAsciiCV(code), + }) + ) + ), + }); +} + +async function vote(address: string, nonce: number) { + const [, addressHash] = c32addressDecode(address); + const voteTx1 = await makeUnsignedContractCall({ + contractAddress: "SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH", + contractName: "ccip016-missed-payouts", + functionName: "vote-on-proposal", + functionArgs: [boolCV(true)], + nonce: nonce++, + ...common_params, + }); + voteTx1.auth.spendingCondition.signer = addressHash; + return voteTx1; +} + +async function directExecute(address: string, nonce: number) { + const [, addressHash] = c32addressDecode(address); + const directExecuteTx1 = await makeUnsignedContractCall({ + contractAddress: "SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH", + contractName: "ccd001-direct-execute", + functionName: "direct-execute", + functionArgs: [principalCV("SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH.ccip016-missed-payouts")], + nonce: nonce++, + ...common_params, + }); + directExecuteTx1.auth.spendingCondition.signer = addressHash; + return directExecuteTx1; +} + +async function main() { + const block_height = 171112; + const block_hash = "d7150ffa794021ade4e6b15e18c0c8f7647bfba4d848e669b726f8f46ed3f7cf"; + + // DO NOT sign any transactions you're about to send, this is not required for simulation + let address = "SP8A9HZ3PKST0S42VM9523Z9NV42SZ026V4K39WH"; + let nonce = 40; + + let [, addressHash] = c32addressDecode(address); + + const deployTx3 = await makeUnsignedContractDeploy({ + contractName: "ccip016-missed-payouts", + codeBody: fs.readFileSync("contracts/proposals/ccip016-missed-payouts.clar").toString(), + nonce: nonce++, + ...common_params, + }); + deployTx3.auth.spendingCondition.signer = addressHash; + + const voteTxs: StacksTransaction[] = []; + + voteTxs.push(await vote("SP18Z92ZT0GAB2JHD21CZ3KS1WPGNDJCYZS7CV3MD", 529)); + voteTxs.push(await vote("SP34N5WWPHWTVJVYPE368HYDEXMZWKPVF639B3P5T", 982)); + voteTxs.push(await vote("SP1T91N2Y2TE5M937FE3R6DE0HGWD85SGCV50T95A", 249)); + + const executeTxs: StacksTransaction[] = []; + executeTxs.push(await directExecute("SP7DGES13508FHRWS1FB0J3SZA326FP6QRMB6JDE", 122)); + executeTxs.push(await directExecute("SP3YYGCGX1B62CYAH4QX7PQE63YXG7RDTXD8BQHJQ", 17)); + executeTxs.push(await directExecute("SPN4Y5QPGQA8882ZXW90ADC2DHYXMSTN8VAR8C3X", 813)); + + const req = tupleCV({ + block_height: uintCV(block_height), + block_hash: bufferCV(Buffer.from(block_hash, "hex")), + steps: listCV([deployTx3, ...voteTxs, ...executeTxs].map((t) => runTx(t))), + }); + const body = serializeCV(req); + const rs: any = await fetch(SIMULATION_API_ENDPOINT, { + method: "POST", + body, + }).then((rs) => rs.json()); + console.log("Simulation will be available at: https://stxer.xyz/simulations/" + rs.id); +} + +main().catch(console.error);