It is on the block header. You can see this from v$bh,
SQL> alter system flush buffer_cache;
System altered.
SQL> create table t ( x primary key, y ) as select 1 x, 2 y from dual;
Table created.
SQL> select data_object_id from user_objects where object_name = 'T';
DATA_OBJECT_ID
--------------
101919
SQL>
SQL> select
2 dbms_rowid.rowid_relative_fno(rowid) f,
3 dbms_rowid.rowid_block_number(rowid) b
4 from t;
F B
---------- ----------
7 16259
--
-- here's the freshly created block
--
SQL> select status
2 from v$bh
3 where file# = 7
4 and block# = 16259
5 and objd = 101919
6 /
STATUS
----------
xcur
--
-- if I flush the buffer cache, the block is still "there" but its marked as free, ie, I could replace it
-- with something else
--
SQL> alter system flush buffer_cache;
System altered.
SQL> select status
2 from v$bh
3 where file# = 7
4 and block# = 16259
5 and objd = 101919
6 /
STATUS
----------
free
--
-- I query it back in, and it is the current version of this block because
-- nothing else has ever need to read it consistently
--
SQL> select * from t where x=1;
X Y
---------- ----------
1 2
SQL> select objd, status
2 from v$bh
3 where file# = 7
4 and block# = 16259
5 and objd = 101919
6 /
OBJD STATUS
---------- ----------
101919 xcur
--
-- now I delete it (without commit)
--
SQL> delete from t;
SQL> select objd, status, dirty
2 from v$bh
3 where file# = 7
4 and block# = 16259
5 and objd = 101919
6 /
OBJD STATUS DIRTY
---------- ---------- -----
101919 xcur Y
--
-- and now another session gets an older version of it via a query
--
SQL> select * from t where x=1;
X Y
---------- ----------
1 2
--
-- and we can see the consistent version be created
--
SQL> select objd, status
2 from v$bh
3 where file# = 7
4 and block# = 16259
5 and objd = 101919
6 /
OBJD STATUS
---------- ----------
101919 xcur
101919 cr
But in simplest conceptual form, the SCN can drive all of this.
When I run a query, I am effectively saying "I need all block as of SCN 1234" (ie, SCN when the query started).
As I encounter a block, whether it is dirty or not, committed or not, my requirement will be - is the SCN on this block equal to or before 1234. If it is not, then the block is too "new" for me, being a signal that I need to get an older version of it.