Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
d4fb9e7
initial commit
sisyphusSmiling Apr 9, 2025
ac892ac
update .gitignore
sisyphusSmiling Apr 9, 2025
7a0e8c3
remove internal check on path in IncrementSwapStack
sisyphusSmiling Apr 9, 2025
408c303
add initial tests & test helpers
sisyphusSmiling Apr 9, 2025
e439cad
update .gitignore
sisyphusSmiling Apr 9, 2025
8adf987
update README & add Makefile
sisyphusSmiling Apr 9, 2025
b40fcab
remove Stack resource
sisyphusSmiling Apr 9, 2025
4897e73
remove unused scripts & transactions
sisyphusSmiling Apr 9, 2025
06bc07d
update Source interface
sisyphusSmiling Apr 11, 2025
bf5773e
update VaultSource implementation & simplify capacity limits
sisyphusSmiling Apr 11, 2025
d28f501
remove non-interface helpers & remove reverting conditionals
sisyphusSmiling Apr 11, 2025
ed20566
update SwapSink init parameters & field assignment
sisyphusSmiling Apr 11, 2025
f6bad6c
update SwapSink.minimumCapacity() calculation
sisyphusSmiling Apr 11, 2025
1c07071
add contract documentation comments
sisyphusSmiling Apr 11, 2025
77ca5f8
fix FungibleTokenStack deposit & withdraw conditions
sisyphusSmiling Apr 11, 2025
50c78e7
fix & simplify SwapSink.depositCapacity
sisyphusSmiling Apr 14, 2025
b3e850f
add entitlement to Source.withdrawAvailable
sisyphusSmiling Apr 15, 2025
fdcdf54
add checks to FungibleTokenStack connectors
sisyphusSmiling Apr 15, 2025
9dee7f1
add SwapSource connector to IncrementSwapStack
sisyphusSmiling Apr 15, 2025
631d15b
add type check on SwapSink.depositCapacity
sisyphusSmiling Apr 15, 2025
42731c3
update SwapSource to check balance of vault returned from inner Source
sisyphusSmiling Apr 15, 2025
1a83d8f
fix FungibleTokenStack connector init pre-condition check
sisyphusSmiling Apr 15, 2025
5a2260b
add example VaultSourceAndSink combination connector for consideration
sisyphusSmiling Apr 15, 2025
d1fb33f
update VaultSink & VaultSource min & max balance init params as optional
sisyphusSmiling Apr 15, 2025
2087295
add Cadence test suite to ci workflows
sisyphusSmiling Apr 15, 2025
2677c7f
update FungibleTokenStack struct init named parameters
sisyphusSmiling Apr 15, 2025
c4511e5
add initial draft of DeFiAdapters
sisyphusSmiling Apr 15, 2025
5a5523c
update DeFiAdapters with quote getters
sisyphusSmiling Apr 15, 2025
f9fc8c5
add DeFiAdapters to config
sisyphusSmiling Apr 15, 2025
62e9f95
rename IncrementSwapStack & generalize using DeFiAdapters struct inte…
sisyphusSmiling Apr 15, 2025
f32c9b2
create IncrementFi contract & define SwapAdapter
sisyphusSmiling Apr 15, 2025
2361b72
restructure repo
sisyphusSmiling Apr 15, 2025
a20c651
update contract comment formatting
sisyphusSmiling Apr 15, 2025
c3943ce
update dependencies
sisyphusSmiling Apr 16, 2025
9a58a1a
add script to hex encode Cadence contract with dynamic testing imports
sisyphusSmiling Apr 16, 2025
d9c5d95
update hexify script to accept network argument
sisyphusSmiling Apr 16, 2025
1923997
add test environment setup for IncrementFi contracts
sisyphusSmiling Apr 16, 2025
0596074
add initial IncrementFiAdapters tests
sisyphusSmiling Apr 16, 2025
476cc8f
update interface comments
sisyphusSmiling May 1, 2025
7d6f74a
add dependencies
sisyphusSmiling May 5, 2025
fb12cc0
add initial EVM router getAmounts queries
sisyphusSmiling May 5, 2025
8721f2c
add additional vm bridge dependencies
sisyphusSmiling May 5, 2025
1789969
expose helper for retrieving a new empty Vault
sisyphusSmiling May 5, 2025
6853773
add first run at EVM swapExactTokensForTokens in adapter
sisyphusSmiling May 5, 2025
5b3afe3
init forge
sisyphusSmiling May 5, 2025
ecc129e
update forge foundry.toml
sisyphusSmiling May 5, 2025
0db00e5
move forge-std to canonical forge lib at solidity/lib
sisyphusSmiling May 5, 2025
1fc2925
add uniswapV2 dependencies
sisyphusSmiling May 5, 2025
040c170
move forge script dir
sisyphusSmiling May 5, 2025
5744192
update .gitignore
sisyphusSmiling May 5, 2025
5ff927d
remove forge template files
sisyphusSmiling May 5, 2025
eae69a9
add openzeppelin dependencies
sisyphusSmiling May 5, 2025
17341fa
add BasicERC20 for testing
sisyphusSmiling May 5, 2025
8239c90
add initial EVM test helpers
sisyphusSmiling May 5, 2025
3227568
add initial EVMStackFiAdapters test w/ uniswapV2 deployment
sisyphusSmiling May 6, 2025
3340ff4
add vm bridge dependencies
sisyphusSmiling May 6, 2025
e7d41a7
add vm bridge test setup
sisyphusSmiling May 6, 2025
fa4ebca
Merge branch 'gio/prototype' into gio/swap-adapter
sisyphusSmiling May 6, 2025
8550fcd
Merge branch 'gio/swap-adapter' into gio/add-increment-tests
sisyphusSmiling May 6, 2025
9d7b1e0
Merge branch 'gio/add-increment-tests' into gio/evm-swap-adapter
sisyphusSmiling May 6, 2025
f7b2662
add Swapper struct interface
sisyphusSmiling May 7, 2025
683cfe8
update Swapper interface
sisyphusSmiling May 9, 2025
a1241a6
refactor IncrementFiAdapters to use new Swapper interface
sisyphusSmiling May 9, 2025
e7cb9b0
refactor SwapStack Source & Sink to use new Swapper interface
sisyphusSmiling May 9, 2025
69c20f8
remove DeFiAdapters contract
sisyphusSmiling May 9, 2025
1ee5f37
rename StackFiInterfaces to DFB & update dependents
sisyphusSmiling May 9, 2025
5e48d32
update DFB Swapper to return a Quote instead of a single value on amo…
sisyphusSmiling May 13, 2025
417bfa8
update SwapStack in conformance with updated Swapper interface
sisyphusSmiling May 13, 2025
9442655
update flow.json
sisyphusSmiling May 13, 2025
67fe495
add pre-conditions to DFB.Swapper interface methods
sisyphusSmiling May 13, 2025
fb54d5d
update IncrementFiAdapters in conformance with new Swapper interface
sisyphusSmiling May 13, 2025
de7d5e9
add interface-level events to DFB
sisyphusSmiling May 13, 2025
cbd2a1c
update Sources & Sinks in conformance with updated DFB interfaces
sisyphusSmiling May 13, 2025
09a1c59
fix Swapper conformance in IncrementFiAdapters.Swapper
sisyphusSmiling May 13, 2025
a790cd6
Merge branch 'gio/swap-adapter' into gio/add-increment-tests
sisyphusSmiling May 13, 2025
c7d0bde
update IncrementFiAdapters tests
sisyphusSmiling May 13, 2025
b9f4c9b
fix test filename typo
sisyphusSmiling May 13, 2025
24ed80a
Merge branch 'gio/add-increment-tests' into gio/evm-swap-adapter
sisyphusSmiling May 13, 2025
ef7d374
rename EVMStackFiAdapters to DeFiBlocksEVMAdapters
sisyphusSmiling May 13, 2025
5811def
remove unused import
sisyphusSmiling May 14, 2025
a795d62
refactor DeFiBlocksEVMAdapters for new Swapper interface
sisyphusSmiling May 14, 2025
195c88f
rename EVMStackFiAdapters_test to DeFiBlocksEVMAdapters_test
sisyphusSmiling May 14, 2025
6eef279
update code comments
sisyphusSmiling May 14, 2025
bdd62f4
fix solidity formatting
sisyphusSmiling May 14, 2025
c97a40a
remove unused forge test command from ci
sisyphusSmiling May 14, 2025
590211f
Merge pull request #2 from onflow/gio/swap-adapter
sisyphusSmiling May 14, 2025
7c7d2fa
fix DeFiBlocksEVMAdapters Swapper by adding approve() call before swa…
sisyphusSmiling May 14, 2025
a1b218b
update code comments
sisyphusSmiling May 14, 2025
1b626e0
remove unused dependency
sisyphusSmiling May 14, 2025
fced438
add initial PriceOracle DFB interface
sisyphusSmiling May 14, 2025
61efd70
add BandOracle dependencies for initial PriceOracle implementation
sisyphusSmiling May 14, 2025
832bb74
update DFB.PriceOracle interface
sisyphusSmiling May 14, 2025
811848f
add PriceOracle implementation adapting BandProtocol
sisyphusSmiling May 14, 2025
61e6a17
simplify PriceOracle interface
sisyphusSmiling May 14, 2025
89cff82
update BandOracleAdapters in conformance with new PriceOracle interface
sisyphusSmiling May 14, 2025
db530a1
remove unused import
sisyphusSmiling May 15, 2025
979a833
Merge branch 'main' into gio/evm-swap-adapter
sisyphusSmiling May 20, 2025
09a743e
update contract comments
sisyphusSmiling May 20, 2025
6034c40
refactor DeFiBlocksEVMAdapters to reduce unnecessary UInt256-UFix64 c…
sisyphusSmiling May 20, 2025
53a4a55
Merge branch 'gio/evm-swap-adapter' into gio/add-oracle
sisyphusSmiling May 20, 2025
ad1ccea
update PriceOracle.price return type
sisyphusSmiling May 21, 2025
9bfdc52
Merge branch 'main' into gio/add-oracle
sisyphusSmiling May 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions cadence/contracts/adapters/BandOracleAdapters.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import "Burner"
import "FungibleToken"
import "FlowToken"
import "BandOracle"

