ETH Price: $3,298.67 (-4.41%)

Contract

0x8154e5F984287C6a53b2938E2B41214f906afD64
 

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 Tokens231204992025-08-11 21:30:4786 days ago1754947847IN
OptiVault: Hot Tub Party
0 ETH0.000088330.74560347
Withdraw Tokens218449062025-02-14 13:09:59265 days ago1739538599IN
OptiVault: Hot Tub Party
0 ETH0.0001861.57006481
Withdraw Tokens213965402024-12-13 22:21:35327 days ago1734128495IN
OptiVault: Hot Tub Party
0 ETH0.0015058412.71068209
Withdraw Tokens213883752024-12-12 18:59:47329 days ago1734029987IN
OptiVault: Hot Tub Party
0 ETH0.0028148627.76792706
Early Withdraw T...209652942024-10-14 17:27:47388 days ago1728926867IN
OptiVault: Hot Tub Party
0 ETH0.0034348833.02771724
Early Withdraw T...164345522023-01-18 15:21:231023 days ago1674055283IN
OptiVault: Hot Tub Party
0 ETH0.0030423525.12266695

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x3d602d80161764182022-12-13 14:37:471059 days ago1670942267  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.