ETH Price: $3,180.58 (-0.38%)

Contract

0x97cDBCe21B6fd0585d29E539B1B99dAd328a1123

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
37179342025-02-21 10:09:31286 days ago1740132571  Contract Creation0 ETH

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
LeafVoter

Compiler Version
v0.8.27+commit.40a35a09

Optimization Enabled:
Yes with 200 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.8.19 <0.9.0;

import {ReentrancyGuard} from "@openzeppelin5/contracts/utils/ReentrancyGuard.sol";
import {EnumerableSet} from "@openzeppelin5/contracts/utils/structs/EnumerableSet.sol";

import {IVotingRewardsFactory} from "../interfaces/rewards/IVotingRewardsFactory.sol";
import {ILeafMessageBridge} from "../interfaces/bridge/ILeafMessageBridge.sol";
import {ILeafGaugeFactory} from "../interfaces/gauges/ILeafGaugeFactory.sol";
import {ILeafGauge} from "../interfaces/gauges/ILeafGauge.sol";
import {IReward} from "../interfaces/rewards/IReward.sol";
import {IPoolFactory} from "../interfaces/pools/IPoolFactory.sol";
import {IPool} from "../interfaces/pools/IPool.sol";
import {ILeafVoter} from "../interfaces/voter/ILeafVoter.sol";

/*

██╗   ██╗███████╗██╗      ██████╗ ██████╗ ██████╗  ██████╗ ███╗   ███╗███████╗
██║   ██║██╔════╝██║     ██╔═══██╗██╔══██╗██╔══██╗██╔═══██╗████╗ ████║██╔════╝
██║   ██║█████╗  ██║     ██║   ██║██║  ██║██████╔╝██║   ██║██╔████╔██║█████╗
╚██╗ ██╔╝██╔══╝  ██║     ██║   ██║██║  ██║██╔══██╗██║   ██║██║╚██╔╝██║██╔══╝
 ╚████╔╝ ███████╗███████╗╚██████╔╝██████╔╝██║  ██║╚██████╔╝██║ ╚═╝ ██║███████╗
  ╚═══╝  ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝  ╚═╝ ╚═════╝ ╚═╝     ╚═╝╚══════╝

███████╗██╗   ██╗██████╗ ███████╗██████╗  ██████╗██╗  ██╗ █████╗ ██╗███╗   ██╗
██╔════╝██║   ██║██╔══██╗██╔════╝██╔══██╗██╔════╝██║  ██║██╔══██╗██║████╗  ██║
███████╗██║   ██║██████╔╝█████╗  ██████╔╝██║     ███████║███████║██║██╔██╗ ██║
╚════██║██║   ██║██╔═══╝ ██╔══╝  ██╔══██╗██║     ██╔══██║██╔══██║██║██║╚██╗██║
███████║╚██████╔╝██║     ███████╗██║  ██║╚██████╗██║  ██║██║  ██║██║██║ ╚████║
╚══════╝ ╚═════╝ ╚═╝     ╚══════╝╚═╝  ╚═╝ ╚═════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═══╝

██╗     ███████╗ █████╗ ███████╗██╗   ██╗ ██████╗ ████████╗███████╗██████╗
██║     ██╔════╝██╔══██╗██╔════╝██║   ██║██╔═══██╗╚══██╔══╝██╔════╝██╔══██╗
██║     █████╗  ███████║█████╗  ██║   ██║██║   ██║   ██║   █████╗  ██████╔╝
██║     ██╔══╝  ██╔══██║██╔══╝  ╚██╗ ██╔╝██║   ██║   ██║   ██╔══╝  ██╔══██╗
███████╗███████╗██║  ██║██║      ╚████╔╝ ╚██████╔╝   ██║   ███████╗██║  ██║
╚══════╝╚══════╝╚═╝  ╚═╝╚═╝       ╚═══╝   ╚═════╝    ╚═╝   ╚══════╝╚═╝  ╚═╝

*/

