From 7a8e283e3230bdea0d0dc9d0657dc620ab1d51de Mon Sep 17 00:00:00 2001 From: dristpunk <107591874+dristpunk@users.noreply.github.com> Date: Fri, 23 Feb 2024 19:21:27 +0300 Subject: [PATCH] style: simplify code (#7) --- .github/workflows/ci.yml | 2 +- .gitignore | 1 + solidity/contracts/ConnextVestingWallet.sol | 194 ++++++------------ solidity/contracts/VestingWalletWithCliff.sol | 55 ----- solidity/interfaces/IConnextVestingWallet.sol | 153 ++++++++++++++ .../integration/ConnextVestingWallet.t.sol | 62 +++--- solidity/test/integration/LlamaVesting.t.sol | 14 +- solidity/test/utils/Constants.sol | 3 - 8 files changed, 245 insertions(+), 239 deletions(-) delete mode 100644 solidity/contracts/VestingWalletWithCliff.sol create mode 100644 solidity/interfaces/IConnextVestingWallet.sol diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 206ce0d..d9ae634 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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: diff --git a/.gitignore b/.gitignore index 9be8a61..9209344 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ yarn-error.log node_modules .DS_STORE +.vscode # Foundry files cache diff --git a/solidity/contracts/ConnextVestingWallet.sol b/solidity/contracts/ConnextVestingWallet.sol index cce08db..588c149 100644 --- a/solidity/contracts/ConnextVestingWallet.sol +++ b/solidity/contracts/ConnextVestingWallet.sol @@ -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'; /** @@ -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)); diff --git a/solidity/contracts/VestingWalletWithCliff.sol b/solidity/contracts/VestingWalletWithCliff.sol deleted file mode 100644 index 19a2b50..0000000 --- a/solidity/contracts/VestingWalletWithCliff.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.20; - -import {VestingWallet} from '@openzeppelin/contracts/finance/VestingWallet.sol'; - -contract VestingWalletWithCliff is VestingWallet { - /** - * @dev The cliff timestamp, set into constructor - */ - uint64 private immutable _CLIFF; - - /** - * @dev Constructor that initializes the vesting schedule. - * @param _beneficiary The beneficiary of the vested tokens. - * @param _vestingStartTimestamp The start time of the vesting schedule. - * @param _durationSeconds The duration of the vesting schedule, in seconds. - * @param _cliffDurationSeconds The duration before the cliff, in seconds. - */ - constructor( - address _beneficiary, - uint64 _vestingStartTimestamp, - uint64 _durationSeconds, - uint64 _cliffDurationSeconds - ) VestingWallet(_beneficiary, _vestingStartTimestamp, _durationSeconds) { - _CLIFF = _vestingStartTimestamp + _cliffDurationSeconds; - } - - /** - * @dev Getter for the cliff timestamp. - * @return _timestamp The timestamp of the cliff. - */ - function cliff() public view virtual returns (uint256 _timestamp) { - return _CLIFF; - } - - /** - * @dev Virtual implementation of the vesting formula. This returns the amount vested, as a function of time, for - * an asset given its total historical allocation. - * @param _totalAllocation The total amount of tokens to be vested. - * @param _timestamp The timestamp to calculate vesting for. - * @return _amount The amount to vest for the passed timestamp. - */ - function _vestingSchedule( - uint256 _totalAllocation, - uint64 _timestamp - ) internal view virtual override returns (uint256 _amount) { - if (_timestamp < cliff()) { - return 0; - } else if (_timestamp >= end()) { - return _totalAllocation; - } else { - return (_totalAllocation * (_timestamp - start())) / duration(); - } - } -} diff --git a/solidity/interfaces/IConnextVestingWallet.sol b/solidity/interfaces/IConnextVestingWallet.sol new file mode 100644 index 0000000..4ffe06b --- /dev/null +++ b/solidity/interfaces/IConnextVestingWallet.sol @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.20; + +import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; + +interface IConnextVestingWallet { + /*/////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Emits when the owner releases tokens + * @param _token The address of the released ERC20 token + * @param _amount The amount of tokens released + */ + event ERC20Released(address indexed _token, uint256 _amount); + + /*/////////////////////////////////////////////////////////////// + ERRRORS + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Permission denied + */ + error NotAllowed(); + + /** + * @notice Zero address not allowed + */ + error ZeroAddress(); + + /*/////////////////////////////////////////////////////////////// + CONSTANTS + //////////////////////////////////////////////////////////////*/ + + /** + * @notice NEXT token address + * @return _nextToken The address of the NEXT token + */ + function NEXT_TOKEN() external view returns (address _nextToken); + + /** + * @notice Token launch date + * @return _timestamp The timestamp of the token launch + */ + function NEXT_TOKEN_LAUNCH() external view returns (uint64 _timestamp); + + /** + * @notice 1 month in seconds (on average) + * @return _timedelta The timedelta of one month + */ + function ONE_MONTH() external view returns (uint64 _timedelta); + + /** + * @notice 1 year in seconds + * @return _timedelta The timedelta of one year + */ + function ONE_YEAR() external view returns (uint64 _timedelta); + + /** + * @notice Sept 5th 2023 in seconds + * @return _timestamp The timestamp of Sept 5th 2023 + */ + function SEPT_05_2023() external view returns (uint64 _timestamp); + + /** + * @notice Vesting cliff duration + * @return _timedelta The timedelta of the cliff duration + */ + function UNLOCK_CLIFF_DURATION() external view returns (uint64 _timedelta); + + /** + * @notice Vesting duration including cliff duration + * @return _timedelta The timedelta of the vesting duration + */ + function UNLOCK_DURATION() external view returns (uint64 _timedelta); + + /** + * @notice Vesting warmup time + * @return _timedelta The timedelta of the warmup time + */ + function UNLOCK_OFFSET() external view returns (uint64 _timedelta); + + /** + * @notice Vesting start date + * @return _timestamp The timestamp of the start date + */ + function UNLOCK_START() external view returns (uint64 _timestamp); + + /** + * @notice Vesting cliff date + * @return _timestamp The timestamp of the cliff date + */ + function UNLOCK_CLIFF() external view returns (uint64 _timestamp); + + /** + * @notice Vesting end date + * @return _timestamp The timestamp of the end date + */ + function UNLOCK_END() external view returns (uint64 _timestamp); + + /*/////////////////////////////////////////////////////////////// + STORAGE + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Total amount of tokens to be vested + * @return _amount The total amount of tokens + */ + function TOTAL_AMOUNT() external view returns (uint256 _amount); + + /** + * @notice The amount of NEXT tokens that are already released + * @return _released The amount of tokens released + */ + function released() external view returns (uint256 _released); + + /*/////////////////////////////////////////////////////////////// + UNLOCK LOGIC + //////////////////////////////////////////////////////////////*/ + + /** + * @notice Claim tokens from Llama Vesting contract + * @param _llamaVestAddress The address of the Llama Vesting contract + */ + function claim(address _llamaVestAddress) external; + + /** + * @notice Collect dust from the contract + * @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; + + /** + * @notice Release releasable NEXT tokens to the owner + */ + function release() external; + + /** + * @notice Calculate the amount of NEXT tokens vested at a given timestamp + * @param _timestamp The timestamp to calculate the vested amount + * @return _amount The amount of tokens vested + */ + function vestedAmount(uint64 _timestamp) external view returns (uint256 _amount); + + /** + * @notice Calculate the amount of NEXT tokens ready to release + * @return _amount The amount of tokens ready to release + */ + function releasable() external view returns (uint256 _amount); +} diff --git a/solidity/test/integration/ConnextVestingWallet.t.sol b/solidity/test/integration/ConnextVestingWallet.t.sol index ce5a52e..b1373c0 100644 --- a/solidity/test/integration/ConnextVestingWallet.t.sol +++ b/solidity/test/integration/ConnextVestingWallet.t.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.20; import {Ownable, Ownable2Step} from '@openzeppelin/contracts/access/Ownable2Step.sol'; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; -import {ConnextVestingWallet} from 'contracts/ConnextVestingWallet.sol'; +import {ConnextVestingWallet, IConnextVestingWallet} from 'contracts/ConnextVestingWallet.sol'; import {Constants} from 'test/utils/Constants.sol'; import {IVestingEscrowSimple} from 'interfaces/IVestingEscrowSimple.sol'; @@ -48,7 +48,7 @@ contract UnitConnextVestingWallet is Test, Constants { _connextVestingWallet = new ConnextVestingWallet(owner, 13 ether); _connextVestingWalletAddress = address(_connextVestingWallet); _connextTokenLaunch = uint64(_connextVestingWallet.NEXT_TOKEN_LAUNCH()); - _firstMilestoneTimestamp = uint64(_connextVestingWallet.cliff()); + _firstMilestoneTimestamp = uint64(_connextVestingWallet.UNLOCK_CLIFF()); } /** @@ -70,28 +70,18 @@ contract UnitConnextVestingWallet is Test, Constants { * After the end of the unlocking period: 13 ether tokens */ function test_UnlockedAtTimestamp() public { - assertEq(_connextVestingWallet.vestedAmount(NEXT_TOKEN_ADDRESS, _connextTokenLaunch), 0); - assertEq(_connextVestingWallet.vestedAmount(NEXT_TOKEN_ADDRESS, _firstMilestoneTimestamp - 1), 0); + assertEq(_connextVestingWallet.vestedAmount(_connextTokenLaunch), 0); + assertEq(_connextVestingWallet.vestedAmount(_firstMilestoneTimestamp - 1), 0); - assertEq(_connextVestingWallet.vestedAmount(NEXT_TOKEN_ADDRESS, _firstMilestoneTimestamp), 1 ether); + assertEq(_connextVestingWallet.vestedAmount(_firstMilestoneTimestamp), 1 ether); - assertApproxEqAbs( - _connextVestingWallet.vestedAmount(NEXT_TOKEN_ADDRESS, _firstMilestoneTimestamp + MONTH), 2 ether, MAX_DELTA - ); + assertEq(_connextVestingWallet.vestedAmount(_firstMilestoneTimestamp + MONTH), 2 ether); - assertApproxEqAbs( - _connextVestingWallet.vestedAmount(NEXT_TOKEN_ADDRESS, _firstMilestoneTimestamp + MONTH * 2), 3 ether, MAX_DELTA - ); + assertEq(_connextVestingWallet.vestedAmount(_firstMilestoneTimestamp + MONTH * 2), 3 ether); - assertApproxEqAbs( - _connextVestingWallet.vestedAmount(NEXT_TOKEN_ADDRESS, _firstMilestoneTimestamp + YEAR), 13 ether, MAX_DELTA - ); + assertEq(_connextVestingWallet.vestedAmount(_firstMilestoneTimestamp + YEAR), 13 ether); - assertApproxEqAbs( - _connextVestingWallet.vestedAmount(NEXT_TOKEN_ADDRESS, _firstMilestoneTimestamp + YEAR + 10 days), - 13 ether, - MAX_DELTA - ); + assertEq(_connextVestingWallet.vestedAmount(_firstMilestoneTimestamp + YEAR + 10 days), 13 ether); } /** @@ -101,29 +91,29 @@ contract UnitConnextVestingWallet is Test, Constants { function test_WithdrawableAmount() public { deal(NEXT_TOKEN_ADDRESS, _connextVestingWalletAddress, 15 ether); - assertEq(_connextVestingWallet.releasable(NEXT_TOKEN_ADDRESS), 0); + assertEq(_connextVestingWallet.releasable(), 0); vm.warp(_connextTokenLaunch + YEAR - 1); - assertEq(_connextVestingWallet.releasable(NEXT_TOKEN_ADDRESS), 0); + assertEq(_connextVestingWallet.releasable(), 0); vm.warp(_firstMilestoneTimestamp); - assertEq(_connextVestingWallet.releasable(NEXT_TOKEN_ADDRESS), 1 ether); + assertEq(_connextVestingWallet.releasable(), 1 ether); vm.warp(_firstMilestoneTimestamp + MONTH); - assertApproxEqAbs(_connextVestingWallet.releasable(NEXT_TOKEN_ADDRESS), 2 ether, MAX_DELTA); + assertEq(_connextVestingWallet.releasable(), 2 ether); - _connextVestingWallet.release(NEXT_TOKEN_ADDRESS); - assertEq(_connextVestingWallet.releasable(NEXT_TOKEN_ADDRESS), 0 ether); + _connextVestingWallet.release(); + assertEq(_connextVestingWallet.releasable(), 0 ether); // 2 ether have been withdrawn vm.warp(_firstMilestoneTimestamp + MONTH * 2); - assertApproxEqAbs(_connextVestingWallet.releasable(NEXT_TOKEN_ADDRESS), 3 ether - 2 ether, MAX_DELTA); + assertEq(_connextVestingWallet.releasable(), 3 ether - 2 ether); vm.warp(_firstMilestoneTimestamp + YEAR); - assertApproxEqAbs(_connextVestingWallet.releasable(NEXT_TOKEN_ADDRESS), 13 ether - 2 ether, MAX_DELTA); + assertEq(_connextVestingWallet.releasable(), 13 ether - 2 ether); vm.warp(_firstMilestoneTimestamp + YEAR + 10 days); - assertApproxEqAbs(_connextVestingWallet.releasable(NEXT_TOKEN_ADDRESS), 13 ether - 2 ether, MAX_DELTA); + assertEq(_connextVestingWallet.releasable(), 13 ether - 2 ether); } /** @@ -135,15 +125,15 @@ contract UnitConnextVestingWallet is Test, Constants { vm.warp(_firstMilestoneTimestamp); vm.startPrank(owner); - _connextVestingWallet.release(NEXT_TOKEN_ADDRESS); + _connextVestingWallet.release(); // Even though the contract has more tokens, the unlocked amount should be the same - assertEq(_connextVestingWallet.released(NEXT_TOKEN_ADDRESS), 1 ether); + assertEq(_connextVestingWallet.released(), 1 ether); assertEq(_nextToken.balanceOf(owner), 1 ether); // Try again and expect no changes - _connextVestingWallet.release(NEXT_TOKEN_ADDRESS); - assertEq(_connextVestingWallet.released(NEXT_TOKEN_ADDRESS), 1 ether); + _connextVestingWallet.release(); + assertEq(_connextVestingWallet.released(), 1 ether); assertEq(_nextToken.balanceOf(owner), 1 ether); vm.stopPrank(); @@ -153,9 +143,9 @@ contract UnitConnextVestingWallet is Test, Constants { * @notice Shouldn't revert if there is nothing to withdraw */ function test_Withdraw_NoSupply() public { - _connextVestingWallet.release(NEXT_TOKEN_ADDRESS); + _connextVestingWallet.release(); - assertEq(_connextVestingWallet.releasable(NEXT_TOKEN_ADDRESS), 0); + assertEq(_connextVestingWallet.releasable(), 0); assertEq(_nextToken.balanceOf(owner), 0); } @@ -202,7 +192,7 @@ contract UnitConnextVestingWallet is Test, Constants { // Can't collect the vesting token assertEq(_nextToken.balanceOf(_randomAddress), 0); - vm.expectRevert(abi.encodeWithSelector(ConnextVestingWallet.NotAllowed.selector)); + vm.expectRevert(abi.encodeWithSelector(IConnextVestingWallet.NotAllowed.selector)); vm.prank(owner); _connextVestingWallet.sendDust(_nextToken, _dustAmount, _randomAddress); assertEq(_nextToken.balanceOf(_randomAddress), 0); @@ -222,7 +212,7 @@ contract UnitConnextVestingWallet is Test, Constants { // Collect vesting token after the vesting period has ended vm.warp(_firstMilestoneTimestamp + 365 days * 3 + 10 days); assertEq(_nextToken.balanceOf(_randomAddress), 0); - _connextVestingWallet.release(NEXT_TOKEN_ADDRESS); + _connextVestingWallet.release(); vm.prank(owner); _connextVestingWallet.sendDust(_nextToken, _dustAmount, _randomAddress); assertEq(_nextToken.balanceOf(_randomAddress), _dustAmount); diff --git a/solidity/test/integration/LlamaVesting.t.sol b/solidity/test/integration/LlamaVesting.t.sol index 896ff2b..61d1356 100644 --- a/solidity/test/integration/LlamaVesting.t.sol +++ b/solidity/test/integration/LlamaVesting.t.sol @@ -4,13 +4,9 @@ pragma solidity 0.8.20; import {IntegrationBase} from 'test/integration/IntegrationBase.sol'; contract IntegrationLlamaVesting is IntegrationBase { - uint256 internal _vestingStartTime; - - function setUp() public override { - super.setUp(); - _vestingStartTime = _connextVestingWallet.start(); - } - + /** + * @notice Assert balances on key points of the timeline + */ function test_VestAndUnlock() public { // At launch date uint256 _timestamp = SEP_05_2023; @@ -55,14 +51,14 @@ contract IntegrationLlamaVesting is IntegrationBase { function _warpAndWithdraw(uint256 _timestamp) internal { vm.warp(_timestamp); _connextVestingWallet.claim(address(_llamaVest)); - _connextVestingWallet.release(NEXT_TOKEN_ADDRESS); + _connextVestingWallet.release(); } /** * @notice Each withdrawal should equally increase the withdrawn amount and the owner's balance */ function _assertOwnerBalance(uint256 _balance) internal { - assertApproxEqAbs(_connextVestingWallet.released(NEXT_TOKEN_ADDRESS), _balance, MAX_DELTA); + assertApproxEqAbs(_connextVestingWallet.released(), _balance, MAX_DELTA); assertApproxEqAbs(_nextToken.balanceOf(owner), _balance, MAX_DELTA); } diff --git a/solidity/test/utils/Constants.sol b/solidity/test/utils/Constants.sol index 43e10ce..912f96a 100644 --- a/solidity/test/utils/Constants.sol +++ b/solidity/test/utils/Constants.sol @@ -11,9 +11,6 @@ contract Constants { // The total amount of tokens to be vested uint256 public constant TOTAL_AMOUNT = 24_960_000 ether; - // The amount of tokens to be streamed per second, TOTAL_AMOUNT / 4 years, with 20 decimals - uint216 public constant PAY_PER_SECOND = 0.19786910197869101978 * 1e20; - address public constant DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F; address public constant NEXT_TOKEN_ADDRESS = 0xFE67A4450907459c3e1FFf623aA927dD4e28c67a; address public constant LLAMA_FACTORY_ADDRESS = 0xB93427b83573C8F27a08A909045c3e809610411a;