abstract contract EthAdapter is AssetAdapterWithFees {

    uint16 internal constant ETH_TYPE_ID = 1;
    uint16 internal constant ETH_ASSET_DATA_LENGTH = 66;
    uint256 internal accumulatedFees = 0;

    constructor() AssetAdapter(ETH_TYPE_ID) {}

    /**
    * @dev extract the amount from the asset data bytes. ETH assetData bytes contents:
    * offset length type     contents
    * +00    32     uint256  data length (== 0x22 == 34 bytes)
    * +32     2     uint16   asset type  (== ETH_TYPE_ID == 1)
    * +34    32     uint256  ether amount in wei
    * +66    32     uint256  ether fee in wei
    */
    function getAmount(bytes memory assetData) internal override pure returns (uint256 amount) {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            amount := mload(add(assetData, 34))
        }
    }

    /**
     * @dev extract the fee from the asset data bytes. See getAmount for bytes contents.
     */
    function getFee(bytes memory assetData) internal override pure returns (uint256 fee) {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            fee := mload(add(assetData, 66))
        }
    }

    function rawSendAsset(
        bytes memory /*assetData*/,
        uint256 _amount,
        address payable _to
    ) internal override returns (bool success) {
        // To enable more complex purchase receiver contracts, we're using `call.value(...)` instead
        // of plain `transfer(...)`, which allows only 2300 gas to be used by the fallback function.
        // This works for transfers to plain accounts too, no need to check if it's a contract.
        // solhint-disable-next-line avoid-low-level-calls
        (bool transferSuccessful,) = _to.call{ value:_amount }("");
        require(transferSuccessful, "etf");  // "eth transfer failed"
        return true;
    }

    function accumulateFee(bytes memory assetData) internal override {
        accumulatedFees += getFee(assetData);
    }

    function withdrawFees(
        bytes calldata /*assetData*/,
        address payable _to
    ) external override onlyOwner returns (bool success) {
        uint256 fees = accumulatedFees;
        accumulatedFees = 0;
        _to.transfer(fees);
        return true;
    }

    /**
     * This adapter can receive eth payments, but no other use of the fallback function is allowed.
     * @dev this is the "receive ether" fallback function, split off from the regular fallback
     * function in Solidity 0.6
     */
    receive () external payable {}

    function checkAssetData(bytes memory assetData, address /*_pool*/) internal override pure {
        require(assetData.length == ETH_ASSET_DATA_LENGTH, "adl");  // "invalid asset data length"
    }

    function getAccumulatedFees(address /*_assetAddress*/) public override view returns (uint256) {
        return accumulatedFees;
    }

}
/**
 * An adapter for handling ether assets.
 *
 * @author Ramp Network sp. z o.o.
 */
/**
 * This adapter can receive eth payments, but no other use of the fallback function is allowed.
 * @dev this is the "receive ether" fallback function, split off from the regular fallback
 * function in Solidity 0.6
 */