ETH Price: $3,380.32 (-1.94%)
Gas: 4 Gwei

Contract

0x3c0417900F5231D448c32C7F4caD40E1EfaD36fC
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Claim200036152024-06-02 10:43:2330 days ago1717325003IN
0x3c041790...1EfaD36fC
0 ETH0.000359057.29954405
Claim197481662024-04-27 17:30:1166 days ago1714239011IN
0x3c041790...1EfaD36fC
0 ETH0.000277775.64541885
Claim194293662024-03-13 23:21:35111 days ago1710372095IN
0x3c041790...1EfaD36fC
0 ETH0.0016438754.79571039
Claim194289722024-03-13 22:01:47111 days ago1710367307IN
0x3c041790...1EfaD36fC
0 ETH0.0019062763.54256877
Claim194289642024-03-13 22:00:11111 days ago1710367211IN
0x3c041790...1EfaD36fC
0 ETH0.0016745355.81796655
Claim194289602024-03-13 21:59:23111 days ago1710367163IN
0x3c041790...1EfaD36fC
0 ETH0.0016358254.52753896
Claim192494122024-02-17 18:39:23136 days ago1708195163IN
0x3c041790...1EfaD36fC
0 ETH0.0008819717.92311036
Claim191150922024-01-29 22:14:47155 days ago1706566487IN
0x3c041790...1EfaD36fC
0 ETH0.0004586814.15653011
Claim190749672024-01-24 7:20:11160 days ago1706080811IN
0x3c041790...1EfaD36fC
0 ETH0.000308869.5327077
Claim190540302024-01-21 8:25:23163 days ago1705825523IN
0x3c041790...1EfaD36fC
0 ETH0.000317369.79490619
Claim190540102024-01-21 8:21:23163 days ago1705825283IN
0x3c041790...1EfaD36fC
0 ETH0.0003385610.44909043
Claim190539182024-01-21 8:02:59163 days ago1705824179IN
0x3c041790...1EfaD36fC
0 ETH0.000311339.60870526
Claim190536002024-01-21 6:59:11163 days ago1705820351IN
0x3c041790...1EfaD36fC
0 ETH0.000321639.92673737
Claim190534502024-01-21 6:29:11163 days ago1705818551IN
0x3c041790...1EfaD36fC
0 ETH0.000319519.86131098
Claim190203312024-01-16 15:24:59168 days ago1705418699IN
0x3c041790...1EfaD36fC
0 ETH0.0013801342.57977788
Claim186029292023-11-19 2:37:47226 days ago1700361467IN
0x3c041790...1EfaD36fC
0 ETH0.0006652913.53021846
Claim185963892023-11-18 4:34:11227 days ago1700282051IN
0x3c041790...1EfaD36fC
0 ETH0.0007988716.24684299
Claim185941142023-11-17 20:55:23228 days ago1700254523IN
0x3c041790...1EfaD36fC
0 ETH0.001194924.30106725
Claim177841002023-07-27 11:27:47341 days ago1690457267IN
0x3c041790...1EfaD36fC
0 ETH0.0010015920.35131859
Claim174527072023-06-10 22:23:23388 days ago1686435803IN
0x3c041790...1EfaD36fC
0 ETH0.0004549814.02674041
Transfer172171502023-05-08 17:06:59421 days ago1683565619IN
0x3c041790...1EfaD36fC
0 ETH0.0038255182.16696074
Claim168701582023-03-20 16:45:23470 days ago1679330723IN
0x3c041790...1EfaD36fC
0 ETH0.000741522.87673316
Claim168671332023-03-20 6:34:47470 days ago1679294087IN
0x3c041790...1EfaD36fC
0 ETH0.0003564111
Claim168583722023-03-19 1:01:47472 days ago1679187707IN
0x3c041790...1EfaD36fC
0 ETH0.0008163316.60661616
Claim167923332023-03-09 18:08:59481 days ago1678385339IN
0x3c041790...1EfaD36fC
0 ETH0.0048077637.61853104
View all transactions

Latest 5 internal transactions

Advanced mode:
Parent Transaction Hash Block From To Value
164383172023-01-19 3:58:23530 days ago1674100703
0x3c041790...1EfaD36fC
0.01361138 ETH
152589482022-08-01 20:57:00701 days ago1659387420
0x3c041790...1EfaD36fC
0.0037784 ETH
152448052022-07-30 16:13:20703 days ago1659197600
0x3c041790...1EfaD36fC
0.0015 ETH
152447632022-07-30 16:03:58703 days ago1659197038
0x3c041790...1EfaD36fC
0.00205 ETH
152147292022-07-25 23:44:25708 days ago1658792665
0x3c041790...1EfaD36fC
0.0045 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
OndoCoinlistDistributor

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 23 : OndoCoinlistDistributor.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.3;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "@openzeppelin/contracts/proxy/Clones.sol";
import "contracts/OndoRegistryClient.sol";
import "contracts/interfaces/IOndoCoinlistDistributor.sol";
import "contracts/interfaces/IOndo.sol";
import "contracts/libraries/OndoLibrary.sol";

/**
 * @dev OndoCoinlistDistributor
 *
 * Distributes Ondo token to a timelocked contract
 * Users can claim drops by providing correct proofs.
 *
 * @notice Ondo governance must approve this contract to transfer tokens
 */
