abstract contract VoxStrategyCurveBase is VoxStrategyBase {
    // curve dao
    address public curve;
    address public gauge;
    address public mintr = 0xd061D61a4d941c39E5453435B6345Dc261C2fcE0;

    // stablecoins
    address public dai = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
    address public usdc = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
    address public usdt = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
    address public susd = 0x57Ab1ec28D129707052df4dF418D58a2D46d5f51;

    // bitcoins
    address public renbtc = 0xEB4C2781e4ebA804CE9a9803C67d0893436bB27D;

    // rewards
    address public crv = 0xD533a949740bb3306d119CC777fa900bA034cd52;

    // keep
    address public keep = 0x85Eee30c52B0b379b046Fb0F85F4f3Dc3009aFEC;
    address public keep_rewards = 0x6828bcF74279eE32f2723eC536c22c51Eed383C6;

    // How much CRV tokens to keep
    uint256 public keepCRV = 0;
    uint256 public keepCRVMax = 10000;

    constructor(
        address _curve,
        address _gauge,
        address _underlying,
        address _governance,
        address _strategist,
        address _treasury,
        address _devfund,
        address _timelock,
        address _vault
    )
        public
        VoxStrategyBase(_underlying, _governance, _strategist, _treasury, _devfund, _timelock, _vault)
    {
        curve = _curve;
        gauge = _gauge;
    }

    // **** Getters ****

    function balanceOfPool() public override view returns (uint256) {
        return ICurveGauge(gauge).balanceOf(address(this));
    }

    function getHarvestable() external returns (uint256) {
        return ICurveGauge(gauge).claimable_tokens(address(this));
    }

    function getMostPremium() public virtual view returns (address, uint256);

    // **** Setters ****

    function setKeepCRV(uint256 _keepCRV) external {
        require(msg.sender == governance, "!governance");
        keepCRV = _keepCRV;
    }

    // **** State Mutation functions ****

    function deposit() public override {
        uint256 _underlying = IERC20(underlying).balanceOf(address(this));
        if (_underlying > 0) {
            IERC20(underlying).safeApprove(gauge, 0);
            IERC20(underlying).safeApprove(gauge, _underlying);
            ICurveGauge(gauge).deposit(_underlying);
        }
    }

    function _withdrawSome(uint256 _amount)
        internal
        override
        returns (uint256)
    {
        ICurveGauge(gauge).withdraw(_amount);
        return _amount;
    }
}
// Base contract for Curve based vault strategies
function balanceOfPool() public override view returns (uint256) {
    return ICurveGauge(gauge).balanceOf(address(this));
}

// **** Getters ****