Extern Entity
An extern entity declares the surface of a foreign entity — one that
lives outside the current Cambrian project but that your code still needs to
call with typed routes. It is an interface stub: route signatures only, no
members, transforms, or bodies.
Declaration
extern entity Token {
route transfer(amount: U256);
view route balanceOf(who: address) -> U256;
}
entity Caller {
routes {
constructor(t: Address<Token>) => []
ping(amount: U256) => [
transfer(amount) ~> m_token
]
view checkBalance(who: address) -> U256 => [
var b = balanceOf(who) ~> m_token;
return(b)
]
}
m_token: Address<Token> {
in constructor(t) => t
}
}
Route modifiers on the stub map to the call ABI:
| Modifier | Meaning on EVM |
|---|---|
| (none) | Ordinary mutating call |
view route | Read-only (staticcall-safe) |
accept route | Payable call surface (attached value: allowed) |
Use extern entity when:
- the target is a third-party or separately built entity (for example an ERC-20 you do not own, on EVM);
- you want typed
Address<Token>members and capturing calls (var x = msg(args) ~> dest) without including the implementation in the project sources.
@solidity_import
Optionally annotate the stub so the EVM emitter imports a real Solidity
interface instead of synthesizing interface IName { ... }:
@solidity_import("@openzeppelin/contracts/token/ERC20/IERC20.sol")
extern entity IERC20 {
route transfer(to: address, amount: U256) -> bool;
view route balanceOf(who: address) -> U256;
}
The generated .sol gets import "@openzeppelin/...";, and call sites use
the imported type name. Pair this with foundry.remappings in
project.yaml so Foundry can resolve the path. Keep the
Cambrian stub in sync with the imported surface manually — mismatches show up
at solc compile time.
Validation
| Rule | Code | Meaning |
|---|---|---|
| Unique name | V30 | Duplicate extern entity, or collision with a real entity |
| Unique route names | V31 | Duplicate route signature inside one extern block |
| Known send target | E22 | Typed send whose destination entity is neither in the project nor declared extern entity |
Typed sends still resolve the target route (V23 if the route is missing).
deploy arity checks (V32) are skipped for extern targets (constructor
surface is unknown).