> ## Documentation Index
> Fetch the complete documentation index at: https://docsuncv2.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# setreadonly

Locks or unlocks a table - locked tables can't have their contents changed until they're unlocked.

```luau theme={null}
setreadonly(t: table, readonly: boolean): ()
```

Most commonly used to lock the table again after unlocking it.

## Parameters

| Parameter  | Type      | Description                                 |
| ---------- | --------- | ------------------------------------------- |
| `t`        | `table`   | The table to lock or unlock.                |
| `readonly` | `boolean` | `true` locks the table, `false` unlocks it. |

## Returns

<code title="the function does not return a value.">void</code>

## Example

Hook the \_\_namecall metamethod, and prevent the \<RemoteEvent> UpdateFPS from firing.

<CodeGroup>
  ```luau Example 1 theme={null}
  <<<<<<< HEAD
  setreadonly(getrawmetatable(game), false)
  =======
  -- setreadonly(t: table, readonly: boolean): ()
  >>>>>>> 50e30f53759b0538759af25c9b271514aa2c9290
  ```

  ```luau Example 2 theme={null}
  local updatefps = game:GetService("ReplicatedStorage"):WaitForChild("UpdateFPS")

  local prev = getidentity()
  setidentity(3)

  local mt = getrawmetatable(game)
  local oldNamecall = mt.__namecall

  setreadonly(mt, false)
  mt.__namecall = newcclosure(function(self, ...)
      -- block FireServer on updatefps from the game's own scripts and let seliware through
      if self == updatefps and not checkcaller() then
          local method = getnamecallmethod()

          if method == "FireServer" or method == "fireServer" then
              return
          end
      end

      return oldNamecall(self, ...)
  end)
  setreadonly(mt, true)

  setidentity(prev)
  ```
</CodeGroup>

<Tip>
  Unified wrapper equivalent to calling `makereadonly` or `makewritable`.
</Tip>
