🚧 This documentation is currently under development. Content may be incomplete or subject to change. 🚧
Skip to content

Admins ​

Admins are addresses that have the most permissions on a handle. Admins can:

  • decrypt the handle
  • use the handle as input to create new handles
  • add other addresses as viewers for the handle
  • allow other addresses to become admins for the handle
  • make the handle publicly decryptable

Checking Admins ​

The Nox protocol smart contract provides a function to check if a specific address is an allowed admin for a given handle:

TIP

isAllowed checks admin access specifically. To check viewer access, use isViewer instead (see Manage Viewers).

solidity
function isAllowed(bytes32 handle, address account) external view returns (bool);

isAllowed ABI:

json
[
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "handle",
        "type": "bytes32"
      },
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "isAllowed",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  }
]
ts
const 
noxContract
= new
Contract
(
NOX_CONTRACT_ADDRESS
,
NOX_CONTRACT_ABI
,
provider
); const
isAllowed
: boolean = await
noxContract
.
isAllowed
(
handle
,
account
);
ts
const 
isAllowed
= await
publicClient
.
readContract
({
address
:
NOX_CONTRACT_ADDRESS
,
abi
:
NOX_CONTRACT_ABI
,
functionName
: 'isAllowed',
args
: [
handle
,
account
],
});

Allowing Admins ​

The Nox protocol smart contract provides a function for admins to allow a specific address as an admin for a given handle:

INFO

Only allowed admins can allow new admins.

WARNING

Once allowed, an admin cannot be revoked.

This is by design: once an admin has been granted access, they can decrypt and use the handle at any time. Revoking on-chain permission would give a false sense of security — the admin may have already decrypted and stored the data locally via the Handle Gateway.

solidity
function allow(bytes32 handle, address account) external;

allow ABI:

json
[
  {
    "inputs": [
      {
        "internalType": "bytes32",
        "name": "handle",
        "type": "bytes32"
      },
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "allow",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  }
]
ts
const 
noxContract
= new
Contract
(
NOX_CONTRACT_ADDRESS
,
NOX_CONTRACT_ABI
,
signer
); const
tx
= await
noxContract
.
allow
(
handle
,
accountToAllow
);
await
tx
.wait();
ts
const [
userAddress
] = await
walletClient
.
getAddresses
();
await
walletClient
.
writeContract
({
account
:
userAddress
,
chain
:
CHAIN
,
address
:
NOX_CONTRACT_ADDRESS
,
abi
:
NOX_CONTRACT_ABI
,
functionName
: 'allow',
args
: [
handle
,
accountToAllow
],
});

Isolating Access via a New Handle ​

There is no on-chain revoke for admin access. For use cases that require access isolation (e.g. end of a regulatory audit), the recommended pattern is to migrate to a fresh handle:

  1. Create a new handle with the same value — Nox.add(existingHandle, Nox.toEuint256(0)) produces a new handle with a fresh ACL. Use the matching converter for other types (Nox.toEuint16, Nox.toEbool, etc.).
  2. Update your contract's storage to point to the new handle.
  3. Grant access only to the addresses that should retain access on the new handle.

The old handle remains accessible to previous admins, but is no longer used by your application.

INFO

This pattern costs extra gas and does not destroy the ciphertext on the Handle Gateway. It is an application-level isolation, not a cryptographic revoke.