Universal Deployer Contract (UDC)
The Universal Deployer Contract (UDC) is a singleton smart contract that wraps the deploy syscall to expose it to any contract that doesn’t implement it, such as account contracts. You can think of it as a standardized generic factory for Starknet contracts.
And since Starknet has no deployment transaction type, it offers a standardized way to deploy smart contracts by following the standard deployer interface and emitting a ContractDeployed
event.
For more information see the proposal for the standard deployer interface. For details on the motivation and the decision making process, see the Universal Deployer Contract proposal.
UDC address
The UDC address is 0x041a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf
in Mainnet, Goerli testnet, Sepolia testnet, and starknet-devnet. This address might change in the future when it is migrated to a modern version of Cairo.
Interface
trait IUniversalDeployer {
fn deployContract(
class_hash: ClassHash,
salt: felt252,
unique: bool,
calldata: Span<felt252>
) -> ContractAddress;
}
Deploying a contract with the UDC
-
Declare the contract with a
DECLARE
transaction, or ensure that the contract has been declared.For more information, see the
DECLARE
transaction. -
Call the
deployContract
function in the UDC.
#[starknet::interface]
trait IUniversalDeployer<TContractState> {
fn deployContract(
ref self: TContractState,
class_hash: ClassHash,
salt: felt252,
unique: bool,
calldata: Span<felt252>
) -> ContractAddress; }
const UDC_ADDRESS: felt252 = 0x041a78e741e5af2fec34b695679bc6891742439f7afb8484ecd7766661ad02bf;
fn deploy() -> ContractAddress {
let dispatcher = IUniversalDeployerDispatcher {
contract_address: UDC_ADDRESS.try_into().unwrap()
};
// deployment parameters
let class_hash = class_hash_const::<
0x5c478ee27f2112411f86f207605b2e2c58cdb647bac0df27f660ef2252359c6
>();
let salt = 1234567879;
let unique = false;
let mut calldata = array![];
// the UDC returns the deployed contract address
dispatcher.deployContract(class_hash, salt, unique, calldata.span())
}
Deployment types
The Universal Deployer Contract offers two types of addresses to deploy: origin-dependent and origin-independent.
As the names suggest, the origin-dependent type includes the deployer’s address in the address calculation,
whereas, the origin-independent type does not.
The unique
boolean parameter ultimately determines the type of deployment.
When deploying a contract that uses |
Origin-dependent
By making deployments dependent upon the origin address, users can reserve a whole address space to prevent someone else from taking ownership of the address.
Only the owner of the origin address can deploy to those addresses.
Achieving this type of deployment necessitates that the origin sets unique
to true
in the deployContract
call.
Under the hood, the function call leverages the origin’s address and creates a hashchain by hashing the origin’s address with the given salt.
To deploy a unique contract address pass:
let deployed_addr = udc.deployContract(class_hash, salt, true, calldata.span());
Origin-independent
Origin-independent contract deployments create contract addresses independent of the deployer and the UDC instance.
Instead, only the class hash, salt, and constructor arguments determine the address.
This type of deployment enables redeployments of accounts and known systems across multiple networks.
To deploy a reproducible deployment, set unique
to false
.
let deployed_addr = udc.deployContract(class_hash, salt, false, calldata.span());
Deploying the UDC
The UDC has already been deployed on most networks and development environments.
The standard requires the UDC to be deployed passing |