Smart Contract

MockOracle

A.d2580caf2ef07c2f.MockOracle

Deployed

1h ago
Feb 26, 2026, 07:28:48 PM UTC

Dependents

0 imports
1import FungibleToken from 0x9a0766d93b6608b7
2
3import DeFiActions from 0x0b11b1848a8aa2c0
4
5///
6/// THIS CONTRACT IS A MOCK AND IS NOT INTENDED FOR USE IN PRODUCTION
7/// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
8///
9access(all) contract MockOracle {
10
11    /// token price denominated in USD
12    access(self) let mockedPrices: {Type: UFix64}
13    /// the token type in which prices are denominated
14    access(self) let unitOfAccount: Type
15    /// bps up or down by which current price moves when bumpPrice is called
16    access(self) let bumpVariance: UInt16
17
18    access(all) struct PriceOracle : DeFiActions.PriceOracle {
19        access(contract) var uniqueID: DeFiActions.UniqueIdentifier?
20
21        init() {
22            self.uniqueID = nil 
23        }
24        /// Returns the asset type serving as the price basis - e.g. USD in FLOW/USD
25        access(all) view fun unitOfAccount(): Type {
26            return MockOracle.unitOfAccount
27        }
28
29        /// Returns the latest price data for a given asset denominated in unitOfAccount()
30        access(all) fun price(ofToken: Type): UFix64? {
31            if ofToken == self.unitOfAccount() {
32                return 1.0
33            }
34            return MockOracle.mockedPrices[ofToken]
35        }
36        access(all) fun getComponentInfo(): DeFiActions.ComponentInfo {
37            return DeFiActions.ComponentInfo(
38                type: self.getType(),
39                id: self.id(),
40                innerComponents: []
41            )
42        }
43        access(contract) view fun copyID(): DeFiActions.UniqueIdentifier? {
44            return self.uniqueID
45        }
46        access(contract) fun setID(_ id: DeFiActions.UniqueIdentifier?) {
47            self.uniqueID = id
48        }
49    }
50
51    // resets the price of the token within 0-bumpVariance (bps) of the current price
52    // allows for mocked data to have variability
53    access(all) fun bumpPrice(forToken: Type) {
54        if forToken == self.unitOfAccount {
55            return
56        }
57        let current = self.mockedPrices[forToken]
58            ?? panic("MockOracle does not have a price set for token \(forToken.identifier)")
59        let sign = revertibleRandom<UInt8>(modulo: 2) // 0 - down | 1 - up
60        let variance = self.convertToBPS(revertibleRandom<UInt16>(modulo: self.bumpVariance)) // bps up or down
61        if sign == 0 {
62            self.mockedPrices[forToken] = current - (current * variance)
63        } else {
64            self.mockedPrices[forToken] = current + (current * variance)
65        }
66    }
67
68    access(all) fun setPrice(forToken: Type, price: UFix64) {
69        self.mockedPrices[forToken] = price
70    }
71
72    access(self) view fun convertToBPS(_ variance: UInt16): UFix64 {
73        var res = UFix64(variance)
74        for i in InclusiveRange(0, 3) {
75            res = res / 10.0
76        } 
77        return res
78    }
79
80    init(unitOfAccountIdentifier: String) {
81        self.mockedPrices = {}
82        // e.g. vault.getType().identifier == 'A.0ae53cb6e3f42a79.FlowToken.Vault'
83        self.unitOfAccount = CompositeType(unitOfAccountIdentifier) ?? panic("Invalid unitOfAccountIdentifier \(unitOfAccountIdentifier)")
84        self.bumpVariance = 100 // 0.1% variance
85    }
86}
87