Holograph provides omnichain NFT infrastructure for the web3 ecosystem. Holograph Protocol enables the creation, deployment, minting, and bridging of omnichain NFTs with complete data integrity.
Please reference the documentation for the full technical specification of the protocol.
Genesis will be deployed on all blockchains that run and support Holograph Protocol. All main components will be deployed via Genesis. Future blockchains will have a Genesis deployment as well.
Factory enables developers to submit a signed version of the following elements to deploy a Holographed smart contract on the blockchain:
- primary deployment chain
- token type (ERC-20, ERC-721, etc.)
- event subscriptions
- custom smart contract bytecode
- custom initialization code
Any additional blockchains that developers want to support can have the same signed data submitted to Factory, allowing for the creation of an identical Holographed contract. The primary job of Factory is to:
- allow propagation of exact data across all blockchains
- ensure a proper standard is selected and used
- ensure all deployments succeed and work as expected
- ensure that security is enforced and impenetrable
Registry is a central on-chain location where all Holograph data is stored. Registry keeps a record of all currently supported standards. New standards can be introduced and enabled as well. Any properly deployed Holographed contracts are also stored as reference. This allows for a definitive way to identify whether a smart contract is secure and properly Holographed. Verifying entities will be able to identify a Holographed contract to ensure the highest level of security and standards.
This contract contains the code responsible for all the bridge-out and bridge-in logic required to enable bridging. Bridge is a universal smart contract that functions as the primary entry and exit point for any Holographed tokens to and from all supported blockchains. Bridge validates and ensures integrity and standard enforcement for every Bridge-In and Bridge-Out request. Additionally, Bridge implements a universal standard for sending tokens across blockchains by abstracting away complexities into sub-modules that remove the burden of management for developers. This allows for simple one-click/one-transaction native gas token payment-based interactions for all bridge requests.
Operator's primary job is to know the messaging protocols that are utilized by the Holograph protocol for all cross-chain messages, and to ensure the authenticity and validity of all requests being submitted. Operator ensures that only valid bridge requests are sent/received and allowed to be executed inside of the protocol.
Holograph is the primary entry-point for all users and developers. A single, universal address across all blockchains will enable developers an easy way to interact with the protocol’s features. Holograph keeps references for all current Registry, Factory, and Bridge implementations. Furthermore, it allows for single interface management of the underlying Holograph Protocol. Holograph provides a reference to the name and ID of all supported blockchains. Additionally, it:
- Enables custom smart contract logic that is chain-dependent
- Frees developers from having to query and monitor the blockchain
Holographer exists at the core of all Holographed smart contracts, which is applied whenever a Holographed smart contract is deployed. Holographer pieces together all components and routes all inbound function calls to their proper smart contracts, ensuring security and the enforcement of specified standards. Holographer is isolated on its own private layer and is essentially hard-coded into the blockchain.
Enforcer enables and ensures complete standards, compliance, and operability for a given standard type. HolographERC20 and HolographERC721 are perfect examples of such Enforcers. Enforcers store and manage all data within themselves to ensure security, compliance, integrity, and enforcement of all protocols. Communication is established with custom contracts via specific event hooks. The storage/data layer is isolated privately and not directly accessible by custom contracts.
HolographRoyalties is an on-chain royalties contract for non-fungible token types. It supports a universal module that understands and speaks all of the different royalty standards on the blockchain. HolographRoyalties is built to be extendable and can have new royalty standards implemented as they are created and agreed upon.
The Interfaces contract is used to store and share standardized data. It acts as an external library contract. This allows all the Holograph protocol smart contracts to reference a single instance of data and code.
Custom contract is any type of smart contract that was developed outside of Holograph Protocol, and is used to create a Holographed contract. This empowers developers to build their projects however they want. The requirements for enabling a custom contract to be Holograph-able are minimal, and allow for even novice-level developers to implement. Any current and future fungible and non-fungible token type contracts can easily be made Holograph-able.
To bridge NFTs, a Holographed contract must be deployed and NFTs minted from the contract. Doing so will ensure that the contract address and token IDs remain the same on all deployed blockchains.
TBD
The simplified code path for bridging out is:
HolographBridge.sol
-bridgeOutRequest
methodHolographRegistery.sol
-_isHolographedContract
methodenforcer/HolographERC721.sol
-_bridgeOut
method [This is the Collection Contract]HolographOperator.sol
-send
methodHolograph/LayerZeroModule.sol
-send
method
At step 1, a user submits their bridge request with a valid payload using the estimatedGas value computed in the previous Estimate Gas section
At step 2, the code checks that the contract is a holographable contract. This means it has implemented the required functions for a Holographed contract. See contracts/enforcer/HolographERC721.sol
for an example.
At step 3, we call the _bridgeOut
function on the Holographed contract and apply various checks and generate a payload with information about the bridge request.
At step 4, we call the send
method on the HolographOperator.sol
contract. This method does some final packaging of the payload that will be sent to the messaging layer.
At step 5, we finally call the send
method to the messaging layer contract /module/LayerZeroModule.sol
. At this point the NFT has left the source chain.
The simplified code path for bridging in is:
module/LayerZeroModule.sol
-lzReceive
methodHolographOperator.sol
-crossChainMessage
methodHolographOperator.sol
- Emits eventAvailableOperatorJob(jobHash, bridgeInRequestPayload);
At step 1, the configured messaging layer calls the method lzReceive
in module/LayerZeroModule.sol
. We do some checks to make sure only LayerZero call this method.
At step 2, we call crossChainMessage
on the HolographOperator.sol
contract. We encode the job, select a primary operator, and 5 substitute operators.
At step 3, the contract will emit a job event. This job event is being observed by our CLI that will then finalize a job. Only users who are in a pod are allowed to finalize jobs.
Operators execute destination chain bridge transaction. Operators must run the CLI, bond the protocol’s native token, and execute transactions. The probability of getting selected to perform this work is based on the number of tokens bonded.
There is a testnet faucet available for getting testnet tokens. These are the tokens you need to be able to bond to a pod and operate. Currently deployed Faucet address can be found in the deployments
dir. Choose the environment/branch, network, and the file will be Faucet.json
.
To become an operator, you must view the pods available to join, select a pod, and bond at least the minimum bond requirement.
HolographOperator.sol
-getTotalPods
HolographOperator.sol
-getPodBondAmounts
HolographOperator.sol
-bondUtilityToken
At step 1, you call getTotalPods
method to get a list of available pods. If the length of pod is zero, then you can bond into pod 1
.
At step 2, when you call getPodBondAmounts
, you will get two values: [_base
, current
]. The base
value represents the original minimum bond requirement to join the pod, while the current
value is the current amount you must provide to join the pod.
At step 3, you are now able to call the bondUtilityToken
function with the pod and amounts you want to use to enter the pod. Please note, there is a minimum bond requirement to join but no maximum.
To leave a pod, you have to call the unbondUtilityToken
in HolographOperator.sol
.
You must join a pod to become an operator. The simplified code path for operating is:
- Receive new Block from the network
- Iterate over block looking for event
AvailableOperatorJob(jobHash, bridgeInRequestPayload);
HolographOperator.sol
-getJobDetails
methodHolographOperator.sol
-jobEstimator
methodHolographOperator.sol
-executeJob
method
At step 1, the CLI connected via websocket receives notification that new block was mined.
At step 2, the CLI makes a request for the full block information. It then iterates over transactions, looking for the AvailableOperatorJob
event.
At step 3, the CLI then calls getJobDetails
in HolographOperator.sol
. This checks if the current wallet user is the selected operator or a backup operator. If it is the selected operator, then it will continue. Otherwise, the job is kept in memory for a short time and reviewed again in the future to check the job status.
At step 4, the CLI will estimate the cost of executing the job. This is used to make sure the transaction sent has enough gas to complete.
At step 5, the wallet sends a transaction to the exectureJob
method on the HolographOperator.sol
contract. In here, further checks are done to validate the job and user's wallet. After this transaction is mined on the blockchain, the NFT will become finalized and available on the new blockchain.
-
This project uses asdf for versions management. Install following plugins
- Install asdf Node plugin:
asdf plugin add nodejs https://github.com/asdf-vm/asdf-nodejs.git
- Install asdf yarn plugin:
asdf plugin-add yarn
- Install asdf Node plugin:
-
Run
asdf install
after to have the correct tool versions. -
Install dependencies with
yarn install
."This project uses environment variables that are stored in
.env
"
When the project is built, the code in the src
folder gets written to the contracts
folder. The files in the contracts
folder are the "real" files that are used for testing and code verification on all the scanners.
Again, files from the src
directory are automatically transpiled into the contracts
directory each time that hardhat compiles the contracts.
NOTE: At this time some tests require hardcoded referencing hardcoded addresses on the local network that are deployed deterministically based on a salt parameter that is stored in the
.env
file. For local development, please setDEVELOP_DEPLOYMENT_SALT=1000
.
There are two sets of tests. The main test suite uses Hardhat. To run them start your local chains that the contracts will be deployed to using:
yarn run ganache-x2
Keep in mind that two networks are spun up in order to facilitate the multichain tests that bridge from one network to the other. Next run the hardhat tests with:
yarn test
The newer tests for Drops use Foundry. Please make sure you have Foundry installed by following the instructions here.
Currently the Foundry tests require "forking" from a local chain that has the rest of the Holograph protocol contracts already deployed. To do this, with the local ganache chains still running from the ganache-x2
command mentioned above, run deploy with:
yarn deploy:localhost
Then you can run the Foundry tests with:
forge test
Before pushing your work to the repo, make sure to prepare your code
Please make use of the yarn run prettier:fix
command to format the codebase into a universal style.
root ├── config: Network configuration files ├── contracts: Smart contracts that power the Holograph protocol ├── deploy: Deployment scripts for the smart contracts uses Hardhat and Hardhat Deploy ├── deployments: Deployment build files that include contract addresses on each network ├── scripts: Scripts and helper utilities ├── src: Source contracts that get dynamically transpiled down into the finalized output contracts └── test: Hardhat tests for the smart contracts
Branch | Status |
---|---|
mainnet | Accepts PRs from testnet or release/x.x.x when we intend to deploy to mainnet. |
testnet | Accepts PRs from develop that are ready to be deployed to testnet. |
develop | Accepts PRs from feature/xyz branches that are experimental or in testing stage. |
experimental | Accepts PRs from any branches. |
release/x.x.x | Accepts PRs from testnet . |
We generally follow this Git branching model. Please read the linked post if you're planning to make frequent PRs into this repository.
The mainnet
branch contains the code for our latest "stable" mainnet releases.
Updates from mainnet
always come from the testnet
branch.
We only ever update the mainnet
branch when we intend to deploy code that has been tested on testnets to all mainnet networks supported by the Holograph protocol.
Our update process takes the form of a PR merging the testnet
branch into the mainnet
branch.
The testnet
branch continas the code that is the latest stable testnet release for all supported networks. This branch is deployed and circulated for beta users of the protocol. Updates are merged in from the develop
branch once they're ready for broad usage.
Our primary development branch is develop
.
develop
contains the most up-to-date software that is being tested via experimental network deployments.
Our primary experimentation branch is experimental
.
experimental
contains the software that is not stable and is trying out new code.
- Validate env variables are correct
- Check Salts
- Check RPCS
- Check
HOLOGRAPH_ENVIRONMENT
- Check Git commit reference
- Clean Repo
- Remove temp folders: [node_modules, artifacts, cache, cache_hardhat, dist, typechain-types, ganache]
- Run Tests
- run
yarn clean-compile
- run
yarn ganache-x2
- terminal 1 - run
yarn deploy
- terminal 2
- run
- Run Deployments per environment, check gas chane per network again, and save output
- avalanche
- Check price envs
- Save output to deploymentHistory. NOTE remove directory info.
- mumbai
- Check price envs
- Save output to deploymentHistory. NOTE remove directory info.
- goerli
- Check price envs
- Save output to deploymentHistory. NOTE remove directory info.
- binance
- Check price envs
- Save output to deploymentHistory. NOTE remove directory info.
- avalanche
- Validate Contracts on each network
Read through CONTRIBUTING.md for a general overview of our contribution process.
Files under this repository are licensed under Holograph Limited Public License (H-LPL) 1.0.0 unless otherwise stated.