Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
18390447 | 496 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xAC7DD73B...63425861A The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
PRBProxy
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.8.18; import { IPRBProxy } from "./interfaces/IPRBProxy.sol"; import { IPRBProxyPlugin } from "./interfaces/IPRBProxyPlugin.sol"; import { IPRBProxyRegistry } from "./interfaces/IPRBProxyRegistry.sol"; /* ██████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗██╗ ██╗ ██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔═══██╗╚██╗██╔╝╚██╗ ██╔╝ ██████╔╝██████╔╝██████╔╝██████╔╝██████╔╝██║ ██║ ╚███╔╝ ╚████╔╝ ██╔═══╝ ██╔══██╗██╔══██╗██╔═══╝ ██╔══██╗██║ ██║ ██╔██╗ ╚██╔╝ ██║ ██║ ██║██████╔╝██║ ██║ ██║╚██████╔╝██╔╝ ██╗ ██║ ╚═╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ */ /// @title PRBProxy /// @dev See the documentation in {IPRBProxy}. contract PRBProxy is IPRBProxy { /*////////////////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////////////////*/ /// @inheritdoc IPRBProxy address public immutable override owner; /// @inheritdoc IPRBProxy IPRBProxyRegistry public immutable override registry; /*////////////////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////////////////*/ /// @notice Creates the proxy by fetching the constructor params from the registry, optionally delegate calling /// to a target contract if one is provided. /// @dev The rationale of this approach is to have the proxy's CREATE2 address not depend on any constructor params. constructor() { registry = IPRBProxyRegistry(msg.sender); (address owner_, address target, bytes memory data) = registry.constructorParams(); owner = owner_; if (target != address(0)) { _execute(target, data); } } /*////////////////////////////////////////////////////////////////////////// FALLBACK FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice Fallback function used to run plugins. /// @dev WARNING: anyone can call this function and thus run any installed plugin. fallback(bytes calldata data) external payable returns (bytes memory response) { // Check if the function selector points to a known installed plugin. IPRBProxyPlugin plugin = registry.getPluginByOwner({ owner: owner, method: msg.sig }); if (address(plugin) == address(0)) { revert PRBProxy_PluginNotInstalledForMethod({ caller: msg.sender, owner: owner, method: msg.sig }); } // Delegate call to the plugin. bool success; (success, response) = address(plugin).delegatecall(data); // Log the plugin run. emit RunPlugin(plugin, data, response); // Check if the call was successful or not. if (!success) { // If there is return data, the delegate call reverted with a reason or a custom error, which we bubble up. if (response.length > 0) { assembly { let returndata_size := mload(response) revert(add(32, response), returndata_size) } } else { revert PRBProxy_PluginReverted(plugin); } } } /// @dev Called when `msg.value` is not zero and the call data is empty. receive() external payable { } /*////////////////////////////////////////////////////////////////////////// USER-FACING NON-CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @inheritdoc IPRBProxy function execute(address target, bytes calldata data) external payable override returns (bytes memory response) { // Check that the caller is either the owner or an envoy with permission. if (owner != msg.sender) { bool permission = registry.getPermissionByOwner({ owner: owner, envoy: msg.sender, target: target }); if (!permission) { revert PRBProxy_ExecutionUnauthorized({ owner: owner, caller: msg.sender, target: target }); } } // Delegate call to the target contract, and handle the response. response = _execute(target, data); } /*////////////////////////////////////////////////////////////////////////// INTERNAL NON-CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice Executes a DELEGATECALL to the provided target with the provided data. /// @dev Shared logic between the constructor and the `execute` function. function _execute(address target, bytes memory data) internal returns (bytes memory response) { // Check that the target is a contract. if (target.code.length == 0) { revert PRBProxy_TargetNotContract(target); } // Delegate call to the target contract. bool success; (success, response) = target.delegatecall(data); // Log the execution. emit Execute(target, data, response); // Check if the call was successful or not. if (!success) { // If there is return data, the delegate call reverted with a reason or a custom error, which we bubble up. if (response.length > 0) { assembly { // The length of the data is at `response`, while the actual data is at `response + 32`. let returndata_size := mload(response) revert(add(response, 32), returndata_size) } } else { revert PRBProxy_ExecutionReverted(); } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; import { IPRBProxyPlugin } from "./IPRBProxyPlugin.sol"; import { IPRBProxyRegistry } from "./IPRBProxyRegistry.sol"; /// @title IPRBProxy /// @notice Proxy contract to compose transactions on behalf of the owner. interface IPRBProxy { /*////////////////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when a target contract reverts without a specified reason. error PRBProxy_ExecutionReverted(); /// @notice Thrown when an unauthorized account tries to execute a delegate call. error PRBProxy_ExecutionUnauthorized(address owner, address caller, address target); /// @notice Thrown when the fallback function fails to find an installed plugin for the method selector. error PRBProxy_PluginNotInstalledForMethod(address caller, address owner, bytes4 method); /// @notice Thrown when a plugin execution reverts without a specified reason. error PRBProxy_PluginReverted(IPRBProxyPlugin plugin); /// @notice Thrown when a non-contract address is passed as the target. error PRBProxy_TargetNotContract(address target); /*////////////////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////////////////*/ /// @notice Emitted when a target contract is delegate called. event Execute(address indexed target, bytes data, bytes response); /// @notice Emitted when a plugin is run for a provided method. event RunPlugin(IPRBProxyPlugin indexed plugin, bytes data, bytes response); /*////////////////////////////////////////////////////////////////////////// CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice The address of the owner account or contract, which controls the proxy. function owner() external view returns (address); /// @notice The address of the registry that has deployed this proxy. function registry() external view returns (IPRBProxyRegistry); /*////////////////////////////////////////////////////////////////////////// NON-CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice Delegate calls to the provided target contract by forwarding the data. It returns the data it /// gets back, and bubbles up any potential revert. /// /// @dev Emits an {Execute} event. /// /// Requirements: /// - The caller must be either the owner or an envoy with permission. /// - `target` must be a contract. /// /// @param target The address of the target contract. /// @param data Function selector plus ABI encoded data. /// @return response The response received from the target contract, if any. function execute(address target, bytes calldata data) external payable returns (bytes memory response); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; /// @title IPRBProxyPlugin /// @notice Interface for plugin contracts that can be installed on a proxy. /// @dev Plugins are contracts that enable the proxy to interact with and respond to calls from other contracts. These /// plugins are run via the proxy's fallback function. /// /// This interface is meant to be directly inherited by plugin implementations. interface IPRBProxyPlugin { /// @notice Retrieves the methods implemented by the plugin. /// @dev The registry pulls these methods when installing the plugin. /// /// Requirements: /// - The plugin must implement at least one method. /// /// @return methods The array of the methods implemented by the plugin. function getMethods() external returns (bytes4[] memory methods); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.4; import { IPRBProxy } from "./IPRBProxy.sol"; import { IPRBProxyPlugin } from "./IPRBProxyPlugin.sol"; /// @title IPRBProxyRegistry /// @notice Deploys new proxies via CREATE2 and keeps a registry of owners to proxies. Proxies can only be deployed /// once per owner, and they cannot be transferred. The registry also supports installing plugins, which are used /// for extending the functionality of the proxy. interface IPRBProxyRegistry { /*////////////////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when trying to install a plugin that implements a method already implemented by another /// installed plugin. error PRBProxyRegistry_PluginMethodCollision( IPRBProxyPlugin currentPlugin, IPRBProxyPlugin newPlugin, bytes4 method ); /// @notice Thrown when trying to uninstall an unknown plugin. error PRBProxyRegistry_PluginUnknown(IPRBProxyPlugin plugin); /// @notice Thrown when trying to install a plugin that doesn't implement any method. error PRBProxyRegistry_PluginWithZeroMethods(IPRBProxyPlugin plugin); /// @notice Thrown when a function requires the user to have a proxy. error PRBProxyRegistry_UserDoesNotHaveProxy(address user); /// @notice Thrown when a function requires the user to not have a proxy. error PRBProxyRegistry_UserHasProxy(address user, IPRBProxy proxy); /*////////////////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////////////////*/ /// @notice Emitted when a new proxy is deployed. event DeployProxy(address indexed operator, address indexed owner, IPRBProxy proxy); /// @notice Emitted when a plugin is installed. event InstallPlugin( address indexed owner, IPRBProxy indexed proxy, IPRBProxyPlugin indexed plugin, bytes4[] methods ); /// @notice Emitted when an envoy's permission is updated. event SetPermission( address indexed owner, IPRBProxy indexed proxy, address indexed envoy, address target, bool newPermission ); /// @notice Emitted when a plugin is uninstalled. event UninstallPlugin( address indexed owner, IPRBProxy indexed proxy, IPRBProxyPlugin indexed plugin, bytes4[] methods ); /*////////////////////////////////////////////////////////////////////////// STRUCTS //////////////////////////////////////////////////////////////////////////*/ /// @param owner The address of the user who will own the proxy. /// @param target The address of the target to delegate call to. Can be set to zero. /// @param data The call data to be passed to the target. Can be set to zero. struct ConstructorParams { address owner; address target; bytes data; } /*////////////////////////////////////////////////////////////////////////// CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice The release version of the proxy system, which applies to both the registry and deployed proxies. /// @dev This is stored in the registry rather than the proxy to save gas for end users. function VERSION() external view returns (string memory); /// @notice The parameters used in constructing the proxy, which the registry sets transiently during proxy /// deployment. /// @dev The proxy constructor fetches these parameters. function constructorParams() external view returns (address owner, address target, bytes memory data); /// @notice Retrieves the list of installed methods for the provided plugin. /// @dev An empty array is returned if the plugin is unknown. /// @param owner The proxy owner for the query. /// @param plugin The plugin for the query. function getMethodsByOwner(address owner, IPRBProxyPlugin plugin) external view returns (bytes4[] memory methods); /// @notice Retrieves the list of installed methods for the provided plugin. /// @dev An empty array is returned if the plugin is unknown. /// @param proxy The proxy for the query. /// @param plugin The plugin for the query. function getMethodsByProxy( IPRBProxy proxy, IPRBProxyPlugin plugin ) external view returns (bytes4[] memory methods); /// @notice Retrieves a boolean flag that indicates whether the provided envoy has permission to call the provided /// target. /// @param owner The proxy owner for the query. /// @param envoy The address checked for permission to call the target. /// @param target The address of the target. function getPermissionByOwner( address owner, address envoy, address target ) external view returns (bool permission); /// @notice Retrieves a boolean flag that indicates whether the provided envoy has permission to call the provided /// target. /// @param proxy The proxy for the query. /// @param envoy The address checked for permission to call the target. /// @param target The address of the target. function getPermissionByProxy( IPRBProxy proxy, address envoy, address target ) external view returns (bool permission); /// @notice Retrieves the address of the plugin installed for the provided method selector. /// @dev The zero address is returned if no plugin is installed. /// @param owner The proxy owner for the query. /// @param method The method selector for the query. function getPluginByOwner(address owner, bytes4 method) external view returns (IPRBProxyPlugin plugin); /// @notice Retrieves the address of the plugin installed for the provided method selector. /// @dev The zero address is returned if no plugin is installed. /// @param proxy The proxy for the query. /// @param method The method selector for the query. function getPluginByProxy(IPRBProxy proxy, bytes4 method) external view returns (IPRBProxyPlugin plugin); /// @notice Retrieves the proxy for the provided user. /// @param user The user address for the query. function getProxy(address user) external view returns (IPRBProxy proxy); /*////////////////////////////////////////////////////////////////////////// NON-CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ /// @notice Deploys a new proxy for the caller. /// /// @dev Emits a {DeployProxy} event. /// /// Requirements: /// - The caller must not have a proxy. /// /// @return proxy The address of the newly deployed proxy. function deploy() external returns (IPRBProxy proxy); /// @notice This function performs two actions: /// 1. Deploys a new proxy for the caller /// 2. Delegate calls to the provided target, returning the data it gets back, and bubbling up any potential revert. /// /// @dev Emits a {DeployProxy} and {Execute} event. /// /// Requirements: /// - The caller must not have a proxy. /// - `target` must be a contract. /// /// @param target The address of the target. /// @param data Function selector plus ABI-encoded data. /// @return proxy The address of the newly deployed proxy. function deployAndExecute(address target, bytes calldata data) external returns (IPRBProxy proxy); /// @notice This function performs three actions: /// 1. Deploys a new proxy for the caller /// 2. Delegate calls to the provided target, returning the data it gets back, and bubbling up any potential revert. /// 3. Installs the provided plugin on the newly deployed proxy. /// /// @dev Emits a {DeployProxy}, {Execute}, and {InstallPlugin} event. /// /// Requirements: /// - The caller must not have a proxy. /// - See the requirements in `installPlugin`. /// - See the requirements in `execute`. /// /// @param target The address of the target. /// @param data Function selector plus ABI-encoded data. /// @param plugin The address of the plugin to install. /// @return proxy The address of the newly deployed proxy. function deployAndExecuteAndInstallPlugin( address target, bytes calldata data, IPRBProxyPlugin plugin ) external returns (IPRBProxy proxy); /// @notice This function performs two actions: /// 1. Deploys a new proxy for the caller. /// 2. Installs the provided plugin on the newly deployed proxy. /// /// @dev Emits a {DeployProxy} and {InstallPlugin} event. /// /// Requirements: /// - The caller must not have a proxy. /// - See the requirements in `installPlugin`. /// /// @param plugin The address of the plugin to install. /// @return proxy The address of the newly deployed proxy. function deployAndInstallPlugin(IPRBProxyPlugin plugin) external returns (IPRBProxy proxy); /// @notice Deploys a new proxy for the provided user. /// /// @dev Emits a {DeployProxy} event. /// /// Requirements: /// - The user must not have a proxy already. /// /// @param user The address that will own the proxy. /// @return proxy The address of the newly deployed proxy. function deployFor(address user) external returns (IPRBProxy proxy); /// @notice Installs the provided plugin on the caller's proxy, and saves the list of methods implemented by the /// plugin so that they can be referenced later. /// /// @dev Emits an {InstallPlugin} event. /// /// Notes: /// - Installing a plugin is a potentially dangerous operation, because anyone can run the plugin. /// - Plugin methods that have the same selectors as {IPRBProxy.execute}, {IPRBProxy.owner}, and /// {IPRBProxy.registry} can be installed, but they can never be run. /// /// Requirements: /// - The caller must have a proxy. /// - The plugin must have at least one implemented method. /// - There must be no method collision with any other plugin installed by the caller. /// /// @param plugin The address of the plugin to install. function installPlugin(IPRBProxyPlugin plugin) external; /// @notice Gives or takes a permission from an envoy to call the provided target and function selector /// on behalf of the caller's proxy. /// /// @dev Emits a {SetPermission} event. /// /// Notes: /// - It is not an error to set the same permission. /// /// Requirements: /// - The caller must have a proxy. /// /// @param envoy The address of the account the caller is giving or taking permission from. /// @param target The address of the target. /// @param permission The boolean permission to set. function setPermission(address envoy, address target, bool permission) external; /// @notice Uninstalls the plugin from the caller's proxy, and removes the list of methods originally implemented by /// the plugin. /// /// @dev Emits an {UninstallPlugin} event. /// /// Requirements: /// - The caller must have a proxy. /// - The plugin must be a known, previously installed plugin. /// /// @param plugin The address of the plugin to uninstall. function uninstallPlugin(IPRBProxyPlugin plugin) external; }
{ "remappings": [ "@prb/test/=lib/prb-test/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "prb-test/=lib/prb-test/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "none", "appendCBOR": false }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"PRBProxy_ExecutionReverted","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"target","type":"address"}],"name":"PRBProxy_ExecutionUnauthorized","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes4","name":"method","type":"bytes4"}],"name":"PRBProxy_PluginNotInstalledForMethod","type":"error"},{"inputs":[{"internalType":"contract IPRBProxyPlugin","name":"plugin","type":"address"}],"name":"PRBProxy_PluginReverted","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"PRBProxy_TargetNotContract","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"response","type":"bytes"}],"name":"Execute","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IPRBProxyPlugin","name":"plugin","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"response","type":"bytes"}],"name":"RunPlugin","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"execute","outputs":[{"internalType":"bytes","name":"response","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IPRBProxyRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Deployed Bytecode
0x60806040526004361015610027575b36156100255761001d366102b5565b602081519101f35b005b6000803560e01c9081631cff79cd1461005a575080637b1039991461005557638da5cb5b0361000e5761017c565b610137565b60403660031901126100ca57600435610072816100cd565b60243567ffffffffffffffff928382116100ca57366023830112156100ca5781600401359384116100ca5736602485840101116100ca576100c66100ba8560248501866104a2565b60405191829182610123565b0390f35b80fd5b6001600160a01b038116036100de57565b600080fd5b919082519283825260005b84811061010f575050826000602080949584010152601f8019910116010190565b6020818301810151848301820152016100ee565b9060206101349281815201906100e3565b90565b346100de5760003660031901126100de576040517f000000000000000000000000584009e9ede26e212182c9745f5c000191296a786001600160a01b03168152602090f35b346100de5760003660031901126100de576040517f00000000000000000000000084f4840e47199f1090ceb108f74c5f332219539a6001600160a01b03168152602090f35b634e487b7160e01b600052604160045260246000fd5b90601f8019910116810190811067ffffffffffffffff8211176101f957604052565b6101c1565b908160209103126100de5751610134816100cd565b6040513d6000823e3d90fd5b908160008237016000815290565b67ffffffffffffffff81116101f957601f01601f191660200190565b3d15610274573d9061025a8261022d565b9161026860405193846101d7565b82523d6000602084013e565b606090565b606090610134939260408252806040830152806000848401376000838284010152601f80199101168101906020838284030191015201906100e3565b6040516361be485960e01b81527f00000000000000000000000084f4840e47199f1090ceb108f74c5f332219539a6001600160a01b0381811660048401526001600160e01b03196000351660248401819052939493906020846044817f000000000000000000000000584009e9ede26e212182c9745f5c000191296a7885165afa93841561044e5760009461041e575b5083169182156103e357505060008060405180610362818961021f565b0390845af4907fc4dabe0d7ef7462e2218f2c398c21ef217803e1c46f5cf802d1a5d1d9b503f2f610391610249565b80966103a260405192839283610279565b0390a2156103ad5750565b8251909150156103c05750805190602001fd5b60405163023c045d60e21b81526001600160a01b03919091166004820152602490fd5b604051638848730f60e01b81523360048201526001600160a01b039190911660248201526001600160e01b0319919091166044820152606490fd5b61044091945060203d8111610447575b61043881836101d7565b8101906101fe565b9238610345565b503d61042e565b610213565b908160209103126100de575180151581036100de5790565b9291926104778261022d565b9161048560405193846101d7565b8294818452818301116100de578281602093846000960137010152565b917f00000000000000000000000084f4840e47199f1090ceb108f74c5f332219539a6001600160a01b0333818316036104ee575b505061013492916104e891369161046b565b906105e5565b60405163b31d1b9960e01b81526001600160a01b0383811660048301523360248301528616604482015290602090829060649082907f000000000000000000000000584009e9ede26e212182c9745f5c000191296a78165afa90811561044e57600091610592575b501561056257806104d6565b6040516355d1750960e01b81526001600160a01b0391821660048201523360248201529084166044820152606490fd5b6105b3915060203d81116105b9575b6105ab81836101d7565b810190610453565b38610556565b503d6105a1565b90916105d7610134936040845260408401906100e3565b9160208184039101526100e3565b9190823b1561066d57600080825160208401865af4907fb24ebe141c5f2a744b103bea65fce6c40e0dc65d7341d092c09b160f40447990610624610249565b60405190956001600160a01b0316928190610641908890836105c0565b0390a21561064b57565b5080511561065b57602081519101fd5b60405163061a160d60e41b8152600490fd5b604051636d17e5ef60e11b81526001600160a01b0384166004820152602490fd
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.