ETH Price: $2,625.64 (-2.00%)

Contract

0x1ccE12F93395fA2A4d490Ef4FC865D9c1EA93563
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FxUSDCompounderHarvestFacet

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 200 runs

Other Settings:
istanbul EvmVersion
File 1 of 5 : FxUSDCompounderHarvestFacet.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.6;

import "../../interfaces/concentrator/IFxUSDCompounder.sol";

import "../libraries/LibConcentratorHarvester.sol";

contract FxUSDCompounderHarvestFacet {
  /// @notice Harvest pending rewards from FxUSDCompounder contract.
  /// @param compounder The address of FxUSDCompounder contract.
  /// @param minBaseOut The minimum amount of base token should be harvested.
  /// @param minFxUSD The minimum amount of FxUSD should be harvested.
  /// @return baseOut The amount of base token harvested.
  /// @return fxUSDOut The amount of FxUSD harvested.
  function harvestConcentratorCompounder(
    address compounder,
    uint256 minBaseOut,
    uint256 minFxUSD
  ) external returns (uint256 baseOut, uint256 fxUSDOut) {
    LibConcentratorHarvester.enforceHasPermission();

    (baseOut, fxUSDOut) = IFxUSDCompounder(compounder).harvest(msg.sender, minBaseOut, minFxUSD);
  }
}

File 2 of 5 : LibConcentratorHarvester.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.6;
pragma abicoder v2;

import "../../interfaces/ICurveVoteEscrow.sol";

// solhint-disable const-name-snakecase
// solhint-disable no-inline-assembly
// solhint-disable not-rely-on-time

library LibConcentratorHarvester {
  /*************
   * Constants *
   *************/

  /// @dev The storage slot for default diamond storage.
  bytes32 private constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage");

  /// @dev The storage slot for harvester storage.
  bytes32 private constant HARVESTER_STORAGE_POSITION = keccak256("diamond.harvester.concentrator.storage");

  /// @dev The address of veCTR contract.
  address internal constant veCTR = 0xe4C09928d834cd58D233CD77B5af3545484B4968;

  /***********
   * Structs *
   ***********/

  struct FacetAddressAndSelectorPosition {
    address facetAddress;
    uint16 selectorPosition;
  }

  struct DiamondStorage {
    // function selector => facet address and selector position in selectors array
    mapping(bytes4 => FacetAddressAndSelectorPosition) facetAddressAndSelectorPosition;
    bytes4[] selectors;
    mapping(bytes4 => bool) supportedInterfaces;
    // owner of the contract
    address contractOwner;
  }

  struct HarvesterStorage {
    uint128 minLockCTR;
    uint128 minLockDuration;
    mapping(address => bool) whitelist;
    mapping(address => bool) blacklist;
  }

  /**********************
   * Internal Functions *
   **********************/

  function diamondStorage() private pure returns (DiamondStorage storage ds) {
    bytes32 position = DIAMOND_STORAGE_POSITION;
    assembly {
      ds.slot := position
    }
  }

  function harvesterStorage() internal pure returns (HarvesterStorage storage hs) {
    bytes32 position = HARVESTER_STORAGE_POSITION;
    assembly {
      hs.slot := position
    }
  }

  function updatePermission(uint128 _minLockCTR, uint128 _minLockDuration) internal {
    HarvesterStorage storage hs = harvesterStorage();

    hs.minLockCTR = _minLockCTR;
    hs.minLockDuration = _minLockDuration;
  }

  function updateWhitelist(address _account, bool _status) internal {
    HarvesterStorage storage hs = harvesterStorage();

    hs.whitelist[_account] = _status;
  }

  function updateBlacklist(address _account, bool _status) internal {
    HarvesterStorage storage hs = harvesterStorage();

    hs.blacklist[_account] = _status;
  }

  function enforceIsContractOwner() internal view {
    require(msg.sender == diamondStorage().contractOwner, "only owner");
  }

  function enforceHasPermission() internal view {
    ICurveVoteEscrow.LockedBalance memory _locked = ICurveVoteEscrow(veCTR).locked(msg.sender);
    HarvesterStorage storage hs = harvesterStorage();

    // check whether is blacklisted
    require(!hs.blacklist[msg.sender], "account blacklisted");

    // check whether is whitelisted
    if (hs.whitelist[msg.sender] || hs.minLockCTR == 0) return;

    // check veCTR locking
    require(uint128(_locked.amount) >= hs.minLockCTR, "insufficient lock amount");
    require(_locked.end >= hs.minLockDuration + block.timestamp, "insufficient lock duration");
  }
}

