Repository: Official-MoonDao/MoonDAO
Pull request #430: Retro updates part 2
Author: login: jaderiverstokes
Created: 2025-04-29T19:21:35Z | Merged: 2025-04-30T16:39:26Z

- adds staked eth to total balance
- pass in multisig signers and team members into project table


Diff:
diff --git a/dispatcher/Pipelines/Integration/POST/Tableland/load_project.ts b/dispatcher/Pipelines/Integration/POST/Tableland/load_project.ts
index e8ee977c8..a7931c3ed 100644
--- a/dispatcher/Pipelines/Integration/POST/Tableland/load_project.ts
+++ b/dispatcher/Pipelines/Integration/POST/Tableland/load_project.ts
@@ -29,6 +29,91 @@ const client = createThirdwebClient({
     clientId: process.env.NEXT_PUBLIC_THIRDWEB_CLIENT_ID as string,
 });
 
+const discordToEthAddress = {
+  "AriBruce#2325": "0x2c485a4DaD1c1a6a031A6DB08D5212b74A4A50e7",
+  "anastasiaadastra": "0x529bd2351476ba114f9d60e71a020a9f0b99f047",
+  "_anna5501": "0x6Af6DCac097EF957F0155d7Ce26CC65996226423",
+  "cryptoariel": "0x407F28ECd4e3EBC4288F5824e8De4fc0aF5463ED",
+  "ashsack": "0x3E08F6e00e78019AA571d144e1cC9b30E80F6646",
+  "astroeliza": "0x08E424b69851b7b210bA3E5E4233Ca6fcc1ADEdb",
+  "ballack6780": "0x6Ae385654CA814C5cAb3fF6a6deb420b681fE7A0",
+  "Barney(🌜,🌛)#4593": "0x87D7276B0068ffcBA8C02781AA16484e935Bde28",
+  "benlifeship": "0x87678f9229910d5462Ee26Df6f7b4cf41888638C",
+  "carla0st": "0x573B64aB6896048EE3629C675a4BcF43f15CAe67",
+  "xtina_korp": "0x3ea48DFA0F7a57D08e3Dd093C78D1e300616B57d",
+  ".coffeecrusher": "0x223da87421786DD8960bf2350e6c499BEbCA64d1",
+  "name.get": "0x80581C6e88Ce00095F85cdf24bB760f16d6eC0D6",
+  "N/A - Coordinape": "0x15B513F658f7390D8720dCE321f50974B28672EF",
+  "damian2848": "0x4b2F36E078A7eFeBe7A0680EDC340A4A60ca8946",
+  "___mustang___": "0x1B7D7d183Bd233af690DDB33cE818f41995118a9",
+  "dreimanj": "0xe2d3aC725E6FFE2b28a9ED83bedAaf6672f2C801",
+  "flowscience": "0x66CD14267fb5a1609496CdC37eB55E6FE3f59C75",
+  "social_hacker_38241": "0x04877685e94E0694944D08a43d021E5768b595f0",
+  "engi_bob": "0x4CBf10c36b481d6afF063070E35b4F42E7Aad201",
+  "favian23": "0xafa46468De1D6f1ab77DEFAe5F7657467911182d",
+  "_furda": "0x01A5109eC48a25C7c26C517b595FD7a5c2cE44eb",
+  "fiyinx20": "0x2753c791bCA3667f10800262FCB0168269e12DC5",
+  "fraiz._.": "0xa1D84CD4Ab2e106B8114842b6B902E9462A73BAd",
+  "consigli3re": "0xeEA7d0FFc09997B8b0cC59C9BBC93cdEd33c14e4",
+  "gregsearch": "0x11646C2BbB14e5db25aB4b4BDAc38Fe35819F844",
+  "jaderiverstokes_": "0x08B3e694caA2F1fcF8eF71095CED1326f3454B89",
+  "jaderiverstokes": "0x08B3e694caA2F1fcF8eF71095CED1326f3454B89",
+  "jango420": "",
+  "jason_n_state_fan": "0x9345a54906191505c6Efd5FDd6A3F02D994C44Aa",
+  "jigglyjams": "0x25910143C255828F623786f46fe9A8941B7983bB",
+  "justinpark01": "0x9A1741b58Bd99EBbc4e9742Bd081b887DfC95f53",
+  "bestape": "0x0D89421D6eec0A4385F95f410732186A2Ab45077",
+  "larrotiz": "0x5640Ddc028f2436B5C0BA0305D2199556C1b5a95",
+  "0xlucasart": "0xD5629b8bF9D81720b9A87E01BFbB5D3fc507fe4F",
+  ".luffy54": "0xe6f4DC7260e77AA6Dc2F36596F3d19493eB20B93",
+  "luisperdomo.eth": "0x157Bd0591c9E80B5640dEC001E9d73720fa19960",
+  "maccon_": "0x1EEc6A3e8f7a369fA4866C2c9B2d38d485511e86",
+  "manuelolariu": "0xD4416b13d2b3a9aBae7AcD5D6C2BbDBE25686401",
+  "ming6348": "0x7FD14Ce34975C4fcF8CffFc9E8eCc4ae5F5e21e3",
+  "mitchie_mitch": "0xb1d4c1B9c8DA3191Fdb515Fa7AdeC3D41D014F4f",
+  "HaonChon": "0x850a146D7478dAAa98Fc26Fd85e6A24e50846A9d",
+  "pmoncada": "0x679d87D8640e66778c3419D164998E720D7495f6",
+  "philiplinden": "0x6bFd9e435cF6194c967094959626ddFF4473a836",
+  "pipilu": "0x4c55c41bd839b3552fb2abecacfdf4a5d2879cb9",
+  ".rocketryder": "0xAfcB3224774297Cb67d20aF99eB2ccf80E9F51Ca",
+  "ionrod": "0xA64f2228cceC96076c82abb903021C33859082F8",
+  "royalty3684": "0x1D6CAaCB0528fd7EfFfE9029604DD2049a40B3cE",
+  "ryand2d": "0xB2d3900807094D4Fe47405871B0C8AdB58E10D42",
+  "ryan": "0xB2d3900807094D4Fe47405871B0C8AdB58E10D42",
+  "santiagoitzcoatl": "0xad43D363701Ed3EFC1263DC4b658745fA3E90e4B",
+  "astrosupreme": "",
+  "sheldenshi": "0xc2BCF46CBC9F4CedA617cB41F2158BE525dD008b",
+  "super.jellie#9120": "0x8C1Bf43198c5E7cAB13439e0C53A8650033d03ef",
+  "cowtools4549": "0x2Ca5F90962c415DA3E3E1761f7Ca159d2E081c46",
+  "sfladepo#2644": "0xEeBAEBaC995989A5Eda2e6149E7B9CD451459ee1",
+  "southside98": "0x3d802730A2F2e24b23d53cd7c5D9a06646e1ff10",
+  "i24titan": "0x86c779b3741e83A36A2a236780d436E4EC673Af4",
+  "twodam": "0xca6ed3fdc8162304d7f1fcfc9ca3a81632d5e5b0",
+  "tyler.shm": "0x680f8C4b76AD9FBE3a25FF40aaceC9Aaf357B885",
+  "yankejun": "0x3e917eAdd649784aaFBEB5Cf4C9132fce42f9f90",
+  ".zeroindex": "0x87D7276B0068ffcBA8C02781AA16484e935Bde27"
+}
+
+function getAddresses(proposalBody: string, patterns: string[]){
+    const matchedLine = proposalBody
+        .split("\n")
+        .reverse()
+        .find((line) => patterns.map(pattern => line.includes(pattern)).some(Boolean));
+    const rawMatches = matchedLine.match(/@[a-zA-Z0-9_.]+/g) || [];
+    const usernames = rawMatches.map(u => u.slice(1));
+    const addresses = usernames.map(username => {
+        const address = discordToEthAddress[username];
+        if (address) {
+            return address;
+        } else {
+            throw new Error(`No address found for username: ${username}`);
+            return null;
+        }
+    });
+    return [usernames, addresses.filter(address => address !== null)];
+}
+
+
 interface PinResponse {
     cid: string;
 }