import "DFB"

/// BandOracleAdapters
///
/// This contract adapts BandOracle's price data oracle contracts for use as a DeFiBlocks PriceOracle connector
///
access(all) contract BandOracleAdapters {

/// Mapping of asset Types to BandOracle symbols
access(all) let assetSymbols: {Type: String}
/// StoragePath for the SymbolUpdater tasked with adding Type:SYMBOL pairs
access(self) let SymbolUpdaterStoragePath: StoragePath

/* EVENTS */
/// Emitted when a Type:SYMBOL pair is added via the SymbolUpdater resource
access(all) event SymbolAdded(symbol: String, asset: String)

/* CONSTRUCTS */

// PriceOracle
//
/// An adapter for BandOracle as an implementation of the DeFiBlocks PriceOracle interface
access(all) struct PriceOracle : DFB.PriceOracle {
/// The token type serving as the price basis - e.g. USD in FLOW/USD
access(self) let quote: Type
/// A Source providing the FlowToken necessary for BandOracle price data requests
access(self) let feeSource: {DFB.Source}
/// The amount of seconds beyond which a price is considered stale and a price() call reverts
access(self) let staleThreshold: UInt64?

init(unitOfAccount: Type, staleThreshold: UInt64?, feeSource: {DFB.Source}) {
pre {
feeSource.getSourceType() == Type<@FlowToken.Vault>():
"Invalid feeSource - given Source must provide FlowToken Vault, but provides \(feeSource.getSourceType().identifier)"
unitOfAccount.getType().isSubtype(of: Type<@{FungibleToken.Vault}>()):
"Invalid unitOfAccount - \(unitOfAccount.identifier) is not a FungibleToken.Vault implementation"
BandOracleAdapters.assetSymbols[unitOfAccount] != nil:
"Could not find a BandOracle symbol assigned to unitOfAccount \(unitOfAccount.identifier)"
}
self.feeSource = feeSource
self.quote = unitOfAccount
self.staleThreshold = staleThreshold
}

/// Returns the asset type serving as the price basis - e.g. USD in FLOW/USD
access(all) view fun unitOfAccount(): Type {
return self.quote
}

/// Returns the latest price data for a given asset denominated in unitOfAccount(). Since BandOracle requests
/// are paid, this implementation reverts if price data has gone stale
access(all) fun price(ofToken: Type): UFix64? {
// lookup the symbols
let baseSymbol = BandOracleAdapters.assetSymbols[ofToken]
?? panic("Base asset type \(ofToken.identifier) does not have an assigned symbol")
let quoteSymbol = BandOracleAdapters.assetSymbols[self.unitOfAccount()]!
// withdraw the oracle fee & get the price data from BandOracle
let fee <- self.feeSource.withdrawAvailable(maxAmount: BandOracle.getFee())
let priceData = BandOracle.getReferenceData(baseSymbol: baseSymbol, quoteSymbol: quoteSymbol, payment: <-fee)

// check price data has not gone stale based on last updated timestamp
let now = UInt64(getCurrentBlock().timestamp)
if self.staleThreshold != nil {
assert(now < priceData.baseTimestamp + self.staleThreshold!,
message: "Price data's base timestamp \(priceData.baseTimestamp) exceeds the staleThreshold "
.concat("\(priceData.baseTimestamp + self.staleThreshold!) at current timestamp \(now)"))
assert(now < priceData.quoteTimestamp + self.staleThreshold!,
message: "Price data's quote timestamp \(priceData.quoteTimestamp) exceeds the staleThreshold "
.concat("\(priceData.quoteTimestamp + self.staleThreshold!) at current timestamp \(now)"))
}

return priceData.fixedPointRate
}
}

// SymbolUpdater
//
/// Resource enabling the addition of new Type:SYMBOL pairings as they are supported by BandOracle's price oracle
access(all) resource SymbolUpdater {
/// Adds a Type:SYMBOL pairing to the contract's mapping. Reverts if the asset Type is already assigned a symbol
access(all) fun addSymbol(_ symbol: String, forAsset: Type) {
pre {
BandOracleAdapters.assetSymbols[forAsset] == nil:
"Asset \(forAsset.identifier) is already assigned symbol \(BandOracleAdapters.assetSymbols[forAsset]!)"
}
BandOracleAdapters.assetSymbols[forAsset] = symbol

emit SymbolAdded(symbol: symbol, asset: forAsset.identifier)
}
}

init() {
self.assetSymbols = {
Type<@FlowToken.Vault>(): "FLOW"
}
self.SymbolUpdaterStoragePath = StoragePath(identifier: "BandOracleAdapterSymbolUpdater_\(self.account.address)")!
self.account.storage.save(<-create SymbolUpdater(), to: self.SymbolUpdaterStoragePath)
}
}
11 changes: 11 additions & 0 deletions cadence/contracts/interfaces/DFB.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,15 @@ access(all) contract DFB {
}
}
}

