Address Contract Partially Verified
Address
0xc3CBd1e850D431adC583f14f03b9B8B651e62A61
Balance
0 ETH
Nonce
1
Code Size
2930 bytes
Creator
0x9De5B000...D178 at tx 0x9a3a6580...a8d3a4
Indexed Transactions
0
Contract Bytecode
2930 bytes
0x608060405234801561001057600080fd5b50600436106100a95760003560e01c80638da5cb5b116100715780638da5cb5b146101585780639f4568ef1461016b578063a695aa4d1461018b578063bbb333ed146101b2578063bedb86fb146101c5578063d51a020b146101d857600080fd5b806313af4035146100ae578063484267a4146100c35780635236be40146100e957806353620494146100fc5780635c975abb1461013b575b600080fd5b6100c16100bc366004610982565b6101ff565b005b6100d66100d1366004610982565b610298565b6040519081526020015b60405180910390f35b6100d66100f73660046109b5565b61046f565b6101237f0000000000000000000000000000000012a0592c154d552c410030e724b2ea0081565b6040516001600160a01b0390911681526020016100e0565b6002546101489060ff1681565b60405190151581526020016100e0565b600054610123906001600160a01b031681565b6100d6610179366004610982565b60016020526000908152604090205481565b6101237f0000000000000000000000007fcc30e97d718864d46a84f13e3ba111a56123d381565b6100d66101c03660046109f5565b610832565b6100c16101d3366004610a0e565b610873565b6101237f000000000000000000000000000000007a58f5f58e697e51ab0357bc9e260a0481565b6000546001600160a01b0316331461024d5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b60448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0383169081178255604051909133917f8292fce18fa69edf4db7b94ea2e58241df0ae57f97e0a6c9b29067028bf92d769190a350565b6040516370a0823160e01b81526001600160a01b03828116600483015260009182917f0000000000000000000000000000000012a0592c154d552c410030e724b2ea0016906370a0823190602401602060405180830381865afa158015610303573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103279190610a2b565b604051639f4568ef60e01b81526001600160a01b0385811660048301529192506000917f0000000000000000000000007fcc30e97d718864d46a84f13e3ba111a56123d31690639f4568ef90602401602060405180830381865afa158015610393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103b79190610a2b565b6001600160a01b0385166000908152600160205260409020546103da9190610a5a565b90508082036103ed575060009392505050565b4263629bf20081101561040557506000949350505050565b6000636427740082111561041a575082610448565b600061042583610832565b9050670de0b6b3a764000061043a8287610a72565b6104449190610a91565b9150505b82811161045b5750600095945050505050565b6104658382610ab3565b9695505050505050565b60025460009060ff16156104ae5760405162461bcd60e51b815260206004820152600660248201526514105554d15160d21b6044820152606401610244565b6040516370a0823160e01b81523360048201526000907f0000000000000000000000000000000012a0592c154d552c410030e724b2ea006001600160a01b0316906370a0823190602401602060405180830381865afa158015610515573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105399190610a2b565b604051639f4568ef60e01b81523360048201529091506000906001600160a01b037f0000000000000000000000007fcc30e97d718864d46a84f13e3ba111a56123d31690639f4568ef90602401602060405180830381865afa1580156105a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c79190610a2b565b336000908152600160205260409020546105e19190610a5a565b9050808211604051806040016040528060098152602001681393d391481311519560ba1b815250906106265760405162461bcd60e51b81526004016102449190610aca565b504263629bf2008110156106695760405162461bcd60e51b815260206004820152600a6024820152691393d517d59154d5115160b21b6044820152606401610244565b6000636427740082111561067e5750826106ac565b600061068983610832565b9050670de0b6b3a764000061069e8287610a72565b6106a89190610a91565b9150505b6040805180820190915260098152681393d391481311519560ba1b60208201528382116106ec5760405162461bcd60e51b81526004016102449190610aca565b5060006106f98483610ab3565b905080955086610741578881101561073d5760405162461bcd60e51b81526020600482015260076024820152664558434545445360c81b6044820152606401610244565b8895505b3360009081526001602052604081208054889290610760908490610a5a565b909155505060405163a9059cbb60e01b81526001600160a01b038981166004830152602482018890527f000000000000000000000000000000007a58f5f58e697e51ab0357bc9e260a04169063a9059cbb906044016020604051808303816000875af11580156107d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107f89190610b1f565b50604051869033907fe6c82503aaaa3db78b70f183901ae8668918f895b3982b2c851cf2ffe0c6c63990600090a350505050509392505050565b600063629bf20063018b820066470de4df820000670d99a8cec7e200008461085b858886610905565b905061086883828461093a565b979650505050505050565b6000546001600160a01b031633146108bc5760405162461bcd60e51b815260206004820152600c60248201526b15539055551213d49256915160a21b6044820152606401610244565b6002805460ff191682151590811790915560405190815233907fe8699cf681560fd07de85543bd994263f4557bdc5179dd702f256d15fd083e1d9060200160405180910390a250565b6000806109128585610ab3565b90508261092782670de0b6b3a7640000610a72565b6109319190610a91565b95945050505050565b600080670de0b6b3a76400006109508585610a72565b61095a9190610a91565b90506109318186610a5a565b80356001600160a01b038116811461097d57600080fd5b919050565b60006020828403121561099457600080fd5b61099d82610966565b9392505050565b80151581146109b257600080fd5b50565b6000806000606084860312156109ca57600080fd5b833592506109da60208501610966565b915060408401356109ea816109a4565b809150509250925092565b600060208284031215610a0757600080fd5b5035919050565b600060208284031215610a2057600080fd5b813561099d816109a4565b600060208284031215610a3d57600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610a6d57610a6d610a44565b500190565b6000816000190483118215151615610a8c57610a8c610a44565b500290565b600082610aae57634e487b7160e01b600052601260045260246000fd5b500490565b600082821015610ac557610ac5610a44565b500390565b600060208083528351808285015260005b81811015610af757858101830151858201604001528201610adb565b81811115610b09576000604083870101525b50601f01601f1916929092016040019392505050565b600060208284031215610b3157600080fd5b815161099d816109a456fea26469706673582212205a7c1aaaced9bdf2235d902e6069e07974af1ab7311735716d83630ee45fac1464736f6c634300080d0033
Verified Source Code Partial Match
Compiler: v0.8.13+commit.abaa5c0e
EVM: london
Optimization: Yes (200 runs)
ICNV.sol 8 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.13;
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
interface ICNV is IERC20 {
function mint(address account, uint256 amount) external;
}
IRedeemBBT.sol 41 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.13;
interface IRedeemBBT {
/// @notice mapping of how many CNV tokens a bbtCNV holder has redeemed
/// @param _who address
/// @return amount amount redeemed so far
function redeemed(address _who)
external
view
returns(uint256 amount);
/// @notice redeem bbtCNV for CNV following vesting schedule
/// @param _amount amount of CNV to redeem, irrelevant if _max = true
/// @param _who address of bbtCNV holder to redeem
/// @param _to address to which to mint CNV
/// @param _max whether to redeem maximum amount possible
/// @return amountOut amount of CNV tokens to be minted to _to
function redeem(uint256 _amount, address _who, address _to, bool _max)
external
returns(uint256 amountOut);
/// @notice to view how much a holder has redeemable
/// @param _who bbtHolder address
/// @return amount redeemable
function redeemable(address _who)
external
view
returns(uint256);
/// @notice returns the percent of holdings vested for a given point
/// in time.
/// @param _time point in time
/// @return vpct percent of holdings vested
function vestedPercent(uint256 _time)
external
pure
returns(uint256 vpct);
}
RedeemBBTV2.sol 226 lines
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.13;
import { IERC20 } from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import { Owned } from "solmate/auth/Owned.sol";
import { ICNV } from "./ICNV.sol";
import { IRedeemBBT } from "./IRedeemBBT.sol";
contract RedeemBBTV2 is Owned {
////////////////////////////////////////////////////////////////////////////
// EVENTS
////////////////////////////////////////////////////////////////////////////
// @notice Emitted when a BBT redemption happens.
event Redemption(
address indexed _from,
uint256 indexed _amount
);
// @notice Emitted when contract is paused/unpaused
event Paused (
address indexed caller,
bool isPaused
);
////////////////////////////////////////////////////////////////////////////
// MUTABLE STATE
////////////////////////////////////////////////////////////////////////////
/// @notice address of bbtCNV Token
address public immutable bbtCNV;
/// @notice address of CNV Token
address public immutable CNV;
/// @notice address of RedeemBBT V1
address public immutable redeemBBTV1;
/// @notice mapping of how many CNV tokens a bbtCNV holder has redeemed
mapping(address => uint256) public redeemed;
/// @notice redeem paused;
bool public paused;
////////////////////////////////////////////////////////////////////////////
// IMMUTABLE STATE
////////////////////////////////////////////////////////////////////////////
string internal constant NONE = "NONE LEFT";
uint256 internal constant JUNE_5_2022 = 1654387200;
uint256 internal constant APRIL_1_2023 = 1680307200;
////////////////////////////////////////////////////////////////////////////
// CONSTRUCTOR
////////////////////////////////////////////////////////////////////////////
// Better to use cosntants for production here.
constructor(
address _bbtCNV,
address _CNV,
address _redeemBBTV1
) Owned(msg.sender) {
bbtCNV = _bbtCNV;
CNV = _CNV;
redeemBBTV1 = _redeemBBTV1;
}
////////////////////////////////////////////////////////////////////////////
// ADMIN/MGMT
////////////////////////////////////////////////////////////////////////////
function setPause(
bool _paused
) external onlyOwner {
paused = _paused;
emit Paused(msg.sender, _paused);
}
////////////////////////////////////////////////////////////////////////////
// ACTIONS
////////////////////////////////////////////////////////////////////////////
/// @notice redeem bbtCNV for CNV following vesting schedule
/// @param _amount amount of CNV to redeem, irrelevant if _max = true
/// @param _to address to which to mint CNV
/// @param _max whether to redeem maximum amount possible
/// @return amountOut amount of CNV tokens to be minted to _to
function redeem(
uint256 _amount,
address _to,
bool _max
) external returns (uint256 amountOut) {
// Check if it's paused
require(!paused, "PAUSED");
// Get user bbtCNV balance, and get amount already redeemed.
// If already redeemed full balance - revert on "FULLY_REDEEMED" since
// all balance has already been redeemed.
uint256 bbtCNVBalance = IERC20(bbtCNV).balanceOf(msg.sender);
uint256 amountRedeemed = redeemed[msg.sender] + IRedeemBBT(redeemBBTV1).redeemed(msg.sender);
require(bbtCNVBalance > amountRedeemed, NONE);
// Check how much is currently vested for user.
// Revert if currently no more available to redeem.
uint256 currentTime = block.timestamp;
require(currentTime >= JUNE_5_2022, "NOT_VESTED");
uint256 amountVested;
if (currentTime > APRIL_1_2023) {
amountVested = bbtCNVBalance;
} else {
uint256 vpct = vestedPercent(currentTime);
amountVested = bbtCNVBalance * vpct / 1e18;
}
require(amountVested > amountRedeemed, NONE);
// Calculate amount redeemable as the amountVested minus the amount that
// has previously been redeemed.
// If _max was not selected and thus a specified amount is to be
// redeemed, ensure this amount doesn't exceed amountRedeemable.
uint256 amountRedeemable = amountVested - amountRedeemed;
amountOut = amountRedeemable;
if (!_max) {
require(amountRedeemable >= _amount,"EXCEEDS");
amountOut = _amount;
}
// Update state to reflect redemption.
redeemed[msg.sender] += amountOut;
// Transfer CNV
ICNV(CNV).transfer(_to, amountOut);
emit Redemption(msg.sender, amountOut);
}
////////////////////////////////////////////////////////////////////////////
// VIEW
////////////////////////////////////////////////////////////////////////////
/// @notice to view how much a holder has redeemable
/// @param _who bbtHolder address
/// @return amount redeemable
function redeemable(
address _who
) external view returns (uint256) {
uint256 bbtCNVBalance = IERC20(bbtCNV).balanceOf(_who);
uint256 amountRedeemed = redeemed[_who] + IRedeemBBT(redeemBBTV1).redeemed(_who);
if (bbtCNVBalance == amountRedeemed) return 0;
uint256 currentTime = block.timestamp;
if (currentTime < JUNE_5_2022) return 0;
uint256 amountVested;
if (currentTime > APRIL_1_2023) {
amountVested = bbtCNVBalance;
} else {
uint256 vpct = vestedPercent(currentTime);
amountVested = bbtCNVBalance * vpct / 1e18;
}
if (amountVested <= amountRedeemed) return 0;
return amountVested - amountRedeemed;
}
/// @notice returns the percent of holdings vested for a given point
/// in time.
/// @param _time point in time
/// @return vpct percent of holdings vested
function vestedPercent(
uint256 _time
) public pure returns (uint256 vpct) {
// Hardcode variables in method to avoid state reads and save gas.
//
// vestingTimeStart
// - time vesting begins: JUNE_5_2022 (Sun Jun 05 2022 00:00:00 GMT+0000)
//
// vestingTimeLength
// - duration of vesting: 25920000 (10 30-day months)
//
// vestingAmountStart
// - vesting begins at 2%
//
// vestingAmountLength
// - vesting grows to 100%, thus has a length of 98
uint256 vestingTimeStart = JUNE_5_2022;
uint256 vestingTimeLength = 25920000;
uint256 vestingAmountStart = 2e16;
uint256 vestingAmountLength = 98e16;
uint256 pctOf = _percentOf(vestingTimeStart, _time, vestingTimeLength);
vpct = _linearMapping(vestingAmountStart, pctOf, vestingAmountLength);
}
////////////////////////////////////////////////////////////////////////////
// INTERNAL
////////////////////////////////////////////////////////////////////////////
/// @notice returns the elapsed percentage of a point within
/// a given range
/// @param _start starting point
/// @param _point current point
/// @param _length lenght
/// @return elapsedPct percent from _start
function _percentOf(
uint256 _start,
uint256 _point,
uint256 _length
) internal pure returns(uint256 elapsedPct) {
uint256 elapsed = _point - _start;
elapsedPct = elapsed * 1e18 / _length;
}
/// @notice linearly maps a percentage point to a range
/// @param _start starting point
/// @param _pct percentage point
/// @param _length lenght
/// @return point point
function _linearMapping(
uint256 _start,
uint256 _pct,
uint256 _length
) internal pure returns (uint256 point) {
uint256 elapsed = _length * _pct / 1e18;
point = _start + elapsed;
}
}
Owned.sol 44 lines
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;
/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event OwnerUpdated(address indexed user, address indexed newOwner);
/*//////////////////////////////////////////////////////////////
OWNERSHIP STORAGE
//////////////////////////////////////////////////////////////*/
address public owner;
modifier onlyOwner() virtual {
require(msg.sender == owner, "UNAUTHORIZED");
_;
}
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor(address _owner) {
owner = _owner;
emit OwnerUpdated(address(0), _owner);
}
/*//////////////////////////////////////////////////////////////
OWNERSHIP LOGIC
//////////////////////////////////////////////////////////////*/
function setOwner(address newOwner) public virtual onlyOwner {
owner = newOwner;
emit OwnerUpdated(msg.sender, newOwner);
}
}
IERC20.sol 82 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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);
/**
* @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 `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, 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 `from` to `to` 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 from,
address to,
uint256 amount
) external returns (bool);
}
Read Contract
CNV 0xd51a020b → address
bbtCNV 0x53620494 → address
owner 0x8da5cb5b → address
paused 0x5c975abb → bool
redeemBBTV1 0xa695aa4d → address
redeemable 0x484267a4 → uint256
redeemed 0x9f4568ef → uint256
vestedPercent 0xbbb333ed → uint256
Write Contract 3 functions
These functions modify contract state and require a wallet transaction to execute.
redeem 0x5236be40
uint256 _amount
address _to
bool _max
returns: uint256
setOwner 0x13af4035
address newOwner
setPause 0xbedb86fb
bool _paused
Recent Transactions
No transactions found for this address