File 3 of 5 : IFxUSDCompounder.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0 || ^0.8.0;

import { IStandardizedYield } from "../../interfaces/pendle/IStandardizedYield.sol";

interface IFxUSDCompounder is IStandardizedYield {
  /// @notice Emitted when pending rewards are harvested.
  /// @param caller The address of function caller.
  /// @param baseOut The amount of base token harvested.
  /// @param expense The amount of performance fee.
  /// @param bounty The amount of harvest bounty.
  /// @param fxUSDOut The amount of FxUSD harvested.
  event Harvest(address indexed caller, uint256 baseOut, uint256 expense, uint256 bounty, uint256 fxUSDOut);

  /// @notice Emitted when liquidated base tokens are converted back to FxUSD.
  /// @param caller The address of function caller.
  /// @param amountBaseToken The amount of base token converted.
  /// @param amountFxUSD The amount of FxUSD converted.
  event Rebalance(address indexed caller, uint256 amountBaseToken, uint256 amountFxUSD);

  /*************************
   * Public View Functions *
   *************************/

  /// @notice The amount of unconverted base token.
  function totalPendingBaseToken() external view returns (uint256);

  /// @notice The total amount of deposited yield token.
  function getTotalAssets() external view returns (uint256);

  /// @notice The address of rebalance pool.
  function getPool() external view returns (address);

  /// @notice The address of base token.
  function getBaseToken() external view returns (address);

  /// @notice Return the token converting routes.
  /// @param token The address of token to query.
  /// @return routes The converting routes.
  function getConvertRoutes(address token) external view returns (uint256[] memory routes);

  /// @notice Return the net asset value.
  function nav() external view returns (uint256);

  /****************************
   * Public Mutated Functions *
   ****************************/

  /// @notice Convert liquidated base token to FxUSD.
  /// @param minFxUSD The minimum amount of FxUSD should be rebalanced.
  /// @return fxUSDOut The amount of FxUSD harvested.
  function rebalance(uint256 minFxUSD) external returns (uint256 fxUSDOut);

  /// @notice Harvest pending rewards from FxUSDCompounder contract.
  /// @param receiver The address of harvest bounty receiver.
  /// @param minBaseOut The minimum amount of base token should be harvested.
  /// @param minFxUSD The minimum amount of FxUSD should be harvested.
  /// @return baseOut The amount of base token harvested.
  /// @return fxUSDOut The amount of FxUSD harvested.
  function harvest(
    address receiver,
    uint256 minBaseOut,
    uint256 minFxUSD
  ) external returns (uint256 baseOut, uint256 fxUSDOut);
}

File 4 of 5 : ICurveVoteEscrow.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.7.6;
pragma abicoder v2;

// solhint-disable func-name-mixedcase
// solhint-disable var-name-mixedcase

interface ICurveVoteEscrow {
  struct LockedBalance {
    int128 amount;
    uint256 end;
  }

  /// @notice Deposit `_value` tokens for `msg.sender` and lock until `_unlock_time`
  /// @param _value Amount to deposit
  /// @param _unlock_time Epoch time when tokens unlock, rounded down to whole weeks
  function create_lock(uint256 _value, uint256 _unlock_time) external;

  /// @notice Deposit `_value` additional tokens for `msg.sender` without modifying the unlock time
  /// @param _value Amount of tokens to deposit and add to the lock
  function increase_amount(uint256 _value) external;

  /// @notice Extend the unlock time for `msg.sender` to `_unlock_time`
  /// @param _unlock_time New epoch time for unlocking
  function increase_unlock_time(uint256 _unlock_time) external;

  /// @notice Withdraw all tokens for `msg.sender`
  /// @dev Only possible if the lock has expired
  function withdraw() external;

  /// @notice Get timestamp when `_addr`'s lock finishes
  /// @param _addr User wallet
  /// @return Epoch time of the lock end
  function locked__end(address _addr) external view returns (uint256);

  function locked(address _addr) external view returns (LockedBalance memory);
}

File 5 of 5 : IStandardizedYield.sol
// SPDX-License-Identifier: GPL-3.0-or-later
/*
 * MIT License
 * ===========
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 */

pragma solidity ^0.7.0 || ^0.8.0;

/// @dev copy from https://github.com/pendle-finance/pendle-core-v2-public/blob/main/contracts/interfaces/IStandardizedYield.sol
interface IStandardizedYield {
  /// @dev Emitted when any base tokens is deposited to mint shares
  event Deposit(
    address indexed caller,
    address indexed receiver,
    address indexed tokenIn,
    uint256 amountDeposited,
    uint256 amountSyOut
  );

