diff --git a/crates/lune-std-ffi/src/ffi/ffi_ref/flags.rs b/crates/lune-std-ffi/src/ffi/ffi_ref/flags.rs
index 114f67c..b6a2ca7 100644
--- a/crates/lune-std-ffi/src/ffi/ffi_ref/flags.rs
+++ b/crates/lune-std-ffi/src/ffi/ffi_ref/flags.rs
@@ -22,7 +22,7 @@ impl FfiRefFlag {
 pub struct FfiRefFlagList(u8);
 #[allow(unused)]
 impl FfiRefFlagList {
-    pub fn zero() -> Self {
+    pub const fn zero() -> Self {
         Self(0)
     }
     pub const fn new(flags: u8) -> Self {
diff --git a/crates/lune-std-ffi/src/ffi/ffi_ref/mod.rs b/crates/lune-std-ffi/src/ffi/ffi_ref/mod.rs
index 4412828..ccd5589 100644
--- a/crates/lune-std-ffi/src/ffi/ffi_ref/mod.rs
+++ b/crates/lune-std-ffi/src/ffi/ffi_ref/mod.rs
@@ -16,6 +16,9 @@ pub use self::{
     flags::{FfiRefFlag, FfiRefFlagList},
 };
 
+// Box:ref():ref() should not be able to modify, Only for external
+const BOX_REF_REF_FLAGS: FfiRefFlagList = FfiRefFlagList::zero();
+
 // A referenced space. It is possible to read and write through types.
 // This operation is not safe. This may cause a memory error in Lua
 // if use it incorrectly.
@@ -46,15 +49,10 @@ impl FfiRef {
         this: LuaAnyUserData<'lua>,
     ) -> LuaResult<LuaAnyUserData<'lua>> {
         let target = this.borrow::<FfiRef>()?;
-        let mut flags = target.flags.clone();
-
-        // FIXME:
-        // We cannot dereference ref which created by lua, in lua
-        flags.set_dereferenceable(false);
 
         let luaref = lua.create_userdata(FfiRef::new(
             ptr::from_ref(&target.ptr) as *mut (),
-            flags,
+            BOX_REF_REF_FLAGS,
             FfiRefBounds {
                 below: 0,
                 above: size_of::<usize>(),
diff --git a/tests/ffi/box-recursion-gc.luau b/tests/ffi/box-recursion-gc.luau
new file mode 100644
index 0000000..d86d045
--- /dev/null
+++ b/tests/ffi/box-recursion-gc.luau
@@ -0,0 +1,20 @@
+--!nocheck
+--!nolint
+
+local ffi = require("@lune/ffi")
+
+local box = ffi.box(ffi.u8:ptr().size)
+local ref = box:ref()
+ffi.u8:ptr():into(box, ref)
+
+local wt = setmetatable({}, { __mode = "v" })
+
+wt[1] = box
+wt[2] = ref
+
+box = nil
+ref = nil
+
+collectgarbage("collect")
+
+assert(wt[1] == nil and wt[2] == nil, "Box - ref recursion GC test failed")
diff --git a/tests/ffi/cast.luau b/tests/ffi/cast.luau
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ffi/external.luau b/tests/ffi/external.luau
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ffi/from-boundary.luau b/tests/ffi/from-boundary.luau
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ffi/into-boundary.luau b/tests/ffi/into-boundary.luau
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ffi/isInteger.luau b/tests/ffi/isInteger.luau
new file mode 100644
index 0000000..1084b8f
--- /dev/null
+++ b/tests/ffi/isInteger.luau
@@ -0,0 +1,10 @@
+--!nocheck
+--!nolint
+
+local ffi = require("@lune/ffi")
+
+local int = 0b1
+local float = 0.5
+
+assert(ffi.isInteger(int) == true, "ffi.isInteger(int) == true failed")
+assert(ffi.isInteger(float) == false, "ffi.isInteger(float) == false failed")
diff --git a/tests/ffi/ptr.luau b/tests/ffi/ptr.luau
deleted file mode 100644
index c62eadf..0000000
--- a/tests/ffi/ptr.luau
+++ /dev/null
@@ -1,33 +0,0 @@
-
-local ffi = require("@lune/ffi")
-
--- ptr size test
-assert(
-    ffi.i32:ptr().size == ffi.i64:ptr().size,
-    "All of Ptr.size must be same.\n"..
-    "ffi.i32:ptr().size == ffi.i64:ptr().size failed"
-)
-
--- inner test
-local i32ptr = ffi.i32:ptr()
-assert(
-    rawequal(ffi.i32, i32ptr.inner),
-    "Ptr.inner must be same with their parent\n"..
-    "raweq ffi.i32 == ffi.i32:ptr().inner failed"
-)
-assert(
-    rawequal(i32ptr, i32ptr:ptr().inner),
-    "Ptr.inner must be same with their parent\n"..
-    "raweq i32ptr == i32ptr:ptr().inner failed"
-)
-assert(
-    rawequal(i32ptr, i32ptr:ptr().inner:ptr().inner:ptr().inner),
-    "Ptr.inner must be same with their parent\n"..
-    "raweq i32ptr == i32ptr:ptr().inner:ptr().inner:ptr().inner failed"
-)
-
--- deep ptr test
-local ok,err = pcall(function()
-    i32ptr:ptr():ptr():ptr():ptr():ptr():ptr():ptr()
-end)
-assert(ok,`Deep ptr test failed.\n{err}`)
diff --git a/tests/ffi/ref-hold-box.luau b/tests/ffi/ref-hold-box.luau
new file mode 100644
index 0000000..f6f1490
--- /dev/null
+++ b/tests/ffi/ref-hold-box.luau
@@ -0,0 +1,15 @@
+--!nocheck
+--!nolint
+
+local ffi = require("@lune/ffi")
+local box = ffi.box(ffi.i32.size)
+local ref = box:ref()
+
+local wt = setmetatable({}, { __mode = "v" })
+
+wt[1] = box
+box = nll
+
+collectgarbage("collect")
+
+assert(wt[1] ~= nil, "ref hold box failed")
diff --git a/tests/ffi/struct.luau b/tests/ffi/struct.luau
deleted file mode 100644
index e1c1f8d..0000000
--- a/tests/ffi/struct.luau
+++ /dev/null
@@ -1,2 +0,0 @@
-
-local ffi = require("@lune/ffi")
diff --git a/tests/ffi/types/arr.luau b/tests/ffi/types/arr.luau
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ffi/types/fn.luau b/tests/ffi/types/fn.luau
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ffi/types/ptr.luau b/tests/ffi/types/ptr.luau
new file mode 100644
index 0000000..cdbc2fe
--- /dev/null
+++ b/tests/ffi/types/ptr.luau
@@ -0,0 +1,32 @@
+--!nocheck
+--!nolint
+
+local ffi = require("@lune/ffi")
+
+-- ptr size test
+assert(
+	ffi.i32:ptr().size == ffi.i64:ptr().size,
+	"All of Ptr.size must be same.\n" .. "ffi.i32:ptr().size == ffi.i64:ptr().size failed"
+)
+
+-- inner test
+local i32ptr = ffi.i32:ptr()
+assert(
+	rawequal(ffi.i32, i32ptr.inner),
+	"Ptr.inner must be same with their parent\n" .. "raweq ffi.i32 == ffi.i32:ptr().inner failed"
+)
+assert(
+	rawequal(i32ptr, i32ptr:ptr().inner),
+	"Ptr.inner must be same with their parent\n" .. "raweq i32ptr == i32ptr:ptr().inner failed"
+)
+assert(
+	rawequal(i32ptr, i32ptr:ptr().inner:ptr().inner:ptr().inner),
+	"Ptr.inner must be same with their parent\n"
+		.. "raweq i32ptr == i32ptr:ptr().inner:ptr().inner:ptr().inner failed"
+)
+
+-- deep ptr test
+local ok, err = pcall(function()
+	i32ptr:ptr():ptr():ptr():ptr():ptr():ptr():ptr()
+end)
+assert(ok, `Deep ptr test failed.\n{err}`)
diff --git a/tests/ffi/types/struct.luau b/tests/ffi/types/struct.luau
new file mode 100644
index 0000000..a955e71
--- /dev/null
+++ b/tests/ffi/types/struct.luau
@@ -0,0 +1,12 @@
+--!nocheck
+--!nolint
+
+local ffi = require("@lune/ffi")
+
+local i32ptr = ffi.i32:ptr()
+local struct = ffi.struct({ i32ptr, ffi.i32 })
+
+assert(rawequal(struct:field(0), i32ptr), "Struct get field failed")
+assert(rawequal(struct:field(1), ffi.i32), "Struct get field failed")
+
+-- offset(2) should fail