/// @title Velodrome Superchain Voter
/// @author velodrome.finance
/// @notice Leaf Voter contract to manage Votes on non-canonical chains
contract LeafVoter is ILeafVoter, ReentrancyGuard {
    using EnumerableSet for EnumerableSet.AddressSet;

    /// @inheritdoc ILeafVoter
    address public immutable bridge;

    /// @dev All pools viable for incentives
    address[] public pools;
    /// @inheritdoc ILeafVoter
    mapping(address => address) public gauges;
    /// @inheritdoc ILeafVoter
    mapping(address => address) public poolForGauge;
    /// @inheritdoc ILeafVoter
    mapping(address => address) public gaugeToFees;
    /// @inheritdoc ILeafVoter
    mapping(address => address) public gaugeToIncentive;
    /// @inheritdoc ILeafVoter
    mapping(address => bool) public isGauge;
    /// @inheritdoc ILeafVoter
    mapping(address => bool) public isAlive;
    /// @inheritdoc ILeafVoter
    mapping(address => uint256) public whitelistTokenCount;
    /// @dev Set of Whitelisted Tokens
    EnumerableSet.AddressSet private _whitelistedTokens;

    constructor(address _bridge) {
        bridge = _bridge;
    }

    /// @inheritdoc ILeafVoter
    function whitelistedTokens() external view returns (address[] memory) {
        return _whitelistedTokens.values();
    }

    /// @inheritdoc ILeafVoter
    function whitelistedTokens(uint256 _start, uint256 _end) external view returns (address[] memory _tokens) {
        uint256 length = _whitelistedTokens.length();
        _end = _end < length ? _end : length;
        _tokens = new address[](_end - _start);
        for (uint256 i = 0; i < _end - _start; i++) {
            _tokens[i] = _whitelistedTokens.at(i + _start);
        }
    }

    /// @inheritdoc ILeafVoter
    function isWhitelistedToken(address _token) external view returns (bool) {
        return _whitelistedTokens.contains(_token);
    }

    /// @inheritdoc ILeafVoter
    function whitelistedTokensLength() external view returns (uint256) {
        return _whitelistedTokens.length();
    }

    /// @inheritdoc ILeafVoter
    function createGauge(address _poolFactory, address _pool, address _votingRewardsFactory, address _gaugeFactory)
        external
        nonReentrant
        returns (address _gauge)
    {
        if (msg.sender != ILeafMessageBridge(bridge).module()) revert NotAuthorized();

        address[] memory rewards = new address[](2);
        (rewards[0], rewards[1]) = IPool(_pool).tokens();

        (address _feesVotingReward, address _incentiveVotingReward) =
            IVotingRewardsFactory(_votingRewardsFactory).createRewards({_rewards: rewards});

        _gauge = ILeafGaugeFactory(_gaugeFactory).createGauge({
            _pool: _pool,
            _feesVotingReward: _feesVotingReward,
            isPool: IPoolFactory(_poolFactory).isPool(_pool)
        });

        gaugeToFees[_gauge] = _feesVotingReward;
        gaugeToIncentive[_gauge] = _incentiveVotingReward;
        gauges[_pool] = _gauge;
        poolForGauge[_gauge] = _pool;
        isGauge[_gauge] = true;
        isAlive[_gauge] = true;
        pools.push(_pool);

        _whitelistToken(rewards[0], true);
        _whitelistToken(rewards[1], true);

        emit GaugeCreated({
            poolFactory: _poolFactory,
            votingRewardsFactory: _votingRewardsFactory,
            gaugeFactory: _gaugeFactory,
            pool: _pool,
            incentiveVotingReward: _incentiveVotingReward,
            feeVotingReward: _feesVotingReward,
            gauge: _gauge
        });
    }

    /// @inheritdoc ILeafVoter
    function killGauge(address _gauge) external {
        if (msg.sender != ILeafMessageBridge(bridge).module()) revert NotAuthorized();
        if (!isAlive[_gauge]) revert GaugeAlreadyKilled();

        isAlive[_gauge] = false;
        (address token0, address token1) = IPool(poolForGauge[_gauge]).tokens();
        _whitelistToken(token0, false);
        _whitelistToken(token1, false);
        emit GaugeKilled({gauge: _gauge});
    }

    /// @inheritdoc ILeafVoter
    function reviveGauge(address _gauge) external {
        if (msg.sender != ILeafMessageBridge(bridge).module()) revert NotAuthorized();
        if (!isGauge[_gauge]) revert NotAGauge();
        if (isAlive[_gauge]) revert GaugeAlreadyRevived();

        isAlive[_gauge] = true;
        (address token0, address token1) = IPool(poolForGauge[_gauge]).tokens();
        _whitelistToken(token0, true);
        _whitelistToken(token1, true);
        emit GaugeRevived({gauge: _gauge});
    }

    /// @inheritdoc ILeafVoter
    function claimRewards(address[] memory _gauges) external {
        uint256 _length = _gauges.length;
        for (uint256 i = 0; i < _length; i++) {
            ILeafGauge(_gauges[i]).getReward(msg.sender);
        }
    }

    /// @notice Sets the whitelist state of a given token
    /// @dev    Assumes token to be unwhitelisted has whitelistTokenCount > 0
    /// @param _token The address of the token for whitelist
    /// @param _bool Whether the token should be whitelisted or not
    function _whitelistToken(address _token, bool _bool) internal {
        if (_bool) {
            if (++whitelistTokenCount[_token] == 1) {
                _whitelistedTokens.add(_token);
            }
        } else {
            if (--whitelistTokenCount[_token] == 0) {
                _whitelistedTokens.remove(_token);
            }
        }
        emit WhitelistToken({token: _token, _bool: _bool});
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

// 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
pragma solidity ^0.8.0;

interface IVotingRewardsFactory {
    error NotVoter();

    /// @notice Returns the address of the voter contract
    /// @return Address of the voter contract
    function voter() external view returns (address);

    /// @notice Returns the address of the bridge contract
    /// @return Address of the bridge contract
    function bridge() external view returns (address);

    /// @notice creates an incentiveVotingReward and a FeesVotingReward contract for a gauge
    /// @param _rewards Addresses of pool tokens to be used as valid rewards tokens
    /// @return feesVotingReward Address of FeesVotingReward contract created
    /// @return incentiveVotingReward Address of IncentiveVotingReward contract created
    function createRewards(address[] memory _rewards)
        external
        returns (address feesVotingReward, address incentiveVotingReward);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ILeafMessageBridge {
    error ZeroAddress();

    event ModuleSet(address indexed _sender, address indexed _module);

    /// @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 module contract that is allowed to send messages x-chain
    function module() 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 Sets the address of the module contract that is allowed to send messages x-chain
    /// @dev Module handles x-chain messages
    /// @param _module The address of the new module contract
    function setModule(address _module) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ILeafGaugeFactory {
    error NotAuthorized();
    error ZeroAddress();
    error NotVoter();

    /// @notice Voter contract
    function voter() external view returns (address);
    /// @notice XERC20 contract, also is the reward token used by the gauge
    function xerc20() external view returns (address);
    /// @notice Velodrome bridge contract
    function bridge() external view returns (address);

    /// @notice Creates a new gauge
    /// @param _pool Pool to create a gauge for
    /// @param _feesVotingReward Reward token for fees voting
    /// @param isPool True if the gauge is linked to a pool
    function createGauge(address _pool, address _feesVotingReward, bool isPool) external returns (address gauge);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ILeafGauge {
    error NotAlive();
    error NotAuthorized();
    error NotModule();
    error RewardRateTooHigh();
    error ZeroAmount();
    error ZeroRewardRate();

    event Deposit(address indexed _sender, address indexed _to, uint256 _amount);
    event Withdraw(address indexed _sender, uint256 _amount);
    event NotifyReward(address indexed _sender, uint256 _amount);
    event ClaimFees(address indexed _sender, uint256 _claimed0, uint256 _claimed1);
    event ClaimRewards(address indexed _sender, uint256 _amount);

    /// @notice Address of the pool LP token which is deposited (staked) for rewards
    function stakingToken() external view returns (address);

    /// @notice Address of the token (VELO v2) rewarded to stakers
    function rewardToken() external view returns (address);

    /// @notice Address of the FeesVotingReward contract linked to the gauge
    function feesVotingReward() external view returns (address);

    /// @notice Address of Velodrome v2 Voter
    function voter() external view returns (address);

    /// @notice Address of Velodrome v2 Bridge
    function bridge() external view returns (address);

    /// @notice Returns if gauge is linked to a legitimate Velodrome pool
    function isPool() external view returns (bool);

    /// @notice Timestamp end of current rewards period
    function periodFinish() external view returns (uint256);

    /// @notice Current reward rate of rewardToken to distribute per second
    function rewardRate() external view returns (uint256);

    /// @notice Most recent timestamp contract has updated state
    function lastUpdateTime() external view returns (uint256);

    /// @notice Most recent stored value of rewardPerToken
    function rewardPerTokenStored() external view returns (uint256);

    /// @notice Amount of stakingToken deposited for rewards
    function totalSupply() external view returns (uint256);

    /// @notice Get the amount of stakingToken deposited by an account
    function balanceOf(address) external view returns (uint256);

    /// @notice Cached rewardPerTokenStored for an account based on their most recent action
    function userRewardPerTokenPaid(address) external view returns (uint256);

    /// @notice Cached amount of rewardToken earned for an account
    function rewards(address) external view returns (uint256);

    /// @notice View to see the rewardRate given the timestamp of the start of the epoch
    function rewardRateByEpoch(uint256) external view returns (uint256);

    /// @notice Cached amount of fees generated from the Pool linked to the Gauge of token0
    function fees0() external view returns (uint256);

    /// @notice Cached amount of fees generated from the Pool linked to the Gauge of token1
    function fees1() external view returns (uint256);

    /// @notice Get the current reward rate per unit of stakingToken deposited
    function rewardPerToken() external view returns (uint256 _rewardPerToken);

    /// @notice Returns the last time the reward was modified or periodFinish if the reward has ended
    function lastTimeRewardApplicable() external view returns (uint256 _time);

    /// @notice Returns accrued balance to date from last claim / first deposit.
    function earned(address _account) external view returns (uint256 _earned);

    /// @notice Total amount of rewardToken to distribute for the current rewards period
    function left() external view returns (uint256 _left);

    /// @notice Retrieve rewards for an address.
    /// @dev Throws if not called by same address or voter.
    /// @param _account .
    function getReward(address _account) external;

    /// @notice Deposit LP tokens into gauge for msg.sender
    /// @param _amount .
    function deposit(uint256 _amount) external;

    /// @notice Deposit LP tokens into gauge for any user
    /// @param _amount .
    /// @param _recipient Recipient to give balance to
    function deposit(uint256 _amount, address _recipient) external;

    /// @notice Withdraw LP tokens for user
    /// @param _amount .
    function withdraw(uint256 _amount) external;

    /// @notice Notifies gauge of gauge rewards. Assumes gauge reward tokens is 18 decimals.
    /// @dev If not 18 decimals, rewardRate may have rounding issues.
    /// @param amount Amount of rewards to be deposited into gauge
    function notifyRewardAmount(uint256 amount) external;

    /// @notice Notifies gauge of gauge rewards without distributing its fees.
    /// @dev Assumes gauge reward tokens is 18 decimals.
    ///      If not 18 decimals, rewardRate may have rounding issues.
    /// @param amount Amount of rewards to be deposited into gauge
    function notifyRewardWithoutClaim(uint256 amount) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IReward {
    error InvalidReward();
    error NotAuthorized();
    error NotGauge();
    error NotEscrowToken();
    error NotSingleToken();
    error NotVotingEscrow();
    error NotWhitelisted();
    error ZeroAmount();

    event Deposit(uint256 indexed _tokenId, uint256 _amount);
    event Withdraw(uint256 indexed _tokenId, uint256 _amount);
    event NotifyReward(address indexed _sender, address indexed _reward, uint256 indexed _epoch, uint256 _amount);
    event ClaimRewards(address indexed _sender, address indexed _reward, uint256 _amount);

    /// @notice A checkpoint for marking balance
    struct Checkpoint {
        uint256 timestamp;
        uint256 balanceOf;
    }

    /// @notice A checkpoint for marking supply
    struct SupplyCheckpoint {
        uint256 timestamp;
        uint256 supply;
    }

    /// @notice Epoch duration constant (7 days)
    function DURATION() external view returns (uint256);

    /// @notice Address of LeafVoter.sol
    function voter() external view returns (address);

    /// @dev Address which has permission to externally call _deposit() & _withdraw()
    function authorized() external view returns (address);

    /// @notice Total amount currently deposited via _deposit()
    function totalSupply() external view returns (uint256);

    /// @notice Current amount deposited by tokenId
    function balanceOf(uint256 tokenId) external view returns (uint256);

    /// @notice Amount of tokens to reward depositors for a given epoch
    /// @param token Address of token to reward
    /// @param epochStart Startime of rewards epoch
    /// @return Amount of token
    function tokenRewardsPerEpoch(address token, uint256 epochStart) external view returns (uint256);

    /// @notice Most recent timestamp a veNFT has claimed their rewards
    /// @param  token Address of token rewarded
    /// @param tokenId veNFT unique identifier
    /// @return Timestamp
    function lastEarn(address token, uint256 tokenId) external view returns (uint256);

    /// @notice List of reward tokens
    /// @param _index Index of reward token
    /// @return Address of reward token
    function rewards(uint256 _index) external view returns (address);

    /// @notice True if a token is or has been an active reward token, else false
    function isReward(address token) external view returns (bool);

    /// @notice The number of checkpoints for each tokenId deposited
    function numCheckpoints(uint256 tokenId) external view returns (uint256);

    /// @notice The total number of checkpoints
    function supplyNumCheckpoints() external view returns (uint256);

    /// @notice Deposit an amount into the rewards contract to earn future rewards associated to a veNFT
    /// @dev Internal notation used as only callable internally by `authorized.module()`.
    /// @param amount Vote weight to deposit
    /// @param tokenId Token ID of weight to deposit
    /// @param timestamp Timestamp of deposit
    function _deposit(uint256 amount, uint256 tokenId, uint256 timestamp) external;

    /// @notice Withdraw an amount from the rewards contract associated to a veNFT
    /// @dev Internal notation used as only callable internally by `authorized.module()`.
    /// @param amount Vote weight to withdraw
    /// @param tokenId Token ID of weight to withdraw
    /// @param timestamp Timestamp of withdraw
    function _withdraw(uint256 amount, uint256 tokenId, uint256 timestamp) external;

    /// @notice Claim the rewards earned by a veNFT staker
    /// @param _recipient  Address of reward recipient
    /// @param _tokenId  Unique identifier of the veNFT
    /// @param _tokens   Array of tokens to claim rewards of
    function getReward(address _recipient, uint256 _tokenId, address[] memory _tokens) external;

    /// @notice Add rewards for stakers to earn
    /// @param token    Address of token to reward
    /// @param amount   Amount of token to transfer to rewards
    function notifyRewardAmount(address token, uint256 amount) external;

    /// @notice Determine the prior balance for an account as of a block number
    /// @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
    /// @param tokenId      The token of the NFT to check
    /// @param timestamp    The timestamp to get the balance at
    /// @return The balance the account had as of the given block
    function getPriorBalanceIndex(uint256 tokenId, uint256 timestamp) external view returns (uint256);

    /// @notice Determine the prior index of supply staked by of a timestamp
    /// @dev Timestamp must be <= current timestamp
    /// @param timestamp The timestamp to get the index at
    /// @return Index of supply checkpoint
    function getPriorSupplyIndex(uint256 timestamp) external view returns (uint256);

    /// @notice Get number of rewards tokens
    function rewardsListLength() external view returns (uint256);

    /// @notice Calculate how much in rewards are earned for a specific token and veNFT
    /// @param token Address of token to fetch rewards of
    /// @param tokenId Unique identifier of the veNFT
    /// @return Amount of token earned in rewards
    function earned(address token, uint256 tokenId) external view returns (uint256);

    function checkpoints(uint256 tokenId, uint256 index) external view returns (uint256 timestamp, uint256 balanceOf);

    function supplyCheckpoints(uint256 index) external view returns (uint256 timestamp, uint256 supply);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IPoolFactory {
    event SetFeeManager(address indexed feeManager);
    event SetPauser(address indexed pauser);
    event SetPauseState(bool indexed state);
    event SetPoolAdmin(address indexed poolAdmin);
    event PoolCreated(address indexed token0, address indexed token1, bool indexed stable, address pool, uint256);
    event SetDefaultFee(bool indexed stable, uint256 fee);
    event FeeModuleChanged(address indexed oldFeeModule, address indexed newFeeModule);

    error FeeInvalid();
    error FeeTooHigh();
    error NotFeeManager();
    error NotPauser();
    error NotPoolAdmin();
    error PoolAlreadyExists();
    error SameAddress();
    error ZeroFee();
    error ZeroAddress();

    /// @notice Return a single pool created by this factory
    /// @return Address of pool
    function allPools(uint256 index) external view returns (address);

    /// @notice Returns all pools created by this factory
    /// @return Array of pool addresses
    function allPools() external view returns (address[] memory);

    /// @notice returns the number of pools created from this factory
    function allPoolsLength() external view returns (uint256);

    /// @notice Is a valid pool created by this factory.
    /// @param .
    function isPool(address pool) external view returns (bool);

    /// @notice Return address of pool created by this factory
    /// @param tokenA .
    /// @param tokenB .
    /// @param stable True if stable, false if volatile
    function getPool(address tokenA, address tokenB, bool stable) external view returns (address);

    /// @notice Support for v3-style pools which wraps around getPool(tokenA,tokenB,stable)
    /// @dev fee is converted to stable boolean.
    /// @param tokenA .
    /// @param tokenB .
    /// @param fee  1 if stable, 0 if volatile, else returns address(0)
    function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address);

    /// @notice Set pool administrator
    /// @dev Allowed to change the name and symbol of any pool created by this factory
    /// @param _poolAdmin Address of the pool administrator
    function setPoolAdmin(address _poolAdmin) external;

    /// @notice Set the pauser for the factory contract
    /// @dev The pauser can pause swaps on pools associated with the factory. Liquidity will always be withdrawable.
    /// @dev Must be called by the pauser
    /// @param _pauser Address of the pauser
    function setPauser(address _pauser) external;

    /// @notice Pause or unpause swaps on pools associated with the factory
    /// @param _state True to pause, false to unpause
    function setPauseState(bool _state) external;

    /// @notice Set the fee manager for the factory contract
    /// @dev The fee manager can set fees on pools associated with the factory.
    /// @dev Must be called by the fee manager
    /// @param _feeManager Address of the fee manager
    function setFeeManager(address _feeManager) external;

    /// @notice Updates the feeModule of the factory
    /// @dev Must be called by the current fee manager
    /// @param _feeModule The new feeModule of the factory
    function setFeeModule(address _feeModule) external;

    /// @notice Set default fee for stable and volatile pools.
    /// @dev Throws if higher than maximum fee.
    ///      Throws if fee is zero.
    /// @param _stable Stable or volatile pool.
    /// @param _fee .
    function setFee(bool _stable, uint256 _fee) external;

    /// @notice Returns fee for a pool, as custom fees are possible.
    function getFee(address _pool, bool _stable) external view returns (uint256);

    /// @notice Create a pool given two tokens and if they're stable/volatile
    /// @dev token order does not matter
    /// @param tokenA .
    /// @param tokenB .
    /// @param stable .
    function createPool(address tokenA, address tokenB, bool stable) external returns (address pool);

    /// @notice Support for v3-style pools which wraps around createPool(tokenA,tokenB,stable)
    /// @dev fee is converted to stable boolean
    /// @dev token order does not matter
    /// @param tokenA .
    /// @param tokenB .
    /// @param fee 1 if stable, 0 if volatile, else revert
    function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool);

    /// @notice The pool implementation used to create pools
    /// @return Address of pool implementation
    function implementation() external view returns (address);

    /// @notice Whether the pools associated with the factory are paused or not.
    /// @dev Pause only pauses swaps, liquidity will always be withdrawable.
    function isPaused() external view returns (bool);

    /// @notice The address of the pauser, can pause swaps on pools associated with factory.
    /// @return Address of the pauser
    function pauser() external view returns (address);

    /// @notice The default fee for all stable pools
    /// @return Default stable fee
    function stableFee() external view returns (uint256);

    /// @notice The default fee for all volatile pools
    /// @return Default volatile fee
    function volatileFee() external view returns (uint256);

    /// @notice Maximum possible fee for default stable or volatile fee
    /// @return 3%
    function MAX_FEE() external view returns (uint256);

    /// @notice Address of the fee manager, can set fees on pools associated with factory.
    /// @notice This overrides the default fee for that pool.
    /// @return Address of the fee manager
    function feeManager() external view returns (address);

    /// @notice Address of the fee module of the factory
    /// @dev Can be changed by the current fee manager via setFeeModule
    /// @return Address of the fee module
    function feeModule() external view returns (address);

    /// @notice Address of the pool administrator, can change the name and symbol of pools created by factory.
    /// @return Address of the pool administrator
    function poolAdmin() external view returns (address);
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IPool {
    error DepositsNotEqual();
    error BelowMinimumK();
    error FactoryAlreadySet();
    error InsufficientLiquidity();
    error InsufficientLiquidityMinted();
    error InsufficientLiquidityBurned();
    error InsufficientOutputAmount();
    error InsufficientInputAmount();
    error IsPaused();
    error InvalidTo();
    error K();

    event Fees(address indexed sender, uint256 amount0, uint256 amount1);
    event Mint(address indexed sender, address indexed to, uint256 amount0, uint256 amount1);
    event Burn(address indexed sender, address indexed to, uint256 amount0, uint256 amount1);
    event Swap(
        address indexed sender,
        address indexed to,
        uint256 amount0In,
        uint256 amount1In,
        uint256 amount0Out,
        uint256 amount1Out
    );
    event Sync(uint256 reserve0, uint256 reserve1);
    event Claim(address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1);

    // Struct to capture time period obervations every 30 minutes, used for local oracles
    struct Observation {
        uint256 timestamp;
        uint256 reserve0Cumulative;
        uint256 reserve1Cumulative;
    }

    /// @notice Returns the decimal (dec), reserves (r), stable (st), and tokens (t) of token0 and token1
    function metadata()
        external
        view
        returns (uint256 dec0, uint256 dec1, uint256 r0, uint256 r1, bool st, address t0, address t1);

    /// @notice Claim accumulated but unclaimed fees (claimable0 and claimable1)
    function claimFees() external returns (uint256, uint256);

    /// @notice Returns [token0, token1]
    function tokens() external view returns (address, address);

    /// @notice Address of token in the pool with the lower address value
    function token0() external view returns (address);

    /// @notice Address of token in the pool with the higher address value
    function token1() external view returns (address);

    /// @notice Address of linked PoolFees.sol
    function poolFees() external view returns (address);

    /// @notice Address of PoolFactory that created this contract
    function factory() external view returns (address);

    /// @notice Capture oracle reading every 30 minutes (1800 seconds)
    function periodSize() external view returns (uint256);

    /// @notice Amount of token0 in pool
    function reserve0() external view returns (uint256);

    /// @notice Amount of token1 in pool
    function reserve1() external view returns (uint256);

    /// @notice Timestamp of last update to pool
    function blockTimestampLast() external view returns (uint256);

    /// @notice Cumulative of reserve0 factoring in time elapsed
    function reserve0CumulativeLast() external view returns (uint256);

    /// @notice Cumulative of reserve1 factoring in time elapsed
    function reserve1CumulativeLast() external view returns (uint256);

    /// @notice Accumulated fees of token0 (global)
    function index0() external view returns (uint256);

    /// @notice Accumulated fees of token1 (global)
    function index1() external view returns (uint256);

    /// @notice Get an LP's relative index0 to index0
    function supplyIndex0(address) external view returns (uint256);

    /// @notice Get an LP's relative index1 to index1
    function supplyIndex1(address) external view returns (uint256);

    /// @notice Amount of unclaimed, but claimable tokens from fees of token0 for an LP
    function claimable0(address) external view returns (uint256);

    /// @notice Amount of unclaimed, but claimable tokens from fees of token1 for an LP
    function claimable1(address) external view returns (uint256);

    /// @notice Returns the value of K in the Pool, based on its reserves.
    function getK() external returns (uint256);

    /// @notice Set pool name
    ///         Only callable by Voter.emergencyCouncil()
    /// @param __name String of new name
    function setName(string calldata __name) external;

    /// @notice Set pool symbol
    ///         Only callable by Voter.emergencyCouncil()
    /// @param __symbol String of new symbol
    function setSymbol(string calldata __symbol) external;

    /// @notice Get the number of observations recorded
    function observationLength() external view returns (uint256);

    /// @notice Get the value of the most recent observation
    function lastObservation() external view returns (Observation memory);

    /// @notice True if pool is stable, false if volatile
    function stable() external view returns (bool);

    /// @notice Produces the cumulative price using counterfactuals to save gas and avoid a call to sync.
    function currentCumulativePrices()
        external
        view
        returns (uint256 reserve0Cumulative, uint256 reserve1Cumulative, uint256 blockTimestamp);

    /// @notice Provides twap price with user configured granularity, up to the full window size
    /// @param tokenIn .
    /// @param amountIn .
    /// @param granularity .
    /// @return amountOut .
    function quote(address tokenIn, uint256 amountIn, uint256 granularity) external view returns (uint256 amountOut);

    /// @notice Returns a memory set of TWAP prices
    ///         Same as calling sample(tokenIn, amountIn, points, 1)
    /// @param tokenIn .
    /// @param amountIn .
    /// @param points Number of points to return
    /// @return Array of TWAP prices
    function prices(address tokenIn, uint256 amountIn, uint256 points) external view returns (uint256[] memory);

    /// @notice Same as prices with with an additional window argument.
    ///         Window = 2 means 2 * 30min (or 1 hr) between observations
    /// @param tokenIn .
    /// @param amountIn .
    /// @param points .
    /// @param window .
    /// @return Array of TWAP prices
    function sample(address tokenIn, uint256 amountIn, uint256 points, uint256 window)
        external
        view
        returns (uint256[] memory);

    /// @notice This low-level function should be called from a contract which performs important safety checks
    /// @param amount0Out   Amount of token0 to send to `to`
    /// @param amount1Out   Amount of token1 to send to `to`
    /// @param to           Address to recieve the swapped output
    /// @param data         Additional calldata for flashloans
    function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;

    /// @notice This low-level function should be called from a contract which performs important safety checks
    ///         standard uniswap v2 implementation
    /// @param to Address to receive token0 and token1 from burning the pool token
    /// @return amount0 Amount of token0 returned
    /// @return amount1 Amount of token1 returned
    function burn(address to) external returns (uint256 amount0, uint256 amount1);

    /// @notice This low-level function should be called by addLiquidity functions in Router.sol, which performs important safety checks
    ///         standard uniswap v2 implementation
    /// @param to           Address to receive the minted LP token
    /// @return liquidity   Amount of LP token minted
    function mint(address to) external returns (uint256 liquidity);

    /// @notice Update reserves and, on the first call per block, price accumulators
    /// @return _reserve0 .
    /// @return _reserve1 .
    /// @return _blockTimestampLast .
    function getReserves() external view returns (uint256 _reserve0, uint256 _reserve1, uint256 _blockTimestampLast);

    /// @notice Get the amount of tokenOut given the amount of tokenIn
    /// @param amountIn Amount of token in
    /// @param tokenIn  Address of token
    /// @return Amount out
    function getAmountOut(uint256 amountIn, address tokenIn) external view returns (uint256);

    /// @notice Force balances to match reserves
    /// @param to Address to receive any skimmed rewards
    function skim(address to) external;

    /// @notice Force reserves to match balances
    function sync() external;

    /// @notice Called on pool creation by PoolFactory
    /// @param _token0 Address of token0
    /// @param _token1 Address of token1
    /// @param _stable True if stable, false if volatile
    function initialize(address _token0, address _token1, bool _stable) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface ILeafVoter {
    error NotAGauge();
    error ZeroAddress();
    error NotAuthorized();
    error GaugeAlreadyKilled();
    error GaugeAlreadyRevived();

    event GaugeCreated(
        address indexed poolFactory,
        address indexed votingRewardsFactory,
        address indexed gaugeFactory,
        address pool,
        address incentiveVotingReward,
        address feeVotingReward,
        address gauge
    );
    event GaugeKilled(address indexed gauge);
    event GaugeRevived(address indexed gauge);
    event WhitelistToken(address indexed token, bool indexed _bool);

    /// @notice Address of bridge contract used to forward x-chain messages
    function bridge() external view returns (address);

    /// @dev Pool => Gauge
    function gauges(address _pool) external view returns (address);

    /// @dev Gauge => Pool
    function poolForGauge(address _gauge) external view returns (address);

    /// @dev Gauge => Fees Voting Reward
    function gaugeToFees(address _gauge) external view returns (address);

    /// @dev Gauge => Incentives Voting Reward
    function gaugeToIncentive(address _gauge) external view returns (address);

    /// @notice Check if a given address is a gauge
    /// @param _gauge The address to be checked
    /// @return Whether the address is a gauge or not
    function isGauge(address _gauge) external view returns (bool);

    /// @notice Check if a given gauge is alive
    /// @param _gauge The address of the gauge to be checked
    /// @return Whether the gauge is alive or not
    function isAlive(address _gauge) external view returns (bool);

    /// @notice Returns the number of times a token has been whitelisted
    /// @param _token Address of token to view whitelist count
    /// @return Number of times token has been whitelisted
    function whitelistTokenCount(address _token) external view returns (uint256);

    /// @notice Get all Whitelisted Tokens approved by the Voter
    /// @return Array of Whitelisted Token addresses
    function whitelistedTokens() external view returns (address[] memory);

    /// @notice Paginated view of all Whitelisted Tokens
    /// @dev    Should not assume the last Token returned is at index matching given `_end`,
    ///         because if `_end` exceeds `length`, implementation defaults to `length`
    /// @param _start Index of first Token to be fetched
    /// @param _end End index for pagination
    /// @return _tokens Array of whitelisted tokens
    function whitelistedTokens(uint256 _start, uint256 _end) external view returns (address[] memory _tokens);

    /// @notice Check if a given token is whitelisted
    /// @param _token The address of the token to be checked
    /// @return Whether the token is whitelisted or not
    function isWhitelistedToken(address _token) external view returns (bool);

    /// @notice Get the length of the whitelistedTokens array
    function whitelistedTokensLength() external view returns (uint256);

    /// @notice Create a new gauge
    /// @dev Only callable by Message Bridge
    /// @param _poolFactory .
    /// @param _pool .
    /// @param _votingRewardsFactory .
    /// @param _gaugeFactory .
    function createGauge(address _poolFactory, address _pool, address _votingRewardsFactory, address _gaugeFactory)
        external
        returns (address _gauge);

    /// @notice Kills a gauge. The gauge will not receive any new emissions and cannot be deposited into.
    ///         Can still withdraw from gauge.
    /// @dev Only callable by Message Bridge
    ///      Throws if gauge already killed.
    /// @param _gauge .
    function killGauge(address _gauge) external;

    /// @notice Revives a killed gauge. Gauge will be able to receive emissions and deposits again.
    /// @dev Only callable by Message Bridge
    ///      Throws if gauge is not killed.
    /// @param _gauge .
    function reviveGauge(address _gauge) external;

    /// @notice Claim emissions from gauges.
    /// @param _gauges Array of gauges to collect emissions from.
    function claimRewards(address[] memory _gauges) external;
}

Settings
{
  "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/",
    "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": "cancun",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_bridge","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"GaugeAlreadyKilled","type":"error"},{"inputs":[],"name":"GaugeAlreadyRevived","type":"error"},{"inputs":[],"name":"NotAGauge","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"poolFactory","type":"address"},{"indexed":true,"internalType":"address","name":"votingRewardsFactory","type":"address"},{"indexed":true,"internalType":"address","name":"gaugeFactory","type":"address"},{"indexed":false,"internalType":"address","name":"pool","type":"address"},{"indexed":false,"internalType":"address","name":"incentiveVotingReward","type":"address"},{"indexed":false,"internalType":"address","name":"feeVotingReward","type":"address"},{"indexed":false,"internalType":"address","name":"gauge","type":"address"}],"name":"GaugeCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"}],"name":"GaugeKilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"gauge","type":"address"}],"name":"GaugeRevived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"bool","name":"_bool","type":"bool"}],"name":"WhitelistToken","type":"event"},{"inputs":[],"name":"bridge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_gauges","type":"address[]"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_poolFactory","type":"address"},{"internalType":"address","name":"_pool","type":"address"},{"internalType":"address","name":"_votingRewardsFactory","type":"address"},{"internalType":"address","name":"_gaugeFactory","type":"address"}],"name":"createGauge","outputs":[{"internalType":"address","name":"_gauge","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gaugeToFees","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gaugeToIncentive","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gauges","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAlive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isGauge","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"isWhitelistedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"killGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolForGauge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pools","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_gauge","type":"address"}],"name":"reviveGauge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistTokenCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistedTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_start","type":"uint256"},{"internalType":"uint256","name":"_end","type":"uint256"}],"name":"whitelistedTokens","outputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistedTokensLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

60a060405234801561000f575f5ffd5b506040516113b53803806113b583398101604081905261002e91610043565b60015f556001600160a01b0316608052610070565b5f60208284031215610053575f5ffd5b81516001600160a01b0381168114610069575f5ffd5b9392505050565b60805161131861009d5f395f81816102bf01528181610401015281816105c2015261080401526113185ff3fe608060405234801561000f575f5ffd5b5060043610610106575f3560e01c8063aa79979b1161009e578063ba9225f71161006e578063ba9225f71461027f578063c4f0816514610292578063e78cea92146102ba578063f7e48c98146102e1578063f9f031df14610300575f5ffd5b8063aa79979b1461020f578063ab37f48614610231578063ac4afa3814610244578063b9a09fd514610257575f5ffd5b80635e1762a0116100d95780635e1762a0146101bf57806375019547146101d4578063992a7933146101e75780639f06247b146101fc575f5ffd5b806306d6a1b21461010a5780631703e5f91461014f5780631e541e44146101815780633231cfee14610197575b5f5ffd5b61013261011836600461100c565b60036020525f90815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61017161015d36600461100c565b60076020525f908152604090205460ff1681565b6040519015158152602001610146565b610189610313565b604051908152602001610146565b6101326101a536600461100c565b60056020525f90815260409020546001600160a01b031681565b6101c7610323565b6040516101469190611027565b6101c76101e2366004611072565b61032f565b6101fa6101f536600461100c565b6103ff565b005b6101fa61020a36600461100c565b6105c0565b61017161021d36600461100c565b60066020525f908152604090205460ff1681565b61017161023f36600461100c565b6107bf565b610132610252366004611092565b6107d1565b61013261026536600461100c565b60026020525f90815260409020546001600160a01b031681565b61013261028d3660046110a9565b6107f9565b6101326102a036600461100c565b60046020525f90815260409020546001600160a01b031681565b6101327f000000000000000000000000000000000000000000000000000000000000000081565b6101896102ef36600461100c565b60086020525f908152604090205481565b6101fa61030e366004611116565b610c4f565b5f61031e6009610cde565b905090565b606061031e6009610ce7565b60605f61033c6009610cde565b905080831061034b578061034d565b825b925061035984846111f5565b67ffffffffffffffff81111561037157610371611102565b60405190808252806020026020018201604052801561039a578160200160208202803683370190505b5091505f5b6103a985856111f5565b8110156103f7576103c56103bd8683611208565b600990610cfa565b8382815181106103d7576103d761121b565b6001600160a01b039092166020928302919091019091015260010161039f565b505092915050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b86d52986040518163ffffffff1660e01b8152600401602060405180830381865afa15801561045b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061047f919061122f565b6001600160a01b0316336001600160a01b0316146104b05760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f9081526007602052604090205460ff166104e857604051633f88da5160e21b815260040160405180910390fd5b6001600160a01b038082165f908152600760209081526040808320805460ff191690556003909152808220548151634eb1c24560e11b8152825193948594921692639d63848a926004808401938290030181865afa15801561054c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610570919061124a565b9150915061057e825f610d05565b610588815f610d05565b6040516001600160a01b038416907f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba7905f90a2505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b86d52986040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610640919061122f565b6001600160a01b0316336001600160a01b0316146106715760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f9081526006602052604090205460ff166106a957604051634753c19760e01b815260040160405180910390fd5b6001600160a01b0381165f9081526007602052604090205460ff16156106e257604051635f5a482960e11b815260040160405180910390fd5b6001600160a01b038082165f908152600760209081526040808320805460ff191660011790556003909152808220548151634eb1c24560e11b8152825193948594921692639d63848a926004808401938290030181865afa158015610749573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061076d919061124a565b9150915061077c826001610d05565b610787816001610d05565b6040516001600160a01b038416907fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa905f90a2505050565b5f6107cb600983610dc6565b92915050565b600181815481106107e0575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f610802610de7565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b86d52986040518163ffffffff1660e01b8152600401602060405180830381865afa15801561085e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610882919061122f565b6001600160a01b0316336001600160a01b0316146108b35760405163ea8e4eb560e01b815260040160405180910390fd5b6040805160028082526060820183525f92602083019080368337019050509050846001600160a01b0316639d63848a6040518163ffffffff1660e01b81526004016040805180830381865afa15801561090e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610932919061124a565b825f815181106109445761094461121b565b602002602001018360018151811061095e5761095e61121b565b6001600160a01b03938416602091820292909201015291811690915260405163887a425760e01b81525f9182919087169063887a4257906109a3908690600401611027565b60408051808303815f875af11580156109be573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e2919061124a565b604051635b16ebb760e01b81526001600160a01b038a811660048301529294509092508187169163b30b6568918a918691908d1690635b16ebb790602401602060405180830381865afa158015610a3b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a5f9190611282565b6040516001600160e01b031960e086901b1681526001600160a01b039384166004820152929091166024830152151560448201526064016020604051808303815f875af1158015610ab2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad6919061122f565b6001600160a01b038181165f81815260046020908152604080832080546001600160a01b03199081168a8816179091556005835281842080548216898816179055948d1680845260028352818420805487168617905593835260038252808320805486168517905560068252808320805460ff199081166001908117909255600790935290832080549092168117909155805480820182559082527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180549093169091179091558451919550610bc591859190610bb657610bb661121b565b60200260200101516001610d05565b610bdb83600181518110610bb657610bb661121b565b604080516001600160a01b038981168252838116602083015284811682840152868116606083015291518783169289811692908c16917f3420db1b33ca18e4323a00a7c63a9bd16ceb7685aad2a46b734f3a3f73b42b869181900360800190a4505050610c4760015f55565b949350505050565b80515f5b81811015610cd957828181518110610c6d57610c6d61121b565b6020908102919091010151604051630c00007b60e41b81523360048201526001600160a01b039091169063c00007b0906024015f604051808303815f87803b158015610cb7575f5ffd5b505af1158015610cc9573d5f5f3e3d5ffd5b505060019092019150610c539050565b505050565b5f6107cb825490565b60605f610cf383610e0f565b9392505050565b5f610cf38383610e68565b8015610d4e576001600160a01b0382165f9081526008602052604081208054909190610d30906112a1565b9182905550600103610d4957610d47600983610e8e565b505b610d8b565b6001600160a01b0382165f9081526008602052604081208054909190610d73906112b9565b91829055505f03610d8b57610d89600983610ea2565b505b604051811515906001600160a01b038416907f06a27d2e85b249c0d83da8b892fb8e69167e1319fb3bb86f860b245f9e0d729f905f90a35050565b6001600160a01b0381165f9081526001830160205260408120541515610cf3565b60025f5403610e0957604051633ee5aeb560e01b815260040160405180910390fd5b60025f55565b6060815f01805480602002602001604051908101604052809291908181526020018280548015610e5c57602002820191905f5260205f20905b815481526020019060010190808311610e48575b50505050509050919050565b5f825f018281548110610e7d57610e7d61121b565b905f5260205f200154905092915050565b5f610cf3836001600160a01b038416610eb6565b5f610cf3836001600160a01b038416610f02565b5f818152600183016020526040812054610efb57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556107cb565b505f6107cb565b5f8181526001830160205260408120548015610fdc575f610f246001836111f5565b85549091505f90610f37906001906111f5565b9050808214610f96575f865f018281548110610f5557610f5561121b565b905f5260205f200154905080875f018481548110610f7557610f7561121b565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080610fa757610fa76112ce565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506107cb565b5f9150506107cb565b6001600160a01b0381168114610ff9575f5ffd5b50565b803561100781610fe5565b919050565b5f6020828403121561101c575f5ffd5b8135610cf381610fe5565b602080825282518282018190525f918401906040840190835b818110156110675783516001600160a01b0316835260209384019390920191600101611040565b509095945050505050565b5f5f60408385031215611083575f5ffd5b50508035926020909101359150565b5f602082840312156110a2575f5ffd5b5035919050565b5f5f5f5f608085870312156110bc575f5ffd5b84356110c781610fe5565b935060208501356110d781610fe5565b925060408501356110e781610fe5565b915060608501356110f781610fe5565b939692955090935050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611126575f5ffd5b813567ffffffffffffffff81111561113c575f5ffd5b8201601f8101841361114c575f5ffd5b803567ffffffffffffffff81111561116657611166611102565b8060051b604051601f19603f830116810181811067ffffffffffffffff8211171561119357611193611102565b6040529182526020818401810192908101878411156111b0575f5ffd5b6020850194505b838510156111d6576111c885610ffc565b8152602094850194016111b7565b509695505050505050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156107cb576107cb6111e1565b808201808211156107cb576107cb6111e1565b634e487b7160e01b5f52603260045260245ffd5b5f6020828403121561123f575f5ffd5b8151610cf381610fe5565b5f5f6040838503121561125b575f5ffd5b825161126681610fe5565b602084015190925061127781610fe5565b809150509250929050565b5f60208284031215611292575f5ffd5b81518015158114610cf3575f5ffd5b5f600182016112b2576112b26111e1565b5060010190565b5f816112c7576112c76111e1565b505f190190565b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220438f507c76a9d5c77d840c7d121b2e66979f77f181dcc05d3888c58fd9046d1964736f6c634300081b0033000000000000000000000000f278761576f45472bdd721eaca19317ce159c011

Deployed Bytecode

0x608060405234801561000f575f5ffd5b5060043610610106575f3560e01c8063aa79979b1161009e578063ba9225f71161006e578063ba9225f71461027f578063c4f0816514610292578063e78cea92146102ba578063f7e48c98146102e1578063f9f031df14610300575f5ffd5b8063aa79979b1461020f578063ab37f48614610231578063ac4afa3814610244578063b9a09fd514610257575f5ffd5b80635e1762a0116100d95780635e1762a0146101bf57806375019547146101d4578063992a7933146101e75780639f06247b146101fc575f5ffd5b806306d6a1b21461010a5780631703e5f91461014f5780631e541e44146101815780633231cfee14610197575b5f5ffd5b61013261011836600461100c565b60036020525f90815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61017161015d36600461100c565b60076020525f908152604090205460ff1681565b6040519015158152602001610146565b610189610313565b604051908152602001610146565b6101326101a536600461100c565b60056020525f90815260409020546001600160a01b031681565b6101c7610323565b6040516101469190611027565b6101c76101e2366004611072565b61032f565b6101fa6101f536600461100c565b6103ff565b005b6101fa61020a36600461100c565b6105c0565b61017161021d36600461100c565b60066020525f908152604090205460ff1681565b61017161023f36600461100c565b6107bf565b610132610252366004611092565b6107d1565b61013261026536600461100c565b60026020525f90815260409020546001600160a01b031681565b61013261028d3660046110a9565b6107f9565b6101326102a036600461100c565b60046020525f90815260409020546001600160a01b031681565b6101327f000000000000000000000000f278761576f45472bdd721eaca19317ce159c01181565b6101896102ef36600461100c565b60086020525f908152604090205481565b6101fa61030e366004611116565b610c4f565b5f61031e6009610cde565b905090565b606061031e6009610ce7565b60605f61033c6009610cde565b905080831061034b578061034d565b825b925061035984846111f5565b67ffffffffffffffff81111561037157610371611102565b60405190808252806020026020018201604052801561039a578160200160208202803683370190505b5091505f5b6103a985856111f5565b8110156103f7576103c56103bd8683611208565b600990610cfa565b8382815181106103d7576103d761121b565b6001600160a01b039092166020928302919091019091015260010161039f565b505092915050565b7f000000000000000000000000f278761576f45472bdd721eaca19317ce159c0116001600160a01b031663b86d52986040518163ffffffff1660e01b8152600401602060405180830381865afa15801561045b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061047f919061122f565b6001600160a01b0316336001600160a01b0316146104b05760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f9081526007602052604090205460ff166104e857604051633f88da5160e21b815260040160405180910390fd5b6001600160a01b038082165f908152600760209081526040808320805460ff191690556003909152808220548151634eb1c24560e11b8152825193948594921692639d63848a926004808401938290030181865afa15801561054c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610570919061124a565b9150915061057e825f610d05565b610588815f610d05565b6040516001600160a01b038416907f04a5d3f5d80d22d9345acc80618f4a4e7e663cf9e1aed23b57d975acec002ba7905f90a2505050565b7f000000000000000000000000f278761576f45472bdd721eaca19317ce159c0116001600160a01b031663b86d52986040518163ffffffff1660e01b8152600401602060405180830381865afa15801561061c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610640919061122f565b6001600160a01b0316336001600160a01b0316146106715760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f9081526006602052604090205460ff166106a957604051634753c19760e01b815260040160405180910390fd5b6001600160a01b0381165f9081526007602052604090205460ff16156106e257604051635f5a482960e11b815260040160405180910390fd5b6001600160a01b038082165f908152600760209081526040808320805460ff191660011790556003909152808220548151634eb1c24560e11b8152825193948594921692639d63848a926004808401938290030181865afa158015610749573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061076d919061124a565b9150915061077c826001610d05565b610787816001610d05565b6040516001600160a01b038416907fed18e9faa3dccfd8aa45f69c4de40546b2ca9cccc4538a2323531656516db1aa905f90a2505050565b5f6107cb600983610dc6565b92915050565b600181815481106107e0575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f610802610de7565b7f000000000000000000000000f278761576f45472bdd721eaca19317ce159c0116001600160a01b031663b86d52986040518163ffffffff1660e01b8152600401602060405180830381865afa15801561085e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610882919061122f565b6001600160a01b0316336001600160a01b0316146108b35760405163ea8e4eb560e01b815260040160405180910390fd5b6040805160028082526060820183525f92602083019080368337019050509050846001600160a01b0316639d63848a6040518163ffffffff1660e01b81526004016040805180830381865afa15801561090e573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610932919061124a565b825f815181106109445761094461121b565b602002602001018360018151811061095e5761095e61121b565b6001600160a01b03938416602091820292909201015291811690915260405163887a425760e01b81525f9182919087169063887a4257906109a3908690600401611027565b60408051808303815f875af11580156109be573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e2919061124a565b604051635b16ebb760e01b81526001600160a01b038a811660048301529294509092508187169163b30b6568918a918691908d1690635b16ebb790602401602060405180830381865afa158015610a3b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a5f9190611282565b6040516001600160e01b031960e086901b1681526001600160a01b039384166004820152929091166024830152151560448201526064016020604051808303815f875af1158015610ab2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ad6919061122f565b6001600160a01b038181165f81815260046020908152604080832080546001600160a01b03199081168a8816179091556005835281842080548216898816179055948d1680845260028352818420805487168617905593835260038252808320805486168517905560068252808320805460ff199081166001908117909255600790935290832080549092168117909155805480820182559082527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180549093169091179091558451919550610bc591859190610bb657610bb661121b565b60200260200101516001610d05565b610bdb83600181518110610bb657610bb661121b565b604080516001600160a01b038981168252838116602083015284811682840152868116606083015291518783169289811692908c16917f3420db1b33ca18e4323a00a7c63a9bd16ceb7685aad2a46b734f3a3f73b42b869181900360800190a4505050610c4760015f55565b949350505050565b80515f5b81811015610cd957828181518110610c6d57610c6d61121b565b6020908102919091010151604051630c00007b60e41b81523360048201526001600160a01b039091169063c00007b0906024015f604051808303815f87803b158015610cb7575f5ffd5b505af1158015610cc9573d5f5f3e3d5ffd5b505060019092019150610c539050565b505050565b5f6107cb825490565b60605f610cf383610e0f565b9392505050565b5f610cf38383610e68565b8015610d4e576001600160a01b0382165f9081526008602052604081208054909190610d30906112a1565b9182905550600103610d4957610d47600983610e8e565b505b610d8b565b6001600160a01b0382165f9081526008602052604081208054909190610d73906112b9565b91829055505f03610d8b57610d89600983610ea2565b505b604051811515906001600160a01b038416907f06a27d2e85b249c0d83da8b892fb8e69167e1319fb3bb86f860b245f9e0d729f905f90a35050565b6001600160a01b0381165f9081526001830160205260408120541515610cf3565b60025f5403610e0957604051633ee5aeb560e01b815260040160405180910390fd5b60025f55565b6060815f01805480602002602001604051908101604052809291908181526020018280548015610e5c57602002820191905f5260205f20905b815481526020019060010190808311610e48575b50505050509050919050565b5f825f018281548110610e7d57610e7d61121b565b905f5260205f200154905092915050565b5f610cf3836001600160a01b038416610eb6565b5f610cf3836001600160a01b038416610f02565b5f818152600183016020526040812054610efb57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556107cb565b505f6107cb565b5f8181526001830160205260408120548015610fdc575f610f246001836111f5565b85549091505f90610f37906001906111f5565b9050808214610f96575f865f018281548110610f5557610f5561121b565b905f5260205f200154905080875f018481548110610f7557610f7561121b565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080610fa757610fa76112ce565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506107cb565b5f9150506107cb565b6001600160a01b0381168114610ff9575f5ffd5b50565b803561100781610fe5565b919050565b5f6020828403121561101c575f5ffd5b8135610cf381610fe5565b602080825282518282018190525f918401906040840190835b818110156110675783516001600160a01b0316835260209384019390920191600101611040565b509095945050505050565b5f5f60408385031215611083575f5ffd5b50508035926020909101359150565b5f602082840312156110a2575f5ffd5b5035919050565b5f5f5f5f608085870312156110bc575f5ffd5b84356110c781610fe5565b935060208501356110d781610fe5565b925060408501356110e781610fe5565b915060608501356110f781610fe5565b939692955090935050565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611126575f5ffd5b813567ffffffffffffffff81111561113c575f5ffd5b8201601f8101841361114c575f5ffd5b803567ffffffffffffffff81111561116657611166611102565b8060051b604051601f19603f830116810181811067ffffffffffffffff8211171561119357611193611102565b6040529182526020818401810192908101878411156111b0575f5ffd5b6020850194505b838510156111d6576111c885610ffc565b8152602094850194016111b7565b509695505050505050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156107cb576107cb6111e1565b808201808211156107cb576107cb6111e1565b634e487b7160e01b5f52603260045260245ffd5b5f6020828403121561123f575f5ffd5b8151610cf381610fe5565b5f5f6040838503121561125b575f5ffd5b825161126681610fe5565b602084015190925061127781610fe5565b809150509250929050565b5f60208284031215611292575f5ffd5b81518015158114610cf3575f5ffd5b5f600182016112b2576112b26111e1565b5060010190565b5f816112c7576112c76111e1565b505f190190565b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220438f507c76a9d5c77d840c7d121b2e66979f77f181dcc05d3888c58fd9046d1964736f6c634300081b0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000f278761576f45472bdd721eaca19317ce159c011

-----Decoded View---------------
Arg [0] : _bridge (address): 0xF278761576f45472bdD721EACA19317cE159c011

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000f278761576f45472bdd721eaca19317ce159c011


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.