Omniscia Bluejay Finance Audit

PriceStabilizer Manual Review Findings

PriceStabilizer Manual Review Findings

PSR-01M: Insufficiently Protected Capability of Oracle Adjustment

Description:

The updateOracle function permits the oracle to be arbitrarily set by the MANAGER_ROLE and thus compromise the stabilizing updatePrice function which can in turn affect the price movement of the token and how its treasury is handled.

Example:

packages/contracts/contracts/PriceStabilizer.sol
33function initializePool(address pool, address oracle)
34 public
35 override
36 onlyRole(MANAGER_ROLE)
37{
38 require(poolInfos[pool].reserve == address(0), "Pool has been initialized");
39 (address reserve, address stablecoin, , ) = stablecoinEngine.poolsInfo(
40 pool
41 );
42 poolInfos[pool] = PoolInfo({
43 reserve: reserve,
44 stablecoin: stablecoin,
45 pool: pool,
46 oracle: oracle
47 });
48}
49
50function updateOracle(address pool, address oracle)
51 public
52 override
53 ifPoolExists(pool)
54 onlyRole(MANAGER_ROLE)
55{
56 require(oracle != address(0), "Address cannot be 0");
57 poolInfos[pool].oracle = oracle;
58 emit UpdatedOracle(pool, oracle);
59}
60
61// oracle should quote the price as number of stablecoin for reserve
62function updatePrice(
63 address pool,
64 uint256 amountIn,
65 uint256 minAmountOut,
66 bool stablecoinForReserve
67)
68 public
69 override
70 ifPoolExists(pool)
71 onlyRole(OPERATOR_ROLE)
72 returns (uint256 poolPrice, uint256 oraclePrice)
73{
74 (uint256 stablecoinReserve, uint256 reserveReserve) = stablecoinEngine
75 .getReserves(pool);
76 poolPrice = (stablecoinReserve * WAD) / reserveReserve;
77 oraclePrice = IPriceFeedOracle(poolInfos[pool].oracle).getPrice();
78 require(
79 stablecoinForReserve
80 ? oraclePrice >= poolPrice
81 : oraclePrice <= poolPrice,
82 "Swap direction is incorrect"
83 );
84
85 stablecoinEngine.swap(pool, amountIn, minAmountOut, stablecoinForReserve);
86
87 (stablecoinReserve, reserveReserve) = stablecoinEngine.getReserves(pool);
88 poolPrice = (stablecoinReserve * WAD) / reserveReserve;
89 require(
90 stablecoinForReserve
91 ? oraclePrice >= poolPrice
92 : oraclePrice <= poolPrice,
93 "Overcorrection"
94 );
95
96 emit UpdatePrice(pool, amountIn, minAmountOut, stablecoinForReserve);
97}

Recommendation:

We advise the capability of adjusting the oracle to be omitted from the codebase. Additionally, we advise more stringent control to be imposed on all oracle related actions (initializePool and updateOracle) as they can compromise the system. As a recommendation, oracle updates could be queued for a pre-determinate period of time in which the owner of the system possesses veto power.

Alleviation:

The Bluejay Finance team stated that they plan to fully decentralize the operation of the stabilizer by assigning the relevant access control roles only to governance-controlled addresses such as the timelock. We consider this decentralization path an adequate response to the exhibit and we mark it as alleviated based on the premise that the Bluejay Finance team will act accordingly after the deployment of their protocol.