Skip to content

Commit

Permalink
style: simplify code (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
dristpunk authored Feb 23, 2024
1 parent 50d4040 commit 7a8e283
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 239 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ concurrency:

env:
MAINNET_RPC: ${{ secrets.MAINNET_RPC }}
DEPLOYER_PRIVATE_KEY: '0x115241e9f8d2246550d50641f38ee4170b937f25dfb983f7e34960f9670fc41d'
DEPLOYER_PRIVATE_KEY: ${{ secrets.DEPLOYER_PRIVATE_KEY }}

jobs:
integration-tests:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
yarn-error.log
node_modules
.DS_STORE
.vscode

# Foundry files
cache
Expand Down
194 changes: 59 additions & 135 deletions solidity/contracts/ConnextVestingWallet.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

// solhint-disable-next-line no-unused-import
import {VestingWallet, VestingWalletWithCliff} from './VestingWalletWithCliff.sol';

import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
import {Ownable2Step} from '@openzeppelin/contracts/access/Ownable2Step.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

import {IConnextVestingWallet} from 'interfaces/IConnextVestingWallet.sol';
import {IVestingEscrowSimple} from 'interfaces/IVestingEscrowSimple.sol';

/**
Expand All @@ -16,183 +15,108 @@ import {IVestingEscrowSimple} from 'interfaces/IVestingEscrowSimple.sol';
* and 1/13 unlocks every month thereafter for 12 months. All tokens are unlocked after 24 months.
* https://forum.connext.network/t/rfc-partnership-token-agreements/938
*/
contract ConnextVestingWallet is VestingWalletWithCliff, Ownable2Step {
/*///////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*/

/**
* @notice 1 year in seconds
*/
contract ConnextVestingWallet is Ownable2Step, IConnextVestingWallet {
/// @inheritdoc IConnextVestingWallet
uint64 public constant ONE_YEAR = 365 days;

/**
* @notice 1 month in seconds (on average)
*/
/// @inheritdoc IConnextVestingWallet
uint64 public constant ONE_MONTH = ONE_YEAR / 12;

/**
* @notice Sept 5th 2023 in seconds
*/
/// @inheritdoc IConnextVestingWallet
uint64 public constant SEPT_05_2023 = 1_693_872_000;

/**
* @notice Token launch date
* @dev Equals to Sept 5th 2023
*/
uint64 public constant NEXT_TOKEN_LAUNCH = SEPT_05_2023;
/// @inheritdoc IConnextVestingWallet
uint64 public constant NEXT_TOKEN_LAUNCH = SEPT_05_2023; // Equals to Sept 5th 2023

/**
* @notice NEXT token address
* @dev Mainnet address
*/
address public constant NEXT_TOKEN = 0xFE67A4450907459c3e1FFf623aA927dD4e28c67a;
/// @inheritdoc IConnextVestingWallet
address public constant NEXT_TOKEN = 0xFE67A4450907459c3e1FFf623aA927dD4e28c67a; // Mainnet NEXT token address

/**
* NOTE: The equivalent vesting schedule has a 13 months duration, with a 1 month cliff,
* offsetted to start from `Sept 5th 2024 - 1 month`: At Sept 5th 2024 the cliff
* is triggered unlocking 1/13 of the tokens, and then 1/13 of the tokens will
* be linearly unlocked every month after that.
*/
/// @inheritdoc IConnextVestingWallet
uint64 public constant UNLOCK_DURATION = ONE_YEAR + ONE_MONTH; // 13 months duration

/**
* @notice Vesting duration including one month of cliff
* @dev 13 months duration
*/
uint64 public constant VESTING_DURATION = ONE_YEAR + ONE_MONTH;
/// @inheritdoc IConnextVestingWallet
uint64 public constant UNLOCK_CLIFF_DURATION = ONE_MONTH; // 1 month cliff

/**
* @notice Vesting cliff duration
* @dev 1 month cliff
*/
uint64 public constant VESTING_CLIFF_DURATION = ONE_MONTH;
/// @inheritdoc IConnextVestingWallet
uint64 public constant UNLOCK_OFFSET = ONE_YEAR - ONE_MONTH; // 11 months offset

/**
* @notice Vesting warmup time
* @dev 11 months offset
*/
uint64 public constant VESTING_OFFSET = ONE_YEAR - ONE_MONTH;
/// @inheritdoc IConnextVestingWallet
uint64 public constant UNLOCK_START = NEXT_TOKEN_LAUNCH + UNLOCK_OFFSET; // Sept 5th 2024 - 1 month

/**
* @notice Vesting start date
* @dev Sept 5th 2024 - 1 month
*/
uint64 public constant VESTING_START_DATE = NEXT_TOKEN_LAUNCH + VESTING_OFFSET;
/// @inheritdoc IConnextVestingWallet
uint64 public constant UNLOCK_CLIFF = UNLOCK_START + UNLOCK_CLIFF_DURATION; // Sept 5th 2024

/*///////////////////////////////////////////////////////////////
STORAGE
//////////////////////////////////////////////////////////////*/
/// @inheritdoc IConnextVestingWallet
uint64 public constant UNLOCK_END = UNLOCK_START + UNLOCK_DURATION; // Sept 5th 2025

/**
* @notice Total amount of tokens to be vested
* @dev Set into constructor
*/
uint256 public immutable TOTAL_AMOUNT;
/// @inheritdoc IConnextVestingWallet
uint256 public immutable TOTAL_AMOUNT; // Set into constructor

/// @inheritdoc IConnextVestingWallet
uint256 public released;

/**
* @dev Init VestingWalletWithCliff and save total amout of tokens to be unlocked
* @param _beneficiary The address of the beneficiary
* @param _totalAmount The total amount of tokens to be unlocked
* @param _owner The address of the beneficiary
* @param _totalAmount The total amount of tokens to be unlocked
*/
constructor(
address _beneficiary,
uint256 _totalAmount
) VestingWalletWithCliff(_beneficiary, VESTING_START_DATE, VESTING_DURATION, VESTING_CLIFF_DURATION) {
constructor(address _owner, uint256 _totalAmount) Ownable(_owner) {
TOTAL_AMOUNT = _totalAmount;
}

/*///////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/

/**
* @notice Permission denied
*/
error NotAllowed();

/**
* @notice Zero address not allowed
* NOTE: The equivalent unlock schedule has a 13 months duration, with a 1 month cliff,
* offsetted to start from `Sept 5th 2024 - 1 month`: At Sept 5th 2024 the cliff
* is triggered unlocking 1/13 of the tokens, and then 1/13 of the tokens will
* be linearly unlocked every month after that.
*/
error ZeroAddress();

/*///////////////////////////////////////////////////////////////
OVERRIDES
//////////////////////////////////////////////////////////////*/

/**
* @inheritdoc VestingWallet
* @notice This contract is only meant to unlock NEXT tokens
*/
function vestedAmount(uint64) public view virtual override returns (uint256 _amount) {
return 0;
/// @inheritdoc IConnextVestingWallet
function vestedAmount(uint64 _timestamp) public view returns (uint256 _amount) {
if (_timestamp < UNLOCK_CLIFF) {
return 0;
} else if (_timestamp >= UNLOCK_END) {
return TOTAL_AMOUNT;
} else {
return (TOTAL_AMOUNT * (_timestamp - UNLOCK_START)) / UNLOCK_DURATION;
}
}

/**
* @inheritdoc VestingWallet
* @notice This contract is only meant to unlock NEXT tokens
*/
function vestedAmount(address _token, uint64 _timestamp) public view virtual override returns (uint256 _amount) {
if (_token != NEXT_TOKEN) return 0;

return _vestingSchedule(TOTAL_AMOUNT, _timestamp);
/// @inheritdoc IConnextVestingWallet
function release() public {
uint256 _amount = releasable();
released += _amount;
IERC20(NEXT_TOKEN).transfer(owner(), _amount);
emit ERC20Released(NEXT_TOKEN, _amount);
}

/**
* @inheritdoc VestingWallet
* @notice This contract is only meant to unlock NEXT tokens
*/
function releasable(address _token) public view virtual override returns (uint256 _amount) {
_amount = vestedAmount(_token, uint64(block.timestamp)) - released(_token);
uint256 _balance = IERC20(_token).balanceOf(address(this));
/// @inheritdoc IConnextVestingWallet
function releasable() public view returns (uint256 _amount) {
_amount = vestedAmount(uint64(block.timestamp)) - released;
uint256 _balance = IERC20(NEXT_TOKEN).balanceOf(address(this));
_amount = _balance < _amount ? _balance : _amount;
}

/**
* @inheritdoc Ownable2Step
* @dev Override needed by linearization
*/
function _transferOwnership(address _newOwner) internal virtual override(Ownable2Step, Ownable) {
super._transferOwnership(_newOwner);
}

/**
* @inheritdoc Ownable2Step
* @dev Override needed by linearization
*/
function transferOwnership(address _newOwner) public virtual override(Ownable2Step, Ownable) {
super.transferOwnership(_newOwner);
}

/*///////////////////////////////////////////////////////////////
CUSTOM LOGIC
//////////////////////////////////////////////////////////////*/

/**
* @notice Collect dust from the contract
* @inheritdoc IConnextVestingWallet
* @dev This contract allows to withdraw any token, with the exception of unlocked NEXT tokens
* @param _token The address of the token to withdraw
* @param _amount The amount of tokens to withdraw
* @param _to The address to send the tokens to
*/
function sendDust(IERC20 _token, uint256 _amount, address _to) external onlyOwner {
if (_to == address(0)) revert ZeroAddress();
if (_token == IERC20(NEXT_TOKEN) && released(NEXT_TOKEN) != TOTAL_AMOUNT) {

if (_token == IERC20(NEXT_TOKEN) && released != TOTAL_AMOUNT) {
revert NotAllowed();
}

if (_token == IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE)) {
// Sending ETH
payable(_to).transfer(_amount);
payable(_to).transfer(_amount); // Sending ETH
} else {
// Sending ERC20s
_token.transfer(_to, _amount);
_token.transfer(_to, _amount); // Sending ERC20s
}
}

/**
* @notice Claim tokens from Llama Vesting contract
* @inheritdoc IConnextVestingWallet
* @dev This func is needed because only the recipients can claim
* @param _llamaVestAddress The address of the Llama Vesting contract
*/
function claim(address _llamaVestAddress) external {
IVestingEscrowSimple(_llamaVestAddress).claim(address(this));
Expand Down
55 changes: 0 additions & 55 deletions solidity/contracts/VestingWalletWithCliff.sol

This file was deleted.

Loading

0 comments on commit 7a8e283

Please sign in to comment.