Source Code
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
137439379 | 1 hr ago | 0.000165832135929 ETH | ||||
137439379 | 1 hr ago | 0.000165832135929 ETH | ||||
137439379 | 1 hr ago | 0.000288207412554 ETH | ||||
137439379 | 1 hr ago | 0.000288207412554 ETH | ||||
137438087 | 1 hr ago | 0.000165832135929 ETH | ||||
137438087 | 1 hr ago | 0.000165832135929 ETH | ||||
137438087 | 1 hr ago | 0.000165832135929 ETH | ||||
137438087 | 1 hr ago | 0.000165832135929 ETH | ||||
137438087 | 1 hr ago | 0.000288207412554 ETH | ||||
137438087 | 1 hr ago | 0.000288207412554 ETH | ||||
137438087 | 1 hr ago | 0.000288207412554 ETH | ||||
137438087 | 1 hr ago | 0.000288207412554 ETH | ||||
137435812 | 2 hrs ago | 0.000165832135929 ETH | ||||
137435812 | 2 hrs ago | 0.000165832135929 ETH | ||||
137435812 | 2 hrs ago | 0.000288207412554 ETH | ||||
137435812 | 2 hrs ago | 0.000288207412554 ETH | ||||
137435777 | 3 hrs ago | 0.000165832135929 ETH | ||||
137435777 | 3 hrs ago | 0.000165832135929 ETH | ||||
137435777 | 3 hrs ago | 0.000288207412554 ETH | ||||
137435777 | 3 hrs ago | 0.000288207412554 ETH | ||||
137428125 | 7 hrs ago | 0.000087162315241 ETH | ||||
137428125 | 7 hrs ago | 0.000087162315241 ETH | ||||
137428125 | 7 hrs ago | 0.000087162315241 ETH | ||||
137428125 | 7 hrs ago | 0.000087162315241 ETH | ||||
137428125 | 7 hrs ago | 0.000087162315372 ETH |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
RootMessageBridge
Compiler Version
v0.8.27+commit.40a35a09
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.19 <0.9.0; import {EnumerableSet} from "@openzeppelin5/contracts/utils/structs/EnumerableSet.sol"; import {SafeERC20} from "@openzeppelin5/contracts/token/ERC20/utils/SafeERC20.sol"; import {IERC20} from "@openzeppelin5/contracts/token/ERC20/IERC20.sol"; import {IFactoryRegistry} from "../../interfaces/external/IFactoryRegistry.sol"; import {IRootMessageBridge} from "../../interfaces/root/bridge/IRootMessageBridge.sol"; import {IMessageSender} from "../../interfaces/root/bridge/IMessageSender.sol"; import {IVoter} from "../../interfaces/external/IVoter.sol"; import {IWETH} from "../../interfaces/external/IWETH.sol"; import {CrossChainRegistry} from "../../bridge/CrossChainRegistry.sol"; import {Commands} from "../../libraries/Commands.sol"; /* ██╗ ██╗███████╗██╗ ██████╗ ██████╗ ██████╗ ██████╗ ███╗ ███╗███████╗ ██║ ██║██╔════╝██║ ██╔═══██╗██╔══██╗██╔══██╗██╔═══██╗████╗ ████║██╔════╝ ██║ ██║█████╗ ██║ ██║ ██║██║ ██║██████╔╝██║ ██║██╔████╔██║█████╗ ╚██╗ ██╔╝██╔══╝ ██║ ██║ ██║██║ ██║██╔══██╗██║ ██║██║╚██╔╝██║██╔══╝ ╚████╔╝ ███████╗███████╗╚██████╔╝██████╔╝██║ ██║╚██████╔╝██║ ╚═╝ ██║███████╗ ╚═══╝ ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ███████╗██╗ ██╗██████╗ ███████╗██████╗ ██████╗██╗ ██╗ █████╗ ██╗███╗ ██╗ ██╔════╝██║ ██║██╔══██╗██╔════╝██╔══██╗██╔════╝██║ ██║██╔══██╗██║████╗ ██║ ███████╗██║ ██║██████╔╝█████╗ ██████╔╝██║ ███████║███████║██║██╔██╗ ██║ ╚════██║██║ ██║██╔═══╝ ██╔══╝ ██╔══██╗██║ ██╔══██║██╔══██║██║██║╚██╗██║ ███████║╚██████╔╝██║ ███████╗██║ ██║╚██████╗██║ ██║██║ ██║██║██║ ╚████║ ╚══════╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ███╗ ███╗███████╗███████╗███████╗ █████╗ ██████╗ ███████╗██████╗ ██████╗ ██╗██████╗ ██████╗ ███████╗ ████╗ ████║██╔════╝██╔════╝██╔════╝██╔══██╗██╔════╝ ██╔════╝██╔══██╗██╔══██╗██║██╔══██╗██╔════╝ ██╔════╝ ██╔████╔██║█████╗ ███████╗███████╗███████║██║ ███╗█████╗ ██████╔╝██████╔╝██║██║ ██║██║ ███╗█████╗ ██║╚██╔╝██║██╔══╝ ╚════██║╚════██║██╔══██║██║ ██║██╔══╝ ██╔══██╗██╔══██╗██║██║ ██║██║ ██║██╔══╝ ██║ ╚═╝ ██║███████╗███████║███████║██║ ██║╚██████╔╝███████╗██████╔╝██║ ██║██║██████╔╝╚██████╔╝███████╗ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═════╝ ╚═╝ ╚═╝╚═╝╚═════╝ ╚═════╝ ╚══════╝ */ /// @title Velodrome Superchain Root Message Bridge /// @notice General purpose message bridge contract /// @dev For notify reward amount, tokens will always be forwarded to the module /// @dev The module can then use any mechanism available to it to send the tokens cross chain contract RootMessageBridge is IRootMessageBridge, CrossChainRegistry { using EnumerableSet for EnumerableSet.UintSet; using SafeERC20 for IERC20; using SafeERC20 for IWETH; using Commands for bytes; /// @inheritdoc IRootMessageBridge address public immutable xerc20; /// @inheritdoc IRootMessageBridge address public immutable voter; /// @inheritdoc IRootMessageBridge address public immutable factoryRegistry; /// @inheritdoc IRootMessageBridge address public immutable weth; constructor(address _owner, address _xerc20, address _voter, address _weth) CrossChainRegistry(_owner) { xerc20 = _xerc20; voter = _voter; factoryRegistry = IVoter(_voter).factoryRegistry(); weth = _weth; } receive() external payable { if (msg.sender != weth) revert NotWETH(); } /// @inheritdoc IRootMessageBridge function sendMessage(uint256 _chainid, bytes calldata _message) external { if (!_chainids.contains({value: _chainid})) revert ChainNotRegistered(); address module = chains[_chainid]; uint256 command = _message.command(); if (command == Commands.DEPOSIT) { address gauge = _message.toAddress(); if (msg.sender != IVoter(voter).gaugeToFees(gauge)) revert NotAuthorized(Commands.DEPOSIT); } else if (command == Commands.WITHDRAW) { address gauge = _message.toAddress(); if (msg.sender != IVoter(voter).gaugeToFees(gauge)) revert NotAuthorized(Commands.WITHDRAW); } else if (command == Commands.CREATE_GAUGE) { address factory = _message.toAddress(); (, address gaugeFactory) = IFactoryRegistry(factoryRegistry).factoriesToPoolFactory(factory); if (msg.sender != gaugeFactory) revert NotAuthorized(Commands.CREATE_GAUGE); } else if (command == Commands.GET_INCENTIVES) { address gauge = _message.toAddress(); if (msg.sender != IVoter(voter).gaugeToBribe(gauge)) revert NotAuthorized(Commands.GET_INCENTIVES); } else if (command == Commands.GET_FEES) { address gauge = _message.toAddress(); if (msg.sender != IVoter(voter).gaugeToFees(gauge)) revert NotAuthorized(Commands.GET_FEES); } else if (command == Commands.NOTIFY || command == Commands.NOTIFY_WITHOUT_CLAIM) { if (!IVoter(voter).isAlive(msg.sender)) revert NotValidGauge(); uint256 amount = _message.amount(); IERC20(xerc20).safeTransferFrom({from: msg.sender, to: module, value: amount}); } else if (command == Commands.KILL_GAUGE) { if (msg.sender != IVoter(voter).emergencyCouncil()) revert NotAuthorized(Commands.KILL_GAUGE); } else if (command == Commands.REVIVE_GAUGE) { if (msg.sender != IVoter(voter).emergencyCouncil()) revert NotAuthorized(Commands.REVIVE_GAUGE); } else { revert InvalidCommand(); } uint256 fee = IMessageSender(module).quote({_destinationDomain: _chainid, _messageBody: _message}); // skip if fee is 0 (some modules may support fee-less messaging) if (fee > 0) { IWETH(weth).safeTransferFrom({from: tx.origin, to: address(this), value: fee}); IWETH(weth).withdraw({wad: fee}); } IMessageSender(module).sendMessage{value: fee}({_chainid: _chainid, _message: _message}); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IFactoryRegistry { error FallbackFactory(); error InvalidFactoriesToPoolFactory(); error PathAlreadyApproved(); error PathNotApproved(); error SameAddress(); error ZeroAddress(); event Approve(address indexed poolFactory, address indexed votingRewardsFactory, address indexed gaugeFactory); event Unapprove(address indexed poolFactory, address indexed votingRewardsFactory, address indexed gaugeFactory); event SetManagedRewardsFactory(address indexed _newRewardsFactory); /// @notice Approve a set of factories used in Velodrome Protocol. /// Router.sol is able to swap any poolFactories currently approved. /// Cannot approve address(0) factories. /// Cannot approve path that is already approved. /// Each poolFactory has one unique set and maintains state. In the case a poolFactory is unapproved /// and then re-approved, the same set of factories must be used. In other words, you cannot overwrite /// the factories tied to a poolFactory address. /// VotingRewardsFactories and GaugeFactories may use the same address across multiple poolFactories. /// @dev Callable by onlyOwner /// @param poolFactory . /// @param votingRewardsFactory . /// @param gaugeFactory . function approve(address poolFactory, address votingRewardsFactory, address gaugeFactory) external; /// @notice Get the factories correlated to a poolFactory. /// Once set, this can never be modified. /// Returns the correlated factories even after an approved poolFactory is unapproved. function factoriesToPoolFactory(address poolFactory) external view returns (address votingRewardsFactory, address gaugeFactory); /// @notice Check if a PoolFactory is approved within the factory registry. Router uses this method to /// ensure a pool swapped from is approved. /// @param poolFactory . /// @return True if PoolFactory is approved, else false function isPoolFactoryApproved(address poolFactory) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IRootMessageBridge { error InvalidCommand(); error NotAuthorized(uint256 command); error NotValidGauge(); error NotWETH(); /// @notice Returns the address of the xERC20 token that is bridged by this contract function xerc20() external view returns (address); /// @notice Returns the address of the voter contract /// @dev Used to verify the sender of a message function voter() external view returns (address); /// @notice Returns the address of the factory registry contract function factoryRegistry() external view returns (address); /// @notice Returns the address of the WETH contract function weth() external view returns (address); /// @notice Sends a message to the msg.sender via the module contract /// @param _message The message /// @param _chainid The chain id of chain the recipient contract is on function sendMessage(uint256 _chainid, bytes calldata _message) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IMessageSender { error NotBridge(); event SentMessage( uint32 indexed _destination, bytes32 indexed _recipient, uint256 _value, string _message, string _metadata ); /// @notice Sends a message to the destination module /// @dev All message modules must implement this function /// @param _chainid The chain id of the destination chain /// @param _message The message function sendMessage(uint256 _chainid, bytes calldata _message) external payable; /// @notice Quotes the amount of native token required to dispatch a message /// @param _destinationDomain The chain id of the destination chain /// @param _messageBody The message body to be dispatched /// @return The amount of native token required to dispatch the message function quote(uint256 _destinationDomain, bytes calldata _messageBody) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IFactoryRegistry} from "src/interfaces/external/IFactoryRegistry.sol"; interface IVoter { error AlreadyVotedOrDeposited(); error DistributeWindow(); error GaugeAlreadyKilled(); error GaugeAlreadyRevived(); error NotEmergencyCouncil(); error ZeroAddress(); event GaugeKilled(address indexed gauge); event GaugeRevived(address indexed gauge); /// @dev Gauge => Amount claimable function claimable(address gauge) external view returns (uint256); /// @notice Address of Minter.sol function minter() external view returns (address); /// @notice Set new emergency council. /// @dev Throws if not called by emergency council. /// @param _emergencyCouncil . function setEmergencyCouncil(address _emergencyCouncil) external; function vote(uint256 _tokenId, address[] calldata _poolVote, uint256[] calldata _weights) external; function gauges(address _pool) external view returns (address); function isGauge(address _gauge) external view returns (bool); function gaugeToFees(address _gauge) external view returns (address); function gaugeToBribe(address _gauge) external view returns (address); /// @dev Nft => Timestamp of last vote (ensures single vote per epoch) function lastVoted(uint256 tokenId) external view returns (uint256); function createGauge(address _poolFactory, address _pool) external returns (address); function factoryRegistry() external view returns (address); /// @dev Utility to distribute to gauges of pools in array. /// @param _gauges Array of gauges to distribute to. function distribute(address[] memory _gauges) external; function isAlive(address _gauge) external view returns (bool); function killGauge(address _gauge) external; /// @notice Revives a killed gauge. Gauge will can receive emissions and deposits again. /// @dev Throws if not called by emergency council. /// Throws if gauge is not killed. /// @param _gauge . function reviveGauge(address _gauge) external; function isWhitelistedToken(address _token) external view returns (bool); function emergencyCouncil() external view returns (address); function ve() external view returns (address); /// @notice Claim emissions from gauges. /// @param _gauges Array of gauges to collect emissions from. // function claimRewards(address[] memory _gauges) external; /// @notice Claim fees for a given NFT. /// @dev Utility to help batch fee claims. /// @param _fees Array of FeesVotingReward contracts to collect from. /// @param _tokens Array of tokens that are used as fees. /// @param _tokenId Id of veNFT that you wish to claim fees for. function claimFees(address[] memory _fees, address[][] memory _tokens, uint256 _tokenId) external; /// @notice Called by users to update voting balances in voting rewards contracts. /// @param _tokenId Id of veNFT whose balance you wish to update. function poke(uint256 _tokenId) external; /// @notice Called by users to reset voting state. Required if you wish to make changes to /// veNFT state (e.g. merge, split, deposit into managed etc). /// Cannot reset in the same epoch that you voted in. /// Can vote or deposit into a managed NFT again after reset. /// @param _tokenId Id of veNFT you are reseting. function reset(uint256 _tokenId) external; /// @notice Standard OZ IGovernor using ve for vote weights. function governor() external view returns (address); /// @notice Whitelist (or unwhitelist) token for use in incentives. /// @dev Throws if not called by governor. /// @param _token . /// @param _bool . function whitelistToken(address _token, bool _bool) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import {IERC20} from "@openzeppelin5/contracts/token/ERC20/IERC20.sol"; interface IWETH is IERC20 { function deposit() external payable; function withdraw(uint256 wad) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.19 <0.9.0; import {Ownable} from "@openzeppelin5/contracts/access/Ownable.sol"; import {EnumerableSet} from "@openzeppelin5/contracts/utils/structs/EnumerableSet.sol"; import {ICrossChainRegistry} from "../interfaces/bridge/ICrossChainRegistry.sol"; /// @title Cross Chain Registry /// @notice Contains logic for managing registered chains from which messages can be sent to or received from abstract contract CrossChainRegistry is ICrossChainRegistry, Ownable { using EnumerableSet for EnumerableSet.UintSet; using EnumerableSet for EnumerableSet.AddressSet; /// @dev Stores list of trusted chains EnumerableSet.UintSet internal _chainids; /// @dev Stores list of modules /// @dev Modules on other chains are not trusted by default and must be checked EnumerableSet.AddressSet internal _modules; /// @inheritdoc ICrossChainRegistry mapping(uint256 => address) public chains; constructor(address _owner) Ownable(_owner) {} /// @inheritdoc ICrossChainRegistry function registerChain(uint256 _chainid, address _module) external onlyOwner { if (_chainid == 10) revert InvalidChainId(); if (!_modules.contains(_module)) revert ModuleNotAdded(); if (_chainids.contains(_chainid)) revert ChainAlreadyAdded(); chains[_chainid] = _module; _chainids.add(_chainid); emit ChainRegistered({_chainid: _chainid, _module: _module}); } /// @inheritdoc ICrossChainRegistry function deregisterChain(uint256 _chainid) external onlyOwner { if (chains[_chainid] == address(0)) revert ChainNotRegistered(); delete chains[_chainid]; _chainids.remove(_chainid); emit ChainDeregistered({_chainid: _chainid}); } /// @inheritdoc ICrossChainRegistry function setModule(uint256 _chainid, address _module) external onlyOwner { if (!_modules.contains(_module)) revert ModuleNotAdded(); if (!_chainids.contains(_chainid)) revert ChainNotRegistered(); chains[_chainid] = _module; emit ModuleSet({_chainid: _chainid, _module: _module}); } /// @inheritdoc ICrossChainRegistry function addModule(address _module) external onlyOwner { if (_modules.contains(_module)) revert ModuleAlreadyAdded(); _modules.add(_module); emit ModuleAdded({_module: _module}); } /// @inheritdoc ICrossChainRegistry function chainids() external view returns (uint256[] memory) { return _chainids.values(); } /// @inheritdoc ICrossChainRegistry function containsChain(uint256 _chainid) external view returns (bool) { return _chainids.contains(_chainid); } /// @inheritdoc ICrossChainRegistry function modules() external view returns (address[] memory) { return _modules.values(); } /// @inheritdoc ICrossChainRegistry function containsModule(address _module) external view returns (bool) { return _modules.contains(_module); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.19 <0.9.0; /// @notice Commands for x-chain interactions /// @dev Existing commands cannot be modified but new commands can be added library Commands { uint256 public constant NOTIFY = 0x00; uint256 public constant NOTIFY_WITHOUT_CLAIM = 0x01; uint256 public constant GET_INCENTIVES = 0x02; uint256 public constant GET_FEES = 0x03; uint256 public constant DEPOSIT = 0x04; uint256 public constant WITHDRAW = 0x05; uint256 public constant CREATE_GAUGE = 0x06; uint256 public constant KILL_GAUGE = 0x07; uint256 public constant REVIVE_GAUGE = 0x08; uint256 private constant COMMAND_OFFSET = 0; uint256 private constant ADDRESS_OFFSET = 1; /// @dev Second and Third offset are used in messages with multiple consecutive addresses uint256 private constant SECOND_OFFSET = ADDRESS_OFFSET + 20; uint256 private constant THIRD_OFFSET = SECOND_OFFSET + 20; // Offsets for Create Gauge Command uint256 private constant TOKEN0_OFFSET = THIRD_OFFSET + 20; uint256 private constant TOKEN1_OFFSET = TOKEN0_OFFSET + 20; uint256 private constant POOL_PARAM_OFFSET = TOKEN1_OFFSET + 20; // Offsets for Reward Claims uint256 private constant LENGTH_OFFSET = THIRD_OFFSET + 32; uint256 private constant TOKENS_OFFSET = LENGTH_OFFSET + 1; // Offset for Deposit/Withdraw uint256 private constant TOKEN_ID_OFFSET = ADDRESS_OFFSET + 20 + 32; uint256 private constant TIMESTAMP_OFFSET = TOKEN_ID_OFFSET + 32; // Offset for Send Token amount uint256 private constant AMOUNT_OFFSET = COMMAND_OFFSET + 20; /// @notice Returns the command encoded in the message /// @dev Assumes message is encoded as (command, ...) /// @param _message The message to be decoded function command(bytes calldata _message) internal pure returns (uint256) { return uint256(uint8(bytes1(_message[COMMAND_OFFSET:COMMAND_OFFSET + 1]))); } /// @notice Returns the address encoded in the message /// @dev Assumes message is encoded as (command, address, ...) /// @param _message The message to be decoded function toAddress(bytes calldata _message) internal pure returns (address) { return address(bytes20(_message[ADDRESS_OFFSET:ADDRESS_OFFSET + 20])); } /// @notice Returns the message without the encoded command /// @dev Assumes message is encoded as (command, message) /// @param _message The message to be decoded function messageWithoutCommand(bytes calldata _message) internal pure returns (bytes calldata) { return bytes(_message[COMMAND_OFFSET + 1:]); } /// @notice Returns the amount encoded in the message /// @dev Assumes message is encoded as (command, amount, ...) /// @param _message The message to be decoded function amount(bytes calldata _message) internal pure returns (uint256) { return uint256(bytes32(_message[SECOND_OFFSET:SECOND_OFFSET + 32])); } /// @notice Returns the amount, tokenId and timestamp encoded in the message /// @dev Assumes message is encoded as (command, amount, tokenId, timestamp, ...) /// @param _message The message to be decoded function voteParams(bytes calldata _message) internal pure returns (uint256, uint256, uint256) { return ( uint256(bytes32(_message[SECOND_OFFSET:SECOND_OFFSET + 32])), uint256(bytes32(_message[TOKEN_ID_OFFSET:TIMESTAMP_OFFSET])), uint256(uint40(bytes5(_message[TIMESTAMP_OFFSET:TIMESTAMP_OFFSET + 5]))) ); } /// @notice Returns the recipient and amount encoded in the message /// @dev Assumes no command is encoded and message is encoded as (address, amount) /// @param _message The message to be decoded function recipientAndAmount(bytes calldata _message) internal pure returns (address, uint256) { return ( address(bytes20(_message[COMMAND_OFFSET:COMMAND_OFFSET + 20])), uint256(bytes32(_message[AMOUNT_OFFSET:AMOUNT_OFFSET + 32])) ); } /// @notice Returns the parameters necessary for gauge creation, encoded in the message /// @dev Assumes message is encoded as (command, address, address, address, address, uint24) /// @param _message The message to be decoded function createGaugeParams(bytes calldata _message) internal pure returns (address, address, address, address, address, uint24) { return ( address(bytes20(_message[ADDRESS_OFFSET:ADDRESS_OFFSET + 20])), address(bytes20(_message[SECOND_OFFSET:SECOND_OFFSET + 20])), address(bytes20(_message[THIRD_OFFSET:THIRD_OFFSET + 20])), address(bytes20(_message[TOKEN0_OFFSET:TOKEN0_OFFSET + 20])), address(bytes20(_message[TOKEN1_OFFSET:TOKEN1_OFFSET + 20])), uint24(bytes3(_message[POOL_PARAM_OFFSET:POOL_PARAM_OFFSET + 3])) ); } /// @notice Returns the owner encoded in the message /// @dev Assumes message is encoded as (command, address, owner, ...) /// @param _message The message to be decoded function owner(bytes calldata _message) internal pure returns (address) { return address(bytes20(_message[SECOND_OFFSET:SECOND_OFFSET + 20])); } /// @notice Returns the tokenId encoded in a reward claiming message /// @dev Assumes message is encoded as (command, address, tokenId, ...) /// @param _message The message to be decoded function tokenId(bytes calldata _message) internal pure returns (uint256) { return uint256(bytes32(_message[THIRD_OFFSET:THIRD_OFFSET + 32])); } /// @notice Returns the token addresses encoded in the message /// @dev Assumes message has length and token addresses encoded /// @param _message The message to be decoded function tokens(bytes calldata _message) internal pure returns (address[] memory _tokens) { uint256 length = uint8(bytes1(_message[LENGTH_OFFSET:LENGTH_OFFSET + 1])); _tokens = new address[](length); for (uint256 i = 0; i < length; i++) { _tokens[i] = address(uint160(uint256(bytes32(_message[TOKENS_OFFSET + (i * 32):TOKENS_OFFSET + ((i + 1) * 32)])))); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) 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 FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev 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. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * 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. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ICrossChainRegistry { event ChainRegistered(uint256 indexed _chainid, address indexed _module); event ChainDeregistered(uint256 indexed _chainid); event ModuleAdded(address indexed _module); event ModuleSet(uint256 indexed _chainid, address indexed _module); error ChainAlreadyAdded(); error ChainNotRegistered(); error InvalidChainId(); error ModuleAlreadyAdded(); error ModuleNotAdded(); /// @notice Add support for a chain with messages forwarded to a given module /// @dev Check module code if adding a new module for the first time /// @param _chainid Chain ID to add /// @param _module Module to forward messages to, must be registered function registerChain(uint256 _chainid, address _module) external; /// @notice Remove support for a chain /// @param _chainid Chain ID to remove function deregisterChain(uint256 _chainid) external; /// @notice Add a module to be used for message forwarding /// @dev Modules are deployed on other chains at the same address /// @dev Modules are not trusted by default and must be checked prior to usage /// @param _module Module to register function addModule(address _module) external; /// @notice Update a module used by a chain for message forwarding /// @param _chainid Chain ID to update /// @param _module Module to forward messages to function setModule(uint256 _chainid, address _module) external; /// @notice Get message module for a given chain /// @param _chainid Chain ID to check function chains(uint256 _chainid) external view returns (address); /// @notice Get list of supported chains function chainids() external view returns (uint256[] memory); /// @notice Check if a chain is supported /// @param _chainid Chain ID to check function containsChain(uint256 _chainid) external view returns (bool); /// @notice Get list of registered modules function modules() external view returns (address[] memory); /// @notice Check if a module is registered /// @param _module Module to check function containsModule(address _module) external view returns (bool); }
// 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; } }
{ "remappings": [ "@openzeppelin5/contracts/=lib/openzeppelin-contracts/contracts/", "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/src/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "createX/=lib/createX/src/", "@nomad-xyz/=lib/ExcessivelySafeCall/", "@hyperlane/=node_modules/@hyperlane-xyz/", "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", "@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/", "ExcessivelySafeCall/=lib/ExcessivelySafeCall/src/", "forge-gas-snapshot/=lib/forge-gas-snapshot/src/", "openzeppelin/=lib/createX/lib/openzeppelin-contracts/contracts/", "solady/=lib/createX/lib/solady/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": { "src/libraries/rateLimits/RateLimitMidpointCommonLibrary.sol": { "RateLimitMidpointCommonLibrary": "0x8326B5f31549d12943088CF3F8Dd637dd6465a99" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_xerc20","type":"address"},{"internalType":"address","name":"_voter","type":"address"},{"internalType":"address","name":"_weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"ChainAlreadyAdded","type":"error"},{"inputs":[],"name":"ChainNotRegistered","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidChainId","type":"error"},{"inputs":[],"name":"InvalidCommand","type":"error"},{"inputs":[],"name":"ModuleAlreadyAdded","type":"error"},{"inputs":[],"name":"ModuleNotAdded","type":"error"},{"inputs":[{"internalType":"uint256","name":"command","type":"uint256"}],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotValidGauge","type":"error"},{"inputs":[],"name":"NotWETH","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_chainid","type":"uint256"}],"name":"ChainDeregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_chainid","type":"uint256"},{"indexed":true,"internalType":"address","name":"_module","type":"address"}],"name":"ChainRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_module","type":"address"}],"name":"ModuleAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_chainid","type":"uint256"},{"indexed":true,"internalType":"address","name":"_module","type":"address"}],"name":"ModuleSet","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":[{"internalType":"address","name":"_module","type":"address"}],"name":"addModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainids","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"chains","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainid","type":"uint256"}],"name":"containsChain","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_module","type":"address"}],"name":"containsModule","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainid","type":"uint256"}],"name":"deregisterChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factoryRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"modules","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":"uint256","name":"_chainid","type":"uint256"},{"internalType":"address","name":"_module","type":"address"}],"name":"registerChain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainid","type":"uint256"},{"internalType":"bytes","name":"_message","type":"bytes"}],"name":"sendMessage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_chainid","type":"uint256"},{"internalType":"address","name":"_module","type":"address"}],"name":"setModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"voter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"xerc20","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
61010060405234801561001157600080fd5b50604051611b1c380380611b1c83398101604081905261003091610166565b83806001600160a01b03811661006057604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b610069816100fa565b50506001600160a01b03808416608052821660a081905260408051633bf0c9fb60e01b81529051633bf0c9fb916004808201926020929091908290030181865afa1580156100bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100df91906101ba565b6001600160a01b0390811660c0521660e052506101dc915050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811461016157600080fd5b919050565b6000806000806080858703121561017c57600080fd5b6101858561014a565b93506101936020860161014a565b92506101a16040860161014a565b91506101af6060860161014a565b905092959194509250565b6000602082840312156101cc57600080fd5b6101d58261014a565b9392505050565b60805160a05160c05160e0516118b361026960003960008181610112015281816101da01528181610ddd0152610e1b015260008181610189015261087201526000818161020e015281816106b7015281816107980152818161094801528181610a1f01528181610ae701528181610bc40152610c870152600081816103df0152610b9201526118b36000f3fe6080604052600436106101025760003560e01c80637eaaac3811610095578063e68e00bf11610064578063e68e00bf14610349578063f2fde38b14610369578063f772795914610389578063f7e80e98146103ab578063ffcbd8d0146103cd57600080fd5b80637eaaac38146102bb5780638da5cb5b146102eb578063e289adcd14610309578063e31b84d81461032957600080fd5b8063550325b5116100d1578063550325b5146102305780635d29163014610266578063715018a6146102865780637e25b5f81461029b57600080fd5b80631ed86f19146101575780633bf0c9fb146101775780633fc8cef3146101c857806346c96aac146101fc57600080fd5b3661015257336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461015057604051635724f38560e01b815260040160405180910390fd5b005b600080fd5b34801561016357600080fd5b50610150610172366004611503565b610401565b34801561018357600080fd5b506101ab7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101d457600080fd5b506101ab7f000000000000000000000000000000000000000000000000000000000000000081565b34801561020857600080fd5b506101ab7f000000000000000000000000000000000000000000000000000000000000000081565b34801561023c57600080fd5b506101ab61024b366004611520565b6005602052600090815260409020546001600160a01b031681565b34801561027257600080fd5b50610150610281366004611539565b610475565b34801561029257600080fd5b50610150610526565b3480156102a757600080fd5b506101506102b6366004611539565b61053a565b3480156102c757600080fd5b506102db6102d6366004611503565b610621565b60405190151581526020016101bf565b3480156102f757600080fd5b506000546001600160a01b03166101ab565b34801561031557600080fd5b50610150610324366004611569565b610634565b34801561033557600080fd5b506102db610344366004611520565b610eec565b34801561035557600080fd5b50610150610364366004611520565b610ef9565b34801561037557600080fd5b50610150610384366004611503565b610f8c565b34801561039557600080fd5b5061039e610fca565b6040516101bf91906115e7565b3480156103b757600080fd5b506103c0610fdb565b6040516101bf919061162a565b3480156103d957600080fd5b506101ab7f000000000000000000000000000000000000000000000000000000000000000081565b610409610fe7565b610414600382611014565b156104325760405163079f102d60e51b815260040160405180910390fd5b61043d600382611039565b506040516001600160a01b038216907fead6a006345da1073a106d5f32372d2d2204f46cb0b4bca8f5ebafcbbed12b8a90600090a250565b61047d610fe7565b610488600382611014565b6104a55760405163d9b2550b60e01b815260040160405180910390fd5b6104b060018361104e565b6104cd57604051634631318960e11b815260040160405180910390fd5b60008281526005602052604080822080546001600160a01b0319166001600160a01b0385169081179091559051909184917fbf17fdfd9b9ec4dc5b4bfa40af4b752c82856d2fe977cf488315f8e64efc54a99190a35050565b61052e610fe7565b6105386000611066565b565b610542610fe7565b81600a0361056357604051633d23e4d160e11b815260040160405180910390fd5b61056e600382611014565b61058b5760405163d9b2550b60e01b815260040160405180910390fd5b61059660018361104e565b156105b4576040516301419f6d60e21b815260040160405180910390fd5b600082815260056020526040902080546001600160a01b0319166001600160a01b0383161790556105e66001836110b6565b506040516001600160a01b0382169083907f7f74812a5c28f04eea9007878d0e63eb304afe494a442babbe1b2875fbc1cfd690600090a35050565b600061062e600383611014565b92915050565b61063f60018461104e565b61065c57604051634631318960e11b815260040160405180910390fd5b6000838152600560205260408120546001600160a01b03169061067f84846110c2565b90506004810361076257600061069585856110f2565b60405163c4f0816560e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063c4f0816590602401602060405180830381865afa158015610700573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610724919061166b565b6001600160a01b0316336001600160a01b03161461075c576040516318488cc760e31b81526004818101526024015b60405180910390fd5b50610d54565b6005810361083957600061077685856110f2565b60405163c4f0816560e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063c4f0816590602401602060405180830381865afa1580156107e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610805919061166b565b6001600160a01b0316336001600160a01b03161461075c576040516318488cc760e31b815260056004820152602401610753565b6006810361091257600061084d85856110f2565b604051631217afdb60e01b81526001600160a01b0380831660048301529192506000917f00000000000000000000000000000000000000000000000000000000000000001690631217afdb906024016040805180830381865afa1580156108b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108dc9190611688565b915050336001600160a01b0382161461090b576040516318488cc760e31b815260066004820152602401610753565b5050610d54565b600281036109e957600061092685856110f2565b60405163929c8dcd60e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063929c8dcd90602401602060405180830381865afa158015610991573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b5919061166b565b6001600160a01b0316336001600160a01b03161461075c576040516318488cc760e31b815260026004820152602401610753565b60038103610ac05760006109fd85856110f2565b60405163c4f0816560e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063c4f0816590602401602060405180830381865afa158015610a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8c919061166b565b6001600160a01b0316336001600160a01b03161461075c576040516318488cc760e31b815260036004820152602401610753565b801580610acd5750600181145b15610bba57604051631703e5f960e01b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690631703e5f990602401602060405180830381865afa158015610b36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5a91906116b7565b610b7757604051635d6da4f560e01b815260040160405180910390fd5b6000610b838585611123565b905061075c6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016338584611161565b60078103610c7d577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637778960e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c44919061166b565b6001600160a01b0316336001600160a01b031614610c78576040516318488cc760e31b815260076004820152602401610753565b610d54565b60088103610d3b577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637778960e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ce3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d07919061166b565b6001600160a01b0316336001600160a01b031614610c78576040516318488cc760e31b815260086004820152602401610753565b6040516312f269e560e01b815260040160405180910390fd5b6040516377d2b77160e01b81526000906001600160a01b038416906377d2b77190610d87908990899089906004016116d9565b602060405180830381865afa158015610da4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc8919061170f565b90508015610e8057610e056001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016323084611161565b604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015610e6757600080fd5b505af1158015610e7b573d6000803e3d6000fd5b505050505b60405163e289adcd60e01b81526001600160a01b0384169063e289adcd908390610eb2908a908a908a906004016116d9565b6000604051808303818588803b158015610ecb57600080fd5b505af1158015610edf573d6000803e3d6000fd5b5050505050505050505050565b600061062e60018361104e565b610f01610fe7565b6000818152600560205260409020546001600160a01b0316610f3657604051634631318960e11b815260040160405180910390fd5b600081815260056020526040902080546001600160a01b0319169055610f5d6001826111c1565b5060405181907f4732a5e8ed8dad61e5185f5b8d342146071e8029d9055b85b5ff24078cee3d8690600090a250565b610f94610fe7565b6001600160a01b038116610fbe57604051631e4fbdf760e01b815260006004820152602401610753565b610fc781611066565b50565b6060610fd660016111cd565b905090565b6060610fd660036111cd565b6000546001600160a01b031633146105385760405163118cdaa760e01b8152336004820152602401610753565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b6000611032836001600160a01b0384166111da565b60008181526001830160205260408120541515611032565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600061103283836111da565b60008281836110d282600161173e565b926110df93929190611751565b6110e89161177b565b60f81c9392505050565b60008260018361110382601461173e565b9261111093929190611751565b611119916117b1565b60601c9392505050565b600082826111336001601461173e565b906111406001601461173e565b61114b90602061173e565b9261115893929190611751565b611032916117f1565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526111bb908590611229565b50505050565b60006110328383611291565b606060006110328361138b565b60008181526001830160205260408120546112215750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561062e565b50600061062e565b600061123e6001600160a01b038416836113e7565b9050805160001415801561126357508080602001905181019061126191906116b7565b155b1561128c57604051635274afe760e01b81526001600160a01b0384166004820152602401610753565b505050565b6000818152600183016020526040812054801561137a5760006112b560018361180f565b85549091506000906112c99060019061180f565b905080821461132e5760008660000182815481106112e9576112e9611822565b906000526020600020015490508087600001848154811061130c5761130c611822565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061133f5761133f611838565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061062e565b600091505061062e565b5092915050565b6060816000018054806020026020016040519081016040528092919081815260200182805480156113db57602002820191906000526020600020905b8154815260200190600101908083116113c7575b50505050509050919050565b60606110328383600084600080856001600160a01b0316848660405161140d919061184e565b60006040518083038185875af1925050503d806000811461144a576040519150601f19603f3d011682016040523d82523d6000602084013e61144f565b606091505b509150915061145f868383611469565b9695505050505050565b60608261147e57611479826114c5565b611032565b815115801561149557506001600160a01b0384163b155b156114be57604051639996b31560e01b81526001600160a01b0385166004820152602401610753565b5080611032565b8051156114d55780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b0381168114610fc757600080fd5b60006020828403121561151557600080fd5b8135611032816114ee565b60006020828403121561153257600080fd5b5035919050565b6000806040838503121561154c57600080fd5b82359150602083013561155e816114ee565b809150509250929050565b60008060006040848603121561157e57600080fd5b83359250602084013567ffffffffffffffff81111561159c57600080fd5b8401601f810186136115ad57600080fd5b803567ffffffffffffffff8111156115c457600080fd5b8660208284010111156115d657600080fd5b939660209190910195509293505050565b602080825282518282018190526000918401906040840190835b8181101561161f578351835260209384019390920191600101611601565b509095945050505050565b602080825282518282018190526000918401906040840190835b8181101561161f5783516001600160a01b0316835260209384019390920191600101611644565b60006020828403121561167d57600080fd5b8151611032816114ee565b6000806040838503121561169b57600080fd5b82516116a6816114ee565b602084015190925061155e816114ee565b6000602082840312156116c957600080fd5b8151801515811461103257600080fd5b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b60006020828403121561172157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561062e5761062e611728565b6000808585111561176157600080fd5b8386111561176e57600080fd5b5050820193919092039150565b80356001600160f81b03198116906001841015611384576001600160f81b031960019490940360031b84901b1690921692915050565b80356bffffffffffffffffffffffff198116906014841015611384576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b8035602083101561062e57600019602084900360031b1b1692915050565b8181038181111561062e5761062e611728565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b6000825160005b8181101561186f5760208186018101518583015201611855565b50600092019182525091905056fea26469706673582212209460effbaa7883ed1a5e87cf925ed368b990eade51b3a2f2559081201026cfa964736f6c634300081b0033000000000000000000000000ba4bb89f4d1e66aa86b60696534892ae0ccf91f50000000000000000000000007f9adfbd38b669f03d1d11000bc76b9aaea28a8100000000000000000000000041c914ee0c7e1a5edcd0295623e6dc557b5abf3c0000000000000000000000004200000000000000000000000000000000000006
Deployed Bytecode
0x6080604052600436106101025760003560e01c80637eaaac3811610095578063e68e00bf11610064578063e68e00bf14610349578063f2fde38b14610369578063f772795914610389578063f7e80e98146103ab578063ffcbd8d0146103cd57600080fd5b80637eaaac38146102bb5780638da5cb5b146102eb578063e289adcd14610309578063e31b84d81461032957600080fd5b8063550325b5116100d1578063550325b5146102305780635d29163014610266578063715018a6146102865780637e25b5f81461029b57600080fd5b80631ed86f19146101575780633bf0c9fb146101775780633fc8cef3146101c857806346c96aac146101fc57600080fd5b3661015257336001600160a01b037f0000000000000000000000004200000000000000000000000000000000000006161461015057604051635724f38560e01b815260040160405180910390fd5b005b600080fd5b34801561016357600080fd5b50610150610172366004611503565b610401565b34801561018357600080fd5b506101ab7f000000000000000000000000f4c67cdeaab8360370f41514d06e32ccd8aa1d7b81565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101d457600080fd5b506101ab7f000000000000000000000000420000000000000000000000000000000000000681565b34801561020857600080fd5b506101ab7f00000000000000000000000041c914ee0c7e1a5edcd0295623e6dc557b5abf3c81565b34801561023c57600080fd5b506101ab61024b366004611520565b6005602052600090815260409020546001600160a01b031681565b34801561027257600080fd5b50610150610281366004611539565b610475565b34801561029257600080fd5b50610150610526565b3480156102a757600080fd5b506101506102b6366004611539565b61053a565b3480156102c757600080fd5b506102db6102d6366004611503565b610621565b60405190151581526020016101bf565b3480156102f757600080fd5b506000546001600160a01b03166101ab565b34801561031557600080fd5b50610150610324366004611569565b610634565b34801561033557600080fd5b506102db610344366004611520565b610eec565b34801561035557600080fd5b50610150610364366004611520565b610ef9565b34801561037557600080fd5b50610150610384366004611503565b610f8c565b34801561039557600080fd5b5061039e610fca565b6040516101bf91906115e7565b3480156103b757600080fd5b506103c0610fdb565b6040516101bf919061162a565b3480156103d957600080fd5b506101ab7f0000000000000000000000007f9adfbd38b669f03d1d11000bc76b9aaea28a8181565b610409610fe7565b610414600382611014565b156104325760405163079f102d60e51b815260040160405180910390fd5b61043d600382611039565b506040516001600160a01b038216907fead6a006345da1073a106d5f32372d2d2204f46cb0b4bca8f5ebafcbbed12b8a90600090a250565b61047d610fe7565b610488600382611014565b6104a55760405163d9b2550b60e01b815260040160405180910390fd5b6104b060018361104e565b6104cd57604051634631318960e11b815260040160405180910390fd5b60008281526005602052604080822080546001600160a01b0319166001600160a01b0385169081179091559051909184917fbf17fdfd9b9ec4dc5b4bfa40af4b752c82856d2fe977cf488315f8e64efc54a99190a35050565b61052e610fe7565b6105386000611066565b565b610542610fe7565b81600a0361056357604051633d23e4d160e11b815260040160405180910390fd5b61056e600382611014565b61058b5760405163d9b2550b60e01b815260040160405180910390fd5b61059660018361104e565b156105b4576040516301419f6d60e21b815260040160405180910390fd5b600082815260056020526040902080546001600160a01b0319166001600160a01b0383161790556105e66001836110b6565b506040516001600160a01b0382169083907f7f74812a5c28f04eea9007878d0e63eb304afe494a442babbe1b2875fbc1cfd690600090a35050565b600061062e600383611014565b92915050565b61063f60018461104e565b61065c57604051634631318960e11b815260040160405180910390fd5b6000838152600560205260408120546001600160a01b03169061067f84846110c2565b90506004810361076257600061069585856110f2565b60405163c4f0816560e01b81526001600160a01b0380831660048301529192507f00000000000000000000000041c914ee0c7e1a5edcd0295623e6dc557b5abf3c9091169063c4f0816590602401602060405180830381865afa158015610700573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610724919061166b565b6001600160a01b0316336001600160a01b03161461075c576040516318488cc760e31b81526004818101526024015b60405180910390fd5b50610d54565b6005810361083957600061077685856110f2565b60405163c4f0816560e01b81526001600160a01b0380831660048301529192507f00000000000000000000000041c914ee0c7e1a5edcd0295623e6dc557b5abf3c9091169063c4f0816590602401602060405180830381865afa1580156107e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610805919061166b565b6001600160a01b0316336001600160a01b03161461075c576040516318488cc760e31b815260056004820152602401610753565b6006810361091257600061084d85856110f2565b604051631217afdb60e01b81526001600160a01b0380831660048301529192506000917f000000000000000000000000f4c67cdeaab8360370f41514d06e32ccd8aa1d7b1690631217afdb906024016040805180830381865afa1580156108b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108dc9190611688565b915050336001600160a01b0382161461090b576040516318488cc760e31b815260066004820152602401610753565b5050610d54565b600281036109e957600061092685856110f2565b60405163929c8dcd60e01b81526001600160a01b0380831660048301529192507f00000000000000000000000041c914ee0c7e1a5edcd0295623e6dc557b5abf3c9091169063929c8dcd90602401602060405180830381865afa158015610991573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b5919061166b565b6001600160a01b0316336001600160a01b03161461075c576040516318488cc760e31b815260026004820152602401610753565b60038103610ac05760006109fd85856110f2565b60405163c4f0816560e01b81526001600160a01b0380831660048301529192507f00000000000000000000000041c914ee0c7e1a5edcd0295623e6dc557b5abf3c9091169063c4f0816590602401602060405180830381865afa158015610a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8c919061166b565b6001600160a01b0316336001600160a01b03161461075c576040516318488cc760e31b815260036004820152602401610753565b801580610acd5750600181145b15610bba57604051631703e5f960e01b81523360048201527f00000000000000000000000041c914ee0c7e1a5edcd0295623e6dc557b5abf3c6001600160a01b031690631703e5f990602401602060405180830381865afa158015610b36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b5a91906116b7565b610b7757604051635d6da4f560e01b815260040160405180910390fd5b6000610b838585611123565b905061075c6001600160a01b037f0000000000000000000000007f9adfbd38b669f03d1d11000bc76b9aaea28a8116338584611161565b60078103610c7d577f00000000000000000000000041c914ee0c7e1a5edcd0295623e6dc557b5abf3c6001600160a01b0316637778960e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c44919061166b565b6001600160a01b0316336001600160a01b031614610c78576040516318488cc760e31b815260076004820152602401610753565b610d54565b60088103610d3b577f00000000000000000000000041c914ee0c7e1a5edcd0295623e6dc557b5abf3c6001600160a01b0316637778960e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ce3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d07919061166b565b6001600160a01b0316336001600160a01b031614610c78576040516318488cc760e31b815260086004820152602401610753565b6040516312f269e560e01b815260040160405180910390fd5b6040516377d2b77160e01b81526000906001600160a01b038416906377d2b77190610d87908990899089906004016116d9565b602060405180830381865afa158015610da4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dc8919061170f565b90508015610e8057610e056001600160a01b037f000000000000000000000000420000000000000000000000000000000000000616323084611161565b604051632e1a7d4d60e01b8152600481018290527f00000000000000000000000042000000000000000000000000000000000000066001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015610e6757600080fd5b505af1158015610e7b573d6000803e3d6000fd5b505050505b60405163e289adcd60e01b81526001600160a01b0384169063e289adcd908390610eb2908a908a908a906004016116d9565b6000604051808303818588803b158015610ecb57600080fd5b505af1158015610edf573d6000803e3d6000fd5b5050505050505050505050565b600061062e60018361104e565b610f01610fe7565b6000818152600560205260409020546001600160a01b0316610f3657604051634631318960e11b815260040160405180910390fd5b600081815260056020526040902080546001600160a01b0319169055610f5d6001826111c1565b5060405181907f4732a5e8ed8dad61e5185f5b8d342146071e8029d9055b85b5ff24078cee3d8690600090a250565b610f94610fe7565b6001600160a01b038116610fbe57604051631e4fbdf760e01b815260006004820152602401610753565b610fc781611066565b50565b6060610fd660016111cd565b905090565b6060610fd660036111cd565b6000546001600160a01b031633146105385760405163118cdaa760e01b8152336004820152602401610753565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b6000611032836001600160a01b0384166111da565b60008181526001830160205260408120541515611032565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600061103283836111da565b60008281836110d282600161173e565b926110df93929190611751565b6110e89161177b565b60f81c9392505050565b60008260018361110382601461173e565b9261111093929190611751565b611119916117b1565b60601c9392505050565b600082826111336001601461173e565b906111406001601461173e565b61114b90602061173e565b9261115893929190611751565b611032916117f1565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526111bb908590611229565b50505050565b60006110328383611291565b606060006110328361138b565b60008181526001830160205260408120546112215750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561062e565b50600061062e565b600061123e6001600160a01b038416836113e7565b9050805160001415801561126357508080602001905181019061126191906116b7565b155b1561128c57604051635274afe760e01b81526001600160a01b0384166004820152602401610753565b505050565b6000818152600183016020526040812054801561137a5760006112b560018361180f565b85549091506000906112c99060019061180f565b905080821461132e5760008660000182815481106112e9576112e9611822565b906000526020600020015490508087600001848154811061130c5761130c611822565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061133f5761133f611838565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061062e565b600091505061062e565b5092915050565b6060816000018054806020026020016040519081016040528092919081815260200182805480156113db57602002820191906000526020600020905b8154815260200190600101908083116113c7575b50505050509050919050565b60606110328383600084600080856001600160a01b0316848660405161140d919061184e565b60006040518083038185875af1925050503d806000811461144a576040519150601f19603f3d011682016040523d82523d6000602084013e61144f565b606091505b509150915061145f868383611469565b9695505050505050565b60608261147e57611479826114c5565b611032565b815115801561149557506001600160a01b0384163b155b156114be57604051639996b31560e01b81526001600160a01b0385166004820152602401610753565b5080611032565b8051156114d55780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b6001600160a01b0381168114610fc757600080fd5b60006020828403121561151557600080fd5b8135611032816114ee565b60006020828403121561153257600080fd5b5035919050565b6000806040838503121561154c57600080fd5b82359150602083013561155e816114ee565b809150509250929050565b60008060006040848603121561157e57600080fd5b83359250602084013567ffffffffffffffff81111561159c57600080fd5b8401601f810186136115ad57600080fd5b803567ffffffffffffffff8111156115c457600080fd5b8660208284010111156115d657600080fd5b939660209190910195509293505050565b602080825282518282018190526000918401906040840190835b8181101561161f578351835260209384019390920191600101611601565b509095945050505050565b602080825282518282018190526000918401906040840190835b8181101561161f5783516001600160a01b0316835260209384019390920191600101611644565b60006020828403121561167d57600080fd5b8151611032816114ee565b6000806040838503121561169b57600080fd5b82516116a6816114ee565b602084015190925061155e816114ee565b6000602082840312156116c957600080fd5b8151801515811461103257600080fd5b83815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b60006020828403121561172157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561062e5761062e611728565b6000808585111561176157600080fd5b8386111561176e57600080fd5b5050820193919092039150565b80356001600160f81b03198116906001841015611384576001600160f81b031960019490940360031b84901b1690921692915050565b80356bffffffffffffffffffffffff198116906014841015611384576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b8035602083101561062e57600019602084900360031b1b1692915050565b8181038181111561062e5761062e611728565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b6000825160005b8181101561186f5760208186018101518583015201611855565b50600092019182525091905056fea26469706673582212209460effbaa7883ed1a5e87cf925ed368b990eade51b3a2f2559081201026cfa964736f6c634300081b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000ba4bb89f4d1e66aa86b60696534892ae0ccf91f50000000000000000000000007f9adfbd38b669f03d1d11000bc76b9aaea28a8100000000000000000000000041c914ee0c7e1a5edcd0295623e6dc557b5abf3c0000000000000000000000004200000000000000000000000000000000000006
-----Decoded View---------------
Arg [0] : _owner (address): 0xBA4BB89f4d1E66AA86B60696534892aE0cCf91F5
Arg [1] : _xerc20 (address): 0x7f9AdFbd38b669F03d1d11000Bc76b9AaEA28A81
Arg [2] : _voter (address): 0x41C914ee0c7E1A5edCD0295623e6dC557B5aBf3C
Arg [3] : _weth (address): 0x4200000000000000000000000000000000000006
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000ba4bb89f4d1e66aa86b60696534892ae0ccf91f5
Arg [1] : 0000000000000000000000007f9adfbd38b669f03d1d11000bc76b9aaea28a81
Arg [2] : 00000000000000000000000041c914ee0c7e1a5edcd0295623e6dc557b5abf3c
Arg [3] : 0000000000000000000000004200000000000000000000000000000000000006
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.