contract AssetAdapter {

    uint16 public ASSET_TYPE;
    bytes32 internal EIP712_SWAP_TYPEHASH;
    bytes32 internal EIP712_ASSET_TYPEHASH;

    constructor(
        uint16 assetType,
        bytes32 swapTypehash,
        bytes32 assetTypehash
    ) internal {
        ASSET_TYPE = assetType;
        EIP712_SWAP_TYPEHASH = swapTypehash;
        EIP712_ASSET_TYPEHASH = assetTypehash;
    }

    /**
     * Ensure the described asset is sent to the given address.
     * Should revert if the transfer failed, but callers must also handle `false` being returned,
     * much like ERC20's `transfer`.
     */
    function sendAssetTo(bytes memory assetData, address payable _to) internal returns (bool success);

    /**
     * Ensure the described asset is sent to the contract (check `msg.value` for ether,
     * do a `transferFrom` for tokens, etc).
     * Should revert if the transfer failed, but callers must also handle `false` being returned,
     * much like ERC20's `transfer`.
     *
     * @dev subclasses that don't use ether should mark this with the `noEther` modifier, to make
     * sure no ether is sent -- because, to have one consistent interface, the `create` function
     * in `AbstractRampSwaps` is marked `payable`.
     */
    function lockAssetFrom(bytes memory assetData, address _from) internal returns (bool success);

    /**
     * Returns the EIP712 hash of the handled asset data struct.
     * See `getAssetTypedHash` in the subclasses for asset struct type description.
     */
    function getAssetTypedHash(bytes memory data) internal view returns (bytes32);

    /**
     * Verify that the passed asset data should be handled by this adapter.
     *
     * @dev it's sufficient to use this only when creating a new swap -- all the other swap
     * functions first check if the swap hash is valid, while a swap hash with invalid
     * asset type wouldn't be created at all.
     *
     * @dev asset type is 2 bytes long, and it's at offset 32 in `assetData`'s memory (the first 32
     * bytes are the data length). We load the word at offset 2 (it ends with the asset type bytes),
     * and retrieve its last 2 bytes into a `uint16` variable.
     */
    modifier checkAssetType(bytes memory assetData) {
        uint16 assetType;
        // solium-disable-next-line security/no-inline-assembly
        assembly {
            assetType := and(
                mload(add(assetData, 2)),
                0xffff
            )
        }
        require(assetType == ASSET_TYPE, "invalid asset type");
        _;
    }

    modifier noEther() {
        require(msg.value == 0, "this asset doesn't accept ether");
        _;
    }

}
/**
 * Abstract class for an asset adapter -- a class handling the binary asset description,
 * encapsulating the asset-specific transfer logic.
 * The `assetData` bytes consist of a 2-byte (uint16) asset type, followed by asset-specific data.
 * The asset type bytes must be equal to the `ASSET_TYPE` constant in each subclass.
 *
 * @dev Subclasses of this class are used as mixins to their respective main swap contract.
 *
 * @author Ramp Network sp. z o.o.
 */
function lockAssetFrom(bytes memory assetData, address _from) internal returns (bool success);

/**
 * Ensure the described asset is sent to the contract (check `msg.value` for ether,
 * do a `transferFrom` for tokens, etc).
 * Should revert if the transfer failed, but callers must also handle `false` being returned,
 * much like ERC20's `transfer`.
 *
 * @dev subclasses that don't use ether should mark this with the `noEther` modifier, to make
 * sure no ether is sent -- because, to have one consistent interface, the `create` function
 * in `AbstractRampSwaps` is marked `payable`.
 */