Where are the Veri SmartMetal contracts?

Veri SmartMetal contracts on Base

Veri SmartMetal is an ERC-1155 token at 0x4516a5D613C30A36D157d3b579813734cbb929a4 on Base, an ERC-1967 proxy in front of the Series1155V1 implementation, with a separate SeriesActivation contract that holds every token until its holder activates it; all three were deployed on 22 May 2025 and are built on QRToken.

Veri SmartMetal

Standard#
ERC-1155
Transactions#
All transactions
Last verified#
13 Oct 2026

Series1155V1

Transactions#
All transactions
Last verified#
13 Oct 2026

SeriesActivation

Transactions#
All transactions
Last verified#
13 Oct 2026

Three contracts make up Veri SmartMetal on Base (chain id 8453). The Fact sheets above list each one; this article says what each does, how they fit together and how to read them yourself. All three were deployed by the same account, 0x73196fa74d6061e02648078246a1fE4D93a7AC2f, within twelve seconds on 22 May 2025.

How the three fit together#

Contract Address Role
Veri SmartMetal 0x4516a5D613C30A36D157d3b579813734cbb929a4 The token. An ERC-1967 proxy: the address wallets and explorers know, holding the balances and the series.
Series1155V1 0x945D54B21a582d5D186Ae1E449DdC2a4Ce39E26c The implementation the proxy delegates to: an ERC-1155 token with series, roles, royalties and pausing.
SeriesActivation 0x412E962bbAE0bB97CE98e74f3424543651a21ce3 Holds every minted token until its holder activates it, then transfers it to the activator’s wallet.

A SmartMetal token’s life runs through all three: the token contract mints it to SeriesActivation, SeriesActivation keeps it until someone proves they hold the key from its QR code, and the token then leaves for that person’s wallet. Activate a SmartMetal walks through that last step.

The token: an ERC-1967 proxy#

The address 0x4516a5D613C30A36D157d3b579813734cbb929a4 is an ERC1967Proxy of 129 bytes. It holds all the storage (balances, series, roles) and forwards every call to the implementation written in the EIP-1967 implementation slot. The proxy was created in block 30,569,433 on 22 May 2025 at 15:36:53 UTC (transaction). That one transaction:

  • emitted Upgraded(0x945D54B21a582d5D186Ae1E449DdC2a4Ce39E26c), the constructor setting the first implementation;
  • called initialize(contractUri) through the proxy, which emitted Initialized(1);
  • granted the deployer five roles (see Roles).

The implementation slot still holds Series1155V1 at 0x945D54B21a582d5D186Ae1E449DdC2a4Ce39E26c (read on 13 Oct 2026; the command is under Check it yourself). The upgrade path is UUPS (UPGRADE_INTERFACE_VERSION() returns 5.0.0): upgradeToAndCall lives in the implementation, guarded by its _authorizeUpgrade, so the contract can be upgraded; the slot read on 13 Oct 2026 still names the original implementation.

Series1155V1#

Series1155V1 at 0x945D54B21a582d5D186Ae1E449DdC2a4Ce39E26c was deployed three blocks before the proxy, in block 30,569,430 (transaction). It is an exact match of its verified source, Solidity 0.8.28 with the optimizer on at 200 runs. It is part of QRToken, Patryk Dwórznik’s own framework, which Veri SmartMetal is built on, and was written by him. The QRToken reference documents the contract in full; this section covers what you meet when you read the Veri deployment.

On top of OpenZeppelin’s upgradeable ERC-1155 it adds:

  • Series. A series is a group of tokens sharing one metadata folder on IPFS. createSeries(cid, isFungible) registers one; its id is keccak256 of the CID string. listSeries, seriesCount, seriesTokenCount, seriesTokens and tokenSeries read them. SmartMetal series lists the two that exist.
  • Minting by series. mintBatch(to, seriesId, tokenIds, amounts) mints the given ids into a series; the caller chooses the ids. A non-fungible series only accepts an amount of 1 per id.
  • Metadata. uri(id) returns ipfs://<series CID>/<id>.json. Series metadata can be updated or frozen in streamed steps (updateSeriesInit and updateSeriesEmit, freezeSeriesInit and freezeSeriesEmit); a frozen series emits a PermanentURI event per token. contractURI() holds the contract-level metadata and can be frozen too. On 13 Oct 2026 nothing was frozen.
  • Roles, royalties and pausing. Access control by role (below), an ERC-2981 royalty that is unset (royaltyInfo returns the zero address and 0), and pause and unpause. It was not paused on 13 Oct 2026.

It reports support for the ERC-1155 (0xd9b67a26), ERC-1155 metadata URI (0x0e89341c) and ERC-2981 (0x2a55205a) interfaces.

Roles#

Role ids are keccak256 of the role name, except DEFAULT_ADMIN_ROLE, which is 0x00. The proxy’s creation transaction granted the deployer, 0x73196fa74d6061e02648078246a1fE4D93a7AC2f, these five, and hasRole still returned true for each on 13 Oct 2026:

Role Id Lets its holder
DEFAULT_ADMIN_ROLE 0x00 grant and revoke the other roles
MINTER_ROLE 0x9f2d…56a6 call mintBatch
METADATA_ROLE 0x6bd6…2f80 create series and update, freeze or set metadata
PAUSER_ROLE 0x65d7…862a pause and unpause transfers
ROYALTY_ROLE 0xeb54…d98e set, clear or freeze the royalty

