Omniscia Bluejay Finance Audit

StablecoinEngine Manual Review Findings

StablecoinEngine Manual Review Findings

SEE-01M: Inherent Race Condition of Pair Creation

Description:

The initializeStablecoin function mandates that the pair between the reserve and the stablecoin hasn't already been created on the Uniswap factory, however, the Uniswap's createPair function imposes no access control. As a result, a race condition materializes whereby if a pending initializeStablecoin transaction is detected, a malicious user can invoke createPair before it is executed and thus cause it to fail.

Example:

packages/contracts/contracts/StablecoinEngine.sol
90// Manager functions
91function initializeStablecoin(
92 address reserve,
93 address stablecoin,
94 uint256 initialReserveAmount,
95 uint256 initialStablecoinAmount
96) public override onlyRole(MANAGER_ROLE) returns (address poolAddress) {
97 require(pools[reserve][stablecoin] == address(0));
98 require(poolFactory.getPair(reserve, stablecoin) == address(0));
99 poolAddress = poolFactory.createPair(reserve, stablecoin);
100 _storePoolInfo(reserve, stablecoin, poolAddress);
101 _addLiquidity(poolAddress, initialReserveAmount, initialStablecoinAmount);
102}

Recommendation:

We advise the require check and corresponding createPair statement to be replaced by a conditional evaluation whereby if the pair has already been created the code retrieves the pair address from the UniswapV2Factory directly. The finding has been classified as minor given that a dedicated initializeExistingPool function exists bypassing this issue.

Alleviation:

The initializeExistingPool implementation functionality was merged with the initializeStablecoin function and now a single function is executed to initialize the pool regardless of whether it has already been initialized at the Uniswap level. As a result, we consider this exhibit alleviated.

SEE-02M: Inexplicable Capability for Arbitrary Mints

Description:

The mint function of the stablecoin engine permits any of its stablecoins to be minted arbitrarily, a trait that is highly advised against as the stablecoins are an integral stabilization component meant to only be minted and burned during stabilization operations.

Example:

packages/contracts/contracts/StablecoinEngine.sol
199// Minter functions
200function mint(
201 address stablecoin,
202 address to,
203 uint256 amount
204) public override onlyRole(MINTER_ROLE) {
205 IMintableBurnableERC20(stablecoin).mint(to, amount);
206}

Recommendation:

We advise the linked functionality to be omitted from the codebase. Alternatively, we advise the Bluejay Finance team to provide sufficient documentation as to why this trait of the system is desirable and beneficial to it.

Alleviation:

The Bluejay Finance team stated that they wish to retain flexibility in the way the stablecoin is minted to allow different future modules to be introduced to the system such as a mechanism similar to MakerDAO's D3M minting system. Given that upgrade-ability of the protocol is desirable, we consider the arbitrary minting system as a valid component for the business use case of Bluejay Finance and render this exhibit nullified based on the principle that the Bluejay Finance team will act responsibly with regards to the access control imposed by the minting function.