[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-eip-7702-siljeon-gaideu-pectra-ihu-seumateu-gyejeong-peulro-guchuk":3},{"article":4,"author":55},{"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":34,"related_articles":35},"d0000000-0000-0000-0000-000000000581","a0000000-0000-0000-0000-000000000052","EIP-7702 실전 가이드: Pectra 이후 스마트 계정 플로우 구축","eip-7702-siljeon-gaideu-pectra-ihu-seumateu-gyejeong-peulro-guchuk","EIP-7702는 모든 Ethereum EOA가 단일 트랜잭션 내에서 스마트 컨트랙트로 임시 동작할 수 있게 합니다. 새로운 계정 추상화 프리미티브를 사용한 배치 트랜잭션, 가스 후원, 소셜 리커버리 구현 방법을 소개합니다.","## EIP-7702가 가능하게 하는 것\n\nEIP-7702는 2025년 3월 Ethereum의 Pectra 업그레이드와 함께 활성화되어, 모든 외부 소유 계정(EOA)이 **위임 지정자**를 설정할 수 있는 새로운 트랜잭션 타입을 도입했습니다. 이것은 스마트 컨트랙트를 가리키는 포인터로, EOA가 트랜잭션 기간 동안 임시로 해당 코드를 채택합니다. 즉, 기존 MetaMask 지갑 주소가 새 컨트랙트 지갑을 배포하거나 주소를 변경하지 않고도 임의의 스마트 컨트랙트 로직을 실행할 수 있습니다.\n\n이것은 이더리움 역사상 가장 중요한 UX 개선입니다.\n\n## EIP-7702 vs ERC-4337: 사용 시기\n\n| 특성 | EIP-7702 | ERC-4337 |\n|------|----------|----------|\n| 레벨 | 프로토콜(새 tx 타입) | 애플리케이션(스마트 컨트랙트) |\n| 계정 타입 | 기존 EOA 업그레이드 | 새 스마트 컨트랙트 지갑 필요 |\n| 주소 | 기존 EOA 주소 유지 | 새 주소(반사실적) |\n| 지속성 | 트랜잭션별 위임 | 영구적 스마트 컨트랙트 |\n| 번들러 필요 | 아니오(표준 tx 플로우) | 예(별도 멤풀) |\n| 가스 오버헤드 | 위임에 ~20,000 가스 | UserOp 검증에 ~42,000 가스 |\n| 지원 지갑 | MetaMask, Coinbase Wallet, Rainbow | 전용(Safe, ZeroDev, Biconomy) |\n| 최적 용도 | 기존 사용자 업그레이드 | 신규 사용자, 복잡한 계정 로직 |\n\n### 결정 프레임워크\n\n**EIP-7702를 사용할 때:**\n- 사용자가 이미 EOA 지갑을 가지고 있을 때\n- 배치 트랜잭션이나 가스 후원이 필요할 때\n- 통합 복잡성을 최소화하고 싶을 때\n\n**ERC-4337을 사용할 때:**\n- 새 지갑을 구축하거나 신규 사용자를 온보딩할 때\n- 영구적인 계정 로직이 필요할 때\n- 모듈, 플러그인, 가디언 등 고급 기능이 필요할 때\n\n## 코드 예제\n\n### 배치 트랜잭션\n\n가장 일반적인 EIP-7702 사용 사례: 단일 트랜잭션에서 여러 작업 실행.\n\n```solidity\n\u002F\u002F SPDX-License-Identifier: MIT\npragma solidity ^0.8.25;\n\n\u002F\u002F\u002F @title BatchExecutor — EIP-7702 배치 콜 위임 대상\ncontract BatchExecutor {\n    struct Call {\n        address target;\n        uint256 value;\n        bytes data;\n    }\n    \n    function executeBatch(Call[] calldata calls) external payable {\n        for (uint256 i = 0; i \u003C calls.length; i++) {\n            (bool success, bytes memory result) = calls[i].target.call{\n                value: calls[i].value\n            }(calls[i].data);\n            \n            if (!success) {\n                assembly {\n                    revert(add(result, 32), mload(result))\n                }\n            }\n        }\n    }\n}\n```\n\nethers.js v6 클라이언트 사이드 사용법:\n\n```typescript\nimport { ethers } from \"ethers\";\n\nconst batchTx = {\n    type: 4,\n    to: userAddress,\n    authorizationList: [{\n        chainId: 1,\n        address: BATCH_EXECUTOR_ADDRESS,\n        nonce: await provider.getTransactionCount(userAddress),\n        yParity: 0, r: \"0x...\", s: \"0x...\"\n    }],\n    data: batchExecutorInterface.encodeFunctionData(\"executeBatch\", [[\n        {\n            target: USDC_ADDRESS,\n            value: 0,\n            data: usdcInterface.encodeFunctionData(\"approve\", [\n                UNISWAP_ROUTER, ethers.parseUnits(\"1000\", 6)\n            ])\n        },\n        {\n            target: UNISWAP_ROUTER,\n            value: 0,\n            data: routerInterface.encodeFunctionData(\"exactInputSingle\", [{\n                tokenIn: USDC_ADDRESS,\n                tokenOut: WETH_ADDRESS,\n                fee: 3000,\n                recipient: userAddress,\n                amountIn: ethers.parseUnits(\"1000\", 6),\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            }])\n        }\n    ]])\n};\n\nconst tx = await signer.sendTransaction(batchTx);\n```\n\n### 가스 후원\n\n```solidity\n\u002F\u002F\u002F @title SponsoredExecutor — EIP-7702를 통한 가스 후원\ncontract SponsoredExecutor {\n    mapping(address => uint256) public nonces;\n    \n    function sponsoredExecute(\n        address user,\n        address target,\n        bytes calldata data,\n        uint256 userNonce,\n        uint256 deadline,\n        bytes calldata signature\n    ) external {\n        require(block.timestamp \u003C= deadline, \"Expired\");\n        require(nonces[user] == userNonce, \"Invalid nonce\");\n        nonces[user]++;\n        \n        bytes32 digest = _hashTypedData(user, target, data, userNonce, deadline);\n        address signer = ECDSA.recover(digest, signature);\n        require(signer == user, \"Invalid signature\");\n        \n        (bool success, bytes memory result) = target.call(data);\n        require(success, \"Call failed\");\n    }\n}\n```\n\n### 소셜 리커버리\n\n```solidity\n\u002F\u002F\u002F @title RecoveryModule — EIP-7702를 통한 소셜 리커버리\ncontract RecoveryModule {\n    struct RecoveryConfig {\n        address[] guardians;\n        uint256 threshold;\n        uint256 delay;\n    }\n    \n    mapping(address => RecoveryConfig) public configs;\n    mapping(bytes32 => uint256) public recoveryTimestamps;\n    mapping(bytes32 => uint256) public approvalCounts;\n    mapping(bytes32 => mapping(address => bool)) public hasApproved;\n    \n    function setupRecovery(\n        address[] calldata guardians,\n        uint256 threshold,\n        uint256 delay\n    ) external {\n        require(guardians.length >= threshold, \"Invalid threshold\");\n        require(threshold >= 2, \"Min 2 guardians\");\n        configs[msg.sender] = RecoveryConfig(guardians, threshold, delay);\n    }\n    \n    function approveRecovery(\n        address account,\n        address newOwner\n    ) external {\n        RecoveryConfig memory config = configs[account];\n        require(_isGuardian(config, msg.sender), \"Not a guardian\");\n        \n        bytes32 recoveryId = keccak256(abi.encode(account, newOwner));\n        require(!hasApproved[recoveryId][msg.sender], \"Already approved\");\n        \n        hasApproved[recoveryId][msg.sender] = true;\n        approvalCounts[recoveryId]++;\n        \n        if (approvalCounts[recoveryId] >= config.threshold) {\n            recoveryTimestamps[recoveryId] = block.timestamp + config.delay;\n        }\n    }\n    \n    function executeRecovery(\n        address account,\n        address newOwner\n    ) external {\n        bytes32 recoveryId = keccak256(abi.encode(account, newOwner));\n        uint256 timestamp = recoveryTimestamps[recoveryId];\n        require(timestamp > 0 && block.timestamp >= timestamp, \"Not ready\");\n    }\n}\n```\n\n## 지갑 통합 현황\n\n### MetaMask\n\nMetaMask는 버전 12.4(2025년 9월)에서 EIP-7702 지원을 추가했습니다.\n\n### Coinbase Wallet\n\nCoinbase Wallet은 가장 적극적인 채택자로, \"Smart Wallet\" 기능(2025년 11월 출시)에 EIP-7702를 통합:\n- **자동 배치** — approve+swap 시퀀스를 자동으로 배치\n- **가스 후원** — $1 이하 수수료 트랜잭션을 Coinbase가 후원\n- **원클릭 DeFi** — 일반적인 DeFi 작업용 사전 구축 위임 대상\n\n### Rainbow, Rabby 등\n\nRainbow는 2026년 1월에 지원을 추가했습니다. Rabby는 type-4 트랜잭션을 지원하지만 배치 시각화 UI는 없습니다.\n\n## 마이그레이션 가이드\n\n### 1단계: 위임 대상 배포\n\n### 2단계: 프론트엔드 업데이트\n\n```typescript\nasync function supportsEIP7702(provider: ethers.Provider): Promise\u003Cboolean> {\n    try {\n        const capabilities = await provider.send(\n            \"wallet_getCapabilities\", []\n        );\n        return capabilities?.atomicBatch?.supported === true;\n    } catch {\n        return false;\n    }\n}\n```\n\n### 3단계: 그레이스풀 디그레이데이션 구현\n\n```typescript\nasync function executeSwap(tokenIn, tokenOut, amount) {\n    if (await supportsEIP7702(provider)) {\n        return executeBatchSwap(tokenIn, tokenOut, amount);\n    } else {\n        await approve(tokenIn, ROUTER, amount);\n        return swap(tokenIn, tokenOut, amount);\n    }\n}\n```\n\n## 보안 고려사항\n\n### 위임 대상 검증\n\n위임 대상 컨트랙트는 트랜잭션 중 EOA 자산에 대한 **전체 제어권**을 가집니다.\n\n**완화:** 감사 및 검증된 컨트랙트에만 위임하세요.\n\n### 리플레이 보호\n\nEIP-7702 인증 목록에는 리플레이 공격을 방지하는 nonce가 포함됩니다.\n\n### 위임을 통한 피싱\n\n**완화:** 지갑은 EOA가 위임하는 코드를 명확히 표시해야 합니다.\n\n### 배치 실행의 재진입성\n\n```solidity\nbool private locked;\n\nmodifier noReentrant() {\n    require(!locked, \"Reentrant\");\n    locked = true;\n    _;\n    locked = false;\n}\n```\n\n### 스토리지 충돌\n\nEIP-7201(네임스페이스 스토리지) 사용:\n\n```solidity\nbytes32 constant STORAGE_SLOT = keccak256(\n    abi.encode(uint256(keccak256(\"batch.executor.storage\")) - 1)\n) & ~bytes32(uint256(0xff));\n```\n\n## 자주 묻는 질문\n\n### EIP-7702가 지갑 주소를 변경하나요?\n\n아니요. EOA 주소는 그대로 유지됩니다. EIP-7702는 단일 트랜잭션 동안만 스마트 컨트랙트 기능을 부여합니다.\n\n### L2에서 EIP-7702를 사용할 수 있나요?\n\n예. 모든 주요 L2(Arbitrum, Base, Optimism, zkSync)가 EIP-7702를 채택했습니다.\n\n### 위임 대상에 버그가 있으면 어떻게 되나요?\n\n피해는 단일 트랜잭션에 한정됩니다. 하지만 해당 트랜잭션 내에서 위임 대상은 EOA 자산에 전체 접근 권한을 가집니다.\n\n### 하드웨어 지갑과 호환되나요?\n\n예. Ledger는 펌웨어 2.3.0(2025년 12월)에서 지원을 추가했습니다.\n\n### EIP-7702로 얼마나 가스를 절약하나요?\n\n일반적인 approve+swap 플로우에서 약 **40-50%** 가스 절약. 복잡한 멀티스텝 DeFi 작업에서는 60-70%에 달할 수 있습니다.","\u003Ch2 id=\"eip-7702\">EIP-7702가 가능하게 하는 것\u003C\u002Fh2>\n\u003Cp>EIP-7702는 2025년 3월 Ethereum의 Pectra 업그레이드와 함께 활성화되어, 모든 외부 소유 계정(EOA)이 \u003Cstrong>위임 지정자\u003C\u002Fstrong>를 설정할 수 있는 새로운 트랜잭션 타입을 도입했습니다. 이것은 스마트 컨트랙트를 가리키는 포인터로, EOA가 트랜잭션 기간 동안 임시로 해당 코드를 채택합니다. 즉, 기존 MetaMask 지갑 주소가 새 컨트랙트 지갑을 배포하거나 주소를 변경하지 않고도 임의의 스마트 컨트랙트 로직을 실행할 수 있습니다.\u003C\u002Fp>\n\u003Cp>이것은 이더리움 역사상 가장 중요한 UX 개선입니다.\u003C\u002Fp>\n\u003Ch2 id=\"eip-7702-vs-erc-4337\">EIP-7702 vs ERC-4337: 사용 시기\u003C\u002Fh2>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>특성\u003C\u002Fth>\u003Cth>EIP-7702\u003C\u002Fth>\u003Cth>ERC-4337\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>레벨\u003C\u002Ftd>\u003Ctd>프로토콜(새 tx 타입)\u003C\u002Ftd>\u003Ctd>애플리케이션(스마트 컨트랙트)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>계정 타입\u003C\u002Ftd>\u003Ctd>기존 EOA 업그레이드\u003C\u002Ftd>\u003Ctd>새 스마트 컨트랙트 지갑 필요\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>주소\u003C\u002Ftd>\u003Ctd>기존 EOA 주소 유지\u003C\u002Ftd>\u003Ctd>새 주소(반사실적)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>지속성\u003C\u002Ftd>\u003Ctd>트랜잭션별 위임\u003C\u002Ftd>\u003Ctd>영구적 스마트 컨트랙트\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>번들러 필요\u003C\u002Ftd>\u003Ctd>아니오(표준 tx 플로우)\u003C\u002Ftd>\u003Ctd>예(별도 멤풀)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>가스 오버헤드\u003C\u002Ftd>\u003Ctd>위임에 ~20,000 가스\u003C\u002Ftd>\u003Ctd>UserOp 검증에 ~42,000 가스\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>지원 지갑\u003C\u002Ftd>\u003Ctd>MetaMask, Coinbase Wallet, Rainbow\u003C\u002Ftd>\u003Ctd>전용(Safe, ZeroDev, Biconomy)\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>최적 용도\u003C\u002Ftd>\u003Ctd>기존 사용자 업그레이드\u003C\u002Ftd>\u003Ctd>신규 사용자, 복잡한 계정 로직\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Ch3>결정 프레임워크\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>EIP-7702를 사용할 때:\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>사용자가 이미 EOA 지갑을 가지고 있을 때\u003C\u002Fli>\n\u003Cli>배치 트랜잭션이나 가스 후원이 필요할 때\u003C\u002Fli>\n\u003Cli>통합 복잡성을 최소화하고 싶을 때\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>\u003Cstrong>ERC-4337을 사용할 때:\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cul>\n\u003Cli>새 지갑을 구축하거나 신규 사용자를 온보딩할 때\u003C\u002Fli>\n\u003Cli>영구적인 계정 로직이 필요할 때\u003C\u002Fli>\n\u003Cli>모듈, 플러그인, 가디언 등 고급 기능이 필요할 때\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"\">코드 예제\u003C\u002Fh2>\n\u003Ch3>배치 트랜잭션\u003C\u002Fh3>\n\u003Cp>가장 일반적인 EIP-7702 사용 사례: 단일 트랜잭션에서 여러 작업 실행.\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">\u002F\u002F SPDX-License-Identifier: MIT\npragma solidity ^0.8.25;\n\n\u002F\u002F\u002F @title BatchExecutor — EIP-7702 배치 콜 위임 대상\ncontract BatchExecutor {\n    struct Call {\n        address target;\n        uint256 value;\n        bytes data;\n    }\n    \n    function executeBatch(Call[] calldata calls) external payable {\n        for (uint256 i = 0; i &lt; calls.length; i++) {\n            (bool success, bytes memory result) = calls[i].target.call{\n                value: calls[i].value\n            }(calls[i].data);\n            \n            if (!success) {\n                assembly {\n                    revert(add(result, 32), mload(result))\n                }\n            }\n        }\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>ethers.js v6 클라이언트 사이드 사용법:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-typescript\">import { ethers } from \"ethers\";\n\nconst batchTx = {\n    type: 4,\n    to: userAddress,\n    authorizationList: [{\n        chainId: 1,\n        address: BATCH_EXECUTOR_ADDRESS,\n        nonce: await provider.getTransactionCount(userAddress),\n        yParity: 0, r: \"0x...\", s: \"0x...\"\n    }],\n    data: batchExecutorInterface.encodeFunctionData(\"executeBatch\", [[\n        {\n            target: USDC_ADDRESS,\n            value: 0,\n            data: usdcInterface.encodeFunctionData(\"approve\", [\n                UNISWAP_ROUTER, ethers.parseUnits(\"1000\", 6)\n            ])\n        },\n        {\n            target: UNISWAP_ROUTER,\n            value: 0,\n            data: routerInterface.encodeFunctionData(\"exactInputSingle\", [{\n                tokenIn: USDC_ADDRESS,\n                tokenOut: WETH_ADDRESS,\n                fee: 3000,\n                recipient: userAddress,\n                amountIn: ethers.parseUnits(\"1000\", 6),\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            }])\n        }\n    ]])\n};\n\nconst tx = await signer.sendTransaction(batchTx);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>가스 후원\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">\u002F\u002F\u002F @title SponsoredExecutor — EIP-7702를 통한 가스 후원\ncontract SponsoredExecutor {\n    mapping(address =&gt; uint256) public nonces;\n    \n    function sponsoredExecute(\n        address user,\n        address target,\n        bytes calldata data,\n        uint256 userNonce,\n        uint256 deadline,\n        bytes calldata signature\n    ) external {\n        require(block.timestamp &lt;= deadline, \"Expired\");\n        require(nonces[user] == userNonce, \"Invalid nonce\");\n        nonces[user]++;\n        \n        bytes32 digest = _hashTypedData(user, target, data, userNonce, deadline);\n        address signer = ECDSA.recover(digest, signature);\n        require(signer == user, \"Invalid signature\");\n        \n        (bool success, bytes memory result) = target.call(data);\n        require(success, \"Call failed\");\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>소셜 리커버리\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">\u002F\u002F\u002F @title RecoveryModule — EIP-7702를 통한 소셜 리커버리\ncontract RecoveryModule {\n    struct RecoveryConfig {\n        address[] guardians;\n        uint256 threshold;\n        uint256 delay;\n    }\n    \n    mapping(address =&gt; RecoveryConfig) public configs;\n    mapping(bytes32 =&gt; uint256) public recoveryTimestamps;\n    mapping(bytes32 =&gt; uint256) public approvalCounts;\n    mapping(bytes32 =&gt; mapping(address =&gt; bool)) public hasApproved;\n    \n    function setupRecovery(\n        address[] calldata guardians,\n        uint256 threshold,\n        uint256 delay\n    ) external {\n        require(guardians.length &gt;= threshold, \"Invalid threshold\");\n        require(threshold &gt;= 2, \"Min 2 guardians\");\n        configs[msg.sender] = RecoveryConfig(guardians, threshold, delay);\n    }\n    \n    function approveRecovery(\n        address account,\n        address newOwner\n    ) external {\n        RecoveryConfig memory config = configs[account];\n        require(_isGuardian(config, msg.sender), \"Not a guardian\");\n        \n        bytes32 recoveryId = keccak256(abi.encode(account, newOwner));\n        require(!hasApproved[recoveryId][msg.sender], \"Already approved\");\n        \n        hasApproved[recoveryId][msg.sender] = true;\n        approvalCounts[recoveryId]++;\n        \n        if (approvalCounts[recoveryId] &gt;= config.threshold) {\n            recoveryTimestamps[recoveryId] = block.timestamp + config.delay;\n        }\n    }\n    \n    function executeRecovery(\n        address account,\n        address newOwner\n    ) external {\n        bytes32 recoveryId = keccak256(abi.encode(account, newOwner));\n        uint256 timestamp = recoveryTimestamps[recoveryId];\n        require(timestamp &gt; 0 &amp;&amp; block.timestamp &gt;= timestamp, \"Not ready\");\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"\">지갑 통합 현황\u003C\u002Fh2>\n\u003Ch3>MetaMask\u003C\u002Fh3>\n\u003Cp>MetaMask는 버전 12.4(2025년 9월)에서 EIP-7702 지원을 추가했습니다.\u003C\u002Fp>\n\u003Ch3>Coinbase Wallet\u003C\u002Fh3>\n\u003Cp>Coinbase Wallet은 가장 적극적인 채택자로, “Smart Wallet” 기능(2025년 11월 출시)에 EIP-7702를 통합:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>자동 배치\u003C\u002Fstrong> — approve+swap 시퀀스를 자동으로 배치\u003C\u002Fli>\n\u003Cli>\u003Cstrong>가스 후원\u003C\u002Fstrong> — $1 이하 수수료 트랜잭션을 Coinbase가 후원\u003C\u002Fli>\n\u003Cli>\u003Cstrong>원클릭 DeFi\u003C\u002Fstrong> — 일반적인 DeFi 작업용 사전 구축 위임 대상\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>Rainbow, Rabby 등\u003C\u002Fh3>\n\u003Cp>Rainbow는 2026년 1월에 지원을 추가했습니다. Rabby는 type-4 트랜잭션을 지원하지만 배치 시각화 UI는 없습니다.\u003C\u002Fp>\n\u003Ch2 id=\"\">마이그레이션 가이드\u003C\u002Fh2>\n\u003Ch3>1단계: 위임 대상 배포\u003C\u002Fh3>\n\u003Ch3>2단계: 프론트엔드 업데이트\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-typescript\">async function supportsEIP7702(provider: ethers.Provider): Promise&lt;boolean&gt; {\n    try {\n        const capabilities = await provider.send(\n            \"wallet_getCapabilities\", []\n        );\n        return capabilities?.atomicBatch?.supported === true;\n    } catch {\n        return false;\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>3단계: 그레이스풀 디그레이데이션 구현\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-typescript\">async function executeSwap(tokenIn, tokenOut, amount) {\n    if (await supportsEIP7702(provider)) {\n        return executeBatchSwap(tokenIn, tokenOut, amount);\n    } else {\n        await approve(tokenIn, ROUTER, amount);\n        return swap(tokenIn, tokenOut, amount);\n    }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"\">보안 고려사항\u003C\u002Fh2>\n\u003Ch3>위임 대상 검증\u003C\u002Fh3>\n\u003Cp>위임 대상 컨트랙트는 트랜잭션 중 EOA 자산에 대한 \u003Cstrong>전체 제어권\u003C\u002Fstrong>을 가집니다.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>완화:\u003C\u002Fstrong> 감사 및 검증된 컨트랙트에만 위임하세요.\u003C\u002Fp>\n\u003Ch3>리플레이 보호\u003C\u002Fh3>\n\u003Cp>EIP-7702 인증 목록에는 리플레이 공격을 방지하는 nonce가 포함됩니다.\u003C\u002Fp>\n\u003Ch3>위임을 통한 피싱\u003C\u002Fh3>\n\u003Cp>\u003Cstrong>완화:\u003C\u002Fstrong> 지갑은 EOA가 위임하는 코드를 명확히 표시해야 합니다.\u003C\u002Fp>\n\u003Ch3>배치 실행의 재진입성\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-solidity\">bool private locked;\n\nmodifier noReentrant() {\n    require(!locked, \"Reentrant\");\n    locked = true;\n    _;\n    locked = false;\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>스토리지 충돌\u003C\u002Fh3>\n\u003Cp>EIP-7201(네임스페이스 스토리지) 사용:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-solidity\">bytes32 constant STORAGE_SLOT = keccak256(\n    abi.encode(uint256(keccak256(\"batch.executor.storage\")) - 1)\n) &amp; ~bytes32(uint256(0xff));\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"\">자주 묻는 질문\u003C\u002Fh2>\n\u003Ch3 id=\"eip-7702\">EIP-7702가 지갑 주소를 변경하나요?\u003C\u002Fh3>\n\u003Cp>아니요. EOA 주소는 그대로 유지됩니다. EIP-7702는 단일 트랜잭션 동안만 스마트 컨트랙트 기능을 부여합니다.\u003C\u002Fp>\n\u003Ch3 id=\"l2-eip-7702\">L2에서 EIP-7702를 사용할 수 있나요?\u003C\u002Fh3>\n\u003Cp>예. 모든 주요 L2(Arbitrum, Base, Optimism, zkSync)가 EIP-7702를 채택했습니다.\u003C\u002Fp>\n\u003Ch3 id=\"\">위임 대상에 버그가 있으면 어떻게 되나요?\u003C\u002Fh3>\n\u003Cp>피해는 단일 트랜잭션에 한정됩니다. 하지만 해당 트랜잭션 내에서 위임 대상은 EOA 자산에 전체 접근 권한을 가집니다.\u003C\u002Fp>\n\u003Ch3 id=\"\">하드웨어 지갑과 호환되나요?\u003C\u002Fh3>\n\u003Cp>예. Ledger는 펌웨어 2.3.0(2025년 12월)에서 지원을 추가했습니다.\u003C\u002Fp>\n\u003Ch3 id=\"eip-7702\">EIP-7702로 얼마나 가스를 절약하나요?\u003C\u002Fh3>\n\u003Cp>일반적인 approve+swap 플로우에서 약 \u003Cstrong>40-50%\u003C\u002Fstrong> 가스 절약. 복잡한 멀티스텝 DeFi 작업에서는 60-70%에 달할 수 있습니다.\u003C\u002Fp>\n","ko","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:43.377765Z","EIP-7702 배치 트랜잭션, 가스 후원, 소셜 리커버리 구현 방법. 코드 예제, 지갑 지원 현황, 보안 가이드.","EIP-7702",null,"index, follow",[21,26,30],{"id":22,"name":23,"slug":24,"created_at":25},"c0000000-0000-0000-0000-000000000013","Security","security","2026-03-28T10:44:21.513630Z",{"id":27,"name":28,"slug":29,"created_at":25},"c0000000-0000-0000-0000-000000000014","Solidity","solidity",{"id":31,"name":32,"slug":33,"created_at":25},"c0000000-0000-0000-0000-000000000009","Web3","web3","블록체인",[36,43,49],{"id":37,"title":38,"slug":39,"excerpt":40,"locale":12,"category_name":41,"published_at":42},"d0000000-0000-0000-0000-000000000674","2026년, Bali가 동남아시아의 임팩트 테크 허브가 되고 있는 이유","bali-2026-dongnamasia-impaekteu-tekeu-heobeu-iyu","Bali는 동남아시아 스타트업 생태계에서 16위를 차지하고 있습니다. Web3 빌더, AI 지속가능성 스타트업, 에코 여행 테크 기업이 집중되면서, 이 섬은 지역 임팩트 테크의 수도로 자리매김하고 있습니다.","엔지니어링","2026-03-28T10:44:49.294484Z",{"id":44,"title":45,"slug":46,"excerpt":47,"locale":12,"category_name":41,"published_at":48},"d0000000-0000-0000-0000-000000000673","ASEAN 데이터 보호 패치워크: 개발자를 위한 컴플라이언스 체크리스트","asean-deiteo-boho-paechiwokeu-gaebaljaleul-wihan-keompeullaieonseuchekeuriseuteu","7개 ASEAN 국가가 포괄적인 데이터 보호법을 시행하고 있으며, 각각 다른 동의 모델, 현지화 요건, 벌칙 구조를 가지고 있습니다. 다중 국가 애플리케이션을 구축하는 개발자를 위한 실용적인 컴플라이언스 체크리스트입니다.","2026-03-28T10:44:49.286400Z",{"id":50,"title":51,"slug":52,"excerpt":53,"locale":12,"category_name":41,"published_at":54},"d0000000-0000-0000-0000-000000000672","Indonesia 290억 달러 디지털 전환: 소프트웨어 기업을 위한 기회","indonesia-290eok-dallleo-dijiteol-jeonhwan-sopeuteuweo-gieopui-gihoe","Indonesia IT 서비스 시장은 2026년 290.3억 달러에 달할 것으로 예상되며, 이는 2025년 243.7억 달러에서 증가한 수치입니다. 클라우드 인프라, AI, 전자상거래, 데이터센터가 동남아시아에서 가장 빠른 성장을 주도하고 있습니다.","2026-03-28T10:44:49.265609Z",{"id":13,"name":56,"slug":57,"bio":58,"photo_url":18,"linkedin":18,"role":59,"created_at":60,"updated_at":60},"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"]