DeploySEALED

█╲&□╱◆~▪○?!~▒▫░▓◇╲□○╳!●○○╱&▓╲●$~*◇!█■█&□~╲░$^$&╳▪&■#@░▓*▫○□╱▫╱%%

Transaction ID

Timestamp

Nov 13, 2025, 08:40:37 PM UTC
3mo ago

Block Height

132,672,751

Computation

0

Execution Fee

0.00000849 FLOW

Transaction Summary

Deploy

Contract deployment

Contract deployment

Script Arguments

0nameString
BandPriceOracle
1codeString
import PriceOracle from 0x17ae3b1b0b0d50db /// BandPriceOracle: Production-ready oracle using Band Protocol /// /// This oracle fetches real-time price data from Band Protocol's decentralized /// oracle network on Flow blockchain. /// /// Band Protocol provides: /// - Decentralized price feeds from multiple data sources /// - Real-time price updates /// - High reliability and accuracy /// - Multiple cryptocurrency and forex pairs /// /// Official Documentation: /// - Flow DeFi Contracts: https://developers.flow.com/ecosystem/defi-liquidity/defi-contracts-mainnet /// - Band Protocol: https://docs.bandchain.org/integration/band-standard-dataset/using-band-dataset/ /// /// Note: BandOracle at 0x6801a6222ebf784a wraps StdReference. We use StdReference directly. /// access(all) contract BandPriceOracle: PriceOracle { /// Price data structure (matches PriceOracle interface) access(all) struct PriceData { access(all) let symbol: String access(all) let price: UFix64 access(all) let timestamp: UFix64 access(all) let confidence: UFix64? init(symbol: String, price: UFix64, timestamp: UFix64, confidence: UFix64?) { self.symbol = symbol self.price = price self.timestamp = timestamp self.confidence = confidence } } /// Band Protocol StdReference contract interface /// This interface defines how to interact with Band's oracle access(all) resource interface StdReference { access(all) fun getReferenceData(base: String, quote: String): ReferenceData access(all) fun getReferenceDataBulk(bases: [String], quotes: [String]): [ReferenceData] } /// Reference data structure from Band Protocol access(all) struct ReferenceData { access(all) let rate: UInt256 // Price * 10^18 access(all) let lastUpdatedBase: UInt256 access(all) let lastUpdatedQuote: UInt256 init(rate: UInt256, lastUpdatedBase: UInt256, lastUpdatedQuote: UInt256) { self.rate = rate self.lastUpdatedBase = lastUpdatedBase self.lastUpdatedQuote = lastUpdatedQuote } } /// Storage paths access(all) let OracleStoragePath: StoragePath access(all) let OraclePublicPath: PublicPath access(all) let AdminStoragePath: StoragePath /// Band Protocol StdReference contract address access(all) var bandReferenceAddress: Address /// Price cache to reduce Band Protocol calls /// Maps symbol -> cached price data access(self) var priceCache: {String: PriceData} /// Cache expiry time (60 seconds default) access(all) var cacheExpiry: UFix64 /// Maximum price age to accept from Band (5 minutes) access(all) var maxPriceAge: UFix64 /// Symbol mapping: DCA symbol -> Band symbol /// Example: "FLOW" -> "FLOW", "USDC" -> "USDC" access(self) var symbolMapping: {String: String} /// Events access(all) event PriceFetched(symbol: String, price: UFix64, timestamp: UFix64, source: String) access(all) event PriceCached(symbol: String, price: UFix64, expiresAt: UFix64) access(all) event PriceFeedStale(symbol: String, age: UFix64, maxAge: UFix64) access(all) event BandReferenceUpdated(oldAddress: Address, newAddress: Address) access(all) event SymbolMappingUpdated(dcaSymbol: String, bandSymbol: String) access(all) event CacheExpiryUpdated(newExpiry: UFix64) access(all) event MaxPriceAgeUpdated(newMaxAge: UFix64) access(all) event AdminTransferred(oldAdmin: Address, newAdmin: Address, transferredBy: Address) /// Admin resource for configuration management /// Only the contract deployer receives this capability access(all) resource Admin { /// Update Band Protocol reference address /// Use this to switch between testnet/mainnet or update to new Band contract access(all) fun setBandReferenceAddress(_ newAddress: Address) { pre { newAddress != Address(0x0): "Invalid Band reference address" } let oldAddress = BandPriceOracle.bandReferenceAddress BandPriceOracle.bandReferenceAddress = newAddress emit BandReferenceUpdated(oldAddress: oldAddress, newAddress: newAddress) } /// Add symbol mapping between DCA symbol and Band symbol /// Example: addSymbolMapping("FLOW", "FLOW") or addSymbolMapping("USDC.e", "USDC") access(all) fun addSymbolMapping(dcaSymbol: String, bandSymbol: String) { pre { dcaSymbol.length > 0: "DCA symbol cannot be empty" bandSymbol.length > 0: "Band symbol cannot be empty" } BandPriceOracle.symbolMapping[dcaSymbol] = bandSymbol emit SymbolMappingUpdated(dcaSymbol: dcaSymbol, bandSymbol: bandSymbol) } /// Set cache expiry time (how long to cache prices before refetching) access(all) fun setCacheExpiry(_ newExpiry: UFix64) { pre { newExpiry > 0.0 && newExpiry <= 3600.0: "Cache expiry must be between 0 and 1 hour" } BandPriceOracle.cacheExpiry = newExpiry emit CacheExpiryUpdated(newExpiry: newExpiry) } /// Set max price age (how old a price can be before considered stale) access(all) fun setMaxPriceAge(_ newMaxAge: UFix64) { pre { newMaxAge > 0.0 && newMaxAge <= 3600.0: "Max price age must be between 0 and 1 hour" } BandPriceOracle.maxPriceAge = newMaxAge emit MaxPriceAgeUpdated(newMaxAge: newMaxAge) } } /// Oracle implementation access(all) resource Oracle: PriceOracle.Oracle { /// Get current price for a token from Band Protocol access(all) fun getPrice(symbol: String): AnyStruct? { if let priceData = BandPriceOracle.fetchPrice(symbol: symbol, maxAge: BandPriceOracle.maxPriceAge) { return priceData as AnyStruct } return nil } /// Get price with custom staleness check access(all) fun getPriceWithMaxAge(symbol: String, maxAge: UFix64): AnyStruct? { if let priceData = BandPriceOracle.fetchPrice(symbol: symbol, maxAge: maxAge) { return priceData as AnyStruct } return nil } /// Check if token is supported access(all) fun supportsToken(symbol: String): Bool { return BandPriceOracle.symbolMapping.containsKey(symbol) } /// Get all supported tokens access(all) fun getSupportedTokens(): [String] { return BandPriceOracle.symbolMapping.keys } } /// Fetch price from Band Protocol with caching access(all) fun fetchPrice(symbol: String, maxAge: UFix64): PriceData? { let currentTime = getCurrentBlock().timestamp // Check cache first if let cachedPrice = self.priceCache[symbol] { let cacheAge = currentTime - cachedPrice.timestamp if cacheAge <= self.cacheExpiry { // Cache hit - return cached price return cachedPrice } } // Cache miss or expired - fetch from Band Protocol return self.fetchFromBand(symbol: symbol, maxAge: maxAge) } /// Fetch price directly from Band Protocol access(self) fun fetchFromBand(symbol: String, maxAge: UFix64): PriceData? { // Get Band symbol mapping let bandSymbol = self.symbolMapping[symbol] if bandSymbol == nil { return nil } // Get Band StdReference capability let bandReference = getAccount(self.bandReferenceAddress) .capabilities.get<&{StdReference}>(/public/BandStdReference) .borrow() if bandReference == nil { // Band Protocol not available - return cached if available return self.priceCache[symbol] } // Fetch price from Band: symbol/USD let refData = bandReference!.getReferenceData( base: bandSymbol!, quote: "USD" ) // Convert Band's rate (UInt256 with 18 decimals) to UFix64 // Band rate is price * 10^18, we need UFix64 price let price = self.convertBandRate(refData.rate) // Check staleness let currentTime = getCurrentBlock().timestamp let bandUpdateTime = UFix64(refData.lastUpdatedBase) let age = currentTime - bandUpdateTime if age > maxAge { emit PriceFeedStale(symbol: symbol, age: age, maxAge: maxAge) return nil } // Create PriceData let priceData = PriceData( symbol: symbol, price: price, timestamp: bandUpdateTime, confidence: nil // Band doesn't provide confidence intervals ) // Cache the price self.priceCache[symbol] = priceData emit PriceCached( symbol: symbol, price: price, expiresAt: currentTime + self.cacheExpiry ) emit PriceFetched( symbol: symbol, price: price, timestamp: bandUpdateTime, source: "Band Protocol" ) return priceData } /// Convert Band's UInt256 rate (with 18 decimals) to UFix64 price /// Band rate format: price * 10^18 /// Example: FLOW at $1.25 = 1250000000000000000 access(self) fun convertBandRate(_ rate: UInt256): UFix64 { // Convert UInt256 to UFix64 // Divide by 10^18 to get actual price // Note: This is a simplified conversion // In production, use proper decimal handling let rateString = rate.toString() let rateLength = rateString.length // If rate is less than 18 digits, price is less than 1 if rateLength <= 18 { // Pad with leading zeros let padding = "000000000000000000".slice(from: 0, upTo: 18 - rateLength) let fullRate = padding.concat(rateString) let integerPart = "0" let decimalPart = fullRate // Construct UFix64 string let priceString = integerPart.concat(".").concat(decimalPart) return UFix64.fromString(priceString) ?? 0.0 } // Extract integer and decimal parts let splitPoint = rateLength - 18 let integerPart = rateString.slice(from: 0, upTo: splitPoint) let decimalPart = rateString.slice(from: splitPoint, upTo: rateLength) // Construct UFix64 string let priceString = integerPart.concat(".").concat(decimalPart) return UFix64.fromString(priceString) ?? 0.0 } /// Public function to get price (convenience) access(all) fun getPrice(symbol: String): PriceData? { return self.fetchPrice(symbol: symbol, maxAge: self.maxPriceAge) } /// Public function to get price with staleness check access(all) fun getPriceWithMaxAge(symbol: String, maxAge: UFix64): PriceData? { return self.fetchPrice(symbol: symbol, maxAge: maxAge) } /// Create a new Oracle resource access(all) fun createOracle(): @Oracle { return <- create Oracle() } init() { self.OracleStoragePath = /storage/BandPriceOracle self.OraclePublicPath = /public/BandPriceOracle self.AdminStoragePath = /storage/BandPriceOracleAdmin // Set Band Protocol StdReference address // Testnet: 0x9f857c97e8c50809 // Mainnet: 0x1a94aed0e4e6c2a7 self.bandReferenceAddress = 0x9f857c97e8c50809 // Testnet default // Cache settings self.cacheExpiry = 60.0 // 60 seconds self.maxPriceAge = 300.0 // 5 minutes // Initialize price cache self.priceCache = {} // Initialize symbol mappings (Band symbol names) self.symbolMapping = { "FLOW": "FLOW", "USDC": "USDC", "USDT": "USDT", "BTC": "BTC", "ETH": "ETH", "FUSD": "FUSD" } self.account.storage.save(<-create Admin(), to: self.AdminStoragePath) } }

Cadence Script

1transaction(name: String, code: String ) {
2		prepare(signer: auth(AddContract) &Account) {
3			signer.contracts.add(name: name, code: code.utf8 )
4		}
5	}