Files
smom-dbis-138/contracts/flash/DBISEngineXSingleSidedDodoCwusdcVault.sol
defiQUG 76143a8fe3 feat(token-aggregation): reports, PMM quotes, config; Engine X flash vaults
- Expand token-aggregation API (report routes), canonical tokens, pools
- Add flash vault contracts + tests (indexed, DODO cwUSDC, XAUT borrow)
- PMM pools JSON, deploy/export scripts, metamask verified list

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 12:56:30 -07:00

235 lines
9.6 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
interface IEngineXDodoPoolLike {
function _BASE_TOKEN_() external view returns (address);
function _QUOTE_TOKEN_() external view returns (address);
function querySellBase(address trader, uint256 payBaseAmount)
external
view
returns (uint256 receiveQuoteAmount, uint256 mtFee);
function querySellQuote(address trader, uint256 payQuoteAmount)
external
view
returns (uint256 receiveBaseAmount, uint256 mtFee);
function getVaultReserve() external view returns (uint256 baseReserve, uint256 quoteReserve);
}
interface IEngineXDodoIntegrationLike {
function addLiquidity(address pool, uint256 baseAmount, uint256 quoteAmount)
external
returns (uint256 baseShare, uint256 quoteShare, uint256 lpShare);
}
/// @notice Engine X single-sided cWUSDC inventory wrapper for later DODO PMM promotion.
/// @dev cWUSDC-only inventory is accounting/support inventory, not executable public DODO liquidity.
/// DODO promotion is allowed only with nonzero base and quote amounts and passing canary guards.
contract DBISEngineXSingleSidedDodoCwusdcVault is Ownable, ReentrancyGuard {
using SafeERC20 for IERC20;
IERC20 public immutable cWUSDC;
IERC20 public immutable quoteToken;
IEngineXDodoIntegrationLike public immutable dodoIntegration;
address public dodoPool;
bool public paused;
uint256 public accountedCwusdcInventory;
uint256 public accountedQuoteInventory;
uint256 public totalCwusdcPromotedToDodo;
uint256 public totalQuotePromotedToDodo;
uint256 public sampleBaseIn;
uint256 public minQuoteOut;
uint256 public sampleQuoteIn;
uint256 public minBaseOut;
event Paused(address indexed operator);
event Unpaused(address indexed operator);
event DodoPoolUpdated(address indexed pool);
event CanaryUpdated(uint256 sampleBaseIn, uint256 minQuoteOut, uint256 sampleQuoteIn, uint256 minBaseOut);
event CwusdcInventoryDeposited(address indexed from, uint256 amount);
event QuoteInventoryDeposited(address indexed from, uint256 amount);
event InventoryWithdrawn(address indexed token, address indexed to, uint256 amount);
event DodoLiquidityPromoted(
address indexed pool,
uint256 baseAmount,
uint256 quoteAmount,
uint256 baseShare,
uint256 quoteShare,
uint256 lpShare
);
event UnaccountedTokenWithdrawn(address indexed token, address indexed to, uint256 amount);
modifier whenNotPaused() {
require(!paused, "paused");
_;
}
constructor(address cWUSDC_, address quoteToken_, address dodoIntegration_, address owner_) Ownable(owner_) {
require(cWUSDC_ != address(0) && quoteToken_ != address(0), "zero token");
require(dodoIntegration_ != address(0), "zero integration");
require(owner_ != address(0), "zero owner");
require(cWUSDC_ != quoteToken_, "same token");
cWUSDC = IERC20(cWUSDC_);
quoteToken = IERC20(quoteToken_);
dodoIntegration = IEngineXDodoIntegrationLike(dodoIntegration_);
}
function pause() external onlyOwner {
paused = true;
emit Paused(msg.sender);
}
function unpause() external onlyOwner {
paused = false;
emit Unpaused(msg.sender);
}
function setDodoPool(address pool) external onlyOwner {
_validatePool(pool);
dodoPool = pool;
emit DodoPoolUpdated(pool);
}
function setCanary(uint256 sampleBaseIn_, uint256 minQuoteOut_, uint256 sampleQuoteIn_, uint256 minBaseOut_)
external
onlyOwner
{
require(sampleBaseIn_ > 0 || sampleQuoteIn_ > 0, "zero canary");
require((sampleBaseIn_ == 0) == (minQuoteOut_ == 0), "base canary mismatch");
require((sampleQuoteIn_ == 0) == (minBaseOut_ == 0), "quote canary mismatch");
sampleBaseIn = sampleBaseIn_;
minQuoteOut = minQuoteOut_;
sampleQuoteIn = sampleQuoteIn_;
minBaseOut = minBaseOut_;
emit CanaryUpdated(sampleBaseIn_, minQuoteOut_, sampleQuoteIn_, minBaseOut_);
}
function depositCwusdc(uint256 amount) external nonReentrant whenNotPaused {
require(amount > 0, "zero deposit");
cWUSDC.safeTransferFrom(msg.sender, address(this), amount);
accountedCwusdcInventory += amount;
emit CwusdcInventoryDeposited(msg.sender, amount);
}
function depositQuote(uint256 amount) external nonReentrant whenNotPaused {
require(amount > 0, "zero deposit");
quoteToken.safeTransferFrom(msg.sender, address(this), amount);
accountedQuoteInventory += amount;
emit QuoteInventoryDeposited(msg.sender, amount);
}
function withdrawCwusdcInventory(address to, uint256 amount) external onlyOwner nonReentrant {
require(to != address(0), "zero to");
require(amount > 0, "zero withdraw");
require(amount <= accountedCwusdcInventory, "insufficient cwusdc inventory");
accountedCwusdcInventory -= amount;
cWUSDC.safeTransfer(to, amount);
_requireSolvent();
emit InventoryWithdrawn(address(cWUSDC), to, amount);
}
function withdrawQuoteInventory(address to, uint256 amount) external onlyOwner nonReentrant {
require(to != address(0), "zero to");
require(amount > 0, "zero withdraw");
require(amount <= accountedQuoteInventory, "insufficient quote inventory");
accountedQuoteInventory -= amount;
quoteToken.safeTransfer(to, amount);
_requireSolvent();
emit InventoryWithdrawn(address(quoteToken), to, amount);
}
function promoteToDodo(
uint256 baseAmount,
uint256 quoteAmount,
uint256 minBaseShare,
uint256 minQuoteShare,
uint256 minLpShare
) external onlyOwner nonReentrant whenNotPaused returns (uint256 baseShare, uint256 quoteShare, uint256 lpShare) {
require(dodoPool != address(0), "pool not set");
require(baseAmount > 0 && quoteAmount > 0, "two-sided required");
require(baseAmount <= accountedCwusdcInventory, "insufficient cwusdc inventory");
require(quoteAmount <= accountedQuoteInventory, "insufficient quote inventory");
accountedCwusdcInventory -= baseAmount;
accountedQuoteInventory -= quoteAmount;
cWUSDC.forceApprove(address(dodoIntegration), baseAmount);
quoteToken.forceApprove(address(dodoIntegration), quoteAmount);
(baseShare, quoteShare, lpShare) = dodoIntegration.addLiquidity(dodoPool, baseAmount, quoteAmount);
cWUSDC.forceApprove(address(dodoIntegration), 0);
quoteToken.forceApprove(address(dodoIntegration), 0);
require(baseShare >= minBaseShare, "base share too low");
require(quoteShare >= minQuoteShare, "quote share too low");
require(lpShare >= minLpShare, "lp share too low");
require(canaryPasses(), "canary failed");
totalCwusdcPromotedToDodo += baseAmount;
totalQuotePromotedToDodo += quoteAmount;
_requireSolvent();
emit DodoLiquidityPromoted(dodoPool, baseAmount, quoteAmount, baseShare, quoteShare, lpShare);
}
function canaryPasses() public view returns (bool) {
if (dodoPool == address(0)) return false;
IEngineXDodoPoolLike pool = IEngineXDodoPoolLike(dodoPool);
(uint256 baseReserve, uint256 quoteReserve) = pool.getVaultReserve();
if (baseReserve == 0 || quoteReserve == 0) return false;
if (sampleBaseIn > 0) {
(uint256 quoteOut,) = pool.querySellBase(address(this), sampleBaseIn);
if (quoteOut < minQuoteOut) return false;
}
if (sampleQuoteIn > 0) {
(uint256 baseOut,) = pool.querySellQuote(address(this), sampleQuoteIn);
if (baseOut < minBaseOut) return false;
}
return true;
}
function solvencyState()
external
view
returns (
uint256 cwusdcBalance,
uint256 quoteBalance,
uint256 cwusdcInventory,
uint256 quoteInventory,
bool solvent,
bool executable
)
{
cwusdcBalance = cWUSDC.balanceOf(address(this));
quoteBalance = quoteToken.balanceOf(address(this));
cwusdcInventory = accountedCwusdcInventory;
quoteInventory = accountedQuoteInventory;
solvent = cwusdcBalance >= cwusdcInventory && quoteBalance >= quoteInventory;
executable = canaryPasses();
}
function rescueUnaccountedToken(address token, address to, uint256 amount) external onlyOwner nonReentrant {
require(to != address(0), "zero to");
require(amount > 0, "zero withdraw");
IERC20(token).safeTransfer(to, amount);
_requireSolvent();
emit UnaccountedTokenWithdrawn(token, to, amount);
}
function _validatePool(address pool) internal view {
require(pool != address(0), "zero pool");
require(IEngineXDodoPoolLike(pool)._BASE_TOKEN_() == address(cWUSDC), "unexpected base");
require(IEngineXDodoPoolLike(pool)._QUOTE_TOKEN_() == address(quoteToken), "unexpected quote");
}
function _requireSolvent() internal view {
require(cWUSDC.balanceOf(address(this)) >= accountedCwusdcInventory, "cwusdc insolvent");
require(quoteToken.balanceOf(address(this)) >= accountedQuoteInventory, "quote insolvent");
}
}