Розробка системи unified accounts
Стикалися з ситуацією, коли для роботи в різних блокчейнах доводиться тримати десяток гаманців і вручну перекидати ліквідність? Наша команда інженерів вирішує цю проблему за допомогою системи unified accounts — єдиного акаунту, який працює на всіх мережах. Це не просто зручна абстракція, а архітектурне рішення, що об'єднує детерміноване розгортання контрактів, кросчейн-синхронізацію та інтент-орієнтоване виконання. Давайте розберемо, як це влаштовано на рівні смарт-контрактів та інфраструктури. Unified accounts еволюціонують від мультичейн-підходу (багато гаманців) до chain-abstracted (один гаманець, прозора мультичейн). Задача нетривіальна: реалізувати її правильно означає вирішити кілька незалежних технічних проблем одночасно. Досвід нашої команди в кросчейн-розробці — понад 10 успішних проєктів.
Як unified account вирішує проблему фрагментації ліквідності?
При роботі з кількома L1/L2 ланцюгами (Ethereum, Polygon, Arbitrum, Optimism, Base) користувач змушений тримати кошти на кожній мережі окремо. Unified account використовує CREATE2 для детермінованої адреси та синхронізує стан через захищений bridge. Це дозволяє мати єдиний логічний баланс, який автоматично доступний на всіх ланцюгах без ручних переказів. Порівняйте: у традиційній схемі для stake 100 USDC в протоколі на Arbitrum потрібно спочатку перевести USDC з Ethereum — це мінімум дві транзакції та 15 хвилин очікування. У unified account користувач вказує намір, а система сама маршрутизує ліквідність через оптимальний bridge за пару кліків. Гарантуємо, що економія на газі та часі досягає 40–60% на типових операціях.
Що таке unified account на технічному рівні?
Наївна реалізація: смарт-контракт на кожному підтримуваному ланцюгу з однаковою адресою (через CREATE2), синхронізація стану через bridge. Це працює, але створює складність: стан розрізнений, синхронізація має затримку та вартість.
Просунута реалізація розділяє чотири шари: Identity, Intent, Execution, Settlement. Кожен шар вирішує своє завдання, а разом вони забезпечують безшовний кросчейн-досвід.
| Шар | Завдання |
|---|---|
| Identity | Визначає користувача на всіх ланцюгах (одна адреса) |
| Intent | Приймає намір користувача (що зробити) |
| Execution | Вибирає оптимальний ланцюг та маршрут виконання |
| Settlement | Проводить остаточний розрахунок та синхронізацію |
Детерміновані адреси через CREATE2
Перший крок — одна й та сама адреса на всіх EVM ланцюгах:
// Factory контракт з однаковою адресою на всіх ланцюгах
contract AccountFactory {
function deployAccount(
bytes32 salt,
bytes calldata initCode
) external returns (address account) {
// CREATE2: адреса залежить тільки від factory address + salt + initCode
// Якщо factory задеплоєно через keyless deployment (одна адреса на всіх EVM),
// то і Account матиме однакову адресу
assembly {
account := create2(0, add(initCode, 32), mload(initCode), salt)
}
if (account == address(0)) revert DeploymentFailed();
}
function predictAddress(
bytes32 salt,
bytes32 initCodeHash
) external view returns (address) {
return address(uint160(uint256(keccak256(abi.encodePacked(
bytes1(0xff),
address(this),
salt,
initCodeHash
)))));
}
}
Keyless deployment (через ERC-2470 Singleton Factory або Nick's method) забезпечує однакову адресу factory на всіх EVM ланцюгах. Отже — один і той самий salt + initCode = одна адреса account на всіх ланцюгах. ERC-2470: Singleton Factory — це стандартний спосіб розгортання контрактів з однаковою адресою.
Cross-chain state synchronization
Другий крок — синхронізація даних акаунту між ланцюгами. Наприклад: користувач оновлює список owners на Ethereum, це має відобразитися на Polygon.
Паттерн: Primary chain + синхронізація через bridge:
contract UnifiedAccountPrimary {
// Primary state зберігається на "home" ланцюгу
mapping(address => bool) public owners;
uint256 public nonce;
// Синхронізація змін на інші ланцюги
function addOwnerAndSync(
address newOwner,
uint64[] calldata targetChains,
address[] calldata targetAccounts
) external onlyOwner {
owners[newOwner] = true;
// Відправляємо update через bridge (CCIP, Axelar, LayerZero)
for (uint i = 0; i < targetChains.length; i++) {
bytes memory payload = abi.encode(
"ADD_OWNER",
newOwner,
++nonce
);
bridge.sendMessage(targetChains[i], targetAccounts[i], payload);
}
emit OwnerAdded(newOwner);
}
}
contract UnifiedAccountReplica {
// Репліка отримує оновлення від Primary
uint256 public lastSyncedNonce;
function receiveSync(
bytes calldata payload,
bytes32 originMessageId
) external onlyBridge {
(string memory action, address target, uint256 nonce) =
abi.decode(payload, (string, address, uint256));
// Захист від replay: nonce має бути наступним
require(nonce == lastSyncedNonce + 1, "Invalid nonce");
lastSyncedNonce = nonce;
if (keccak256(bytes(action)) == keccak256(bytes("ADD_OWNER"))) {
_addOwner(target);
}
}
}
Intent-based execution
Unified account приймає наміри користувача, а не конкретні транзакції. Користувач каже «хочу stake 100 USDC в протоколі X» — система сама вирішує звідки взяти USDC та на якому ланцюгу виконати:
interface UserIntent {
action: "stake" | "swap" | "transfer" | "borrow";
targetProtocol: string;
targetChain?: number; // опціонально — якщо не вказано, система обирає
inputToken: string;
inputAmount: string;
outputToken?: string;
minOutputAmount?: string;
deadline?: number;
}
class IntentRouter {
async resolveIntent(intent: UserIntent, userProfile: UserProfile): Promise<ExecutionPlan> {
// 1. Знаходимо найкращий ланцюг для виконання
const targetChain = intent.targetChain ||
await this.findOptimalChain(intent, userProfile);
// 2. Визначаємо звідки взяти кошти
const fundingSource = await this.findBestFundingSource(
intent.inputToken,
intent.inputAmount,
userProfile.balances,
targetChain
);
// 3. Будуємо execution plan
const steps: ExecutionStep[] = [];
if (fundingSource.chainId !== targetChain) {
// Потрібен bridge
steps.push({
type: "bridge",
fromChain: fundingSource.chainId,
toChain: targetChain,
token: intent.inputToken,
amount: intent.inputAmount,
bridgeProtocol: await this.selectBridge(fundingSource.chainId, targetChain),
});
}
// Основна дія
steps.push({
type: intent.action,
chainId: targetChain,
protocol: intent.targetProtocol,
...
});
return {
steps,
estimatedGas: await this.estimateTotalGas(steps),
estimatedTime: this.estimateTime(steps),
};
}
}
Gasless cross-chain операції
Для повного UX unified account — користувач не повинен думати про газ. Система абстрагує це:
// Користувач платить в USDC, система конвертує в нативні токени
async function executeGasless(
intent: UserIntent,
feeToken: "USDC" | "USDT" | string
): Promise<string> {
const plan = await intentRouter.resolveIntent(intent, userProfile);
// Розраховуємо загальну вартість у feeToken
const totalCostInFeeToken = await priceOracle.convertGasCost(
plan.estimatedGas,
plan.steps.map(s => s.chainId),
feeToken
);
// Отримуємо UserOperation зі sponsored газом
const userOp = await buildSponsordUserOp(plan, feeToken, totalCostInFeeToken);
// Підписуємо один раз на вихідному ланцюгу
const signedOp = await userAccount.signUserOperation(userOp);
// Executor relay виконує всі steps
return relayer.submitIntent(signedOp);
}
Account abstraction як фундамент
Unified accounts нативно будуються на ERC-4337: Smart account замість EOA на кожному ланцюгу, UserOperations як одиниця intent, Bundler як executor, Paymaster як gas abstraction layer. ZeroDev Kernel, Safe з модулями або кастомна реалізація — вибір залежить від необхідної гнучкості.
Проблема атомарності
Критичне питання: що відбувається, якщо крок 1 (bridge) пройшов успішно, а крок 2 (stake на цільовому ланцюгу) завершився помилкою? Варіанти: Optimistic execution (продовжуємо, записуємо pending state, retry при невдачі), Atomic through escrow (кошти в escrow контракті до підтвердження фінального кроку), Two-phase commit (prepare → commit/rollback). На практиці більшість систем використовують optimistic з retry механізмом і ручним fallback (кошти залишаються на цільовому ланцюгу, якщо дія не виконана).
Порівняння підходів до кросчейн-комунікації
| Протокол | Тип | Затримка | Безпека |
|---|---|---|---|
| LayerZero | light oracle + relayer | ~1 хвилина | залежить від оракула |
| Axelar | validator set | ~5 хвилин | 2/3 валідаторів |
| CCIP (Chainlink) | децентралізовані оракули | ~10 хвилин | перевірений аудитом |
Що входить у роботу над unified account
- Аналіз цільових мереж і вимог до синхронізації.
- Проєктування архітектури identity та intent шарів.
- Розгортання factory контрактів через keyless deployment.
- Інтеграція bridge-протоколу та налаштування синхронізації.
- Реалізація intent router з підтримкою gas abstraction.
- Інтеграція frontend SDK.
- Розгортання на testnet та проведення аудиту.
- Deploy на mainnet та запуск.
Строки
- Базова unified identity (CREATE2 однакові адреси, базовий sync): 4-6 тижнів
- Intent routing + cross-chain execution: 6-8 тижнів
- Gas abstraction + feeToken: 3-4 тижні
- Production hardening + security audit: 6-8 тижнів
- Всього: 4-6 місяців
Бюджет на розробку unified account розраховується індивідуально. Зв'яжіться з нами, надайте специфікацію використовуваних мереж і вимоги до синхронізації — ми підготуємо індивідуальну пропозицію з точними строками. Замовте консультацію, щоб оцінити ваш проєкт та отримати професійну розробку під ключ.







