This guide will show you how to customize token transferability logic on Etherscan or similar block explorers.
Transfering a token is one “operation” you can take on a token contract, both through the
v0.4.0 of 0xRails, all tokens come with a Guard system that enables
adding custom logic to only allow operations under certain conditions. Each guard setting is stored as a
mapping(bytes8 => address)
which connects an operation key to the Guard contract to use when that operation is triggered.
To read the current values, call
guardOf(bytes8) to get the Guard of a specific operation or
getAllGuards() to get all Guards set.
You can do this from Etherscan by navigating to your contract’s page and opening the
If you do not see your contracts function, you will need to click “Is this a proxy?” and complete the flow to pull the contract interface.
Afterwards, you should be able to call view functions under the “Read as Proxy” sectino and write data under the “Write as Proxy” section.
To mutate a Guard value, call the
setGuard(bytes8, address) function on your token contract from an address with the
You can view token admins in the settings page on the GroupOS app and the token owner also has this permission by defualt.
operation input, paste
0x5cc15eb80ba37777 for indicating transfer, calculated by taking the first 8 bytes of
implementation input will be the Guard contract that should be called when a transfer is attempted.
Transferable tokens have no additional constraints applied to regulate when transfers are allowed.
All tokens are transferable by default, but can be set explicitly to transferable by using the zero address,
Strictly non-transferable tokens reject all transfer attempts, no matter what. Unanimous rejection behavior can
use the max address,
0xffffffffffffffffffffffffffffffffffffffff, as a special value. This special value can be used
for any operation to always prevent it.
Partially transferable tokens reject some transfer attempts and allow others. This logic is implemented by the
Guard contract and must implement the
IGuard.sol interface with the
bytes calldata data parameter encoded according to the token type:
abi.encode(address operator, address from, address to, uint256 value)
abi.encode(address operator, address from, address to, uint256 startTokenId, uint256 quantity)
abi.encode(address operator, address from, address to, uint256 tokenIds, uint256 values)