contract OndoCoinlistDistributor is
  IOndoCoinlistDistributor,
  OndoRegistryClient
{
  /// @notice use SafeERC20
  using SafeERC20 for IERC20;

  /// @dev Ondo token contract
  address public immutable override ondo;
  /// @dev Token multisig with Ondo to claim
  address public ondoMultisig;
  /// @dev The merkle root which will be used to verify claims
  bytes32 public override merkleRoot;
  /// @dev The investorType that claims from this contract
  IOndo.InvestorType public immutable investorType;

  /// @dev This is a packed array of booleans.
  mapping(uint256 => uint256) private claimedBitMap;

  constructor(
    address _ondo,
    address _ondoMultisig,
    address _registry,
    bytes32 _merkleRoot,
    IOndo.InvestorType _investorType
  ) OndoRegistryClient(_registry) {
    ondo = _ondo;
    ondoMultisig = _ondoMultisig;
    merkleRoot = _merkleRoot;
    investorType = _investorType;
  }

  /**
   * @dev Check if the user of the merkle index has claimed drops already.
   * @param index - The merkle index
   * @return true if it's claimed, otherwise false
   */
  function isClaimed(uint256 index) public view override returns (bool) {
    uint256 claimedWordIndex = index / 256;
    uint256 claimedBitIndex = index % 256;
    uint256 claimedWord = claimedBitMap[claimedWordIndex];
    uint256 mask = (1 << claimedBitIndex);
    return claimedWord & mask == mask;
  }

  /**
   * @dev Marks that the user of the merkle index has claimed drops.
   * @param index - The merkle index
   */
  function _setClaimed(uint256 index) private {
    uint256 claimedWordIndex = index / 256;
    uint256 claimedBitIndex = index % 256;
    claimedBitMap[claimedWordIndex] =
      claimedBitMap[claimedWordIndex] |
      (1 << claimedBitIndex);
  }

  /**
   * @notice Marks that the user of the merkle index has claimed drops.
   * @param _newMultisig - Address that holds Ondo to transfer to the user
   */
  function updateMultisig(address _newMultisig)
    external
    isAuthorized(OLib.GOVERNANCE_ROLE)
  {
    ondoMultisig = _newMultisig;
    emit MultiSigUpdated(_newMultisig);
  }

  /**
   * @dev Allows users to claim tokens.
   * It reverts when the user has already claimed or after terminated.
   * index, account, amount, merkleProof - all these data has been used
   * to contribute merkle tree, hence users must keep it securely and provide correct data
   * or it will fail to claim.
   *
   * @param index       - The merkle index
   * @param account     - The address of the user
   * @param amount      - The amount to be distributed to the user
   * @param merkleProof - The merkle proof
   */
  function claim(
    uint256 index,
    address account,
    uint256 amount,
    bytes32[] calldata merkleProof
  ) external override {
    require(msg.sender == account, "Can't claim another user's tokens");
    require(!isClaimed(index), "Ondo: Drop already claimed.");

    // Verify the merkle proof.
    bytes32 node = keccak256(abi.encodePacked(index, account, amount));
    require(
      MerkleProof.verify(merkleProof, merkleRoot, node),
      "Ondo: Invalid proof."
    );

    // Mark address as claimed
    _setClaimed(index);

    // Set tranche balances for user
    IOndo(ondo).updateTrancheBalance(account, amount, investorType);

    IERC20(ondo).safeTransferFrom(ondoMultisig, account, amount);

    emit Claimed(index, account, amount);
  }
}

File 2 of 23 : 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 3 of 23 : 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'
        // solhint-disable-next-line max-line-length
        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
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 4 of 23 : MerkleProof.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle trees (hash trees),
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        bytes32 computedHash = leaf;

        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];

            if (computedHash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
            }
        }

        // Check if the computed hash (root) is equal to the provided root
        return computedHash == root;
    }
}

File 5 of 23 : Clones.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for
 * deploying minimal proxy contracts, also known as "clones".
 *
 * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
 * > a minimal bytecode implementation that delegates all calls to a known, fixed address.
 *
 * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
 * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
 * deterministic method.
 *
 * _Available since v3.4._
 */
library Clones {
    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create opcode, which should never revert.
     */
    function clone(address implementation) internal returns (address instance) {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            instance := create(0, ptr, 0x37)
        }
        require(instance != address(0), "ERC1167: create failed");
    }

    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create2 opcode and a `salt` to deterministically deploy
     * the clone. Using the same `implementation` and `salt` multiple time will revert, since
     * the clones cannot be deployed twice at the same address.
     */
    function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
            instance := create2(0, ptr, 0x37, salt)
        }
        require(instance != address(0), "ERC1167: create2 failed");
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(address implementation, bytes32 salt, address deployer) internal pure returns (address predicted) {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(ptr, 0x14), shl(0x60, implementation))
            mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
            mstore(add(ptr, 0x38), shl(0x60, deployer))
            mstore(add(ptr, 0x4c), salt)
            mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
            predicted := keccak256(add(ptr, 0x37), 0x55)
        }
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(address implementation, bytes32 salt) internal view returns (address predicted) {
        return predictDeterministicAddress(implementation, salt, address(this));
    }
}

File 6 of 23 : OndoRegistryClient.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.3;

import "contracts/OndoRegistryClientInitializable.sol";

abstract contract OndoRegistryClient is OndoRegistryClientInitializable {
  constructor(address _registry) {
    __OndoRegistryClient__initialize(_registry);
  }
}

File 7 of 23 : IOndoCoinlistDistributor.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.0;

// Allows anyone to claim a token if they exist in a merkle root.
interface IOndoCoinlistDistributor {
  // Returns the ondo token address.
  function ondo() external view returns (address);

  // Returns the merkle root of the merkle tree containing account balances available to claim.
  function merkleRoot() external view returns (bytes32);

  // Returns true if the index has been marked claimed.
  function isClaimed(uint256 index) external view returns (bool);

  // Claim the given amount of the token to the given address. Reverts if the inputs are invalid.
  function claim(
    uint256 index,
    address account,
    uint256 amount,
    bytes32[] calldata merkleProof
  ) external;

  // This event is triggered whenever a call to #claim succeeds.
  event Claimed(uint256 index, address account, uint256 amount);

  // This event is triggered whenever we update the multiSig that distributes Ondo
  event MultiSigUpdated(address newMultisig);
}

File 8 of 23 : IOndo.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.3;

interface IOndo {
  enum InvestorType {
    CoinlistTranche1,
    CoinlistTranche2,
    SeedTranche
  }

  // ----------- State changing api -----------

  /// @notice Called by timelock contract to initialize locked balance of coinlist/seed investor
  function updateTrancheBalance(
    address beneficiary,
    uint256 rawAmount,
    InvestorType tranche
  ) external;

