contract FlashPot is ERC20("FlashPot Wrapped Ether", "FWETH", 18), IERC3156FlashLender, ReentrancyGuard, TridentOwnable {
    using SafeTransferLib for address;

    /*///////////////////////////////////////////////////////////////
                            EVENTS
    //////////////////////////////////////////////////////////////*/

    event Deposit(address indexed from, uint256 amount);

    event Withdrawal(address indexed to, uint256 amount);

    /*///////////////////////////////////////////////////////////////
                            ERRORS
    //////////////////////////////////////////////////////////////*/

    error CallbackFailed();

    error RepayFailed();

    /*///////////////////////////////////////////////////////////////
                            FLASH STORAGE
    //////////////////////////////////////////////////////////////*/

    bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");

    uint256 public fee;

    /*///////////////////////////////////////////////////////////////
                            CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(uint256 fee_) {
        fee = fee_;
    }

    /*///////////////////////////////////////////////////////////////
                            FLASH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function flashLoan(
        IERC3156FlashBorrower receiver,
        address,
        uint256 amount,
        bytes calldata data
    ) public override nonReentrant returns (bool) {
        uint256 flee = flashFee(address(0), amount);

        uint256 startingBalance = address(this).balance;

        address(receiver).safeTransferETH(amount);

        if (receiver.onFlashLoan(msg.sender, address(0), amount, flee, data) != CALLBACK_SUCCESS) revert CallbackFailed();

        if (address(this).balance != startingBalance + flee) revert RepayFailed();

        return true;
    }

    function flashFee(
        address,
        uint256 amount
    ) public view override returns (uint256) {
        return amount * fee / 10000;
    }

    function maxFlashLoan(address) public view override returns (uint256) {
        return address(this).balance;
    }

    /*///////////////////////////////////////////////////////////////
                            WRAP OPERATIONS
    //////////////////////////////////////////////////////////////*/
    
    function deposit() public payable nonReentrant {
        uint256 totalShares = totalSupply;

        uint256 totalETH = address(this).balance - msg.value;

        if (totalShares == 0 || totalETH == 0) {
            _mint(msg.sender, msg.value);
        } else {
            uint256 what = (msg.value * totalShares) / totalETH;
            _mint(msg.sender, what);
        }

        emit Deposit(msg.sender, msg.value);
    }

    function withdraw(uint256 share) public nonReentrant {
        uint256 what = (share * address(this).balance) / totalSupply;

        _burn(msg.sender, share);

        msg.sender.safeTransferETH(what);

        emit Withdrawal(msg.sender, share);
    }

    receive() external payable {}

    /*///////////////////////////////////////////////////////////////
                            GOVERNANCE
    //////////////////////////////////////////////////////////////*/

    function updateFlashFee(uint256 fee_) public onlyOwner {
        fee = fee_;
    }
}
/// @notice Flash-lendable ETH wrapper with elastic shares.
function updateFlashFee(uint256 fee_) public onlyOwner {
    fee = fee_;
}

/*///////////////////////////////////////////////////////////////
 GOVERNANCE
 //////////////////////////////////////////////////////////////*/