From 582df14dec236d63aed221d9d96c154a0331bf07 Mon Sep 17 00:00:00 2001 From: RuslanProgrammer Date: Mon, 8 Jan 2024 09:59:33 +0100 Subject: [PATCH 1/6] fixed floating promises in tests --- .eslintrc.json | 6 ++++-- test/Distribution.test.ts | 28 ++++++++++++++-------------- test/L2MessageReceiver.test.ts | 2 +- test/L2TokenReceiver.test.ts | 2 +- test/MOR.test.ts | 2 +- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 446ede9..402a5fb 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,7 +2,8 @@ "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 12, - "sourceType": "module" + "sourceType": "module", + "project": "./tsconfig.json" }, "plugins": ["@typescript-eslint"], "extends": [ @@ -11,7 +12,8 @@ "plugin:prettier/recommended" ], "rules": { - "@typescript-eslint/no-unused-vars": "error" + "@typescript-eslint/no-unused-vars": "error", + "@typescript-eslint/no-floating-promises": "error" }, "env": { "browser": true, diff --git a/test/Distribution.test.ts b/test/Distribution.test.ts index 160cc75..ce8fc31 100644 --- a/test/Distribution.test.ts +++ b/test/Distribution.test.ts @@ -131,7 +131,7 @@ describe('Distribution', () => { const l2MessageReceiverProxy = await ERC1967ProxyFactory.deploy(l2MessageReceiverImplementation, '0x'); l2MessageReceiver = L2MessageReceiver.attach(l2MessageReceiverProxy) as L2MessageReceiver; - l2MessageReceiver.L2MessageReceiver__init(); + await l2MessageReceiver.L2MessageReceiver__init(); const l2TokenReceiverProxy = await ERC1967ProxyFactory.deploy(l2TokenReceiverImplementation, '0x'); l2TokenReceiver = L2TokenReceiver.attach(l2TokenReceiverProxy) as L2TokenReceiver; @@ -164,7 +164,7 @@ describe('Distribution', () => { // Deploy reward token rewardToken = await MORFactory.deploy(wei(1000000000)); - rewardToken.transferOwnership(l2MessageReceiver); + await rewardToken.transferOwnership(l2MessageReceiver); await l2MessageReceiver.setParams(rewardToken, { gateway: lZEndpointMockReceiver, @@ -364,7 +364,7 @@ describe('Distribution', () => { it('should correctly imitate stake and withdraw process', async () => { let userData; - setNextTime(oneHour * 2); + await setNextTime(oneHour * 2); let tx = await distribution.manageUsersInPrivatePool(poolId, [secondAddress, ownerAddress], [wei(1), wei(4)]); await expect(tx).to.emit(distribution, 'UserStaked').withArgs(poolId, secondAddress, wei(1)); await expect(tx).to.emit(distribution, 'UserStaked').withArgs(poolId, ownerAddress, wei(4)); @@ -381,7 +381,7 @@ describe('Distribution', () => { expect(userData.deposited).to.eq(wei(4)); expect(userData.pendingRewards).to.eq(0); - setNextTime(oneHour * 3); + await setNextTime(oneHour * 3); tx = await distribution.manageUsersInPrivatePool(poolId, [secondAddress, ownerAddress], [wei(10), wei(1)]); await expect(tx).to.emit(distribution, 'UserStaked').withArgs(poolId, secondAddress, wei(9)); await expect(tx).to.emit(distribution, 'UserWithdrawn').withArgs(poolId, ownerAddress, wei(3)); @@ -401,7 +401,7 @@ describe('Distribution', () => { it('should correctly calculate and withdraw rewards', async () => { let userData; - setNextTime(oneHour * 2); + await setNextTime(oneHour * 2); await distribution.manageUsersInPrivatePool(poolId, [secondAddress, ownerAddress], [wei(1), wei(4)]); // Claim after 1 day @@ -422,7 +422,7 @@ describe('Distribution', () => { expect(userData.pendingRewards).to.eq(0); // Withdraw after 2 days - setNextTime(oneDay + oneDay * 2); + await setNextTime(oneDay + oneDay * 2); await distribution.manageUsersInPrivatePool(poolId, [secondAddress, ownerAddress], [wei(0), wei(0)]); expect(await depositToken.balanceOf(secondAddress)).to.eq(wei(1000)); @@ -442,11 +442,11 @@ describe('Distribution', () => { it('should correctly calculate rewards after partial stake', async () => { let userData; - setNextTime(oneHour * 2); + await setNextTime(oneHour * 2); await distribution.manageUsersInPrivatePool(poolId, [secondAddress, ownerAddress], [wei(1), wei(4)]); // Stake after 1 day - setNextTime(oneDay + oneDay * 1); + await setNextTime(oneDay + oneDay * 1); await distribution.manageUsersInPrivatePool(poolId, [secondAddress, ownerAddress], [wei(5), wei(5)]); expect(await depositToken.balanceOf(secondAddress)).to.eq(wei(1000)); @@ -502,7 +502,7 @@ describe('Distribution', () => { it('should correctly calculate rewards if change before distribution end and claim after', async () => { let userData; - setNextTime(oneDay + oneDay * 25); + await setNextTime(oneDay + oneDay * 25); await distribution.manageUsersInPrivatePool(poolId, [secondAddress, ownerAddress], [wei(1), wei(4)]); await setNextTime(oneDay * 20000); @@ -541,7 +541,7 @@ describe('Distribution', () => { it('should correctly calculate rewards if change both at and distribution end', async () => { let userData; - setNextTime(oneDay + oneDay * 25); + await setNextTime(oneDay + oneDay * 25); await distribution.manageUsersInPrivatePool(poolId, [secondAddress, ownerAddress], [wei(1), wei(4)]); await setNextTime(oneDay * 20000); @@ -562,7 +562,7 @@ describe('Distribution', () => { it('should correctly work if multiple changes in one block', async () => { let userData; - setNextTime(oneHour * 2); + await setNextTime(oneHour * 2); await ethers.provider.send('evm_setAutomine', [false]); @@ -597,7 +597,7 @@ describe('Distribution', () => { expect(userData.pendingRewards).to.eq(0); // Withdraw after 2 days - setNextTime(oneDay + oneDay * 2); + await setNextTime(oneDay + oneDay * 2); await distribution.manageUsersInPrivatePool(poolId, [secondAddress, ownerAddress], [wei(0), wei(0)]); await distribution.claim(poolId, SECOND, { value: wei(0.5) }); await distribution.claim(poolId, OWNER, { value: wei(0.5) }); @@ -617,7 +617,7 @@ describe('Distribution', () => { it('should do nothing id deposited amount is the same', async () => { let userData; - setNextTime(oneHour * 2); + await setNextTime(oneHour * 2); await distribution.manageUsersInPrivatePool(poolId, [secondAddress, ownerAddress], [wei(1), wei(4)]); expect(await depositToken.balanceOf(secondAddress)).to.eq(wei(1000)); @@ -632,7 +632,7 @@ describe('Distribution', () => { expect(userData.deposited).to.eq(wei(4)); expect(userData.pendingRewards).to.eq(0); - setNextTime(oneHour * 3); + await setNextTime(oneHour * 3); await distribution.manageUsersInPrivatePool(poolId, [secondAddress, ownerAddress], [wei(1), wei(4)]); expect(await depositToken.balanceOf(secondAddress)).to.eq(wei(1000)); diff --git a/test/L2MessageReceiver.test.ts b/test/L2MessageReceiver.test.ts index 524a381..08832dc 100644 --- a/test/L2MessageReceiver.test.ts +++ b/test/L2MessageReceiver.test.ts @@ -40,7 +40,7 @@ describe('L2MessageReceiver', () => { await mor.transferOwnership(l2MessageReceiver); - reverter.snapshot(); + await reverter.snapshot(); }); beforeEach(async () => { diff --git a/test/L2TokenReceiver.test.ts b/test/L2TokenReceiver.test.ts index b7fe7d3..aa49583 100644 --- a/test/L2TokenReceiver.test.ts +++ b/test/L2TokenReceiver.test.ts @@ -63,7 +63,7 @@ describe('L2TokenReceiver', () => { sqrtPriceLimitX96: 0, }); - reverter.snapshot(); + await reverter.snapshot(); }); beforeEach(async () => { diff --git a/test/MOR.test.ts b/test/MOR.test.ts index 8393b99..f3ec9a1 100644 --- a/test/MOR.test.ts +++ b/test/MOR.test.ts @@ -21,7 +21,7 @@ describe('MOR', () => { const MORFactory = await ethers.getContractFactory('MOR'); mor = await MORFactory.deploy(cap); - reverter.snapshot(); + await reverter.snapshot(); }); afterEach(async () => { From e463df79be92cf83c36815537147414ac2c32f65 Mon Sep 17 00:00:00 2001 From: RuslanProgrammer Date: Mon, 8 Jan 2024 10:28:18 +0100 Subject: [PATCH 2/6] fixed 'No Conflicting Inheritance' --- contracts/L2TokenReceiver.sol | 4 ++-- contracts/MOR.sol | 8 ++++---- contracts/interfaces/IL2TokenReceiver.sol | 4 +--- contracts/interfaces/IMOR.sol | 15 +-------------- 4 files changed, 8 insertions(+), 23 deletions(-) diff --git a/contracts/L2TokenReceiver.sol b/contracts/L2TokenReceiver.sol index 441372d..14fdd49 100644 --- a/contracts/L2TokenReceiver.sol +++ b/contracts/L2TokenReceiver.sol @@ -9,7 +9,7 @@ import {TransferHelper} from "@uniswap/v3-periphery/contracts/libraries/Transfer import {ISwapRouter} from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; import {INonfungiblePositionManager} from "./interfaces/uniswap-v3/INonfungiblePositionManager.sol"; -import {IL2TokenReceiver, IERC165} from "./interfaces/IL2TokenReceiver.sol"; +import {IL2TokenReceiver} from "./interfaces/IL2TokenReceiver.sol"; import {IWStETH} from "./interfaces/tokens/IWStETH.sol"; contract L2TokenReceiver is IL2TokenReceiver, ERC165, OwnableUpgradeable, UUPSUpgradeable { @@ -32,7 +32,7 @@ contract L2TokenReceiver is IL2TokenReceiver, ERC165, OwnableUpgradeable, UUPSUp _editParams(params_); } - function supportsInterface(bytes4 interfaceId_) public view override(ERC165, IERC165) returns (bool) { + function supportsInterface(bytes4 interfaceId_) public view override returns (bool) { return interfaceId_ == type(IL2TokenReceiver).interfaceId || super.supportsInterface(interfaceId_); } diff --git a/contracts/MOR.sol b/contracts/MOR.sol index 9cf74d2..b2b76a3 100644 --- a/contracts/MOR.sol +++ b/contracts/MOR.sol @@ -6,19 +6,19 @@ import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC2 import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {IMOR, IERC165, IERC20} from "./interfaces/IMOR.sol"; +import {IMOR, IERC20} from "./interfaces/IMOR.sol"; contract MOR is IMOR, ERC165, ERC20Capped, ERC20Burnable, Ownable { constructor(uint256 cap_) ERC20("MOR", "MOR") ERC20Capped(cap_) {} - function supportsInterface(bytes4 interfaceId_) public view override(ERC165, IERC165) returns (bool) { + function supportsInterface(bytes4 interfaceId_) public view override returns (bool) { return interfaceId_ == type(IMOR).interfaceId || interfaceId_ == type(IERC20).interfaceId || super.supportsInterface(interfaceId_); } - function cap() public view override(IMOR, ERC20Capped) returns (uint256) { + function cap() public view override returns (uint256) { return ERC20Capped.cap(); } @@ -26,7 +26,7 @@ contract MOR is IMOR, ERC165, ERC20Capped, ERC20Burnable, Ownable { _mint(account_, amount_); } - function burn(uint256 amount_) public override(IMOR, ERC20Burnable) { + function burn(uint256 amount_) public override { ERC20Burnable.burn(amount_); } diff --git a/contracts/interfaces/IL2TokenReceiver.sol b/contracts/interfaces/IL2TokenReceiver.sol index 8bad575..9621c62 100644 --- a/contracts/interfaces/IL2TokenReceiver.sol +++ b/contracts/interfaces/IL2TokenReceiver.sol @@ -1,12 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; - /** * This is Swap contract that swaps tokens using Uniswap V3. */ -interface IL2TokenReceiver is IERC165 { +interface IL2TokenReceiver { /** * The structure that stores the swap params. * @param tokenIn The address of the token to swap from. diff --git a/contracts/interfaces/IMOR.sol b/contracts/interfaces/IMOR.sol index df58b22..42ebd33 100644 --- a/contracts/interfaces/IMOR.sol +++ b/contracts/interfaces/IMOR.sol @@ -2,28 +2,15 @@ pragma solidity ^0.8.20; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; /** * This is the MOR token contract. The token is ERC20 with cap and burnable features. */ -interface IMOR is IERC20, IERC165 { - /** - * The function to get the cap of the token. - * @return The cap of the token. - */ - function cap() external view returns (uint256); - +interface IMOR is IERC20 { /** * The function to mint tokens. * @param account_ The address of the account to mint tokens to. * @param amount_ The amount of tokens to mint. */ function mint(address account_, uint256 amount_) external; - - /** - * The function to burn tokens. - * @param amount_ The amount of tokens to burn. - */ - function burn(uint256 amount_) external; } From bcd58ed07823d5ee98bc8009329f280736a91ee7 Mon Sep 17 00:00:00 2001 From: RuslanProgrammer Date: Mon, 8 Jan 2024 10:31:18 +0100 Subject: [PATCH 3/6] fixed 'unnecessarily permissive visibility' --- contracts/libs/LinearDistributionIntervalDecrease.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/libs/LinearDistributionIntervalDecrease.sol b/contracts/libs/LinearDistributionIntervalDecrease.sol index 9ca9eba..9e559d2 100644 --- a/contracts/libs/LinearDistributionIntervalDecrease.sol +++ b/contracts/libs/LinearDistributionIntervalDecrease.sol @@ -23,7 +23,7 @@ library LinearDistributionIntervalDecrease { uint128 interval_, uint128 startTime_, uint128 endTime_ - ) public pure returns (uint256) { + ) external pure returns (uint256) { if (interval_ == 0) { return 0; } From bd813f2db600d89283215d44fb8f814e65d5cb47 Mon Sep 17 00:00:00 2001 From: RuslanProgrammer Date: Mon, 8 Jan 2024 10:44:09 +0100 Subject: [PATCH 4/6] fixed tests --- contracts/MOR.sol | 2 +- contracts/interfaces/IMOR.sol | 6 ++++++ test/MOR.test.ts | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/contracts/MOR.sol b/contracts/MOR.sol index b2b76a3..797abfb 100644 --- a/contracts/MOR.sol +++ b/contracts/MOR.sol @@ -18,7 +18,7 @@ contract MOR is IMOR, ERC165, ERC20Capped, ERC20Burnable, Ownable { super.supportsInterface(interfaceId_); } - function cap() public view override returns (uint256) { + function cap() public view override(IMOR, ERC20Capped) returns (uint256) { return ERC20Capped.cap(); } diff --git a/contracts/interfaces/IMOR.sol b/contracts/interfaces/IMOR.sol index 42ebd33..52c19df 100644 --- a/contracts/interfaces/IMOR.sol +++ b/contracts/interfaces/IMOR.sol @@ -7,6 +7,12 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; * This is the MOR token contract. The token is ERC20 with cap and burnable features. */ interface IMOR is IERC20 { + /** + * The function to get the cap of the token. + * @return The cap of the token. + */ + function cap() external view returns (uint256); + /** * The function to mint tokens. * @param account_ The address of the account to mint tokens to. diff --git a/test/MOR.test.ts b/test/MOR.test.ts index f3ec9a1..8332709 100644 --- a/test/MOR.test.ts +++ b/test/MOR.test.ts @@ -41,7 +41,7 @@ describe('MOR', () => { describe('supportsInterface', () => { it('should support IMOR', async () => { - expect(await mor.supportsInterface('0x3705179b')).to.be.true; + expect(await mor.supportsInterface('0x75937bf3')).to.be.true; }); it('should support IERC20', async () => { expect(await mor.supportsInterface('0x36372b07')).to.be.true; From cb9e5a47fbef25ecdf12a6ac2212d7820968f8b4 Mon Sep 17 00:00:00 2001 From: RuslanProgrammer Date: Tue, 9 Jan 2024 20:15:43 +0100 Subject: [PATCH 5/6] fixed multiple issues --- contracts/Distribution.sol | 39 +++++++++++------------ contracts/L1Sender.sol | 8 ++--- contracts/L2MessageReceiver.sol | 2 -- contracts/L2TokenReceiver.sol | 22 ++++++------- contracts/MOR.sol | 13 ++++---- contracts/interfaces/IL2TokenReceiver.sol | 4 ++- contracts/interfaces/IMOR.sol | 3 +- contracts/mock/SwapRouterMock.sol | 2 +- contracts/mock/tokens/StETHMock.sol | 3 -- test/Distribution.test.ts | 2 +- 10 files changed, 45 insertions(+), 53 deletions(-) diff --git a/contracts/Distribution.sol b/contracts/Distribution.sol index d82910f..cbf1245 100644 --- a/contracts/Distribution.sol +++ b/contracts/Distribution.sol @@ -1,16 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; + import {PRECISION} from "@solarity/solidity-lib/utils/Globals.sol"; import {LinearDistributionIntervalDecrease} from "./libs/LinearDistributionIntervalDecrease.sol"; -import {IDistribution} from "./interfaces/IDistribution.sol"; -import {IMOR} from "./interfaces/IMOR.sol"; import {L1Sender} from "./L1Sender.sol"; +import {IDistribution} from "./interfaces/IDistribution.sol"; contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable { using SafeERC20 for IERC20; @@ -54,7 +54,7 @@ contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable { __Ownable_init(); __UUPSUpgradeable_init(); - for (uint256 i = 0; i < poolsInfo_.length; i++) { + for (uint256 i; i < poolsInfo_.length; ++i) { createPool(poolsInfo_[i]); } @@ -108,7 +108,7 @@ contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable { ); } - function _validatePool(Pool calldata pool_) internal pure { + function _validatePool(Pool calldata pool_) private pure { if (pool_.rewardDecrease > 0) { require(pool_.decreaseInterval > 0, "DS: invalid reward decrease"); } @@ -127,7 +127,7 @@ contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable { uint256 currentPoolRate_ = _getCurrentPoolRate(poolId_); - for (uint256 i = 0; i < users_.length; i++) { + for (uint256 i; i < users_.length; ++i) { address user_ = users_[i]; uint256 amount_ = amounts_[i]; @@ -188,7 +188,7 @@ contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable { return _getCurrentUserReward(currentPoolRate_, userData); } - function _stake(address user_, uint256 poolId_, uint256 amount_, uint256 currentPoolRate_) internal { + function _stake(address user_, uint256 poolId_, uint256 amount_, uint256 currentPoolRate_) private { require(amount_ > 0, "DS: nothing to stake"); Pool storage pool = pools[poolId_]; @@ -222,7 +222,7 @@ contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable { emit UserStaked(poolId_, user_, amount_); } - function _withdraw(address user_, uint256 poolId_, uint256 amount_, uint256 currentPoolRate_) internal { + function _withdraw(address user_, uint256 poolId_, uint256 amount_, uint256 currentPoolRate_) private { Pool storage pool = pools[poolId_]; PoolData storage poolData = poolsData[poolId_]; UserData storage userData = usersData[user_][poolId_]; @@ -248,10 +248,8 @@ contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable { newDeposited_ = deposited_ - amount_; - require( - amount_ > 0 && (newDeposited_ >= pool.minimalStake || newDeposited_ == 0), - "DS: invalid withdraw amount" - ); + require(amount_ > 0, "DS: nothing to withdraw"); + require(newDeposited_ >= pool.minimalStake || newDeposited_ == 0, "DS: invalid withdraw amount"); } else { newDeposited_ = deposited_ - amount_; } @@ -277,16 +275,13 @@ contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable { emit UserWithdrawn(poolId_, user_, amount_); } - function _getCurrentUserReward( - uint256 currentPoolRate_, - UserData memory userData_ - ) internal pure returns (uint256) { + function _getCurrentUserReward(uint256 currentPoolRate_, UserData memory userData_) private pure returns (uint256) { uint256 newRewards_ = ((currentPoolRate_ - userData_.rate) * userData_.deposited) / PRECISION; return userData_.pendingRewards + newRewards_; } - function _getCurrentPoolRate(uint256 poolId_) internal view returns (uint256) { + function _getCurrentPoolRate(uint256 poolId_) private view returns (uint256) { PoolData storage poolData = poolsData[poolId_]; if (poolData.totalDeposited == 0) { @@ -298,7 +293,7 @@ contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable { return poolData.rate + (rewards_ * PRECISION) / poolData.totalDeposited; } - function _poolExists(uint256 poolId_) internal view returns (bool) { + function _poolExists(uint256 poolId_) private view returns (bool) { return poolId_ < pools.length; } @@ -319,19 +314,21 @@ contract Distribution is IDistribution, OwnableUpgradeable, UUPSUpgradeable { uint256 gasLimit_, uint256 maxFeePerGas_, uint256 maxSubmissionCost_ - ) external payable onlyOwner returns (bytes memory bridgeMessageId_) { + ) external payable onlyOwner returns (bytes memory) { uint256 overplus_ = overplus(); require(overplus_ > 0, "DS: overplus is zero"); IERC20(depositToken).safeTransfer(l1Sender, overplus_); - bridgeMessageId_ = L1Sender(l1Sender).sendDepositToken{value: msg.value}( + bytes memory bridgeMessageId_ = L1Sender(l1Sender).sendDepositToken{value: msg.value}( gasLimit_, maxFeePerGas_, maxSubmissionCost_ ); emit OverplusBridged(overplus_, bridgeMessageId_); + + return bridgeMessageId_; } /**********************************************************************************************/ diff --git a/contracts/L1Sender.sol b/contracts/L1Sender.sol index a10fe12..deea6cd 100644 --- a/contracts/L1Sender.sol +++ b/contracts/L1Sender.sol @@ -5,15 +5,13 @@ import {ILayerZeroEndpoint} from "@layerzerolabs/lz-evm-sdk-v1-0.7/contracts/int import {IGatewayRouter} from "@arbitrum/token-bridge-contracts/contracts/tokenbridge/libraries/gateway/IGatewayRouter.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {IWStETH} from "./interfaces/tokens/IWStETH.sol"; -import {IStETH} from "./interfaces/tokens/IStETH.sol"; -import {IMOR} from "./interfaces/IMOR.sol"; import {IL1Sender} from "./interfaces/IL1Sender.sol"; +import {IWStETH} from "./interfaces/tokens/IWStETH.sol"; contract L1Sender is IL1Sender, ERC165, OwnableUpgradeable, UUPSUpgradeable { address public unwrappedDepositToken; diff --git a/contracts/L2MessageReceiver.sol b/contracts/L2MessageReceiver.sol index 8ad113c..9cbafeb 100644 --- a/contracts/L2MessageReceiver.sol +++ b/contracts/L2MessageReceiver.sol @@ -3,12 +3,10 @@ pragma solidity ^0.8.20; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {ILayerZeroReceiver} from "@layerzerolabs/lz-evm-sdk-v1-0.7/contracts/interfaces/ILayerZeroReceiver.sol"; import {IMOR} from "./interfaces/IMOR.sol"; -import {IL1Sender} from "./interfaces/IL1Sender.sol"; import {IL2MessageReceiver} from "./interfaces/IL2MessageReceiver.sol"; contract L2MessageReceiver is ILayerZeroReceiver, IL2MessageReceiver, OwnableUpgradeable, UUPSUpgradeable { diff --git a/contracts/L2TokenReceiver.sol b/contracts/L2TokenReceiver.sol index 14fdd49..3ad6bff 100644 --- a/contracts/L2TokenReceiver.sol +++ b/contracts/L2TokenReceiver.sol @@ -3,16 +3,14 @@ pragma solidity ^0.8.20; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; -import {TransferHelper} from "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol"; import {ISwapRouter} from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; +import {TransferHelper} from "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol"; +import {IL2TokenReceiver, IERC165} from "./interfaces/IL2TokenReceiver.sol"; import {INonfungiblePositionManager} from "./interfaces/uniswap-v3/INonfungiblePositionManager.sol"; -import {IL2TokenReceiver} from "./interfaces/IL2TokenReceiver.sol"; -import {IWStETH} from "./interfaces/tokens/IWStETH.sol"; -contract L2TokenReceiver is IL2TokenReceiver, ERC165, OwnableUpgradeable, UUPSUpgradeable { +contract L2TokenReceiver is IL2TokenReceiver, OwnableUpgradeable, UUPSUpgradeable { address public router; address public nonfungiblePositionManager; @@ -32,11 +30,11 @@ contract L2TokenReceiver is IL2TokenReceiver, ERC165, OwnableUpgradeable, UUPSUp _editParams(params_); } - function supportsInterface(bytes4 interfaceId_) public view override returns (bool) { - return interfaceId_ == type(IL2TokenReceiver).interfaceId || super.supportsInterface(interfaceId_); + function supportsInterface(bytes4 interfaceId_) external pure returns (bool) { + return interfaceId_ == type(IL2TokenReceiver).interfaceId || interfaceId_ == type(IERC165).interfaceId; } - function editParams(SwapParams memory newParams_) public onlyOwner { + function editParams(SwapParams memory newParams_) external onlyOwner { if (params.tokenIn != newParams_.tokenIn) { TransferHelper.safeApprove(params.tokenIn, router, 0); TransferHelper.safeApprove(params.tokenIn, nonfungiblePositionManager, 0); @@ -49,7 +47,7 @@ contract L2TokenReceiver is IL2TokenReceiver, ERC165, OwnableUpgradeable, UUPSUp _editParams(newParams_); } - function swap(uint256 amountIn_, uint256 amountOutMinimum_) external onlyOwner returns (uint256 amountOut_) { + function swap(uint256 amountIn_, uint256 amountOutMinimum_) external onlyOwner returns (uint256) { SwapParams memory params_ = params; ISwapRouter.ExactInputSingleParams memory swapParams_ = ISwapRouter.ExactInputSingleParams({ @@ -63,9 +61,11 @@ contract L2TokenReceiver is IL2TokenReceiver, ERC165, OwnableUpgradeable, UUPSUp sqrtPriceLimitX96: params_.sqrtPriceLimitX96 }); - amountOut_ = ISwapRouter(router).exactInputSingle(swapParams_); + uint256 amountOut_ = ISwapRouter(router).exactInputSingle(swapParams_); emit TokensSwapped(params_.tokenIn, params_.tokenOut, amountIn_, amountOut_, amountOutMinimum_); + + return amountOut_; } function increaseLiquidityCurrentRange( @@ -112,7 +112,7 @@ contract L2TokenReceiver is IL2TokenReceiver, ERC165, OwnableUpgradeable, UUPSUp emit LiquidityIncreased(tokenId_, amount0_, amount1_, liquidity_, amountMin0_, amountMin1_); } - function _editParams(SwapParams memory newParams_) internal { + function _editParams(SwapParams memory newParams_) private { require(newParams_.tokenIn != address(0), "L2TR: invalid tokenIn"); require(newParams_.tokenOut != address(0), "L2TR: invalid tokenOut"); diff --git a/contracts/MOR.sol b/contracts/MOR.sol index 797abfb..9110c9f 100644 --- a/contracts/MOR.sol +++ b/contracts/MOR.sol @@ -1,21 +1,20 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {ERC20, ERC20Capped} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol"; -import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; -import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import {ERC20, ERC20Capped} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol"; -import {IMOR, IERC20} from "./interfaces/IMOR.sol"; +import {IMOR, IERC20, IERC165} from "./interfaces/IMOR.sol"; -contract MOR is IMOR, ERC165, ERC20Capped, ERC20Burnable, Ownable { +contract MOR is IMOR, ERC20Capped, ERC20Burnable, Ownable { constructor(uint256 cap_) ERC20("MOR", "MOR") ERC20Capped(cap_) {} - function supportsInterface(bytes4 interfaceId_) public view override returns (bool) { + function supportsInterface(bytes4 interfaceId_) external pure returns (bool) { return interfaceId_ == type(IMOR).interfaceId || interfaceId_ == type(IERC20).interfaceId || - super.supportsInterface(interfaceId_); + interfaceId_ == type(IERC165).interfaceId; } function cap() public view override(IMOR, ERC20Capped) returns (uint256) { diff --git a/contracts/interfaces/IL2TokenReceiver.sol b/contracts/interfaces/IL2TokenReceiver.sol index 9621c62..341c0f9 100644 --- a/contracts/interfaces/IL2TokenReceiver.sol +++ b/contracts/interfaces/IL2TokenReceiver.sol @@ -1,10 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + /** * This is Swap contract that swaps tokens using Uniswap V3. */ -interface IL2TokenReceiver { +interface IL2TokenReceiver is IERC165 { /** * The structure that stores the swap params. * @param tokenIn The address of the token to swap from. diff --git a/contracts/interfaces/IMOR.sol b/contracts/interfaces/IMOR.sol index 52c19df..49f138e 100644 --- a/contracts/interfaces/IMOR.sol +++ b/contracts/interfaces/IMOR.sol @@ -2,11 +2,12 @@ pragma solidity ^0.8.20; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * This is the MOR token contract. The token is ERC20 with cap and burnable features. */ -interface IMOR is IERC20 { +interface IMOR is IERC20, IERC165 { /** * The function to get the cap of the token. * @return The cap of the token. diff --git a/contracts/mock/SwapRouterMock.sol b/contracts/mock/SwapRouterMock.sol index e474461..b5d11fd 100644 --- a/contracts/mock/SwapRouterMock.sol +++ b/contracts/mock/SwapRouterMock.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; import {ISwapRouter} from "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol"; -import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract SwapRouterMock { function exactInputSingle(ISwapRouter.ExactInputSingleParams calldata params_) external returns (uint256) { diff --git a/contracts/mock/tokens/StETHMock.sol b/contracts/mock/tokens/StETHMock.sol index 8a2b992..bfb7f7d 100644 --- a/contracts/mock/tokens/StETHMock.sol +++ b/contracts/mock/tokens/StETHMock.sol @@ -1,12 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {PRECISION} from "@solarity/solidity-lib/utils/Globals.sol"; -import {IStETH} from "../../interfaces/tokens/IStETH.sol"; - contract StETHMock is ERC20 { uint256 public totalPooledEther = PRECISION; diff --git a/test/Distribution.test.ts b/test/Distribution.test.ts index ce8fc31..fcc63ec 100644 --- a/test/Distribution.test.ts +++ b/test/Distribution.test.ts @@ -1340,7 +1340,7 @@ describe('Distribution', () => { await distribution.withdraw(poolId, wei(10)); - await expect(distribution.withdraw(poolId, 0)).to.be.revertedWith('DS: invalid withdraw amount'); + await expect(distribution.withdraw(poolId, 0)).to.be.revertedWith('DS: nothing to withdraw'); }); it("should revert if user didn't stake", async () => { await expect(distribution.withdraw(poolId, 1)).to.be.revertedWith("DS: user isn't staked"); From 5ac3db9942bda597c9e7b991017c9e4d98cde472 Mon Sep 17 00:00:00 2001 From: RuslanProgrammer Date: Wed, 10 Jan 2024 12:22:04 +0100 Subject: [PATCH 6/6] added mainnet config --- deploy/data/config.json | 20 ++++++++++++++-- deploy/data/config_localhost.json | 38 +++++++++++++++++++++++++++++++ deploy/helpers/config-parser.ts | 2 ++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 deploy/data/config_localhost.json diff --git a/deploy/data/config.json b/deploy/data/config.json index 54aca13..d9f2514 100644 --- a/deploy/data/config.json +++ b/deploy/data/config.json @@ -1,8 +1,8 @@ { "cap": "1000000000000000000000000", "chainsConfig": { - "senderChainId": 10121, - "receiverChainId": 10143 + "senderChainId": 101, + "receiverChainId": 110 }, "pools": [ { @@ -31,8 +31,24 @@ "amounts": ["1", "1"] } ], + "L1": { + "stEth": "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84", + "wStEth": "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0" + }, + "L2": { + "swapRouter": "0xE592427A0AEce92De3Edee1F18E0157C05861564", + "nonfungiblePositionManager": "0xC36442b4a4522E871399CD717aBDD847Ab11FE88", + "wStEth": "0x5979D7b546E38E414F7E9822514be443A4800529" + }, "swapParams": { "fee": 10000, "sqrtPriceLimitX96": 0 + }, + "arbitrumConfig": { + "arbitrumBridgeGatewayRouter": "0x72Ce9c846789fdB6fC1f34aC4AD25Dd9ef7031ef" + }, + "lzConfig": { + "lzEndpointL1": "0x66A71Dcef29A0fFBDBE3c6a460a3B5BC225Cd675", + "lzEndpointL2": "0x3c2269811836af69497E5F486A85D7316753cf62" } } diff --git a/deploy/data/config_localhost.json b/deploy/data/config_localhost.json new file mode 100644 index 0000000..54aca13 --- /dev/null +++ b/deploy/data/config_localhost.json @@ -0,0 +1,38 @@ +{ + "cap": "1000000000000000000000000", + "chainsConfig": { + "senderChainId": 10121, + "receiverChainId": 10143 + }, + "pools": [ + { + "payoutStart": 1765790236, + "decreaseInterval": 86400, + "withdrawLockPeriod": 120, + "claimLockPeriod": 60, + "initialReward": "14400000000000000000000", + "rewardDecrease": "2468994701000000000", + "minimalStake": "1000000000000000", + "isPublic": true + }, + { + "payoutStart": 1765790236, + "decreaseInterval": 60, + "withdrawLockPeriod": 1, + "claimLockPeriod": 1, + "initialReward": "100000000000000000000", + "rewardDecrease": "100000000000000000000", + "minimalStake": "1000000000000000", + "isPublic": false, + "whitelistedUsers": [ + "0x901F2d23823730fb7F2356920e0E273EFdCdFe17", + "0x19ec1E4b714990620edf41fE28e9a1552953a7F4" + ], + "amounts": ["1", "1"] + } + ], + "swapParams": { + "fee": 10000, + "sqrtPriceLimitX96": 0 + } +} diff --git a/deploy/helpers/config-parser.ts b/deploy/helpers/config-parser.ts index db73884..e7b6636 100644 --- a/deploy/helpers/config-parser.ts +++ b/deploy/helpers/config-parser.ts @@ -42,6 +42,8 @@ export function parseConfig(chainId: bigint): Config { let configPath: string; if (chainId === 31337n) { + configPath = `deploy/data/config_localhost.json`; + } else if (chainId === 1n || chainId === 42161n) { configPath = `deploy/data/config.json`; } else if (chainId === 5n || chainId === 421613n) { configPath = `deploy/data/config_goerli.json`;