creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "lib/LayerZero/contracts/interfaces/ILayerZeroReceiver.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity >=0.5.0;\n\ninterface ILayerZeroReceiver {\n    // @notice LayerZero endpoint will invoke this function to deliver the message on the destination\n    // @param _srcChainId - the source endpoint identifier\n    // @param _srcAddress - the source sending contract address from the source chain\n    // @param _nonce - the ordered message nonce\n    // @param _payload - the signed payload is the UA bytes has encoded to be sent\n    function lzReceive(uint16 _srcChainId, bytes calldata _srcAddress, uint64 _nonce, bytes calldata _payload) external;\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20.sol\";\n"
      },
      "lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "src/DCBTokenClaim.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\n//** DCB Token claim Contract */\n//** Author: Aceson 2022.3 */\n\npragma solidity 0.8.19;\n\nimport \"openzeppelin-contracts/contracts/interfaces/IERC20.sol\";\nimport \"openzeppelin-contracts/contracts/proxy/utils/Initializable.sol\";\n\nimport \"./interfaces/IDCBInvestments.sol\";\nimport \"./interfaces/IDCBPlatformVesting.sol\";\nimport \"./interfaces/IDCBTokenClaim.sol\";\nimport \"layerzero/interfaces/ILayerZeroReceiver.sol\";\n\ncontract DCBTokenClaim is Initializable, ILayerZeroReceiver, IDCBTokenClaim {\n    IDCBInvestments public _investment; //Investments contract\n    IERC20 public _rewardToken; //Token to be used for tier calc\n    IDCBPlatformVesting public _vesting; //Vesting contract\n    address public layerZero; //Layerzero contract address\n\n    //Keccack(<hidden answer>)\n    /* solhint-disable var-name-mixedcase */\n    bytes32 public ANSWER_HASH;\n    uint256 public totalShares; //Total shares for the event\n\n    mapping(address => UserAllocation) public userAllocation; //Allocation per user\n\n    ClaimInfo public claimInfo;\n    Tiers[] public tierInfo;\n\n    address[] private participants;\n    address[] private registeredUsers;\n    address public tierMigratorAddr;\n    uint16 internal nativeChainId;\n\n    uint8 public constant VERSION = 1;\n\n    event CreateTokenClaim(Params p);\n    event UserRegistered(address user);\n    event UserClaimed(address user, uint256 amount);\n\n    modifier onlyManager() {\n        require(_investment.hasRole(keccak256(\"MANAGER_ROLE\"), msg.sender), \"Only manager\");\n        _;\n    }\n\n    function initialize(Params calldata p) external initializer {\n        require(p.distAmount > 0 && p.startDate >= block.timestamp && p.endDate > p.startDate, \"Invalid params\");\n        _investment = IDCBInvestments(msg.sender);\n        _rewardToken = IERC20(p.rewardTokenAddr);\n        _vesting = IDCBPlatformVesting(p.vestingAddr);\n        layerZero = p.layerZeroAddr;\n        tierMigratorAddr = p.tierMigratorAddr;\n        nativeChainId = p.nativeChainId;\n\n        /**\n         * Generate the new Claim Event\n         */\n        claimInfo.minTier = p.minTier;\n        claimInfo.distAmount = p.distAmount;\n        claimInfo.createDate = uint32(block.timestamp);\n        claimInfo.startDate = p.startDate;\n        claimInfo.endDate = p.endDate;\n\n        ANSWER_HASH = p.answerHash;\n\n        for (uint256 i = 0; i < p.tiers.length; i++) {\n            tierInfo.push(Tiers({ minLimit: p.tiers[i].minLimit, multi: p.tiers[i].multi }));\n        }\n\n        emit CreateTokenClaim(p);\n    }\n\n    /**\n     * @notice Set the params for the claim\n     *\n     * @param p Params struct\n     */\n    function setParams(Params calldata p) external {\n        require(msg.sender == address(_investment), \"Only factory\");\n        require(p.distAmount > 0 && p.startDate >= block.timestamp && p.endDate > p.startDate, \"Invalid params\");\n\n        claimInfo.minTier = p.minTier;\n        claimInfo.distAmount = p.distAmount;\n        claimInfo.startDate = p.startDate;\n        claimInfo.endDate = p.endDate;\n\n        _rewardToken = IERC20(p.rewardTokenAddr);\n        ANSWER_HASH = p.answerHash;\n\n        for (uint256 i = 0; i < p.tiers.length; i++) {\n            tierInfo[i] = Tiers({ minLimit: p.tiers[i].minLimit, multi: p.tiers[i].multi });\n        }\n    }\n\n    /**\n     *  @notice Register user for the claim\n     *\n     * @param _user  User address\n     * @param _tier  Tier of the user\n     * @param _multi  Multiplier of the user\n     * @param _shares  Shares of the user\n     */\n    function registerForAllocation(address _user, uint8 _tier, uint8 _multi, uint256 _shares) public returns (bool) {\n        require(msg.sender == (layerZero) || msg.sender == tierMigratorAddr, \"Invalid sender\");\n\n        if (_tier < claimInfo.minTier) return false;\n\n        (, uint16 _holdMulti) = getTier(_user);\n        _shares = _shares * _holdMulti / 1000;\n        uint256 oldShares = userAllocation[_user].shares;\n\n        if (userAllocation[_user].active == 0) registeredUsers.push(_user);\n        userAllocation[_user].active = 1;\n        userAllocation[_user].registeredTier = _tier;\n        userAllocation[_user].multi = _multi;\n\n        if (oldShares != _shares) {\n            userAllocation[_user].shares = _shares;\n            totalShares = totalShares - oldShares + _shares;\n        }\n\n        emit UserRegistered(_user);\n\n        return true;\n    }\n\n    /**\n     * @notice Register bulk users for the claim\n     *\n     * @param _users  Array of users\n     * @param _tierOfUser  Array of tiers\n     * @param _multiOfUser  Array of multipliers\n     * @param _sharesOfUser  Array of shares\n     */\n    function registerByManager(\n        address[] calldata _users,\n        uint8[] calldata _tierOfUser,\n        uint8[] calldata _multiOfUser,\n        uint256[] calldata _sharesOfUser\n    )\n        external\n        onlyManager\n    {\n        require((_users.length == _tierOfUser.length) && (_tierOfUser.length == _multiOfUser.length), \"Invalid input\");\n        uint256 len = _users.length;\n        uint256 total;\n        require(block.timestamp <= claimInfo.endDate && block.timestamp >= claimInfo.startDate, \"Registration closed\");\n\n        for (uint256 i = 0; i < len; i++) {\n            require(userAllocation[_users[i]].active == 0, \"Already registered\");\n\n            (, uint16 _holdMulti) = getTier(_users[i]);\n            uint256 shares = _sharesOfUser[i] * _holdMulti / 1000;\n\n            userAllocation[_users[i]].active = 1;\n            userAllocation[_users[i]].shares = shares;\n            userAllocation[_users[i]].registeredTier = _tierOfUser[i];\n            userAllocation[_users[i]].multi = _multiOfUser[i];\n\n            registeredUsers.push(_users[i]);\n\n            total = total + shares;\n            emit UserRegistered(_users[i]);\n        }\n\n        totalShares = totalShares + total;\n    }\n\n    /**\n     *  @notice Callback function for layerzero\n     *\n     * @param _id  Chain id\n     * @param _srcAddress  Source address\n     * param null  Null\n     * @param data  Data received\n     */\n    function lzReceive(uint16 _id, bytes calldata _srcAddress, uint64, bytes memory data) public override {\n        require(\n            _id == nativeChainId\n                && keccak256(_srcAddress) == keccak256(abi.encodePacked(tierMigratorAddr, address(this))),\n            \"Invalid source\"\n        );\n\n        address user;\n        uint8 tier;\n        uint8 multi;\n        uint256 shares;\n\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            // Extract the address from data (first 20 bytes)\n            user := mload(add(data, 20))\n\n            // Extract the first uint8 (21st byte)\n            tier := byte(0, mload(add(data, 52)))\n\n            // Extract the second uint8 (22nd byte)\n            multi := byte(0, mload(add(data, 53)))\n\n            // Extract the third uint256 (last 32 bytes)\n            shares := mload(add(data, 54))\n        }\n\n        registerForAllocation(user, tier, multi, shares);\n    }\n\n    /**\n     * @notice Set the token to be used for claim\n     *\n     * @param _token Token address\n     */\n    function setToken(address _token) external {\n        require(msg.sender == address(_investment), \"Only factory\");\n        _rewardToken = IERC20(_token);\n    }\n\n    /**\n     * @notice Function to claim tokens for the user\n     *\n     * @return bool Returns true if successful\n     */\n    function claimTokens() external returns (bool) {\n        UserAllocation storage user = userAllocation[msg.sender];\n\n        require(user.active == 1, \"Not registered / Already claimed\");\n        require(block.timestamp >= claimInfo.endDate, \"Claim not open yet\");\n\n        uint256 amount = getClaimableAmount(msg.sender);\n\n        user.shares = 0;\n        user.claimedAmount = amount;\n        user.active = 0;\n\n        if (amount > 0) {\n            participants.push(msg.sender);\n            _investment.setUserInvestment(msg.sender, address(this), amount);\n            _vesting.setTokenClaimWhitelist(msg.sender, amount);\n        }\n\n        emit UserClaimed(msg.sender, amount);\n\n        return true;\n    }\n\n    /**\n     * @notice Getter function for participants\n     */\n    function getParticipants() external view returns (address[] memory) {\n        return participants;\n    }\n\n    /**\n     * @notice Getter function for registered users\n     */\n    function getRegisteredUsers() external view returns (address[] memory) {\n        return registeredUsers;\n    }\n\n    /**\n     *  @notice Function to get the claim amount for shares\n     *\n     * @param _shares Shares to be checked\n     */\n    function getClaimForShares(uint256 _shares) public view returns (uint256) {\n        if (totalShares == 0) return 0;\n        return (_shares * claimInfo.distAmount / totalShares);\n    }\n\n    /**\n     * @notice Function to get the claimable amount for a user\n     *\n     * @param _address Address to be checked\n     */\n    function getClaimableAmount(address _address) public view returns (uint256) {\n        if (totalShares == 0) return 0;\n        return (userAllocation[_address].shares * claimInfo.distAmount / totalShares);\n    }\n\n    /**\n     * @notice Function to get the hold tier of a user\n     *\n     * @param _user User address\n     * @return _tier  Tier of the user\n     * @return _holdMulti  Multiplier of the user\n     */\n    function getTier(address _user) public view returns (uint256 _tier, uint16 _holdMulti) {\n        uint256 len = tierInfo.length;\n        uint256 amount = _rewardToken.balanceOf(_user);\n\n        for (uint256 i = len - 1; i >= 0; i--) {\n            if (amount >= tierInfo[i].minLimit) {\n                return (i, tierInfo[i].multi);\n            }\n        }\n    }\n}\n"
      },
      "src/interfaces/IDCBInvestments.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\n//** DCB Investments Interface */\n//** Author Aaron & Aceson : DCB 2023.2 */\n\npragma solidity 0.8.19;\n\ninterface IDCBInvestments {\n    event DistributionClaimed(address _user, address _event);\n    event ImplementationsChanged(address _newVesting, address _newTokenClaim, address _newCrowdfunding);\n    event Initialized(uint8 version);\n    event ManagerRoleSet(address _user, bool _status);\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n    event UserInvestmentSet(address _address, address _event, uint256 _amount);\n\n    function changeImplementations(address _newVesting, address _newTokenClaim, address _newCrowdfunding) external;\n\n    function changeVestingStartTime(address _event, uint256 _newTime) external;\n\n    function claimDistribution(address _event) external returns (bool);\n\n    function crowdfundingImpl() external view returns (address);\n\n    function events(address)\n        external\n        view\n        returns (\n            string memory name,\n            address paymentToken,\n            address tokenAddress,\n            address vestingAddress,\n            uint8 eventType\n        );\n\n    function eventsList(uint256) external view returns (address);\n\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    function getUserInvestments(address _address) external view returns (address[] memory);\n\n    function grantRole(bytes32 role, address account) external;\n\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    function initialize() external;\n\n    function numUserInvestments(address) external view returns (uint256);\n\n    function renounceRole(bytes32 role, address account) external;\n\n    function revokeRole(bytes32 role, address account) external;\n\n    function setManagerRole(address _user, bool _status) external;\n\n    function setUserInvestment(address _address, address _event, uint256 _amount) external returns (bool);\n\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n\n    function tokenClaimImpl() external view returns (address);\n\n    function userAmount(address, address) external view returns (uint256);\n\n    function vestingImpl() external view returns (address);\n}\n"
      },
      "src/interfaces/IDCBPlatformVesting.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\n//** DCB Vesting Interface */\n\npragma solidity 0.8.19;\n\ninterface IDCBPlatformVesting {\n    struct VestingInfo {\n        uint256 cliff;\n        uint256 start;\n        uint256 duration;\n        uint256 initialUnlockPercent;\n    }\n\n    struct VestingPool {\n        uint256 cliff;\n        uint256 start;\n        uint256 duration;\n        uint256 initialUnlockPercent;\n        WhitelistInfo[] whitelistPool;\n        mapping(address => HasWhitelist) hasWhitelist;\n    }\n\n    /**\n     *\n     * @dev WhiteInfo is the struct type which store whitelist information\n     *\n     */\n    struct WhitelistInfo {\n        address wallet;\n        uint256 amount;\n        uint256 distributedAmount;\n        uint256 value; // price * amount in decimals of payment token\n        uint256 joinDate;\n        uint256 refundDate;\n        bool refunded;\n    }\n\n    struct HasWhitelist {\n        uint256 arrIdx;\n        bool active;\n    }\n\n    struct ContractSetup {\n        address _innovator;\n        address _vestedToken;\n        address _paymentToken;\n        uint32 _nativeChainId;\n        uint256 _totalTokenOnSale;\n        uint256 _gracePeriod;\n        uint256[] _refundFees;\n    }\n\n    struct VestingSetup {\n        uint256 _startTime;\n        uint256 _cliff;\n        uint256 _duration;\n        uint256 _initialUnlockPercent;\n    }\n\n    struct BuybackSetup {\n        address router;\n        address[] path;\n    }\n\n    event Claim(address indexed token, uint256 amount, uint256 time);\n\n    event SetWhitelist(address indexed wallet, uint256 amount, uint256 value);\n\n    event Refund(address indexed wallet, uint256 amount);\n\n    function initializeCrowdfunding(ContractSetup memory c, VestingSetup memory p, BuybackSetup memory b) external;\n\n    function initializeTokenClaim(address _token, VestingSetup memory p, uint32 _nativeChainId) external;\n\n    function setCrowdfundingWhitelist(address _wallet, uint256 _amount, uint256 _value) external;\n\n    function setTokenClaimWhitelist(address _wallet, uint256 _amount) external;\n\n    function claimDistribution(address _wallet) external returns (bool);\n\n    function getWhitelist(address _wallet) external view returns (WhitelistInfo memory);\n\n    function getWhitelistPool() external view returns (WhitelistInfo[] memory);\n\n    function transferOwnership(address _newOwner) external;\n\n    function setVestingParams(\n        uint256 _cliff,\n        uint256 _start,\n        uint256 _duration,\n        uint256 _initialUnlockPercent\n    )\n        external;\n\n    function setCrowdFundingParams(ContractSetup calldata c) external;\n\n    function setToken(address _newToken) external;\n\n    function rescueTokens(address _receiver, uint256 _amount) external;\n\n    /**\n     *\n     * inherit functions will be used in contract\n     *\n     */\n    function getVestAmount(address _wallet) external view returns (uint256);\n\n    function getReleasableAmount(address _wallet) external view returns (uint256);\n\n    function getVestingInfo() external view returns (VestingInfo memory);\n}\n"
      },
      "src/interfaces/IDCBTokenClaim.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.19;\n\n/* solhint-disable */\n\ninterface IDCBTokenClaim {\n    struct Params {\n        uint8 minTier;\n        uint16 nativeChainId;\n        uint32 startDate;\n        uint32 endDate;\n        address rewardTokenAddr;\n        address vestingAddr;\n        address tierMigratorAddr;\n        address layerZeroAddr;\n        bytes32 answerHash;\n        uint256 distAmount;\n        Tiers[] tiers;\n    }\n\n    struct Tiers {\n        uint256 minLimit;\n        uint16 multi;\n    }\n\n    struct UserAllocation {\n        uint8 active; //Is active or not\n        uint8 registeredTier; //Tier of user while registering\n        uint8 multi; //Multiplier of user while registering\n        uint256 shares; //Shares owned by user\n        uint256 claimedAmount; //Claimed amount from event\n    }\n\n    struct ClaimInfo {\n        uint8 minTier; //Minimum tier required for users while registering\n        uint32 createDate; //Created date\n        uint32 startDate; //Event start date\n        uint32 endDate; //Event end date\n        uint256 distAmount; //Total distributed amount\n    }\n\n    function ANSWER_HASH() external view returns (bytes32);\n\n    function claimInfo()\n        external\n        view\n        returns (uint8 minTier, uint32 createDate, uint32 startDate, uint32 endDate, uint256 distAmount);\n\n    function claimTokens() external returns (bool);\n\n    function getClaimableAmount(address _address) external view returns (uint256);\n\n    function getParticipants() external view returns (address[] memory);\n\n    function getRegisteredUsers() external view returns (address[] memory);\n\n    function getTier(address _user) external view returns (uint256 _tier, uint16 _holdMulti);\n\n    function initialize(Params memory p) external;\n\n    function setParams(Params calldata p) external;\n\n    function setToken(address _token) external;\n\n    function registerForAllocation(address _user, uint8 _tier, uint8 _multi, uint256 _shares) external returns (bool);\n\n    function registerByManager(\n        address[] calldata _users,\n        uint8[] calldata _tierOfUser,\n        uint8[] calldata _multiOfUser,\n        uint256[] calldata _sharesOfUser\n    )\n        external;\n\n    function tierInfo(uint256) external view returns (uint256 minLimit, uint16 multi);\n\n    function totalShares() external view returns (uint256);\n\n    function userAllocation(address)\n        external\n        view\n        returns (uint8 active, uint8 registeredTier, uint8 multi, uint256 shares, uint256 claimedAmount);\n}\n"
      }
    },
    "settings": {
      "metadata": {
        "bytecodeHash": "none"
      },
      "optimizer": {
        "enabled": true,
        "runs": 10000
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "remappings": [
        "@prb/test/=lib/prb-math/lib/prb-test/src/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "forge-std/=lib/forge-std/src/",
        "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "src/=src/",
        "v2-periphery/=lib/v2-periphery/contracts/",
        "layerzero/=lib/LayerZero/contracts/",
        "LayerZero/=lib/LayerZero/contracts/",
        "prb-math/=lib/prb-math/src/",
        "prb-test/=lib/prb-test/src/"
      ],
      "libraries": {}
    }
  }}