[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6GXGDGF0TMRNFKZC2MY110T":3,"skill-same:01M6GXGDGF0TMRNFKZC2MY110T":78},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":16,"sourceHtmlUrl":17,"categories":18,"keywords":19,"publishedAt":36,"linkOnly":37,"markdownContent":38,"markdownBody":39,"frontMatter":40,"refName":41,"commitSha":42,"skillDirectory":43,"forksCount":44,"repositoryHtmlUrl":45,"repositoryHomepageUrl":6,"ownerHtmlUrl":46,"ownerBlogUrl":47,"ownerDescription":48,"updatedAt":49,"install":50,"resources":63},"01M6GXGDGF0TMRNFKZC2MY110T","audit-a-dao-treasury-signer-set",null,"Use when reviewing who can move a DAO treasury, or after a signer change. Compares the multisig's on-chain owners and threshold against the governance-approved roster.","jiayaoqijia\u002Fcryptoskill","jiayaoqijia","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1453879?v=4","01M6GMYTX7Q7S504VC6E756ENR","YQ","01M6GMYV1QKJ1CC75MTTGT9PR0",81,"MIT","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-audit-a-dao-treasury-signer-set\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-audit-a-dao-treasury-signer-set\u002FSKILL.md",[],[20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35],"audit","SET","dao","treasury","audit a dao treasury signer set","change","governance","owners","use","multisig","chain","roster","move","can","on-chain","when","2026-11-10 10:12:30",false,"---\nname: audit-a-dao-treasury-signer-set\ndescription: Use when reviewing who can move a DAO treasury, or after a signer change. Compares the multisig's on-chain owners and threshold against the governance-approved roster.\n---\n\n# Audit a DAO treasury signer set\n\nThe treasury multisig is only as legitimate as the signer set governance approved. A signer silently swapped in, or a threshold lowered by one, changes who controls the funds without a vote.\n\n## Procedure\n\n1. Read the current owners and threshold:\n   `cast call $SAFE \"getOwners()(address[])\" --rpc-url $RPC`\n   `cast call $SAFE \"getThreshold()(uint256)\" --rpc-url $RPC`\n2. Fetch the governance-approved roster: the proposal that last set the signer set, decoded from its calldata.\n   `cast call $GOV \"getActions(uint256)(address[],uint256[],bytes[],bytes32)\" $ID --rpc-url $RPC`\n3. Diff the two sets: any owner not in the approved list, or a missing approved owner, is a finding.\n4. Check no two owners are controlled by one key: compare against a known cluster map, and flag duplicate hardware-wallet addresses or an owner that is an EOA of a current signer's hot key.\n5. Verify the threshold still matches the approved value; a threshold reduced from 4\u002F7 to 3\u002F7 is a governance change even if the owners are identical.\n6. Confirm the Safe is the timelock's beneficiary, not a rogue parallel treasury: the address the governor pays must equal this Safe.\n7. Re-run after every `AddedOwner`\u002F`RemovedOwner`\u002F`ChangedThreshold` event; alert on any that does not trace to an executed proposal.\n\n8. Check each owner is still an active signer, not a departed member or a revoked key; a stale owner is a standing point of compromise.\n9. Confirm no owner is a contract that cannot sign (e.g. the governor's own timelock); a non-signing owner quietly lowers the effective threshold.\n10. Record the audit block and the proposal id that last authorised the set, so the check is reproducible later.\n\n## Pitfalls\n\n- Auditing owners but not the threshold; the same owners with a lower threshold is a weaker control.\n- Assuming the owners are the governance council when the founding team holds the keys from before the DAO existed.\n- Missing a signer module: a Safe with an enabled module (e.g. a recovery or spending-limit module) can move funds without the normal threshold.\n- Treating the Safe address as canonical without checking the governor's target; a proposal to pay a different, similarly-named Safe is the attack.\n- Ignoring signer rotation history; a signer added and removed within a term may still hold a copy of the config.\n\n- A Safe whose owners include the deployer EOA from before governance existed still grants that key standing weight.\n- Trusting the Safe UI's owner list; read `getOwners()` on-chain, since a pending owner change is not yet applied.\n- A module-enabled Safe can be drained through the module without any owner signing; check `getModulesPaginated`.\n\n## Verification\n\n    cast call $SAFE \"getOwners()(address[])\" --rpc-url $RPC && cast call $SAFE \"getThreshold()(uint256)\" --rpc-url $RPC\n    # owners set and threshold must equal the decoded roster from the executed proposal\n\nReport the owner set, the threshold, the approved roster, and any diff or non-governance signer change, with the events cited.\n","# Audit a DAO treasury signer set\n\nThe treasury multisig is only as legitimate as the signer set governance approved. A signer silently swapped in, or a threshold lowered by one, changes who controls the funds without a vote.\n\n## Procedure\n\n1. Read the current owners and threshold:\n   `cast call $SAFE \"getOwners()(address[])\" --rpc-url $RPC`\n   `cast call $SAFE \"getThreshold()(uint256)\" --rpc-url $RPC`\n2. Fetch the governance-approved roster: the proposal that last set the signer set, decoded from its calldata.\n   `cast call $GOV \"getActions(uint256)(address[],uint256[],bytes[],bytes32)\" $ID --rpc-url $RPC`\n3. Diff the two sets: any owner not in the approved list, or a missing approved owner, is a finding.\n4. Check no two owners are controlled by one key: compare against a known cluster map, and flag duplicate hardware-wallet addresses or an owner that is an EOA of a current signer's hot key.\n5. Verify the threshold still matches the approved value; a threshold reduced from 4\u002F7 to 3\u002F7 is a governance change even if the owners are identical.\n6. Confirm the Safe is the timelock's beneficiary, not a rogue parallel treasury: the address the governor pays must equal this Safe.\n7. Re-run after every `AddedOwner`\u002F`RemovedOwner`\u002F`ChangedThreshold` event; alert on any that does not trace to an executed proposal.\n\n8. Check each owner is still an active signer, not a departed member or a revoked key; a stale owner is a standing point of compromise.\n9. Confirm no owner is a contract that cannot sign (e.g. the governor's own timelock); a non-signing owner quietly lowers the effective threshold.\n10. Record the audit block and the proposal id that last authorised the set, so the check is reproducible later.\n\n## Pitfalls\n\n- Auditing owners but not the threshold; the same owners with a lower threshold is a weaker control.\n- Assuming the owners are the governance council when the founding team holds the keys from before the DAO existed.\n- Missing a signer module: a Safe with an enabled module (e.g. a recovery or spending-limit module) can move funds without the normal threshold.\n- Treating the Safe address as canonical without checking the governor's target; a proposal to pay a different, similarly-named Safe is the attack.\n- Ignoring signer rotation history; a signer added and removed within a term may still hold a copy of the config.\n\n- A Safe whose owners include the deployer EOA from before governance existed still grants that key standing weight.\n- Trusting the Safe UI's owner list; read `getOwners()` on-chain, since a pending owner change is not yet applied.\n- A module-enabled Safe can be drained through the module without any owner signing; check `getModulesPaginated`.\n\n## Verification\n\n    cast call $SAFE \"getOwners()(address[])\" --rpc-url $RPC && cast call $SAFE \"getThreshold()(uint256)\" --rpc-url $RPC\n    # owners set and threshold must equal the decoded roster from the executed proposal\n\nReport the owner set, the threshold, the approved roster, and any diff or non-governance signer change, with the events cited.\n",{"name":5,"description":7},"main","3df1d0d67b30ff15236561f8c0f9f06d33f42dfd","skills\u002Fpayments\u002F0xklen-audit-a-dao-treasury-signer-set",17,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia","https:\u002F\u002Feth2030.com","Hardcore infra. Building @alt-research and applied cryptography.","2026-11-12 02:28:42",{"source":8,"skillName":5,"commands":51,"prompt":61,"zipAvailable":62},[52,55,58],{"tool":53,"command":54},"npx","npx skills add jiayaoqijia\u002Fcryptoskill --skill audit-a-dao-treasury-signer-set",{"tool":56,"command":57},"bunx","bunx skills add jiayaoqijia\u002Fcryptoskill --skill audit-a-dao-treasury-signer-set",{"tool":59,"command":60},"pnpm","pnpm dlx skills add jiayaoqijia\u002Fcryptoskill --skill audit-a-dao-treasury-signer-set","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-audit-a-dao-treasury-signer-set\u002FSKILL.md",true,[64,68,74],{"path":65,"resourceType":65,"resourceTypeDesc":66,"sizeBytes":67,"sourceHtmlUrl":16},"LICENSE","许可证",1063,{"path":69,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":72,"sourceHtmlUrl":73},"SOURCE.md","REFERENCE","参考文档",357,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-audit-a-dao-treasury-signer-set\u002FSOURCE.md",{"path":75,"resourceType":70,"resourceTypeDesc":71,"sizeBytes":76,"sourceHtmlUrl":77},"TRUST.auto.yaml",2191,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-audit-a-dao-treasury-signer-set\u002FTRUST.auto.yaml",[79,107,130,148,161,171],{"skillNo":80,"name":81,"nameZh":6,"description":82,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":83,"sourceHtmlUrl":84,"categories":85,"keywords":86,"publishedAt":36},"01M712C436EQYE43342Q4E7GG1","recipe-performance","Diagnose a specific MetaMask user flow's real-app performance and Sentry critical-user-flow telemetry with deterministic mm-harness recipes. Use for CUF boundaries, cold\u002Fwarm\u002Fbackground-resume behavior, latency regressions, lifecycle tags, duplicate or blocking network requests, long tasks, layout\u002Fpaint cost, screen redraws, React rerenders, or browser trace analysis where tests alone cannot prove the real app.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fwallets\u002Fmetamask-official-recipe-performance\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fwallets\u002Fmetamask-official-recipe-performance\u002FSKILL.md",[],[87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106],"performance","recipe performance","recipe","mm","sentry","harness","app","deterministic","recipes","flow","cold","critical","analysis","tasks","react","browser","layout","screen","network","metamask",{"skillNo":108,"name":109,"nameZh":6,"description":110,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":111,"licenseFileUrl":112,"sourceHtmlUrl":113,"categories":114,"keywords":115,"publishedAt":36},"01M70XT2F8A5CQZ81JBP98KSW3","mexc-spot-websocket","MEXC Spot WebSocket workflows for public streams, protobuf handling, depth maintenance, listen keys, and private streams without exposing API keys.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-websocket\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-websocket\u002FSKILL.md",[],[116,117,118,119,120,121,122,123,124,125,126,127,128,129],"mexc spot websocket","spot","websocket","api","workflows","public","listen","streams","depth","keys","for","api keys","maintenance","protobuf",{"skillNo":131,"name":132,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":111,"licenseFileUrl":134,"sourceHtmlUrl":135,"categories":136,"keywords":137,"publishedAt":36},"01M70XT0MBXN3WZY1BKN0CPNKR","mexc-spot-rest","MEXC Spot REST workflows for public data, signed account requests, orders, wallet\u002Fadmin actions, and secure signing without exposing API keys.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-rest\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-rest\u002FSKILL.md",[],[138,117,139,140,141,142,143,127,126,125,144,145,146,121,147,120,119],"mexc spot rest","REST","admin","signing","Wallet","requests","actions","secure","data","orders",{"skillNo":149,"name":150,"nameZh":6,"description":151,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":111,"licenseFileUrl":152,"sourceHtmlUrl":153,"categories":154,"keywords":155,"publishedAt":36},"01M70XSYSVZ2N0N91XCAR2CAK0","mexc-futures-websocket","MEXC Futures WebSocket workflows for public streams, private account\u002Forder\u002Fposition streams, ping\u002Fpong, subscriptions, and depth maintenance.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-futures-websocket\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-futures-websocket\u002FSKILL.md",[],[156,157,118,158,159,128,126,160,124,123,121,120],"mexc futures websocket","futures","position","ping","subscriptions",{"skillNo":162,"name":163,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":164,"sourceHtmlUrl":165,"categories":166,"keywords":167,"publishedAt":36},"01M6H0ZWHVE5W04WG2DKQE2SQC","0xklen-version-and-refresh-sanctions-lists","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-version-and-refresh-sanctions-lists\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-version-and-refresh-sanctions-lists\u002FSKILL.md",[],[168,169,170],"refresh","0xklen version and refresh sanctions lists","version",{"skillNo":172,"name":173,"nameZh":6,"description":174,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":175,"sourceHtmlUrl":176,"categories":177,"keywords":178,"publishedAt":36},"01M6H0Z28Q3R8J0S799GJQWXM3","verify-tests-cover-changed-lines","Use when a PR adds code that the existing suite may not exercise. Measures patch coverage — the share of newly changed lines hit by tests — before approving.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-verify-tests-cover-changed-lines\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-verify-tests-cover-changed-lines\u002FSKILL.md",[],[179,180,181,182,183,184,185,28,186,187,188],"tests","cover","verify tests cover changed lines","verify","coverage","pr","exercise","patch","code","share"]