ADMIN_ROLE (0xa498…1775) exists in the contract but was not granted at deployment and the deployer does not hold it. SeriesActivation holds no role: it only receives tokens. Whether any other account has been granted a role since deployment was not checked; hasRole(role, account) answers for any address.

SeriesActivation#

SeriesActivation at 0x412E962bbAE0bB97CE98e74f3424543651a21ce3 was deployed three blocks after the proxy, in block 30,569,436 (transaction), with two constructor arguments: the token contract, 0x4516a5D613C30A36D157d3b579813734cbb929a4, and _maxTimestampAge, 3600 seconds. Both are still the values it returns. It is also part of QRToken, written by Patryk Dwórznik, and an exact match of its verified source.

It is Ownable, not role-based: owner() returns the deployer, 0x73196fa74d6061e02648078246a1fE4D93a7AC2f, who can register holders and change maxTimestampAge. What it stores, per token id:

  • tokenHolders(id): the address registered as the token’s holder, the key the QR code carries. It is zero once the token is activated, and zero for an id that was never registered.
  • activatedTokens(id): true after activation.
  • tokenStatus(id): 0 for a registered token waiting for activation, 1 for an id with no registration, 2 for an activated token.

The contract only accepts tokens whose id has a registered holder: its onERC1155Received and onERC1155BatchReceived revert with UnregisteredTokenTransfer otherwise. That is why every series is registered first and minted second, as SmartMetal series shows for both. activate(timestamp, signature) is the one function anyone can call; Activate a SmartMetal describes it.

Check it yourself#

Each command is a JSON-RPC call to a public Base endpoint; swap in https://base-rpc.publicnode.com if the first one is busy.

# The proxy's implementation slot (EIP-1967): 0x…945d54b21a582d5d186ae1e449ddc2a4ce39e26c
curl -s https://mainnet.base.org -X POST -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_getStorageAt","params":["0x4516a5d613c30a36d157d3b579813734cbb929a4","0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc","latest"]}'

# seriesCount(): 0x…02
curl -s https://mainnet.base.org -X POST -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"0x4516a5d613c30a36d157d3b579813734cbb929a4","data":"0xd7f2c0ef"},"latest"]}'

# hasRole(MINTER_ROLE, 0x7319…AC2f): 0x…01, which is true
curl -s https://mainnet.base.org -X POST -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"0x4516a5d613c30a36d157d3b579813734cbb929a4","data":"0x91d148549f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a600000000000000000000000073196fa74d6061e02648078246a1fe4d93a7ac2f"},"latest"]}'

# paused(): 0x…00, which is false
curl -s https://mainnet.base.org -X POST -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"0x4516a5d613c30a36d157d3b579813734cbb929a4","data":"0x5c975abb"},"latest"]}'

# SeriesActivation: tokenContract() is 0x…4516a5d613c30a36d157d3b579813734cbb929a4, maxTimestampAge() is 0x…e10 (3600), owner() is 0x…73196fa74d6061e02648078246a1fe4d93a7ac2f
curl -s https://mainnet.base.org -X POST -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"0x412e962bbae0bb97ce98e74f3424543651a21ce3","data":"0x55a373d6"},"latest"]}'
curl -s https://mainnet.base.org -X POST -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"0x412e962bbae0bb97ce98e74f3424543651a21ce3","data":"0x0dee2789"},"latest"]}'
curl -s https://mainnet.base.org -X POST -H 'content-type: application/json' \
  --data '{"jsonrpc":"2.0","id":1,"method":"eth_call","params":[{"to":"0x412e962bbae0bb97ce98e74f3424543651a21ce3","data":"0x8da5cb5b"},"latest"]}'

With Foundry installed, its cast command runs the same checks and decodes the answers:

export ETH_RPC_URL=https://mainnet.base.org

# Implementation behind the proxy: 0x945d54b21a582d5d186ae1e449ddc2a4ce39e26c
cast implementation 0x4516a5d613c30a36d157d3b579813734cbb929a4

# 2
cast call 0x4516a5d613c30a36d157d3b579813734cbb929a4 'seriesCount()(uint256)'

# true
cast call 0x4516a5d613c30a36d157d3b579813734cbb929a4 'hasRole(bytes32,address)(bool)' $(cast keccak MINTER_ROLE) 0x73196fa74d6061e02648078246a1fE4D93a7AC2f

# false
cast call 0x4516a5d613c30a36d157d3b579813734cbb929a4 'paused()(bool)'

# 0x4516a5D613C30A36D157d3b579813734cbb929a4, 3600, 0x73196fa74d6061e02648078246a1fE4D93a7AC2f
cast call 0x412e962bbae0bb97ce98e74f3424543651a21ce3 'tokenContract()(address)'
cast call 0x412e962bbae0bb97ce98e74f3424543651a21ce3 'maxTimestampAge()(uint256)'
cast call 0x412e962bbae0bb97ce98e74f3424543651a21ce3 'owner()(address)'

The ABIs are served at /abi/smartmetal.json (the proxy), /abi/series1155v1.json and /abi/smartmetal-activation.json. To decode calls to the token, use the Series1155V1 ABI against the proxy address. The data files page lists every file.

Sources#

  1. Veri SmartMetal proxy, verified source on BaseScan
  2. Series1155V1, verified source on BaseScan
  3. SeriesActivation, verified source on BaseScan
  4. Proxy creation transaction, BaseScan
  5. QRToken contract reference, Series1155V1
  6. QRToken contract reference, SeriesActivation
  7. EIP-1967: Proxy Storage Slots