[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6GZ78HDYF3CS5YMC9SHY418":3,"skill-same:01M6GZ78HDYF3CS5YMC9SHY418":82},{"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":24,"publishedAt":40,"linkOnly":41,"markdownContent":42,"markdownBody":43,"frontMatter":44,"refName":45,"commitSha":46,"skillDirectory":47,"forksCount":48,"repositoryHtmlUrl":49,"repositoryHomepageUrl":6,"ownerHtmlUrl":50,"ownerBlogUrl":51,"ownerDescription":52,"updatedAt":53,"install":54,"resources":67},"01M6GZ78HDYF3CS5YMC9SHY418","measure-on-chain-svg-gas-cost",null,"Use when a generative NFT renders SVG or JSON inside the contract and tokenURI gas must stay under a viewer's call limit. Measures the real cost and the dominant contributor before optimizing.","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-measure-on-chain-svg-gas-cost\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-measure-on-chain-svg-gas-cost\u002FSKILL.md",[19],{"categoryNo":20,"categoryName":21,"taxonomyType":22,"taxonomyTypeDesc":23},"01JBSEEDCAT000000000000016","图像与多媒体","SCENARIO","使用场景",[25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],"gas","cost","SVG","chain","measure on chain svg gas cost","json","use","call","nft","contract","limit","viewer","generative","contributor","when","2026-11-10 10:12:30",false,"---\nname: measure-on-chain-svg-gas-cost\ndescription: Use when a generative NFT renders SVG or JSON inside the contract and tokenURI gas must stay under a viewer's call limit. Measures the real cost and the dominant contributor before optimizing.\n---\n\n# Measure on-chain SVG gas cost\n\nRendering an SVG inside the contract pushes bytes into `tokenURI`; naive concatenation can cost hundreds of thousands of gas per call and blow the `eth_call` gas limit some wallets use.\n\n## Procedure\n\n1. Baseline the byte size of a metadata read:\n\n   ```\n   cast call $NFT \"tokenURI(uint256)(string)\" 1 --rpc-url $RPC | wc -c\n   cast call $NFT \"tokenURI(uint256)(string)\" 1 --rpc-url $RPC --gas-limit 50000000 >\u002Fdev\u002Fnull && echo \"renders\"\n   ```\n\n2. Measure the actual gas with forge:\n\n   ```\n   forge test --match-test testTokenURIGas --gas-report\n   ```\n\n   or in a script: `forge script script\u002FUriGas.s.sol --gas-limit 50000000`.\n\n3. Decompose the cost. Static bytes read from storage are cheap; repeated `string.concat` in a loop grows O(n²) because each concat copies the whole running string. Prefer one `abi.encodePacked` pass.\n\n4. Compare storage strategies per byte: a `bytes` slot costs 20000 gas SSTORE per 32-byte word, while SSTORE2 bytecode costs ~200 gas to deploy per byte and ~200 to read — cheaper for large static blobs read rarely.\n\n5. Benchmark the base64 encoder separately. Pure-Solidity base64 of a fixed string is fine; encoding a long dynamic string in the same call nearly doubles the work.\n\n6. Verify the rendered output parses before optimizing further:\n\n   ```\n   cast call $NFT \"tokenURI(uint256)(string)\" 1 --rpc-url $RPC \\\n     | jq -r '.image' | sed 's#data:image\u002Fsvg+xml;base64,##' | base64 -d | xmllint --noout -\n   ```\n\n7. Set a budget: if `tokenURI` exceeds ~30M gas, some RPCs and wallets drop the call and the collection renders blank. Cut bytes, not promises.\n\n## Pitfalls\n\n- Optimizing storage misses the true cost: string concatenation and base64 dominate.\n- SVG path data stored as `string[]` becomes one SLOAD per element per trait; pack the whole drawing into a single blob.\n- `tokenURI` that reverts on a gas limit makes every token render blank across marketplaces at once.\n- Off-by-one in base64 padding silently corrupts the image while still returning text.\n- Gas measured by `eth_estimateGas` excludes part of the read path; measure with `eth_call` at an explicit high gas.\n\n## Verification\n\n    forge test --match-test testTokenURIGas --gas-report | grep -i tokenURI\n\nPass: the reported `tokenURI` gas is under your budget and `xmllint --noout -` exits 0 on the decoded SVG. Report the measured gas, the biggest cost contributor, and the storage strategy chosen.\n","# Measure on-chain SVG gas cost\n\nRendering an SVG inside the contract pushes bytes into `tokenURI`; naive concatenation can cost hundreds of thousands of gas per call and blow the `eth_call` gas limit some wallets use.\n\n## Procedure\n\n1. Baseline the byte size of a metadata read:\n\n   ```\n   cast call $NFT \"tokenURI(uint256)(string)\" 1 --rpc-url $RPC | wc -c\n   cast call $NFT \"tokenURI(uint256)(string)\" 1 --rpc-url $RPC --gas-limit 50000000 >\u002Fdev\u002Fnull && echo \"renders\"\n   ```\n\n2. Measure the actual gas with forge:\n\n   ```\n   forge test --match-test testTokenURIGas --gas-report\n   ```\n\n   or in a script: `forge script script\u002FUriGas.s.sol --gas-limit 50000000`.\n\n3. Decompose the cost. Static bytes read from storage are cheap; repeated `string.concat` in a loop grows O(n²) because each concat copies the whole running string. Prefer one `abi.encodePacked` pass.\n\n4. Compare storage strategies per byte: a `bytes` slot costs 20000 gas SSTORE per 32-byte word, while SSTORE2 bytecode costs ~200 gas to deploy per byte and ~200 to read — cheaper for large static blobs read rarely.\n\n5. Benchmark the base64 encoder separately. Pure-Solidity base64 of a fixed string is fine; encoding a long dynamic string in the same call nearly doubles the work.\n\n6. Verify the rendered output parses before optimizing further:\n\n   ```\n   cast call $NFT \"tokenURI(uint256)(string)\" 1 --rpc-url $RPC \\\n     | jq -r '.image' | sed 's#data:image\u002Fsvg+xml;base64,##' | base64 -d | xmllint --noout -\n   ```\n\n7. Set a budget: if `tokenURI` exceeds ~30M gas, some RPCs and wallets drop the call and the collection renders blank. Cut bytes, not promises.\n\n## Pitfalls\n\n- Optimizing storage misses the true cost: string concatenation and base64 dominate.\n- SVG path data stored as `string[]` becomes one SLOAD per element per trait; pack the whole drawing into a single blob.\n- `tokenURI` that reverts on a gas limit makes every token render blank across marketplaces at once.\n- Off-by-one in base64 padding silently corrupts the image while still returning text.\n- Gas measured by `eth_estimateGas` excludes part of the read path; measure with `eth_call` at an explicit high gas.\n\n## Verification\n\n    forge test --match-test testTokenURIGas --gas-report | grep -i tokenURI\n\nPass: the reported `tokenURI` gas is under your budget and `xmllint --noout -` exits 0 on the decoded SVG. Report the measured gas, the biggest cost contributor, and the storage strategy chosen.\n",{"name":5,"description":7},"main","3df1d0d67b30ff15236561f8c0f9f06d33f42dfd","skills\u002Fpayments\u002F0xklen-measure-on-chain-svg-gas-cost",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-14 02:27:51",{"source":8,"skillName":5,"commands":55,"prompt":65,"zipAvailable":66},[56,59,62],{"tool":57,"command":58},"npx","npx skills add jiayaoqijia\u002Fcryptoskill --skill measure-on-chain-svg-gas-cost",{"tool":60,"command":61},"bunx","bunx skills add jiayaoqijia\u002Fcryptoskill --skill measure-on-chain-svg-gas-cost",{"tool":63,"command":64},"pnpm","pnpm dlx skills add jiayaoqijia\u002Fcryptoskill --skill measure-on-chain-svg-gas-cost","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-measure-on-chain-svg-gas-cost\u002FSKILL.md",true,[68,72,78],{"path":69,"resourceType":69,"resourceTypeDesc":70,"sizeBytes":71,"sourceHtmlUrl":16},"LICENSE","许可证",1063,{"path":73,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":76,"sourceHtmlUrl":77},"SOURCE.md","REFERENCE","参考文档",355,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-measure-on-chain-svg-gas-cost\u002FSOURCE.md",{"path":79,"resourceType":74,"resourceTypeDesc":75,"sizeBytes":80,"sourceHtmlUrl":81},"TRUST.auto.yaml",2217,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-measure-on-chain-svg-gas-cost\u002FTRUST.auto.yaml",[83,111,134,152,165,175],{"skillNo":84,"name":85,"nameZh":6,"description":86,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":87,"sourceHtmlUrl":88,"categories":89,"keywords":90,"publishedAt":40},"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",[],[91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110],"performance","recipe performance","recipe","mm","sentry","harness","app","deterministic","recipes","flow","cold","critical","analysis","tasks","react","browser","layout","screen","network","metamask",{"skillNo":112,"name":113,"nameZh":6,"description":114,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":115,"licenseFileUrl":116,"sourceHtmlUrl":117,"categories":118,"keywords":119,"publishedAt":40},"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",[],[120,121,122,123,124,125,126,127,128,129,130,131,132,133],"mexc spot websocket","spot","websocket","api","workflows","public","listen","streams","depth","keys","for","api keys","maintenance","protobuf",{"skillNo":135,"name":136,"nameZh":6,"description":137,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":115,"licenseFileUrl":138,"sourceHtmlUrl":139,"categories":140,"keywords":141,"publishedAt":40},"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",[],[142,121,143,144,145,146,147,131,130,129,148,149,150,125,151,124,123],"mexc spot rest","REST","admin","signing","Wallet","requests","actions","secure","data","orders",{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":115,"licenseFileUrl":156,"sourceHtmlUrl":157,"categories":158,"keywords":159,"publishedAt":40},"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",[],[160,161,122,162,163,132,130,164,128,127,125,124],"mexc futures websocket","futures","position","ping","subscriptions",{"skillNo":166,"name":167,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":168,"sourceHtmlUrl":169,"categories":170,"keywords":171,"publishedAt":40},"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",[],[172,173,174],"refresh","0xklen version and refresh sanctions lists","version",{"skillNo":176,"name":177,"nameZh":6,"description":178,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":179,"sourceHtmlUrl":180,"categories":181,"keywords":182,"publishedAt":40},"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",[],[183,184,185,186,187,188,189,31,190,191,192],"tests","cover","verify tests cover changed lines","verify","coverage","pr","exercise","patch","code","share"]