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).
function isAllowed(bytes32 handle, address account) external view returns (bool);isAllowed ABI:
[
{
"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"
}
]const noxContract = new Contract(
NOX_CONTRACT_ADDRESS,
NOX_CONTRACT_ABI,
provider
);
const isAllowed: boolean = await noxContract.isAllowed(handle, account);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.
function allow(bytes32 handle, address account) external;allow ABI:
[
{
"inputs": [
{
"internalType": "bytes32",
"name": "handle",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "allow",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]const noxContract = new Contract(
NOX_CONTRACT_ADDRESS,
NOX_CONTRACT_ABI,
signer
);
const tx = await noxContract.allow(handle, accountToAllow);
await tx.wait();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:
- 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.). - Update your contract's storage to point to the new handle.
- 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.