  // ----------- Getters -----------

  /// @notice Gets the TOTAL amount of Ondo available for an address
  function getFreedBalance(address account) external view returns (uint96);

  /// @notice Gets the initial locked balance and unlocked Ondo for an address
  function getVestedBalance(address account)
    external
    view
    returns (uint96, uint96);
}

File 9 of 23 : OndoLibrary.sol
/**SPDX-License-Identifier: AGPL-3.0

          ▄▄█████████▄                                                                  
       ╓██▀└ ,╓▄▄▄, '▀██▄                                                               
      ██▀ ▄██▀▀╙╙▀▀██▄ └██µ           ,,       ,,      ,     ,,,            ,,,         
     ██ ,██¬ ▄████▄  ▀█▄ ╙█▄      ▄███▀▀███▄   ███▄    ██  ███▀▀▀███▄    ▄███▀▀███,     
    ██  ██ ╒█▀'   ╙█▌ ╙█▌ ██     ▐██      ███  █████,  ██  ██▌    └██▌  ██▌     └██▌    
    ██ ▐█▌ ██      ╟█  █▌ ╟█     ██▌      ▐██  ██ └███ ██  ██▌     ╟██ j██       ╟██    
    ╟█  ██ ╙██    ▄█▀ ▐█▌ ██     ╙██      ██▌  ██   ╙████  ██▌    ▄██▀  ██▌     ,██▀    
     ██ "██, ╙▀▀███████████⌐      ╙████████▀   ██     ╙██  ███████▀▀     ╙███████▀`     
      ██▄ ╙▀██▄▄▄▄▄,,,                ¬─                                    '─¬         
       ╙▀██▄ '╙╙╙▀▀▀▀▀▀▀▀                                                               
          ╙▀▀██████R⌐                                                                   

 */
pragma solidity >=0.8.3;

import "@openzeppelin/contracts/utils/Arrays.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/**
 * @title Helper functions
 */
library OLib {
  using Arrays for uint256[];

  // State transition per Vault. Just linear transitions.
  enum State {
    Inactive,
    Deposit,
    Live,
    Withdraw
  }

  // Only supports 2 tranches for now
  enum Tranche {
    Senior,
    Junior
  }

  struct VaultParams {
    address seniorAsset;
    address juniorAsset;
    address strategist;
    address strategy;
    uint256 hurdleRate;
    uint256 startTime;
    uint256 enrollment;
    uint256 duration;
    string seniorName;
    string seniorSym;
    string juniorName;
    string juniorSym;
    uint256 seniorTrancheCap;
    uint256 seniorUserCap;
    uint256 juniorTrancheCap;
    uint256 juniorUserCap;
  }

  struct RolloverParams {
    address strategist;
    string seniorName;
    string seniorSym;
    string juniorName;
    string juniorSym;
  }

  bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");
  bytes32 public constant PANIC_ROLE = keccak256("PANIC_ROLE");
  bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE");
  bytes32 public constant DEPLOYER_ROLE = keccak256("DEPLOYER_ROLE");
  bytes32 public constant CREATOR_ROLE = keccak256("CREATOR_ROLE");
  bytes32 public constant STRATEGIST_ROLE = keccak256("STRATEGIST_ROLE");
  bytes32 public constant VAULT_ROLE = keccak256("VAULT_ROLE");
  bytes32 public constant ROLLOVER_ROLE = keccak256("ROLLOVER_ROLE");
  bytes32 public constant STRATEGY_ROLE = keccak256("STRATEGY_ROLE");
  bytes32 public constant SINGLE_ASSET_WHITELIST_ROLE =
    keccak256("SINGLE_ASSET_WHITELIST_ROLE");
  bytes32 public constant LAAS_WHITELIST_ROLE =
    keccak256("LAAS_WHITELIST_ROLE");

  // Both sums are running sums. If a user deposits [$1, $5, $3], then
  // userSums would be [$1, $6, $9]. You can figure out the deposit
  // amount be subtracting userSums[i]-userSum[i-1].

  // prefixSums is the total deposited for all investors + this
  // investors deposit at the time this deposit is made. So at
  // prefixSum[0], it would be $1 + totalDeposits, where totalDeposits
  // could be $1000 because other investors have put in money.
  struct Investor {
    uint256[] userSums;
    uint256[] prefixSums;
    bool claimed;
    bool withdrawn;
  }

  /**
   * @dev Given the total amount invested by the Vault, we want to find
   *   out how many of this investor's deposits were actually
   *   used. Use findUpperBound on the prefixSum to find the point
   *   where total deposits were accepted. For example, if $2000 was
   *   deposited by all investors and $1000 was invested, then some
   *   position in the prefixSum splits the array into deposits that
   *   got in, and deposits that didn't get in. That same position
   *   maps to userSums. This is the user's deposits that got
   *   in. Since we are keeping track of the sums, we know at that
   *   position the total deposits for a user was $15, even if it was
   *   15 $1 deposits. And we know the amount that didn't get in is
   *   the last value in userSum - the amount that got it.

   * @param investor A specific investor
   * @param invested The total amount invested by this Vault
   */
  function getInvestedAndExcess(Investor storage investor, uint256 invested)
    internal
    view
    returns (uint256 userInvested, uint256 excess)
  {
    uint256[] storage prefixSums_ = investor.prefixSums;
    uint256 length = prefixSums_.length;
    if (length == 0) {
      // There were no deposits. Return 0, 0.
      return (userInvested, excess);
    }
    uint256 leastUpperBound = prefixSums_.findUpperBound(invested);
    if (length == leastUpperBound) {
      // All deposits got in, no excess. Return total deposits, 0
      userInvested = investor.userSums[length - 1];
      return (userInvested, excess);
    }
    uint256 prefixSum = prefixSums_[leastUpperBound];
    if (prefixSum == invested) {
      // Not all deposits got in, but there are no partial deposits
      userInvested = investor.userSums[leastUpperBound];
      excess = investor.userSums[length - 1] - userInvested;
    } else {
      // Let's say some of my deposits got in. The last deposit,
      // however, was $100 and only $30 got in. Need to split that
      // deposit so $30 got in, $70 is excess.
      userInvested = leastUpperBound > 0
        ? investor.userSums[leastUpperBound - 1]
        : 0;
      uint256 depositAmount = investor.userSums[leastUpperBound] - userInvested;
      if (prefixSum - depositAmount < invested) {
        userInvested += (depositAmount + invested - prefixSum);
        excess = investor.userSums[length - 1] - userInvested;
      } else {
        excess = investor.userSums[length - 1] - userInvested;
      }
    }
  }

  /*
   Used to avoid phantom overflow issues that can arise during this calculation:
   @notice Calculates floor(x*y÷denominator) with full precision.
   @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.
   @dec Credit to prb-math for refactoring for solidity ^0.8 https://github.com/paulrberg/prb-math/blob/main/contracts/PRBMath.sol
  */
  function safeMulDiv(
    uint256 x,
    uint256 y,
    uint256 denominator
  ) internal pure returns (uint256 result) {
    // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
    // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
    // variables such that product = prod1 * 2^256 + prod0.
    uint256 prod0; // Least significant 256 bits of the product
    uint256 prod1; // Most significant 256 bits of the product
    assembly {
      let mm := mulmod(x, y, not(0))
      prod0 := mul(x, y)
      prod1 := sub(sub(mm, prod0), lt(mm, prod0))
    }
    // Handle non-overflow cases, 256 by 256 division.
    if (prod1 == 0) {
      unchecked {
        result = prod0 / denominator;
      }
      return result;
    }
    // Make sure the result is less than 2^256. Also prevents denominator == 0.
    if (prod1 >= denominator) {
      revert("OLib__MulDivOverflow(prod1, denominator)");
    }
    ///////////////////////////////////////////////
    // 512 by 256 division.
    ///////////////////////////////////////////////
    // Make division exact by subtracting the remainder from [prod1 prod0].
    uint256 remainder;
    assembly {
      // Compute remainder using mulmod.
      remainder := mulmod(x, y, denominator)
      // Subtract 256 bit number from 512 bit number.
      prod1 := sub(prod1, gt(remainder, prod0))
      prod0 := sub(prod0, remainder)
    }
    // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
    // See https://cs.stackexchange.com/q/138556/92363.
    unchecked {
      // Does not overflow because the denominator cannot be zero at this stage in the function.
      uint256 lpotdod = denominator & (~denominator + 1);
      assembly {
        // Divide denominator by lpotdod.
        denominator := div(denominator, lpotdod)
        // Divide [prod1 prod0] by lpotdod.
        prod0 := div(prod0, lpotdod)
        // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.
        lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)
      }
      // Shift in bits from prod1 into prod0.
      prod0 |= prod1 * lpotdod;
      // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
      // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
      // four bits. That is, denominator * inv = 1 mod 2^4.
      uint256 inverse = (3 * denominator) ^ 2;
      // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel’s lifting lemma, this also works
      // in modular arithmetic, doubling the correct bits in each step.
      inverse *= 2 - denominator * inverse; // inverse mod 2^8
      inverse *= 2 - denominator * inverse; // inverse mod 2^16
      inverse *= 2 - denominator * inverse; // inverse mod 2^32
      inverse *= 2 - denominator * inverse; // inverse mod 2^64
      inverse *= 2 - denominator * inverse; // inverse mod 2^128
      inverse *= 2 - denominator * inverse; // inverse mod 2^256
      // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
      // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
      // less than 2^256, this is the final result. We don’t need to compute the high bits of the result and prod1
      // is no longer required.
      result = prod0 * inverse;
      return result;
    }
  }
}

