Contract 0xf75a66c535fbe97beecd1a465e32c8afd846765d

Contract Overview

Balance:
0 FTM
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x9ffc2f473feb1408f96a522a4c3d2c6a896232326286d41d61c0401950380da20x6080604057579162021-12-08 2:51:5750 days 33 mins ago0xbf334f8bd1420a1cbfe15407f73919424934b1b3 IN  Contract Creation0 FTM0.7382169
[ Download CSV Export 
Latest 8 internal transactions
Parent Txn Hash Block From To Value
0xe983367c2259ddc1a312105e6bf2e555aafebc33a54ee8f1eb451255c222595857586632021-12-08 3:48:1349 days 23 hrs ago 0xf75a66c535fbe97beecd1a465e32c8afd846765d  Contract Creation0 FTM
0xefb20ec65a0d9e5795a06825bb489b2e0e0542a8e1a79f86bc3e5f181caa409b57586452021-12-08 3:45:4749 days 23 hrs ago 0xf75a66c535fbe97beecd1a465e32c8afd846765d  Contract Creation0 FTM
0x4b8e73c48fa061b1f2ede4a35067838ff173aa285c867e3ac7363bd9f152001757586392021-12-08 3:45:2249 days 23 hrs ago 0xf75a66c535fbe97beecd1a465e32c8afd846765d  Contract Creation0 FTM
0x1af4b6a7f1323e573e350136167e90b284b4776e87c5364240b60e35bb08916857586342021-12-08 3:44:4749 days 23 hrs ago 0xf75a66c535fbe97beecd1a465e32c8afd846765d  Contract Creation0 FTM
0x3decbd6cc820de264708c67453b8dea28b5cff7593791975609b25fae9aefbb357586112021-12-08 3:42:4349 days 23 hrs ago 0xf75a66c535fbe97beecd1a465e32c8afd846765d  Contract Creation0 FTM
0xa12f238904f5bfeec66b72dc027be417f0ca7a7742e823bd93c361b2740b6c1357585902021-12-08 3:41:3949 days 23 hrs ago 0xf75a66c535fbe97beecd1a465e32c8afd846765d  Contract Creation0 FTM
0xd92b1da2efd94d3edfe305856a7470053e4d28fc813670972d5327dff6e9699957585782021-12-08 3:41:0849 days 23 hrs ago 0xf75a66c535fbe97beecd1a465e32c8afd846765d  Contract Creation0 FTM
0x9ffc2f473feb1408f96a522a4c3d2c6a896232326286d41d61c0401950380da257579162021-12-08 2:51:5750 days 33 mins ago 0xbf334f8bd1420a1cbfe15407f73919424934b1b3  Contract Creation0 FTM
[ Download CSV Export 
Loading

Similar Match Source Code
Note: This contract matches the deployed ByteCode of the Source Code for Contract 0x34A0946CEAD3417E629B2679D05C0A24d49a1eB4

Contract Name:
SeedERC20Factory

Compiler Version
v0.8.10+commit.fc410830

Optimization Enabled:
Yes with 100000 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 16 : SeedERC20Factory.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.10;

import { Factory } from "../factory/Factory.sol";
import { SeedERC20, SeedERC20Config } from "./SeedERC20.sol";

/// @title SeedERC20Factory
/// @notice Factory for creating and deploying `SeedERC20` contracts.
contract SeedERC20Factory is Factory {

    /// @inheritdoc Factory
    function _createChild(
        bytes calldata data_
    ) internal virtual override returns(address) {
        (SeedERC20Config memory config_) = abi.decode(
            data_,
            (SeedERC20Config)
        );
        return address(new SeedERC20(config_));
    }

    /// Allows calling `createChild` with `SeedERC20Config` struct.
    /// Use original `Factory` `createChild` function signature if function
    /// parameters are already encoded.
    ///
    /// @param config_ `SeedERC20` constructor configuration.
    /// @return New `SeedERC20` child contract address.
    function createChild(SeedERC20Config calldata config_)
        external
        returns(address)
    {
        return this.createChild(abi.encode(config_));
    }
}

File 2 of 16 : Factory.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.10;

import { IFactory } from "./IFactory.sol";
// solhint-disable-next-line max-line-length
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";

/// @title Factory
/// @notice Base contract for deploying and registering child contracts.
abstract contract Factory is IFactory, ReentrancyGuard {
    /// @dev state to track each deployed contract address. A `Factory` will
    /// never lie about deploying a child, unless `isChild` is overridden to do
    /// so.
    mapping(address => bool) private contracts;

    /// Implements `IFactory`.
    ///
    /// `_createChild` hook must be overridden to actually create child
    /// contract.
    ///
    /// Implementers may want to overload this function with a typed equivalent
    /// to expose domain specific structs etc. to the compiled ABI consumed by
    /// tooling and other scripts. To minimise gas costs for deployment it is
    /// expected that the tooling will consume the typed ABI, then encode the
    /// arguments and pass them to this function directly.
    ///
    /// @param data_ ABI encoded data to pass to child contract constructor.
    // Slither false positive. This is intended to overridden.
    // https://github.com/crytic/slither/issues/929
    // slither-disable-next-line dead-code
    function _createChild(bytes calldata data_)
        internal
        virtual
        returns(address)
    { } // solhint-disable-line no-empty-blocks

    /// Implements `IFactory`.
    ///
    /// Calls the _createChild hook, which inheriting contracts must override.
    /// Registers child contract address such that `isChild` is `true`.
    /// Emits `NewContract` event.
    ///
    /// @param data_ Encoded data to pass down to child contract constructor.
    /// @return New child contract address.
    function createChild(bytes calldata data_)
        external
        virtual
        override
        nonReentrant
        returns(address) {
        // Create child contract using hook.
        address child_ = _createChild(data_);
        // Register child contract address to `contracts` mapping.
        contracts[child_] = true;
        // Emit `NewContract` event with child contract address.
        emit IFactory.NewContract(child_);
        return child_;
    }

    /// Implements `IFactory`.
    ///
    /// Checks if address is registered as a child contract of this factory.
    ///
    /// @param maybeChild_ Address of child contract to look up.
    /// @return Returns `true` if address is a contract created by this
    /// contract factory, otherwise `false`.
    function isChild(address maybeChild_)
        external
        virtual
        override
        returns(bool)
    {
        return contracts[maybeChild_];
    }
}

File 3 of 16 : IFactory.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.10;

interface IFactory {
    /// Whenever a new child contract is deployed, a `NewContract` event
    /// containing the new child contract address MUST be emitted.
    event NewContract(address indexed _contract);

    /// Creates a new child contract.
    ///
    /// @param data_ Domain specific data for the child contract constructor.
    /// @return New child contract address.
    function createChild(bytes calldata data_) external returns(address);

    /// Checks if address is registered as a child contract of this factory.
    ///
    /// Addresses that were not deployed by `createChild` MUST NOT return
    /// `true` from `isChild`. This is CRITICAL to the security guarantees for
    /// any contract implementing `IFactory`.
    ///
    /// @param maybeChild_ Address to check registration for.
    /// @return `true` if address was deployed by this contract factory,
    /// otherwise `false`.
    function isChild(address maybeChild_) external returns(bool);
}

File 4 of 16 : SeedERC20.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.10;

import { ERC20Config } from "../erc20/ERC20Config.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
// solhint-disable-next-line max-line-length
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";

import { Phase, Phased } from "../phased/Phased.sol";
import { Cooldown } from "../cooldown/Cooldown.sol";

/// Everything required to construct a `SeedERC20` contract.
struct SeedERC20Config {
    // Reserve erc20 token contract used to purchase seed tokens.
    IERC20 reserve;
    // Recipient address for all reserve funds raised when seeding is complete.
    address recipient;
    // Price per seed unit denominated in reserve token.
    uint256 seedPrice;
    // Total seed units to be mint and sold.
    // 100% of all seed units must be sold for seeding to complete.
    // Recommended to keep seed units to a small value (single-triple digits).
    // The ability for users to buy/sell or not buy/sell dust seed quantities
    // is likely NOT desired.
    uint16 seedUnits;
    // Cooldown duration in blocks for seed/unseed cycles.
    // Seeding requires locking funds for at least the cooldown period.
    // Ideally `unseed` is never called and `seed` leaves funds in the contract
    // until all seed tokens are sold out.
    // A failed raise cannot make funds unrecoverable, so `unseed` does exist,
    // but it should be called rarely.
    uint16 cooldownDuration;
    // ERC20 config.
    ERC20Config erc20Config;
}

/// @title SeedERC20
/// @notice Facilitates raising seed reserve from an open set of seeders.
///
/// When a single seeder address cannot be specified at the time the
/// `Trust` is constructed a `SeedERC20` will be deployed.
///
/// The `SeedERC20` has two phases:
///
/// - `Phase.ZERO`: Can swap seed tokens for reserve assets with
/// `seed` and `unseed`
/// - `Phase.ONE`: Can redeem seed tokens pro-rata for reserve assets
///
/// When the last seed token is distributed the `SeedERC20`
/// immediately moves to `Phase.ONE` atomically within that
/// transaction and forwards all reserve to the configured recipient.
///
/// For our use-case the recipient is a `Trust` contract but `SeedERC20`
/// could be used as a mini-fundraise contract for many purposes. In the case
/// that a recipient is not a `Trust` the recipient will need to be careful not
/// to fall afoul of KYC and securities law.
///
/// @dev Facilitates a pool of reserve funds to forward to a named recipient
/// contract.
/// The funds to raise and the recipient is fixed at construction.
/// The total is calculated as `( seedPrice * seedUnits )` and so is a fixed
/// amount. It is recommended to keep seedUnits relatively small so that each
/// unit represents a meaningful contribution to keep dust out of the system.
///
/// The contract lifecycle is split into two phases:
///
/// - `Phase.ZERO`: the `seed` and `unseed` functions are callable by anyone.
/// - `Phase.ONE`: holders of the seed erc20 token can redeem any reserve funds
///   in the contract pro-rata.
///
/// When `seed` is called the `SeedERC20` contract takes ownership of reserve
/// funds in exchange for seed tokens.
/// When `unseed` is called the `SeedERC20` contract takes ownership of seed
/// tokens in exchange for reserve funds.
///
/// When the last `seed` token is transferred to an external address the
/// `SeedERC20` contract immediately:
///
/// - Moves to `Phase.ONE`, disabling both `seed` and `unseed`
/// - Transfers the full balance of reserve from itself to the recipient
///   address.
///
/// Seed tokens are standard ERC20 so can be freely transferred etc.
///
/// The recipient (or anyone else) MAY transfer reserve back to the `SeedERC20`
/// at a later date.
/// Seed token holders can call `redeem` in `Phase.ONE` to burn their tokens in
/// exchange for pro-rata reserve assets.
contract SeedERC20 is Ownable, ERC20, Phased, Cooldown {

    using Math for uint256;
    using SafeERC20 for IERC20;

    /// Seed token burn for reserve.
    /// @param redeemer Account burning and receiving.
    /// @param redeemAmounts Number of seed tokens burned.
    /// Number of reserve redeemed for burned seed tokens.
    /// `[seedAmount, reserveAmount]`
    event Redeem(
        address indexed redeemer,
        uint256[2] redeemAmounts
    );

    /// @param seeder Account seeding.
    /// @param seedAmounts Number of tokens seeded.
    /// Number of reserve sent for seed tokens.
    event Seed(
        address indexed seeder,
        uint256[2] seedAmounts
    );

    /// @param unseeder Account unseeding.
    /// @param unseedAmounts Number of tokens unseeded.
    /// Number of reserve tokens returned for unseeded tokens.
    event Unseed(
        address indexed unseeder,
        uint256[2] unseedAmounts
    );

    /// Reserve erc20 token contract used to purchase seed tokens.
    IERC20 public immutable reserve;
    /// Recipient address for all reserve funds raised when seeding is
    /// complete.
    address public immutable recipient;
    /// Price in reserve for a unit of seed token.
    uint256 public immutable seedPrice;

    /// Sanity checks on configuration.
    /// Store relevant config as contract state.
    /// Mint all seed tokens.
    /// @param config_ All config required to construct the contract.
    constructor (SeedERC20Config memory config_)
    ERC20(config_.erc20Config.name, config_.erc20Config.symbol)
    Cooldown(config_.cooldownDuration) {
        require(config_.seedPrice > 0, "PRICE_0");
        require(config_.seedUnits > 0, "UNITS_0");
        require(config_.recipient != address(0), "RECIPIENT_0");
        seedPrice = config_.seedPrice;
        reserve = config_.reserve;
        recipient = config_.recipient;
        _mint(address(this), config_.seedUnits);
    }

    /// @inheritdoc ERC20
    function decimals() public pure override returns(uint8) {
        return 0;
    }

    /// Take reserve from seeder as `units * seedPrice`.
    ///
    /// When the final unit is sold the contract immediately:
    ///
    /// - enters `Phase.ONE`
    /// - transfers its entire reserve balance to the recipient
    ///
    /// The desired units may not be available by the time this transaction
    /// executes. This could be due to high demand, griefing and/or
    /// front-running on the contract.
    /// The caller can set a range between `minimumUnits_` and `desiredUnits_`
    /// to mitigate errors due to the contract running out of stock.
    /// The maximum available units up to `desiredUnits_` will always be
    /// processed by the contract. Only the stock of this contract is checked
    /// against the seed unit range, the caller is responsible for ensuring
    /// their reserve balance.
    /// Seeding enforces the cooldown configured in the constructor.
    /// @param minimumUnits_ The minimum units the caller will accept for a
    /// successful `seed` call.
    /// @param desiredUnits_ The maximum units the caller is willing to fund.
    function seed(uint256 minimumUnits_, uint256 desiredUnits_)
        external
        onlyPhase(Phase.ZERO)
        onlyAfterCooldown
    {
        require(desiredUnits_ > 0, "DESIRED_0");
        require(minimumUnits_ <= desiredUnits_, "MINIMUM_OVER_DESIRED");
        uint256 remainingStock_ = balanceOf(address(this));
        require(minimumUnits_ <= remainingStock_, "INSUFFICIENT_STOCK");

        uint256 units_ = desiredUnits_.min(remainingStock_);
        uint256 reserveAmount_ = seedPrice * units_;

        // If `remainingStock_` is less than units then the transfer below will
        // fail and rollback.
        if (remainingStock_ == units_) {
            scheduleNextPhase(uint32(block.number));
        }
        _transfer(address(this), msg.sender, units_);

        emit Seed(
            msg.sender,
            [units_, reserveAmount_]
        );

        reserve.safeTransferFrom(
            msg.sender,
            address(this),
            reserveAmount_
        );
        // Immediately transfer to the recipient.
        // The transfer is immediate rather than only approving for the
        // recipient.
        // This avoids the situation where a seeder immediately redeems their
        // units before the recipient can withdraw.
        // It also introduces a failure case where the reserve errors on
        // transfer. If this fails then everyone can call `unseed` after their
        // individual cooldowns to exit.
        if (currentPhase() == Phase.ONE) {
            reserve.safeTransfer(recipient, reserve.balanceOf(address(this)));
        }
    }

    /// Send reserve back to seeder as `( units * seedPrice )`.
    ///
    /// Allows addresses to back out until `Phase.ONE`.
    /// Unlike `redeem` the seed tokens are NOT burned so become newly
    /// available for another account to `seed`.
    ///
    /// In `Phase.ONE` the only way to recover reserve assets is:
    /// - Wait for the recipient or someone else to deposit reserve assets into
    ///   this contract.
    /// - Call redeem and burn the seed tokens
    ///
    /// @param units_ Units to unseed.
    function unseed(uint256 units_)
        external
        onlyPhase(Phase.ZERO)
        onlyAfterCooldown
    {
        uint256 reserveAmount_ = seedPrice * units_;
        _transfer(msg.sender, address(this), units_);

        emit Unseed(
            msg.sender,
            [units_, reserveAmount_]
        );

        // Reentrant reserve transfer.
        reserve.safeTransfer(msg.sender, reserveAmount_);
    }

    /// Burn seed tokens for pro-rata reserve assets.
    ///
    /// ```
    /// (units * reserve held by seed contract) / total seed token supply
    /// = reserve transfer to `msg.sender`
    /// ```
    ///
    /// The recipient or someone else must first transfer reserve assets to the
    /// `SeedERC20` contract.
    /// The recipient MUST be a TRUSTED contract or third party.
    /// This contract has no control over the reserve assets once they are
    /// transferred away at the start of `Phase.ONE`.
    /// It is the caller's responsibility to monitor the reserve balance of the
    /// `SeedERC20` contract.
    ///
    /// For example, if `SeedERC20` is used as a seeder for a `Trust` contract
    /// (in this repo) it will receive a refund or refund + fee.
    /// @param units_ Amount of seed units to burn and redeem for reserve
    /// assets.
    function redeem(uint256 units_) external onlyPhase(Phase.ONE) {
        uint256 supplyBeforeBurn_ = totalSupply();
        _burn(msg.sender, units_);

        uint256 currentReserveBalance_ = reserve.balanceOf(address(this));
        // Guard against someone accidentally calling redeem before any reserve
        // has been returned.
        require(currentReserveBalance_ > 0, "RESERVE_BALANCE");
        uint256 reserveAmount_
            = ( units_ * currentReserveBalance_ )
            / supplyBeforeBurn_;
        emit Redeem(
            msg.sender,
            [units_, reserveAmount_]
        );
        reserve.safeTransfer(
            msg.sender,
            reserveAmount_
        );
    }

    /// Sanity check the last phase is `Phase.ONE`.
    /// @inheritdoc Phased
    function _beforeScheduleNextPhase(uint32 nextPhaseBlock_)
        internal
        override
        virtual
    {
        super._beforeScheduleNextPhase(nextPhaseBlock_);
        // Phase.ONE is the last phase.
        assert(currentPhase() < Phase.ONE);
    }
}

File 5 of 16 : ERC20Config.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.10;

struct ERC20Config {
    string name;
    string symbol;
}

File 6 of 16 : Phased.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.10;

/// Defines all possible phases.
/// `Phased` begins in `Phase.ZERO` and moves through each phase sequentially.
enum Phase {
    ZERO,
    ONE,
    TWO,
    THREE,
    FOUR,
    FIVE,
    SIX,
    SEVEN,
    EIGHT
}

/// @title Phased
/// @notice `Phased` is an abstract contract that defines up to `9` phases that
/// an implementing contract moves through.
///
/// `Phase.ZERO` is always the first phase and does not, and cannot, be set
/// expicitly. Effectively it is implied that `Phase.ZERO` has been active
/// since block zero.
///
/// Each subsequent phase `Phase.ONE` through `Phase.EIGHT` must be
/// scheduled sequentially and explicitly at a block number.
///
/// Only the immediate next phase can be scheduled with `scheduleNextPhase`,
/// it is not possible to schedule multiple phases ahead.
///
/// Multiple phases can be scheduled in a single block if each scheduled phase
/// is scheduled for the current block.
///
/// Several utility functions and modifiers are provided.
///
/// A single hook `_beforeScheduleNextPhase` is provided so contracts can
/// implement additional phase shift checks.
///
/// One event `PhaseShiftScheduled` is emitted each time a phase shift is
/// scheduled (not when the scheduled phase is reached).
///
/// @dev `Phased` contracts have a defined timeline with available
/// functionality grouped into phases.
/// Every `Phased` contract starts at `Phase.ZERO` and moves sequentially
/// through phases `ONE` to `EIGHT`.
/// Every `Phase` other than `Phase.ZERO` is optional, there is no requirement
/// that all 9 phases are implemented.
/// Phases can never be revisited, the inheriting contract always moves through
/// each achieved phase linearly.
/// This is enforced by only allowing `scheduleNextPhase` to be called once per
/// phase.
/// It is possible to call `scheduleNextPhase` several times in a single block
/// but the `block.number` for each phase must be reached each time to schedule
/// the next phase.
/// Importantly there are events and several modifiers and checks available to
/// ensure that functionality is limited to the current phase.
/// The full history of each phase shift block is recorded as a fixed size
/// array of `uint32`.
abstract contract Phased {
    /// Every phase block starts uninitialized.
    /// Only uninitialized blocks can be set by the phase scheduler.
    uint32 public constant UNINITIALIZED = 0xFFFFFFFF;

    /// `PhaseShiftScheduled` is emitted when the next phase is scheduled.
    event PhaseShiftScheduled(uint32 indexed newPhaseBlock_);

    /// 8 phases each as 32 bits to fit a single 32 byte word.
    uint32[8] public phaseBlocks;

    constructor() {
        for (uint256 i_ = 0; i_ < 8; i_++) {
            phaseBlocks[i_] = UNINITIALIZED;
        }
    }

    /// Pure function to reduce an array of phase blocks and block number to a
    /// specific `Phase`.
    /// The phase will be the highest attained even if several phases have the
    /// same block number.
    /// If every phase block is after the block number then `Phase.ZERO` is
    /// returned.
    /// If every phase block is before the block number then `Phase.EIGHT` is
    /// returned.
    /// @param phaseBlocks_ Fixed array of phase blocks to compare against.
    /// @param blockNumber_ Determine the relevant phase relative to this block
    /// number.
    /// @return The "current" phase relative to the block number and phase
    /// blocks list.
    function phaseAtBlockNumber(
        uint32[8] memory phaseBlocks_,
        uint32 blockNumber_
    )
        public
        pure
        returns(Phase)
    {
        for(uint i_ = 0; i_<8; i_++) {
            if (blockNumber_ < phaseBlocks_[i_]) {
                return Phase(i_);
            }
        }
        return Phase(8);
    }

    /// Pure function to reduce an array of phase blocks and phase to a
    /// specific block number.
    /// `Phase.ZERO` will always return block `0`.
    /// Every other phase will map to a block number in `phaseBlocks_`.
    /// @param phaseBlocks_ Fixed array of phase blocks to compare against.
    /// @param phase_ Determine the relevant block number for this phase.
    /// @return The block number for the phase according to the phase blocks
    ///         list, as uint32.
    function blockNumberForPhase(uint32[8] calldata phaseBlocks_, Phase phase_)
        external
        pure
        returns(uint32)
    {
        return phase_ > Phase.ZERO ? phaseBlocks_[uint(phase_) - 1] : 0;
    }

    /// Impure read-only function to return the "current" phase from internal
    /// contract state.
    /// Simply wraps `phaseAtBlockNumber` for current values of `phaseBlocks`
    /// and `block.number`.
    function currentPhase() public view returns (Phase) {
        return phaseAtBlockNumber(phaseBlocks, uint32(block.number));
    }

    /// Modifies functions to only be callable in a specific phase.
    /// @param phase_ Modified functions can only be called during this phase.
    modifier onlyPhase(Phase phase_) {
        require(currentPhase() == phase_, "BAD_PHASE");
        _;
    }

    /// Modifies functions to only be callable in a specific phase OR if the
    /// specified phase has passed.
    /// @param phase_ Modified function only callable during or after this
    /// phase.
    modifier onlyAtLeastPhase(Phase phase_) {
        require(currentPhase() >= phase_, "MIN_PHASE");
        _;
    }

    /// Writes the block for the next phase.
    /// Only uninitialized blocks can be written to.
    /// Only the immediate next phase relative to `currentPhase` can be written
    /// to.
    /// Emits `PhaseShiftScheduled` with the next phase block.
    /// @param nextPhaseBlock_ The block for the next phase.
    function scheduleNextPhase(uint32 nextPhaseBlock_) internal {
        require(uint32(block.number) <= nextPhaseBlock_, "NEXT_BLOCK_PAST");
        require(nextPhaseBlock_ < UNINITIALIZED, "NEXT_BLOCK_UNINITIALIZED");

        // The next index is the current phase because `Phase.ZERO` doesn't
        // exist as an index.
        uint nextIndex_ = uint(currentPhase());
        require(UNINITIALIZED == phaseBlocks[nextIndex_], "NEXT_BLOCK_SET");

        _beforeScheduleNextPhase(nextPhaseBlock_);
        phaseBlocks[nextIndex_] = nextPhaseBlock_;

        emit PhaseShiftScheduled(nextPhaseBlock_);
    }

    /// Hook called before scheduling the next phase.
    /// Useful to apply additional constraints or state changes on a phase
    /// change.
    /// Note this is called when scheduling the phase change, not on the block
    /// the phase change occurs.
    /// This is called before the phase change so that all functionality that
    /// is behind a phase gate is still available at the moment of applying the
    /// hook for scheduling the next phase.
    /// @param nextPhaseBlock_ The block for the next phase.
    function _beforeScheduleNextPhase(uint32 nextPhaseBlock_)
        internal
        virtual
    { } //solhint-disable-line no-empty-blocks
}

File 7 of 16 : Cooldown.sol
// SPDX-License-Identifier: CAL
pragma solidity ^0.8.10;

/// @title Cooldown
/// @notice `Cooldown` is an abstract contract that rate limits functions on
/// the contract per `msg.sender`.
///
/// Each time a function with the `onlyAfterCooldown` modifier is called the
/// `msg.sender` must wait N blocks before calling any modified function.
///
/// This does nothing to prevent sybils who can generate an arbitrary number of
/// `msg.sender` values in parallel to spam a contract.
///
/// `Cooldown` is intended to prevent rapid state cycling to grief a contract,
/// such as rapidly locking and unlocking a large amount of capital in the
/// `SeedERC20` contract.
///
/// Requiring a lock/deposit of significant economic stake that sybils will not
/// have access to AND applying a cooldown IS a sybil mitigation. The economic
/// stake alone is NOT sufficient if gas is cheap as sybils can cycle the same
/// stake between each other. The cooldown alone is NOT sufficient as many
/// sybils can be created, each as a new `msg.sender`.
///
/// @dev Base for anything that enforces a cooldown delay on functions.
/// Cooldown requires a minimum time in blocks to elapse between actions that
/// cooldown. The modifier `onlyAfterCooldown` both enforces and triggers the
/// cooldown. There is a single cooldown across all functions per-contract
/// so any function call that requires a cooldown will also trigger it for
/// all other functions.
///
/// Cooldown is NOT an effective sybil resistance alone, as the cooldown is
/// per-address only. It is always possible for many accounts to be created
/// to spam a contract with dust in parallel.
/// Cooldown is useful to stop a single account rapidly cycling contract
/// state in a way that can be disruptive to peers. Cooldown works best when
/// coupled with economic stake associated with each state change so that
/// peers must lock capital during the cooldown. Cooldown tracks the first
/// `msg.sender` it sees for a call stack so cooldowns are enforced across
/// reentrant code.
abstract contract Cooldown {
    /// Time in blocks to restrict access to modified functions.
    uint16 public immutable cooldownDuration;

    /// Every address has its own cooldown state.
    mapping (address => uint256) public cooldowns;
    address private caller;

    /// The cooldown duration is global to the contract.
    /// Cooldown duration must be greater than 0.
    /// @param cooldownDuration_ The global cooldown duration.
    constructor(uint16 cooldownDuration_) {
        require(cooldownDuration_ > 0, "COOLDOWN_0");
        cooldownDuration = cooldownDuration_;
    }

    /// Modifies a function to enforce the cooldown for `msg.sender`.
    /// Saves the original caller so that cooldowns are enforced across
    /// reentrant code.
    modifier onlyAfterCooldown() {
        address caller_ = caller == address(0) ? caller = msg.sender : caller;
        require(cooldowns[caller_] <= block.number, "COOLDOWN");
        // Every action that requires a cooldown also triggers a cooldown.
        cooldowns[caller_] = block.number + cooldownDuration;
        _;
        delete caller;
    }
}

File 8 of 16 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @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;

    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 make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

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

File 9 of 16 : ERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);
        }

        return true;
    }

    /**
     * @dev 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) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    /**
     * @dev 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) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(_msgSender(), spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

File 10 of 16 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 11 of 16 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 12 of 16 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 13 of 16 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 14 of 16 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @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
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

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

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

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(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) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(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) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason 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 {
            // 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

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 15 of 16 : Math.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a / b + (a % b == 0 ? 0 : 1);
    }
}

File 16 of 16 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _setOwner(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _setOwner(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

Settings
{
  "metadata": {
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 100000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_contract","type":"address"}],"name":"NewContract","type":"event"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"reserve","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"seedPrice","type":"uint256"},{"internalType":"uint16","name":"seedUnits","type":"uint16"},{"internalType":"uint16","name":"cooldownDuration","type":"uint16"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"internalType":"struct ERC20Config","name":"erc20Config","type":"tuple"}],"internalType":"struct SeedERC20Config","name":"config_","type":"tuple"}],"name":"createChild","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"createChild","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"maybeChild_","type":"address"}],"name":"isChild","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b506001600055613a86806100256000396000f3fe60806040523480156200001157600080fd5b5060043610620000465760003560e01c8063144415a8146200004b5780632ea72a49146200008c578063fc91a89714620000a3575b600080fd5b620000626200005c3660046200030b565b620000f0565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620000626200009d36600462000350565b6200019a565b620000df620000b4366004620003ed565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205460ff1690565b604051901515815260200162000083565b60003073ffffffffffffffffffffffffffffffffffffffff16632ea72a49836040516020016200012191906200052f565b6040516020818303038152906040526040518263ffffffff1660e01b81526004016200014e919062000678565b6020604051808303816000875af11580156200016e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200019491906200068d565b92915050565b6000600260005414156200020e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640160405180910390fd5b60026000908155620002218484620002a9565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169092179091555192935090917f387ea218537e939551af33bbc2dd6c53b1fee55d377a0dce288258f972cb3a9c9190a260016000559392505050565b600080620002ba83850185620007e1565b905080604051620002cb90620002fd565b620002d7919062000909565b604051809103906000f080158015620002f4573d6000803e3d6000fd5b50949350505050565b61308180620009d083390190565b6000602082840312156200031e57600080fd5b813567ffffffffffffffff8111156200033657600080fd5b820160c081850312156200034957600080fd5b9392505050565b600080602083850312156200036457600080fd5b823567ffffffffffffffff808211156200037d57600080fd5b818501915085601f8301126200039257600080fd5b813581811115620003a257600080fd5b866020828501011115620003b557600080fd5b60209290920196919550909350505050565b73ffffffffffffffffffffffffffffffffffffffff81168114620003ea57600080fd5b50565b6000602082840312156200040057600080fd5b81356200034981620003c7565b803561ffff811681146200042057600080fd5b919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126200045b57600080fd5b830160208101925035905067ffffffffffffffff8111156200047c57600080fd5b8036038313156200048c57600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b6000620004ea828362000425565b60408552620004fe60408601828462000493565b91505062000510602084018462000425565b85830360208701526200052583828462000493565b9695505050505050565b60208152600082356200054281620003c7565b73ffffffffffffffffffffffffffffffffffffffff8082166020850152602085013591506200057182620003c7565b808216604085015250506040830135606083015262000593606084016200040d565b61ffff808216608085015280620005ad608087016200040d565b1660a0850152505060a08301357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1843603018112620005eb57600080fd5b60c0808401526200060260e08401858301620004dc565b949350505050565b6000815180845260005b81811015620006325760208185018101518683018201520162000614565b8181111562000645576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006200034960208301846200060a565b600060208284031215620006a057600080fd5b81516200034981620003c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715620007025762000702620006ad565b60405290565b6040805190810167ffffffffffffffff81118282101715620007025762000702620006ad565b600082601f8301126200074057600080fd5b813567ffffffffffffffff808211156200075e576200075e620006ad565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620007a757620007a7620006ad565b81604052838152866020858801011115620007c157600080fd5b836020870160208301376000602085830101528094505050505092915050565b600060208284031215620007f457600080fd5b813567ffffffffffffffff808211156200080d57600080fd5b9083019060c082860312156200082257600080fd5b6200082c620006dc565b82356200083981620003c7565b815260208301356200084b81620003c7565b60208201526040838101359082015262000868606084016200040d565b60608201526200087b608084016200040d565b608082015260a0830135828111156200089357600080fd5b929092019160408387031215620008a957600080fd5b620008b362000708565b833583811115620008c357600080fd5b620008d1888287016200072e565b825250602084013583811115620008e757600080fd5b620008f5888287016200072e565b60208301525060a082015295945050505050565b60208152600073ffffffffffffffffffffffffffffffffffffffff8084511660208401528060208501511660408401525060408301516060830152606083015161ffff80821660808501528060808601511660a0850152505060a083015160c0808401528051604060e0850152620009866101208501826200060a565b9050602082015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2084820301610100850152620009c681836200060a565b9594505050505056fe6101006040523480156200001257600080fd5b5060405162003081380380620030818339810160408190526200003591620005e7565b608081015160a0820151805160209091015162000052336200023f565b81516200006790600490602085019062000374565b5080516200007d90600590602084019062000374565b50505060005b6008811015620000e75763ffffffff60068260088110620000a857620000a8620006b5565b600891828204019190066004026101000a81548163ffffffff021916908363ffffffff1602179055508080620000de90620006e1565b91505062000083565b5060008161ffff16116200012f5760405162461bcd60e51b815260206004820152600a6024820152690434f4f4c444f574e5f360b41b60448201526064015b60405180910390fd5b61ffff166080526040810151620001735760405162461bcd60e51b8152602060048201526007602482015266050524943455f360cc1b604482015260640162000126565b6000816060015161ffff1611620001b75760405162461bcd60e51b81526020600482015260076024820152660554e4954535f360cc1b604482015260640162000126565b60208101516001600160a01b0316620002015760405162461bcd60e51b815260206004820152600b60248201526a0524543495049454e545f360ac1b604482015260640162000126565b604081015160e05280516001600160a01b0390811660a05260208201511660c05260608101516200023890309061ffff166200028f565b5062000757565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b038216620002e75760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015260640162000126565b8060036000828254620002fb9190620006ff565b90915550506001600160a01b038216600090815260016020526040812080548392906200032a908490620006ff565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b82805462000382906200071a565b90600052602060002090601f016020900481019282620003a65760008555620003f1565b82601f10620003c157805160ff1916838001178555620003f1565b82800160010185558215620003f1579182015b82811115620003f1578251825591602001919060010190620003d4565b50620003ff92915062000403565b5090565b5b80821115620003ff576000815560010162000404565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b03811182821017156200045557620004556200041a565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200048657620004866200041a565b604052919050565b6001600160a01b0381168114620004a457600080fd5b50565b805161ffff81168114620004ba57600080fd5b919050565b600082601f830112620004d157600080fd5b81516001600160401b03811115620004ed57620004ed6200041a565b602062000503601f8301601f191682016200045b565b82815285828487010111156200051857600080fd5b60005b83811015620005385785810183015182820184015282016200051b565b838111156200054a5760008385840101525b5095945050505050565b6000604082840312156200056757600080fd5b604080519081016001600160401b0380821183831017156200058d576200058d6200041a565b816040528293508451915080821115620005a657600080fd5b620005b486838701620004bf565b83526020850151915080821115620005cb57600080fd5b50620005da85828601620004bf565b6020830152505092915050565b600060208284031215620005fa57600080fd5b81516001600160401b03808211156200061257600080fd5b9083019060c082860312156200062757600080fd5b6200063162000430565b82516200063e816200048e565b8152602083015162000650816200048e565b6020820152604083810151908201526200066d60608401620004a7565b60608201526200068060808401620004a7565b608082015260a0830151828111156200069857600080fd5b620006a68782860162000554565b60a08301525095945050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415620006f857620006f8620006cb565b5060010190565b60008219821115620007155762000715620006cb565b500190565b600181811c908216806200072f57607f821691505b602082108114156200075157634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e0516128a3620007de600039600081816103a7015281816107a70152610bf701526000818161031d0152610d300152600081816104380152818161085401528181610cb501528181610d6701528181610de9015281816112be015261143f0152600081816102a8015281816107520152610a4a01526128a36000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c806366d003ac116100f95780639923c94b11610097578063cd3293de11610071578063cd3293de14610433578063db006a751461045a578063dd62ed3e1461046d578063f2fde38b146104b357600080fd5b80639923c94b146103fa578063a457c2d71461040d578063a9059cbb1461042057600080fd5b80637e34cd3d116100d35780637e34cd3d146103a257806381e45d9a146103c95780638da5cb5b146103d457806395d89b41146103f257600080fd5b806366d003ac1461031857806370a0823114610364578063715018a61461039a57600080fd5b806318160ddd1161016657806334c1df751161014057806334c1df751461029057806335269315146102a357806339509351146102dd57806345bdfa8a146102f057600080fd5b806318160ddd1461026657806323b872dd1461026e578063313ce5671461028157600080fd5b80630948909611610197578063094890961461021b578063095ea7b314610230578063166a00e41461025357600080fd5b806301320fe2146101be578063055ad42e146101f157806306fdde0314610206575b600080fd5b6101de6101cc366004612313565b60076020526000908152604090205481565b6040519081526020015b60405180910390f35b6101f96104c6565b6040516101e8919061235d565b61020e610531565b6040516101e891906123ca565b61022e61022936600461241b565b6105c3565b005b61024361023e366004612434565b6108a9565b60405190151581526020016101e8565b61022e61026136600461245e565b6108c0565b6003546101de565b61024361027c366004612480565b610e41565b604051600081526020016101e8565b6101f961029e3660046124ff565b610f29565b6102ca7f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff90911681526020016101e8565b6102436102eb366004612434565b610f96565b6103036102fe366004612594565b610fdf565b60405163ffffffff90911681526020016101e8565b61033f7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101e8565b6101de610372366004612313565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205490565b61022e611042565b6101de7f000000000000000000000000000000000000000000000000000000000000000081565b61030363ffffffff81565b60005473ffffffffffffffffffffffffffffffffffffffff1661033f565b61020e6110cf565b61030361040836600461241b565b6110de565b61024361041b366004612434565b61110e565b61024361042e366004612434565b6111e6565b61033f7f000000000000000000000000000000000000000000000000000000000000000081565b61022e61046836600461241b565b6111f3565b6101de61047b3660046125d6565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020908152604080832093909416825291909152205490565b61022e6104c1366004612313565b61146d565b6040805161010081019182905260009161052c91906006906008908286855b82829054906101000a900463ffffffff1663ffffffff16815260200190600401906020826003010492830192600103820291508084116104e5579050505050505043610f29565b905090565b60606004805461054090612609565b80601f016020809104026020016040519081016040528092919081815260200182805461056c90612609565b80156105b95780601f1061058e576101008083540402835291602001916105b9565b820191906000526020600020905b81548152906001019060200180831161059c57829003601f168201915b5050505050905090565b6000806105ce6104c6565b60088111156105df576105df61232e565b1461064b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f4241445f5048415345000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b60085460009073ffffffffffffffffffffffffffffffffffffffff161561068a5760085473ffffffffffffffffffffffffffffffffffffffff166106b8565b600880547fffffffffffffffffffffffff000000000000000000000000000000000000000016339081179091555b73ffffffffffffffffffffffffffffffffffffffff811660009081526007602052604090205490915043101561074a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f434f4f4c444f574e0000000000000000000000000000000000000000000000006044820152606401610642565b61077861ffff7f0000000000000000000000000000000000000000000000000000000000000000164361268c565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600760205260408120919091556107cb847f00000000000000000000000000000000000000000000000000000000000000006126a4565b90506107d833308661159d565b3373ffffffffffffffffffffffffffffffffffffffff167f7c14c9db98cea20a2acb2d08c72c3f77c7e2a84d19c6190d70993b9eef3c3ff960405180604001604052808781526020018481525060405161083291906126e1565b60405180910390a261087b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611852565b5050600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555050565b60006108b633848461192b565b5060015b92915050565b6000806108cb6104c6565b60088111156108dc576108dc61232e565b14610943576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f4241445f504841534500000000000000000000000000000000000000000000006044820152606401610642565b60085460009073ffffffffffffffffffffffffffffffffffffffff16156109825760085473ffffffffffffffffffffffffffffffffffffffff166109b0565b600880547fffffffffffffffffffffffff000000000000000000000000000000000000000016339081179091555b73ffffffffffffffffffffffffffffffffffffffff8116600090815260076020526040902054909150431015610a42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f434f4f4c444f574e0000000000000000000000000000000000000000000000006044820152606401610642565b610a7061ffff7f0000000000000000000000000000000000000000000000000000000000000000164361268c565b73ffffffffffffffffffffffffffffffffffffffff821660009081526007602052604090205582610afd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f444553495245445f3000000000000000000000000000000000000000000000006044820152606401610642565b82841115610b67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4d494e494d554d5f4f5645525f444553495245440000000000000000000000006044820152606401610642565b3060009081526001602052604090205480851115610be1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f494e53554646494349454e545f53544f434b00000000000000000000000000006044820152606401610642565b6000610bed8583611ade565b90506000610c1b827f00000000000000000000000000000000000000000000000000000000000000006126a4565b905081831415610c2e57610c2e43611af4565b610c3930338461159d565b3373ffffffffffffffffffffffffffffffffffffffff167f923ce970640985aa12afeae016e55fa5d676bf990ab39b5ea2466764cd44055e604051806040016040528085815260200184815250604051610c9391906126e1565b60405180910390a2610cdd73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084611d0c565b6001610ce76104c6565b6008811115610cf857610cf861232e565b1415610e10576040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610e10907f00000000000000000000000000000000000000000000000000000000000000009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610dae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd29190612712565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190611852565b5050600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555050505050565b6000610e4e84848461159d565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260026020908152604080832033845290915290205482811015610f0f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206160448201527f6c6c6f77616e63650000000000000000000000000000000000000000000000006064820152608401610642565b610f1c853385840361192b565b60019150505b9392505050565b6000805b6008811015610f8c57838160088110610f4857610f4861272b565b602002015163ffffffff168363ffffffff161015610f7a57806008811115610f7257610f7261232e565b9150506108ba565b80610f848161275a565b915050610f2d565b5060089392505050565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916108b6918590610fda90869061268c565b61192b565b600080826008811115610ff457610ff461232e565b11611000576000610f22565b8260018360088111156110155761101561232e565b61101f9190612793565b6008811061102f5761102f61272b565b602002016020810190610f2291906127aa565b60005473ffffffffffffffffffffffffffffffffffffffff1633146110c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610642565b6110cd6000611d6a565b565b60606005805461054090612609565b600681600881106110ee57600080fd5b60089182820401919006600402915054906101000a900463ffffffff1681565b33600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168452909152812054828110156111cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610642565b6111dc338585840361192b565b5060019392505050565b60006108b633848461159d565b6001806111fe6104c6565b600881111561120f5761120f61232e565b14611276576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f4241445f504841534500000000000000000000000000000000000000000000006044820152606401610642565b600061128160035490565b905061128d3384611ddf565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa15801561131a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133e9190612712565b9050600081116113aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f524553455256455f42414c414e434500000000000000000000000000000000006044820152606401610642565b6000826113b783876126a4565b6113c191906127c5565b90503373ffffffffffffffffffffffffffffffffffffffff167fdbb205db698e6b34158cdff6fba75ad516eb88dcaea40bac07ca663283cf350860405180604001604052808881526020018481525060405161141d91906126e1565b60405180910390a261146673ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163383611852565b5050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146114ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610642565b73ffffffffffffffffffffffffffffffffffffffff8116611591576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610642565b61159a81611d6a565b50565b73ffffffffffffffffffffffffffffffffffffffff8316611640576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610642565b73ffffffffffffffffffffffffffffffffffffffff82166116e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610642565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001602052604090205481811015611799576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610642565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600160205260408082208585039055918516815290812080548492906117dd90849061268c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161184391815260200190565b60405180910390a35b50505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526119269084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611fcc565b505050565b73ffffffffffffffffffffffffffffffffffffffff83166119cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610642565b73ffffffffffffffffffffffffffffffffffffffff8216611a70576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610642565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6000818310611aed5781610f22565b5090919050565b8063ffffffff164363ffffffff161115611b6a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600f60248201527f4e4558545f424c4f434b5f5041535400000000000000000000000000000000006044820152606401610642565b63ffffffff81811610611bd9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4e4558545f424c4f434b5f554e494e495449414c495a454400000000000000006044820152606401610642565b6000611be36104c6565b6008811115611bf457611bf461232e565b905060068160088110611c0957611c0961272b565b60088104919091015460079091166004026101000a900463ffffffff90811614611c8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4558545f424c4f434b5f5345540000000000000000000000000000000000006044820152606401610642565b611c98826120d8565b8160068260088110611cac57611cac61272b565b600891828204019190066004026101000a81548163ffffffff021916908363ffffffff1602179055508163ffffffff167f260aac5b840edc27b89fdf50e91311a413363a400959466e1049e6d071b8cee260405160405180910390a25050565b60405173ffffffffffffffffffffffffffffffffffffffff8085166024830152831660448201526064810182905261184c9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016118a4565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff8216611e82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610642565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090205481811015611f38576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610642565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160205260408120838303905560038054849290611f74908490612793565b909155505060405182815260009073ffffffffffffffffffffffffffffffffffffffff8516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3505050565b600061202e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166121009092919063ffffffff16565b805190915015611926578080602001905181019061204c9190612800565b611926576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610642565b60016120e26104c6565b60088111156120f3576120f361232e565b1061159a5761159a612822565b606061210f8484600085612117565b949350505050565b6060824710156121a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610642565b843b612211576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610642565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161223a9190612851565b60006040518083038185875af1925050503d8060008114612277576040519150601f19603f3d011682016040523d82523d6000602084013e61227c565b606091505b509150915061228c828286612297565b979650505050505050565b606083156122a6575081610f22565b8251156122b65782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161064291906123ca565b803573ffffffffffffffffffffffffffffffffffffffff8116811461230e57600080fd5b919050565b60006020828403121561232557600080fd5b610f22826122ea565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6020810160098310612398577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b60005b838110156123b95781810151838201526020016123a1565b8381111561184c5750506000910152565b60208152600082518060208401526123e981604085016020870161239e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60006020828403121561242d57600080fd5b5035919050565b6000806040838503121561244757600080fd5b612450836122ea565b946020939093013593505050565b6000806040838503121561247157600080fd5b50508035926020909101359150565b60008060006060848603121561249557600080fd5b61249e846122ea565b92506124ac602085016122ea565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b803563ffffffff8116811461230e57600080fd5b600080610120838503121561251357600080fd5b83601f84011261252257600080fd5b60405161010080820182811067ffffffffffffffff82111715612547576125476124bc565b6040528401818682111561255a57600080fd5b855b8281101561257b5761256d816124eb565b82526020918201910161255c565b5050819350612589816124eb565b925050509250929050565b60008061012083850312156125a857600080fd5b6101008301848111156125ba57600080fd5b83925035600981106125cb57600080fd5b809150509250929050565b600080604083850312156125e957600080fd5b6125f2836122ea565b9150612600602084016122ea565b90509250929050565b600181811c9082168061261d57607f821691505b60208210811415612657577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000821982111561269f5761269f61265d565b500190565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156126dc576126dc61265d565b500290565b60408101818360005b60028110156127095781518352602092830192909101906001016126ea565b50505092915050565b60006020828403121561272457600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561278c5761278c61265d565b5060010190565b6000828210156127a5576127a561265d565b500390565b6000602082840312156127bc57600080fd5b610f22826124eb565b6000826127fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006020828403121561281257600080fd5b81518015158114610f2257600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b6000825161286381846020870161239e565b919091019291505056fea2646970667358221220c1f426dcd312ee13a52065149e36e402d57709522a04e2248fbfb11920e4e68564736f6c634300080a0033a264697066735822122022f3502cc605c8f8c80b80da41708e90bac2388bb36ded525281bd04a1a0c23064736f6c634300080a0033

Deployed ByteCode Sourcemap

269:823:15:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;928:162;;;;;;:::i;:::-;;:::i;:::-;;;590:42:16;578:55;;;560:74;;548:2;533:18;928:162:15;;;;;;;;1870:469:11;;;;;;:::i;:::-;;:::i;2651:160::-;;;;;;:::i;:::-;2782:22;;2755:4;2782:22;;;:9;:22;;;;;;;;;2651:160;;;;1817:14:16;;1810:22;1792:41;;1780:2;1765:18;2651:160:11;1652:187:16;928:162:15;1016:7;1046:4;:16;;;1074:7;1063:19;;;;;;;;:::i;:::-;;;;;;;;;;;;;1046:37;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1039:44;928:162;-1:-1:-1;;928:162:15:o;1870:469:11:-;2000:7;1680:1:1;2259:7;;:19;;2251:63;;;;;;;5867:2:16;2251:63:1;;;5849:21:16;5906:2;5886:18;;;5879:30;5945:33;5925:18;;;5918:61;5996:18;;2251:63:1;;;;;;;;1680:1;2389:7;:18;;;2081:19:11::1;2094:5:::0;;2081:12:::1;:19::i;:::-;2177:17;::::0;::::1;;::::0;;;2197:4:::1;2177:17;::::0;;;;;;;:24;;;::::1;::::0;;::::1;::::0;;;2281:28;2064:36;;-1:-1:-1;2177:17:11;;2281:28:::1;::::0;2177:17;2281:28:::1;1637:1:1::0;2562:7;:22;2326:6:11;1870:469;-1:-1:-1;;;1870:469:11:o;341:271:15:-;433:7;;487:70;;;;511:5;487:70;:::i;:::-;452:105;;596:7;582:22;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;567:38:15;341:271;-1:-1:-1;;;;341:271:15:o;-1:-1:-1:-;;;;;;;;:::o;14:395:16:-;108:6;161:2;149:9;140:7;136:23;132:32;129:52;;;177:1;174;167:12;129:52;217:9;204:23;250:18;242:6;239:30;236:50;;;282:1;279;272:12;236:50;305:22;;361:3;343:16;;;339:26;336:46;;;378:1;375;368:12;336:46;401:2;14:395;-1:-1:-1;;;14:395:16:o;645:591::-;715:6;723;776:2;764:9;755:7;751:23;747:32;744:52;;;792:1;789;782:12;744:52;832:9;819:23;861:18;902:2;894:6;891:14;888:34;;;918:1;915;908:12;888:34;956:6;945:9;941:22;931:32;;1001:7;994:4;990:2;986:13;982:27;972:55;;1023:1;1020;1013:12;972:55;1063:2;1050:16;1089:2;1081:6;1078:14;1075:34;;;1105:1;1102;1095:12;1075:34;1150:7;1145:2;1136:6;1132:2;1128:15;1124:24;1121:37;1118:57;;;1171:1;1168;1161:12;1118:57;1202:2;1194:11;;;;;1224:6;;-1:-1:-1;645:591:16;;-1:-1:-1;;;;645:591:16:o;1241:154::-;1327:42;1320:5;1316:54;1309:5;1306:65;1296:93;;1385:1;1382;1375:12;1296:93;1241:154;:::o;1400:247::-;1459:6;1512:2;1500:9;1491:7;1487:23;1483:32;1480:52;;;1528:1;1525;1518:12;1480:52;1567:9;1554:23;1586:31;1611:5;1586:31;:::i;1844:159::-;1911:20;;1971:6;1960:18;;1950:29;;1940:57;;1993:1;1990;1983:12;1940:57;1844:159;;;:::o;2008:563::-;2067:5;2074:6;2134:3;2121:17;2216:66;2205:8;2189:14;2185:29;2181:102;2161:18;2157:127;2147:155;;2298:1;2295;2288:12;2147:155;2326:33;;2430:4;2417:18;;;-1:-1:-1;2378:21:16;;-1:-1:-1;2458:18:16;2447:30;;2444:50;;;2490:1;2487;2480:12;2444:50;2540:6;2524:14;2520:27;2510:8;2506:42;2503:62;;;2561:1;2558;2551:12;2503:62;2008:563;;;;;:::o;2576:326::-;2665:6;2660:3;2653:19;2717:6;2710:5;2703:4;2698:3;2694:14;2681:43;;2769:1;2762:4;2753:6;2748:3;2744:16;2740:27;2733:38;2635:3;2891:4;2821:66;2816:2;2808:6;2804:15;2800:88;2795:3;2791:98;2787:109;2780:116;;2576:326;;;;:::o;2907:513::-;2970:3;3022:45;3061:5;3054;3022:45;:::i;:::-;3088:4;3083:3;3076:17;3114:70;3178:4;3173:3;3169:14;3155:12;3141;3114:70;:::i;:::-;3102:82;;;3231:56;3281:4;3274:5;3270:16;3263:5;3231:56;:::i;:::-;3329:3;3323:4;3319:14;3312:4;3307:3;3303:14;3296:38;3350:64;3409:4;3393:14;3377;3350:64;:::i;:::-;3343:71;2907:513;-1:-1:-1;;;;;;2907:513:16:o;3425:1222::-;3622:2;3611:9;3604:21;3585:4;3660:6;3647:20;3676:31;3701:5;3676:31;:::i;:::-;3726:42;3815:2;3808:5;3804:14;3799:2;3788:9;3784:18;3777:42;3868:2;3860:6;3856:15;3843:29;3828:44;;3881:33;3906:7;3881:33;:::i;:::-;3963:2;3954:7;3950:16;3945:2;3934:9;3930:18;3923:44;;;4028:2;4020:6;4016:15;4003:29;3998:2;3987:9;3983:18;3976:57;4062:34;4092:2;4084:6;4080:15;4062:34;:::i;:::-;4115:6;4176:2;4162:12;4158:21;4152:3;4141:9;4137:19;4130:50;4258:2;4221:35;4251:3;4243:6;4239:16;4221:35;:::i;:::-;4217:44;4211:3;4200:9;4196:19;4189:73;;;4322:3;4314:6;4310:16;4297:30;4403:66;4394:6;4378:14;4374:27;4370:100;4350:18;4346:125;4336:153;;4485:1;4482;4475:12;4336:153;4527:4;4520;4509:9;4505:20;4498:34;4549:92;4636:3;4625:9;4621:19;4612:6;4592:18;4588:31;4549:92;:::i;:::-;4541:100;3425:1222;-1:-1:-1;;;;3425:1222:16:o;4652:530::-;4693:3;4731:5;4725:12;4758:6;4753:3;4746:19;4783:1;4793:162;4807:6;4804:1;4801:13;4793:162;;;4869:4;4925:13;;;4921:22;;4915:29;4897:11;;;4893:20;;4886:59;4822:12;4793:162;;;4973:6;4970:1;4967:13;4964:87;;;5039:1;5032:4;5023:6;5018:3;5014:16;5010:27;5003:38;4964:87;-1:-1:-1;5096:2:16;5084:15;5101:66;5080:88;5071:98;;;;5171:4;5067:109;;4652:530;-1:-1:-1;;4652:530:16:o;5187:217::-;5334:2;5323:9;5316:21;5297:4;5354:44;5394:2;5383:9;5379:18;5371:6;5354:44;:::i;5409:251::-;5479:6;5532:2;5520:9;5511:7;5507:23;5503:32;5500:52;;;5548:1;5545;5538:12;5500:52;5580:9;5574:16;5599:31;5624:5;5599:31;:::i;6025:184::-;6077:77;6074:1;6067:88;6174:4;6171:1;6164:15;6198:4;6195:1;6188:15;6214:248;6281:2;6275:9;6323:4;6311:17;;6358:18;6343:34;;6379:22;;;6340:62;6337:88;;;6405:18;;:::i;:::-;6441:2;6434:22;6214:248;:::o;6467:251::-;6539:2;6533:9;;;6569:15;;6614:18;6599:34;;6635:22;;;6596:62;6593:88;;;6661:18;;:::i;6723:778::-;6766:5;6819:3;6812:4;6804:6;6800:17;6796:27;6786:55;;6837:1;6834;6827:12;6786:55;6873:6;6860:20;6899:18;6936:2;6932;6929:10;6926:36;;;6942:18;;:::i;:::-;7076:2;7070:9;7138:4;7130:13;;6981:66;7126:22;;;7150:2;7122:31;7118:40;7106:53;;;7174:18;;;7194:22;;;7171:46;7168:72;;;7220:18;;:::i;:::-;7260:10;7256:2;7249:22;7295:2;7287:6;7280:18;7341:3;7334:4;7329:2;7321:6;7317:15;7313:26;7310:35;7307:55;;;7358:1;7355;7348:12;7307:55;7422:2;7415:4;7407:6;7403:17;7396:4;7388:6;7384:17;7371:54;7469:1;7462:4;7457:2;7449:6;7445:15;7441:26;7434:37;7489:6;7480:15;;;;;;6723:778;;;;:::o;7506:1492::-;7598:6;7651:2;7639:9;7630:7;7626:23;7622:32;7619:52;;;7667:1;7664;7657:12;7619:52;7707:9;7694:23;7736:18;7777:2;7769:6;7766:14;7763:34;;;7793:1;7790;7783:12;7763:34;7816:22;;;;7872:4;7854:16;;;7850:27;7847:47;;;7890:1;7887;7880:12;7847:47;7916:17;;:::i;:::-;7970:2;7957:16;7982:33;8007:7;7982:33;:::i;:::-;8024:22;;8091:2;8083:11;;8070:25;8104:33;8070:25;8104:33;:::i;:::-;8164:2;8153:14;;8146:31;8230:2;8222:11;;;8209:25;8193:14;;;8186:49;8267:30;8293:2;8285:11;;8267:30;:::i;:::-;8262:2;8255:5;8251:14;8244:54;8331:31;8357:3;8353:2;8349:12;8331:31;:::i;:::-;8325:3;8318:5;8314:15;8307:56;8409:3;8405:2;8401:12;8388:26;8439:2;8429:8;8426:16;8423:36;;;8455:1;8452;8445:12;8423:36;8478:17;;;;;8529:2;8511:16;;;8507:25;8504:45;;;8545:1;8542;8535:12;8504:45;8573:22;;:::i;:::-;8633:2;8620:16;8661:2;8651:8;8648:16;8645:36;;;8677:1;8674;8667:12;8645:36;8706:45;8743:7;8732:8;8728:2;8724:17;8706:45;:::i;:::-;8697:7;8690:62;;8798:2;8794;8790:11;8777:25;8827:2;8817:8;8814:16;8811:36;;;8843:1;8840;8833:12;8811:36;8881:45;8918:7;8907:8;8903:2;8899:17;8881:45;:::i;:::-;8876:2;8863:16;;8856:71;-1:-1:-1;8954:3:16;8943:15;;8936:32;8947:5;7506:1492;-1:-1:-1;;;;;7506:1492:16:o;9003:1172::-;9198:2;9187:9;9180:21;9161:4;9220:42;9317:2;9308:6;9302:13;9298:22;9293:2;9282:9;9278:18;9271:50;9385:2;9379;9371:6;9367:15;9361:22;9357:31;9352:2;9341:9;9337:18;9330:59;;9443:2;9435:6;9431:15;9425:22;9420:2;9409:9;9405:18;9398:50;9495:2;9487:6;9483:15;9477:22;9518:6;9579:2;9565:12;9561:21;9555:3;9544:9;9540:19;9533:50;9649:2;9642:3;9634:6;9630:16;9624:23;9620:32;9614:3;9603:9;9599:19;9592:61;;;9702:3;9694:6;9690:16;9684:23;9745:4;9738;9727:9;9723:20;9716:34;9787:14;9781:21;9839:2;9833:3;9822:9;9818:19;9811:31;9865:53;9913:3;9902:9;9898:19;9882:14;9865:53;:::i;:::-;9851:67;;9975:2;9959:14;9955:23;9949:30;9927:52;;10044:66;10032:9;10024:6;10020:22;10016:95;10010:3;9999:9;9995:19;9988:124;10129:40;10162:6;10146:14;10129:40;:::i;:::-;10121:48;9003:1172;-1:-1:-1;;;;;9003:1172:16:o

Swarm Source

ipfs://22f3502cc605c8f8c80b80da41708e90bac2388bb36ded525281bd04a1a0c230
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Validator ID :
0 FTM

Amount Staked
0

Amount Delegated
0

Staking Total
0

Staking Start Epoch
0

Staking Start Time
0

Proof of Importance
0

Origination Score
0

Validation Score
0

Active
0

Online
0

Downtime
0 s
Address Amount claimed Rewards Created On Epoch Created On
Block Uncle Number Difficulty Gas Used Reward
Loading