Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BalancerV2 Feed #26

Open
wants to merge 65 commits into
base: main-archive
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
b7e22e6
Adjust GitHub Actions for dev branch (#52)
sicknick99 Apr 13, 2022
a893c39
[WIP] Get BalancerV2 pool token addrs
sicknick99 Feb 5, 2022
26bca2d
Misc feed comments
sicknick99 Feb 5, 2022
1317889
[WIP] Stack too deep error
sicknick99 Feb 7, 2022
9803643
Pass BalV2 tokens data into feed as struct
sicknick99 Feb 7, 2022
cfd5028
Test BalV2 getPoolTokensData fn
sicknick99 Feb 9, 2022
e5c1d69
Fix sol lints
sicknick99 Feb 9, 2022
bfb0210
[WIP] Update feed deployer fn
sicknick99 Feb 10, 2022
9255a80
Fix ovlWethToken in construct
sicknick99 Feb 11, 2022
09a8e45
Test BalV2 feed reverts when market tok is not WETH
sicknick99 Feb 11, 2022
95d9813
Test all require statements in OverlayV1BalancerV2Feed deploy fn
sicknick99 Feb 11, 2022
1636ef1
Use PAR/USDC pool for reverts testing, doc comments
sicknick99 Feb 12, 2022
821f3d0
Move feed deploy fixture to conftest, test view fns"
sicknick99 Feb 12, 2022
0747e9a
[WIP] Check pool ids in balv2 feed, test getPoolId view, test reverts…
sicknick99 Feb 12, 2022
752a908
Pass in pool info as struct to deploy, tests
sicknick99 Feb 17, 2022
b4e8d31
Solidity lint
sicknick99 Feb 17, 2022
2923730
Misc comments
sicknick99 Feb 24, 2022
0d1ae80
Doc comment
sicknick99 Feb 24, 2022
0d6b25a
[WIP] Call getTimeWeightedAverage Balv2 fn from feed
sicknick99 Mar 7, 2022
2de27a5
[WIP] Working getOracleAverageQuery, getTimeWeightedAverage
sicknick99 Mar 9, 2022
f8905fa
Pass queries in as arr to getTimeWeightedAverage
sicknick99 Mar 9, 2022
f0d544d
getPairPrice function
sicknick99 Mar 9, 2022
7ea0e0f
Get reserve over a micro window, getReserve
sicknick99 Mar 10, 2022
900012a
Get reserve in OVL terms
sicknick99 Mar 17, 2022
b6dadf5
Doc comment syntax fixes
sicknick99 Mar 17, 2022
25dc402
Doc comments getTokensPool, getNormalizedWeights, getPoolId
sicknick99 Mar 17, 2022
494a780
Doc comments
sicknick99 Mar 23, 2022
e5ef030
[WIP] In the middle of feed revision
sicknick99 Mar 25, 2022
5185789
Order functions according to NatSpec
sicknick99 Mar 25, 2022
038a8f9
Fix syntax lints
sicknick99 Mar 26, 2022
d442252
Lint python
sicknick99 Mar 26, 2022
f37ac70
Begin testing BalancerV2 Factory
sicknick99 Mar 26, 2022
81e3b0a
Add in the BalancerV2Token struct fns
sicknick99 Mar 26, 2022
58b2165
Use interface for BalancerV2 factory
sicknick99 Mar 26, 2022
9d4d77f
Use interface for BalancerV2 feed -> needs updating in the future
sicknick99 Mar 26, 2022
16ce2e6
Doc comment update
sicknick99 Mar 26, 2022
fd8477b
Test that BalV2 factory deploys feed successfully
sicknick99 Mar 26, 2022
571befa
Test that BalV2 factory deploys inverse feed successfully
sicknick99 Mar 26, 2022
eb85288
Test that BalV2 factory reverts if deploying already existing feed
sicknick99 Mar 26, 2022
397b6f5
[WIP] getPairPrice not returning anything
sicknick99 Mar 29, 2022
901a0a9
Test getTWAPInvariant, fix balv2 feed contract errors
sicknick99 Mar 30, 2022
2caca62
Get reserve and some unfinished tests
sicknick99 Mar 31, 2022
0d559fd
BalV2 Feed inherits from interface
sicknick99 Apr 9, 2022
b1fc6f7
BalV2 feed interface includes more fns
sicknick99 Apr 9, 2022
9a744ce
Fix rebase error
sicknick99 Apr 9, 2022
426ce5c
Add init
sicknick99 Apr 10, 2022
b55697b
Minor comments to self
sicknick99 Apr 10, 2022
3db3332
Used fixed point
sicknick99 Apr 10, 2022
259ebdf
Rm unused ovlWethPoolId global
sicknick99 Apr 10, 2022
39c138f
Address some minor misc todos
sicknick99 Apr 10, 2022
bb80ced
Rm unused getTwapPairPrice fn
sicknick99 Apr 10, 2022
91a85d9
Misc comments
sicknick99 Apr 10, 2022
30202ec
Calculate B_k in getReserveInWeth depending on token order
sicknick99 Apr 11, 2022
117ac30
Calc reserve when WETH is base or quote, rm unused vars
sicknick99 Apr 11, 2022
902b779
Lint
sicknick99 Apr 11, 2022
194efa0
Todo test notes
sicknick99 Apr 12, 2022
444a36f
Lint python
sicknick99 Apr 18, 2022
202e207
Revert to main gh actions
sicknick99 Apr 18, 2022
2a1ee0f
Fix typos, rename balancer lib directory
sicknick99 Apr 20, 2022
d31a786
Mark hardcode WETH as TODO
sicknick99 Apr 20, 2022
135a75d
Update doc comment
sicknick99 Apr 20, 2022
4a94e1e
Comment fixes, getReserve market->ovlWeth fix
sicknick99 Apr 23, 2022
30057e6
Remove BalancerV2Tokens struct, add vault to BalancerV2PoolInfo struc…
sicknick99 Apr 24, 2022
e0ca652
Update tests post BalancerV2Tokens struct removal
sicknick99 Apr 24, 2022
05e6693
Remove marketBaseAmount global variable
sicknick99 Apr 24, 2022
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
8 changes: 5 additions & 3 deletions contracts/feeds/OverlayV1Feed.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ abstract contract OverlayV1Feed is IOverlayV1Feed {
feedFactory = msg.sender;
}

/// @dev returns freshest possible data from oracle
/// @return Freshest possible data from oracle
function latest() external view returns (Oracle.Data memory) {
return _fetch();
}

/// @dev fetches data from oracle. should be implemented differently
/// @dev for each feed type
/// @dev Fetches data from oracle.
/// @dev Should be implemented differently for every Oracle's feed type
/// @dev For each feed type
sicknick99 marked this conversation as resolved.
Show resolved Hide resolved
/// @return Freshest possible data from oracle
function _fetch() internal view virtual returns (Oracle.Data memory);
}
5 changes: 4 additions & 1 deletion contracts/feeds/OverlayV1FeedFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ abstract contract OverlayV1FeedFactory is IOverlayV1FeedFactory {
uint256 public immutable microWindow;
uint256 public immutable macroWindow;

// registry of deployed feeds by factory
/// Registry of deployed feeds by factory
mapping(address => bool) public isFeed;

/// Event emitted on newly deployed feed
event FeedDeployed(address indexed user, address feed);

/// @param _microWindow Micro window to define TWAP over (typically 600s)
/// @param _macroWindow Macro window to define TWAP over (typically 3600s)
constructor(uint256 _microWindow, uint256 _macroWindow) {
// sanity checks on micro and macroWindow
require(_microWindow > 0, "OVLV1: microWindow == 0");
Expand Down
83 changes: 83 additions & 0 deletions contracts/feeds/balancerv2/OverlayV1BalancerV2Factory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import "../../interfaces/feeds/balancerv2/IOverlayV1BalancerV2FeedFactory.sol";

import "../../libraries/balancer/balancer-v2-monorepo/BalancerV2Tokens.sol";
import "../../libraries/balancer/balancer-v2-monorepo/BalancerV2PoolInfo.sol";
import "../OverlayV1FeedFactory.sol";
import "./OverlayV1BalancerV2Feed.sol";

contract OverlayV1BalancerV2Factory is IOverlayV1BalancerV2FeedFactory, OverlayV1FeedFactory {
using BalancerV2Tokens for BalancerV2Tokens.Info;
using BalancerV2PoolInfo for BalancerV2PoolInfo.Pool;
address public immutable ovlWethPool;
address public immutable ovl;

// registry of feeds; for a given (pool, base, quote, amount) pair, returns associated feed
mapping(address => mapping(address => mapping(address => mapping(uint128 => address))))
public getFeed;

/// @notice Constructs a new OverlayV1UniswapV3Factory contract for used to deploy new
/// @notice UniswapV3 feeds to be offered as a market
/// @param _ovlWethPool Address of OVL <-> WETH pool being offered as a market
/// @param _ovl Address of OVL tokens
/// @param _microWindow Micro window to define TWAP over (typically 600s)
/// @param _macroWindow Macro window to define TWAP over (typically 3600s)
constructor(
address _ovlWethPool,
address _ovl,
uint256 _microWindow,
uint256 _macroWindow
) OverlayV1FeedFactory(_microWindow, _macroWindow) {
ovlWethPool = _ovlWethPool;
ovl = _ovl;
}

/// @notice Deploys a new OverlayV1BalancerV2Feed contract
/// @param marketPool Address of pool being offered as a market
/// @param marketBaseToken The base token address of the pool
/// @param marketQuoteToken The quote token address of the pool
/// @param marketBaseAmount TODO
function deployFeed(
address marketPool,
address marketBaseToken,
address marketQuoteToken,
uint128 marketBaseAmount,
BalancerV2Tokens.Info memory balancerV2Tokens
Copy link
Contributor

Choose a reason for hiding this comment

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

Passing in BalancerV2Tokens.Info struct as a deploy feed function input is vulnerable to manipulation: I can deploy a feed with the vault address as my own malicious contract that implements the vault interface, but returns the wrong data to feed.

deployFeed() therefore needs a check that the struct info

library BalancerV2Tokens {
    struct Info {
        address vault;
        bytes32 ovlWethPoolId;
        bytes32 marketPoolId;
    }
}

data is valid. See here how I do this with Uniswap, but you want to use a Balancer "trusted" factory contract or the address of the vault itself as the check. Then get the pool tokens from the vault. The vault address can be stored as an immutable in this feed factory contract, and passed in to the constructor.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also relevant from audit. Would change to something like:

address public immutable ovl;
address public immutable balancerV2Vault;

// TODO: eventually get rid of ovlWethPool storage in favor of ovlXPool approach we have with Uniswap
address public immutable ovlWethPool;

constructor(
    address _ovl,
    address _balancerV2Vault,
    address _ovlWethPool,
    uint256 _microWindow,
    uint256 _macroWindow
) OverlayV1FeedFactory(_microWindow, _macroWindow) {
    ovl = _ovl;
    balancerV2Vault = _balancerV2Vault;
    ovlWethPool = _ovlWethPool;
}

function deployFeed(
    bytes32 marketPoolId,
    address marketBaseToken,
    address marketQuoteToken,
    uint128 marketBaseAmount,
    BalancerV2Tokens.Info memory balancerV2Tokens
) external returns (address feed_) {
    // get the pool address for market tokens
    (address marketPool, ) = IBalancerV2Vault(balancerV2Vault).getPool(marketPoolId)

    // check feed doesn't already exist
    require(
        getFeed[marketPool][marketBaseToken][marketQuoteToken][marketBaseAmount] == address(0),
        "OVLV1: feed already exists"
    );

    ...

This way we revert on the withRegisteredPool() modifier Balancer has if the passed in pool ID isn't actually a valid pool

) external returns (address feed_) {
require(
getFeed[marketPool][marketBaseToken][marketQuoteToken][marketBaseAmount] == address(0),
"OVLV1: feed already exists"
);

BalancerV2PoolInfo.Pool memory balancerV2Pool = BalancerV2PoolInfo.Pool(
marketPool,
ovlWethPool,
ovl,
marketBaseToken,
marketQuoteToken,
marketBaseAmount
);

// Use the CREATE2 opcode to deploy a new Feed contract.
// Will revert if feed which accepts (marketPool, marketBaseToken, marketQuoteToken,
// marketBaseAmount) in its constructor has already been deployed since salt would be the
// same and can't deploy with it twice.
feed_ = address(
new OverlayV1BalancerV2Feed{
salt: keccak256(
abi.encode(marketPool, marketBaseToken, marketQuoteToken, marketBaseAmount)
)
}(balancerV2Pool, balancerV2Tokens, microWindow, macroWindow)
);

// store feed registry record for (marketPool, marketBaseToken, marketQuoteToken) combo
// and record address as deployed feed
getFeed[marketPool][marketBaseToken][marketQuoteToken][marketBaseAmount] = feed_;
isFeed[feed_] = true;
emit FeedDeployed(msg.sender, feed_);
}
}
Loading