It may not be appropriate to get rid of the full table scan, if the majority (or even a large minority) of the rows in contract_history match the WHERE clause condition. Full scans are not inherently bad.
However, if the WHERE clause really only matches a small proportion of the rows, then you could perhaps add an index such as:
create index contract_history_idx on contract_history
( nvl(ch_pending,'X'), ch_validfrom);
Then change the query to:
select nvl (max (ch_validfrom), sysdate)
where nvl(ch_pending,'X') != 'X';
Oracle can then answer this query using the index alone.