contract NativeEtherWrapper is Owned, MixinResolver {
    bytes32 private constant CONTRACT_ETHER_WRAPPER = "EtherWrapper";
    bytes32 private constant CONTRACT_SYNTHSETH = "SynthsETH";

    constructor(address _owner, address _resolver) public Owned(_owner) MixinResolver(_resolver) {}

    /* ========== PUBLIC FUNCTIONS ========== */

    /* ========== VIEWS ========== */
    function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
        bytes32[] memory addresses = new bytes32[](2);
        addresses[0] = CONTRACT_ETHER_WRAPPER;
        addresses[1] = CONTRACT_SYNTHSETH;
        return addresses;
    }

    function etherWrapper() internal view returns (IEtherWrapper) {
        return IEtherWrapper(requireAndGetAddress(CONTRACT_ETHER_WRAPPER));
    }

    function weth() internal view returns (IWETH) {
        return etherWrapper().weth();
    }

    function synthsETH() internal view returns (IERC20) {
        return IERC20(requireAndGetAddress(CONTRACT_SYNTHSETH));
    }

    /* ========== MUTATIVE FUNCTIONS ========== */

    function mint() public payable {
        uint amount = msg.value;
        require(amount > 0, "msg.value must be greater than 0");

        // Convert sent ETH into WETH.
        weth().deposit.value(amount)();

        // Approve for the EtherWrapper.
        weth().approve(address(etherWrapper()), amount);

        // Now call mint.
        etherWrapper().mint(amount);

        // Transfer the sETH to msg.sender.
        synthsETH().transfer(msg.sender, synthsETH().balanceOf(address(this)));

        emit Minted(msg.sender, amount);
    }

    function burn(uint amount) public {
        require(amount > 0, "amount must be greater than 0");
        IWETH weth = weth();

        // Transfer sETH from the msg.sender.
        synthsETH().transferFrom(msg.sender, address(this), amount);

        // Approve for the EtherWrapper.
        synthsETH().approve(address(etherWrapper()), amount);

        // Now call burn.
        etherWrapper().burn(amount);

        // Convert WETH to ETH and send to msg.sender.
        weth.withdraw(weth.balanceOf(address(this)));
        // solhint-disable avoid-low-level-calls
        msg.sender.call.value(address(this).balance)("");

        emit Burned(msg.sender, amount);
    }

    function() external payable {
        // Allow the WETH contract to send us ETH during
        // our call to WETH.deposit. The gas stipend it gives
        // is 2300 gas, so it's not possible to do much else here.
    }

    /* ========== EVENTS ========== */
    // While these events are replicated in the core EtherWrapper,
    // it is useful to see the usage of the NativeEtherWrapper contract.
    event Minted(address indexed account, uint amount);
    event Burned(address indexed account, uint amount);
}
// @unsupported: ovm
// Inheritance
// Internal references
// https://docs.synthetix.io/contracts/source/contracts/nativeetherwrapper
function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
    bytes32[] memory addresses = new bytes32[](2);
    addresses[0] = CONTRACT_ETHER_WRAPPER;
    addresses[1] = CONTRACT_SYNTHSETH;
    return addresses;
}

/* ========== VIEWS ========== */