/// An interface for a price oracle adapter. Implementations should adapt this interface to various price feed
/// oracles deployed on Flow
access(all) struct interface PriceOracle {
/// Returns the asset type serving as the price basis - e.g. USD in FLOW/USD
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would we represent USD here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking we would use a stablecoin. For example, a PriceOracle where unitOfAccount() == Type<@USDCFlow.Vault>() would denominate all prices in USDCFlow which for the most part can be considered equivalent to USD.
The big assumption of course is that the price for any stablecoin is exactly par for USD which isn't always the case. That said, there's not a type that can be used exactly as USD so all prices served by this PriceOracle would always be relative to some other token type.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, though using USDCFlow is probably risky, since the Flow foundation basically gave up on it in favor of the other bridged USDC representations. Probably better to rely on those. We should talk to Zach or someone to get an idea of which on will be the most stable

access(all) view fun unitOfAccount(): Type
/// Returns the latest price data for a given asset denominated in unitOfAccount() if available, otherwise `nil`
/// should be returned. Callers should note that although an optional is supported, implementations may choose
/// to revert.
access(all) fun price(ofToken: Type): UFix64?
}
}
30 changes: 30 additions & 0 deletions cadence/tests/BandOracleAdapters_test.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import Test
import BlockchainHelpers
import "test_helpers.cdc"

