library TransferImpl {

    // ============ Public Implementation Functions ============

    function transferLoanImpl(
        MarginState.State storage state,
        bytes32 positionId,
        address newLender
    )
        public
    {
        require(
            MarginCommon.containsPositionImpl(state, positionId),
            "TransferImpl#transferLoanImpl: Position does not exist"
        );

        address originalLender = state.positions[positionId].lender;

        require(
            msg.sender == originalLender,
            "TransferImpl#transferLoanImpl: Only lender can transfer ownership"
        );
        require(
            newLender != originalLender,
            "TransferImpl#transferLoanImpl: Cannot transfer ownership to self"
        );

        // Doesn't change the state of positionId; figures out the final owner of loan.
        // That is, newLender may pass ownership to a different address.
        address finalLender = TransferInternal.grantLoanOwnership(
            positionId,
            originalLender,
            newLender);

        require(
            finalLender != originalLender,
            "TransferImpl#transferLoanImpl: Cannot ultimately transfer ownership to self"
        );

        // Set state only after resolving the new owner (to reduce the number of storage calls)
        state.positions[positionId].lender = finalLender;
    }

    function transferPositionImpl(
        MarginState.State storage state,
        bytes32 positionId,
        address newOwner
    )
        public
    {
        require(
            MarginCommon.containsPositionImpl(state, positionId),
            "TransferImpl#transferPositionImpl: Position does not exist"
        );

        address originalOwner = state.positions[positionId].owner;

        require(
            msg.sender == originalOwner,
            "TransferImpl#transferPositionImpl: Only position owner can transfer ownership"
        );
        require(
            newOwner != originalOwner,
            "TransferImpl#transferPositionImpl: Cannot transfer ownership to self"
        );

        // Doesn't change the state of positionId; figures out the final owner of position.
        // That is, newOwner may pass ownership to a different address.
        address finalOwner = TransferInternal.grantPositionOwnership(
            positionId,
            originalOwner,
            newOwner);

        require(
            finalOwner != originalOwner,
            "TransferImpl#transferPositionImpl: Cannot ultimately transfer ownership to self"
        );

        // Set state only after resolving the new owner (to reduce the number of storage calls)
        state.positions[positionId].owner = finalOwner;
    }
}
/**
 * @title TransferImpl
 * @author dYdX
 *
 * This library contains the implementation for the transferPosition and transferLoan functions of
 * Margin
 */
function transferLoanImpl(
    MarginState.State storage state,
    bytes32 positionId,
    address newLender
)
    public
{
    require(
        MarginCommon.containsPositionImpl(state, positionId),
        "TransferImpl#transferLoanImpl: Position does not exist"
    );

    address originalLender = state.positions[positionId].lender;

    require(
        msg.sender == originalLender,
        "TransferImpl#transferLoanImpl: Only lender can transfer ownership"
    );
    require(
        newLender != originalLender,
        "TransferImpl#transferLoanImpl: Cannot transfer ownership to self"
    );

    // Doesn't change the state of positionId; figures out the final owner of loan.
    // That is, newLender may pass ownership to a different address.
    address finalLender = TransferInternal.grantLoanOwnership(
        positionId,
        originalLender,
        newLender);

    require(
        finalLender != originalLender,
        "TransferImpl#transferLoanImpl: Cannot ultimately transfer ownership to self"
    );

    // Set state only after resolving the new owner (to reduce the number of storage calls)
    state.positions[positionId].lender = finalLender;
}

// ============ Public Implementation Functions ============