Sepolia Testnet

Contract

0xb0C1b6f0eFA6bDFFA958fC65bdC0bBD74E3d66aD

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To

There are no matching entries

9 Internal Transactions found.

Latest 9 internal transactions

Advanced mode:
Parent Transaction Hash Block
From
To
63570922024-07-22 16:32:12181 days ago1721665932
0xb0C1b6f0...74E3d66aD
0 ETH
63570322024-07-22 16:16:48181 days ago1721665008
0xb0C1b6f0...74E3d66aD
0 ETH
60046502024-05-30 5:04:48235 days ago1717045488
0xb0C1b6f0...74E3d66aD
0 ETH
59595952024-05-23 5:57:00242 days ago1716443820
0xb0C1b6f0...74E3d66aD
0 ETH
59595942024-05-23 5:56:48242 days ago1716443808
0xb0C1b6f0...74E3d66aD
0 ETH
59595902024-05-23 5:56:00242 days ago1716443760
0xb0C1b6f0...74E3d66aD
0 ETH
59595902024-05-23 5:56:00242 days ago1716443760
0xb0C1b6f0...74E3d66aD
0 ETH
59595822024-05-23 5:54:24242 days ago1716443664
0xb0C1b6f0...74E3d66aD
0 ETH
59595812024-05-23 5:54:12242 days ago1716443652
0xb0C1b6f0...74E3d66aD
0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PerpRewardDistributor

Compiler Version
v0.8.22+commit.4fc1097e

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 18 : PerpRewardDistributor.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

import {IRewardDistributor} from "@synthetixio/main/contracts/interfaces/external/IRewardDistributor.sol";
import {IPoolModule} from "@synthetixio/main/contracts/interfaces/IPoolModule.sol";
import {IRewardsManagerModule} from "@synthetixio/main/contracts/interfaces/IRewardsManagerModule.sol";
import {IERC165} from "@synthetixio/core-contracts/contracts/interfaces/IERC165.sol";
import {AccessError} from "@synthetixio/core-contracts/contracts/errors/AccessError.sol";
import {ParameterError} from "@synthetixio/core-contracts/contracts/errors/ParameterError.sol";
import {ERC20Helper} from "@synthetixio/core-contracts/contracts/token/ERC20Helper.sol";
import {ERC20} from "@synthetixio/core-contracts/contracts/token/ERC20.sol";
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import {IPerpRewardDistributor} from "../../interfaces/IPerpRewardDistributor.sol";

/* solhint-disable meta-transactions/no-msg-sender */

contract PerpRewardDistributor is Initializable, IPerpRewardDistributor {
    using ERC20Helper for address;

    /// @notice Address of the RewardManager (i.e. Synthetix core proxy)
    address private _rewardManager;
    /// @notice Address the BFP market proxy.
    address private _perpMarket;
    /// @notice Address of the reward token to distribute.
    address private _payoutToken;
    /// @notice User defined name of this reward distributor.
    string private _name;
    /// @notice Pool this distributor is registered against.
    uint128 private _poolId;
    /// @notice Delegated pool collateral addresses at the point of distributor init.
    address[] private _poolCollateralTypes;
    /// @notice Internal counter to track distributed/payout reward tokens.
    uint256 private _rewardsAmount;
    /// @notice Flag to enable or disable payouts.
    bool public shouldFailPayout;

    constructor() {
        _disableInitializers();
    }

    /// @inheritdoc IPerpRewardDistributor
    function initialize(
        address rewardManager,
        address perpMarket,
        uint128 poolId_,
        address[] calldata poolCollateralTypes_,
        address payoutToken_,
        string memory name_
    ) external initializer {
        _rewardManager = rewardManager; // CoreProxy
        _perpMarket = perpMarket;
        _poolId = poolId_;
        _poolCollateralTypes = poolCollateralTypes_;
        _payoutToken = payoutToken_;
        _name = name_;

        // Verify the `payoutToken` on init has exactly 18 decimals.
        (bool success, bytes memory data) = payoutToken_.staticcall(
            abi.encodeWithSignature("decimals()")
        );
        if (!success || data.length == 0 || abi.decode(data, (uint8)) != 18) {
            revert ParameterError.InvalidParameter(
                "payoutToken",
                "Token decimals expected to be 18"
            );
        }
    }

    /// @inheritdoc IPerpRewardDistributor
    function distributeRewards(address collateralType, uint256 amount) external {
        onlyPerpMarket();

        uint256 currentRewardsAmount = _rewardsAmount;
        uint256 nextRewardsAmount = currentRewardsAmount + amount;

        // NOTE: Caller must `payoutToken.transfer(address(this), amount)` before calling distributeRewards.
        uint256 balance = ERC20(_payoutToken).balanceOf(address(this));
        if (nextRewardsAmount > balance) {
            revert InsufficientRewardBalance(amount, balance);
        }

        _rewardsAmount = nextRewardsAmount;

        IRewardsManagerModule(_rewardManager).distributeRewards(
            _poolId,
            collateralType,
            amount,
            // solhint-disable-next-line numcast/safe-cast
            uint64(block.timestamp),
            0
        );
    }

    /// @inheritdoc IPerpRewardDistributor
    function getPoolId() external view returns (uint128) {
        return _poolId;
    }

    /// @inheritdoc IPerpRewardDistributor
    function getPoolCollateralTypes() external view returns (address[] memory) {
        return _poolCollateralTypes;
    }

    /// @inheritdoc IPerpRewardDistributor
    function setShouldFailPayout(bool _shouldFailedPayout) external {
        onlyPoolOwner();
        shouldFailPayout = _shouldFailedPayout;
    }

    // --- IRewardDistributor requirements --- //

    /// @inheritdoc IRewardDistributor
    function name() public view override returns (string memory) {
        return _name;
    }

    /// @inheritdoc IRewardDistributor
    function token() public view override returns (address) {
        return _payoutToken;
    }

    /// @inheritdoc IRewardDistributor
    function payout(
        uint128,
        uint128 poolId,
        address,
        address payoutTarget_, // msg.sender that called `claimRewards`
        uint256 payoutAmount_
    ) external returns (bool) {
        if (shouldFailPayout) {
            return false;
        }
        if (poolId != _poolId) {
            revert ParameterError.InvalidParameter("poolId", "Unexpected poolId");
        }

        onlyRewardManager();

        uint256 currentRewardsAmount = _rewardsAmount;
        if (payoutAmount_ > currentRewardsAmount) {
            revert InsufficientRewardBalance(payoutAmount_, currentRewardsAmount);
        }
        _rewardsAmount = currentRewardsAmount - payoutAmount_;
        _payoutToken.safeTransfer(payoutTarget_, payoutAmount_);

        return true;
    }

    /// @inheritdoc IRewardDistributor
    function onPositionUpdated(uint128, uint128, address, uint256) external pure {}

    /// @inheritdoc IERC165
    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override(IERC165) returns (bool) {
        return
            interfaceId == type(IRewardDistributor).interfaceId ||
            interfaceId == this.supportsInterface.selector;
    }

    // --- Helpers --- //

    /// @dev Throws `Unauthorized` when msg.sender is not the PerpMarketProxy.
    function onlyPerpMarket() private view {
        if (msg.sender != _perpMarket) {
            revert AccessError.Unauthorized(msg.sender);
        }
    }

    /// @dev Throws `Unauthorized` when msg.sender is not the RewardManagerProxy.
    function onlyRewardManager() private view {
        if (msg.sender != _rewardManager) {
            revert AccessError.Unauthorized(msg.sender);
        }
    }

    /// @dev Throws `Unauthorized` when msg.sender is not the `poolId` pool owner.
    function onlyPoolOwner() private view {
        if (msg.sender != IPoolModule(_rewardManager).getPoolOwner(_poolId)) {
            revert AccessError.Unauthorized(msg.sender);
        }
    }
}