/**
 * @title Subset of SafeERC20 from openZeppelin
 *
 * @dev Some non-standard ERC20 contracts (e.g. Tether) break
 * `approve` by forcing it to behave like `safeApprove`. This means
 * `safeIncreaseAllowance` will fail when it tries to adjust the
 * allowance. The code below simply adds an extra call to
 * `approve(spender, 0)`.
 */
library OndoSaferERC20 {
  using SafeERC20 for IERC20;

  function ondoSafeIncreaseAllowance(
    IERC20 token,
    address spender,
    uint256 value
  ) internal {
    uint256 newAllowance = token.allowance(address(this), spender) + value;
    token.safeApprove(spender, 0);
    token.safeApprove(spender, newAllowance);
  }
}

File 10 of 23 : 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;
        // solhint-disable-next-line no-inline-assembly
        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");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 11 of 23 : OndoRegistryClientInitializable.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.3;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "contracts/interfaces/IRegistry.sol";
import "contracts/libraries/OndoLibrary.sol";

abstract contract OndoRegistryClientInitializable is
  Initializable,
  ReentrancyGuard,
  Pausable
{
  using SafeERC20 for IERC20;

  IRegistry public registry;
  uint256 public denominator;

  // solhint-disable-next-line func-name-mixedcase
  function __OndoRegistryClient__initialize(address _registry)
    internal
    initializer
  {
    require(_registry != address(0), "Invalid registry address");
    registry = IRegistry(_registry);
    denominator = registry.denominator();
  }

  /**
   * @notice General ACL checker
   * @param _role Role as defined in OndoLibrary
   */
  modifier isAuthorized(bytes32 _role) {
    require(registry.authorized(_role, msg.sender), "Unauthorized");
    _;
  }

  /*
   * @notice Helper to expose a Pausable interface to tools
   */
  function paused() public view virtual override returns (bool) {
    return registry.paused() || super.paused();
  }

  function pause() external virtual isAuthorized(OLib.PANIC_ROLE) {
    super._pause();
  }

  function unpause() external virtual isAuthorized(OLib.GUARDIAN_ROLE) {
    super._unpause();
  }

  /**
   * @notice Grab tokens and send to caller
   * @dev If the _amount[i] is 0, then transfer all the tokens
   * @param _tokens List of tokens
   * @param _amounts Amount of each token to send
   */
  function _rescueTokens(address[] calldata _tokens, uint256[] memory _amounts)
    internal
    virtual
  {
    for (uint256 i = 0; i < _tokens.length; i++) {
      uint256 amount = _amounts[i];
      if (amount == 0) {
        amount = IERC20(_tokens[i]).balanceOf(address(this));
      }
      IERC20(_tokens[i]).safeTransfer(msg.sender, amount);
    }
  }

  function rescueTokens(address[] calldata _tokens, uint256[] memory _amounts)
    public
    whenPaused
    isAuthorized(OLib.GUARDIAN_ROLE)
  {
    require(_tokens.length == _amounts.length, "Invalid array sizes");
    _rescueTokens(_tokens, _amounts);
  }
}

