Creating Tables from Contracts

Creating Tables from Contracts

Smart contracts can call the Tableland registry contract directly to create tables.


Developers can leverage smart contract calls to the TablelandTables registry smart contract for chain-based table creation. There is one major callout to implement.

The creating contract must be able to receive an ERC721 token.

Namely, please be sure to implement a way for the contract to receive the ERC721 token that is minted & sent by the TablelandTables registry contract. Two common paths to achieve this include:

  • Inherit the ERC721Holder contract, provided by OpenZeppelin.
  • Implement the underlying IERC721Receiver and its onERC721Received function.

Without this implementation, your contract will revert when trying to create tables since it is unable receive the corresponding token.


For those opting to inherit from the ERC721Holder, please be sure to review the specification on OpenZeppelin for more information. If possible, try for at least solc 0.8.12 since this introduced string concatenation bug fixes, which is used in writing SQL.

Alternatively, you may wish to use IERC721Receiver and implement onERC721Received yourself:


Let’s walk through an example with ERC721Holder since IERC721Receiver is rather similar. This is a simple smart contract that calls the Tableland registry smart contract and mints a table. Upon minting a table, there is a mapping that tracks tableNames to their corresponding tableIds, but this is purely for demonstration purposes. Alternatively, you may want to store the tableName and tableId as storage variables if you anticipate only needing to mint and use a select few tables.

Put differently, the contract below is a table factory that simply mints tables, but your app will likely have a specific set of tables it needs to use, and that’s it. You might want to replace the tables mapping with its components, tableName and tableId, or something similar.

The contract can now call the Tableland registry and mint tables. Note the usage of address(this). The TablelandTables contract has a createTable function that takes an address called owner as the first parameter. It simply mints a TABLE ERC721 token to this owner — which is the contract since address(this) was passed.

It’s possible that a developer will choose to pass the address of some function caller’s address, like msg.sender, instead of having the contract itself be the owner via address(this). Here, it would eliminate the need for inheriting ERC721Holder or IERC721Receiver since the contract would, thus, be acting as a passthrough to the Tableland registry contract and never actually receives an ERC721 token. It’d be minted right to msg.sender.