access(all) let serviceAccount = Test.serviceAccount()

access(all) fun setup() {
var err = Test.deployContract(
name: "DFB",
path: "../contracts/interfaces/DFB.cdc",
arguments: [],
)
Test.expect(err, Test.beNil())
err = Test.deployContract(
name: "BandOracle",
path: "../../imports/6801a6222ebf784a/BandOracle.cdc",
arguments: [],
)
Test.expect(err, Test.beNil())
err = Test.deployContract(
name: "BandOracleAdapters",
path: "../contracts/adapters/BandOracleAdapters.cdc",
arguments: [],
)
Test.expect(err, Test.beNil())
}

access(all) fun testSetupSuccess() {
log("BandOracleAdapters deployment success")
}
18 changes: 17 additions & 1 deletion flow.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
{
"contracts": {
"BandOracleAdapters": {
"source": "cadence/contracts/adapters/BandOracleAdapters.cdc",
"aliases": {
"testing": "0000000000000007"
}
},
"DFB": {
"source": "cadence/contracts/interfaces/DFB.cdc",
"aliases": {
Expand Down Expand Up @@ -59,6 +65,15 @@
"testnet": "dfc20aee650fcbdf"
}
},
"BandOracle": {
"source": "mainnet://6801a6222ebf784a.BandOracle",
"hash": "be8c986f46eccfe55a25447e1b7fa07e95769ac4ca11918833130a4bf3297b16",
"aliases": {
"mainnet": "6801a6222ebf784a",
"testing": "0000000000000007",
"testnet": "2c71de7af78d1adf"
}
},
"Burner": {
"source": "mainnet://f233dcee88fe0abe.Burner",
"hash": "71af18e227984cd434a3ad00bb2f3618b76482842bae920ee55662c37c8bf331",
Expand Down Expand Up @@ -472,7 +487,8 @@
"StringUtils",
"ArrayUtils",
"ScopedFTProviders",
"FlowEVMBridgeResolver"
"FlowEVMBridgeResolver",
"BandOracle"
]
}
}
Expand Down