Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers. Name tag integration is not available in advanced view.
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | ||||
---|---|---|---|---|---|---|---|
20634672 | 59 days ago | 0 ETH | |||||
20634672 | 59 days ago | 0 ETH | |||||
20634543 | 59 days ago | 0 ETH | |||||
20634543 | 59 days ago | 0 ETH | |||||
20634543 | 59 days ago | 0 ETH | |||||
20634079 | 59 days ago | 0 ETH | |||||
20634079 | 59 days ago | 0 ETH | |||||
20633947 | 59 days ago | 0 ETH | |||||
20633947 | 59 days ago | 0 ETH | |||||
20633947 | 59 days ago | 0 ETH | |||||
20633484 | 60 days ago | 0 ETH | |||||
20633484 | 60 days ago | 0 ETH | |||||
20633353 | 60 days ago | 0 ETH | |||||
20633353 | 60 days ago | 0 ETH | |||||
20633353 | 60 days ago | 0 ETH | |||||
20632886 | 60 days ago | 0 ETH | |||||
20632886 | 60 days ago | 0 ETH | |||||
20632754 | 60 days ago | 0 ETH | |||||
20632754 | 60 days ago | 0 ETH | |||||
20632754 | 60 days ago | 0 ETH | |||||
20632291 | 60 days ago | 0 ETH | |||||
20632291 | 60 days ago | 0 ETH | |||||
20632163 | 60 days ago | 0 ETH | |||||
20632163 | 60 days ago | 0 ETH | |||||
20632163 | 60 days ago | 0 ETH |
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0x5c214986...e1548bb2A The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
OptimismHubConnector
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.17; import {IRootManager} from "../../interfaces/IRootManager.sol"; import {OptimismAmb} from "../../interfaces/ambs/optimism/OptimismAmb.sol"; import {IOptimismPortal} from "../../interfaces/ambs/optimism/IOptimismPortal.sol"; import {HubConnector} from "../HubConnector.sol"; import {Connector} from "../Connector.sol"; import {Types} from "./lib/Types.sol"; import {BaseOptimism} from "./BaseOptimism.sol"; contract OptimismHubConnector is HubConnector, BaseOptimism { // ============ Storage ============ IOptimismPortal public immutable OPTIMISM_PORTAL; // NOTE: This is needed because we need to track the roots we've // already sent across chains. When sending an optimism message, we send calldata // for Connector.processMessage. At any point these messages could be processed // before the timeout using `processFromRoot` or after the timeout using `process` // we track the roots sent here to ensure we process each root once mapping(bytes32 => bool) public processed; // ============ Constructor ============ constructor( uint32 _domain, uint32 _mirrorDomain, address _amb, address _rootManager, address _mirrorConnector, address _optimismPortal, uint256 _gasCap ) HubConnector(_domain, _mirrorDomain, _amb, _rootManager, _mirrorConnector) BaseOptimism(_gasCap) { OPTIMISM_PORTAL = IOptimismPortal(_optimismPortal); } // ============ Override Fns ============ function _verifySender(address _expected) internal view override returns (bool) { return _verifySender(AMB, _expected); } /** * @dev Sends `aggregateRoot` to messaging on l2 */ function _sendMessage(bytes memory _data, bytes memory) internal override { // Should always be dispatching the aggregate root require(_data.length == 32, "!length"); // Get the calldata bytes memory _calldata = abi.encodeWithSelector(Connector.processMessage.selector, _data); // Dispatch message OptimismAmb(AMB).sendMessage(mirrorConnector, _calldata, uint32(gasCap)); } /** * @dev modified from: OptimismPortal contract * https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol#L208 */ function processMessageFromRoot( Types.WithdrawalTransaction memory _tx, uint256 _l2OutputIndex, Types.OutputRootProof calldata _outputRootProof, bytes[] calldata _withdrawalProof ) external { OPTIMISM_PORTAL.proveWithdrawalTransaction(_tx, _l2OutputIndex, _outputRootProof, _withdrawalProof); // Extract the argument from the data // uint256 _nonce, // address _sender, // address _target, // uint256 _value, // uint256 _minGasLimit, // bytes memory _message (, address _sender, address _target, , , bytes memory _message) = decodeCrossDomainMessageV1(_tx.data); // ensure the l2 connector sent the message require(_sender == mirrorConnector, "!mirror connector"); require(_target == address(this), "!target"); // get the data // _message = abi.encodePacked(bytes32(root)) require(_message.length == 32, "!length"); bytes32 root = bytes32(_message); require(!processed[root], "processed"); // set root to processed processed[root] = true; // update the root on the root manager IRootManager(ROOT_MANAGER).aggregate(MIRROR_DOMAIN, root); emit MessageProcessed(_message, msg.sender); } /** * @notice Encodes a cross domain message based on the V1 (current) encoding. * * @param _encodedData cross domain message. * @return _nonce Message nonce. * @return _sender Address of the sender of the message. * @return _target Address of the target of the message. * @return _value ETH value to send to the target. * @return _gasLimit Gas limit to use for the message. * @return _data Data to send with the message. * */ function decodeCrossDomainMessageV1( bytes memory _encodedData ) internal pure returns (uint256 _nonce, address _sender, address _target, uint256 _value, uint256 _gasLimit, bytes memory _data) { bytes4 selector = bytes4(0); assembly { selector := mload(add(_encodedData, 32)) } // Make sure the function selector matches require(selector == bytes4(keccak256("relayMessage(uint256,address,address,uint256,uint256,bytes)")), "!selector"); uint256 start = 4; uint256 len = _encodedData.length - start; bytes memory sliced = new bytes(len); assembly { // Get the memory pointer to the start of the original data let src := add(_encodedData, add(32, start)) // Get the memory pointer to the start of the new sliced data let dest := add(sliced, 32) // Copy the data from src to dest for { let i := 0 } lt(i, len) { i := add(i, 32) } { mstore(add(dest, i), mload(add(src, i))) } } // Extract the argument from the data (_nonce, _sender, _target, _value, _gasLimit, _data) = abi.decode( sliced, (uint256, address, address, uint256, uint256, bytes) ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.17; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {ProposedOwnable} from "../../shared/ProposedOwnable.sol"; import {IConnector} from "../interfaces/IConnector.sol"; /** * @title Connector * @author Connext Labs, Inc. * @notice This contract has the messaging interface functions used by all connectors. * * @dev This contract stores information about mirror connectors, but can be used as a * base for contracts that do not have a mirror (i.e. the connector handling messaging on * mainnet). In this case, the `mirrorConnector` and `MIRROR_DOMAIN` * will be empty * * @dev If ownership is renounced, this contract will be unable to update its `mirrorConnector` * or `mirrorGas` */ abstract contract Connector is ProposedOwnable, IConnector { // ========== Custom Errors =========== error Connector__processMessage_notUsed(); // ============ Events ============ event NewConnector( uint32 indexed domain, uint32 indexed mirrorDomain, address amb, address rootManager, address mirrorConnector ); event MirrorConnectorUpdated(address previous, address current); /** * @notice Emitted when funds are withdrawn by the admin * @dev See comments in `withdrawFunds` * @param to The recipient of the funds * @param amount The amount withdrawn */ event FundsWithdrawn(address indexed to, uint256 amount); // ============ Public Storage ============ /** * @notice The domain of this Messaging (i.e. Connector) contract. */ uint32 public immutable DOMAIN; /** * @notice Address of the AMB on this domain. */ address public immutable AMB; /** * @notice RootManager contract address. */ address public immutable ROOT_MANAGER; /** * @notice The domain of the corresponding messaging (i.e. Connector) contract. */ uint32 public immutable MIRROR_DOMAIN; /** * @notice Connector on L2 for L1 connectors, and vice versa. */ address public mirrorConnector; // ============ Modifiers ============ /** * @notice Errors if the msg.sender is not the registered AMB */ modifier onlyAMB() { require(msg.sender == AMB, "!AMB"); _; } /** * @notice Errors if the msg.sender is not the registered ROOT_MANAGER */ modifier onlyRootManager() { // NOTE: RootManager will be zero address for spoke connectors. // Only root manager can dispatch a message to spokes/L2s via the hub connector. require(msg.sender == ROOT_MANAGER, "!rootManager"); _; } // ============ Constructor ============ /** * @notice Creates a new HubConnector instance * @dev The connectors are deployed such that there is one on each side of an AMB (i.e. * for optimism, there is one connector on optimism and one connector on mainnet) * @param _domain The domain this connector lives on * @param _mirrorDomain The spoke domain * @param _amb The address of the amb on the domain this connector lives on * @param _rootManager The address of the RootManager on mainnet * @param _mirrorConnector The address of the spoke connector */ constructor( uint32 _domain, uint32 _mirrorDomain, address _amb, address _rootManager, address _mirrorConnector ) ProposedOwnable() { // set the owner _setOwner(msg.sender); // sanity checks on values require(_domain != 0, "empty domain"); require(_rootManager != address(0), "empty rootManager"); // see note at top of contract on why the mirror values are not sanity checked // set immutables DOMAIN = _domain; AMB = _amb; ROOT_MANAGER = _rootManager; MIRROR_DOMAIN = _mirrorDomain; // set mutables if defined if (_mirrorConnector != address(0)) { _setMirrorConnector(_mirrorConnector); } emit NewConnector(_domain, _mirrorDomain, _amb, _rootManager, _mirrorConnector); } // ============ Receivable ============ /** * @notice Connectors may need to receive native asset to handle fees when sending a * message */ receive() external payable {} // ============ Admin Functions ============ /** * @notice Sets the address of the l2Connector for this domain */ function setMirrorConnector(address _mirrorConnector) public onlyOwner { _setMirrorConnector(_mirrorConnector); } /** * @notice This function should be callable by owner, and send funds trapped on * a connector to the provided recipient. * @dev Withdraws the entire balance of the contract. * * @param _to The recipient of the funds withdrawn */ function withdrawFunds(address _to) public onlyOwner { uint256 amount = address(this).balance; Address.sendValue(payable(_to), amount); emit FundsWithdrawn(_to, amount); } // ============ Public Functions ============ /** * @notice Processes a message received by an AMB * @dev This is called by AMBs to process messages originating from mirror connector */ function processMessage(bytes memory _data) external virtual onlyAMB { _processMessage(_data); emit MessageProcessed(_data, msg.sender); } /** * @notice Checks the cross domain sender for a given address */ function verifySender(address _expected) external returns (bool) { return _verifySender(_expected); } // ============ Virtual Functions ============ /** * @notice This function is used by the Connext contract on the l2 domain to send a message to the * l1 domain (i.e. called by Connext on optimism to send a message to mainnet with roots) * @param _data The contents of the message * @param _encodedData Data used to send the message; specific to connector */ function _sendMessage(bytes memory _data, bytes memory _encodedData) internal virtual; /** * @notice This function is used by the AMBs to handle incoming messages. Should store the latest * root generated on the l2 domain. */ function _processMessage( bytes memory /* _data */ ) internal virtual { // By default, reverts. This is to ensure the call path is not used unless this function is // overridden by the inheriting class revert Connector__processMessage_notUsed(); } /** * @notice Verify that the msg.sender is the correct AMB contract, and that the message's origin sender * is the expected address. * @dev Should be overridden by the implementing Connector contract. */ function _verifySender(address _expected) internal virtual returns (bool); // ============ Private Functions ============ function _setMirrorConnector(address _mirrorConnector) internal virtual { emit MirrorConnectorUpdated(mirrorConnector, _mirrorConnector); mirrorConnector = _mirrorConnector; } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.17; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {ProposedOwnable} from "../../shared/ProposedOwnable.sol"; /** * @notice This contract is used to enforce upper bounds on the amount of fees * forwarded along. This caps the amount relayers could charge for the service */ abstract contract GasCap is ProposedOwnable { // ============ Storage ============ /** * @notice The gnosis amb requires destination gas to be specified on the origin. * The gas used will be passed in by the relayer to allow for real-time estimates, * but will be capped at the admin-set cap. */ uint256 public gasCap; // ============ Events ============ /** * @notice Emitted when admin updates the gas cap * @param _previous The starting value * @param _updated The final value */ event GasCapUpdated(uint256 _previous, uint256 _updated); // ============ Constructor ============ constructor(uint256 _gasCap) { _setGasCap(_gasCap); } // ============ Admin Fns ============ function setGasCap(uint256 _gasCap) public onlyOwner { _setGasCap(_gasCap); } // ============ Internal Fns ============ /** * @notice Used (by admin) to update the gas cap * @param _gasCap The new value */ function _setGasCap(uint256 _gasCap) internal { emit GasCapUpdated(gasCap, _gasCap); gasCap = _gasCap; } /** * @notice Used to get the gas to use. Will be the original value IFF it * is less than the cap * @param _gas The proposed gas value */ function _getGas(uint256 _gas) internal view returns (uint256) { if (_gas > gasCap) { _gas = gasCap; } return _gas; } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.17; import {Connector} from "./Connector.sol"; /** * @title HubConnector * @author Connext Labs, Inc. * @notice This contract implements the messaging functions needed on the hub-side of a given AMB. * The HubConnector has a limited set of functionality compared to the SpokeConnector, namely that * it contains no logic to store or prove messages. * * @dev This contract should be deployed on the hub-side of an AMB (i.e. on L1), and contracts * which extend this should implement the virtual functions defined in the BaseConnector class */ abstract contract HubConnector is Connector { /** * @notice Creates a new HubConnector instance * @dev The connectors are deployed such that there is one on each side of an AMB (i.e. * for optimism, there is one connector on optimism and one connector on mainnet) * @param _domain The domain this connector lives on * @param _mirrorDomain The spoke domain * @param _amb The address of the amb on the domain this connector lives on * @param _rootManager The address of the RootManager on mainnet * @param _mirrorConnector The address of the spoke connector */ constructor( uint32 _domain, uint32 _mirrorDomain, address _amb, address _rootManager, address _mirrorConnector ) Connector(_domain, _mirrorDomain, _amb, _rootManager, _mirrorConnector) {} // ============ Public fns ============ /** * @notice Sends a message over the amb * @dev This is called by the root manager *only* on mainnet to propagate the aggregate root */ function sendMessage(bytes memory _data, bytes memory _encodedData) external payable onlyRootManager { _sendMessage(_data, _encodedData); emit MessageSent(_data, _encodedData, msg.sender); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.17; import {OptimismAmb} from "../../interfaces/ambs/optimism/OptimismAmb.sol"; import {GasCap} from "../GasCap.sol"; abstract contract BaseOptimism is GasCap { // ============ Constructor ============ constructor(uint256 _gasCap) GasCap(_gasCap) {} // ============ Override Fns ============ function _verifySender(address _amb, address _expected) internal view returns (bool) { require(msg.sender == _amb, "!bridge"); return OptimismAmb(_amb).xDomainMessageSender() == _expected; } /** * @notice Using Optimism AMB, the gas is provided to `sendMessage` as an encoded uint */ function _getGasFromEncoded(bytes memory _encodedData) internal view returns (uint256 _gas) { // Should include gas info in specialized calldata require(_encodedData.length == 32, "!data length"); // Get the gas, if it is more than the cap use the cap _gas = _getGas(abi.decode(_encodedData, (uint256))); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /** * @title Types * @notice Contains various types used throughout the Optimism contract system. */ library Types { /** * @notice OutputProposal represents a commitment to the L2 state. The timestamp is the L1 * timestamp that the output root is posted. This timestamp is used to verify that the * finalization period has passed since the output root was submitted. * * @custom:field outputRoot Hash of the L2 output. * @custom:field timestamp Timestamp of the L1 block that the output root was submitted in. * @custom:field l2BlockNumber L2 block number that the output corresponds to. */ struct OutputProposal { bytes32 outputRoot; uint128 timestamp; uint128 l2BlockNumber; } /** * @notice Struct representing the elements that are hashed together to generate an output root * which itself represents a snapshot of the L2 state. * * @custom:field version Version of the output root. * @custom:field stateRoot Root of the state trie at the block of this output. * @custom:field messagePasserStorageRoot Root of the message passer storage trie. * @custom:field latestBlockhash Hash of the block this output was generated from. */ struct OutputRootProof { bytes32 version; bytes32 stateRoot; bytes32 messagePasserStorageRoot; bytes32 latestBlockhash; } /** * @notice Struct representing a deposit transaction (L1 => L2 transaction) created by an end * user (as opposed to a system deposit transaction generated by the system). * * @custom:field from Address of the sender of the transaction. * @custom:field to Address of the recipient of the transaction. * @custom:field isCreation True if the transaction is a contract creation. * @custom:field value Value to send to the recipient. * @custom:field mint Amount of ETH to mint. * @custom:field gasLimit Gas limit of the transaction. * @custom:field data Data of the transaction. * @custom:field l1BlockHash Hash of the block the transaction was submitted in. * @custom:field logIndex Index of the log in the block the transaction was submitted in. */ struct UserDepositTransaction { address from; address to; bool isCreation; uint256 value; uint256 mint; uint64 gasLimit; bytes data; bytes32 l1BlockHash; uint256 logIndex; } /** * @notice Struct representing a withdrawal transaction. * * @custom:field nonce Nonce of the withdrawal transaction * @custom:field sender Address of the sender of the transaction. * @custom:field target Address of the recipient of the transaction. * @custom:field value Value to send to the recipient. * @custom:field gasLimit Gas limit of the transaction. * @custom:field data Data of the transaction. */ struct WithdrawalTransaction { uint256 nonce; address sender; address target; uint256 value; uint256 gasLimit; bytes data; } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.17; import {IProposedOwnable} from "../../shared/interfaces/IProposedOwnable.sol"; /** * @notice This interface is what the Connext contract will send and receive messages through. * The messaging layer should conform to this interface, and should be interchangeable (i.e. * could be Nomad or a generic AMB under the hood). * * @dev This uses the nomad format to ensure nomad can be added in as it comes back online. * * Flow from transfer from polygon to optimism: * 1. User calls `xcall` with destination specified * 2. This will swap in to the bridge assets * 3. The swapped assets will get burned * 4. The Connext contract will call `dispatch` on the messaging contract to add the transfer * to the root * 5. [At some time interval] Relayers call `send` to send the current root from polygon to * mainnet. This is done on all "spoke" domains. * 6. [At some time interval] Relayers call `propagate` [better name] on mainnet, this generates a new merkle * root from all of the AMBs * - This function must be able to read root data from all AMBs and aggregate them into a single merkle * tree root * - Will send the mixed root from all chains back through the respective AMBs to all other chains * 7. AMB will call `update` to update the latest root on the messaging contract on spoke domains * 8. [At any point] Relayers can call `proveAndProcess` to prove inclusion of dispatched message, and call * process on the `Connext` contract * 9. Takes minted bridge tokens and credits the LP * * AMB requirements: * - Access `msg.sender` both from mainnet -> spoke and vice versa * - Ability to read *our root* from the AMB * * AMBs: * - PoS bridge from polygon * - arbitrum bridge * - optimism bridge * - gnosis chain * - bsc (use multichain for messaging) */ interface IConnector is IProposedOwnable { // ============ Events ============ /** * @notice Emitted whenever a message is successfully sent over an AMB * @param data The contents of the message * @param encodedData Data used to send the message; specific to connector * @param caller Who called the function (sent the message) */ event MessageSent(bytes data, bytes encodedData, address caller); /** * @notice Emitted whenever a message is successfully received over an AMB * @param data The contents of the message * @param caller Who called the function */ event MessageProcessed(bytes data, address caller); // ============ Public fns ============ function processMessage(bytes memory _data) external; function verifySender(address _expected) external returns (bool); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.17; interface IRootManager { /** * @notice This is called by relayers to generate + send the mixed root from mainnet via AMB to * spoke domains. * @dev This must read information for the root from the registered AMBs. */ function propagate( address[] calldata _connectors, uint256[] calldata _fees, bytes[] memory _encodedData ) external payable; /** * @notice Called by the connectors for various domains on the hub to aggregate their latest * inbound root. * @dev This must read information for the root from the registered AMBs */ function aggregate(uint32 _domain, bytes32 _outbound) external; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {Types} from "../../../connectors/optimism/lib/Types.sol"; /** * @dev An informal interface. Technically not an interface but a contract, since we need to reference * a mapping when interfacing with the real thing (and mappings cannot be declared in interfaces in solidity). */ interface IOptimismPortal { /** * @notice Proves a withdrawal transaction. * * @param _tx Withdrawal transaction to finalize. * @param _l2OutputIndex L2 output index to prove against. * @param _outputRootProof Inclusion proof of the L2ToL1MessagePasser contract's storage root. * @param _withdrawalProof Inclusion proof of the withdrawal in L2ToL1MessagePasser contract. */ function proveWithdrawalTransaction( Types.WithdrawalTransaction memory _tx, uint256 _l2OutputIndex, Types.OutputRootProof calldata _outputRootProof, bytes[] calldata _withdrawalProof ) external; }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity 0.8.17; /** * @dev The optimism bridge shares both of these functions, but it is important * to note that when going from L2 -> L1, the message cannot be processed by the * AMB until the challenge period elapses. * * HOWEVER, before the challenge elapses, you can read the state of the L2 as it is * placed on mainnet. By processing data from the L2 state, we are able to "circumvent" * this delay to a reasonable degree. * * This means that for messages going L1 -> L2, you can call "processMessage" and expect * the call to be executed to pass up the aggregate root. When going from L2 -> L1, you * must read the root from the L2 state * * L2 messenger: https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L2/messaging/L2CrossDomainMessenger.sol * L1 messenger: https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts/contracts/L1/messaging/L1CrossDomainMessenger.sol */ interface OptimismAmb { function sendMessage( address _target, bytes memory _message, uint32 _gasLimit ) external; function xDomainMessageSender() external view returns (address); }
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.17; import {IProposedOwnable} from "./interfaces/IProposedOwnable.sol"; /** * @title ProposedOwnable * @notice Contract module which provides a basic access control mechanism, * where there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed via a two step process: * 1. Call `proposeOwner` * 2. Wait out the delay period * 3. Call `acceptOwner` * * @dev This module is used through inheritance. It will make available the * modifier `onlyOwner`, which can be applied to your functions to restrict * their use to the owner. * * @dev The majority of this code was taken from the openzeppelin Ownable * contract * */ abstract contract ProposedOwnable is IProposedOwnable { // ========== Custom Errors =========== error ProposedOwnable__onlyOwner_notOwner(); error ProposedOwnable__onlyProposed_notProposedOwner(); error ProposedOwnable__ownershipDelayElapsed_delayNotElapsed(); error ProposedOwnable__proposeNewOwner_invalidProposal(); error ProposedOwnable__proposeNewOwner_noOwnershipChange(); error ProposedOwnable__renounceOwnership_noProposal(); error ProposedOwnable__renounceOwnership_invalidProposal(); // ============ Properties ============ address private _owner; address private _proposed; uint256 private _proposedOwnershipTimestamp; uint256 private constant _delay = 7 days; // ======== Getters ========= /** * @notice Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @notice Returns the address of the proposed owner. */ function proposed() public view virtual returns (address) { return _proposed; } /** * @notice Returns the address of the proposed owner. */ function proposedTimestamp() public view virtual returns (uint256) { return _proposedOwnershipTimestamp; } /** * @notice Returns the delay period before a new owner can be accepted. */ function delay() public view virtual returns (uint256) { return _delay; } /** * @notice Throws if called by any account other than the owner. */ modifier onlyOwner() { if (_owner != msg.sender) revert ProposedOwnable__onlyOwner_notOwner(); _; } /** * @notice Throws if called by any account other than the proposed owner. */ modifier onlyProposed() { if (_proposed != msg.sender) revert ProposedOwnable__onlyProposed_notProposedOwner(); _; } /** * @notice Throws if the ownership delay has not elapsed */ modifier ownershipDelayElapsed() { // Ensure delay has elapsed if ((block.timestamp - _proposedOwnershipTimestamp) <= _delay) revert ProposedOwnable__ownershipDelayElapsed_delayNotElapsed(); _; } /** * @notice Indicates if the ownership has been renounced() by * checking if current owner is address(0) */ function renounced() public view returns (bool) { return _owner == address(0); } // ======== External ========= /** * @notice Sets the timestamp for an owner to be proposed, and sets the * newly proposed owner as step 1 in a 2-step process */ function proposeNewOwner(address newlyProposed) public virtual onlyOwner { // Contract as source of truth if (_proposed == newlyProposed && _proposedOwnershipTimestamp != 0) revert ProposedOwnable__proposeNewOwner_invalidProposal(); // Sanity check: reasonable proposal if (_owner == newlyProposed) revert ProposedOwnable__proposeNewOwner_noOwnershipChange(); _setProposed(newlyProposed); } /** * @notice Renounces ownership of the contract after a delay */ function renounceOwnership() public virtual onlyOwner ownershipDelayElapsed { // Ensure there has been a proposal cycle started if (_proposedOwnershipTimestamp == 0) revert ProposedOwnable__renounceOwnership_noProposal(); // Require proposed is set to 0 if (_proposed != address(0)) revert ProposedOwnable__renounceOwnership_invalidProposal(); // Emit event, set new owner, reset timestamp _setOwner(address(0)); } /** * @notice Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function acceptProposedOwner() public virtual onlyProposed ownershipDelayElapsed { // NOTE: no need to check if _owner == _proposed, because the _proposed // is 0-d out and this check is implicitly enforced by modifier // NOTE: no need to check if _proposedOwnershipTimestamp > 0 because // the only time this would happen is if the _proposed was never // set (will fail from modifier) or if the owner == _proposed (checked // above) // Emit event, set new owner, reset timestamp _setOwner(_proposed); } // ======== Internal ========= function _setOwner(address newOwner) internal { emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; delete _proposedOwnershipTimestamp; delete _proposed; } function _setProposed(address newlyProposed) private { _proposedOwnershipTimestamp = block.timestamp; _proposed = newlyProposed; emit OwnershipProposed(newlyProposed); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; /** * @title IProposedOwnable * @notice Defines a minimal interface for ownership with a two step proposal and acceptance * process */ interface IProposedOwnable { /** * @dev This emits when change in ownership of a contract is proposed. */ event OwnershipProposed(address indexed proposedOwner); /** * @dev This emits when ownership of a contract changes. */ event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @notice Get the address of the owner * @return owner_ The address of the owner. */ function owner() external view returns (address owner_); /** * @notice Get the address of the proposed owner * @return proposed_ The address of the proposed. */ function proposed() external view returns (address proposed_); /** * @notice Set the address of the proposed owner of the contract * @param newlyProposed The proposed new owner of the contract */ function proposeNewOwner(address newlyProposed) external; /** * @notice Set the address of the proposed owner of the contract */ function acceptProposedOwner() external; }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint32","name":"_domain","type":"uint32"},{"internalType":"uint32","name":"_mirrorDomain","type":"uint32"},{"internalType":"address","name":"_amb","type":"address"},{"internalType":"address","name":"_rootManager","type":"address"},{"internalType":"address","name":"_mirrorConnector","type":"address"},{"internalType":"address","name":"_optimismPortal","type":"address"},{"internalType":"uint256","name":"_gasCap","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Connector__processMessage_notUsed","type":"error"},{"inputs":[],"name":"ProposedOwnable__onlyOwner_notOwner","type":"error"},{"inputs":[],"name":"ProposedOwnable__onlyProposed_notProposedOwner","type":"error"},{"inputs":[],"name":"ProposedOwnable__ownershipDelayElapsed_delayNotElapsed","type":"error"},{"inputs":[],"name":"ProposedOwnable__proposeNewOwner_invalidProposal","type":"error"},{"inputs":[],"name":"ProposedOwnable__proposeNewOwner_noOwnershipChange","type":"error"},{"inputs":[],"name":"ProposedOwnable__renounceOwnership_invalidProposal","type":"error"},{"inputs":[],"name":"ProposedOwnable__renounceOwnership_noProposal","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_previous","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_updated","type":"uint256"}],"name":"GasCapUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"MessageProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"encodedData","type":"bytes"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"MessageSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previous","type":"address"},{"indexed":false,"internalType":"address","name":"current","type":"address"}],"name":"MirrorConnectorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"domain","type":"uint32"},{"indexed":true,"internalType":"uint32","name":"mirrorDomain","type":"uint32"},{"indexed":false,"internalType":"address","name":"amb","type":"address"},{"indexed":false,"internalType":"address","name":"rootManager","type":"address"},{"indexed":false,"internalType":"address","name":"mirrorConnector","type":"address"}],"name":"NewConnector","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"proposedOwner","type":"address"}],"name":"OwnershipProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"AMB","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIRROR_DOMAIN","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPTIMISM_PORTAL","outputs":[{"internalType":"contract IOptimismPortal","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROOT_MANAGER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptProposedOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"delay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mirrorConnector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"processMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct Types.WithdrawalTransaction","name":"_tx","type":"tuple"},{"internalType":"uint256","name":"_l2OutputIndex","type":"uint256"},{"components":[{"internalType":"bytes32","name":"version","type":"bytes32"},{"internalType":"bytes32","name":"stateRoot","type":"bytes32"},{"internalType":"bytes32","name":"messagePasserStorageRoot","type":"bytes32"},{"internalType":"bytes32","name":"latestBlockhash","type":"bytes32"}],"internalType":"struct Types.OutputRootProof","name":"_outputRootProof","type":"tuple"},{"internalType":"bytes[]","name":"_withdrawalProof","type":"bytes[]"}],"name":"processMessageFromRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"processed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newlyProposed","type":"address"}],"name":"proposeNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proposed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposedTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounced","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"bytes","name":"_encodedData","type":"bytes"}],"name":"sendMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_gasCap","type":"uint256"}],"name":"setGasCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_mirrorConnector","type":"address"}],"name":"setMirrorConnector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_expected","type":"address"}],"name":"verifySender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Deployed Bytecode
0x6080604052600436106101445760003560e01c8063715018a6116100b6578063c5b350df1161006f578063c5b350df146103e9578063cc394283146103fe578063d1851c921461041e578063d232c2201461043c578063d69f9d611461045b578063db1b76591461048f57600080fd5b8063715018a6146103025780637850b0201461031757806385734ee1146103375780638da5cb5b1461036b578063b1f8100d14610389578063c1f0808a146103a957600080fd5b806352a9674b1161010857806352a9674b1461020c5780635bd11efc146102405780635f61e3ec1461026057806368742da6146102ac5780636a42b8f8146102cc5780637049138f146102e257600080fd5b8063047dbeb81461015057806314168416146101795780633cf52ffb146101c257806348e6fa23146101d75780634ff746f6146101ec57600080fd5b3661014b57005b600080fd5b34801561015c57600080fd5b5061016660045481565b6040519081526020015b60405180910390f35b34801561018557600080fd5b506101ad7f000000000000000000000000000000000000000000000000000000006d6f646581565b60405163ffffffff9091168152602001610170565b3480156101ce57600080fd5b50600254610166565b6101ea6101e5366004611232565b6104af565b005b3480156101f857600080fd5b506101ea610207366004611296565b610564565b34801561021857600080fd5b506101ad7f000000000000000000000000000000000000000000000000000000000065746881565b34801561024c57600080fd5b506101ea61025b3660046112e8565b61060a565b34801561026c57600080fd5b506102947f000000000000000000000000523ab7424ad126809b1d7a134eb6e0ee414c9b3a81565b6040516001600160a01b039091168152602001610170565b3480156102b857600080fd5b506101ea6102c73660046112e8565b610641565b3480156102d857600080fd5b5062093a80610166565b3480156102ee57600080fd5b506101ea6102fd366004611370565b6106be565b34801561030e57600080fd5b506101ea61098d565b34801561032357600080fd5b506101ea61033236600461146a565b610a41565b34801561034357600080fd5b506102947f0000000000000000000000008b34b14c7c7123459cf3076b8cb929be097d0c0781565b34801561037757600080fd5b506000546001600160a01b0316610294565b34801561039557600080fd5b506101ea6103a43660046112e8565b610a75565b3480156103b557600080fd5b506103d96103c436600461146a565b60056020526000908152604090205460ff1681565b6040519015158152602001610170565b3480156103f557600080fd5b506101ea610b13565b34801561040a57600080fd5b50600354610294906001600160a01b031681565b34801561042a57600080fd5b506001546001600160a01b0316610294565b34801561044857600080fd5b506000546001600160a01b0316156103d9565b34801561046757600080fd5b506102947f00000000000000000000000095bdca6c8edeb69c98bd5bd17660bacef1298a6f81565b34801561049b57600080fd5b506103d96104aa3660046112e8565b610b83565b336001600160a01b037f000000000000000000000000523ab7424ad126809b1d7a134eb6e0ee414c9b3a161461051b5760405162461bcd60e51b815260206004820152600c60248201526b10b937b7ba26b0b730b3b2b960a11b60448201526064015b60405180910390fd5b6105258282610b94565b7fdcaa37a042a0087de79018c629bbd29cee82ca80bd9be394e1696bf9e9355077828233604051610558939291906114d3565b60405180910390a15050565b336001600160a01b037f00000000000000000000000095bdca6c8edeb69c98bd5bd17660bacef1298a6f16146105c55760405162461bcd60e51b81526004016105129060208082526004908201526310a0a6a160e11b604082015260600190565b6105ce81610cab565b7fb3abc57bfeebd2cac918901db582f71972a8e628bccf19f5ae3e3482b98a5ced81336040516105ff929190611511565b60405180910390a150565b6000546001600160a01b03163314610635576040516311a8a1bb60e31b815260040160405180910390fd5b61063e81610cc4565b50565b6000546001600160a01b0316331461066c576040516311a8a1bb60e31b815260040160405180910390fd5b476106778282610d2d565b816001600160a01b03167feaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d826040516106b291815260200190565b60405180910390a25050565b604051634870496f60e01b81526001600160a01b037f0000000000000000000000008b34b14c7c7123459cf3076b8cb929be097d0c071690634870496f9061071290889088908890889088906004016115f6565b600060405180830381600087803b15801561072c57600080fd5b505af1158015610740573d6000803e3d6000fd5b5050505060008060006107568860a00151610e4b565b60035494985092965091945050506001600160a01b0380861691161490506107b45760405162461bcd60e51b815260206004820152601160248201527010b6b4b93937b91031b7b73732b1ba37b960791b6044820152606401610512565b6001600160a01b03821630146107f65760405162461bcd60e51b8152602060048201526007602482015266085d185c99d95d60ca1b6044820152606401610512565b80516020146108315760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606401610512565b600061083c826116ac565b60008181526005602052604090205490915060ff161561088a5760405162461bcd60e51b81526020600482015260096024820152681c1c9bd8d95cdcd95960ba1b6044820152606401610512565b60008181526005602052604090819020805460ff191660011790555163473ec9fd60e11b81527f000000000000000000000000000000000000000000000000000000006d6f646563ffffffff166004820152602481018290526001600160a01b037f000000000000000000000000523ab7424ad126809b1d7a134eb6e0ee414c9b3a1690638e7d93fa90604401600060405180830381600087803b15801561093157600080fd5b505af1158015610945573d6000803e3d6000fd5b505050507fb3abc57bfeebd2cac918901db582f71972a8e628bccf19f5ae3e3482b98a5ced823360405161097a929190611511565b60405180910390a1505050505050505050565b6000546001600160a01b031633146109b8576040516311a8a1bb60e31b815260040160405180910390fd5b62093a80600254426109ca91906116d0565b116109e8576040516324e0285f60e21b815260040160405180910390fd5b600254600003610a0b57604051630e4b303f60e21b815260040160405180910390fd5b6001546001600160a01b031615610a35576040516323295ef960e01b815260040160405180910390fd5b610a3f6000610f68565b565b6000546001600160a01b03163314610a6c576040516311a8a1bb60e31b815260040160405180910390fd5b61063e81610fcd565b6000546001600160a01b03163314610aa0576040516311a8a1bb60e31b815260040160405180910390fd5b6001546001600160a01b038281169116148015610abe575060025415155b15610adc576040516311bc066560e11b815260040160405180910390fd5b6000546001600160a01b03808316911603610b0a57604051634a2fb73f60e11b815260040160405180910390fd5b61063e8161100e565b6001546001600160a01b03163314610b3e576040516311a7f27160e11b815260040160405180910390fd5b62093a8060025442610b5091906116d0565b11610b6e576040516324e0285f60e21b815260040160405180910390fd5b600154610a3f906001600160a01b0316610f68565b6000610b8e8261105c565b92915050565b8151602014610bcf5760405162461bcd60e51b8152602060048201526007602482015266042d8cadccee8d60cb1b6044820152606401610512565b6000634ff746f660e01b83604051602401610bea91906116f1565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252600354600480549351633dbb202b60e01b81529294506001600160a01b037f00000000000000000000000095bdca6c8edeb69c98bd5bd17660bacef1298a6f811694633dbb202b94610c749490921692879201611704565b600060405180830381600087803b158015610c8e57600080fd5b505af1158015610ca2573d6000803e3d6000fd5b50505050505050565b6040516316c2fdb560e21b815260040160405180910390fd5b600354604080516001600160a01b03928316815291831660208301527fc77bec288fc88f168427f2f7da682eadb26cac89d8d591af6e443da98dff2bbc910160405180910390a1600380546001600160a01b0319166001600160a01b0392909216919091179055565b80471015610d7d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610512565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610dca576040519150601f19603f3d011682016040523d82523d6000602084013e610dcf565b606091505b5050905080610e465760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610512565b505050565b602081015160009081908190819081906060906001600160e01b0319811663d764ad0b60e01b14610eaa5760405162461bcd60e51b815260206004820152600960248201526810b9b2b632b1ba37b960b91b6044820152606401610512565b8751600490600090610ebd9083906116d0565b905060008167ffffffffffffffff811115610eda57610eda611144565b6040519080825280601f01601f191660200182016040528015610f04576020820181803683370190505b509050826020018b016020820160005b84811015610f2c578281015182820152602001610f14565b50505080806020019051810190610f43919061173e565b809a50819b50829c50839d50849e50859f505050505050505050505091939550919395565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b039092166001600160a01b0319928316178155600255600180549091169055565b60045460408051918252602082018390527f877a02cb809da0364d23adca3cd50c451b53f279d3df632e1fc11eb66335bce5910160405180910390a1600455565b42600255600180546001600160a01b0319166001600160a01b0383169081179091556040517f6ab4d119f23076e8ad491bc65ce85f017fb0591dce08755ba8591059cc51737a90600090a250565b6000610b8e7f00000000000000000000000095bdca6c8edeb69c98bd5bd17660bacef1298a6f836000336001600160a01b038416146110c75760405162461bcd60e51b81526020600482015260076024820152662162726964676560c81b6044820152606401610512565b816001600160a01b0316836001600160a01b0316636e296e456040518163ffffffff1660e01b8152600401602060405180830381865afa15801561110f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113391906117fb565b6001600160a01b0316149392505050565b634e487b7160e01b600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561117d5761117d611144565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156111ac576111ac611144565b604052919050565b600067ffffffffffffffff8211156111ce576111ce611144565b50601f01601f191660200190565b600082601f8301126111ed57600080fd5b81356112006111fb826111b4565b611183565b81815284602083860101111561121557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561124557600080fd5b823567ffffffffffffffff8082111561125d57600080fd5b611269868387016111dc565b9350602085013591508082111561127f57600080fd5b5061128c858286016111dc565b9150509250929050565b6000602082840312156112a857600080fd5b813567ffffffffffffffff8111156112bf57600080fd5b6112cb848285016111dc565b949350505050565b6001600160a01b038116811461063e57600080fd5b6000602082840312156112fa57600080fd5b8135611305816112d3565b9392505050565b60006080828403121561131e57600080fd5b50919050565b60008083601f84011261133657600080fd5b50813567ffffffffffffffff81111561134e57600080fd5b6020830191508360208260051b850101111561136957600080fd5b9250929050565b600080600080600060e0868803121561138857600080fd5b853567ffffffffffffffff808211156113a057600080fd5b9087019060c0828a0312156113b457600080fd5b6113bc61115a565b8235815260208301356113ce816112d3565b602082015260408301356113e1816112d3565b80604083015250606083013560608201526080830135608082015260a08301358281111561140e57600080fd5b61141a8b8286016111dc565b60a0830152509650602088013595506114368960408a0161130c565b945060c088013591508082111561144c57600080fd5b5061145988828901611324565b969995985093965092949392505050565b60006020828403121561147c57600080fd5b5035919050565b60005b8381101561149e578181015183820152602001611486565b50506000910152565b600081518084526114bf816020860160208601611483565b601f01601f19169290920160200192915050565b6060815260006114e660608301866114a7565b82810360208401526114f881866114a7565b91505060018060a01b0383166040830152949350505050565b60408152600061152460408301856114a7565b905060018060a01b03831660208301529392505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b81835260006020808501808196508560051b810191508460005b878110156115e95782840389528135601e1988360301811261159f57600080fd5b8701858101903567ffffffffffffffff8111156115bb57600080fd5b8036038213156115ca57600080fd5b6115d586828461153b565b9a87019a955050509084019060010161157e565b5091979650505050505050565b60e080825286519082015260208601516001600160a01b039081166101008301526040870151166101208201526060860151610140820152608086015161016082015260a086015160c06101808301526000906116576101a08401826114a7565b905086602084015261168d6040840187803582526020810135602083015260408101356040830152606081013560608301525050565b82810360c08401526116a0818587611564565b98975050505050505050565b8051602080830151919081101561131e5760001960209190910360031b1b16919050565b81810381811115610b8e57634e487b7160e01b600052601160045260246000fd5b60208152600061130560208301846114a7565b6001600160a01b0384168152606060208201819052600090611728908301856114a7565b905063ffffffff83166040830152949350505050565b60008060008060008060c0878903121561175757600080fd5b865195506020870151611769816112d3565b604088015190955061177a816112d3565b80945050606087015192506080870151915060a087015167ffffffffffffffff8111156117a657600080fd5b8701601f810189136117b757600080fd5b80516117c56111fb826111b4565b8181528a60208385010111156117da57600080fd5b6117eb826020830160208601611483565b8093505050509295509295509295565b60006020828403121561180d57600080fd5b8151611305816112d356fea26469706673582212208e217d671dc72d25ecadbb77036d51b17a6c09ac2a00f99e68a058736c56021164736f6c63430008110033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.