File 2 of 18 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.2;

import "../../utils/Address.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     * @custom:oz-retyped-from bool
     */
    uint8 private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint8 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
     * constructor.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        bool isTopLevelCall = !_initializing;
        require(
            (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),
            "Initializable: contract is already initialized"
        );
        _initialized = 1;
        if (isTopLevelCall) {
            _initializing = true;
        }
        _;
        if (isTopLevelCall) {
            _initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: setting the version to 255 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint8 version) {
        require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
        _initialized = version;
        _initializing = true;
        _;
        _initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        require(!_initializing, "Initializable: contract is initializing");
        if (_initialized != type(uint8).max) {
            _initialized = type(uint8).max;
            emit Initialized(type(uint8).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint8) {
        return _initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _initializing;
    }
}

File 3 of 18 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 4 of 18 : AccessError.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

/**
 * @title Library for access related errors.
 */
library AccessError {
    /**
     * @dev Thrown when an address tries to perform an unauthorized action.
     * @param addr The address that attempts the action.
     */
    error Unauthorized(address addr);
}

File 5 of 18 : InitError.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

/**
 * @title Library for initialization related errors.
 */
library InitError {
    /**
     * @dev Thrown when attempting to initialize a contract that is already initialized.
     */
    error AlreadyInitialized();

    /**
     * @dev Thrown when attempting to interact with a contract that has not been initialized yet.
     */
    error NotInitialized();
}

File 6 of 18 : ParameterError.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

/**
 * @title Library for errors related with expected function parameters.
 */
library ParameterError {
    /**
     * @dev Thrown when an invalid parameter is used in a function.
     * @param parameter The name of the parameter.
     * @param reason The reason why the received parameter is invalid.
     */
    error InvalidParameter(string parameter, string reason);
}

File 7 of 18 : IERC165.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

/**
 * @title ERC165 interface for determining if a contract supports a given interface.
 */
interface IERC165 {
    /**
     * @notice Determines if the contract in question supports the specified interface.
     * @param interfaceID XOR of all selectors in the contract.
     * @return True if the contract supports the specified interface.
     */
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

File 8 of 18 : IERC20.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

/**
 * @title ERC20 token implementation.
 */
interface IERC20 {
    /**
     * @notice Emitted when tokens have been transferred.
     * @param from The address that originally owned the tokens.
     * @param to The address that received the tokens.
     * @param amount The number of tokens that were transferred.
     */
    event Transfer(address indexed from, address indexed to, uint256 amount);

    /**
     * @notice Emitted when a user has provided allowance to another user for transferring tokens on its behalf.
     * @param owner The address that is providing the allowance.
     * @param spender The address that received the allowance.
     * @param amount The number of tokens that were added to `spender`'s allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /**
     * @notice Thrown when the address interacting with the contract does not have sufficient allowance to transfer tokens from another contract.
     * @param required The necessary allowance.
     * @param existing The current allowance.
     */
    error InsufficientAllowance(uint256 required, uint256 existing);

    /**
     * @notice Thrown when the address interacting with the contract does not have sufficient tokens.
     * @param required The necessary balance.
     * @param existing The current balance.
     */
    error InsufficientBalance(uint256 required, uint256 existing);

    /**
     * @notice Retrieves the name of the token, e.g. "Synthetix Network Token".
     * @return A string with the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @notice Retrieves the symbol of the token, e.g. "SNX".
     * @return A string with the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @notice Retrieves the number of decimals used by the token. The default is 18.
     * @return The number of decimals.
     */
    function decimals() external view returns (uint8);

    /**
     * @notice Returns the total number of tokens in circulation (minted - burnt).
     * @return The total number of tokens.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @notice Returns the balance of a user.
     * @param owner The address whose balance is being retrieved.
     * @return The number of tokens owned by the user.
     */
    function balanceOf(address owner) external view returns (uint256);

    /**
     * @notice Returns how many tokens a user has allowed another user to transfer on its behalf.
     * @param owner The user who has given the allowance.
     * @param spender The user who was given the allowance.
     * @return The amount of tokens `spender` can transfer on `owner`'s behalf.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @notice Transfer tokens from one address to another.
     * @param to The address that will receive the tokens.
     * @param amount The amount of tokens to be transferred.
     * @return A boolean which is true if the operation succeeded.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @notice Allows users to provide allowance to other users so that they can transfer tokens on their behalf.
     * @param spender The address that is receiving the allowance.
     * @param amount The amount of tokens that are being added to the allowance.
     * @return A boolean which is true if the operation succeeded.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @notice Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) external returns (bool);

    /**
     * @notice Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);

    /**
     * @notice Allows a user who has been given allowance to transfer tokens on another user's behalf.
     * @param from The address that owns the tokens that are being transferred.
     * @param to The address that will receive the tokens.
     * @param amount The number of tokens to transfer.
     * @return A boolean which is true if the operation succeeded.
     */
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

File 9 of 18 : ERC20.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

import "../utils/ERC2771Context.sol";
import "../interfaces/IERC20.sol";
import "../errors/InitError.sol";
import "../errors/ParameterError.sol";
import "./ERC20Storage.sol";

/*
 * @title ERC20 token implementation.
 * See IERC20.
 *
 * Reference implementations:
 * - OpenZeppelin - https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol
 * - Rari-Capital - https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol
 */
contract ERC20 is IERC20 {
    /**
     * @inheritdoc IERC20
     */
    function name() external view override returns (string memory) {
        return ERC20Storage.load().name;
    }

    /**
     * @inheritdoc IERC20
     */
    function symbol() external view override returns (string memory) {
        return ERC20Storage.load().symbol;
    }

    /**
     * @inheritdoc IERC20
     */
    function decimals() external view override returns (uint8) {
        return ERC20Storage.load().decimals;
    }

    /**
     * @inheritdoc IERC20
     */
    function totalSupply() external view virtual override returns (uint256) {
        return ERC20Storage.load().totalSupply;
    }

    /**
     * @inheritdoc IERC20
     */
    function allowance(
        address owner,
        address spender
    ) public view virtual override returns (uint256) {
        return ERC20Storage.load().allowance[owner][spender];
    }

    /**
     * @inheritdoc IERC20
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        return ERC20Storage.load().balanceOf[owner];
    }

    /**
     * @inheritdoc IERC20
     */

    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(ERC2771Context._msgSender(), spender, amount);
        return true;
    }

    /**
     * @inheritdoc IERC20
     */

    function increaseAllowance(
        address spender,
        uint256 addedValue
    ) public virtual override returns (bool) {
        uint256 currentAllowance = ERC20Storage.load().allowance[ERC2771Context._msgSender()][
            spender
        ];
        _approve(ERC2771Context._msgSender(), spender, currentAllowance + addedValue);

        return true;
    }

    /**
     * @inheritdoc IERC20
     */

    function decreaseAllowance(
        address spender,
        uint256 subtractedValue
    ) public virtual override returns (bool) {
        uint256 currentAllowance = ERC20Storage.load().allowance[ERC2771Context._msgSender()][
            spender
        ];
        _approve(ERC2771Context._msgSender(), spender, currentAllowance - subtractedValue);

        return true;
    }

    /**
     * @inheritdoc IERC20
     */

    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        _transfer(ERC2771Context._msgSender(), to, amount);

        return true;
    }

    /**
     * @inheritdoc IERC20
     */

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external virtual override returns (bool) {
        return _transferFrom(from, to, amount);
    }

    function _transferFrom(
        address from,
        address to,
        uint256 amount
    ) internal virtual returns (bool) {
        ERC20Storage.Data storage store = ERC20Storage.load();

        uint256 currentAllowance = store.allowance[from][ERC2771Context._msgSender()];
        if (currentAllowance < amount) {
            revert InsufficientAllowance(amount, currentAllowance);
        }

        unchecked {
            store.allowance[from][ERC2771Context._msgSender()] -= amount;
        }

        _transfer(from, to, amount);

        return true;
    }

    function _transfer(address from, address to, uint256 amount) internal virtual {
        _checkZeroAddressOrAmount(to, amount);

        ERC20Storage.Data storage store = ERC20Storage.load();

        uint256 accountBalance = store.balanceOf[from];
        if (accountBalance < amount) {
            revert InsufficientBalance(amount, accountBalance);
        }

        // We are now sure that we can perform this operation safely
        // since it didn't revert in the previous step.
        // The total supply cannot exceed the maximum value of uint256,
        // thus we can now perform accounting operations in unchecked mode.
        unchecked {
            store.balanceOf[from] -= amount;
            store.balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);
    }

    function _approve(address owner, address spender, uint256 amount) internal virtual {
        _checkZeroAddress(spender);

        ERC20Storage.load().allowance[owner][spender] = amount;

        emit Approval(owner, spender, amount);
    }

    function _checkZeroAddressOrAmount(address target, uint256 amount) private pure {
        _checkZeroAddress(target);

        if (amount == 0) {
            revert ParameterError.InvalidParameter("amount", "Zero amount");
        }
    }

    function _checkZeroAddress(address target) private pure {
        if (target == address(0)) {
            revert ParameterError.InvalidParameter("target", "Zero address");
        }
    }

    function _mint(address to, uint256 amount) internal virtual {
        _checkZeroAddressOrAmount(to, amount);

        ERC20Storage.Data storage store = ERC20Storage.load();

        store.totalSupply += amount;

        // No need for overflow check since it is done in the previous step
        unchecked {
            store.balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        _checkZeroAddressOrAmount(from, amount);

        ERC20Storage.Data storage store = ERC20Storage.load();

        uint256 accountBalance = store.balanceOf[from];
        if (accountBalance < amount) {
            revert InsufficientBalance(amount, accountBalance);
        }

        // No need for underflow check since it would have occurred in the previous step
        unchecked {
            store.balanceOf[from] -= amount;
            store.totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }

    function _initialize(
        string memory tokenName,
        string memory tokenSymbol,
        uint8 tokenDecimals
    ) internal virtual {
        ERC20Storage.Data storage store = ERC20Storage.load();

        if (bytes(tokenName).length == 0 || bytes(tokenSymbol).length == 0 || tokenDecimals == 0) {
            revert ParameterError.InvalidParameter(
                "tokenName|tokenSymbol|tokenDecimals",
                "At least one is zero"
            );
        }

        //If decimals is already initialized, it can not change
        if (store.decimals != 0 && tokenDecimals != store.decimals) {
            revert InitError.AlreadyInitialized();
        }

        store.name = tokenName;
        store.symbol = tokenSymbol;
        store.decimals = tokenDecimals;
    }
}

File 10 of 18 : ERC20Helper.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

import "../interfaces/IERC20.sol";

library ERC20Helper {
    error FailedTransfer(address from, address to, uint256 value);

    function safeTransfer(address token, address to, uint256 value) internal {
        (bool success, bytes memory data) = token.call(
            abi.encodeWithSelector(IERC20.transfer.selector, to, value)
        );
        if (!success || (data.length != 0 && !abi.decode(data, (bool)))) {
            revert FailedTransfer(address(this), to, value);
        }
    }

    function safeTransferFrom(address token, address from, address to, uint256 value) internal {
        (bool success, bytes memory data) = token.call(
            abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value)
        );
        if (!success || (data.length != 0 && !abi.decode(data, (bool)))) {
            revert FailedTransfer(from, to, value);
        }
    }
}

File 11 of 18 : ERC20Storage.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

library ERC20Storage {
    bytes32 private constant _SLOT_ERC20_STORAGE =
        keccak256(abi.encode("io.synthetix.core-contracts.ERC20"));

    struct Data {
        string name;
        string symbol;
        uint8 decimals;
        mapping(address => uint256) balanceOf;
        mapping(address => mapping(address => uint256)) allowance;
        uint256 totalSupply;
    }

    function load() internal pure returns (Data storage store) {
        bytes32 s = _SLOT_ERC20_STORAGE;
        assembly {
            store.slot := s
        }
    }
}

File 12 of 18 : ERC2771Context.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/* solhint-disable meta-transactions/no-msg-sender */
/* solhint-disable meta-transactions/no-msg-data */

library ERC2771Context {
    // This is the trusted-multicall-forwarder. The address is constant due to CREATE2.
    address private constant TRUSTED_FORWARDER = 0xE2C5658cC5C448B48141168f3e475dF8f65A1e3e;

    function _msgSender() internal view returns (address sender) {
        if (isTrustedForwarder(msg.sender) && msg.data.length >= 20) {
            // The assembly code is more direct than the Solidity version using `abi.decode`.
            /// @solidity memory-safe-assembly
            assembly {
                sender := shr(96, calldataload(sub(calldatasize(), 20)))
            }
        } else {
            return msg.sender;
        }
    }

    function _msgData() internal view returns (bytes calldata) {
        if (isTrustedForwarder(msg.sender) && msg.data.length >= 20) {
            return msg.data[:msg.data.length - 20];
        } else {
            return msg.data;
        }
    }

    function isTrustedForwarder(address forwarder) internal pure returns (bool) {
        return forwarder == TRUSTED_FORWARDER;
    }

    function trustedForwarder() internal pure returns (address) {
        return TRUSTED_FORWARDER;
    }
}

File 13 of 18 : IRewardDistributor.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

import "@synthetixio/core-contracts/contracts/interfaces/IERC165.sol";

/// @title Interface a reward distributor.
interface IRewardDistributor is IERC165 {
    /// @notice Returns a human-readable name for the reward distributor
    function name() external view returns (string memory);

    /// @notice This function should revert if ERC2771Context._msgSender() is not the Synthetix CoreProxy address.
    /// @return whether or not the payout was executed
    function payout(
        uint128 accountId,
        uint128 poolId,
        address collateralType,
        address sender,
        uint256 amount
    ) external returns (bool);

    /// @notice This function is called by the Synthetix Core Proxy whenever
    /// a position is updated on a pool which this distributor is registered
    function onPositionUpdated(
        uint128 accountId,
        uint128 poolId,
        address collateralType,
        uint256 newShares
    ) external;

    /// @notice Address to ERC-20 token distributed by this distributor, for display purposes only
    /// @dev Return address(0) if providing non ERC-20 rewards
    function token() external view returns (address);
}

File 14 of 18 : IPoolModule.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

import "../storage/MarketConfiguration.sol";
import "../storage/PoolCollateralConfiguration.sol";

/**
 * @title Module for the creation and management of pools.
 * @dev The pool owner can be specified during creation, can be transferred, and has credentials for configuring the pool.
 */
interface IPoolModule {
    /**
     * @notice Thrown when attempting to disconnect a market whose capacity is locked, and whose removal would cause a decrease in its associated pool's credit delegation proportion.
     */
    error CapacityLocked(uint256 marketId);

    /**
     * @notice Gets fired when pool will be created.
     * @param poolId The id of the newly created pool.
     * @param owner The owner of the newly created pool.
     * @param sender The address that triggered the creation of the pool.
     */
    event PoolCreated(uint128 indexed poolId, address indexed owner, address indexed sender);

    /**
     * @notice Gets fired when pool owner proposes a new owner.
     * @param poolId The id of the pool for which the nomination ocurred.
     * @param nominatedOwner The address that was nominated as the new owner of the pool.
     * @param owner The address of the current owner of the pool.
     */
    event PoolOwnerNominated(
        uint128 indexed poolId,
        address indexed nominatedOwner,
        address indexed owner
    );

    /**
     * @notice Gets fired when pool nominee accepts nomination.
     * @param poolId The id of the pool for which the owner nomination was accepted.
     * @param owner The address of the new owner of the pool, which accepted the nomination.
     */
    event PoolOwnershipAccepted(uint128 indexed poolId, address indexed owner);

    /**
     * @notice Gets fired when pool owner revokes nomination.
     * @param poolId The id of the pool in which the nomination was revoked.
     * @param owner The current owner of the pool.
     */
    event PoolNominationRevoked(uint128 indexed poolId, address indexed owner);

    /**
     * @notice Gets fired when pool nominee renounces nomination.
     * @param poolId The id of the pool for which the owner nomination was renounced.
     * @param owner The current owner of the pool.
     */
    event PoolNominationRenounced(uint128 indexed poolId, address indexed owner);

    /**
     * @notice Gets fired when pool owner renounces his own ownership.
     * @param poolId The id of the pool for which the owner nomination was renounced.
     */
    event PoolOwnershipRenounced(uint128 indexed poolId, address indexed owner);

    /**
     * @notice Gets fired when pool name changes.
     * @param poolId The id of the pool whose name was updated.
     * @param name The new name of the pool.
     * @param sender The address that triggered the rename of the pool.
     */
    event PoolNameUpdated(uint128 indexed poolId, string name, address indexed sender);

    /**
     * @notice Gets fired when pool gets configured.
     * @param poolId The id of the pool whose configuration was set.
     * @param markets Array of configuration data of the markets that were connected to the pool.
     * @param sender The address that triggered the pool configuration.
     */
    event PoolConfigurationSet(
        uint128 indexed poolId,
        MarketConfiguration.Data[] markets,
        address indexed sender
    );

    event PoolCollateralConfigurationUpdated(
        uint128 indexed poolId,
        address collateralType,
        PoolCollateralConfiguration.Data config
    );

    /**
     * @notice Emitted when a system-wide minimum liquidity ratio is set
     * @param minLiquidityRatio The new system-wide minimum liquidity ratio
     */
    event SetMinLiquidityRatio(uint256 minLiquidityRatio);

    /**
     * @notice Allows collaterals accepeted by the system to be accepeted by the pool by default
     * @param poolId The id of the pool.
     * @param disabled Shows if new collateral's will be dsiabled by default for the pool
     */
    event PoolCollateralDisabledByDefaultSet(uint128 poolId, bool disabled);

    /**
     * @notice Creates a pool with the requested pool id.
     * @param requestedPoolId The requested id for the new pool. Reverts if the id is not available.
     * @param owner The address that will own the newly created pool.
     */
    function createPool(uint128 requestedPoolId, address owner) external;

    /**
     * @notice Allows the pool owner to configure the pool.
     * @dev The pool's configuration is composed of an array of MarketConfiguration objects, which describe which markets the pool provides liquidity to, in what proportion, and to what extent.
     * @dev Incoming market ids need to be provided in ascending order.
     * @param poolId The id of the pool whose configuration is being set.
     * @param marketDistribution The array of market configuration objects that define the list of markets that are connected to the system.
     */
    function setPoolConfiguration(
        uint128 poolId,
        MarketConfiguration.Data[] memory marketDistribution
    ) external;

    /**
     * @notice Allows the pool owner to set the configuration of a specific collateral type for their pool.
     * @param poolId The id of the pool whose configuration is being set.
     * @param collateralType The collate
     * @param newConfig The config to set
     */
    function setPoolCollateralConfiguration(
        uint128 poolId,
        address collateralType,
        PoolCollateralConfiguration.Data memory newConfig
    ) external;

    /**
     * @notice Retrieves the pool configuration of a specific collateral type.
     * @param poolId The id of the pool whose configuration is being returned.
     * @param collateralType The address of the collateral.
     * @return config The PoolCollateralConfiguration object that describes the requested collateral configuration of the pool.
     */
    function getPoolCollateralConfiguration(
        uint128 poolId,
        address collateralType
    ) external view returns (PoolCollateralConfiguration.Data memory config);

    /**
     * @notice Allows collaterals accepeted by the system to be accepeted by the pool by default
     * @param poolId The id of the pool.
     * @param disabled If set to true new collaterals will be disabled for the pool.
     */
    function setPoolCollateralDisabledByDefault(uint128 poolId, bool disabled) external;

    /**
     * @notice Retrieves the MarketConfiguration of the specified pool.
     * @param poolId The id of the pool whose configuration is being queried.
     * @return markets The array of MarketConfiguration objects that describe the pool's configuration.
     */
    function getPoolConfiguration(
        uint128 poolId
    ) external view returns (MarketConfiguration.Data[] memory markets);

    /**
     * @notice Allows the owner of the pool to set the pool's name.
     * @param poolId The id of the pool whose name is being set.
     * @param name The new name to give to the pool.
     */
    function setPoolName(uint128 poolId, string memory name) external;

    /**
     * @notice Returns the pool's name.
     * @param poolId The id of the pool whose name is being queried.
     * @return poolName The current name of the pool.
     */
    function getPoolName(uint128 poolId) external view returns (string memory poolName);

    /**
     * @notice Allows the current pool owner to nominate a new owner.
     * @param nominatedOwner The address to nominate os the new pool owner.
     * @param poolId The id whose ownership is being transferred.
     */
    function nominatePoolOwner(address nominatedOwner, uint128 poolId) external;

    /**
     * @notice After a new pool owner has been nominated, allows it to accept the nomination and thus ownership of the pool.
     * @param poolId The id of the pool for which the caller is to accept ownership.
     */
    function acceptPoolOwnership(uint128 poolId) external;

    /**
     * @notice After a new pool owner has been nominated, allows it to reject the nomination.
     * @param poolId The id of the pool for which the new owner nomination is to be revoked.
     */
    function revokePoolNomination(uint128 poolId) external;

    /**
     * @notice Allows the current nominated owner to renounce the nomination.
     * @param poolId The id of the pool for which the caller is renouncing ownership nomination.
     */
    function renouncePoolNomination(uint128 poolId) external;

    /**
     * @notice Allows the current owner to renounce his ownership.
     * @param poolId The id of the pool for which the caller is renouncing ownership nomination.
     */
    function renouncePoolOwnership(uint128 poolId) external;

    /**
     * @notice Returns the current pool owner.
     * @param poolId The id of the pool whose ownership is being queried.
     * @return owner The current owner of the pool.
     */
    function getPoolOwner(uint128 poolId) external view returns (address owner);

    /**
     * @notice Returns the current nominated pool owner.
     * @param poolId The id of the pool whose nominated owner is being queried.
     * @return nominatedOwner The current nominated owner of the pool.
     */
    function getNominatedPoolOwner(uint128 poolId) external view returns (address nominatedOwner);

    /**
     * @notice Allows the system owner (not the pool owner) to set the system-wide minimum liquidity ratio.
     * @param minLiquidityRatio The new system-wide minimum liquidity ratio, denominated with 18 decimals of precision. (100% is represented by 1 followed by 18 zeros.)
     */
    function setMinLiquidityRatio(uint256 minLiquidityRatio) external;

    /**
     @notice returns a pool minimum issuance ratio
     * @param poolId The id of the pool for to check the collateral for.
     * @param collateral The address of the collateral.
     */
    function getPoolCollateralIssuanceRatio(
        uint128 poolId,
        address collateral
    ) external view returns (uint256 issuanceRatioD18);

    /**
     * @notice Retrieves the system-wide minimum liquidity ratio.
     * @return minRatioD18 The current system-wide minimum liquidity ratio, denominated with 18 decimals of precision. (100% is represented by 1 followed by 18 zeros.)
     */
    function getMinLiquidityRatio() external view returns (uint256 minRatioD18);

    /**
     * @notice Distributes cached debt in a pool to its vaults and updates market credit capacities.
     * @param poolId the pool to rebalance
     * @param optionalCollateralType in addition to rebalancing the pool, calculate updated collaterals and debts for the specified vault
     */
    function rebalancePool(uint128 poolId, address optionalCollateralType) external;
}

File 15 of 18 : IRewardsManagerModule.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

/**
 * @title Module for connecting rewards distributors to vaults.
 */
interface IRewardsManagerModule {
    /**
     * @notice Emitted when a reward distributor returns `false` from `payout` indicating a problem
     * preventing the payout from being executed. In this case, it is advised to check with the
     * project maintainers, and possibly try again in the future.
     * @param distributor the distributor which originated the issue
     */
    error RewardUnavailable(address distributor);

    /**
     * @notice Emitted when the pool owner or an existing reward distributor sets up rewards for vault participants.
     * @param poolId The id of the pool on which rewards were distributed.
     * @param collateralType The collateral type of the pool on which rewards were distributed.
     * @param distributor The reward distributor associated to the rewards that were distributed.
     * @param amount The amount of rewards that were distributed.
     * @param start The date one which the rewards will begin to be claimable.
     * @param duration The time in which all of the distributed rewards will be claimable.
     */
    event RewardsDistributed(
        uint128 indexed poolId,
        address indexed collateralType,
        address distributor,
        uint256 amount,
        uint256 start,
        uint256 duration
    );

    /**
     * @notice Emitted when a vault participant claims rewards.
     * @param accountId The id of the account that claimed the rewards.
     * @param poolId The id of the pool where the rewards were claimed.
     * @param collateralType The address of the collateral used in the pool's rewards.
     * @param distributor The address of the rewards distributor associated with these rewards.
     * @param amount The amount of rewards that were claimed.
     */
    event RewardsClaimed(
        uint128 indexed accountId,
        uint128 indexed poolId,
        address indexed collateralType,
        address distributor,
        uint256 amount
    );

    /**
     * @notice Emitted when a new rewards distributor is registered.
     * @param poolId The id of the pool whose reward distributor was registered.
     * @param collateralType The address of the collateral used in the pool's rewards.
     * @param distributor The address of the newly registered reward distributor.
     */
    event RewardsDistributorRegistered(
        uint128 indexed poolId,
        address indexed collateralType,
        address indexed distributor
    );

    /**
     * @notice Emitted when an already registered rewards distributor is removed.
     * @param poolId The id of the pool whose reward distributor was registered.
     * @param collateralType The address of the collateral used in the pool's rewards.
     * @param distributor The address of the registered reward distributor.
     */
    event RewardsDistributorRemoved(
        uint128 indexed poolId,
        address indexed collateralType,
        address indexed distributor
    );

    /**
     * @notice Called by pool owner to register rewards for vault participants.
     * @param poolId The id of the pool whose rewards are to be managed by the specified distributor.
     * @param collateralType The address of the collateral used in the pool's rewards.
     * @param distributor The address of the reward distributor to be registered.
     */
    function registerRewardsDistributor(
        uint128 poolId,
        address collateralType,
        address distributor
    ) external;

    /**
     * @notice Called by pool owner to remove a registered rewards distributor for vault participants.
     * WARNING: if you remove a rewards distributor, the same address can never be re-registered again. If you
     * simply want to turn off
     * rewards, call `distributeRewards` with 0 emission. If you need to completely reset the rewards distributor
     * again, create a new rewards distributor at a new address and register the new one.
     * This function is provided since the number of rewards distributors added to an account is finite,
     * so you can remove an unused rewards distributor if need be.
     * NOTE: unclaimed rewards can still be claimed after a rewards distributor is removed (though any
     * rewards-over-time will be halted)
     * @param poolId The id of the pool whose rewards are to be managed by the specified distributor.
     * @param collateralType The address of the collateral used in the pool's rewards.
     * @param distributor The address of the reward distributor to be registered.
     */
    function removeRewardsDistributor(
        uint128 poolId,
        address collateralType,
        address distributor
    ) external;

    /**
     * @notice Called by a registered distributor to set up rewards for vault participants.
     * @dev Will revert if the caller is not a registered distributor.
     * @param poolId The id of the pool to distribute rewards to.
     * @param collateralType The address of the collateral used in the pool's rewards.
     * @param amount The amount of rewards to be distributed.
     * @param start The date at which the rewards will begin to be claimable.
     * @param duration The period after which all distributed rewards will be claimable.
     */
    function distributeRewards(
        uint128 poolId,
        address collateralType,
        uint256 amount,
        uint64 start,
        uint32 duration
    ) external;

    /**
     * @notice Called by owner of a pool to set rewards for vault participants. This method
     * of reward setting is generally intended to only be used to recover from a case where the
     * distributor state is out of sync with the core system state, or if the distributor is only
     * able to payout and not capable of distributing its own rewards.
     * @dev Will revert if the caller is not the owner of the pool.
     * @param poolId The id of the pool to distribute rewards to.
     * @param collateralType The address of the collateral used in the pool's rewards.
     * @param rewardsDistributor The address of the reward distributor which pays out the tokens.
     * @param amount The amount of rewards to be distributed.
     * @param start The date at which the rewards will begin to be claimable.
     * @param duration The period after which all distributed rewards will be claimable.
     */
    function distributeRewardsByOwner(
        uint128 poolId,
        address collateralType,
        address rewardsDistributor,
        uint256 amount,
        uint64 start,
        uint32 duration
    ) external;

    /**
     * @notice Allows a user with appropriate permissions to claim rewards associated with a position.
     * @param accountId The id of the account that is to claim the rewards.
     * @param poolId The id of the pool to claim rewards on.
     * @param collateralType The address of the collateral used in the pool's rewards.
     * @param distributor The address of the rewards distributor associated with the rewards being claimed.
     * @return amountClaimedD18 The amount of rewards that were available for the account and thus claimed.
     */
    function claimRewards(
        uint128 accountId,
        uint128 poolId,
        address collateralType,
        address distributor
    ) external returns (uint256 amountClaimedD18);

    /**
     * @notice For a given position, return the rewards that can currently be claimed.
     * @param poolId The id of the pool being queried.
     * @param collateralType The address of the collateral used in the pool's rewards.
     * @param accountId The id of the account whose available rewards are being queried.
     * @return claimableD18 An array of ids of the reward entries that are claimable by the position.
     * @return distributors An array with the addresses of the reward distributors associated with the claimable rewards.
     */
    function updateRewards(
        uint128 poolId,
        address collateralType,
        uint128 accountId
    ) external returns (uint256[] memory claimableD18, address[] memory distributors);

    /**
     * @notice Returns the number of individual units of amount emitted per second per share for the given poolId, collateralType, distributor vault.
     * @param poolId The id of the pool being queried.
     * @param collateralType The address of the collateral used in the pool's rewards.
     * @param distributor The address of the rewards distributor associated with the rewards in question.
     * @return rateD18 The queried rewards rate.
     */
    function getRewardRate(
        uint128 poolId,
        address collateralType,
        address distributor
    ) external view returns (uint256 rateD18);

    /**
     * @notice Returns the amount of claimable rewards for a given accountId for a vault distributor.
     * @param accountId The id of the account to look up rewards on.
     * @param poolId The id of the pool to claim rewards on.
     * @param collateralType The address of the collateral used in the pool's rewards.
     * @param distributor The address of the rewards distributor associated with the rewards being claimed.
     * @return rewardAmount The amount of available rewards that are available for the provided account.
     */
    function getAvailableRewards(
        uint128 accountId,
        uint128 poolId,
        address collateralType,
        address distributor
    ) external view returns (uint256 rewardAmount);
}

File 16 of 18 : MarketConfiguration.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

/**
 * @title Tracks a market's weight within a Pool, and its maximum debt.
 *
 * Each pool has an array of these, with one entry per market managed by the pool.
 *
 * A market's weight determines how much liquidity the pool provides to the market, and how much debt exposure the market gives the pool.
 *
 * Weights are used to calculate percentages by adding all the weights in the pool and dividing the market's weight by the total weights.
 *
 * A market's maximum debt in a pool is indicated with a maximum debt value per share.
 */
library MarketConfiguration {
    struct Data {
        /**
         * @dev Numeric identifier for the market.
         *
         * Must be unique, and in a list of `MarketConfiguration[]`, must be increasing.
         */
        uint128 marketId;
        /**
         * @dev The ratio of each market's `weight` to the pool's `totalWeights` determines the pro-rata share of the market to the pool's total liquidity.
         */
        uint128 weightD18;
        /**
         * @dev Maximum value per share that a pool will tolerate for this market.
         *
         * If the the limit is met, the markets exceeding debt will be distributed, and it will be disconnected from the pool that no longer provides credit to it.
         *
         * Note: This value will have no effect if the system wide limit is hit first. See `PoolConfiguration.minLiquidityRatioD18`.
         */
        int128 maxDebtShareValueD18;
    }
}

File 17 of 18 : PoolCollateralConfiguration.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

library PoolCollateralConfiguration {
    bytes32 private constant _SLOT =
        keccak256(abi.encode("io.synthetix.synthetix.PoolCollateralConfiguration"));

    struct Data {
        uint256 collateralLimitD18;
        uint256 issuanceRatioD18;
    }
}

File 18 of 18 : IPerpRewardDistributor.sol
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.11 <0.9.0;

import {IRewardDistributor} from "@synthetixio/main/contracts/interfaces/external/IRewardDistributor.sol";

// @see: https://github.com/Synthetixio/rewards-distributors
interface IPerpRewardDistributor is IRewardDistributor {
    // --- Errors --- //

    /// @notice Thrown when rewards `balance` does not meet distribute or payout requirements.
    /// @param amount Amount of reward tokens to payout or distribute
    /// @param balance Current internally tracked token balance
    error InsufficientRewardBalance(uint256 amount, uint256 balance);

    // --- Views --- //

    /// @notice Returns the id of the pool this was registered with.
    /// @return getPoolId Id of the pool this RD was registered with
    function getPoolId() external view returns (uint128);

    /// @notice Returns a list of pool collateral types this distributor was registered with.
    /// @return getPoolCollateralTypes An array of delegated pool collateral addresses to distribute to
    function getPoolCollateralTypes() external view returns (address[] memory);

    // --- Mutations --- //

    /// @notice Initializes the PerpRewardDistributor with references, name, token to distribute etc.
    /// @param rewardManager Address of the reward manager (i.e. Synthetix core proxy)
    /// @param perpMarket Address of the bfp market proxy
    /// @param poolId_ Id of the pool this RD was registered with
    /// @param collateralTypes An array of delegated pool collateral types to dstribute to
    /// @param payoutToken_ Reward token to distribute
    /// @param name_ Name of the reward distributor
    function initialize(
        address rewardManager,
        address perpMarket,
        uint128 poolId_,
        address[] calldata collateralTypes,
        address payoutToken_,
        string memory name_
    ) external;

    /// @notice Set true to disable `payout` to revert on claim or false to allow. Only callable by pool owner.
    /// @param _shouldFailedPayout True to fail subsequent payout calls, false otherwise
    function setShouldFailPayout(bool _shouldFailedPayout) external;

    /// @notice Creates a new distribution entry for LPs of `collateralType` to `amount` of tokens.
    /// @param collateralType Delegated collateral in pool to distribute rewards to
    /// @param amount Amount of reward tokens to distribute
    function distributeRewards(address collateralType, uint256 amount) external;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"FailedTransfer","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"balance","type":"uint256"}],"name":"InsufficientRewardBalance","type":"error"},{"inputs":[{"internalType":"string","name":"parameter","type":"string"},{"internalType":"string","name":"reason","type":"string"}],"name":"InvalidParameter","type":"error"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"inputs":[{"internalType":"address","name":"collateralType","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"distributeRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getPoolCollateralTypes","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolId","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rewardManager","type":"address"},{"internalType":"address","name":"perpMarket","type":"address"},{"internalType":"uint128","name":"poolId_","type":"uint128"},{"internalType":"address[]","name":"poolCollateralTypes_","type":"address[]"},{"internalType":"address","name":"payoutToken_","type":"address"},{"internalType":"string","name":"name_","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"onPositionUpdated","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"poolId","type":"uint128"},{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"payoutTarget_","type":"address"},{"internalType":"uint256","name":"payoutAmount_","type":"uint256"}],"name":"payout","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_shouldFailedPayout","type":"bool"}],"name":"setShouldFailPayout","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shouldFailPayout","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b5061001961001e565b6100dd565b600054610100900460ff161561008a5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146100db576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b611091806100ec6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c8063829a42af11610071578063829a42af146101285780639a99916f1461013d578063a8031a1d14610151578063c6361d3814610164578063d221e7f214610177578063fc0c546a1461018a57600080fd5b806301ffc9a7146100ae57806306fdde03146100d65780630effe8b5146100eb57806310e23da4146100f857806338fff2d01461010d575b600080fd5b6100c16100bc366004610aa8565b6101a5565b60405190151581526020015b60405180910390f35b6100de6101dc565b6040516100cd9190610afd565b6007546100c19060ff1681565b61010b610106366004610b41565b61026e565b005b6004546040516001600160801b0390911681526020016100cd565b610130610289565b6040516100cd9190610b5e565b61010b61014b366004610be7565b50505050565b61010b61015f366004610c34565b6102ea565b61010b610172366004610d03565b61044d565b6100c1610185366004610de2565b610721565b6002546040516001600160a01b0390911681526020016100cd565b60006001600160e01b03198216632c927f3d60e21b14806101d657506001600160e01b031982166301ffc9a760e01b145b92915050565b6060600380546101eb90610e42565b80601f016020809104026020016040519081016040528092919081815260200182805461021790610e42565b80156102645780601f1061023957610100808354040283529160200191610264565b820191906000526020600020905b81548152906001019060200180831161024757829003601f168201915b5050505050905090565b610276610811565b6007805460ff1916911515919091179055565b6060600580548060200260200160405190810160405280929190818152602001828054801561026457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116102c3575050505050905090565b6102f26108c7565b60065460006103018383610e92565b6002546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561034f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103739190610ea5565b9050808211156103a5576040516365ac9d4360e01b815260048101859052602481018290526044015b60405180910390fd5b60068290556000805460048054604051635a7ff7c560e01b81526001600160801b03909116918101919091526001600160a01b0388811660248301526044820188905267ffffffffffffffff4216606483015260848201939093526201000090910490911690635a7ff7c59060a401600060405180830381600087803b15801561042e57600080fd5b505af1158015610442573d6000803e3d6000fd5b505050505050505050565b600054610100900460ff161580801561046d5750600054600160ff909116105b806104875750303b158015610487575060005460ff166001145b6104ea5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161039c565b6000805460ff19166001179055801561050d576000805461ff0019166101001790555b6000805462010000600160b01b031916620100006001600160a01b038b81169190910291909117909155600180546001600160a01b031916918916919091179055600480546fffffffffffffffffffffffffffffffff19166001600160801b03881617905561057e60058686610a30565b50600280546001600160a01b0319166001600160a01b03851617905560036105a68382610f0f565b5060408051600481526024810182526020810180516001600160e01b031663313ce56760e01b179052905160009182916001600160a01b038716916105ea91610fcf565b600060405180830381855afa9150503d8060008114610625576040519150601f19603f3d011682016040523d82523d6000602084013e61062a565b606091505b509150915081158061063b57508051155b8061065d5750808060200190518101906106559190610feb565b60ff16601214155b156106cf5760408051634bab873760e11b81526004810191909152600b60448201526a3830bcb7baba2a37b5b2b760a91b606482015260806024820152602060848201527f546f6b656e20646563696d616c7320657870656374656420746f20626520313860a482015260c40161039c565b50508015610717576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b60075460009060ff161561073757506000610808565b6004546001600160801b038681169116146107a85760408051634bab873760e11b8152600481019190915260066044820152651c1bdbdb125960d21b6064820152608060248201526011608482015270155b995e1c1958dd1959081c1bdbdb1259607a1b60a482015260c40161039c565b6107b06108f4565b600654808311156107de576040516365ac9d4360e01b8152600481018490526024810182905260440161039c565b6107e8838261100e565b600655600254610802906001600160a01b03168585610927565b60019150505b95945050505050565b60005460048054604051635deebe2d60e11b81526001600160801b0390911691810191909152620100009091046001600160a01b03169063bbdd7c5a90602401602060405180830381865afa15801561086e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108929190611021565b6001600160a01b0316336001600160a01b0316146108c55760405163472511eb60e11b815233600482015260240161039c565b565b6001546001600160a01b031633146108c55760405163472511eb60e11b815233600482015260240161039c565b6000546201000090046001600160a01b031633146108c55760405163472511eb60e11b815233600482015260240161039c565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916109839190610fcf565b6000604051808303816000865af19150503d80600081146109c0576040519150601f19603f3d011682016040523d82523d6000602084013e6109c5565b606091505b50915091508115806109f357508051158015906109f35750808060200190518101906109f1919061103e565b155b15610a2957604051633210e1d960e01b81523060048201526001600160a01b03851660248201526044810184905260640161039c565b5050505050565b828054828255906000526020600020908101928215610a83579160200282015b82811115610a835781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190610a50565b50610a8f929150610a93565b5090565b5b80821115610a8f5760008155600101610a94565b600060208284031215610aba57600080fd5b81356001600160e01b031981168114610ad257600080fd5b9392505050565b60005b83811015610af4578181015183820152602001610adc565b50506000910152565b6020815260008251806020840152610b1c816040850160208701610ad9565b601f01601f19169190910160400192915050565b8015158114610b3e57600080fd5b50565b600060208284031215610b5357600080fd5b8135610ad281610b30565b6020808252825182820181905260009190848201906040850190845b81811015610b9f5783516001600160a01b031683529284019291840191600101610b7a565b50909695505050505050565b80356001600160801b0381168114610bc257600080fd5b919050565b6001600160a01b0381168114610b3e57600080fd5b8035610bc281610bc7565b60008060008060808587031215610bfd57600080fd5b610c0685610bab565b9350610c1460208601610bab565b92506040850135610c2481610bc7565b9396929550929360600135925050565b60008060408385031215610c4757600080fd5b8235610c5281610bc7565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610c8757600080fd5b813567ffffffffffffffff80821115610ca257610ca2610c60565b604051601f8301601f19908116603f01168101908282118183101715610cca57610cca610c60565b81604052838152866020858801011115610ce357600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600080600060c0888a031215610d1e57600080fd5b8735610d2981610bc7565b96506020880135610d3981610bc7565b9550610d4760408901610bab565b9450606088013567ffffffffffffffff80821115610d6457600080fd5b818a0191508a601f830112610d7857600080fd5b813581811115610d8757600080fd5b8b60208260051b8501011115610d9c57600080fd5b6020830196509450610db060808b01610bdc565b935060a08a0135915080821115610dc657600080fd5b50610dd38a828b01610c76565b91505092959891949750929550565b600080600080600060a08688031215610dfa57600080fd5b610e0386610bab565b9450610e1160208701610bab565b93506040860135610e2181610bc7565b92506060860135610e3181610bc7565b949793965091946080013592915050565b600181811c90821680610e5657607f821691505b602082108103610e7657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156101d6576101d6610e7c565b600060208284031215610eb757600080fd5b5051919050565b601f821115610f0a576000816000526020600020601f850160051c81016020861015610ee75750805b601f850160051c820191505b81811015610f0657828155600101610ef3565b5050505b505050565b815167ffffffffffffffff811115610f2957610f29610c60565b610f3d81610f378454610e42565b84610ebe565b602080601f831160018114610f725760008415610f5a5750858301515b600019600386901b1c1916600185901b178555610f06565b600085815260208120601f198616915b82811015610fa157888601518255948401946001909101908401610f82565b5085821015610fbf5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008251610fe1818460208701610ad9565b9190910192915050565b600060208284031215610ffd57600080fd5b815160ff81168114610ad257600080fd5b818103818111156101d6576101d6610e7c565b60006020828403121561103357600080fd5b8151610ad281610bc7565b60006020828403121561105057600080fd5b8151610ad281610b3056fea2646970667358221220a42a7808a1f1472fa8d8688745e177f02afd3f8de26e4a9926caa38d6ee3333264736f6c63430008160033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100a95760003560e01c8063829a42af11610071578063829a42af146101285780639a99916f1461013d578063a8031a1d14610151578063c6361d3814610164578063d221e7f214610177578063fc0c546a1461018a57600080fd5b806301ffc9a7146100ae57806306fdde03146100d65780630effe8b5146100eb57806310e23da4146100f857806338fff2d01461010d575b600080fd5b6100c16100bc366004610aa8565b6101a5565b60405190151581526020015b60405180910390f35b6100de6101dc565b6040516100cd9190610afd565b6007546100c19060ff1681565b61010b610106366004610b41565b61026e565b005b6004546040516001600160801b0390911681526020016100cd565b610130610289565b6040516100cd9190610b5e565b61010b61014b366004610be7565b50505050565b61010b61015f366004610c34565b6102ea565b61010b610172366004610d03565b61044d565b6100c1610185366004610de2565b610721565b6002546040516001600160a01b0390911681526020016100cd565b60006001600160e01b03198216632c927f3d60e21b14806101d657506001600160e01b031982166301ffc9a760e01b145b92915050565b6060600380546101eb90610e42565b80601f016020809104026020016040519081016040528092919081815260200182805461021790610e42565b80156102645780601f1061023957610100808354040283529160200191610264565b820191906000526020600020905b81548152906001019060200180831161024757829003601f168201915b5050505050905090565b610276610811565b6007805460ff1916911515919091179055565b6060600580548060200260200160405190810160405280929190818152602001828054801561026457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116102c3575050505050905090565b6102f26108c7565b60065460006103018383610e92565b6002546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa15801561034f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103739190610ea5565b9050808211156103a5576040516365ac9d4360e01b815260048101859052602481018290526044015b60405180910390fd5b60068290556000805460048054604051635a7ff7c560e01b81526001600160801b03909116918101919091526001600160a01b0388811660248301526044820188905267ffffffffffffffff4216606483015260848201939093526201000090910490911690635a7ff7c59060a401600060405180830381600087803b15801561042e57600080fd5b505af1158015610442573d6000803e3d6000fd5b505050505050505050565b600054610100900460ff161580801561046d5750600054600160ff909116105b806104875750303b158015610487575060005460ff166001145b6104ea5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840161039c565b6000805460ff19166001179055801561050d576000805461ff0019166101001790555b6000805462010000600160b01b031916620100006001600160a01b038b81169190910291909117909155600180546001600160a01b031916918916919091179055600480546fffffffffffffffffffffffffffffffff19166001600160801b03881617905561057e60058686610a30565b50600280546001600160a01b0319166001600160a01b03851617905560036105a68382610f0f565b5060408051600481526024810182526020810180516001600160e01b031663313ce56760e01b179052905160009182916001600160a01b038716916105ea91610fcf565b600060405180830381855afa9150503d8060008114610625576040519150601f19603f3d011682016040523d82523d6000602084013e61062a565b606091505b509150915081158061063b57508051155b8061065d5750808060200190518101906106559190610feb565b60ff16601214155b156106cf5760408051634bab873760e11b81526004810191909152600b60448201526a3830bcb7baba2a37b5b2b760a91b606482015260806024820152602060848201527f546f6b656e20646563696d616c7320657870656374656420746f20626520313860a482015260c40161039c565b50508015610717576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050505050505050565b60075460009060ff161561073757506000610808565b6004546001600160801b038681169116146107a85760408051634bab873760e11b8152600481019190915260066044820152651c1bdbdb125960d21b6064820152608060248201526011608482015270155b995e1c1958dd1959081c1bdbdb1259607a1b60a482015260c40161039c565b6107b06108f4565b600654808311156107de576040516365ac9d4360e01b8152600481018490526024810182905260440161039c565b6107e8838261100e565b600655600254610802906001600160a01b03168585610927565b60019150505b95945050505050565b60005460048054604051635deebe2d60e11b81526001600160801b0390911691810191909152620100009091046001600160a01b03169063bbdd7c5a90602401602060405180830381865afa15801561086e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108929190611021565b6001600160a01b0316336001600160a01b0316146108c55760405163472511eb60e11b815233600482015260240161039c565b565b6001546001600160a01b031633146108c55760405163472511eb60e11b815233600482015260240161039c565b6000546201000090046001600160a01b031633146108c55760405163472511eb60e11b815233600482015260240161039c565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916109839190610fcf565b6000604051808303816000865af19150503d80600081146109c0576040519150601f19603f3d011682016040523d82523d6000602084013e6109c5565b606091505b50915091508115806109f357508051158015906109f35750808060200190518101906109f1919061103e565b155b15610a2957604051633210e1d960e01b81523060048201526001600160a01b03851660248201526044810184905260640161039c565b5050505050565b828054828255906000526020600020908101928215610a83579160200282015b82811115610a835781546001600160a01b0319166001600160a01b03843516178255602090920191600190910190610a50565b50610a8f929150610a93565b5090565b5b80821115610a8f5760008155600101610a94565b600060208284031215610aba57600080fd5b81356001600160e01b031981168114610ad257600080fd5b9392505050565b60005b83811015610af4578181015183820152602001610adc565b50506000910152565b6020815260008251806020840152610b1c816040850160208701610ad9565b601f01601f19169190910160400192915050565b8015158114610b3e57600080fd5b50565b600060208284031215610b5357600080fd5b8135610ad281610b30565b6020808252825182820181905260009190848201906040850190845b81811015610b9f5783516001600160a01b031683529284019291840191600101610b7a565b50909695505050505050565b80356001600160801b0381168114610bc257600080fd5b919050565b6001600160a01b0381168114610b3e57600080fd5b8035610bc281610bc7565b60008060008060808587031215610bfd57600080fd5b610c0685610bab565b9350610c1460208601610bab565b92506040850135610c2481610bc7565b9396929550929360600135925050565b60008060408385031215610c4757600080fd5b8235610c5281610bc7565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112610c8757600080fd5b813567ffffffffffffffff80821115610ca257610ca2610c60565b604051601f8301601f19908116603f01168101908282118183101715610cca57610cca610c60565b81604052838152866020858801011115610ce357600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600080600060c0888a031215610d1e57600080fd5b8735610d2981610bc7565b96506020880135610d3981610bc7565b9550610d4760408901610bab565b9450606088013567ffffffffffffffff80821115610d6457600080fd5b818a0191508a601f830112610d7857600080fd5b813581811115610d8757600080fd5b8b60208260051b8501011115610d9c57600080fd5b6020830196509450610db060808b01610bdc565b935060a08a0135915080821115610dc657600080fd5b50610dd38a828b01610c76565b91505092959891949750929550565b600080600080600060a08688031215610dfa57600080fd5b610e0386610bab565b9450610e1160208701610bab565b93506040860135610e2181610bc7565b92506060860135610e3181610bc7565b949793965091946080013592915050565b600181811c90821680610e5657607f821691505b602082108103610e7657634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b808201808211156101d6576101d6610e7c565b600060208284031215610eb757600080fd5b5051919050565b601f821115610f0a576000816000526020600020601f850160051c81016020861015610ee75750805b601f850160051c820191505b81811015610f0657828155600101610ef3565b5050505b505050565b815167ffffffffffffffff811115610f2957610f29610c60565b610f3d81610f378454610e42565b84610ebe565b602080601f831160018114610f725760008415610f5a5750858301515b600019600386901b1c1916600185901b178555610f06565b600085815260208120601f198616915b82811015610fa157888601518255948401946001909101908401610f82565b5085821015610fbf5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008251610fe1818460208701610ad9565b9190910192915050565b600060208284031215610ffd57600080fd5b815160ff81168114610ad257600080fd5b818103818111156101d6576101d6610e7c565b60006020828403121561103357600080fd5b8151610ad281610bc7565b60006020828403121561105057600080fd5b8151610ad281610b3056fea2646970667358221220a42a7808a1f1472fa8d8688745e177f02afd3f8de26e4a9926caa38d6ee3333264736f6c63430008160033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits

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.