@@ -94,7 +179,7 @@ async function loadProjectData() {
         console.log(`Found ${tablelandMDPs.length} existing MPDs in Tableland`);
 
         // Get proposals from Nance
-        const proposals = await getProposals("moondao", 40);
+        const proposals = await getProposals("moondao", 47);
 
         if (!proposals) {
             throw new Error("Failed to fetch proposals from Nance");
@@ -115,29 +200,28 @@ async function loadProjectData() {
                 );
                 continue;
             }
-            var signers;
-            var members = []
-            if (proposal?.actions?.[0]?.payload?.multisigTeam && proposal.actions[0].payload.projectTeam) {
-                signers = proposal.actions[0].payload.multisigTeam.map((member) => member.address);
+            var members = [];
+            var membersUsernames = [];
+            if (proposal?.actions?.[0]?.payload?.projectTeam) {
                 members = proposal.actions[0].payload.projectTeam.map((member) => member.votingAddress);
             }else{
-                const multisigLine = proposal.body
-                    .split("\n")
-                    .find((line) => line.includes("Multisig") || line.includes("Multi-sig") || line.includes("multisig"));
-                const addresses = multisigLine.match(/0x[a-fA-F0-9]{40}/g) || [];
-                const ensNames = multisigLine.match(/([a-zA-Z0-9-]+\.eth)/g) || [];
-                const ensAddresses = await Promise.all(
-                    ensNames.map(async (name) => {
-                        const address = await resolveAddress({
-                            client,
-                            name: name,
-                        });
-                        return address;
-                    })
-                );
-                signers = addresses.concat(ensAddresses);
+                const [leads, leadsUsernames] = getAddresses(proposal.body, ["Project Lead", "Team Rocketeer"]);
+                [members, membersUsernames] = getAddresses(proposal.body, ["Initial Team"]);
+                // Only allow the first lead to be the lead for smart contract purposes
+                if (leads.length > 1) {
+                    members = [...leads.slice(1), ...members];
+                    membersUsernames = [...leadsUsernames.slice(1), ...membersUsernames];
+                }
+            }
+            var signers = [];
+            var signersUsernames = [];
+            if (proposal?.actions?.[0]?.payload?.multisigTeam){
+                signers = proposal.actions[0].payload.multisigTeam.map((member) => member.address);
+            }else{
+                [signers, signersUsernames] = getAddresses(proposal.body, ["Multi-sig Signers"]);
             }
 
+
             if (existingMDPs.has(proposal.proposalId)) {
                 console.log(
                     "Skipping existing proposal MDP:",
@@ -204,7 +288,7 @@ async function loadProjectData() {
             }
             // allow keyboard input to confirm the proposal, otherwise skip
             const conf = prompt(
-                `Create project for proposal ${proposal.proposalId} ${proposal.title}? (y/n)`
+                `Create project for proposal ${proposal.proposalId} ${proposal.title}?\nlead ${proposal.authorAddress}\n\nmembers [${members}]\n (${membersUsernames})\n\nsigners [${signers}]\n (${signersUsernames})\n (y/n)`
             );
             if (conf !== "y") {
                 console.log("Skipping proposal MDP:", proposal.proposalId, " ", proposal.title);
diff --git a/ui/components/nance/RetroactiveRewards.tsx b/ui/components/nance/RetroactiveRewards.tsx
index d2b92d6c3..3b6e61a3e 100644
--- a/ui/components/nance/RetroactiveRewards.tsx
+++ b/ui/components/nance/RetroactiveRewards.tsx
@@ -10,6 +10,7 @@ import {
   POLYGON_ASSETS_URL,
   BASE_ASSETS_URL,
 } from 'const/config'
+import useStakedEth from 'lib/utils/hooks/useStakedEth'
 import _ from 'lodash'
 import Image from 'next/image'
 import { useRouter } from 'next/router'
@@ -232,11 +233,13 @@ export function RetroactiveRewards({
   const { tokens: arbitrumTokens } = useAssets(ARBITRUM_ASSETS_URL)
   const { tokens: polygonTokens } = useAssets(POLYGON_ASSETS_URL)
   const { tokens: baseTokens } = useAssets(BASE_ASSETS_URL)
+  const { stakedEth, error } = useStakedEth()
 
   const tokens = mainnetTokens
     .concat(arbitrumTokens)
     .concat(polygonTokens)
     .concat(baseTokens)
+    .concat([{ symbol: 'stETH', balance: stakedEth }])
 
   const { ethBudget, usdBudget, mooneyBudget, ethPrice } = getBudget(
     tokens,
diff --git a/ui/const/abis/StakingContract.json b/ui/const/abis/StakingContract.json
new file mode 100644
index 000000000..96b682bd3
--- /dev/null
+++ b/ui/const/abis/StakingContract.json
@@ -0,0 +1 @@
+[{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"Deactivated","type":"error"},{"inputs":[],"name":"DepositFailure","type":"error"},{"inputs":[],"name":"DepositsStopped","type":"error"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"DuplicateValidatorKey","type":"error"},{"inputs":[],"name":"Forbidden","type":"error"},{"inputs":[],"name":"FundedValidatorDeletionAttempt","type":"error"},{"inputs":[],"name":"InvalidArgument","type":"error"},{"inputs":[],"name":"InvalidCall","type":"error"},{"inputs":[],"name":"InvalidDepositValue","type":"error"},{"inputs":[],"name":"InvalidFee","type":"error"},{"inputs":[],"name":"InvalidPublicKeys","type":"error"},{"inputs":[],"name":"InvalidSignatures","type":"error"},{"inputs":[],"name":"InvalidValidatorCount","type":"error"},{"inputs":[],"name":"InvalidWithdrawer","type":"error"},{"inputs":[],"name":"InvalidZeroAddress","type":"error"},{"inputs":[],"name":"LastEditAfterSnapshot","type":"error"},{"inputs":[],"name":"MaximumOperatorCountAlreadyReached","type":"error"},{"inputs":[],"name":"NoOperators","type":"error"},{"inputs":[],"name":"NotEnoughValidators","type":"error"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"keyCount","type":"uint256"}],"name":"OperatorLimitTooHigh","type":"error"},{"inputs":[],"name":"PublicKeyNotInContract","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnsortedIndexes","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_operatorIndex","type":"uint256"}],"name":"ActivatedOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"ChangedAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isStopped","type":"bool"}],"name":"ChangedDepositsStopped","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newGlobalFee","type":"uint256"}],"name":"ChangedGlobalFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"operatorIndex","type":"uint256"},{"indexed":false,"internalType":"address","name":"operatorAddress","type":"address"},{"indexed":false,"internalType":"address","name":"feeRecipientAddress","type":"address"}],"name":"ChangedOperatorAddresses","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newOperatorFee","type":"uint256"}],"name":"ChangedOperatorFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"operatorIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"limit","type":"uint256"}],"name":"ChangedOperatorLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newTreasury","type":"address"}],"name":"ChangedTreasury","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"publicKey","type":"bytes"},{"indexed":false,"internalType":"address","name":"newWithdrawer","type":"address"}],"name":"ChangedWithdrawer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_operatorIndex","type":"uint256"}],"name":"DeactivatedOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"withdrawer","type":"address"},{"indexed":false,"internalType":"bytes","name":"publicKey","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"signature","type":"bytes"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bytes","name":"pubkey","type":"bytes"}],"name":"ExitRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operatorAddress","type":"address"},{"indexed":false,"internalType":"address","name":"feeRecipientAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"NewOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"_status","type":"bool"}],"name":"SetWithdrawerCustomizationStatus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"operatorIndex","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"publicKey","type":"bytes"}],"name":"ValidatorKeyRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"operatorIndex","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"publicKeys","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"signatures","type":"bytes"}],"name":"ValidatorKeysAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"ValidatorsEdited","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"DEPOSIT_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PUBLIC_KEY_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SIGNATURE_LENGTH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_operatorIndex","type":"uint256"},{"internalType":"address","name":"_newFeeRecipient","type":"address"}],"name":"activateOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_operatorAddress","type":"address"},{"internalType":"address","name":"_feeRecipientAddress","type":"address"}],"name":"addOperator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_operatorIndex","type":"uint256"},{"internalType":"uint256","name":"_keyCount","type":"uint256"},{"internalType":"bytes","name":"_publicKeys","type":"bytes"},{"internalType":"bytes","name":"_signatures","type":"bytes"}],"name":"addValidators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_publicKeys","type":"bytes"}],"name":"batchWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_publicKeys","type":"bytes"}],"name":"batchWithdrawCLFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_publicKeys","type":"bytes"}],"name":"batchWithdrawELFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_operatorIndex","type":"uint256"},{"internalType":"address","name":"_temporaryFeeRecipient","type":"address"}],"name":"deactivateOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAvailableValidatorCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_publicKey","type":"bytes"}],"name":"getCLFeeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDepositsStopped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_publicKey","type":"bytes"}],"name":"getELFeeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_publicKeyRoot","type":"bytes32"}],"name":"getEnabledFromPublicKeyRoot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_publicKeyRoot","type":"bytes32"}],"name":"getExitRequestedFromRoot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGlobalFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_operatorIndex","type":"uint256"}],"name":"getOperator","outputs":[{"internalType":"address","name":"operatorAddress","type":"address"},{"internalType":"address","name":"feeRecipientAddress","type":"address"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"uint256","name":"keys","type":"uint256"},{"internalType":"uint256","name":"funded","type":"uint256"},{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"bool","name":"deactivated","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOperatorFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"pubKeyRoot","type":"bytes32"}],"name":"getOperatorFeeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTreasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_operatorIndex","type":"uint256"},{"internalType":"uint256","name":"_validatorIndex","type":"uint256"}],"name":"getValidator","outputs":[{"internalType":"bytes","name":"publicKey","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"withdrawer","type":"address"},{"internalType":"bool","name":"funded","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_publicKey","type":"bytes"}],"name":"getWithdrawer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_publicKeyRoot","type":"bytes32"}],"name":"getWithdrawerFromPublicKeyRoot","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_publicKeyRoot","type":"bytes32"}],"name":"getWithdrawnFromPublicKeyRoot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"address","name":"_depositContract","type":"address"},{"internalType":"address","name":"_elDispatcher","type":"address"},{"internalType":"address","name":"_clDispatcher","type":"address"},{"internalType":"address","name":"_feeRecipientImplementation","type":"address"},{"internalType":"uint256","name":"_globalFee","type":"uint256"},{"internalType":"uint256","name":"_operatorFee","type":"uint256"},{"internalType":"uint256","name":"globalCommissionLimitBPS","type":"uint256"},{"internalType":"uint256","name":"operatorCommissionLimitBPS","type":"uint256"}],"name":"initialize_1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"globalCommissionLimitBPS","type":"uint256"},{"internalType":"uint256","name":"operatorCommissionLimitBPS","type":"uint256"}],"name":"initialize_2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_operatorIndex","type":"uint256"},{"internalType":"uint256[]","name":"_indexes","type":"uint256[]"}],"name":"removeValidators","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_publicKeys","type":"bytes"}],"name":"requestValidatorsExit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"val","type":"bool"}],"name":"setDepositsStopped","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_globalFee","type":"uint256"}],"name":"setGlobalFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_operatorIndex","type":"uint256"},{"internalType":"address","name":"_operatorAddress","type":"address"},{"internalType":"address","name":"_feeRecipientAddress","type":"address"}],"name":"setOperatorAddresses","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_operatorFee","type":"uint256"}],"name":"setOperatorFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_operatorIndex","type":"uint256"},{"internalType":"uint256","name":"_limit","type":"uint256"},{"internalType":"uint256","name":"_snapshot","type":"uint256"}],"name":"setOperatorLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newTreasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_publicKey","type":"bytes"},{"internalType":"address","name":"_newWithdrawer","type":"address"}],"name":"setWithdrawer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setWithdrawerCustomizationEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_publicKeyRoot","type":"bytes32"}],"name":"toggleWithdrawnFromPublicKeyRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newAdmin","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_publicKey","type":"bytes"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_publicKey","type":"bytes"}],"name":"withdrawCLFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_publicKey","type":"bytes"}],"name":"withdrawELFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
diff --git a/ui/const/config.ts b/ui/const/config.ts
index 03f46092b..05bd82b96 100644
--- a/ui/const/config.ts
+++ b/ui/const/config.ts
@@ -290,6 +290,7 @@ export const ORACLE_ADDRESS = '0x08B3e694caA2F1fcF8eF71095CED1326f3454B89'
 
 export const OPERATOR_ADDRESS = '0x08B3e694caA2F1fcF8eF71095CED1326f3454B89'
 
