On the Radix Network, components can be thought of as the “smart contracts” users can call to perform complex operations. However, they work differently than on other platforms, and one of the key differences is that their implementation (the code which defines their behavior) is separate from the actual address that you call. For those familiar with object-oriented programming, a “blueprint” is like a class and a “component” is like an instance of that class–an object. This allows for easy re-use of useful logic without having to constantly redeploy the same code, and much easier user verification that two components which claim to do the same thing (e.g., two Radiswap pools) actually have the same underlying behavior.
There are two kinds of components: user components and system components. Let’s tackle each one.
User components are what you normally have in mind when you think of a smart contract. They’re written in Scrypto, by anyone, and deployed atop the running network.
A developer writes blueprint code in Scrypto, groups one or more blueprints together into a package, and then compiles that package to WebAssembly (WASM) and deploys it to the Radix Ledger as part of a special type of transaction.
Packages have a global address, and their associated blueprints can be called from Scrypto code or transaction manifests. Blueprints don’t manage any state (they can’t hold tokens or instance variables), so the most common reason to call a blueprint directly is to instantiate a global component from it. Global components have their own address and their own state.
When a blueprint or user component is called within code or from a transaction manifest, the Radix Engine loads the WASM for the associated package and executes it.
System components have their behavior defined by precompiled system blueprints which are part of the Radix Engine. They are thus part of the Radix platform itself, and were available at the genesis of the Babylon mainnet upgrade.
Precompiled blueprints are called differently than other blueprints, using special transaction manifest instructions or Scrypto code. Once instantiated to a system component, they are called in exactly the same way as user components, though some do exist in special address spaces.
When a system component or precompiled blueprint is called, there is no need for the Radix Engine to load and run any WASM–the logic is already built-in. This means that system component calls incur lower overhead than user component calls, and hence components which are needed in a majority of transactions are good candidates to be made into system components.
When do I need to pay attention to the difference?
As a network user, probably never. Interactions with user and system components work in exactly the same way, and any transaction can call any combination of them. As a developer, it’s just good foundational knowledge to have on how things work under the hood.