EIP-7702 في الممارسة العملية: بناء تدفقات الحساب الذكي بعد Pectra
Engineering Team
ما يُمكّنه EIP-7702
EIP-7702، المُفعّل مع ترقية Pectra لـ Ethereum في مارس 2025، يُقدم نوع معاملة جديداً يسمح لأي حساب ملكية خارجية (EOA) بتعيين مُحدد تفويض — مؤشر إلى عقد ذكي يتبنى EOA كوده مؤقتاً طوال مدة المعاملة. هذا يعني أن عنوان محفظة MetaMask الحالي يمكنه تنفيذ منطق عقد ذكي تعسفي دون نشر محفظة عقد جديدة أو تغيير عنوانك.
هذا هو أهم تحسين لتجربة المستخدم في تاريخ Ethereum.
EIP-7702 مقابل ERC-4337: متى تستخدم أيهما
| الميزة | EIP-7702 | ERC-4337 |
|---|---|---|
| المستوى | البروتوكول (نوع tx جديد) | التطبيق (عقد ذكي) |
| نوع الحساب | ترقية EOAs الموجودة | يتطلب محفظة عقد ذكي جديدة |
| العنوان | يحتفظ بعنوان EOA الحالي | عنوان جديد (مضاد للواقع) |
| الاستمرارية | تفويض لكل معاملة | عقد ذكي دائم |
| يتطلب Bundler | لا (تدفق tx قياسي) | نعم (mempool منفصل) |
| عبء الغاز | ~20,000 غاز للتفويض | ~42,000 غاز لتحقق UserOp |
| المحافظ المدعومة | MetaMask, Coinbase Wallet, Rainbow | متخصصة (Safe, ZeroDev, Biconomy) |
| الأفضل لـ | ترقية المستخدمين الحاليين | مستخدمون جدد، منطق حساب معقد |
إطار القرار
استخدم EIP-7702 عندما:
- لدى مستخدميك محافظ EOA بالفعل
- تحتاج معاملات مجمّعة أو رعاية غاز
- تريد الحد الأدنى من تعقيد التكامل
استخدم ERC-4337 عندما:
- تبني محفظة جديدة أو تُدمج مستخدمين جدداً
- تحتاج منطق حساب مستمر
- تحتاج ميزات متقدمة مثل الوحدات أو الإضافات أو الأوصياء
أمثلة على الكود
المعاملات المجمّعة
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
/// @title BatchExecutor — هدف تفويض EIP-7702 للاستدعاءات المجمّعة
contract BatchExecutor {
struct Call {
address target;
uint256 value;
bytes data;
}
function executeBatch(Call[] calldata calls) external payable {
for (uint256 i = 0; i < calls.length; i++) {
(bool success, bytes memory result) = calls[i].target.call{
value: calls[i].value
}(calls[i].data);
if (!success) {
assembly {
revert(add(result, 32), mload(result))
}
}
}
}
}
الاستخدام من جانب العميل مع ethers.js v6:
import { ethers } from "ethers";
const batchTx = {
type: 4,
to: userAddress,
authorizationList: [{
chainId: 1,
address: BATCH_EXECUTOR_ADDRESS,
nonce: await provider.getTransactionCount(userAddress),
yParity: 0, r: "0x...", s: "0x..."
}],
data: batchExecutorInterface.encodeFunctionData("executeBatch", [[
{
target: USDC_ADDRESS,
value: 0,
data: usdcInterface.encodeFunctionData("approve", [
UNISWAP_ROUTER, ethers.parseUnits("1000", 6)
])
},
{
target: UNISWAP_ROUTER,
value: 0,
data: routerInterface.encodeFunctionData("exactInputSingle", [{
tokenIn: USDC_ADDRESS,
tokenOut: WETH_ADDRESS,
fee: 3000,
recipient: userAddress,
amountIn: ethers.parseUnits("1000", 6),
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
}])
}
]])
};
const tx = await signer.sendTransaction(batchTx);
رعاية الغاز
/// @title SponsoredExecutor — رعاية الغاز عبر EIP-7702
contract SponsoredExecutor {
mapping(address => uint256) public nonces;
function sponsoredExecute(
address user,
address target,
bytes calldata data,
uint256 userNonce,
uint256 deadline,
bytes calldata signature
) external {
require(block.timestamp <= deadline, "Expired");
require(nonces[user] == userNonce, "Invalid nonce");
nonces[user]++;
bytes32 digest = _hashTypedData(user, target, data, userNonce, deadline);
address signer = ECDSA.recover(digest, signature);
require(signer == user, "Invalid signature");
(bool success, bytes memory result) = target.call(data);
require(success, "Call failed");
}
}
الاسترداد الاجتماعي
/// @title RecoveryModule — الاسترداد الاجتماعي عبر EIP-7702
contract RecoveryModule {
struct RecoveryConfig {
address[] guardians;
uint256 threshold;
uint256 delay;
}
mapping(address => RecoveryConfig) public configs;
mapping(bytes32 => uint256) public recoveryTimestamps;
mapping(bytes32 => uint256) public approvalCounts;
mapping(bytes32 => mapping(address => bool)) public hasApproved;
function setupRecovery(
address[] calldata guardians,
uint256 threshold,
uint256 delay
) external {
require(guardians.length >= threshold, "Invalid threshold");
require(threshold >= 2, "Min 2 guardians");
configs[msg.sender] = RecoveryConfig(guardians, threshold, delay);
}
function approveRecovery(
address account,
address newOwner
) external {
RecoveryConfig memory config = configs[account];
require(_isGuardian(config, msg.sender), "Not a guardian");
bytes32 recoveryId = keccak256(abi.encode(account, newOwner));
require(!hasApproved[recoveryId][msg.sender], "Already approved");
hasApproved[recoveryId][msg.sender] = true;
approvalCounts[recoveryId]++;
if (approvalCounts[recoveryId] >= config.threshold) {
recoveryTimestamps[recoveryId] = block.timestamp + config.delay;
}
}
function executeRecovery(
address account,
address newOwner
) external {
bytes32 recoveryId = keccak256(abi.encode(account, newOwner));
uint256 timestamp = recoveryTimestamps[recoveryId];
require(timestamp > 0 && block.timestamp >= timestamp, "Not ready");
}
}
حالة تكامل المحافظ
MetaMask
أضافت MetaMask دعم EIP-7702 في الإصدار 12.4 (سبتمبر 2025).
Coinbase Wallet
Coinbase Wallet هو المتبني الأكثر حماساً، حيث دمج EIP-7702 في ميزة “Smart Wallet” (أُطلقت في نوفمبر 2025):
- التجميع التلقائي — المحفظة تُجمّع تلقائياً تسلسلات approve+swap
- رعاية الغاز — Coinbase ترعى الغاز للمعاملات التي تقل رسومها عن $1
- DeFi بنقرة واحدة — أهداف تفويض مبنية مسبقاً لعمليات DeFi الشائعة
Rainbow وRabby وغيرها
أضافت Rainbow الدعم في يناير 2026. Rabby تدعم معاملات type-4 لكن بدون واجهة تصور التجميع.
دليل الترحيل
الخطوة 1: نشر أهداف التفويض
الخطوة 2: تحديث الواجهة الأمامية
async function supportsEIP7702(provider: ethers.Provider): Promise<boolean> {
try {
const capabilities = await provider.send(
"wallet_getCapabilities", []
);
return capabilities?.atomicBatch?.supported === true;
} catch {
return false;
}
}
الخطوة 3: تنفيذ التدهور الأنيق
async function executeSwap(tokenIn, tokenOut, amount) {
if (await supportsEIP7702(provider)) {
return executeBatchSwap(tokenIn, tokenOut, amount);
} else {
await approve(tokenIn, ROUTER, amount);
return swap(tokenIn, tokenOut, amount);
}
}
اعتبارات الأمان
التحقق من هدف التفويض
عقد هدف التفويض له سيطرة كاملة على أصول EOA أثناء المعاملة.
التخفيف: فوّض فقط إلى عقود مُدققة ومُتحقق منها.
حماية إعادة التشغيل
تتضمن قوائم التفويض EIP-7702 رقم nonce لمنع هجمات إعادة التشغيل.
التصيد عبر التفويض
التخفيف: يجب على المحافظ عرض الكود الذي يُفوّض إليه EOA بوضوح.
إعادة الدخول في التنفيذ المجمّع
bool private locked;
modifier noReentrant() {
require(!locked, "Reentrant");
locked = true;
_;
locked = false;
}
تصادم التخزين
استخدام EIP-7201 (تخزين مسمى):
bytes32 constant STORAGE_SLOT = keccak256(
abi.encode(uint256(keccak256("batch.executor.storage")) - 1)
) & ~bytes32(uint256(0xff));
الأسئلة الشائعة
هل يُغيّر EIP-7702 عنوان محفظتي؟
لا. يبقى عنوان EOA كما هو. يمنح EIP-7702 عنوانك مؤقتاً قدرات العقد الذكي لمدة معاملة واحدة.
هل يمكنني استخدام EIP-7702 على L2؟
نعم. جميع L2 الرئيسية (Arbitrum, Base, Optimism, zkSync) تبنت EIP-7702.
ماذا يحدث إذا كان هدف التفويض به خطأ؟
يقتصر الضرر على معاملة واحدة. لكن ضمن تلك المعاملة، يمتلك الهدف وصولاً كاملاً لأصول EOA.
هل EIP-7702 متوافق مع محافظ الأجهزة؟
نعم. أضافت Ledger الدعم في البرنامج الثابت 2.3.0 (ديسمبر 2025).
كم من الغاز يوفر EIP-7702؟
لتدفق approve+swap نموذجي، يوفر EIP-7702 حوالي 40-50% من الغاز. لعمليات DeFi المعقدة متعددة الخطوات، يمكن أن تصل الوفورات إلى 60-70%.