File 12 of 23 : Initializable.sol
// SPDX-License-Identifier: MIT

// solhint-disable-next-line compiler-version
pragma solidity ^0.8.0;

import "../../utils/AddressUpgradeable.sol";

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {

    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

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

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }
}

File 13 of 23 : Pausable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor () {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

File 14 of 23 : 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 15 of 23 : IRegistry.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.3;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "contracts/interfaces/IWETH.sol";

/**
 * @title Global values used by many contracts
 * @notice This is mostly used for access control
 */
interface IRegistry is IAccessControl {
  function paused() external view returns (bool);

  function pause() external;

  function unpause() external;

  function enableFeatureFlag(bytes32 _featureFlag) external;

  function disableFeatureFlag(bytes32 _featureFlag) external;

  function getFeatureFlag(bytes32 _featureFlag) external view returns (bool);

  function denominator() external view returns (uint256);

  function weth() external view returns (IWETH);

  function authorized(bytes32 _role, address _account)
    external
    view
    returns (bool);
}

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

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @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;
        // solhint-disable-next-line no-inline-assembly
        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");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (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");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 17 of 23 : 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) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

File 18 of 23 : AccessControl.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    function hasRole(bytes32 role, address account) external view returns (bool);
    function getRoleAdmin(bytes32 role) external view returns (bytes32);
    function grantRole(bytes32 role, address account) external;
    function revokeRole(bytes32 role, address account) external;
    function renounceRole(bytes32 role, address account) external;
}

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping (address => bool) members;
        bytes32 adminRole;
    }

    mapping (bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId
            || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual override {
        require(hasRole(getRoleAdmin(role), _msgSender()), "AccessControl: sender must be an admin to grant");

        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual override {
        require(hasRole(getRoleAdmin(role), _msgSender()), "AccessControl: sender must be an admin to revoke");

        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);
        _roles[role].adminRole = adminRole;
    }

    function _grantRole(bytes32 role, address account) private {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    function _revokeRole(bytes32 role, address account) private {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

File 19 of 23 : IWETH.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.8.3;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IWETH is IERC20 {
  function deposit() external payable;

  function withdraw(uint256 wad) external;
}

File 20 of 23 : ERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 21 of 23 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 22 of 23 : Arrays.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./math/Math.sol";

/**
 * @dev Collection of functions related to array types.
 */
library Arrays {
   /**
     * @dev Searches a sorted `array` and returns the first index that contains
     * a value greater or equal to `element`. If no such index exists (i.e. all
     * values in the array are strictly less than `element`), the array length is
     * returned. Time complexity O(log n).
     *
     * `array` is expected to be sorted in ascending order, and to contain no
     * repeated elements.
     */
    function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
        if (array.length == 0) {
            return 0;
        }

        uint256 low = 0;
        uint256 high = array.length;

        while (low < high) {
            uint256 mid = Math.average(low, high);

            // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
            // because Math.average rounds down (it does integer division with truncation).
            if (array[mid] > element) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
        if (low > 0 && array[low - 1] == element) {
            return low - 1;
        } else {
            return low;
        }
    }
}

File 23 of 23 : 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, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_ondo","type":"address"},{"internalType":"address","name":"_ondoMultisig","type":"address"},{"internalType":"address","name":"_registry","type":"address"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"enum IOndo.InvestorType","name":"_investorType","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newMultisig","type":"address"}],"name":"MultiSigUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"denominator","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"investorType","outputs":[{"internalType":"enum IOndo.InvestorType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"isClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ondo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ondoMultisig","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"rescueTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newMultisig","type":"address"}],"name":"updateMultisig","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c06040523480156200001157600080fd5b506040516200174c3803806200174c8339810160408190526200003491620002a5565b600180556002805460ff19169055826200004e81620000bf565b50606085901b6001600160601b031916608052600480546001600160a01b0319166001600160a01b03861617905560058290558060028111156200009657620000966200032d565b60a0816002811115620000ad57620000ad6200032d565b60f81b81525050505050505062000343565b600054610100900460ff1680620000d9575060005460ff16155b620001425760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b600054610100900460ff1615801562000165576000805461ffff19166101011790555b6001600160a01b038216620001bd5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420726567697374727920616464726573730000000000000000604482015260640162000139565b81600260016101000a8154816001600160a01b0302191690836001600160a01b03160217905550600260019054906101000a90046001600160a01b03166001600160a01b03166396ce07956040518163ffffffff1660e01b815260040160206040518083038186803b1580156200023357600080fd5b505afa15801562000248573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200026e919062000313565b600355801562000284576000805461ff00191690555b5050565b80516001600160a01b0381168114620002a057600080fd5b919050565b600080600080600060a08688031215620002be57600080fd5b620002c98662000288565b9450620002d96020870162000288565b9350620002e96040870162000288565b9250606086015191506080860151600381106200030557600080fd5b809150509295509295909350565b6000602082840312156200032657600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b60805160601c60a05160f81c6113c8620003846000396000818161017b01526105060152600081816101d8015281816104d5015261057001526113c86000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c80636e8dcef61161008c5780638456cb59116100665780638456cb59146101c257806396ce0795146101ca5780639a8898b5146101d35780639e34070f146101fa57600080fd5b80636e8dcef61461014b578063779dada9146101765780637b103999146101aa57600080fd5b80632929c25c146100d45780632e7ba6ef146100e95780632eb4a7ab146100fc5780633bf8d620146101185780633f4ba83a1461012b5780635c975abb14610133575b600080fd5b6100e76100e236600461103f565b61020d565b005b6100e76100f736600461119c565b61032e565b61010560055481565b6040519081526020015b60405180910390f35b6100e761012636600461105a565b6105ec565b6100e7610751565b61013b61081f565b604051901515815260200161010f565b60045461015e906001600160a01b031681565b6040516001600160a01b03909116815260200161010f565b61019d7f000000000000000000000000000000000000000000000000000000000000000081565b60405161010f9190611266565b60025461015e9061010090046001600160a01b031681565b6100e76108bc565b61010560035481565b61015e7f000000000000000000000000000000000000000000000000000000000000000081565b61013b61020836600461116a565b610987565b600254604051631fe1defb60e11b81527f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1600482018190523360248301529161010090046001600160a01b031690633fc3bdf69060440160206040518083038186803b15801561027c57600080fd5b505afa158015610290573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b49190611148565b6102d95760405162461bcd60e51b81526004016102d0906112ad565b60405180910390fd5b600480546001600160a01b0319166001600160a01b0384169081179091556040519081527f7ca1bb3a0b8a33b929834f1be025e2a6c15b7273b9f8efc6978a86d84af395cc9060200160405180910390a15050565b336001600160a01b038516146103905760405162461bcd60e51b815260206004820152602160248201527f43616e277420636c61696d20616e6f746865722075736572277320746f6b656e6044820152607360f81b60648201526084016102d0565b61039985610987565b156103e65760405162461bcd60e51b815260206004820152601b60248201527f4f6e646f3a2044726f7020616c726561647920636c61696d65642e000000000060448201526064016102d0565b60408051602081018790526bffffffffffffffffffffffff19606087901b1691810191909152605481018490526000906074016040516020818303038152906040528051906020012090506104728383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060055491508490506109c8565b6104b55760405162461bcd60e51b815260206004820152601460248201527327b732379d1024b73b30b634b210383937b7b31760611b60448201526064016102d0565b6104be86610a79565b60405163e17ddf8760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063e17ddf879061052e90889088907f000000000000000000000000000000000000000000000000000000000000000090600401611242565b600060405180830381600087803b15801561054857600080fd5b505af115801561055c573d6000803e3d6000fd5b505060045461059b92506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169250168787610ab7565b604080518781526001600160a01b03871660208201529081018590527f4ec90e965519d92681267467f775ada5bd214aa92c0dc93d90a5e880ce9ed0269060600160405180910390a1505050505050565b6105f461081f565b6106375760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016102d0565b600254604051631fe1defb60e11b81527f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041600482018190523360248301529161010090046001600160a01b031690633fc3bdf69060440160206040518083038186803b1580156106a657600080fd5b505afa1580156106ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106de9190611148565b6106fa5760405162461bcd60e51b81526004016102d0906112ad565b815183146107405760405162461bcd60e51b8152602060048201526013602482015272496e76616c69642061727261792073697a657360681b60448201526064016102d0565b61074b848484610b22565b50505050565b600254604051631fe1defb60e11b81527f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041600482018190523360248301529161010090046001600160a01b031690633fc3bdf69060440160206040518083038186803b1580156107c057600080fd5b505afa1580156107d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f89190611148565b6108145760405162461bcd60e51b81526004016102d0906112ad565b61081c610c46565b50565b6000600260019054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b15801561086f57600080fd5b505afa158015610883573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a79190611148565b806108b757505060025460ff1690565b905090565b600254604051631fe1defb60e11b81527fb3e53bff87a96979079674767cfa1a09f3cf2847ba695cbaae933c232f4bf7f0600482018190523360248301529161010090046001600160a01b031690633fc3bdf69060440160206040518083038186803b15801561092b57600080fd5b505afa15801561093f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109639190611148565b61097f5760405162461bcd60e51b81526004016102d0906112ad565b61081c610cdb565b600080610996610100846112d3565b905060006109a66101008561133c565b60009283526006602052604090922054600190921b9182169091149392505050565b600081815b8551811015610a6c5760008682815181106109ea576109ea611366565b60200260200101519050808311610a2c576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610a59565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b5080610a6481611313565b9150506109cd565b50831490505b9392505050565b6000610a87610100836112d3565b90506000610a976101008461133c565b6000928352600660205260409092208054600190931b9092179091555050565b6040516001600160a01b038085166024830152831660448201526064810182905261074b9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610d58565b60005b8281101561074b576000828281518110610b4157610b41611366565b602002602001015190508060001415610bf757848483818110610b6657610b66611366565b9050602002016020810190610b7b919061103f565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015610bbc57600080fd5b505afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190611183565b90505b610c333382878786818110610c0e57610c0e611366565b9050602002016020810190610c23919061103f565b6001600160a01b03169190610e2f565b5080610c3e81611313565b915050610b25565b610c4e61081f565b610c915760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016102d0565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b610ce361081f565b15610d235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016102d0565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610cbe3390565b6000610dad826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610e5f9092919063ffffffff16565b805190915015610e2a5780806020019051810190610dcb9190611148565b610e2a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102d0565b505050565b6040516001600160a01b038316602482015260448101829052610e2a90849063a9059cbb60e01b90606401610aeb565b6060610e6e8484600085610e76565b949350505050565b606082471015610ed75760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102d0565b843b610f255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102d0565b600080866001600160a01b03168587604051610f419190611226565b60006040518083038185875af1925050503d8060008114610f7e576040519150601f19603f3d011682016040523d82523d6000602084013e610f83565b606091505b5091509150610f93828286610f9e565b979650505050505050565b60608315610fad575081610a72565b825115610fbd5782518084602001fd5b8160405162461bcd60e51b81526004016102d0919061127a565b80356001600160a01b0381168114610fee57600080fd5b919050565b60008083601f84011261100557600080fd5b50813567ffffffffffffffff81111561101d57600080fd5b6020830191508360208260051b850101111561103857600080fd5b9250929050565b60006020828403121561105157600080fd5b610a7282610fd7565b60008060006040848603121561106f57600080fd5b833567ffffffffffffffff8082111561108757600080fd5b61109387838801610ff3565b90955093506020915085820135818111156110ad57600080fd5b8601601f810188136110be57600080fd5b8035828111156110d0576110d061137c565b8060051b604051601f19603f830116810181811086821117156110f5576110f561137c565b604052828152858101945083860182850187018c101561111457600080fd5b600094505b83851015611137578035865294860194600194909401938601611119565b508096505050505050509250925092565b60006020828403121561115a57600080fd5b81518015158114610a7257600080fd5b60006020828403121561117c57600080fd5b5035919050565b60006020828403121561119557600080fd5b5051919050565b6000806000806000608086880312156111b457600080fd5b853594506111c460208701610fd7565b935060408601359250606086013567ffffffffffffffff8111156111e757600080fd5b6111f388828901610ff3565b969995985093965092949392505050565b6003811061122257634e487b7160e01b600052602160045260246000fd5b9052565b600082516112388184602087016112e7565b9190910192915050565b6001600160a01b03841681526020810183905260608101610e6e6040830184611204565b602081016112748284611204565b92915050565b60208152600082518060208401526112998160408501602087016112e7565b601f01601f19169190910160400192915050565b6020808252600c908201526b155b985d5d1a1bdc9a5e995960a21b604082015260600190565b6000826112e2576112e2611350565b500490565b60005b838110156113025781810151838201526020016112ea565b8381111561074b5750506000910152565b600060001982141561133557634e487b7160e01b600052601160045260246000fd5b5060010190565b60008261134b5761134b611350565b500690565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220023622dfb34c17d69e355aaeb30e852df6477613a838fbef8611036f860ed1af64736f6c63430008070033000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be3000000000000000000000000677fd4ed8ae623f2f625deb2d64f2070e46ca1a1000000000000000000000000f69c52bf2cf76250647c0bb5390d4ba8854a1d4a682ebf5bec99625187b6db7f94e79c933b86d9ebc55372ada248d7fa27dc276b0000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c80636e8dcef61161008c5780638456cb59116100665780638456cb59146101c257806396ce0795146101ca5780639a8898b5146101d35780639e34070f146101fa57600080fd5b80636e8dcef61461014b578063779dada9146101765780637b103999146101aa57600080fd5b80632929c25c146100d45780632e7ba6ef146100e95780632eb4a7ab146100fc5780633bf8d620146101185780633f4ba83a1461012b5780635c975abb14610133575b600080fd5b6100e76100e236600461103f565b61020d565b005b6100e76100f736600461119c565b61032e565b61010560055481565b6040519081526020015b60405180910390f35b6100e761012636600461105a565b6105ec565b6100e7610751565b61013b61081f565b604051901515815260200161010f565b60045461015e906001600160a01b031681565b6040516001600160a01b03909116815260200161010f565b61019d7f000000000000000000000000000000000000000000000000000000000000000081565b60405161010f9190611266565b60025461015e9061010090046001600160a01b031681565b6100e76108bc565b61010560035481565b61015e7f000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be381565b61013b61020836600461116a565b610987565b600254604051631fe1defb60e11b81527f71840dc4906352362b0cdaf79870196c8e42acafade72d5d5a6d59291253ceb1600482018190523360248301529161010090046001600160a01b031690633fc3bdf69060440160206040518083038186803b15801561027c57600080fd5b505afa158015610290573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b49190611148565b6102d95760405162461bcd60e51b81526004016102d0906112ad565b60405180910390fd5b600480546001600160a01b0319166001600160a01b0384169081179091556040519081527f7ca1bb3a0b8a33b929834f1be025e2a6c15b7273b9f8efc6978a86d84af395cc9060200160405180910390a15050565b336001600160a01b038516146103905760405162461bcd60e51b815260206004820152602160248201527f43616e277420636c61696d20616e6f746865722075736572277320746f6b656e6044820152607360f81b60648201526084016102d0565b61039985610987565b156103e65760405162461bcd60e51b815260206004820152601b60248201527f4f6e646f3a2044726f7020616c726561647920636c61696d65642e000000000060448201526064016102d0565b60408051602081018790526bffffffffffffffffffffffff19606087901b1691810191909152605481018490526000906074016040516020818303038152906040528051906020012090506104728383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060055491508490506109c8565b6104b55760405162461bcd60e51b815260206004820152601460248201527327b732379d1024b73b30b634b210383937b7b31760611b60448201526064016102d0565b6104be86610a79565b60405163e17ddf8760e01b81526001600160a01b037f000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be3169063e17ddf879061052e90889088907f000000000000000000000000000000000000000000000000000000000000000090600401611242565b600060405180830381600087803b15801561054857600080fd5b505af115801561055c573d6000803e3d6000fd5b505060045461059b92506001600160a01b037f000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be381169250168787610ab7565b604080518781526001600160a01b03871660208201529081018590527f4ec90e965519d92681267467f775ada5bd214aa92c0dc93d90a5e880ce9ed0269060600160405180910390a1505050505050565b6105f461081f565b6106375760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016102d0565b600254604051631fe1defb60e11b81527f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041600482018190523360248301529161010090046001600160a01b031690633fc3bdf69060440160206040518083038186803b1580156106a657600080fd5b505afa1580156106ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106de9190611148565b6106fa5760405162461bcd60e51b81526004016102d0906112ad565b815183146107405760405162461bcd60e51b8152602060048201526013602482015272496e76616c69642061727261792073697a657360681b60448201526064016102d0565b61074b848484610b22565b50505050565b600254604051631fe1defb60e11b81527f55435dd261a4b9b3364963f7738a7a662ad9c84396d64be3365284bb7f0a5041600482018190523360248301529161010090046001600160a01b031690633fc3bdf69060440160206040518083038186803b1580156107c057600080fd5b505afa1580156107d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f89190611148565b6108145760405162461bcd60e51b81526004016102d0906112ad565b61081c610c46565b50565b6000600260019054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b15801561086f57600080fd5b505afa158015610883573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a79190611148565b806108b757505060025460ff1690565b905090565b600254604051631fe1defb60e11b81527fb3e53bff87a96979079674767cfa1a09f3cf2847ba695cbaae933c232f4bf7f0600482018190523360248301529161010090046001600160a01b031690633fc3bdf69060440160206040518083038186803b15801561092b57600080fd5b505afa15801561093f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109639190611148565b61097f5760405162461bcd60e51b81526004016102d0906112ad565b61081c610cdb565b600080610996610100846112d3565b905060006109a66101008561133c565b60009283526006602052604090922054600190921b9182169091149392505050565b600081815b8551811015610a6c5760008682815181106109ea576109ea611366565b60200260200101519050808311610a2c576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610a59565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b5080610a6481611313565b9150506109cd565b50831490505b9392505050565b6000610a87610100836112d3565b90506000610a976101008461133c565b6000928352600660205260409092208054600190931b9092179091555050565b6040516001600160a01b038085166024830152831660448201526064810182905261074b9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610d58565b60005b8281101561074b576000828281518110610b4157610b41611366565b602002602001015190508060001415610bf757848483818110610b6657610b66611366565b9050602002016020810190610b7b919061103f565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a082319060240160206040518083038186803b158015610bbc57600080fd5b505afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190611183565b90505b610c333382878786818110610c0e57610c0e611366565b9050602002016020810190610c23919061103f565b6001600160a01b03169190610e2f565b5080610c3e81611313565b915050610b25565b610c4e61081f565b610c915760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b60448201526064016102d0565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b610ce361081f565b15610d235760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b60448201526064016102d0565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610cbe3390565b6000610dad826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316610e5f9092919063ffffffff16565b805190915015610e2a5780806020019051810190610dcb9190611148565b610e2a5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102d0565b505050565b6040516001600160a01b038316602482015260448101829052610e2a90849063a9059cbb60e01b90606401610aeb565b6060610e6e8484600085610e76565b949350505050565b606082471015610ed75760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102d0565b843b610f255760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102d0565b600080866001600160a01b03168587604051610f419190611226565b60006040518083038185875af1925050503d8060008114610f7e576040519150601f19603f3d011682016040523d82523d6000602084013e610f83565b606091505b5091509150610f93828286610f9e565b979650505050505050565b60608315610fad575081610a72565b825115610fbd5782518084602001fd5b8160405162461bcd60e51b81526004016102d0919061127a565b80356001600160a01b0381168114610fee57600080fd5b919050565b60008083601f84011261100557600080fd5b50813567ffffffffffffffff81111561101d57600080fd5b6020830191508360208260051b850101111561103857600080fd5b9250929050565b60006020828403121561105157600080fd5b610a7282610fd7565b60008060006040848603121561106f57600080fd5b833567ffffffffffffffff8082111561108757600080fd5b61109387838801610ff3565b90955093506020915085820135818111156110ad57600080fd5b8601601f810188136110be57600080fd5b8035828111156110d0576110d061137c565b8060051b604051601f19603f830116810181811086821117156110f5576110f561137c565b604052828152858101945083860182850187018c101561111457600080fd5b600094505b83851015611137578035865294860194600194909401938601611119565b508096505050505050509250925092565b60006020828403121561115a57600080fd5b81518015158114610a7257600080fd5b60006020828403121561117c57600080fd5b5035919050565b60006020828403121561119557600080fd5b5051919050565b6000806000806000608086880312156111b457600080fd5b853594506111c460208701610fd7565b935060408601359250606086013567ffffffffffffffff8111156111e757600080fd5b6111f388828901610ff3565b969995985093965092949392505050565b6003811061122257634e487b7160e01b600052602160045260246000fd5b9052565b600082516112388184602087016112e7565b9190910192915050565b6001600160a01b03841681526020810183905260608101610e6e6040830184611204565b602081016112748284611204565b92915050565b60208152600082518060208401526112998160408501602087016112e7565b601f01601f19169190910160400192915050565b6020808252600c908201526b155b985d5d1a1bdc9a5e995960a21b604082015260600190565b6000826112e2576112e2611350565b500490565b60005b838110156113025781810151838201526020016112ea565b8381111561074b5750506000910152565b600060001982141561133557634e487b7160e01b600052601160045260246000fd5b5060010190565b60008261134b5761134b611350565b500690565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220023622dfb34c17d69e355aaeb30e852df6477613a838fbef8611036f860ed1af64736f6c63430008070033

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

000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be3000000000000000000000000677fd4ed8ae623f2f625deb2d64f2070e46ca1a1000000000000000000000000f69c52bf2cf76250647c0bb5390d4ba8854a1d4a682ebf5bec99625187b6db7f94e79c933b86d9ebc55372ada248d7fa27dc276b0000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _ondo (address): 0xfAbA6f8e4a5E8Ab82F62fe7C39859FA577269BE3
Arg [1] : _ondoMultisig (address): 0x677FD4Ed8aE623f2f625DEB2D64F2070E46cA1A1
Arg [2] : _registry (address): 0xf69C52Bf2CF76250647C0bb5390d4ba8854a1d4a
Arg [3] : _merkleRoot (bytes32): 0x682ebf5bec99625187b6db7f94e79c933b86d9ebc55372ada248d7fa27dc276b
Arg [4] : _investorType (uint8): 0

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000faba6f8e4a5e8ab82f62fe7c39859fa577269be3
Arg [1] : 000000000000000000000000677fd4ed8ae623f2f625deb2d64f2070e46ca1a1
Arg [2] : 000000000000000000000000f69c52bf2cf76250647c0bb5390d4ba8854a1d4a
Arg [3] : 682ebf5bec99625187b6db7f94e79c933b86d9ebc55372ada248d7fa27dc276b
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.