Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
UTSCodeStorageConnectorNative
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 1 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../connector/UTSConnectorNative.sol"; import "../interfaces/IUTSCodeStorage.sol"; /** * @notice A contract stores creation bytecode for UTSConnectorNative contract. * * The bytecode is used by the {UTSFactory} for deployment. */ contract UTSCodeStorageConnectorNative is IUTSCodeStorage { /** * @notice Returns the UTSConnectorNative creation bytecode. * @return bytecode creation bytecode of the {UTSConnectorNative} contract. */ function getCode(bool /* isConnector */) external pure returns(bytes memory bytecode) { return type(UTSConnectorNative).creationCode; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; interface IUTSCodeStorage { function getCode(bool isConnector) external pure returns(bytes memory bytecode); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/[email protected]/access/AccessControl.sol"; import "../extensions/UTSBaseIndexed.sol"; import "../interfaces/IUTSConnector.sol"; /** * @notice A contract that provides functionality to use UTS protocol V1 crosschain messaging for bridging * native currency. * * @dev An {UTSConnectorNative} contract stores and releases native currency and interacts with the UTS protocol. * A contract implements and overrides the minimum functionality for correct running and interaction with the UTS protocol. * Since native currency cannot be minted or burned in general, only a lock/unlock mechanism is used here. */ contract UTSConnectorNative is IUTSConnector, UTSBaseIndexed, AccessControl { /// @dev Library for {address} converting, since in crosschain messaging its represented as {bytes} type. using AddressConverter for address; /** * @notice Indicates an error that the provided {amount} exceeds transaction's {msg.value}. * @dev Since part of the {msg.value} will be sent to {_router} as payment for the bridging execution, * {msg.value} should be equal to {amount} + estimated bridge fee. */ error UTSConnectorNative__E0(); /// @notice Indicates an error that the provided {amount} exceeds native currency {address(this).balance}. error UTSConnectorNative__E1(); /// @notice Indicates an error that native currency transfer to {to} address is failed. error UTSConnectorNative__E2(bytes); /// @notice Indicates an error that the provided {from} address is not equal {spender(msg.sender)} address. error UTSConnectorNative__E3(); /** * @notice Initializes basic settings with provided parameters. * @param _owner the address of the initial {AccessControl.DEFAULT_ADMIN_ROLE}. * @param underlyingToken_ placeholder address, see the {UTSFactory.NATIVE_ADDRESS()} for details. * @param _router the address of the authorized {UTSRouter}. * @param _allowedChainIds chains Ids available for bridging in both directions. * @param _chainConfigs array of {ChainConfig} settings for provided {_allowedChainIds}. * @dev See the {UTSERC20DataTypes.ChainConfig} for details. * @dev Can and MUST be called only once. Reinitialization is prevented by {UTSBase.__UTSBase_init} function. */ function initializeConnector( address _owner, address underlyingToken_, address _router, uint256[] calldata _allowedChainIds, ChainConfig[] calldata _chainConfigs ) external { __UTSBase_init(underlyingToken_, 18); _setRouter(_router); _setChainConfig(_allowedChainIds, _chainConfigs); _grantRole(DEFAULT_ADMIN_ROLE, _owner); } /** * @notice Provides the ability to send native currency to the current contract to replenish liquidity for bridging. */ receive() external payable { } /** * @notice Returns decimals value of the native currency. * @return decimals decimals of the current chain native currency. */ function underlyingDecimals() external view returns(uint8 decimals) { return _decimals; } /** * @notice Returns the name of the underlying native token. * @return name name of the {_underlyingToken}. * @dev Must be hardcoded for a specific chain. */ function underlyingName() external pure returns(string memory name) { return "Sonic"; } /** * @notice Returns the symbol of the underlying native token. * @return symbol symbol of the {_underlyingToken}. * @dev Must be hardcoded for a specific chain. */ function underlyingSymbol() external pure returns(string memory symbol) { return "S"; } /** * @notice Returns the balance of the native currency held by this contract. * @return nativeBalance native currency balance held by the {UTSConnectorNative} contract. */ function underlyingBalance() external view returns(uint256 nativeBalance) { return address(this).balance; } /** * @notice Returns true if this contract implements the interface defined by `interfaceId`. * See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified * to learn more about how these ids are created. */ function supportsInterface(bytes4 interfaceId) public view override(UTSBase, AccessControl) returns(bool) { return interfaceId == type(IUTSConnector).interfaceId || super.supportsInterface(interfaceId); } /** * @notice Overridden function that send bridging request to the {_router}. * @param payment current transaction's {msg.value}, that can be used as payment for bridging execution. * @param dstToken the address of the {UTSToken} or {UTSConnector} on the destination chain. * @param to bridged native currency receiver on the destination chain. * @param amount native currency amount to bridge to the destination chain. * @param srcDecimals decimals of the current chain native currency. * @param dstChainId destination chain Id. * @param dstGasLimit {redeem} call gas limit on the destination chain. * @param customPayload user's additional data. * @param protocolPayload UTS protocol's additional data. * @return success call result. * * @dev By default, {payment} is equal to current transaction's {msg.value} as payment, but in this case, only * part of the {msg.value} must be sent to the {_router}. Function is overriden to send to the {_router} only the * difference between {payment} {msg.value} and {amount}, since {amount} is the amount of native currency that * will be bridged to the destination chain and should remain on the {UTSConnectorNative} contract * balance as locked liquidity. */ function _sendRequest( uint256 payment, bytes memory dstToken, bytes memory to, uint256 amount, uint8 srcDecimals, uint256 dstChainId, uint64 dstGasLimit, bytes memory customPayload, bytes memory protocolPayload ) internal override returns(bool success) { return IUTSRouter(router()).bridge{value: payment - amount}( dstToken, msg.sender.toBytes(), to, amount, srcDecimals, dstChainId, dstGasLimit, customPayload, protocolPayload ); } /** * @notice Overridden function that just checks {msg.value} is greater than the {amount}. * @param spender transaction sender, must be {msg.sender}. * @param from tokens holder on the current chain (msg.sender in that case). * @param amount native currency amount to bridge to the destination chain. * @return bridgedNativeAmount bridged native currency amount, that will be released on the destination chain. * @dev {bridgedNativeAmount} value may be different from {amount}, in case amount modifies by fee collecting * or any other custom logic. Returned {bridgedNativeAmount} value will be actually used for crosschain message. */ function _burnFrom( address spender, address from, bytes memory /* to */, uint256 amount, uint256 /* dstChainId */, bytes memory /* customPayload */ ) internal override returns(uint256 bridgedNativeAmount) { if (amount > msg.value) revert UTSConnectorNative__E0(); if (spender != from) revert UTSConnectorNative__E3(); return amount; } /** * @notice Overridden function that transfer native currency {amount} from this contract to receiver {to} address. * @param to native currency receiver on the current chain. * @param amount amount that {to} address will be received. * @return receivedNativeAmount amount that {to} address received. * @dev {receivedNativeAmount} value may be different from {amount}, in case amount modifies by fee collecting or * any other custom logic. * * @dev Some checks are added to ensure that the {to} address has received the native currency {amount}: * 1. {address(this).balance} is greater than the {amount} to transfer * 2. native currency transfer by low level {call} function is successful */ function _mintTo( address to, uint256 amount, bytes memory /* customPayload */, Origin memory /* origin */ ) internal override returns(uint256 receivedNativeAmount) { if (to != address(this)) { if (amount > address(this).balance) revert UTSConnectorNative__E1(); (bool _callResult, bytes memory _callResponse) = to.call{value: amount}(""); if (!_callResult) revert UTSConnectorNative__E2(_callResponse); } return amount; } /** * @notice The function is overridden only to include access restriction to the {setRouter} and {setChainConfig} functions. */ function _authorizeCall() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) { } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../../libraries/UTSERC20DataTypes.sol"; interface IUTSConnector { function underlyingDecimals() external view returns(uint8); function underlyingBalance() external view returns(uint256); function underlyingName() external view returns(string memory); function underlyingSymbol() external view returns(string memory); function initializeConnector( address owner, address underlyingToken, address router, uint256[] calldata allowedChainIds, ChainConfig[] calldata chainConfigs ) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "./UTSBaseExtended.sol"; interface IUTSFactory { function REGISTRY() external view returns(address); } interface IUTSRegistry { function updateChainConfigs(uint256[] calldata allowedChainIds, ChainConfig[] calldata chainConfigs) external; function updateRouter(address newRouter) external; } /** * @notice Extension of {UTSBase} that adds an external calls to emit events in the {UTSRegistry} to log crucial data * off-chain. * * @dev Сan only be used by contracts deployed by {UTSFactory} or contracts manually registered in the {UTSRegistry}. */ abstract contract UTSBaseIndexed is UTSBaseExtended { /// @notice The {UTSRegistry} contract address. address private immutable REGISTRY; /// @notice Initializes immutable {REGISTRY} variable. constructor() { REGISTRY = IUTSFactory(msg.sender).REGISTRY(); } function _setChainConfig(uint256[] memory allowedChainIds, ChainConfig[] memory chainConfigs) internal virtual override { IUTSRegistry(REGISTRY).updateChainConfigs(allowedChainIds, chainConfigs); super._setChainConfig(allowedChainIds, chainConfigs); } function _setRouter(address newRouter) internal virtual override { IUTSRegistry(REGISTRY).updateRouter(newRouter); super._setRouter(newRouter); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /// @notice Various structs used in the UTS protocol V1 ERC20-module contracts. /// @notice Destination chain {ChainConfig} settings for {UTSBase}. struct ChainConfig { bytes peerAddress; // connected {UTSToken} or {UTSConnector} contract address on the destination chain uint64 minGasLimit; // the amount of gas required to execute {UTSBase.redeem} function on the destination chain uint8 decimals; // connected {peerAddress} decimals on the destination chain bool paused; // flag indicating whether current contract is paused for sending/receiving messages from the connected {peerAddress} } /// @notice Destination {peerAddress} contract {ChainConfig} settings for {UTSBaseExtended.setChainConfigToDestination} function. struct ChainConfigUpdate { uint256[] allowedChainIds; // chains Ids available for bridging in both directions ChainConfig[] chainConfigs; // {ChainConfig} settings } /// @notice Crosschain message source peer data. struct Origin { bytes sender; // source message {msg.sender} sender uint256 chainId; // source chain Id bytes peerAddress; // source {UTSToken} or {UTSConnector} contract address uint8 decimals; // source {peerAddress} decimals } /// @notice {UTSToken} initial settings, configuration, and metadata for deployment and initialization. struct DeployTokenData { bytes owner; // the address of the initial {AccessControl.DEFAULT_ADMIN_ROLE} string name; // the {ERC20.name} of the {UTSToken} token string symbol; // the {ERC20.symbol} of the {UTSToken} token uint8 decimals; // the {ERC20.decimals} of the {UTSToken} token uint256 initialSupply; // total initial {UTSToken} supply to mint uint256 mintedAmountToOwner; // initial {UTSToken} supply to mint to {owner} balance bool pureToken; // flag indicating whether the {UTSToken} is use lock/unlock or mint/burn mechanism for bridging bool mintable; // flag indicating whether {owner} can mint an unlimited amount of {UTSToken} tokens bool globalBurnable; // flag indicating whether the {UTSToken} is globally burnable by anyone bool onlyRoleBurnable; // flag indicating whether only addresses with the {AccessControl.BURNER_ROLE} can burn tokens bool feeModule; // flag indicating whether the {UTSToken} is supports the fee deducting for bridging bytes router; // the address of the authorized {UTSRouter} uint256[] allowedChainIds; // chains Ids available for bridging in both directions ChainConfig[] chainConfigs; // {ChainConfig} settings for the corresponding {allowedChainIds} bytes32 salt; // value used for precalculation of {UTSToken} contract address } /// @notice {UTSConnector} initial settings and configuration for deployment and initialization. struct DeployConnectorData { bytes owner; // the address of the initial {AccessControl.DEFAULT_ADMIN_ROLE} bytes underlyingToken; // underlying ERC20 token address bool feeModule; // flag indicating whether the {UTSConnector} is supports the fee deducting for bridging bytes router; // the address of the authorized {UTSRouter} uint256[] allowedChainIds; // chains Ids available for bridging in both directions ChainConfig[] chainConfigs; // {ChainConfig} settings for the corresponding {allowedChainIds} bytes32 salt; // value used for precalculation of {UTSConnector} contract address } /// @notice Metadata for the crosschain deployment request for {UTSDeploymentRouter.sendDeployRequest}. struct DeployMetadata { uint256 dstChainId; // destination chain Id bool isConnector; // flag indicating whether is {UTSConnector}(true) or {UTSToken}(false) deployment bytes params; // abi.encoded {DeployTokenData} struct or abi.encoded {DeployConnectorData} struct } /// @notice Destination chain settings for sending a crosschain deployment request in the {UTSDeploymentRouter}. struct DstDeployConfig { bytes factory; // destination {UTSFactory} address uint64 tokenDeployGas; // the amount of gas required to deploy the {UTSToken} on the destination chain uint64 connectorDeployGas; // the amount of gas required to deploy the {UTSConnector} on the destination chain uint16 protocolFee; // protocol fee (basis points) for crosschain deployment on the destination chain }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../UTSBase.sol"; import "../interfaces/IUTSBaseExtended.sol"; /** * @notice Extension of {UTSBase} that allows {UTSBase} contract owner to change {ChainConfig} settings on different * destination chains with a single crosschain transaction. */ abstract contract UTSBaseExtended is IUTSBaseExtended, UTSBase { using AddressConverter for address; using BytesLib for bytes; /** * @notice Send crosschain message that will change destination {ChainConfig}. * @param dstChainIds destination chains Ids to which a message will be sent to change their {ChainConfig}. * @param newConfigs new {ChainConfig} settings for provided {allowedChainIds} to be setted on the destination chains. * @return success call result. */ function setChainConfigToDestination( uint256[] calldata dstChainIds, ChainConfigUpdate[] calldata newConfigs ) external payable returns(bool success) { _authorizeCall(); if (dstChainIds.length != newConfigs.length) revert UTSBase__E4(); bytes[] memory _dstPeers = new bytes[](dstChainIds.length); for (uint256 i; dstChainIds.length > i; ++i) _dstPeers[i] = _chainConfig[dstChainIds[i]].peerAddress; return IUTSRouter(router()).requestToUpdateConfig{value: msg.value}( msg.sender.toBytes(), dstChainIds, _dstPeers, newConfigs ); } /** * @notice Sets the destination chains settings by crosschain message. * @param allowedChainIds chains Ids available for bridging in both directions. * @param chainConfigs array of new {ChainConfig} settings for provided {allowedChainIds}. * @param origin source chain data. * @dev Only the {_router} can execute this function. */ function setChainConfigByRouter( uint256[] calldata allowedChainIds, ChainConfig[] calldata chainConfigs, Origin calldata origin ) external { _onlyRouter(); if (!_chainConfig[origin.chainId].peerAddress.equalStorage(origin.peerAddress)) revert UTSBase__E7(); _setChainConfig(allowedChainIds, chainConfigs); } /** * @notice Returns estimated minimal amount to pay for {setChainConfigToDestination} call. * @param dstChainIds destination chains Ids to which a message will be sent. * @param configsLength {ChainConfigUpdate.allowedChainIds} length. * @return paymentAmount source chain native currency amount to pay for {setChainConfigToDestination} call. */ function estimateUpdateFee( uint256[] calldata dstChainIds, uint256[] calldata configsLength ) external view returns(uint256 paymentAmount) { return IUTSRouter(router()).getUpdateFee(dstChainIds, configsLength); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "./IUTSBase.sol"; interface IUTSBaseExtended { function setChainConfigToDestination( uint256[] calldata dstChainIds, ChainConfigUpdate[] calldata newConfigs ) external payable returns(bool success); function setChainConfigByRouter( uint256[] calldata allowedChainIds, ChainConfig[] calldata chainConfigs, Origin calldata origin ) external; function estimateUpdateFee( uint256[] calldata dstChainIds, uint256[] calldata configsLength ) external view returns(uint256 paymentAmount); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "@openzeppelin/[email protected]/utils/introspection/ERC165.sol"; import "../libraries/BytesLib.sol"; import "../libraries/AddressConverter.sol"; import "../libraries/DecimalsConverter.sol"; import "../libraries/UTSERC20DataTypes.sol"; import "./interfaces/IUTSBase.sol"; import "./interfaces/IUTSRouter.sol"; /** * @notice Abstract contract implementing minimal and basic functionality for sending and receiving crosschain bridges * of ERC20 tokens via UTS protocol V1. * * @dev * The {__UTSBase_init} function MUST be called before using other functions of the {UTSBase} contract. * The {_authorizeCall} function MUST be overridden to include access restriction to the {setRouter} and * {setChainConfig} functions. * The {_mintTo} function MUST be overridden to implement {mint}/{transfer} underlying tokens to receiver {to} address * by {_router}. * The {_burnFrom} function MUST be overridden to implement {burn}/{transferFrom} underlying tokens from {spender}/{from} * address for bridging. */ abstract contract UTSBase is IUTSBase, ERC165 { using AddressConverter for address; using DecimalsConverter for uint256; using BytesLib for bytes; /// @notice Nonce used for {storeFailedExecution} executions to guarantee uniqueness. uint256 private _retryNonce; /** * @notice Address that can execute {redeem} and {storeFailedExecution} functions. * @dev Should be an authorized {UTSRouter} contract address or a zero address in case of disconnection from UTS protocol. */ address private _router; /// @notice Address of the underlying ERC20 token. address internal _underlyingToken; /// @notice Decimals of the underlying ERC20 token. uint8 internal _decimals; /// @notice {ChainConfig} settings for the corresponding destination chain Id. /// @dev See the {UTSERC20DataTypes.ChainConfig} for details. mapping(uint256 chainId => ChainConfig dstChainConfig) internal _chainConfig; /** * @notice Receiver address for the corresponding {redeem} message hash. * @dev Mapping is filled only by {storeFailedExecution} function if the {redeem} call is unsuccessful. * IMPORTANT: Execution of the {_redeem} function with a {to} zero address MUST be forbidden. */ mapping(bytes32 msgHash => address receiverAddress) private _failedExecution; /// @notice Indicates an error that the {UTSBase} contract initialized already. error UTSBase__E0(); /// @notice Indicates an error that the function caller is not the {_router}. error UTSBase__E1(); /// @notice Indicates an error that the {to} is zero address. error UTSBase__E2(); /// @notice Indicates an error that the {amount} to bridge is zero. error UTSBase__E3(); /// @notice Indicates an error that lengths of {allowedChainIds} and {chainConfigs} do not match in the {_setChainConfig} function. error UTSBase__E4(); /// @notice Indicates an error that the destination {peerAddress} is paused for sending and receiving crosschain messages. error UTSBase__E5(); /// @notice Indicates an error that the provided {dstGasLimit} is less than the minimum required amount. error UTSBase__E6(); /// @notice Indicates an error that the source {Origin.peerAddress} is unauthorized in the {ChainConfig} for corresponding {Origin.chainId}. error UTSBase__E7(); /** * @notice Emitted when the {_router} address is updated. * @param caller the caller address who set the new {_router} address. * @param newRouter the address of the new {_router}. */ event RouterSet(address indexed caller, address newRouter); /** * @notice Emitted when {ChainConfig} settings are updated. * @param caller the caller address who set the new destination {ChainConfig} settings. * @param allowedChainIds new chains Ids available for bridging in both directions. * @param chainConfigs array of new {ChainConfig} settings for corresponding {allowedChainIds}. */ event ChainConfigUpdated(address indexed caller, uint256[] allowedChainIds, ChainConfig[] chainConfigs); /** * @notice Emitted when tokens are successfully redeemed from the source chain. * @param to tokens receiver on the current chain. * @param amount received amount. * @param srcPeerAddressIndexed indexed source {peerAddress}. * @param srcPeerAddress source {peerAddress}. * @param srcChainId source chain Id. * @param sender source chain sender's address. */ event Redeemed( address indexed to, uint256 amount, bytes indexed srcPeerAddressIndexed, bytes srcPeerAddress, uint256 indexed srcChainId, bytes sender ); /** * @notice Emitted when crosschain bridge message is successfully sent to a destination chain. * @param spender the caller address who initiate the bridge. * @param from tokens holder on the current chain. * @param dstPeerAddressIndexed indexed destination {peerAddress}. * @param dstPeerAddress destination {peerAddress}. * @param to bridged tokens receiver on the destination chain. * @param amount bridged tokens amount. * @param dstChainId destination chain Id. */ event Bridged( address indexed spender, address from, bytes indexed dstPeerAddressIndexed, bytes dstPeerAddress, bytes to, uint256 amount, uint256 indexed dstChainId ); /** * @notice Emitted when a {storeFailedExecution} executed in case of failed {redeem} call. * @param to tokens receiver on the current chain. * @param amount amount to receive. * @param customPayload user's additional data. * @param originIndexed indexed source chain data. * @param origin source chain data. * @dev See the {UTSERC20DataTypes.Origin} for details. * @param result handled error message. * @param nonce unique failed execution's counter. */ event ExecutionFailed( address indexed to, uint256 amount, bytes customPayload, Origin indexed originIndexed, Origin origin, bytes indexed result, uint256 nonce ); /** * @notice Initializes basic settings. * @param underlyingToken_ underlying ERC20 token address. * @dev In case this contract and ERC20 are the same contract, {underlyingToken_} should be address(this). * * @param decimals_ underlying token decimals. * @dev Can and MUST be called only once. */ function __UTSBase_init(address underlyingToken_, uint8 decimals_) internal { if (_retryNonce > 0) revert UTSBase__E0(); _underlyingToken = underlyingToken_; _decimals = decimals_; // {_retryNonce} counter increases here for two reasons: // 1. to block repeated {__UTSBase_init} call // 2. initialize the {_retryNonce} variable to unify the gas limit calculation of the {storeFailedExecution} call _retryNonce = 1; } /** * @notice Initiates the tokens bridging. * @param from tokens holder on the current chain. * @param to bridged tokens receiver on the destination chain. * @param amount tokens amount to bridge to the destination chain. * @param dstChainId destination chain Id. * @param dstGasLimit {redeem} call gas limit on the destination chain. * @param customPayload user's additional data. * @param protocolPayload UTS protocol's additional data. * @return success call result. * @return bridgedAmount bridged tokens amount. */ function bridge( address from, bytes calldata to, uint256 amount, uint256 dstChainId, uint64 dstGasLimit, bytes calldata customPayload, bytes calldata protocolPayload ) external payable virtual returns(bool success, uint256 bridgedAmount) { return _bridge( msg.sender, from, to, amount, dstChainId, dstGasLimit, customPayload, protocolPayload ); } /** * @notice Executes the tokens delivery from the source chain. * @param to tokens receiver on the current chain. * @param amount amount to receive. * @param customPayload user's additional data. * @param origin source chain data. * @dev See the {UTSERC20DataTypes.Origin} for details. * @return success call result. * @dev Only the {_router} can execute this function. */ function redeem( address to, uint256 amount, bytes calldata customPayload, Origin calldata origin ) external payable virtual returns(bool success) { _onlyRouter(); return _redeem(to, amount, customPayload, origin); } /** * @notice Stores failed execution's data. * @param to tokens receiver on the current chain. * @param amount tokens amount to receive. * @param customPayload user's additional data. * @param origin source chain data. * @dev See the {UTSERC20DataTypes.Origin} for details. * @param result handled error message. * @dev Only the {_router} can execute this function. */ function storeFailedExecution( address to, uint256 amount, bytes calldata customPayload, Origin calldata origin, bytes calldata result ) external virtual { _onlyRouter(); _failedExecution[keccak256(abi.encode(to, amount, customPayload, origin, _retryNonce))] = to; emit ExecutionFailed(to, amount, customPayload, origin, origin, result, _retryNonce); _retryNonce++; } /** * @notice Executes the tokens delivery after failed execution. * @param to tokens receiver on the current chain. * @param amount amount to receive. * @param customPayload user's additional data. * @param origin source chain data. * @dev See the {UTSERC20DataTypes.Origin} for details. * @param nonce unique failed execution's counter. * @return success call result. */ function retryRedeem( address to, uint256 amount, bytes calldata customPayload, Origin calldata origin, uint256 nonce ) external virtual returns(bool success) { if (to == address(0)) return false; bytes32 _hash = keccak256(abi.encode(to, amount, customPayload, origin, nonce)); if (_failedExecution[_hash] != to) return false; delete _failedExecution[_hash]; return _redeem(to, amount, customPayload, origin); } /** * @notice Sets the destination chains settings. * @param allowedChainIds chains Ids available for bridging in both directions. * @param chainConfigs array of {ChainConfig} settings for provided {allowedChainIds}, containing: * peerAddress: connected {UTSToken} or {UTSConnector} contract address on the destination chain * minGasLimit: the amount of gas required to execute {redeem} function on the destination chain * decimals: connected {peerAddress} decimals on the destination chain * paused: flag indicating whether current contract is paused for sending/receiving messages from the connected {peerAddress} * * @return success call result. */ function setChainConfig( uint256[] calldata allowedChainIds, ChainConfig[] calldata chainConfigs ) external virtual returns(bool success) { _authorizeCall(); _setChainConfig(allowedChainIds, chainConfigs); return true; } /** * @notice Sets the UTSRouter address. * @param newRouter new {_router} address. * @return success call result. * @dev {_router} address has access rights to execute {redeem} and {storeFailedExecution} functions. */ function setRouter(address newRouter) external virtual returns(bool success) { _authorizeCall(); _setRouter(newRouter); return true; } /** * @notice Returns the UTSRouter {_router} address. * @return routerAddress the {UTSRouter} address. */ function router() public view returns(address routerAddress) { return _router; } /** * @notice Returns the UTSBase protocol version. * @return UTS protocol version. */ function protocolVersion() public pure virtual returns(bytes2) { return 0x0101; } /** * @notice Returns the underlying ERC20 token address. * @return ERC20 {_underlyingToken} address. */ function underlyingToken() public view virtual returns(address) { return _underlyingToken; } /** * @notice Returns whether failed execution's data is stored. * @param to tokens receiver on the current chain. * @param amount amount to receive. * @param customPayload user's additional data. * @param origin source chain data. * @dev See the {UTSERC20DataTypes.Origin} for details. * @param nonce unique failed execution's counter. * @return isFailed result. */ function isExecutionFailed( address to, uint256 amount, bytes calldata customPayload, Origin calldata origin, uint256 nonce ) external view virtual returns(bool isFailed) { if (to == address(0)) return false; return _failedExecution[keccak256(abi.encode(to, amount, customPayload, origin, nonce))] == to; } /** * @notice Returns estimated minimal amount to pay for bridging and minimal gas limit. * @param dstChainId destination chain Id. * @param dstGasLimit {redeem} call gas limit on the destination chain. * @param customPayloadLength user's additional data length. * @param protocolPayload UTS protocol's additional data. * @return paymentAmount source chain native currency amount to pay for bridging. * @return dstMinGasLimit destination chain minimal {redeem} call gas limit. */ function estimateBridgeFee( uint256 dstChainId, uint64 dstGasLimit, uint16 customPayloadLength, bytes calldata protocolPayload ) public view virtual returns(uint256 paymentAmount, uint64 dstMinGasLimit) { dstMinGasLimit = IUTSRouter(_router).dstMinGasLimit(dstChainId); uint64 _configMinGasLimit = _chainConfig[dstChainId].minGasLimit; return ( IUTSRouter(_router).getBridgeFee(dstChainId, dstGasLimit, customPayloadLength, protocolPayload), dstMinGasLimit >= _configMinGasLimit ? dstMinGasLimit : _configMinGasLimit ); } /** * @notice Returns destination chain configs for sending and receiving crosschain messages. * @param chainIds destination chain Ids. * @return configs array of {ChainConfig} settings for provided {chainIds}. * @dev See the {UTSERC20DataTypes.ChainConfig} for details. */ function getChainConfigs(uint256[] calldata chainIds) external view returns(ChainConfig[] memory configs) { configs = new ChainConfig[](chainIds.length); for (uint256 i; chainIds.length > i; ++i) configs[i] = _chainConfig[chainIds[i]]; } /** * @notice Returns true if this contract implements the interface defined by `interfaceId`. * See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified * to learn more about how these ids are created. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns(bool) { return interfaceId == type(IUTSBase).interfaceId || super.supportsInterface(interfaceId); } /** * @notice Internal function that initiates the tokens bridging. * @param spender transaction sender, must be {msg.sender}. * @param from tokens holder on the current chain. * @param to bridged tokens receiver on the destination chain. * @param amount tokens amount to bridge to the destination chain. * @param dstChainId destination chain Id. * @param dstGasLimit {redeem} call gas limit on the destination chain. * @param customPayload user's additional data. * @param protocolPayload UTS protocol's additional data. * * @return success call result. * @return bridgedAmount bridged tokens amount. * * @dev Implements all basic checks and calculations, containing: * 1. required destination gas limit check * 2. destination peer is not paused check * 3. amount conversion in accordance with destination token decimals * 4. bridged tokens amount is not zero check */ function _bridge( address spender, address from, bytes memory to, uint256 amount, uint256 dstChainId, uint64 dstGasLimit, bytes memory customPayload, bytes memory protocolPayload ) internal virtual returns(bool success, uint256 bridgedAmount) { if (from == address(0)) from = spender; ChainConfig memory config = _chainConfig[dstChainId]; if (config.minGasLimit > dstGasLimit) revert UTSBase__E6(); if (config.paused) revert UTSBase__E5(); uint8 _srcDecimals = _decimals; amount = amount.convert(_srcDecimals, config.decimals).convert(config.decimals, _srcDecimals); amount = _burnFrom( spender, from, to, amount, dstChainId, customPayload ); if (amount == 0) revert UTSBase__E3(); emit Bridged(spender, from, config.peerAddress, config.peerAddress, to, amount, dstChainId); return ( _sendRequest( msg.value, config.peerAddress, to, amount, _srcDecimals, dstChainId, dstGasLimit, customPayload, protocolPayload ), amount ); } /** * @notice Internal function that call {_router} contract to send crosschain bridge message. * @param payment the native currency amount that will be transfer to the {_router} as payment for sending this message. * @param dstToken the contract address on the {dstChainId} that will receive this message. * @param to bridged tokens receiver on the destination chain. * @param amount amount that {to} address will receive (before decimals conversion on the destination chain). * @param srcDecimals source ERC20 underlying token decimals. * @param dstChainId destination chain Id. * @param dstGasLimit {redeem} call gas limit on the destination chain. * @param customPayload user's additional data. * @param protocolPayload UTS protocol's additional data. * * @return success call result. * * @dev {customPayload} can be used to send an additional data, it will be sent to the {dstToken} contract on the * destination chain in accordance with {redeem} function. */ function _sendRequest( uint256 payment, bytes memory dstToken, bytes memory to, uint256 amount, uint8 srcDecimals, uint256 dstChainId, uint64 dstGasLimit, bytes memory customPayload, bytes memory protocolPayload ) internal virtual returns(bool success) { return IUTSRouter(_router).bridge{value: payment}( dstToken, msg.sender.toBytes(), to, amount, srcDecimals, dstChainId, dstGasLimit, customPayload, protocolPayload ); } /** * @notice Internal function that releases tokens to receiver by crosschain message from the source chain. * @param to bridged tokens receiver on the current chain. * @param amount amount that {to} address will receive (before decimals conversion on the current chain). * @param customPayload user's additional data. * @param origin source chain data. * @dev See the {UTSERC20DataTypes.Origin} for details. * @return success call result. * * @dev Implements all basic checks and calculations, containing: * 1. receiver address is not zero address check * 2. source peer address is allowed to send messages to this contract check * 3. source peer address is not paused check * 4. amount conversion in accordance with source token decimals */ function _redeem( address to, uint256 amount, bytes memory customPayload, Origin memory origin ) internal virtual returns(bool success) { if (to == address(0)) revert UTSBase__E2(); ChainConfig memory config = _chainConfig[origin.chainId]; if (!config.peerAddress.equal(origin.peerAddress)) revert UTSBase__E7(); if (config.paused) revert UTSBase__E5(); amount = _mintTo(to, amount.convert(origin.decimals, _decimals), customPayload, origin); emit Redeemed(to, amount, origin.peerAddress, origin.peerAddress, origin.chainId, origin.sender); return true; } /** * @notice Internal function that sets the destination chains settings and emits corresponding event. * @param allowedChainIds chains Ids available for bridging in both directions. * @param chainConfigs array of {ChainConfig} settings for provided {allowedChainIds}. * @dev See the {UTSERC20DataTypes.ChainConfig} for details. */ function _setChainConfig(uint256[] memory allowedChainIds, ChainConfig[] memory chainConfigs) internal virtual { if (allowedChainIds.length != chainConfigs.length) revert UTSBase__E4(); for (uint256 i; allowedChainIds.length > i; ++i) _chainConfig[allowedChainIds[i]] = chainConfigs[i]; emit ChainConfigUpdated(msg.sender, allowedChainIds, chainConfigs); } /** * @notice Internal function that sets the UTSRouter address and emits corresponding event. * @param newRouter new {_router} address. */ function _setRouter(address newRouter) internal virtual { _router = newRouter; emit RouterSet(msg.sender, newRouter); } /** * @notice Internal view function that implement basic access check for {redeem} and {storeFailedExecution} functions. */ function _onlyRouter() internal view { if (msg.sender != _router) revert UTSBase__E1(); } /** * @dev The function MUST be overridden to include access restriction to the {setRouter} and {setChainConfig} functions. */ function _authorizeCall() internal virtual; /** * @dev The function MUST be overridden to implement {mint}/{transfer} underlying tokens to receiver {to} address by {_router}. */ function _mintTo( address to, uint256 amount, bytes memory customPayload, Origin memory origin ) internal virtual returns(uint256 receivedAmount); /** * @dev The function MUST be overridden to implement {burn}/{transferFrom} underlying tokens from {spender}/{from} * address for bridging. * * IMPORTANT: If this contract IS a token itself, and the {spender} and {from} addresses are different, an {ERC20.allowance} * check MUST be added. * * IMPORTANT: If this contract IS NOT a token itself, the {spender} and {from} addresses MUST be the same to prevent tokens * stealing via third-party allowances. * * IMPORTANT: Returned {bridgedAmount} value will be actually used for crosschain message, as it may be different from {amount}, * if custom logic inside {_burnFrom} function modifies it. */ function _burnFrom( address spender, address from, bytes memory to, uint256 amount, uint256 dstChainId, bytes memory customPayload ) internal virtual returns(uint256 bridgedAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../../libraries/UTSERC20DataTypes.sol"; interface IUTSBase { function protocolVersion() external view returns(bytes2); function underlyingToken() external view returns(address underlyingTokenAddress); function router() external view returns(address routerAddress); function getChainConfigs(uint256[] calldata chainIds) external view returns(ChainConfig[] memory configs); function isExecutionFailed( address to, uint256 amount, bytes calldata customPayload, Origin calldata origin, uint256 nonce ) external view returns(bool isFailed); function estimateBridgeFee( uint256 dstChainId, uint64 dstGasLimit, uint16 customPayloadLength, bytes calldata protocolPayload ) external view returns(uint256 paymentAmount, uint64 dstMinGasLimit); function setRouter(address newRouter) external returns(bool success); function setChainConfig( uint256[] calldata allowedChainIds, ChainConfig[] calldata chainConfigs ) external returns(bool success); function bridge( address from, bytes calldata to, uint256 amount, uint256 dstChainId, uint64 dstGasLimit, bytes calldata customPayload, bytes calldata protocolPayload ) external payable returns(bool success, uint256 bridgedAmount); function redeem( address to, uint256 amount, bytes calldata customPayload, Origin calldata origin ) external payable returns(bool success); function storeFailedExecution( address to, uint256 amount, bytes calldata customPayload, Origin calldata origin, bytes calldata result ) external; function retryRedeem( address to, uint256 amount, bytes calldata customPayload, Origin calldata origin, uint256 nonce ) external returns(bool success); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "../../libraries/UTSERC20DataTypes.sol"; interface IUTSRouter { function MASTER_ROUTER() external view returns(address); function PRICE_FEED() external view returns(address); function protocolVersion() external view returns(bytes2); function getBridgeFee( uint256 dstChainId, uint64 dstGasLimit, uint256 payloadLength, bytes calldata protocolPayload ) external view returns(uint256 bridgeFeeAmount); function getUpdateFee( uint256[] calldata dstChainIds, uint256[] calldata configsLength ) external view returns(uint256 updateFeeAmount); function dstMinGasLimit(uint256 dstChainId) external view returns(uint64 dstMinGasLimitAmount); function dstProtocolFee(uint256 dstChainId) external view returns(uint16 dstProtocolFeeRate); function dstUpdateGas(uint256 dstChainId) external view returns(uint64 dstUpdateGasAmount); function setDstMinGasLimit(uint256[] calldata dstChainIds, uint64[] calldata newDstMinGasLimits) external; function setDstProtocolFee(uint256[] calldata dstChainIds, uint16[] calldata newDstProtocolFees) external; function setDstUpdateGas(uint256[] calldata dstChainIds, uint64[] calldata newDstUpdateGas) external; function bridge( bytes calldata dstToken, bytes calldata sender, bytes calldata to, uint256 amount, uint8 srcDecimals, uint256 dstChainId, uint64 dstGasLimit, bytes calldata customPayload, bytes calldata protocolPayload ) external payable returns(bool success); function requestToUpdateConfig( bytes calldata sender, uint256[] calldata dstChainIds, bytes[] calldata dstPeers, ChainConfigUpdate[] calldata newConfigs ) external payable returns(bool success); function execute( address peerAddress, bytes1 messageType, bytes calldata localParams ) external payable returns(uint8 opResult); function pause() external; function unpause() external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /** * @notice The library contains utility function for converting amounts with different decimals values for the UTS protocol V1. */ library DecimalsConverter { function convert(uint256 amount, uint256 decimalsIn, uint256 decimalsOut) internal pure returns(uint256) { if (decimalsOut > decimalsIn) { return amount * (10 ** (decimalsOut - decimalsIn)); } else { if (decimalsOut < decimalsIn) { return amount / (10 ** (decimalsIn - decimalsOut)); } } return amount; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /** * @notice A library contains utility functions for converting address type for the UTS protocol V1. */ library AddressConverter { function toBytes(address _address) internal pure returns(bytes memory) { return abi.encodePacked(_address); } function toAddress(bytes memory _params) internal pure returns(address) { return address(uint160(bytes20(_params))); } function toAddressPadded(bytes memory _params) internal pure returns(address addressPadded) { if (32 > _params.length) return address(0); assembly { addressPadded := div(mload(add(add(_params, 0x20), 12)), 0x1000000000000000000000000) } } }
// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for { } eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } }
{ "viaIR": true, "evmVersion": "paris", "optimizer": { "enabled": true, "runs": 1 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "remappings": [] }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"bool","name":"","type":"bool"}],"name":"getCode","outputs":[{"internalType":"bytes","name":"bytecode","type":"bytes"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
6080806040523461001657612966908161001c8239f35b600080fdfe6080600436101561000f57600080fd5b6000803560e01c63b514681e1461002557600080fd5b346100d857602090816003193601126100d857600435801515036100d857601f1991612855603f8101841685019291908584106001600160401b038511176100c45760409593929195926040528084526100dc868501396040519485938185528051938483870152835b8581106100ae57866040818a601f8a8a85828601015201168101030190f35b828101840151898201830152889650830161008f565b634e487b7160e01b83526041600452602483fd5b80fdfe60a08060405234620000d7576306433b1b60e01b8152602081600481335afa908115620000cb5760009162000053575b506080526040516127789081620000dd8239608051818181611d6b0152611ee40152f35b60203d602011620000c3575b601f8101601f191682016001600160401b03811183821017620000af57602091839160405281010312620000ab5751906001600160a01b0382168203620000a85750386200002f565b80fd5b5080fd5b634e487b7160e01b84526041600452602484fd5b503d6200005f565b6040513d6000823e3d90fd5b600080fdfe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806301ffc9a7146101cb57806304e7aae9146101c6578063081fafa0146101c15780631b7fd4ec146101bc5780631d34dbc3146101b7578063248a9ca3146101b25780632495a599146101ad57806325a760c2146101a85780632ae9c600146101a35780632da04cba1461019e5780632f2ff15d1461019957806336568abe1461019457806359356c5c1461018f578063755067181461018a5780638ec58bb51461018557806391d1485414610180578063a217fddf1461017b578063bd2d87eb14610176578063c0d7865514610171578063cb05ac031461016c578063d3a2ba7614610167578063d547741f14610162578063d90a730e1461015d578063dde63fed14610158578063e8f6e9e214610153578063f887ea401461014e5763f96e52ca0361000e57611097565b610fcd565b610ea8565b610e89565b610e47565b610e08565b610c84565b610b0c565b610ae3565b610a9d565b610a25565b6109e5565b6109bc565b610872565b610856565b61080f565b6107d0565b610718565b6106f7565b6106d3565b6106aa565b61067b565b6105da565b6104fd565b610395565b6102d4565b346102555760203660031901126102555760043563ffffffff60e01b8116809103610255576020906303ca2c9760e01b8114908115610210575b506040519015158152f35b637965db0b60e01b81149150811561022a575b5038610205565b63950a21e160e01b811491508115610244575b5038610223565b6301ffc9a760e01b1490503861023d565b600080fd5b9181601f84011215610255578235916001600160401b038311610255576020808501948460051b01011161025557565b6040600319820112610255576001600160401b039160043583811161025557826102b69160040161025a565b93909392602435918211610255576102d09160040161025a565b9091565b346102555761030d6102ff6103076102eb3661028a565b94916102f893919361209e565b3691611212565b9236916112e5565b90611d68565b602060405160018152f35b600435906001600160a01b038216820361025557565b602435906001600160a01b038216820361025557565b604435906001600160a01b038216820361025557565b9181601f84011215610255578235916001600160401b038311610255576020838186019501011161025557565b908160809103126102555790565b6080366003190112610255576103a9610318565b6001600160401b03604435818111610255576103c990369060040161035a565b909160643590811161025557610402926103ea6103fa923690600401610387565b926103f3611e69565b369161127b565b5036906113af565b906001600160a01b03811680156104eb57602083019161042a6104258451611575565b611cd1565b928351936104456104416040880196875190612433565b1590565b6104d957606001516104c75761049960008051602061272383398151915292610493610475606089015160ff1690565b60ff8061048860025460ff9060a01c1690565b1691166024356124a1565b90612511565b935190519451936104b96104ac83611e8f565b9560405193849384611eaf565b0390a4602060405160018152f35b60405163188e252560e11b8152600490fd5b604051637cb3947160e11b8152600490fd5b6040516351c7b3e160e01b8152600490fd5b346102555760a036600319011261025557610516610318565b61051e61032e565b90610527610344565b6001600160401b0392906064358481116102555761054990369060040161025a565b9290946084359081116102555761056490369060040161025a565b926000546105b757600280546001600160a81b0319166001600160a01b0390941693909317600960a11b179092556001600055610019956105b294610307936102ff9291906102f890611eda565b611f8d565b60405163180cbc2160e21b8152600490fd5b6001600160401b0381160361025557565b60e0366003190112610255576105ee610318565b6001600160401b03906024358281116102555761060f90369060040161035a565b906084359061061d826105c9565b60a4358581116102555761063590369060040161035a565b92909160c4359687116102555761065361066397369060040161035a565b9690956064359260443592611428565b604080519215158352602083019190915290f35b0390f35b346102555760203660031901126102555760043560005260056020526020600160406000200154604051908152f35b34610255576000366003190112610255576002546040516001600160a01b039091168152602090f35b3461025557600036600319011261025557602060ff60025460a01c16604051908152f35b346102555760003660031901126102555760405161010160f01b8152602090f35b3461025557610763602061072b3661028a565b9492909161077560018060a01b03600154169360405197889687958695632d79c1e160e01b8752604060048801526044870191611594565b84810360031901602486015291611594565b03915afa80156107cb576106779160009161079c575b506040519081529081906020820190565b6107be915060203d6020116107c4575b6107b681836111d8565b810190611585565b3861078b565b503d6107ac565b6115b8565b34610255576040366003190112610255576100196004356107ef61032e565b9080600052600560205261080a6001604060002001546120e9565b611fff565b346102555760403660031901126102555761082861032e565b336001600160a01b03821603610844576100199060043561212a565b60405163334bd91960e11b8152600490fd5b3461025557600036600319011261025557602047604051908152f35b34610255576060366003190112610255576001600160401b03600435818111610255576108a390369060040161025a565b90602435838111610255576108bc90369060040161025a565b9190604435858111610255576108d6903690600401610387565b946108df611e69565b6000956020810135875260036020526040872090604081013590601e19813603018212156109535701803592831161094f5760200190823603821361094f576109306104419261093694369161127b565b9061219d565b6104d9576102ff6103079261094c953691611212565b80f35b8780fd5b8880fd5b60a0600319820112610255576004356001600160a01b03811681036102555791602435916001600160401b0391604435838111610255578261099b9160040161035a565b93909392606435918211610255576109b591600401610387565b9060843590565b346102555760206109db6109cf36610957565b949390939291926116b4565b6040519015158152f35b3461025557604036600319011261025557602060ff610a19610a0561032e565b6004356000526005845260406000206117ff565b54166040519015158152f35b3461025557600036600319011261025557602060405160008152f35b60005b838110610a545750506000910152565b8181015183820152602001610a44565b90602091610a7d81518092818552858086019101610a41565b601f01601f1916010190565b906020610a9a928181520190610a64565b90565b3461025557600036600319011261025557610677604051610abd816111bd565b6005815264536f6e696360d81b6020820152604051918291602083526020830190610a64565b346102555760203660031901126102555761030d610aff610318565b610b0761209e565b611eda565b3461025557608036600319011261025557602435600435610b2c826105c9565b60443561ffff81168103610255576001600160401b0360643581811161025557610b5a90369060040161035a565b600154909390610b8090610b74906001600160a01b031681565b6001600160a01b031690565b6040516329d2f02160e21b815260048101879052602097909291908884602481855afa9788156107cb578994600099610c55575b50610bf1610bd46001610bc684611575565b01546001600160401b031690565b986040519788968795869562092e8760e71b87526004870161182b565b03915afa9485156107cb57600095610c36575b505081811690831610610c2e5750905b604080519182526001600160401b03929092166020820152f35b905090610c14565b610c4d929550803d106107c4576107b681836111d8565b923880610c04565b610c76919950853d8711610c7d575b610c6e81836111d8565b810190611816565b9738610bb4565b503d610c64565b346102555760a036600319011261025557610c9d610318565b6001600160401b03906024359060443583811161025557610cc290369060040161035a565b909260643585811161025557610cdc903690600401610387565b90608435958611610255577f89fecad7e82e777b95efd8da30d0290c555adcd7d5fd59c2bbd44752bc09ccab610e0395610de595610dfb610d2360409a369060040161035a565b9096610d2d611e69565b610d8a8460009d8e8a8d610d608b610d5285548a885195869460208601988c8a611671565b03601f1981018352826111d8565b519020815260046020522080546001600160a01b0319166001600160a01b03909216919091179055565b8b54998a92604051602081610dca610dac82610da689806115e5565b9061185e565b83880135815283610dc060408a018a6115e5565b919092019161185e565b60ff610dd8606089016112cd565b1681520301902099611873565b9860405195869560018060a01b03169886611888565b0390a46118ce565b815580f35b3461025557604036600319011261025557610019600435610e2761032e565b90806000526005602052610e426001604060002001546120e9565b61212a565b3461025557600036600319011261025557610677604051610e67816111bd565b60018152605360f81b6020820152604051918291602083526020830190610a64565b346102555760206109db610e9c36610957565b949390939291926118e2565b610eb13661028a565b610ebc92919261209e565b808203610fbb57610ecc82611926565b9260005b808411610f7b57506001549394602094909190610f2190610ef9906001600160a01b0316610b74565b93610f0333612254565b604051633bde546760e11b8152988997889687969360048801611c38565b039134905af180156107cb5761067791600091610f4c575b5060405190151581529081906020820190565b610f6e915060203d602011610f74575b610f6681836111d8565b810190611a8e565b38610f39565b503d610f5c565b80610f9b610f96610f90610fb694888b611986565b35611575565b6119e9565b610fa5828861199b565b52610fb0818761199b565b506118ce565b610ed0565b60405163743be11560e11b8152600490fd5b34610255576000366003190112610255576001546040516001600160a01b039091168152602090f35b908082519081815260208091019281808460051b8301019501936000915b8483106110245750505050505090565b9091929394958480600192601f1985820301865289519061104e6080835190808452830190610a64565b91858060401b03848201511684830152604060ff81830151169083015260608091015115159101529801930193019194939290611014565b906020610a9a928181520190610ff6565b3461025557602080600319360112610255576004356001600160401b038111610255576110c890369060040161025a565b6110d1816111fb565b9260406110e160405195866111d8565b828552601f196110f0846111fb565b019060005b828110611147575050505060005b80821161111857604051806106778682611086565b8061112d610425610f90611142948688611986565b611137828761199b565b52610fb0818661199b565b611103565b839082516111548161118a565b600060608083528185840152818684015282015282828a010152016110f5565b634e487b7160e01b600052604160045260246000fd5b608081019081106001600160401b038211176111a557604052565b611174565b6001600160401b0381116111a557604052565b604081019081106001600160401b038211176111a557604052565b601f909101601f19168101906001600160401b038211908210176111a557604052565b6001600160401b0381116111a55760051b60200190565b929161121d826111fb565b9161122b60405193846111d8565b829481845260208094019160051b810192831161025557905b8282106112515750505050565b81358152908301908301611244565b6001600160401b0381116111a557601f01601f191660200190565b92919261128782611260565b9161129560405193846111d8565b829481845281830111610255578281602093846000960137010152565b9080601f8301121561025557816020610a9a9335910161127b565b359060ff8216820361025557565b8015150361025557565b9291906112f1816111fb565b9160409161130260405194856111d8565b839581855260208095019160051b8101938385116102555781925b85841061132d5750505050505050565b6001600160401b038435818111610255578401916080838803126102555783516113568161118a565b8335928311610255578361136f898c96958796016112b2565b82528381013561137e816105c9565b8483015261138d8682016112cd565b86830152606080910135906113a1826112db565b82015281520193019261131d565b91909160808184031261025557604051906113c98261118a565b90928391906001600160401b0390823582811161025557816113ec9185016112b2565b8452602083013560208501526040830135918211610255578261141860609492611423948694016112b2565b6040860152016112cd565b910152565b9791956114416114499261145195999c9b98369161127b565b9a369161127b565b94369161127b565b936001600160a01b0386161561156d575b61146e61042583611575565b60208101519096906001600160401b0385811691161161155b5760608701516104c7576114ec6114e560ff89946114df6114d96114d160406114b660025460ff9060a01c1690565b9901936114c4855160ff1690565b868b1696879116916124a1565b925160ff1690565b60ff1690565b906124a1565b82336125a6565b9889156115495787848b936115459a51907f4ba393f2ef2da70e2b9689da0c6a653dad20a8811c0564cacfe3dc04b6a7d6eb8561152884611e8f565b9361153b89604051938493339785612068565b0390a451346125e7565b9190565b604051636efa655f60e01b8152600490fd5b604051633527309d60e11b8152600490fd5b339550611462565b6000526003602052604060002090565b90816020910312610255575190565b81835290916001600160fb1b0383116102555760209260051b809284830137010190565b6040513d6000823e3d90fd5b908060209392818452848401376000828201840152601f01601f1916010190565b9035601e1982360301811215610255570160208101919035906001600160401b03821161025557813603831361025557565b90606060ff61166a8261166361163e61163088806115e5565b6080895260808901916115c4565b6020880135602088015261165560408901896115e5565b9088830360408a01526115c4565b95016112cd565b1691015290565b96959491926080946116af946116a19360018060a01b03168a5260208a015260a060408a015260a08901916115c4565b908682036060880152611617565b930152565b909492936001600160a01b0380831694929385156117f25784816116eb8a610d528b988860409d8e5196879560208701998a611671565b51902060005260046020528660002093868554938416036117e4576001600160a01b0319909216909355611724926103fa91369161127b565b9360208501916117376104258451611575565b9182519261174d610441888a0195865190612433565b6117d357606001516117c2576117a06000805160206127238339815191529493926104936117ba9361178360608c015160ff1690565b9060ff8061179760025460ff9060a01c1690565b169216906124a1565b9151925196516117af84611e8f565b965193849384611eaf565b0390a4600190565b855163188e252560e11b8152600490fd5b8651637cb3947160e11b8152600490fd5b505050505050505050600090565b5050505050505050600090565b9060018060a01b0316600052602052604060002090565b908160209103126102555751610a9a816105c9565b9081526001600160401b03909116602082015261ffff9091166040820152608060608201819052610a9a939101916115c4565b81908337600082820152601f01601f19160190565b81604051928392833781016000815203902090565b959493906116af926060946118aa928952608060208a015260808901916115c4565b908682036040880152611617565b634e487b7160e01b600052601160045260246000fd5b60001981146118dd5760010190565b6118b8565b92939060018060a01b03948585169687156117f25761191093610d529260405196879560208701998a611671565b5190206000526004602052604060002054161490565b90611930826111fb565b61193d60405191826111d8565b828152809261194e601f19916111fb565b019060005b82811061195f57505050565b806060602080938501015201611953565b634e487b7160e01b600052603260045260246000fd5b91908110156119965760051b0190565b611970565b80518210156119965760209160051b010190565b90600182811c921680156119df575b60208310146119c957565b634e487b7160e01b600052602260045260246000fd5b91607f16916119be565b906040519182600082546119fc816119af565b90818452602094600191600181169081600014611a6c5750600114611a2d575b505050611a2b925003836111d8565b565b600090815285812095935091905b818310611a54575050611a2b9350820101388080611a1c565b85548884018501529485019487945091830191611a3b565b92505050611a2b94925060ff191682840152151560051b820101388080611a1c565b908160209103126102555751610a9a816112db565b9035601e1982360301811215610255570160208101919035906001600160401b038211610255578160051b3603831361025557565b90918092808252602080920191600593818360051b8701019581956000925b858410611b0957505050505050505090565b9091929394959697601f19808583030189528935603e198436030181121561025557918388929301604091611b5a611b50611b448480611aa3565b86855286850191611594565b9285810190611aa3565b9091858185039101528083528483019285828a1b8201019683956000915b848310611b9d575050505050505050806001929a019801940192919095949395611af7565b809294969850838a929496989a03018852883590607e1988360301821215610255578e8091896001940190611be46080611bd784806115e5565b90918085528401916115c4565b9183810135611bf2816105c9565b868060401b03168483015260ff611c0a8983016112cd565b1688830152606080910135611c1e816112db565b15159101529a019801930190918d97969492959395611b78565b919695939492611c53611c6392608085526080850190610a64565b906020988483038a860152611594565b95818703604083015284518088528188019180808360051b8b01019701926000905b838210611ca4575050505050610a9a9495506060818503910152611ad8565b90919293978380611cc26001938e601f199082030186528c51610a64565b9a019201920190939291611c85565b90604051611cde8161118a565b606060ff60018395611cef816119e9565b855201546001600160401b0381166020850152604081811c83169085015260481c161515910152565b9092916040820191604081528451809352606081019260208096019060005b818110611d5457505050610a9a9394506020818403910152610ff6565b825186529487019491870191600101611d37565b907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b15610255576040916040518091631cfa86f360e31b82526000928391818381611dc3898c60048401611d18565b03925af180156107cb57611e5a575b50908351815103610fbb57815b8085511115611e1e5780611e14611df9611e19938561199b565b51611e04838961199b565b51865260036020528686206122cf565b6118ce565b611ddf565b507f25bb14184ed47336f0e8c5b9b58e65ca31a0cfd0cf8eb80cd59b5005339b4db69250611e559150604051918291339583611d18565b0390a2565b611e63906111aa565b38611dd2565b6001546001600160a01b03163303611e7d57565b6040516347b3ba4760e01b8152600490fd5b611ea790602060405192828480945193849201610a41565b810103902090565b91611ecc90610a9a94928452606060208501526060840190610a64565b916040818403910152610a64565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691823b1561025557600091602483926040519485938492636428e61960e11b845216968760048401525af180156107cb57611f7e575b50600180546001600160a01b0319168217905560405190815233907f8ab4cea230ab04f96aaa9a71fbc4bfa98097c7b9f07e06be33868b500f81002890602090a2565b611f87906111aa565b38611f3b565b6000808052600560205260ff611fb1836000805160206127038339815191526117ff565b5416611ffa578080526005602052611fcc82604083206117ff565b805460ff1916600117905533916001600160a01b0316906000805160206126e38339815191528180a4600190565b905090565b600090808252600560205260ff61201984604085206117ff565b541661206257808252600560205261203483604084206117ff565b805460ff1916600117905533926001600160a01b0316916000805160206126e38339815191529080a4600190565b50905090565b9493926120906060936116af9360018060a01b03168852608060208901526080880190610a64565b908682036040880152610a64565b60008052600560205260ff6120c1336000805160206127038339815191526117ff565b5416156120ca57565b60405163e2517d3f60e01b815233600482015260006024820152604490fd5b80600052600560205260ff6121023360406000206117ff565b54161561210c5750565b6044906040519063e2517d3f60e01b82523360048301526024820152fd5b600090808252600560205260ff61214484604085206117ff565b54161561206257808252600560205261216083604084206117ff565b805460ff1916905533926001600160a01b0316917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9080a4600190565b60019181546000198482161560081b018116841c928251918285146001146121ca57505050505050600090565b846121d8575b505050505090565b602080951060011461223a575060009081528381209183018401928401916001905b6002828686100114612217575050505050505b38808080806121d0565b835181540361222d575b928501926001016121fa565b9195508591829150612221565b939291505001519060ff1916031561220d5750600061220d565b60405160609190911b6001600160601b031916602082015260148152610a9a816111bd565b90601f811161228757505050565b6000916000526020600020906020601f850160051c830194106122c5575b601f0160051c01915b8281106122ba57505050565b8181556001016122ae565b90925082906122a5565b8151805190939291906001600160401b0381116111a5576122fa816122f484546119af565b84612279565b602080601f83116001146123b857506123939261233983606094600194611a2b999a6000926123ad575b50508160011b916000199060031b1c19161790565b81555b6020850151910180546001600160401b0319166001600160401b039092169190911781559261238c612372604083015160ff1690565b855460ff60401b191660409190911b60ff60401b16178555565b0151151590565b815460ff60481b191690151560481b60ff60481b16179055565b015190503880612324565b90601f198316966123ce85600052602060002090565b926000905b89821061241b5750508360019361239396938593606097611a2b9b9c10612402575b505050811b01815561233c565b015160001960f88460031b161c191690553880806123f5565b806001859682949686015181550195019301906123d3565b6001918151918151831460011461244d5750505050600090565b600160208080958185019401019301915b600282858310011461247257505050505090565b8251815103612487575b91840191840161245e565b6000955085915061247c565b604d81116118dd57600a0a90565b9190808211156124d15781039081116118dd576124bd90612493565b908181029181830414901517156118dd5790565b908181106124de57505090565b81039081116118dd576124f090612493565b9081156124fb570490565b634e487b7160e01b600052601260045260246000fd5b306001600160a01b03821603612525575090565b47821161259457819060008080809481945af13d1561258b573d61254881611260565b9061255660405192836111d8565b8152809260203d92013e5b1561256a575090565b604051632e2af28f60e11b81529081906125879060048301610a89565b0390fd5b60609150612561565b6040516342ff79cb60e01b8152600490fd5b903483116125d5576001600160a01b039081169116036125c35790565b60405163976868d560e01b8152600490fd5b604051637df0c20360e01b8152600490fd5b949791939590929660018060a01b0360015416978087039687116118dd5761260e33612254565b926040519a8b998a9889986332a68c8d60e01b8a5260048a0161012090526101248a0161263a91610a64565b9660031997888b82030160248c015261265291610a64565b878a82030160448b015261266591610a64565b606489019490945260ff16608488015260a48701526001600160401b031660c4860152848103830160e486015261269b91610a64565b90838203016101048401526126af91610a64565b03915a94602095f19081156107cb576000916126c9575090565b610a9a915060203d602011610f7457610f6681836111d856fe2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc57349f3521319d500766c25bbf2260c005d16a7164533a3596bd7a2790679911a2646970667358221220544392bd16a2f667751d5027315bc924b715b0f40e59a72a9c55686ea1118a3064736f6c63430008180033a264697066735822122016aa94dc25092cf266bd801a628550400dc1f4776d36597abb2583a4c887af9e64736f6c63430008180033
Deployed Bytecode
0x6080600436101561000f57600080fd5b6000803560e01c63b514681e1461002557600080fd5b346100d857602090816003193601126100d857600435801515036100d857601f1991612855603f8101841685019291908584106001600160401b038511176100c45760409593929195926040528084526100dc868501396040519485938185528051938483870152835b8581106100ae57866040818a601f8a8a85828601015201168101030190f35b828101840151898201830152889650830161008f565b634e487b7160e01b83526041600452602483fd5b80fdfe60a08060405234620000d7576306433b1b60e01b8152602081600481335afa908115620000cb5760009162000053575b506080526040516127789081620000dd8239608051818181611d6b0152611ee40152f35b60203d602011620000c3575b601f8101601f191682016001600160401b03811183821017620000af57602091839160405281010312620000ab5751906001600160a01b0382168203620000a85750386200002f565b80fd5b5080fd5b634e487b7160e01b84526041600452602484fd5b503d6200005f565b6040513d6000823e3d90fd5b600080fdfe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806301ffc9a7146101cb57806304e7aae9146101c6578063081fafa0146101c15780631b7fd4ec146101bc5780631d34dbc3146101b7578063248a9ca3146101b25780632495a599146101ad57806325a760c2146101a85780632ae9c600146101a35780632da04cba1461019e5780632f2ff15d1461019957806336568abe1461019457806359356c5c1461018f578063755067181461018a5780638ec58bb51461018557806391d1485414610180578063a217fddf1461017b578063bd2d87eb14610176578063c0d7865514610171578063cb05ac031461016c578063d3a2ba7614610167578063d547741f14610162578063d90a730e1461015d578063dde63fed14610158578063e8f6e9e214610153578063f887ea401461014e5763f96e52ca0361000e57611097565b610fcd565b610ea8565b610e89565b610e47565b610e08565b610c84565b610b0c565b610ae3565b610a9d565b610a25565b6109e5565b6109bc565b610872565b610856565b61080f565b6107d0565b610718565b6106f7565b6106d3565b6106aa565b61067b565b6105da565b6104fd565b610395565b6102d4565b346102555760203660031901126102555760043563ffffffff60e01b8116809103610255576020906303ca2c9760e01b8114908115610210575b506040519015158152f35b637965db0b60e01b81149150811561022a575b5038610205565b63950a21e160e01b811491508115610244575b5038610223565b6301ffc9a760e01b1490503861023d565b600080fd5b9181601f84011215610255578235916001600160401b038311610255576020808501948460051b01011161025557565b6040600319820112610255576001600160401b039160043583811161025557826102b69160040161025a565b93909392602435918211610255576102d09160040161025a565b9091565b346102555761030d6102ff6103076102eb3661028a565b94916102f893919361209e565b3691611212565b9236916112e5565b90611d68565b602060405160018152f35b600435906001600160a01b038216820361025557565b602435906001600160a01b038216820361025557565b604435906001600160a01b038216820361025557565b9181601f84011215610255578235916001600160401b038311610255576020838186019501011161025557565b908160809103126102555790565b6080366003190112610255576103a9610318565b6001600160401b03604435818111610255576103c990369060040161035a565b909160643590811161025557610402926103ea6103fa923690600401610387565b926103f3611e69565b369161127b565b5036906113af565b906001600160a01b03811680156104eb57602083019161042a6104258451611575565b611cd1565b928351936104456104416040880196875190612433565b1590565b6104d957606001516104c75761049960008051602061272383398151915292610493610475606089015160ff1690565b60ff8061048860025460ff9060a01c1690565b1691166024356124a1565b90612511565b935190519451936104b96104ac83611e8f565b9560405193849384611eaf565b0390a4602060405160018152f35b60405163188e252560e11b8152600490fd5b604051637cb3947160e11b8152600490fd5b6040516351c7b3e160e01b8152600490fd5b346102555760a036600319011261025557610516610318565b61051e61032e565b90610527610344565b6001600160401b0392906064358481116102555761054990369060040161025a565b9290946084359081116102555761056490369060040161025a565b926000546105b757600280546001600160a81b0319166001600160a01b0390941693909317600960a11b179092556001600055610019956105b294610307936102ff9291906102f890611eda565b611f8d565b60405163180cbc2160e21b8152600490fd5b6001600160401b0381160361025557565b60e0366003190112610255576105ee610318565b6001600160401b03906024358281116102555761060f90369060040161035a565b906084359061061d826105c9565b60a4358581116102555761063590369060040161035a565b92909160c4359687116102555761065361066397369060040161035a565b9690956064359260443592611428565b604080519215158352602083019190915290f35b0390f35b346102555760203660031901126102555760043560005260056020526020600160406000200154604051908152f35b34610255576000366003190112610255576002546040516001600160a01b039091168152602090f35b3461025557600036600319011261025557602060ff60025460a01c16604051908152f35b346102555760003660031901126102555760405161010160f01b8152602090f35b3461025557610763602061072b3661028a565b9492909161077560018060a01b03600154169360405197889687958695632d79c1e160e01b8752604060048801526044870191611594565b84810360031901602486015291611594565b03915afa80156107cb576106779160009161079c575b506040519081529081906020820190565b6107be915060203d6020116107c4575b6107b681836111d8565b810190611585565b3861078b565b503d6107ac565b6115b8565b34610255576040366003190112610255576100196004356107ef61032e565b9080600052600560205261080a6001604060002001546120e9565b611fff565b346102555760403660031901126102555761082861032e565b336001600160a01b03821603610844576100199060043561212a565b60405163334bd91960e11b8152600490fd5b3461025557600036600319011261025557602047604051908152f35b34610255576060366003190112610255576001600160401b03600435818111610255576108a390369060040161025a565b90602435838111610255576108bc90369060040161025a565b9190604435858111610255576108d6903690600401610387565b946108df611e69565b6000956020810135875260036020526040872090604081013590601e19813603018212156109535701803592831161094f5760200190823603821361094f576109306104419261093694369161127b565b9061219d565b6104d9576102ff6103079261094c953691611212565b80f35b8780fd5b8880fd5b60a0600319820112610255576004356001600160a01b03811681036102555791602435916001600160401b0391604435838111610255578261099b9160040161035a565b93909392606435918211610255576109b591600401610387565b9060843590565b346102555760206109db6109cf36610957565b949390939291926116b4565b6040519015158152f35b3461025557604036600319011261025557602060ff610a19610a0561032e565b6004356000526005845260406000206117ff565b54166040519015158152f35b3461025557600036600319011261025557602060405160008152f35b60005b838110610a545750506000910152565b8181015183820152602001610a44565b90602091610a7d81518092818552858086019101610a41565b601f01601f1916010190565b906020610a9a928181520190610a64565b90565b3461025557600036600319011261025557610677604051610abd816111bd565b6005815264536f6e696360d81b6020820152604051918291602083526020830190610a64565b346102555760203660031901126102555761030d610aff610318565b610b0761209e565b611eda565b3461025557608036600319011261025557602435600435610b2c826105c9565b60443561ffff81168103610255576001600160401b0360643581811161025557610b5a90369060040161035a565b600154909390610b8090610b74906001600160a01b031681565b6001600160a01b031690565b6040516329d2f02160e21b815260048101879052602097909291908884602481855afa9788156107cb578994600099610c55575b50610bf1610bd46001610bc684611575565b01546001600160401b031690565b986040519788968795869562092e8760e71b87526004870161182b565b03915afa9485156107cb57600095610c36575b505081811690831610610c2e5750905b604080519182526001600160401b03929092166020820152f35b905090610c14565b610c4d929550803d106107c4576107b681836111d8565b923880610c04565b610c76919950853d8711610c7d575b610c6e81836111d8565b810190611816565b9738610bb4565b503d610c64565b346102555760a036600319011261025557610c9d610318565b6001600160401b03906024359060443583811161025557610cc290369060040161035a565b909260643585811161025557610cdc903690600401610387565b90608435958611610255577f89fecad7e82e777b95efd8da30d0290c555adcd7d5fd59c2bbd44752bc09ccab610e0395610de595610dfb610d2360409a369060040161035a565b9096610d2d611e69565b610d8a8460009d8e8a8d610d608b610d5285548a885195869460208601988c8a611671565b03601f1981018352826111d8565b519020815260046020522080546001600160a01b0319166001600160a01b03909216919091179055565b8b54998a92604051602081610dca610dac82610da689806115e5565b9061185e565b83880135815283610dc060408a018a6115e5565b919092019161185e565b60ff610dd8606089016112cd565b1681520301902099611873565b9860405195869560018060a01b03169886611888565b0390a46118ce565b815580f35b3461025557604036600319011261025557610019600435610e2761032e565b90806000526005602052610e426001604060002001546120e9565b61212a565b3461025557600036600319011261025557610677604051610e67816111bd565b60018152605360f81b6020820152604051918291602083526020830190610a64565b346102555760206109db610e9c36610957565b949390939291926118e2565b610eb13661028a565b610ebc92919261209e565b808203610fbb57610ecc82611926565b9260005b808411610f7b57506001549394602094909190610f2190610ef9906001600160a01b0316610b74565b93610f0333612254565b604051633bde546760e11b8152988997889687969360048801611c38565b039134905af180156107cb5761067791600091610f4c575b5060405190151581529081906020820190565b610f6e915060203d602011610f74575b610f6681836111d8565b810190611a8e565b38610f39565b503d610f5c565b80610f9b610f96610f90610fb694888b611986565b35611575565b6119e9565b610fa5828861199b565b52610fb0818761199b565b506118ce565b610ed0565b60405163743be11560e11b8152600490fd5b34610255576000366003190112610255576001546040516001600160a01b039091168152602090f35b908082519081815260208091019281808460051b8301019501936000915b8483106110245750505050505090565b9091929394958480600192601f1985820301865289519061104e6080835190808452830190610a64565b91858060401b03848201511684830152604060ff81830151169083015260608091015115159101529801930193019194939290611014565b906020610a9a928181520190610ff6565b3461025557602080600319360112610255576004356001600160401b038111610255576110c890369060040161025a565b6110d1816111fb565b9260406110e160405195866111d8565b828552601f196110f0846111fb565b019060005b828110611147575050505060005b80821161111857604051806106778682611086565b8061112d610425610f90611142948688611986565b611137828761199b565b52610fb0818661199b565b611103565b839082516111548161118a565b600060608083528185840152818684015282015282828a010152016110f5565b634e487b7160e01b600052604160045260246000fd5b608081019081106001600160401b038211176111a557604052565b611174565b6001600160401b0381116111a557604052565b604081019081106001600160401b038211176111a557604052565b601f909101601f19168101906001600160401b038211908210176111a557604052565b6001600160401b0381116111a55760051b60200190565b929161121d826111fb565b9161122b60405193846111d8565b829481845260208094019160051b810192831161025557905b8282106112515750505050565b81358152908301908301611244565b6001600160401b0381116111a557601f01601f191660200190565b92919261128782611260565b9161129560405193846111d8565b829481845281830111610255578281602093846000960137010152565b9080601f8301121561025557816020610a9a9335910161127b565b359060ff8216820361025557565b8015150361025557565b9291906112f1816111fb565b9160409161130260405194856111d8565b839581855260208095019160051b8101938385116102555781925b85841061132d5750505050505050565b6001600160401b038435818111610255578401916080838803126102555783516113568161118a565b8335928311610255578361136f898c96958796016112b2565b82528381013561137e816105c9565b8483015261138d8682016112cd565b86830152606080910135906113a1826112db565b82015281520193019261131d565b91909160808184031261025557604051906113c98261118a565b90928391906001600160401b0390823582811161025557816113ec9185016112b2565b8452602083013560208501526040830135918211610255578261141860609492611423948694016112b2565b6040860152016112cd565b910152565b9791956114416114499261145195999c9b98369161127b565b9a369161127b565b94369161127b565b936001600160a01b0386161561156d575b61146e61042583611575565b60208101519096906001600160401b0385811691161161155b5760608701516104c7576114ec6114e560ff89946114df6114d96114d160406114b660025460ff9060a01c1690565b9901936114c4855160ff1690565b868b1696879116916124a1565b925160ff1690565b60ff1690565b906124a1565b82336125a6565b9889156115495787848b936115459a51907f4ba393f2ef2da70e2b9689da0c6a653dad20a8811c0564cacfe3dc04b6a7d6eb8561152884611e8f565b9361153b89604051938493339785612068565b0390a451346125e7565b9190565b604051636efa655f60e01b8152600490fd5b604051633527309d60e11b8152600490fd5b339550611462565b6000526003602052604060002090565b90816020910312610255575190565b81835290916001600160fb1b0383116102555760209260051b809284830137010190565b6040513d6000823e3d90fd5b908060209392818452848401376000828201840152601f01601f1916010190565b9035601e1982360301811215610255570160208101919035906001600160401b03821161025557813603831361025557565b90606060ff61166a8261166361163e61163088806115e5565b6080895260808901916115c4565b6020880135602088015261165560408901896115e5565b9088830360408a01526115c4565b95016112cd565b1691015290565b96959491926080946116af946116a19360018060a01b03168a5260208a015260a060408a015260a08901916115c4565b908682036060880152611617565b930152565b909492936001600160a01b0380831694929385156117f25784816116eb8a610d528b988860409d8e5196879560208701998a611671565b51902060005260046020528660002093868554938416036117e4576001600160a01b0319909216909355611724926103fa91369161127b565b9360208501916117376104258451611575565b9182519261174d610441888a0195865190612433565b6117d357606001516117c2576117a06000805160206127238339815191529493926104936117ba9361178360608c015160ff1690565b9060ff8061179760025460ff9060a01c1690565b169216906124a1565b9151925196516117af84611e8f565b965193849384611eaf565b0390a4600190565b855163188e252560e11b8152600490fd5b8651637cb3947160e11b8152600490fd5b505050505050505050600090565b5050505050505050600090565b9060018060a01b0316600052602052604060002090565b908160209103126102555751610a9a816105c9565b9081526001600160401b03909116602082015261ffff9091166040820152608060608201819052610a9a939101916115c4565b81908337600082820152601f01601f19160190565b81604051928392833781016000815203902090565b959493906116af926060946118aa928952608060208a015260808901916115c4565b908682036040880152611617565b634e487b7160e01b600052601160045260246000fd5b60001981146118dd5760010190565b6118b8565b92939060018060a01b03948585169687156117f25761191093610d529260405196879560208701998a611671565b5190206000526004602052604060002054161490565b90611930826111fb565b61193d60405191826111d8565b828152809261194e601f19916111fb565b019060005b82811061195f57505050565b806060602080938501015201611953565b634e487b7160e01b600052603260045260246000fd5b91908110156119965760051b0190565b611970565b80518210156119965760209160051b010190565b90600182811c921680156119df575b60208310146119c957565b634e487b7160e01b600052602260045260246000fd5b91607f16916119be565b906040519182600082546119fc816119af565b90818452602094600191600181169081600014611a6c5750600114611a2d575b505050611a2b925003836111d8565b565b600090815285812095935091905b818310611a54575050611a2b9350820101388080611a1c565b85548884018501529485019487945091830191611a3b565b92505050611a2b94925060ff191682840152151560051b820101388080611a1c565b908160209103126102555751610a9a816112db565b9035601e1982360301811215610255570160208101919035906001600160401b038211610255578160051b3603831361025557565b90918092808252602080920191600593818360051b8701019581956000925b858410611b0957505050505050505090565b9091929394959697601f19808583030189528935603e198436030181121561025557918388929301604091611b5a611b50611b448480611aa3565b86855286850191611594565b9285810190611aa3565b9091858185039101528083528483019285828a1b8201019683956000915b848310611b9d575050505050505050806001929a019801940192919095949395611af7565b809294969850838a929496989a03018852883590607e1988360301821215610255578e8091896001940190611be46080611bd784806115e5565b90918085528401916115c4565b9183810135611bf2816105c9565b868060401b03168483015260ff611c0a8983016112cd565b1688830152606080910135611c1e816112db565b15159101529a019801930190918d97969492959395611b78565b919695939492611c53611c6392608085526080850190610a64565b906020988483038a860152611594565b95818703604083015284518088528188019180808360051b8b01019701926000905b838210611ca4575050505050610a9a9495506060818503910152611ad8565b90919293978380611cc26001938e601f199082030186528c51610a64565b9a019201920190939291611c85565b90604051611cde8161118a565b606060ff60018395611cef816119e9565b855201546001600160401b0381166020850152604081811c83169085015260481c161515910152565b9092916040820191604081528451809352606081019260208096019060005b818110611d5457505050610a9a9394506020818403910152610ff6565b825186529487019491870191600101611d37565b907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690813b15610255576040916040518091631cfa86f360e31b82526000928391818381611dc3898c60048401611d18565b03925af180156107cb57611e5a575b50908351815103610fbb57815b8085511115611e1e5780611e14611df9611e19938561199b565b51611e04838961199b565b51865260036020528686206122cf565b6118ce565b611ddf565b507f25bb14184ed47336f0e8c5b9b58e65ca31a0cfd0cf8eb80cd59b5005339b4db69250611e559150604051918291339583611d18565b0390a2565b611e63906111aa565b38611dd2565b6001546001600160a01b03163303611e7d57565b6040516347b3ba4760e01b8152600490fd5b611ea790602060405192828480945193849201610a41565b810103902090565b91611ecc90610a9a94928452606060208501526060840190610a64565b916040818403910152610a64565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691823b1561025557600091602483926040519485938492636428e61960e11b845216968760048401525af180156107cb57611f7e575b50600180546001600160a01b0319168217905560405190815233907f8ab4cea230ab04f96aaa9a71fbc4bfa98097c7b9f07e06be33868b500f81002890602090a2565b611f87906111aa565b38611f3b565b6000808052600560205260ff611fb1836000805160206127038339815191526117ff565b5416611ffa578080526005602052611fcc82604083206117ff565b805460ff1916600117905533916001600160a01b0316906000805160206126e38339815191528180a4600190565b905090565b600090808252600560205260ff61201984604085206117ff565b541661206257808252600560205261203483604084206117ff565b805460ff1916600117905533926001600160a01b0316916000805160206126e38339815191529080a4600190565b50905090565b9493926120906060936116af9360018060a01b03168852608060208901526080880190610a64565b908682036040880152610a64565b60008052600560205260ff6120c1336000805160206127038339815191526117ff565b5416156120ca57565b60405163e2517d3f60e01b815233600482015260006024820152604490fd5b80600052600560205260ff6121023360406000206117ff565b54161561210c5750565b6044906040519063e2517d3f60e01b82523360048301526024820152fd5b600090808252600560205260ff61214484604085206117ff565b54161561206257808252600560205261216083604084206117ff565b805460ff1916905533926001600160a01b0316917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9080a4600190565b60019181546000198482161560081b018116841c928251918285146001146121ca57505050505050600090565b846121d8575b505050505090565b602080951060011461223a575060009081528381209183018401928401916001905b6002828686100114612217575050505050505b38808080806121d0565b835181540361222d575b928501926001016121fa565b9195508591829150612221565b939291505001519060ff1916031561220d5750600061220d565b60405160609190911b6001600160601b031916602082015260148152610a9a816111bd565b90601f811161228757505050565b6000916000526020600020906020601f850160051c830194106122c5575b601f0160051c01915b8281106122ba57505050565b8181556001016122ae565b90925082906122a5565b8151805190939291906001600160401b0381116111a5576122fa816122f484546119af565b84612279565b602080601f83116001146123b857506123939261233983606094600194611a2b999a6000926123ad575b50508160011b916000199060031b1c19161790565b81555b6020850151910180546001600160401b0319166001600160401b039092169190911781559261238c612372604083015160ff1690565b855460ff60401b191660409190911b60ff60401b16178555565b0151151590565b815460ff60481b191690151560481b60ff60481b16179055565b015190503880612324565b90601f198316966123ce85600052602060002090565b926000905b89821061241b5750508360019361239396938593606097611a2b9b9c10612402575b505050811b01815561233c565b015160001960f88460031b161c191690553880806123f5565b806001859682949686015181550195019301906123d3565b6001918151918151831460011461244d5750505050600090565b600160208080958185019401019301915b600282858310011461247257505050505090565b8251815103612487575b91840191840161245e565b6000955085915061247c565b604d81116118dd57600a0a90565b9190808211156124d15781039081116118dd576124bd90612493565b908181029181830414901517156118dd5790565b908181106124de57505090565b81039081116118dd576124f090612493565b9081156124fb570490565b634e487b7160e01b600052601260045260246000fd5b306001600160a01b03821603612525575090565b47821161259457819060008080809481945af13d1561258b573d61254881611260565b9061255660405192836111d8565b8152809260203d92013e5b1561256a575090565b604051632e2af28f60e11b81529081906125879060048301610a89565b0390fd5b60609150612561565b6040516342ff79cb60e01b8152600490fd5b903483116125d5576001600160a01b039081169116036125c35790565b60405163976868d560e01b8152600490fd5b604051637df0c20360e01b8152600490fd5b949791939590929660018060a01b0360015416978087039687116118dd5761260e33612254565b926040519a8b998a9889986332a68c8d60e01b8a5260048a0161012090526101248a0161263a91610a64565b9660031997888b82030160248c015261265291610a64565b878a82030160448b015261266591610a64565b606489019490945260ff16608488015260a48701526001600160401b031660c4860152848103830160e486015261269b91610a64565b90838203016101048401526126af91610a64565b03915a94602095f19081156107cb576000916126c9575090565b610a9a915060203d602011610f7457610f6681836111d856fe2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d05b8ccbb9d4d8fb16ea74ce3c29a41f1b461fbdaff4714a0d9a8eb05499746bc57349f3521319d500766c25bbf2260c005d16a7164533a3596bd7a2790679911a2646970667358221220544392bd16a2f667751d5027315bc924b715b0f40e59a72a9c55686ea1118a3064736f6c63430008180033a264697066735822122016aa94dc25092cf266bd801a628550400dc1f4776d36597abb2583a4c887af9e64736f6c63430008180033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.