contract wSQUID is ERC20 {
    using SafeERC20 for ERC20;
    using Address for address;
    using SafeMath for uint;

    address public immutable staking;
    address public immutable SQUID;
    address public immutable sSQUID;

    constructor( address _staking, address _SQUID, address _sSQUID ) ERC20( 'Wrapped sSQUID', 'wsSQUID' ) {
        require( _staking != address(0) );
        staking = _staking;
        require( _SQUID != address(0) );
        SQUID = _SQUID;
        require( _sSQUID != address(0) );
        sSQUID = _sSQUID;
    }

    /**
        @notice stakes SQUID and wraps sSQUID
        @param _amount uint
        @return uint
     */
    function wrapFromSQUID( uint _amount ) external returns ( uint ) {
        IERC20( SQUID ).transferFrom( msg.sender, address(this), _amount );

        IERC20( SQUID ).approve( staking, _amount ); // stake SQUID for sSQUID
        IStaking( staking ).stake( _amount, address(this) );

        uint value = wSQUIDValue( _amount );
        _mint( msg.sender, value );
        return value;
    }

    /**
        @notice unwrap sSQUID and unstake SQUID
        @param _amount uint
        @return uint
     */
    function unwrapToSQUID( uint _amount ) external returns ( uint ) {
        _burn( msg.sender, _amount );

        uint value = sSQUIDValue( _amount );
        IERC20( sSQUID ).approve( staking, value ); // unstake sSQUID for SQUID
        IStaking( staking ).unstake( value, address(this) );

        IERC20( SQUID ).transfer( msg.sender, value );
        return value;
    }

    /**
        @notice wrap sSQUID
        @param _amount uint
        @return uint
     */
    function wrapFromsSQUID( uint _amount ) external returns ( uint ) {
        IERC20( sSQUID ).transferFrom( msg.sender, address(this), _amount );

        uint value = wSQUIDValue( _amount );
        _mint( msg.sender, value );
        return value;
    }

    /**
        @notice unwrap sSQUID
        @param _amount uint
        @return uint
     */
    function unwrapTosSQUID( uint _amount ) external returns ( uint ) {
        _burn( msg.sender, _amount );

        uint value = sSQUIDValue( _amount );
        IERC20( sSQUID ).transfer( msg.sender, value );
        return value;
    }

    /**
        @notice converts wSQUID amount to sSQUID
        @param _amount uint
        @return uint
     */
    function sSQUIDValue( uint _amount ) public view returns ( uint ) {
        return _amount.mul( IStaking( staking ).index() ).div( 10 ** decimals() );
    }

    /**
        @notice converts sSQUID amount to wSQUID
        @param _amount uint
        @return uint
     */
    function wSQUIDValue( uint _amount ) public view returns ( uint ) {
        return _amount.mul( 10 ** decimals() ).div( IStaking( staking ).index() );
    }

}
function wrapFromsSQUID( uint _amount ) external returns ( uint ) {
    IERC20( sSQUID ).transferFrom( msg.sender, address(this), _amount );

    uint value = wSQUIDValue( _amount );
    _mint( msg.sender, value );
    return value;
}

/**
 @notice wrap sSQUID
 @param _amount uint
 @return uint
 */