הצוות שלנו מביא ניסיון של 5+ שנים בפיתוח חוזים חכמים והשיק בהצלחה 20+ חוזים ברשתות מרובות. אנו מתמחים בפיתוח חוזי multicall לפעולות אצווה — הפחתת בקשות RPC בעד 90% ועלויות גז בעד 70%. קריאת המצב של עשרה חוזים בנפרד פירושה עשר בקשות RPC, עשר נסיעות הלוך ושוב לצומת. בנקודות קצה ציבוריות, זמן הטעינה של dApp נמתח ל-2–5 שניות. פעולות אצווה של Multicall פותרות זאת: לקריאות — איגום בקשות לקריאת RPC אחת, לכתיבות — פעולות on-chain מרובות בעסקה אחת. עומס הצומת יורד ב-90%, וחוויית המשתמש הופכת למגיבה.
הניסיון שלנו: 5+ שנים ב-Web3, פרסנו למעלה מ-20 חוזים חכמים לפרוטוקולי DeFi, שווקי NFT וגשרי cross-chain. כל החוזים עוברים ביקורות אבטחה, המבטיחות עמידה בשיטות העבודה המומלצות. הביקורות שלנו תפסו 100% מהפגיעויות הקריטיות לפני הפריסה.
כיצד Multicall3 מפחית את עומס ה-RPC
Multicall3 בכתובת 0xcA11bde05977b3631167028862bE2a173976CA11 פרוס על 50+ רשתות. הוא מקבל מערך של (address target, bytes callData), מבצע את כל הקריאות ומחזיר תוצאות. עבור בקשות read-only, נעשה שימוש ב-import { useReadContracts } from 'wagmi'; const { data } = useReadContracts({ contracts: [ { address: token1, abi: erc20Abi, functionName: 'balanceOf', args: [user] }, { address: token2, abi: erc20Abi, functionName: 'balanceOf', args: [user] }, { address: pool, abi: poolAbi, functionName: 'getReserves' }, { address: oracle, abi: oracleAbi, functionName: 'latestAnswer' }, ] }); // один RPC запрос вместо четырёх , וכל הקריאות מבוצעות בבקשת RPC אחת.
שימוש טיפוסי דרך wagmi/viem:
import { useReadContracts } from 'wagmi';
const { data } = useReadContracts({
contracts: [
{
address: token1,
abi: erc20Abi,
functionName: 'balanceOf',
args: [user],
},
{
address: token2,
abi: erc20Abi,
functionName: 'balanceOf',
args: [user],
},
{
address: pool,
abi: poolAbi,
functionName: 'getReserves',
},
{
address: oracle,
abi: oracleAbi,
functionName: 'latestAnswer',
},
],
});
// один RPC запрос вместо четырёхWagmi משתמש ב-Multicall3 מתחת למכסה המנוע: כל הקריאות ב-useReadContracts אחד מתקפלות ל-Multicall.sol אחד. אם הרשת אינה תומכת ב-Multicall3, wagmi נופל ל-abstract contract Multicall { function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { (bool success, bytes memory result) = address(this).delegatecall(data[i]); require(success, _getRevertMsg(result)); results[i] = result; } } } מקבילים, מה שעדיין חוסך זמן. חיסכון בגז עד 70% בפעולות אצווה.
מתי חוזה מותאם אישית מנצח
Multicall3 אינו מאחסן מצב, אינו בודק הרשאות ואינו תומך ב-ETH מקורי לקריאות בודדות. עבור פעולות כתיבה עם לוגיקה מותאמת אישית, אנו כותבים חוזה משלנו.
תבנית ה-self-multicall — חוזה הקורא לעצמו דרך פונקציות מרובות בעסקה אחת. OpenZeppelin Multicall מיישם זאת דרך contract AtomicBatcher { struct Step { address target; bytes callData; uint256 value; uint256 minReturnValue; // проверка результата } function executeBatch(Step[] calldata steps) external payable returns (bytes[] memory results) { results = new bytes[](steps.length); for (uint256 i = 0; i < steps.length; i++) { (bool success, bytes memory result) = steps[i].target.call{ value: steps[i].value }(steps[i].callData); require(success, string(abi.encodePacked("Step ", i, " failed"))); if (steps[i].minReturnValue > 0) { uint256 returnValue = abi.decode(result, (uint256)); require(returnValue >= steps[i].minReturnValue, "Slippage exceeded"); } results[i] = result; } // вернуть незатраченный ETH if (address(this).balance > 0) { (bool sent,) = msg.sender.call{value: address(this).balance}(""); require(sent); } } } :
abstract contract Multicall {
function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {
results = new bytes[](data.length);
for (uint256 i = 0; i < data.length; i++) {
(bool success, bytes memory result) = address(this).delegatecall(data[i]);
require(success, _getRevertMsg(result));
results[i] = result;
}
}
}delegatecall על address(this) — החוזה קורא לפונקציות שלו בשם ה-msg.sender המקורי. זה מאפשר ביצוע approve + deposit בקריאה אחת שבה שני השלבים רואים את אותו msg.sender.
אזהרת אבטחה קריטית
delegatecall על address(this) עם נתונים שסופקו על ידי המשתמש הוא פגיעות פוטנציאלית. אם החוזה אינו מבודד מפונקציות מוסמכות, תוקף יכול ליצור נתונים הקוראים ל-transferOwnership. OpenZeppelin מזהיר: אל תשתמשו בתבנית זו עם חוזים שבהם ההרשאה תלויה ב-msg.sender ללא בדיקות נוספות. בפיתוח שלנו, אנו תמיד מיישמים בדיקות בקרת גישה בכל שלב: כל פונקציה הנגישה דרך self-multicall מאמתת msg.sender.
כיצד ליישם פעולות אטומיות מרובות-שלבים
עבור פעולות DeFi מורכבות (flash loan → swap → repay), יש צורך בחוזה עם מצב ביניים שמחזיר הכל אם שלב כלשהו נכשל:
contract AtomicBatcher {
struct Step {
address target;
bytes callData;
uint256 value;
uint256 minReturnValue; // проверка результата
}
function executeBatch(Step[] calldata steps) external payable returns (bytes[] memory results) {
results = new bytes[](steps.length);
for (uint256 i = 0; i < steps.length; i++) {
(bool success, bytes memory result) = steps[i].target.call{ value: steps[i].value }(steps[i].callData);
require(success, string(abi.encodePacked("Step ", i, " failed")));
if (steps[i].minReturnValue > 0) {
uint256 returnValue = abi.decode(result, (uint256));
require(returnValue >= steps[i].minReturnValue, "Slippage exceeded");
}
results[i] = result;
}
// вернуть незатраченный ETH
if (address(this).balance > 0) {
(bool sent,) = msg.sender.call{value: address(this).balance}("");
require(sent);
}
}
}minReturnValue — הגנה מובנית מפני החלקה בכל שלב. אם swap מחזיר פחות מהמינימום, כל העסקה מתבטלת.
השוואה: Multicall3 מול חוזה מותאם אישית
| תרחיש | Multicall3 | מותאם אישית |
|---|---|---|
| איגום בקשות קריאה | מספיק | מוגזם |
| העברות ERC-20 מרובות | מספיק | מוגזם |
| Approve + פעולת פרוטוקול (אסימון יחיד) | מספיק | מספיק |
| Flash loan + ארביטראז' + החזר | לא מתאים | נדרש |
| פעולות מותנות (אם תוצאת שלב X > Y) | לא מתאים | נדרש |
| חלוקת ETH עם סכומים שונים | לא מתאים | נדרש |
עבור פעולות DeFi מורכבות מרובות-שלבים, חוזה מותאם אישית עולה על Multicall3 בעד פי 3 ביעילות גז ובגמישות.
הערכות זמן פיתוח
| מורכבות | משך משוער | אופטימיזציית גז |
|---|---|---|
| פשוט (איגום קריאות) | יום אחד | Multicall3 מספיק |
| בינוני (אצוות כתיבה עם בדיקות) | 2-3 ימים | מותאם חלקית |
| מורכב (DeFi מרובה-שלבים) | 3-5 ימים | מותאם לחלוטין |
מה כלול בעבודה
- ניתוח דרישות ועיצוב ארכיטקטורה.
- כתיבת חוזה Solidity ובדיקות (Foundry, Tenderly).
- ביקורת אבטחה (Slither, Mythril, סקירה ידנית).
- פריסה ואימות קוד ב-Etherscan.
- תיעוד (Natspec, README) וגישה למאגר.
- חודש אחד של ניהול תקלות ותמיכה.
- הכשרת צוות הלקוח לשימוש בחוזה.
תהליך פיתוח שלב-אחר-שלב
- ניתוח דרישות — הגדרת מקרי שימוש, דרישות אבטחה ומגבלות גז.
- עיצוב ארכיטקטורה — בחירה בין Multicall3 לחוזה מותאם אישית, עיצוב מבני נתונים.
- כתיבת קוד — יישום חוזה Solidity עם אופטימיזציית גז ואימותים.
- בדיקות — בדיקות יחידה עם Foundry, בדיקות עומס ב-Tenderly, סימולציה.
- ביקורת אבטחה — ניתוח סטטי (Slither, Mythril), סקירה ידנית על ידי מפתחים מנוסים.
- פריסה ואימות — פריסה לרשת היעד, אימות קוד ב-Etherscan.
- תיעוד ותמיכה — Natspec, README, חודש אחד של ניהול תקלות.
אנו מציעים פיתוח חוזי multicall במפתח מלא, כולל ביקורת ופריסה. הזמינו פיתוח — המהנדסים שלנו יעריכו את הפרויקט שלכם ביום אחד. צרו קשר לייעוץ חינם דרך Telegram או דוא"ל. ניסיון — 5+ שנים, למעלה מ-20 השקות מוצלחות. אנו מבטיחים קוד נקי ומעבר ביקורות חיצוניות.







