From e7162be72038d24bc0bc10b1bd1e6e0c50fc43cb Mon Sep 17 00:00:00 2001 From: BkChoy Date: Tue, 20 Feb 2024 17:29:00 +1300 Subject: [PATCH] bug fixes and improvements --- .../ccip/SDLPoolCCIPControllerPrimary.sol | 5 ++ .../ccip/SDLPoolCCIPControllerSecondary.sol | 10 ++- contracts/core/ccip/WrappedTokenBridge.sol | 32 +++++---- contracts/core/ccip/base/CCIPReceiver.sol | 66 +++++++++++++++++++ .../core/ccip/base/SDLPoolCCIPController.sol | 25 ++++--- .../core/sdlPool/LinearBoostController.sol | 28 ++++++-- contracts/core/sdlPool/SDLPoolPrimary.sol | 5 +- contracts/core/sdlPool/SDLPoolSecondary.sol | 14 ++-- contracts/core/sdlPool/base/SDLPool.sol | 8 +-- .../core/test/chainlink/CCIPOffRampMock.sol | 2 +- .../core/test/chainlink/CCIPOnRampMock.sol | 5 +- test/core/ccip/resdl-token-bridge.test.ts | 2 +- .../sdl-pool-ccip-controller-primary.test.ts | 10 ++- ...sdl-pool-ccip-controller-secondary.test.ts | 10 ++- test/core/ccip/wrapped-token-bridge.test.ts | 14 ++-- .../sdlPool/linear-boost-controller.test.ts | 6 +- test/core/sdlPool/sdl-pool-primary.test.ts | 3 +- test/core/sdlPool/sdl-pool-secondary.test.ts | 1 + 18 files changed, 192 insertions(+), 54 deletions(-) create mode 100644 contracts/core/ccip/base/CCIPReceiver.sol diff --git a/contracts/core/ccip/SDLPoolCCIPControllerPrimary.sol b/contracts/core/ccip/SDLPoolCCIPControllerPrimary.sol index c7555ebe..e5dd5e66 100644 --- a/contracts/core/ccip/SDLPoolCCIPControllerPrimary.sol +++ b/contracts/core/ccip/SDLPoolCCIPControllerPrimary.sol @@ -8,6 +8,11 @@ interface ISDLPoolPrimary is ISDLPool { function handleIncomingUpdate(uint256 _numNewRESDLTokens, int256 _totalRESDLSupplyChange) external returns (uint256); } +/** + * @title SDL Pool CCIP Controller Secondary + * @notice Acts as interface between CCIP and primary SDL Pool + * @dev deployed only on primary chain + */ contract SDLPoolCCIPControllerPrimary is SDLPoolCCIPController { using SafeERC20 for IERC20; diff --git a/contracts/core/ccip/SDLPoolCCIPControllerSecondary.sol b/contracts/core/ccip/SDLPoolCCIPControllerSecondary.sol index 591b752e..cdf32e89 100644 --- a/contracts/core/ccip/SDLPoolCCIPControllerSecondary.sol +++ b/contracts/core/ccip/SDLPoolCCIPControllerSecondary.sol @@ -11,6 +11,12 @@ interface ISDLPoolSecondary is ISDLPool { function shouldUpdate() external view returns (bool); } +/** + * @title SDL Pool CCIP Controller Secondary + * @notice Acts as interface between CCIP and secondary SDL Pools + * @dev deployed on secondary chains, should always hold a small protocol owned reSDL + * position to negate certain edge cases + */ contract SDLPoolCCIPControllerSecondary is SDLPoolCCIPController { using SafeERC20 for IERC20; @@ -72,16 +78,18 @@ contract SDLPoolCCIPControllerSecondary is SDLPoolCCIPController { /** * @notice Handles the outgoing transfer of an reSDL token to the primary chain + * @param _destinationChainSelector id of the destination chain * @param _sender sender of the transfer * @param _tokenId id of token * @return the destination address * @return the token being transferred **/ function handleOutgoingRESDL( - uint64, + uint64 _destinationChainSelector, address _sender, uint256 _tokenId ) external override onlyBridge returns (address, ISDLPool.RESDLToken memory) { + if (_destinationChainSelector != primaryChainSelector) revert InvalidDestination(); return (primaryChainDestination, ISDLPoolSecondary(sdlPool).handleOutgoingRESDL(_sender, _tokenId, address(this))); } diff --git a/contracts/core/ccip/WrappedTokenBridge.sol b/contracts/core/ccip/WrappedTokenBridge.sol index 1f5eeaf7..4169e85e 100644 --- a/contracts/core/ccip/WrappedTokenBridge.sol +++ b/contracts/core/ccip/WrappedTokenBridge.sol @@ -3,11 +3,10 @@ pragma solidity 0.8.15; import {IRouterClient} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol"; import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol"; -import {CCIPReceiver} from "@chainlink/contracts-ccip/src/v0.8/ccip/applications/CCIPReceiver.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../interfaces/IWrappedLST.sol"; +import "./base/CCIPReceiver.sol"; /** * @title Wrapped token bridge @@ -16,7 +15,7 @@ import "../interfaces/IWrappedLST.sol"; * - can wrap tokens and initiate a CCIP transfer of the wrapped tokens to a destination chain * - can receive a CCIP transfer of wrapped tokens, unwrap them, and send them to the receiver */ -contract WrappedTokenBridge is Ownable, CCIPReceiver { +contract WrappedTokenBridge is CCIPReceiver { using SafeERC20 for IERC20; IERC20 linkToken; @@ -119,13 +118,18 @@ contract WrappedTokenBridge is Ownable, CCIPReceiver { /** * @notice Returns the current fee for a token transfer * @param _destinationChainSelector id of destination chain + * @param _amount amount of tokens to transfer * @param _payNative whether fee should be paid natively or with LINK * @return fee current fee **/ - function getFee(uint64 _destinationChainSelector, bool _payNative) external view returns (uint256) { + function getFee( + uint64 _destinationChainSelector, + uint256 _amount, + bool _payNative + ) external view returns (uint256) { Client.EVM2AnyMessage memory evm2AnyMessage = _buildCCIPMessage( address(this), - 1000 ether, + _amount, _payNative ? address(0) : address(linkToken) ); @@ -133,16 +137,20 @@ contract WrappedTokenBridge is Ownable, CCIPReceiver { } /** - * @notice Recovers tokens that were accidentally sent to this contract - * @param _tokens list of tokens to recover - * @param _receiver address to receive recovered tokens + * @notice Withdraws tokens held by this contract + * @param _tokens list of tokens to withdraw + * @param _amounts list of corresponding amounts to withdraw + * @param _receiver address to receive tokens **/ - function recoverTokens(address[] calldata _tokens, address _receiver) external onlyOwner { + function recoverTokens( + address[] calldata _tokens, + uint256[] calldata _amounts, + address _receiver + ) external onlyOwner { if (_receiver == address(0)) revert InvalidReceiver(); for (uint256 i = 0; i < _tokens.length; ++i) { - IERC20 tokenToTransfer = IERC20(_tokens[i]); - tokenToTransfer.safeTransfer(_receiver, tokenToTransfer.balanceOf(address(this))); + IERC20(_tokens[i]).safeTransfer(_receiver, _amounts[i]); } } @@ -220,7 +228,7 @@ contract WrappedTokenBridge is Ownable, CCIPReceiver { receiver: abi.encode(_receiver), data: "", tokenAmounts: tokenAmounts, - extraArgs: "0x", + extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 0})), feeToken: _feeTokenAddress }); diff --git a/contracts/core/ccip/base/CCIPReceiver.sol b/contracts/core/ccip/base/CCIPReceiver.sol new file mode 100644 index 00000000..f84e3482 --- /dev/null +++ b/contracts/core/ccip/base/CCIPReceiver.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.15; + +import {IAny2EVMMessageReceiver} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IAny2EVMMessageReceiver.sol"; +import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +/// @title CCIPReceiver - Base contract for CCIP applications that can receive messages. +/// @dev copied from https://github.com/smartcontractkit and modified to make i_router settable +abstract contract CCIPReceiver is IAny2EVMMessageReceiver, IERC165, Ownable { + address internal i_router; + + constructor(address _router) { + if (_router == address(0)) revert InvalidRouter(address(0)); + i_router = _router; + } + + /// @notice IERC165 supports an interfaceId + /// @param _interfaceId The interfaceId to check + /// @return true if the interfaceId is supported + /// @dev Should indicate whether the contract implements IAny2EVMMessageReceiver + /// e.g. return interfaceId == type(IAny2EVMMessageReceiver).interfaceId || interfaceId == type(IERC165).interfaceId + /// This allows CCIP to check if ccipReceive is available before calling it. + /// If this returns false or reverts, only tokens are transferred to the receiver. + /// If this returns true, tokens are transferred and ccipReceive is called atomically. + /// Additionally, if the receiver address does not have code associated with + /// it at the time of execution (EXTCODESIZE returns 0), only tokens will be transferred. + function supportsInterface(bytes4 _interfaceId) public pure virtual override returns (bool) { + return _interfaceId == type(IAny2EVMMessageReceiver).interfaceId || _interfaceId == type(IERC165).interfaceId; + } + + /// @inheritdoc IAny2EVMMessageReceiver + function ccipReceive(Client.Any2EVMMessage calldata _message) external virtual override onlyRouter { + _ccipReceive(_message); + } + + /// @notice Override this function in your implementation. + /// @param _message Any2EVMMessage + function _ccipReceive(Client.Any2EVMMessage memory _message) internal virtual; + + ///////////////////////////////////////////////////////////////////// + // Plumbing + ///////////////////////////////////////////////////////////////////// + + /// @notice Return the current router + /// @return i_router address + function getRouter() public view returns (address) { + return address(i_router); + } + + /// @notice Sets the router + /// @param _router router address + function setRouter(address _router) external onlyOwner { + if (_router == address(0)) revert InvalidRouter(address(0)); + i_router = _router; + } + + error InvalidRouter(address router); + + /// @dev only calls from the set router are accepted. + modifier onlyRouter() { + if (msg.sender != address(i_router)) revert InvalidRouter(msg.sender); + _; + } +} diff --git a/contracts/core/ccip/base/SDLPoolCCIPController.sol b/contracts/core/ccip/base/SDLPoolCCIPController.sol index 7fe4d529..668f9c12 100644 --- a/contracts/core/ccip/base/SDLPoolCCIPController.sol +++ b/contracts/core/ccip/base/SDLPoolCCIPController.sol @@ -3,14 +3,17 @@ pragma solidity 0.8.15; import {IRouterClient} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol"; import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol"; -import {CCIPReceiver} from "@chainlink/contracts-ccip/src/v0.8/ccip/applications/CCIPReceiver.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "../../interfaces/IRESDLTokenBridge.sol"; import "../../interfaces/ISDLPool.sol"; +import "./CCIPReceiver.sol"; -abstract contract SDLPoolCCIPController is Ownable, CCIPReceiver { +/** + * @title SDL Pool CCIP Controller + * @notice Base contract for SDL Pool CCIP controllers + */ +abstract contract SDLPoolCCIPController is CCIPReceiver { using SafeERC20 for IERC20; IERC20 public immutable linkToken; @@ -110,16 +113,20 @@ abstract contract SDLPoolCCIPController is Ownable, CCIPReceiver { } /** - * @notice Recovers tokens that were accidentally sent to this contract - * @param _tokens list of tokens to recover - * @param _receiver address to receive recovered tokens + * @notice Withdraws tokens held by this contract + * @param _tokens list of tokens to withdraw + * @param _amounts list of corresponding amounts to withdraw + * @param _receiver address to receive tokens **/ - function recoverTokens(address[] calldata _tokens, address _receiver) external onlyOwner { + function recoverTokens( + address[] calldata _tokens, + uint256[] calldata _amounts, + address _receiver + ) external onlyOwner { if (_receiver == address(0)) revert InvalidReceiver(); for (uint256 i = 0; i < _tokens.length; ++i) { - IERC20 tokenToTransfer = IERC20(_tokens[i]); - tokenToTransfer.safeTransfer(_receiver, tokenToTransfer.balanceOf(address(this))); + IERC20(_tokens[i]).safeTransfer(_receiver, _amounts[i]); } } diff --git a/contracts/core/sdlPool/LinearBoostController.sol b/contracts/core/sdlPool/LinearBoostController.sol index a5b798a2..00ce500b 100644 --- a/contracts/core/sdlPool/LinearBoostController.sol +++ b/contracts/core/sdlPool/LinearBoostController.sol @@ -8,20 +8,28 @@ import "@openzeppelin/contracts/access/Ownable.sol"; * @notice Handles boost calculations */ contract LinearBoostController is Ownable { + uint64 public minLockingDuration; uint64 public maxLockingDuration; uint64 public maxBoost; - event SetMaxLockingDuration(uint256 _maxLockingDuration); - event SetMaxBoost(uint256 _maxBoost); + event SetMinLockingDuration(uint64 _minLockingDuration); + event SetMaxLockingDuration(uint64 _maxLockingDuration); + event SetMaxBoost(uint64 _maxBoost); - error MaxLockingDurationExceeded(); + error InvalidLockingDuration(); /** * @notice initializes the contract state + * @param _minLockingDuration minimum non-zero locking duration in seconds * @param _maxLockingDuration maximum locking duration in seconds * @param _maxBoost maximum boost multiplier */ - constructor(uint64 _maxLockingDuration, uint64 _maxBoost) { + constructor( + uint64 _minLockingDuration, + uint64 _maxLockingDuration, + uint64 _maxBoost + ) { + minLockingDuration = _minLockingDuration; maxLockingDuration = _maxLockingDuration; maxBoost = _maxBoost; } @@ -34,10 +42,20 @@ contract LinearBoostController is Ownable { * @return amount of boost balance received in addition to the unboosted balance */ function getBoostAmount(uint256 _amount, uint64 _lockingDuration) external view returns (uint256) { - if (_lockingDuration > maxLockingDuration) revert MaxLockingDurationExceeded(); + if ((_lockingDuration != 0 && _lockingDuration < minLockingDuration) || _lockingDuration > maxLockingDuration) + revert InvalidLockingDuration(); return (_amount * uint256(maxBoost) * uint256(_lockingDuration)) / uint256(maxLockingDuration); } + /** + * @notice sets the minimum non-zero locking duration + * @param _minLockingDuration min non-zero locking duration in seconds + */ + function setMinLockingDuration(uint64 _minLockingDuration) external onlyOwner { + minLockingDuration = _minLockingDuration; + emit SetMinLockingDuration(_minLockingDuration); + } + /** * @notice sets the maximum locking duration * @param _maxLockingDuration max locking duration in seconds diff --git a/contracts/core/sdlPool/SDLPoolPrimary.sol b/contracts/core/sdlPool/SDLPoolPrimary.sol index 86d7095e..3f6caccd 100644 --- a/contracts/core/sdlPool/SDLPoolPrimary.sol +++ b/contracts/core/sdlPool/SDLPoolPrimary.sol @@ -33,10 +33,11 @@ contract SDLPoolPrimary is SDLPool { address _sdlToken, address _boostController ) public reinitializer(2) { - if (delegatorPool == address(0)) { + if (ccipController == address(0)) { __SDLPoolBase_init(_name, _symbol, _sdlToken, _boostController); } else { delegatorPool = ccipController; + delete ccipController; } } @@ -186,6 +187,7 @@ contract SDLPoolPrimary is SDLPool { delete locks[_lockId].amount; delete lockOwners[_lockId]; balances[_sender] -= 1; + delete tokenApprovals[_lockId]; uint256 totalAmount = lock.amount + lock.boostAmount; effectiveBalances[_sender] -= totalAmount; @@ -231,6 +233,7 @@ contract SDLPoolPrimary is SDLPool { function handleIncomingUpdate(uint256 _numNewRESDLTokens, int256 _totalRESDLSupplyChange) external onlyCCIPController + updateRewards(ccipController) returns (uint256) { uint256 mintStartIndex; diff --git a/contracts/core/sdlPool/SDLPoolSecondary.sol b/contracts/core/sdlPool/SDLPoolSecondary.sol index 27150425..179a102c 100644 --- a/contracts/core/sdlPool/SDLPoolSecondary.sol +++ b/contracts/core/sdlPool/SDLPoolSecondary.sol @@ -49,6 +49,7 @@ contract SDLPoolSecondary is SDLPool { error UpdateInProgress(); error NoUpdateInProgress(); error TooManyQueuedLocks(); + error LockWithdrawn(); /// @custom:oz-upgrades-unsafe-allow constructor constructor() { @@ -268,6 +269,7 @@ contract SDLPoolSecondary is SDLPool { delete locks[_lockId].amount; delete lockOwners[_lockId]; balances[_sender] -= 1; + delete tokenApprovals[_lockId]; uint256 totalAmount = lock.amount + lock.boostAmount; effectiveBalances[_sender] -= totalAmount; @@ -432,6 +434,8 @@ contract SDLPoolSecondary is SDLPool { uint64 _lockingDuration ) internal onlyLockOwner(_lockId, _owner) { Lock memory lock = _getQueuedLockState(_lockId); + if (lock.amount == 0) revert LockWithdrawn(); + LockUpdate memory lockUpdate = LockUpdate(updateBatchIndex, _updateLock(lock, _amount, _lockingDuration)); queuedLockUpdates[_lockId].push(lockUpdate); queuedRESDLSupplyChange += @@ -471,21 +475,21 @@ contract SDLPoolSecondary is SDLPool { delete locks[lockId]; delete lockOwners[lockId]; balances[_owner] -= 1; - if (tokenApprovals[lockId] != address(0)) delete tokenApprovals[lockId]; + delete tokenApprovals[lockId]; emit Transfer(_owner, address(0), lockId); } else { locks[lockId].amount = updateLockState.amount; } sdlToken.safeTransfer(_owner, uint256(-1 * baseAmountDiff)); - } else if (boostAmountDiff < 0) { + } else if (boostAmountDiff < 0 && updateLockState.boostAmount == 0) { locks[lockId].expiry = updateLockState.expiry; locks[lockId].boostAmount = 0; emit InitiateUnlock(_owner, lockId, updateLockState.expiry); } else { locks[lockId] = updateLockState; - uint256 totalDiff = uint256(baseAmountDiff + boostAmountDiff); - effectiveBalances[_owner] += totalDiff; - totalEffectiveBalance += totalDiff; + int256 totalDiff = baseAmountDiff + boostAmountDiff; + effectiveBalances[_owner] = uint256(int256(effectiveBalances[_owner]) + totalDiff); + totalEffectiveBalance = uint256(int256(totalEffectiveBalance) + totalDiff); emit UpdateLock( _owner, lockId, diff --git a/contracts/core/sdlPool/base/SDLPool.sol b/contracts/core/sdlPool/base/SDLPool.sol index f036770a..eaff71af 100644 --- a/contracts/core/sdlPool/base/SDLPool.sol +++ b/contracts/core/sdlPool/base/SDLPool.sol @@ -44,6 +44,8 @@ contract SDLPool is RewardsPoolController, IERC721Upgradeable, IERC721MetadataUp string public baseURI; + uint256[3] __gap; + event InitiateUnlock(address indexed owner, uint256 indexed lockId, uint64 expiry); event Withdraw(address indexed owner, uint256 indexed lockId, uint256 amount); event CreateLock( @@ -67,9 +69,8 @@ contract SDLPool is RewardsPoolController, IERC721Upgradeable, IERC721MetadataUp error InvalidLockId(); error InvalidLockingDuration(); error TransferFromIncorrectOwner(); - error TransferToZeroAddress(); + error TransferToInvalidAddress(); error TransferToNonERC721Implementer(); - error TransferToCCIPController(); error ApprovalToCurrentOwner(); error ApprovalToCaller(); error InvalidValue(); @@ -458,8 +459,7 @@ contract SDLPool is RewardsPoolController, IERC721Upgradeable, IERC721MetadataUp uint256 _lockId ) internal virtual { if (_from != ownerOf(_lockId)) revert TransferFromIncorrectOwner(); - if (_to == address(0)) revert TransferToZeroAddress(); - if (_to == ccipController) revert TransferToCCIPController(); + if (_to == address(0) || _to == ccipController || _to == _from) revert TransferToInvalidAddress(); delete tokenApprovals[_lockId]; diff --git a/contracts/core/test/chainlink/CCIPOffRampMock.sol b/contracts/core/test/chainlink/CCIPOffRampMock.sol index eed6b8d4..b79ed557 100644 --- a/contracts/core/test/chainlink/CCIPOffRampMock.sol +++ b/contracts/core/test/chainlink/CCIPOffRampMock.sol @@ -42,7 +42,7 @@ contract CCIPOffRampMock { tokenPools[_tokenAmounts[i].token].releaseOrMint(_receiver, _tokenAmounts[i].amount); } - (bool success, ) = router.routeMessage( + (bool success, , ) = router.routeMessage( Client.Any2EVMMessage(_messageId, _sourceChainSelector, abi.encode(msg.sender), _data, _tokenAmounts), GAS_FOR_CALL_EXACT_CHECK, 1000000, diff --git a/contracts/core/test/chainlink/CCIPOnRampMock.sol b/contracts/core/test/chainlink/CCIPOnRampMock.sol index 11be30ed..6f6ef1c7 100644 --- a/contracts/core/test/chainlink/CCIPOnRampMock.sol +++ b/contracts/core/test/chainlink/CCIPOnRampMock.sol @@ -38,15 +38,16 @@ contract CCIPOnRampMock { return requestData[requestData.length - 1]; } - function getFee(Client.EVM2AnyMessage calldata _message) external view returns (uint256) { + function getFee(uint64, Client.EVM2AnyMessage calldata _message) external view returns (uint256) { return _message.feeToken == linkToken ? 2 ether : 3 ether; } - function getPoolBySourceToken(address _token) public view returns (address) { + function getPoolBySourceToken(uint64, address _token) public view returns (address) { return tokenPools[_token]; } function forwardFromRouter( + uint64, Client.EVM2AnyMessage calldata _message, uint256 _feeTokenAmount, address _originalSender diff --git a/test/core/ccip/resdl-token-bridge.test.ts b/test/core/ccip/resdl-token-bridge.test.ts index 1abf4999..95a434f3 100644 --- a/test/core/ccip/resdl-token-bridge.test.ts +++ b/test/core/ccip/resdl-token-bridge.test.ts @@ -68,7 +68,7 @@ describe('RESDLTokenBridge', () => { await router.applyRampUpdates([[77, onRamp.address]], [], [[77, offRamp.address]]) - let boostController = await deploy('LinearBoostController', [4 * 365 * 86400, 4]) + let boostController = await deploy('LinearBoostController', [10, 4 * 365 * 86400, 4]) sdlPool = (await deployUpgradeable('SDLPoolPrimary', [ 'reSDL', 'reSDL', diff --git a/test/core/ccip/sdl-pool-ccip-controller-primary.test.ts b/test/core/ccip/sdl-pool-ccip-controller-primary.test.ts index b84bdd4c..f0bed948 100644 --- a/test/core/ccip/sdl-pool-ccip-controller-primary.test.ts +++ b/test/core/ccip/sdl-pool-ccip-controller-primary.test.ts @@ -78,7 +78,7 @@ describe('SDLPoolCCIPControllerPrimary', () => { await router.applyRampUpdates([[77, onRamp.address]], [], [[77, offRamp.address]]) - let boostController = await deploy('LinearBoostController', [4 * 365 * 86400, 4]) + let boostController = await deploy('LinearBoostController', [10, 4 * 365 * 86400, 4]) sdlPool = (await deployUpgradeable('SDLPoolPrimary', [ 'reSDL', 'reSDL', @@ -396,9 +396,13 @@ describe('SDLPoolCCIPControllerPrimary', () => { it('recoverTokens should work correctly', async () => { await linkToken.transfer(controller.address, toEther(1000)) await sdlToken.transfer(controller.address, toEther(2000)) - await controller.recoverTokens([linkToken.address, sdlToken.address], accounts[3]) + await controller.recoverTokens( + [linkToken.address, sdlToken.address], + [toEther(1000), toEther(2000)], + accounts[3] + ) - assert.equal(fromEther(await linkToken.balanceOf(accounts[3])), 1100) + assert.equal(fromEther(await linkToken.balanceOf(accounts[3])), 1000) assert.equal(fromEther(await sdlToken.balanceOf(accounts[3])), 2000) }) }) diff --git a/test/core/ccip/sdl-pool-ccip-controller-secondary.test.ts b/test/core/ccip/sdl-pool-ccip-controller-secondary.test.ts index 515f03b5..07412abf 100644 --- a/test/core/ccip/sdl-pool-ccip-controller-secondary.test.ts +++ b/test/core/ccip/sdl-pool-ccip-controller-secondary.test.ts @@ -77,7 +77,7 @@ describe('SDLPoolCCIPControllerSecondary', () => { await router.applyRampUpdates([[77, onRamp.address]], [], [[77, offRamp.address]]) - let boostController = await deploy('LinearBoostController', [4 * 365 * 86400, 4]) + let boostController = await deploy('LinearBoostController', [10, 4 * 365 * 86400, 4]) sdlPool = (await deployUpgradeable('SDLPoolSecondary', [ 'reSDL', 'reSDL', @@ -430,9 +430,13 @@ describe('SDLPoolCCIPControllerSecondary', () => { it('recoverTokens should work correctly', async () => { await linkToken.transfer(controller.address, toEther(1000)) await sdlToken.transfer(controller.address, toEther(2000)) - await controller.recoverTokens([linkToken.address, sdlToken.address], accounts[3]) + await controller.recoverTokens( + [linkToken.address, sdlToken.address], + [toEther(1000), toEther(2000)], + accounts[3] + ) - assert.equal(fromEther(await linkToken.balanceOf(accounts[3])), 1100) + assert.equal(fromEther(await linkToken.balanceOf(accounts[3])), 1000) assert.equal(fromEther(await sdlToken.balanceOf(accounts[3])), 2000) }) }) diff --git a/test/core/ccip/wrapped-token-bridge.test.ts b/test/core/ccip/wrapped-token-bridge.test.ts index aa9f1976..b5f5a693 100644 --- a/test/core/ccip/wrapped-token-bridge.test.ts +++ b/test/core/ccip/wrapped-token-bridge.test.ts @@ -102,10 +102,10 @@ describe('WrappedTokenBridge', () => { }) it('getFee should work correctly', async () => { - assert.equal(fromEther(await bridge.getFee(77, false)), 2) - assert.equal(fromEther(await bridge.getFee(77, true)), 3) - await expect(bridge.getFee(78, false)).to.be.reverted - await expect(bridge.getFee(78, true)).to.be.reverted + assert.equal(fromEther(await bridge.getFee(77, 1000, false)), 2) + assert.equal(fromEther(await bridge.getFee(77, 1000, true)), 3) + await expect(bridge.getFee(78, 1000, false)).to.be.reverted + await expect(bridge.getFee(78, 1000, true)).to.be.reverted }) it('transferTokens should work correctly with LINK fee', async () => { @@ -272,7 +272,11 @@ describe('WrappedTokenBridge', () => { it('recoverTokens should work correctly', async () => { await linkToken.transfer(bridge.address, toEther(1000)) await stakingPool.transfer(bridge.address, toEther(2000)) - await bridge.recoverTokens([linkToken.address, stakingPool.address], accounts[3]) + await bridge.recoverTokens( + [linkToken.address, stakingPool.address], + [toEther(1000), toEther(2000)], + accounts[3] + ) assert.equal(fromEther(await linkToken.balanceOf(accounts[3])), 1000) assert.equal(fromEther(await stakingPool.balanceOf(accounts[3])), 2000) diff --git a/test/core/sdlPool/linear-boost-controller.test.ts b/test/core/sdlPool/linear-boost-controller.test.ts index 5f58825b..b57c3deb 100644 --- a/test/core/sdlPool/linear-boost-controller.test.ts +++ b/test/core/sdlPool/linear-boost-controller.test.ts @@ -9,6 +9,7 @@ describe('LinearBoostController', () => { beforeEach(async () => { boostController = (await deploy('LinearBoostController', [ + 10, 4 * 365 * DAY, 4, ])) as LinearBoostController @@ -40,7 +41,10 @@ describe('LinearBoostController', () => { assert.equal(fromEther(await boostController.getBoostAmount(toEther(5), 2 * 365 * DAY)), 30) await expect(boostController.getBoostAmount(toEther(5), 2 * 365 * DAY + 1)).to.be.revertedWith( - 'MaxLockingDurationExceeded()' + 'InvalidLockingDuration()' + ) + await expect(boostController.getBoostAmount(toEther(5), 9)).to.be.revertedWith( + 'InvalidLockingDuration()' ) }) }) diff --git a/test/core/sdlPool/sdl-pool-primary.test.ts b/test/core/sdlPool/sdl-pool-primary.test.ts index 45d664b2..bae949f1 100644 --- a/test/core/sdlPool/sdl-pool-primary.test.ts +++ b/test/core/sdlPool/sdl-pool-primary.test.ts @@ -54,6 +54,7 @@ describe('SDLPoolPrimary', () => { await setupToken(sdlToken, accounts) boostController = (await deploy('LinearBoostController', [ + 10, 4 * 365 * DAY, 4, ])) as LinearBoostController @@ -1320,6 +1321,6 @@ describe('SDLPoolPrimary', () => { await expect( sdlPool.connect(signers[1]).transferFrom(accounts[1], accounts[0], 1) - ).to.be.revertedWith('TransferToCCIPController()') + ).to.be.revertedWith('TransferToInvalidAddress()') }) }) diff --git a/test/core/sdlPool/sdl-pool-secondary.test.ts b/test/core/sdlPool/sdl-pool-secondary.test.ts index 4fc4c3f1..74e3b5ef 100644 --- a/test/core/sdlPool/sdl-pool-secondary.test.ts +++ b/test/core/sdlPool/sdl-pool-secondary.test.ts @@ -86,6 +86,7 @@ describe('SDLPoolSecondary', () => { await setupToken(sdlToken, accounts) boostController = (await deploy('LinearBoostController', [ + 10, 4 * 365 * DAY, 4, ])) as LinearBoostController