  /// @dev Emitted when any shares are redeemed for base tokens
  event Redeem(
    address indexed caller,
    address indexed receiver,
    address indexed tokenOut,
    uint256 amountSyToRedeem,
    uint256 amountTokenOut
  );

  /// @dev check `assetInfo()` for more information
  enum AssetType {
    TOKEN,
    LIQUIDITY
  }

  /// @dev Emitted when (`user`) claims their rewards
  event ClaimRewards(address indexed user, address[] rewardTokens, uint256[] rewardAmounts);

  /**
   * @notice mints an amount of shares by depositing a base token.
   * @param receiver shares recipient address
   * @param tokenIn address of the base tokens to mint shares
   * @param amountTokenToDeposit amount of base tokens to be transferred from (`msg.sender`)
   * @param minSharesOut reverts if amount of shares minted is lower than this
   * @return amountSharesOut amount of shares minted
   * @dev Emits a {Deposit} event
   *
   * Requirements:
   * - (`tokenIn`) must be a valid base token.
   */
  function deposit(
    address receiver,
    address tokenIn,
    uint256 amountTokenToDeposit,
    uint256 minSharesOut
  ) external payable returns (uint256 amountSharesOut);

  /**
   * @notice redeems an amount of base tokens by burning some shares
   * @param receiver recipient address
   * @param amountSharesToRedeem amount of shares to be burned
   * @param tokenOut address of the base token to be redeemed
   * @param minTokenOut reverts if amount of base token redeemed is lower than this
   * @param burnFromInternalBalance if true, burns from balance of `address(this)`, otherwise burns from `msg.sender`
   * @return amountTokenOut amount of base tokens redeemed
   * @dev Emits a {Redeem} event
   *
   * Requirements:
   * - (`tokenOut`) must be a valid base token.
   */
  function redeem(
    address receiver,
    uint256 amountSharesToRedeem,
    address tokenOut,
    uint256 minTokenOut,
    bool burnFromInternalBalance
  ) external returns (uint256 amountTokenOut);

  /**
     * @notice exchangeRate * syBalance / 1e18 must return the asset balance of the account
     * @notice vice-versa, if a user uses some amount of tokens equivalent to X asset, the amount of sy
     he can mint must be X * exchangeRate / 1e18
     * @dev SYUtils's assetToSy & syToAsset should be used instead of raw multiplication
     & division
     */
  function exchangeRate() external view returns (uint256 res);

  /**
   * @notice claims reward for (`user`)
   * @param user the user receiving their rewards
   * @return rewardAmounts an array of reward amounts in the same order as `getRewardTokens`
   * @dev
   * Emits a `ClaimRewards` event
   * See {getRewardTokens} for list of reward tokens
   */
  function claimRewards(address user) external returns (uint256[] memory rewardAmounts);

  /**
   * @notice get the amount of unclaimed rewards for (`user`)
   * @param user the user to check for
   * @return rewardAmounts an array of reward amounts in the same order as `getRewardTokens`
   */
  function accruedRewards(address user) external view returns (uint256[] memory rewardAmounts);

  function rewardIndexesCurrent() external returns (uint256[] memory indexes);

  function rewardIndexesStored() external view returns (uint256[] memory indexes);

  /**
   * @notice returns the list of reward token addresses
   */
  function getRewardTokens() external view returns (address[] memory);

  /**
   * @notice returns the address of the underlying yield token
   */
  function yieldToken() external view returns (address);

  /**
   * @notice returns all tokens that can mint this SY
   */
  function getTokensIn() external view returns (address[] memory res);

  /**
   * @notice returns all tokens that can be redeemed by this SY
   */
  function getTokensOut() external view returns (address[] memory res);

  function isValidTokenIn(address token) external view returns (bool);

  function isValidTokenOut(address token) external view returns (bool);

  function previewDeposit(address tokenIn, uint256 amountTokenToDeposit)
    external
    view
    returns (uint256 amountSharesOut);

  function previewRedeem(address tokenOut, uint256 amountSharesToRedeem) external view returns (uint256 amountTokenOut);

