Loading...
Loading...


0x).0xto: "0x8ba1f109551bD432803012645Hac136c"null или пустое значениеvalue: "1000000000000000000" // 1 ETH в wei// Примеры конвертацииconst oneEther = ethers.utils.parseEther('1.0'); // "1000000000000000000"const tenGwei = ethers.utils.parseUnits('10', 'gwei'); // "10000000000"const fiveWei = '5'; // "5"data: "0xa9059cbb000000000000000000000000..."0xa9059cbb // Первые 4 байта - selector функции transfer(address,uint256)000000000000000000000000742d35cc6634c0532925a3b8d4c9db96590c6c87 // Адрес получателя0000000000000000000000000000000000000000000000000de0b6b3a7640000 // Сумма в wei0x): простой перевод ETHgasLimit: 21000// Оценка газа для операцииconst gasEstimate = await contract.estimateGas.transfer(recipient, amount);const gasLimit = gasEstimate.mul(120).div(100); // +20% запас безопасностиgasPrice: "20000000000" // 20 gweinonce: 42// Получение текущего nonceconst nonce = await provider.getTransactionCount(wallet.address, 'pending');
// Для параллельных транзакцийconst transactions = [ { ...txData, nonce: nonce }, // Будет выполнена первой { ...txData, nonce: nonce + 1 }, // Будет выполнена второй { ...txData, nonce: nonce + 2 }, // Будет выполнена третьей];v: 27r: "0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608"s: "0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada"// Подписание транзакцииconst signedTx = await wallet.signTransaction(transaction);
// Восстановление адреса отправителя из подписиconst recoveredAddress = ethers.utils.recoverAddress( ethers.utils.keccak256(serializedTx), { v, r, s },);{ type: 2, // Тип транзакции maxFeePerGas: "30000000000", // Максимальная цена газа maxPriorityFeePerGas: "2000000000", // Чаевые для майнеров // ... остальные поля}// Оригинальный формат транзакций{ nonce: 42, gasPrice: "20000000000", // Фиксированная цена газа gasLimit: 21000, to: "0x742d35Cc6634C0532925a3b8D4C9db96590c6C87", value: "1000000000000000000", data: "0x", v: 27, r: "0x...", s: "0x..."}gasPrice × gasUsed// Транзакции с access list{ type: 1, chainId: 1, // Ethereum Mainnet nonce: 42, gasPrice: "20000000000", gasLimit: 100000, to: "0x...", value: "0", data: "0x...", accessList: [ { address: "0x1234567890123456789012345678901234567890", storageKeys: [ "0x0000000000000000000000000000000000000000000000000000000000000001" ] } ]}{ type: 2, chainId: 1, nonce: 42, maxFeePerGas: "30000000000", // 30 gwei максимум maxPriorityFeePerGas: "2000000000", // 2 gwei чаевых gasLimit: 21000, to: "0x742d35Cc6634C0532925a3b8D4C9db96590c6C87", value: "1000000000000000000", data: "0x", accessList: [] // Опционально}// Расчет итоговой стоимостиconst actualFee = Math.min(maxFeePerGas, baseFee + maxPriorityFeePerGas);const totalCost = actualFee * gasUsed;const refund = (maxFeePerGas - actualFee) * gasUsed; // Возврат излишкаХарактеристика | Legacy (Type 0) | EIP-2930 (Type 1) | EIP-1559 (Type 2) |
|---|---|---|---|
Ценообразование | gasPrice | gasPrice | baseFee + priority |
Предсказуемость | Низкая | Средняя | Высокая |
Access List | ❌ | ✅ | ✅ |
Сжигание ETH | ❌ | ❌ | ✅ (baseFee) |
Рекомендуется | ❌ | Редко | ✅ |
// Современный EIP-1559 перевод ETH{ type: 2, // Тип транзакции EIP-1559 chainId: 1, // Ethereum Mainnet from: "0x742d35Cc6634C0532925a3b8D4C9db96590c6C87", // Адрес отправителя to: "0x8ba1f109551bD432803012645Hac136c", // Адрес получателя value: "1000000000000000000", // 1 ETH = 1 * 10^18 wei gasLimit: 21000, // Всегда 21,000 для простых переводов maxFeePerGas: "30000000000", // 30 gwei - максимальная готовность платить maxPriorityFeePerGas: "2000000000", // 2 gwei - чаевые валидаторам nonce: 42, // Порядковый номер транзакции data: "0x" // Пустые данные для простого перевода}
// Legacy перевод (старый формат){ from: "0x742d35Cc6634C0532925a3b8D4C9db96590c6C87", to: "0x8ba1f109551bD432803012645Hac136c", value: "1000000000000000000", // 1 ETH в wei gasLimit: 21000, // Фиксированное значение для ETH gasPrice: "20000000000", // 20 gwei - фиксированная цена nonce: 42, // Счетчик транзакций от адреса data: "0x" // Пустое поле для простого перевода}// Вызов функции transfer ERC-20 токена (современный EIP-1559){ type: 2, // EIP-1559 транзакция chainId: 1, // Ethereum Mainnet from: "0x742d35Cc6634C0532925a3b8D4C9db96590c6C87", // Отправитель to: "0x1234567890123456789012345678901234567890", // Адрес ERC-20 контракта value: "0", // Не отправляем ETH контракту gasLimit: 65000, // Примерно 65k газа для ERC-20 transfer maxFeePerGas: "25000000000", // 25 gwei максимум maxPriorityFeePerGas: "2000000000", // 2 gwei чаевых nonce: 43, // Следующий номер после предыдущей транзакции data: "0xa9059cbb" + // Function selector для transfer(address,uint256) "000000000000000000000000742d35cc6634c0532925a3b8d4c9db96590c6c87" + // Получатель (дополнен до 32 байт) "0000000000000000000000000000000000000000000000000de0b6b3a7640000" // Сумма: 1 токен (18 decimals)}
// Расшифровка поля data:// 0xa9059cbb = первые 4 байта keccak256("transfer(address,uint256)")// Следующие 32 байта = адрес получателя токенов// Последние 32 байта = количество токенов для перевода// Создание нового смарт-контракта (EIP-1559){ type: 2, // Современный тип транзакции chainId: 1, // Ethereum Mainnet from: "0x742d35Cc6634C0532925a3b8D4C9db96590c6C87", // Создатель контракта to: null, // NULL = создание нового контракта value: "0", // Обычно не отправляем ETH при создании gasLimit: 2000000, // Создание может требовать много газа maxFeePerGas: "30000000000", // 30 gwei максимум (выше для важных деплоев) maxPriorityFeePerGas: "3000000000", // 3 gwei чаевых для быстрого подтверждения nonce: 44, // Инкрементированный nonce data: "0x608060405234801561001057600080fd5b50" + // Байт-код контракта "34801561002057600080fd5b50600436106100415760003560e01c80" + // Продолжение байт-кода "..." // Полный байт-код может быть очень длинным (несколько KB)}
// После успешного создания:// - Контракту будет присвоен адрес (вычисляется от адреса создателя + nonce)// - Новый адрес = keccak256(rlp([sender_address, nonce]))[12:]// - Например: 0x5FbDB2315678afecb367f032d93F642f64180aa3// Современное создание транзакции с ethers.js v6import { ethers } from 'ethers';
// EIP-1559 транзакция (рекомендуется)const modernTransaction = { type: 2, // EIP-1559 тип to: '0x742d35Cc6634C0532925a3b8D4C9db96590c6C87', // Адрес получателя value: ethers.parseEther('1.0'), // 1 ETH -> wei конвертация gasLimit: 21000, // Лимит газа для ETH перевода maxFeePerGas: ethers.parseUnits('25', 'gwei'), // Максимальная плата maxPriorityFeePerGas: ethers.parseUnits('2', 'gwei'), // Чаевые валидаторам};
// Legacy транзакция (для совместимости)const legacyTransaction = { to: '0x742d35Cc6634C0532925a3b8D4C9db96590c6C87', value: ethers.parseEther('1.0'), // Конвертация: 1 ETH = 10^18 wei gasLimit: 21000, // Всегда 21000 для простых переводов gasPrice: ethers.parseUnits('20', 'gwei'), // 20 gwei = 20 * 10^9 wei};
// Автоматическое получение nonce (рекомендуется)const nonce = await provider.getTransactionCount(wallet.address, 'pending');modernTransaction.nonce = nonce;Transaction Hash: 0x1234567890abcdef...Status: Success ✅Block: 18,500,000From: 0x742d35Cc6634C0532925a3b8D4C9db96590c6C87To: 0x8ba1f109551bD432803012645Hac136cValue: 1.5 ETHGas Limit: 21,000Gas Used: 21,000 (100%)Gas Price: 25 gweiTransaction Fee: 0.000525 ETHGas Limit: 50,000Gas Used: 50,000 (100%)Status: Failed ❌Error: Out of gasStatus: Failed ❌Error: execution reverted: Insufficient balance// Современная проверка адреса с ethers.js v6import { ethers, isAddress, getAddress } from 'ethers';
const recipient = '0x742d35Cc6634C0532925a3b8D4C9db96590c6C87';
// Базовая проверка формата адресаif (!isAddress(recipient)) { throw new Error('Неверный формат адреса Ethereum!');}
// Нормализация адреса с checksummingconst normalizedAddress = getAddress(recipient);console.log('Normalized:', normalizedAddress); // "0x742d35Cc6634C0532925a3b8D4C9db96590c6C87"
// Проверка на нулевой адрес (опасно отправлять сюда средства)const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';if (normalizedAddress === ZERO_ADDRESS) { throw new Error('Нельзя отправлять на нулевой адрес!');}
// Проверка типа адреса (EOA vs Contract)const code = await provider.getCode(recipient);if (code === '0x') { console.log('Адрес получателя: обычный кошелек (EOA)');} else { console.log('Адрес получателя: смарт-контракт'); console.log('Размер кода:', code.length, 'символов');}// Получение рекомендуемых параметров газа (ethers.js v6)const provider = new ethers.JsonRpcProvider( 'https://mainnet.infura.io/v3/YOUR_KEY',);
// Для EIP-1559 транзакцийconst feeData = await provider.getFeeData();console.log({ gasPrice: feeData.gasPrice, // Legacy gas price (для type 0) maxFeePerGas: feeData.maxFeePerGas, // Максимальная плата (type 2) maxPriorityFeePerGas: feeData.maxPriorityFeePerGas, // Чаевые (type 2)});
// Добавление запаса для надежностиconst optimizedTransaction = { type: 2, maxFeePerGas: (feeData.maxFeePerGas * 110n) / 100n, // +10% запас maxPriorityFeePerGas: (feeData.maxPriorityFeePerGas * 110n) / 100n, // +10% чаевых // ... остальные поля};
// Для Legacy транзакций (старый способ)const legacyGasPrice = await provider.getGasPrice();const optimizedGasPrice = (legacyGasPrice * 110n) / 100n; // +10% для надежности// Плохо: фиксированный лимит газаconst badTransaction = { gasLimit: 21000, // может не хватить для сложных операций};
// Хорошо: оценка газаconst gasEstimate = await contract.estimateGas.transfer(to, amount);const goodTransaction = { gasLimit: gasEstimate.mul(120).div(100), // +20% запас};// Получение правильного nonceconst nonce = await provider.getTransactionCount(wallet.address, 'pending');