+export const MOONDAO_TREASURY: string = '0xce4a1E86a5c47CD677338f53DA22A91d85cab2c9'
 export const MOONDAO_L2_TREASURY: string =
   '0x8C0252c3232A2c7379DDC2E44214697ae8fF097a'
 export const DEAD_ADDRESS: string =
@@ -366,3 +367,4 @@ export const POLYGON_ASSETS_URL =
   'https://safe-client.safe.global/v1/chains/137/safes/0x8C0252c3232A2c7379DDC2E44214697ae8fF097a/balances/usd?trusted=true'
 export const BASE_ASSETS_URL =
   'https://safe-client.safe.global/v1/chains/8453/safes/0x871e232Eb935E54Eb90B812cf6fe0934D45e7354/balances/usd?trusted=true'
+export const STAKED_ETH_ADDRESS = "0xbbb56e071f33e020daEB0A1dD2249B8Bbdb69fB8";
diff --git a/ui/lib/utils/hooks/useStakedEth.ts b/ui/lib/utils/hooks/useStakedEth.ts
new file mode 100644
index 000000000..b834786a0
--- /dev/null
+++ b/ui/lib/utils/hooks/useStakedEth.ts
@@ -0,0 +1,70 @@
+import { useState, useEffect } from 'react'
+import { Contract, utils } from "ethers";
+import { keccak256 } from 'ethers/lib/utils'
+import { ethereum } from 'thirdweb/chains'
+import useContract from '@/lib/thirdweb/hooks/useContract'
+import {STAKED_ETH_ADDRESS, MOONDAO_TREASURY} from "const/config";
+import StakedEthABI from "const/abis/StakingContract.json";
+import { readContract } from 'thirdweb'
+import { ethers5Adapter } from 'thirdweb/adapters/ethers5'
+import client from 'lib/thirdweb/client'
+
+export default function useStakedEth() {
+  const [stakedEth, setStakedEth] = useState<any>()
+  const [isLoading, setIsLoading] = useState<boolean>(false)
+  const [error, setError] = useState<any>(null)
+  const contract = useContract({
+    address: STAKED_ETH_ADDRESS,
+    abi: StakedEthABI as any,
+    chain: ethereum,
+  })
+  const provider = ethers5Adapter.provider.toEthers({
+    client,
+    chain: ethereum,
+  })
+  const ethersContract = new Contract(
+    STAKED_ETH_ADDRESS,
+    StakedEthABI,  // include at least the Deposit event ABI
+    provider
+  );
+
+  useEffect(() => {
+      async function fetchStakedEth() {
+        setIsLoading(true)
+        try {
+            const filter = ethersContract.filters.Deposit(null, MOONDAO_TREASURY);
+
+            // Inital stake transaction
+            //https://app.safe.global/transactions/tx?safe=eth:0xce4a1E86a5c47CD677338f53DA22A91d85cab2c9&id=multisig_0xce4a1E86a5c47CD677338f53DA22A91d85cab2c9_0xc00049254699f2e997d1732c8da36024697bef66ff02cab0da39f629a105fac1
+            const initialStakeBlockNumber = 21839730
+
+            // 0. Grab deposit events from the contract
+            const events = await ethersContract.queryFilter(filter, initialStakeBlockNumber, initialStakeBlockNumber);
+            const pubKeys = events.map(e => e?.args?.publicKey);
+
+            // 1. Check if any deposits have been withdrawn
+            const roots = pubKeys.map(pk => keccak256(pk));
+            const withdrawnFrom = await Promise.all(
+                roots.map(root => readContract({
+                    contract: contract,
+                    method: 'getWithdrawnFromPublicKeyRoot' as string,
+                    params: [root],
+                    }))
+            );
+            const stillStakedCount = roots.filter((_, i) => !withdrawnFrom[i]).length;
+
+            // 2. each deposit = 32 ETH
+            const totalStaked = stillStakedCount * 32;
+            setStakedEth(totalStaked)
+        } catch (error) {
+            console.log('Error fetching staked ETH:', error)
+            setError(error)
+        } finally {
+            setIsLoading(false)
+        }
+
+    }
+    fetchStakedEth()
+  }, [contract]);
+  return { stakedEth, isLoading, error }
+}
diff --git a/ui/lib/utils/rewards.ts b/ui/lib/utils/rewards.ts
index dae435055..f6e848ecd 100644
--- a/ui/lib/utils/rewards.ts
+++ b/ui/lib/utils/rewards.ts
@@ -301,17 +301,19 @@ export function getBudget(tokens: any, year: number, quarter: number) {
     (token: any) => token.symbol === 'ETH' && token.balance > 0
   )
   if (tokens && ethToken) {
+    ethPrice = ethToken.usd / ethToken.balance
     for (const token of tokens) {
       if (token.symbol !== 'MOONEY') {
-        usdValue += token.usd
+        if (token.symbol == "stETH"){
+          usdValue += token.balance * ethPrice
+        } else {
+          usdValue += token.usd
+        }
       }
     }
-    ethPrice = ethToken.usd / ethToken.balance
     const ethValue = usdValue / ethPrice
     usdBudget = usdValue * 0.05
     ethBudget = ethValue * 0.05
-    //FIXME undo hardcoded values
-    ethBudget = 309.9667 * 0.05
     usdBudget = ethBudget * ethPrice
     const MOONEY_INITIAL_BUDGET = 15_000_000
     const MOONEY_DECAY_RATE = 0.95


Reviews:
user: login: pmoncada
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T23:29:54Z

Review comments:
diff_hunk: @@ -29,6 +29,91 @@ const client = createThirdwebClient({
     clientId: process.env.NEXT_PUBLIC_THIRDWEB_CLIENT_ID as string,
 });
 
+const discordToEthAddress = {
path: dispatcher/Pipelines/Integration/POST/Tableland/load_project.ts
user: login: pmoncada
body: this could be tough to maintain over time w/ new addresses. Wish there were a way to get this data from the bot we use to unlock access in the discord
created_at: 2025-04-29T23:27:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,70 @@
+import { useState, useEffect } from 'react'
+import { Contract, utils } from "ethers";
+import { keccak256 } from 'ethers/lib/utils'
+import { ethereum } from 'thirdweb/chains'
+import useContract from '@/lib/thirdweb/hooks/useContract'
+import {STAKED_ETH_ADDRESS, MOONDAO_TREASURY} from "const/config";
+import StakedEthABI from "const/abis/StakingContract.json";
+import { readContract } from 'thirdweb'
+import { ethers5Adapter } from 'thirdweb/adapters/ethers5'
+import client from 'lib/thirdweb/client'
+
+export default function useStakedEth() {
+  const [stakedEth, setStakedEth] = useState<any>()
+  const [isLoading, setIsLoading] = useState<boolean>(false)
+  const [error, setError] = useState<any>(null)
+  const contract = useContract({
+    address: STAKED_ETH_ADDRESS,
+    abi: StakedEthABI as any,
+    chain: ethereum,
+  })
+  const provider = ethers5Adapter.provider.toEthers({
+    client,
+    chain: ethereum,
+  })
+  const ethersContract = new Contract(
+    STAKED_ETH_ADDRESS,
+    StakedEthABI,  // include at least the Deposit event ABI
+    provider
+  );
+
+  useEffect(() => {
+      async function fetchStakedEth() {
path: ui/lib/utils/hooks/useStakedEth.ts
user: login: pmoncada
body: It's too bad that gnosis doesn't just natively recognize the staked ETH. Especially since what we're using is their native staking service - nice work though
created_at: 2025-04-29T23:29:23Z
author_association: CONTRIBUTOR

PR comments:
user: login: netlify[bot]
created_at: 2025-04-29T19:21:53Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *moondao-stc* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | ec008cc3d5256666baf83fc86d84b7f93a41334c |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/moondao-stc/deploys/68115ceff1ebbc0008aba273 |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-430--moondao-stc.netlify.app](https://deploy-preview-430--moondao-stc.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTQzMC0tbW9vbmRhby1zdGMubmV0bGlmeS5hcHAifQ.iO7oqQi-7WA0eeJSvUvR88OM799eEm1wn0YErlEhdl4)<br /><br />_Use your smartphone camera to open QR code link._</details> |
|<span aria-hidden="true">![Lighthouse](https://app.netlify.com/public/external-usage/git-comments/lighthouse-sm.png)</span><br />Lighthouse | 1 paths audited<br />**Performance**: 26 (🔴 down 3 from production)<br />**Accessibility**: 92 (no change from production)<br />**Best Practices**: 83 (no change from production)<br />**SEO**: 92 (no change from production)<br />**PWA**: -<br />[View the detailed breakdown and full score reports](https://app.netlify.com/sites/moondao-stc/deploys/68115ceff1ebbc0008aba273) |
---
<!-- [moondao-stc Preview](https://deploy-preview-430--moondao-stc.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify site configuration](https://app.netlify.com/sites/moondao-stc/configuration/notifications#deploy-webhooks)._
author_association: NONE
user: login: netlify[bot]
created_at: 2025-04-29T19:22:11Z
body: ### <span aria-hidden="true">✅</span> Deploy Preview for *moondao-ce-demo* ready!


|  Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | ec008cc3d5256666baf83fc86d84b7f93a41334c |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/moondao-ce-demo/deploys/68115cef14832a00085b1525 |
|<span aria-hidden="true">😎</span> Deploy Preview | [https://deploy-preview-430--moondao-ce-demo.netlify.app](https://deploy-preview-430--moondao-ce-demo.netlify.app) |
|<span aria-hidden="true">📱</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br />![QR Code](https://app.netlify.com/qr-code/eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1cmwiOiJodHRwczovL2RlcGxveS1wcmV2aWV3LTQzMC0tbW9vbmRhby1jZS1kZW1vLm5ldGxpZnkuYXBwIn0.JEtzQWZoQ4f7J45Fas4CZF748_exDckxIFCZZndS8WQ)<br /><br />_Use your smartphone camera to open QR code link._</details> |
---
<!-- [moondao-ce-demo Preview](https://deploy-preview-430--moondao-ce-demo.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify site configuration](https://app.netlify.com/sites/moondao-ce-demo/configuration/notifications#deploy-webhooks)._
author_association: NONE