Description
Code
DVM: The DVM contract is designed to set up and manage the basic configurations of a decentralized trading platform, including fee rates, trading parameters, and the TWAP toggle.
DVMFunding: Deal with the shares.
DVMTrader: Deal with the flashloan & Base Tokens.
Goal
Make WETH.balanceOf(dvm) == 0;, Start with 100 ether
Solution
The DVM is a DODO Vending Machine that is designed to sell tokens without large initial liquidity requirements.
Beacuse it is cloned, so when i check the init() function, i found that everyone can call the init(), it is external.
contract DVM is DVMTrader, DVMFunding {
    function init(
        address maintainer,
        address baseTokenAddress,
        address quoteTokenAddress,
        uint256 lpFeeRate,
        address mtFeeRateModel,
        uint256 i,
        uint256 k,
        bool isOpenTWAP
    ) external {
        require(baseTokenAddress != quoteTokenAddress, "BASE_QUOTE_CAN_NOT_BE_SAME");
        _BASE_TOKEN_ = IERC20(baseTokenAddress);
        _QUOTE_TOKEN_ = IERC20(quoteTokenAddress);
        require(i > 0 && i <= 10**36);
        _I_ = i;
        require(k <= 10**18);
        _K_ = k;
        _LP_FEE_RATE_ = lpFeeRate;
        _MT_FEE_RATE_MODEL_ = IFeeRateModel(mtFeeRateModel);
        _MAINTAINER_ = maintainer;
        _IS_OPEN_TWAP_ = isOpenTWAP;
        if(isOpenTWAP) _BLOCK_TIMESTAMP_LAST_ = uint32(block.timestamp % 2**32);
        string memory connect = "_";
        string memory suffix = "DLP";
        name = string(abi.encodePacked(suffix, connect, addressToShortString(address(this))));
        symbol = "DLP";
        decimals = _BASE_TOKEN_.decimals();
        // ============================== Permit ====================================
        uint256 chainId;
        assembly {
            chainId := chainid()
        }
        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                // keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
                0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f,
                keccak256(bytes(name)),
                keccak256(bytes("1")),
                chainId,
                address(this)
            )
        );
        // ==========================================================================
    }
So we can call flashloan, and in our callback function, we can call the init(), change the baseToken and QuoteToken address.
function flashLoan(
    uint256 baseAmount,
    uint256 quoteAmount,
    address assetTo,
    bytes calldata data
) external preventReentrant {
    _transferBaseOut(assetTo, baseAmount);
    _transferQuoteOut(assetTo, quoteAmount);
    if (data.length > 0)
        IDODOCallee(assetTo).DVMFlashLoanCall(msg.sender, baseAmount, quoteAmount, data);
    uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this));
    uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this));
    // no input -> pure loss
    require(
        baseBalance >= _BASE_RESERVE_ || quoteBalance >= _QUOTE_RESERVE_,
        "FLASH_LOAN_FAILED"
    );
    // sell quote
    if (baseBalance < _BASE_RESERVE_) {
        uint256 quoteInput = quoteBalance.sub(uint256(_QUOTE_RESERVE_));
        (uint256 receiveBaseAmount, uint256 mtFee) = querySellQuote(tx.origin, quoteInput);
        require(uint256(_BASE_RESERVE_).sub(baseBalance) <= receiveBaseAmount, "FLASH_LOAN_FAILED");
        _transferBaseOut(_MAINTAINER_, mtFee);
        emit DODOSwap(
            address(_QUOTE_TOKEN_),
            address(_BASE_TOKEN_),
            quoteInput,
            receiveBaseAmount,
            msg.sender,
            assetTo
        );
    }
    // sell base
    if (quoteBalance < _QUOTE_RESERVE_) {
        uint256 baseInput = baseBalance.sub(uint256(_BASE_RESERVE_));
        (uint256 receiveQuoteAmount, uint256 mtFee) = querySellBase(tx.origin, baseInput);
        require(uint256(_QUOTE_RESERVE_).sub(quoteBalance) <= receiveQuoteAmount, "FLASH_LOAN_FAILED");
        _transferQuoteOut(_MAINTAINER_, mtFee);
        emit DODOSwap(
            address(_BASE_TOKEN_),
            address(_QUOTE_TOKEN_),
            baseInput,
            receiveQuoteAmount,
            msg.sender,
            assetTo
        );
    }
    _sync();
    emit DODOFlashLoan(msg.sender, assetTo, baseAmount, quoteAmount);
}