[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-deep-evm-8-chun-yul-goujian-token-swap":3},{"article":4,"author":58},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":7,"meta_description":16,"focus_keyword":17,"og_image":18,"canonical_url":18,"robots_meta":19,"created_at":15,"updated_at":15,"tags":20,"category_name":38,"related_articles":39},"d3000000-0000-0000-0000-000000000108","a0000000-0000-0000-0000-000000000032","Deep EVM #8：用纯Yul构建Token Swap","deep-evm-8-chun-yul-goujian-token-swap","用纯Yul构建完整的Uniswap V2 token swap合约：calldata解析、外部调用、返回数据处理以及逐行gas分析。","## 为什么用纯Yul构建Token Swap\n\n在前几篇文章中，我们学习了Yul的基础知识。现在我们把所有知识结合起来，构建一个真实的项目：一个完整的Uniswap V2 token swap合约，完全用Yul编写。\n\n这个项目将展示：\n- Calldata解析和函数分发\n- 外部调用构建\n- 返回数据处理\n- 错误处理\n- Gas优化技巧\n\n## 合约结构\n\n```yul\nobject \"TokenSwap\" {\n    code {\n        datacopy(0, dataoffset(\"runtime\"), datasize(\"runtime\"))\n        return(0, datasize(\"runtime\"))\n    }\n    object \"runtime\" {\n        code {\n            \u002F\u002F 函数分发\n            switch selector()\n            case 0x12345678 { swap() }\n            default { revert(0, 0) }\n\n            function selector() -> s {\n                s := shr(224, calldataload(0))\n            }\n\n            function swap() {\n                \u002F\u002F 从calldata解析参数\n                let tokenIn := calldataload(0x04)\n                let tokenOut := calldataload(0x24)\n                let amountIn := calldataload(0x44)\n                let pair := calldataload(0x64)\n\n                \u002F\u002F 执行swap逻辑...\n            }\n        }\n    }\n}\n```\n\n## Calldata解析\n\n每个参数从calldata中的固定偏移量读取。前4字节是函数选择器，随后每32字节是一个参数。\n\n## 外部调用构建\n\n调用ERC-20 transfer需要手动在内存中构建calldata：\n\n```yul\n\u002F\u002F approve(address,uint256)\nmstore(0x00, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\nmstore(0x04, spender)\nmstore(0x24, amount)\nlet success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)\n```\n\n## 返回数据处理\n\n外部调用后，必须检查成功状态和返回数据。某些代币（如USDT）不返回布尔值。\n\n## Gas分析\n\n与Solidity版本相比，纯Yul实现通常节省30-50%的gas，因为消除了ABI编码\u002F解码开销、溢出检查和编译器生成的内存管理。\n\n## 总结\n\n用纯Yul构建token swap展示了汇编级编程的威力。虽然代码更复杂，但gas节省是实质性的——对于MEV机器人和高频DEX操作来说，这些节省直接转化为利润。","\u003Ch2 id=\"yul-token-swap\">为什么用纯Yul构建Token Swap\u003C\u002Fh2>\n\u003Cp>在前几篇文章中，我们学习了Yul的基础知识。现在我们把所有知识结合起来，构建一个真实的项目：一个完整的Uniswap V2 token swap合约，完全用Yul编写。\u003C\u002Fp>\n\u003Cp>这个项目将展示：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>Calldata解析和函数分发\u003C\u002Fli>\n\u003Cli>外部调用构建\u003C\u002Fli>\n\u003Cli>返回数据处理\u003C\u002Fli>\n\u003Cli>错误处理\u003C\u002Fli>\n\u003Cli>Gas优化技巧\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"\">合约结构\u003C\u002Fh2>\n\u003Cpre>\u003Ccode class=\"language-yul\">object \"TokenSwap\" {\n    code {\n        datacopy(0, dataoffset(\"runtime\"), datasize(\"runtime\"))\n        return(0, datasize(\"runtime\"))\n    }\n    object \"runtime\" {\n        code {\n            \u002F\u002F 函数分发\n            switch selector()\n            case 0x12345678 { swap() }\n            default { revert(0, 0) }\n\n            function selector() -&gt; s {\n                s := shr(224, calldataload(0))\n            }\n\n            function swap() {\n                \u002F\u002F 从calldata解析参数\n                let tokenIn := calldataload(0x04)\n                let tokenOut := calldataload(0x24)\n                let amountIn := calldataload(0x44)\n                let pair := calldataload(0x64)\n\n                \u002F\u002F 执行swap逻辑...\n            }\n        }\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"calldata\">Calldata解析\u003C\u002Fh2>\n\u003Cp>每个参数从calldata中的固定偏移量读取。前4字节是函数选择器，随后每32字节是一个参数。\u003C\u002Fp>\n\u003Ch2 id=\"\">外部调用构建\u003C\u002Fh2>\n\u003Cp>调用ERC-20 transfer需要手动在内存中构建calldata：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-yul\">\u002F\u002F approve(address,uint256)\nmstore(0x00, 0x095ea7b300000000000000000000000000000000000000000000000000000000)\nmstore(0x04, spender)\nmstore(0x24, amount)\nlet success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"\">返回数据处理\u003C\u002Fh2>\n\u003Cp>外部调用后，必须检查成功状态和返回数据。某些代币（如USDT）不返回布尔值。\u003C\u002Fp>\n\u003Ch2 id=\"gas\">Gas分析\u003C\u002Fh2>\n\u003Cp>与Solidity版本相比，纯Yul实现通常节省30-50%的gas，因为消除了ABI编码\u002F解码开销、溢出检查和编译器生成的内存管理。\u003C\u002Fp>\n\u003Ch2 id=\"\">总结\u003C\u002Fh2>\n\u003Cp>用纯Yul构建token swap展示了汇编级编程的威力。虽然代码更复杂，但gas节省是实质性的——对于MEV机器人和高频DEX操作来说，这些节省直接转化为利润。\u003C\u002Fp>\n","zh","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:25.895049Z","用纯Yul构建完整的Uniswap V2 token swap：calldata解析、外部调用、返回数据处理以及逐行gas分析。","Yul token swap",null,"index, follow",[21,26,30,34],{"id":22,"name":23,"slug":24,"created_at":25},"c0000000-0000-0000-0000-000000000016","EVM","evm","2026-03-28T10:44:21.513630Z",{"id":27,"name":28,"slug":29,"created_at":25},"c0000000-0000-0000-0000-000000000020","Gas Optimization","gas-optimization",{"id":31,"name":32,"slug":33,"created_at":25},"c0000000-0000-0000-0000-000000000017","Huff","huff",{"id":35,"name":36,"slug":37,"created_at":25},"c0000000-0000-0000-0000-000000000018","Yul","yul","区块链",[40,46,52],{"id":41,"title":42,"slug":43,"excerpt":44,"locale":12,"category_name":38,"published_at":45},"d0000000-0000-0000-0000-000000000599","Ethereum互操作层：55+个L2如何成为一条链","ethereum-hucaozuoceng-55-l2-chengwei-yitiao-lian","Ethereum有55+个Layer 2 rollup，碎片化了流动性和用户体验。Ethereum互操作层 — 结合跨rollup消息传递、共享排序器和based rollup — 旨在将它们统一为一个可组合的网络。","2026-03-28T10:44:44.539584Z",{"id":47,"title":48,"slug":49,"excerpt":50,"locale":12,"category_name":38,"published_at":51},"d0000000-0000-0000-0000-000000000598","ZK证明超越Rollups：Ethereum上的可验证AI推理","zk-zhengming-chaoyue-rollups-ethereum-keyanzheng-ai-tuili","零知识证明不再仅仅是扩容工具。在2026年，zkML实现了链上可验证的AI推理，ZK协处理器将繁重计算移至链下并在链上验证，而SP1和Jolt等新证明系统使其变得实用。","2026-03-28T10:44:44.534954Z",{"id":53,"title":54,"slug":55,"excerpt":56,"locale":12,"category_name":38,"published_at":57},"d0000000-0000-0000-0000-000000000575","EIP-7702实战：Pectra之后构建智能账户流程","eip-7702-shizhan-pectra-zhihou-goujian-zhineng-zhanghu-liucheng","EIP-7702允许任何Ethereum EOA在单笔交易中临时充当智能合约。以下是如何使用新的账户抽象原语实现批量交易、gas赞助和社交恢复。","2026-03-28T10:44:42.997040Z",{"id":13,"name":59,"slug":60,"bio":61,"photo_url":18,"linkedin":18,"role":62,"created_at":63,"updated_at":63},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]