Интеграция с Chainlink (оракулы)
Chainlink — де-факто стандарт ценовых оракулов в DeFi. $100B+ обеспечен Chainlink price feeds в Aave, Compound, Synthetix и сотнях других протоколов. Интеграция Chainlink — обязательный навык для любого DeFi разработчика.
Price Feeds: базовая интеграция
Chainlink Data Feeds — агрегированные цены от сети независимых node operators.
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract PriceConsumer {
AggregatorV3Interface internal priceFeed;
constructor() {
// ETH/USD на Ethereum mainnet
priceFeed = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);
}
function getLatestPrice() public view returns (int256) {
(
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
) = priceFeed.latestRoundData();
// Проверить staleness
require(updatedAt >= block.timestamp - 3600, "Stale price");
require(answer > 0, "Invalid price");
return answer; // 8 decimals для USD feeds
}
}
Staleness check — обязательно: если updatedAt слишком давно — оракул не обновлялся. При стейл цене лучше revert чем использовать устаревшие данные.
Decimals и нормализация
Разные feeds имеют разные decimals:
- ETH/USD: 8 decimals (price × 10^8)
- ETH/BTC: 8 decimals
- USDC/ETH: 18 decimals
Всегда читайте priceFeed.decimals() и нормализуйте:
function normalizePrice(int256 price, uint8 feedDecimals, uint8 targetDecimals)
internal pure returns (uint256) {
if (feedDecimals < targetDecimals) {
return uint256(price) * 10 ** (targetDecimals - feedDecimals);
} else {
return uint256(price) / 10 ** (feedDecimals - targetDecimals);
}
}
Chainlink VRF (Verifiable Random Function)
Для приложений требующих верифицируемой случайности: NFT mint, лотереи, игры.
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
contract VRFConsumer is VRFConsumerBaseV2 {
VRFCoordinatorV2Interface COORDINATOR;
uint64 s_subscriptionId;
bytes32 keyHash = 0x...; // gas lane
function requestRandomWords() external returns (uint256 requestId) {
requestId = COORDINATOR.requestRandomWords(
keyHash,
s_subscriptionId,
3, // confirmations
100000, // callback gas limit
2 // num words
);
}
function fulfillRandomWords(uint256, uint256[] memory randomWords)
internal override {
// randomWords[0] — верифицируемое случайное число
}
}
Chainlink Automation (бывший Keepers)
Автоматизация on-chain задач без централизованного сервиса:
import "@chainlink/contracts/src/v0.8/AutomationCompatible.sol";
contract AutomatedContract is AutomationCompatibleInterface {
function checkUpkeep(bytes calldata) external view override
returns (bool upkeepNeeded, bytes memory performData) {
upkeepNeeded = shouldTrigger();
performData = abi.encode(getDataToProcess());
}
function performUpkeep(bytes calldata performData) external override {
// Chainlink Automation вызывает это когда checkUpkeep = true
processData(abi.decode(performData, (MyData)));
}
}
Chainlink Automation — замена cron-ботам. Децентрализованная сеть keepers вызывает performUpkeep когда условие выполнено.
Интеграция базовых price feeds — несколько часов. VRF и Automation — 1-3 дня для production-ready реализации.