  /**
     * @notice This function contains information to interpret what the asset is
     * @return assetType the type of the asset (0 for ERC20 tokens, 1 for AMM liquidity tokens,
        2 for bridged yield bearing tokens like wstETH, rETH on Arbi whose the underlying asset doesn't exist on the chain)
     * @return assetAddress the address of the asset
     * @return assetDecimals the decimals of the asset
     */
  function assetInfo()
    external
    view
    returns (
      AssetType assetType,
      address assetAddress,
      uint8 assetDecimals
    );
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"compounder","type":"address"},{"internalType":"uint256","name":"minBaseOut","type":"uint256"},{"internalType":"uint256","name":"minFxUSD","type":"uint256"}],"name":"harvestConcentratorCompounder","outputs":[{"internalType":"uint256","name":"baseOut","type":"uint256"},{"internalType":"uint256","name":"fxUSDOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b506103ed806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806378f26f5b14610030575b600080fd5b6100626004803603606081101561004657600080fd5b506001600160a01b03813516906020810135906040013561007b565b6040805192835260208301919091528051918290030190f35b600080610086610117565b6040805163f758870160e01b8152336004820152602481018690526044810185905281516001600160a01b0388169263f758870192606480820193918290030181600087803b1580156100d857600080fd5b505af11580156100ec573d6000803e3d6000fd5b505050506040513d604081101561010257600080fd5b50805160209091015190969095509350505050565b60405163cbf9fe5f60e01b815260009073e4c09928d834cd58d233cd77b5af3545484b49689063cbf9fe5f90610151903390600401610308565b604080518083038186803b15801561016857600080fd5b505afa15801561017c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a091906102b1565b905060006101ac61028d565b33600090815260028201602052604090205490915060ff16156101ea5760405162461bcd60e51b81526004016101e19061031c565b60405180910390fd5b33600090815260018201602052604090205460ff1680610212575080546001600160801b0316155b1561021e57505061028b565b805482516001600160801b039182169116101561024d5760405162461bcd60e51b81526004016101e190610349565b805460208301516001600160801b03600160801b90920491909116420111156102885760405162461bcd60e51b81526004016101e190610380565b50505b565b7f7b3d7c6d072f5ba80c1b8069e5afa5580d5083ebf8116656029468cd718daac790565b6000604082840312156102c2578081fd5b6040516040810181811067ffffffffffffffff821117156102df57fe5b6040528251600f81900b81146102f3578283fd5b81526020928301519281019290925250919050565b6001600160a01b0391909116815260200190565b6020808252601390820152721858d8dbdd5b9d08189b1858dadb1a5cdd1959606a1b604082015260600190565b60208082526018908201527f696e73756666696369656e74206c6f636b20616d6f756e740000000000000000604082015260600190565b6020808252601a908201527f696e73756666696369656e74206c6f636b206475726174696f6e00000000000060408201526060019056fea2646970667358221220432bfbc99a4b22069d4993137b962286e785c1f369e569c3f7f724f4bf16daf364736f6c63430007060033

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061002b5760003560e01c806378f26f5b14610030575b600080fd5b6100626004803603606081101561004657600080fd5b506001600160a01b03813516906020810135906040013561007b565b6040805192835260208301919091528051918290030190f35b600080610086610117565b6040805163f758870160e01b8152336004820152602481018690526044810185905281516001600160a01b0388169263f758870192606480820193918290030181600087803b1580156100d857600080fd5b505af11580156100ec573d6000803e3d6000fd5b505050506040513d604081101561010257600080fd5b50805160209091015190969095509350505050565b60405163cbf9fe5f60e01b815260009073e4c09928d834cd58d233cd77b5af3545484b49689063cbf9fe5f90610151903390600401610308565b604080518083038186803b15801561016857600080fd5b505afa15801561017c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101a091906102b1565b905060006101ac61028d565b33600090815260028201602052604090205490915060ff16156101ea5760405162461bcd60e51b81526004016101e19061031c565b60405180910390fd5b33600090815260018201602052604090205460ff1680610212575080546001600160801b0316155b1561021e57505061028b565b805482516001600160801b039182169116101561024d5760405162461bcd60e51b81526004016101e190610349565b805460208301516001600160801b03600160801b90920491909116420111156102885760405162461bcd60e51b81526004016101e190610380565b50505b565b7f7b3d7c6d072f5ba80c1b8069e5afa5580d5083ebf8116656029468cd718daac790565b6000604082840312156102c2578081fd5b6040516040810181811067ffffffffffffffff821117156102df57fe5b6040528251600f81900b81146102f3578283fd5b81526020928301519281019290925250919050565b6001600160a01b0391909116815260200190565b6020808252601390820152721858d8dbdd5b9d08189b1858dadb1a5cdd1959606a1b604082015260600190565b60208082526018908201527f696e73756666696369656e74206c6f636b20616d6f756e740000000000000000604082015260600190565b6020808252601a908201527f696e73756666696369656e74206c6f636b206475726174696f6e00000000000060408201526060019056fea2646970667358221220432bfbc99a4b22069d4993137b962286e785c1f369e569c3f7f724f4bf16daf364736f6c63430007060033

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

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.