ETH Price: $3,409.35 (-1.00%)

Contract

0xFb9e4a050Af9A91887d12439FCB90bb0644238e3
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw Tokens230907162025-08-07 17:36:3593 days ago1754588195IN
0xFb9e4a05...0644238e3
0 ETH0.000072210.71234468
Withdraw Tokens225951882025-05-30 11:15:23162 days ago1748603723IN
0xFb9e4a05...0644238e3
0 ETH0.000161441.59264472
Withdraw Tokens220439062025-03-14 8:25:11239 days ago1741940711IN
0xFb9e4a05...0644238e3
0 ETH0.000096350.95047128
Withdraw Tokens219947502025-03-07 11:37:47246 days ago1741347467IN
0xFb9e4a05...0644238e3
0 ETH0.000148791.25599751
Early Withdraw T...209533532024-10-13 1:19:35392 days ago1728782375IN
0xFb9e4a05...0644238e3
0 ETH0.000880948.47067061
Early Withdraw T...201800102024-06-27 2:22:47500 days ago1719454967IN
0xFb9e4a05...0644238e3
0 ETH0.000627255.17967759

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x3d602d80167703482023-03-06 15:58:11978 days ago1678118291  Contract Creation0 ETH
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Minimal Proxy Contract for 0xc5a00a96e6a7039dad5af5c41584469048b26038

Contract Name:
OptiVault

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

pragma solidity ^0.8.4;

import '@uniswap/v2-periphery/contracts/interfaces/IERC20.sol';

interface IOptiVaultBalanceLookup {
  function sharesOf(address user) external view returns (uint256 _shares); //shares
}

contract OptiVault {
  // **********************************************************************************
  // *       OptiVaults provide an easy way to lock tokens as a group.                *
  // *    Reflective staking means that early withdrawals are allowed,                *
  // *      for a 20% penalty that is distributed to everyone else.                   *
  // **********************************************************************************

  bool private initialized;
  IERC20 public token; 
  uint256 public lockupDate;                         // deposits cannot be made after this
  uint256 public minimumTokenCommitment;             // deposited tokens must exceed this amount to lock
  bool public failed;                                // campaign failed to reach minimum and is not subject to lock
  bool public succeeded;                             // campaign reached minimum and is locked
  uint256 public withdrawalsLockedUntilTimestamp;    // time at which haircut-free withdrawal is available.
  mapping (address => uint256) private shareBalance; // internal balance tracking for self-contained campaigns
  uint256 private totalShares;                       // the denominator which decreases faster than the token balance
  IOptiVaultBalanceLookup public shareBalanceLookup; // external balance tracking for use by other contracts
  mapping (address => bool) public withdrawn;        // instead of zeroing share balances, this flag is set.

  function initialize(address _token, uint256 _lockupDate, uint256 _minimumTokenCommitment, uint256 _withdrawalsLockedUntilTimestamp, address _balanceLookup) external {
     require(!initialized);
     token = IERC20(_token);
     lockupDate = _lockupDate;
     minimumTokenCommitment = _minimumTokenCommitment;
     withdrawalsLockedUntilTimestamp = _withdrawalsLockedUntilTimestamp;
     if (lockupDate == 0) {
       totalShares = token.balanceOf(address(this));
     }
     shareBalanceLookup = IOptiVaultBalanceLookup(_balanceLookup);
     initialized = true;
   }
 
  function unlockTimestamp() external view returns (uint256 _unlockTimestamp) {
    _unlockTimestamp = withdrawalsLockedUntilTimestamp;
  }

  function sharesOf(address user) external view returns (uint256 _shares) {
    //Shares in the staking venture.    
    _shares = shareBalance[user];
  }

  function tokenBalanceOf(address user) external view returns (uint256 _amount) {
    //The number of tokens redeemable by the user's share.
    if (withdrawn[msg.sender]) {
      return 0;
    }
    uint256 shares = shareBalanceLookup.sharesOf(user);
    _amount = (shares * token.balanceOf(address(this))) / totalShares;
  }

  function tokenLocked() external view returns (address _token) {
    _token = address(token);
  }

  function withdrawable() public view returns (bool) {
    return (failed || block.timestamp >= withdrawalsLockedUntilTimestamp);
  }

  function contribute(uint tokenAmount) public {
    require(block.timestamp < lockupDate, "OptiVault: Pooling phase has ended.");
    token.transferFrom(msg.sender, address(this), tokenAmount);
    shareBalance[msg.sender] += tokenAmount;
    totalShares += tokenAmount;
    if (token.balanceOf(address(this)) >= minimumTokenCommitment) {
      succeeded = true;
    }
  }

  function fail() public {
    require(block.timestamp > lockupDate, "OptiVault: Still in Pooling phase.");
    require(token.balanceOf(address(this)) < minimumTokenCommitment, "OptiVault: Staking succesful.");
    require(!succeeded, "OptiVault: Campaign already succeeded.");
    require(!failed, "OptiVault: Campaign already marked failed.");
    failed = true;
  }

  function earlyWithdrawTokens() public {
    require(withdrawn[msg.sender] == false, "OptiVault: Already withdrawn.");
    require(block.timestamp > lockupDate, "OptiVault: Still in Pooling phase.");
    require(!withdrawable(), "OptiVault: Staking period has ended.");
    uint userTokenBalance = this.tokenBalanceOf(msg.sender);
    uint userShareBalance = shareBalanceLookup.sharesOf(msg.sender);

    uint toTransfer; 
    if (userShareBalance == totalShares) {
      toTransfer = userTokenBalance;
    } else {
      toTransfer = userTokenBalance * 80 / 100;
    }

    totalShares -= userShareBalance;
    token.transfer(msg.sender, toTransfer);
    withdrawn[msg.sender] = true;
  }

  function withdrawTokens() public {
    require(withdrawable(), "OptiVault: Tokens still locked.");
    require(withdrawn[msg.sender] == false, "OptiVault: Already withdrawn.");
    uint toTransfer =  this.tokenBalanceOf(msg.sender);
    token.transfer(msg.sender, toTransfer);
    totalShares -= shareBalanceLookup.sharesOf(msg.sender);
    withdrawn[msg.sender] = true;
  }
}

pragma solidity >=0.5.0;

interface IERC20 {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);
}

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

Contract ABI

API
[{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"contribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"earlyWithdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fail","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"failed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_lockupDate","type":"uint256"},{"internalType":"uint256","name":"_minimumTokenCommitment","type":"uint256"},{"internalType":"uint256","name":"_withdrawalsLockedUntilTimestamp","type":"uint256"},{"internalType":"address","name":"_balanceLookup","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockupDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumTokenCommitment","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"shareBalanceLookup","outputs":[{"internalType":"contract IOptiVaultBalanceLookup","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"sharesOf","outputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"succeeded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"tokenBalanceOf","outputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenLocked","outputs":[{"internalType":"address","name":"_token","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockTimestamp","outputs":[{"internalType":"uint256","name":"_unlockTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawalsLockedUntilTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"withdrawn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
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.