Skip to content

tristeroresearch/create5

Repository files navigation

Create5 – Domain‑scoped, permissioned CREATE3 factory

What problem does it solve?

  • Cross‑chain reuse safety: If different teams reuse the same salt with a plain factory, they can clash or hijack expected addresses. Create5 introduces per‑owner domains so each deployer has an isolated namespace.
  • Deterministic addresses with chain‑specific configs: You often want the same contract address across chains while passing different constructor args (e.g., oracles, chain IDs). CREATE3 makes the address independent of init code; Create5 keeps that property while adding safe authorization.

Why plain CREATE2 isn’t enough

  • initCode dependence: the created contract depends on the initCode (constructor args) to be deployed, which is not always desired.

Why plain CREATE3 isn’t enough

  • No ownership or operators: Anyone who knows your salt can front‑run or squat it in a shared factory.
  • No namespacing: A single global salt space leads to accidental collisions and malicious reuse.
  • Operational gap for cross‑chain: You need predictable, per‑project coordination of salts across chains; plain CREATE3 doesn’t provide that structure.

How Create5 solves it

  • Domains: A domain is keccak256(abi.encodePacked(owner, tag)). All deployments use a combined salt keccak256(abi.encodePacked(domain, salt)), cleanly namespacing addresses per owner.
  • Permissions: Only the domain owner or its operators can deploy under that domain.
  • CREATE3 under the hood: Uses the official Create3 library so final addresses are independent of init code, enabling chain‑specific parameters without changing the address formula.

Salt mining

Salt mining for vanity addresses is straightforward, there is a rust tool available.

Deployments -> See deployments.md

ABI

[{"inputs":[],"name":"DomainAlreadyExists","type":"error"},{"inputs":[],"name":"ErrorCreatingContract","type":"error"},{"inputs":[],"name":"ErrorCreatingProxy","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"TargetAlreadyExists","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"submitter","type":"address"},{"indexed":true,"internalType":"address","name":"finalAddress","type":"address"},{"indexed":true,"internalType":"bytes32","name":"domain","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"Deployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"bytes32","name":"domain","type":"bytes32"}],"name":"DomainCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"domain","type":"bytes32"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"isAuthorized","type":"bool"}],"name":"DomainOperatorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"domain","type":"bytes32"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"DomainOwnershipTransferred","type":"event"},{"inputs":[{"internalType":"bytes32","name":"domain","type":"bytes32"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"computeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"tag","type":"bytes32"}],"name":"createDomain","outputs":[{"internalType":"bytes32","name":"domain","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"domain","type":"bytes32"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"initCode","type":"bytes"}],"name":"deploy","outputs":[{"internalType":"address","name":"deployed","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"domainOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"}],"name":"isOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"domain","type":"bytes32"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"authorized","type":"bool"}],"name":"setDomainOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"domain","type":"bytes32"},{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferDomainOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

About

Domain‑scoped, permissioned CREATE3 factory

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors