Files
smom-dbis-138/contracts/flash/DBISEngineXFlashProofBorrower.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

88 lines
3.3 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {IERC3156FlashBorrower} from "@openzeppelin/contracts/interfaces/IERC3156FlashBorrower.sol";
import {IERC3156FlashLender} from "@openzeppelin/contracts/interfaces/IERC3156FlashLender.sol";
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";
/// @notice Minimal Engine X ERC-3156 borrower for proving same-transaction USDC working capital.
/// @dev Prefund this contract with at least the flash fee before calling `runFlashProof`.
contract DBISEngineXFlashProofBorrower is IERC3156FlashBorrower, Ownable {
using SafeERC20 for IERC20;
bytes32 private constant _RETURN_VALUE = keccak256("ERC3156FlashBorrower.onFlashLoan");
IERC3156FlashLender public immutable lender;
IERC20 public immutable usdc;
mapping(bytes32 => bool) public usedProofIds;
event EngineXFlashProof(
bytes32 indexed proofId,
address indexed initiator,
address indexed lender,
address token,
uint256 amount,
uint256 fee,
bytes32 iso20022DocumentHash,
bytes32 auditEnvelopeHash,
bytes32 pegProofHash
);
constructor(address lender_, address usdc_, address owner_) Ownable(owner_) {
require(lender_ != address(0) && usdc_ != address(0), "zero address");
lender = IERC3156FlashLender(lender_);
usdc = IERC20(usdc_);
}
function runFlashProof(
uint256 amount,
bytes32 proofId,
bytes32 iso20022DocumentHash,
bytes32 auditEnvelopeHash,
bytes32 pegProofHash
) external onlyOwner returns (bool) {
require(proofId != bytes32(0), "zero proof");
require(!usedProofIds[proofId], "proof used");
require(iso20022DocumentHash != bytes32(0), "zero iso hash");
require(auditEnvelopeHash != bytes32(0), "zero audit hash");
require(pegProofHash != bytes32(0), "zero peg hash");
bytes memory data = abi.encode(msg.sender, proofId, iso20022DocumentHash, auditEnvelopeHash, pegProofHash);
return lender.flashLoan(this, address(usdc), amount, data);
}
function onFlashLoan(address initiator, address token, uint256 amount, uint256 fee, bytes calldata data)
external
override
returns (bytes32)
{
require(msg.sender == address(lender), "bad lender");
require(initiator == address(this), "bad initiator");
require(token == address(usdc), "bad token");
(
address operator,
bytes32 proofId,
bytes32 iso20022DocumentHash,
bytes32 auditEnvelopeHash,
bytes32 pegProofHash
) = abi.decode(data, (address, bytes32, bytes32, bytes32, bytes32));
require(!usedProofIds[proofId], "proof used");
usedProofIds[proofId] = true;
usdc.forceApprove(msg.sender, amount + fee);
emit EngineXFlashProof(
proofId, operator, msg.sender, token, amount, fee, iso20022DocumentHash, auditEnvelopeHash, pegProofHash
);
return _RETURN_VALUE;
}
function withdraw(address token, address to, uint256 amount) external onlyOwner {
require(to != address(0), "zero to");
IERC20(token).safeTransfer(to, amount);
}
}