From efb1c275fd01d86b089e712a576bbcd9705bb73d Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 24 Jun 2024 13:19:27 +0100 Subject: [PATCH 1/6] Add blacklist --- contracts/helpers/Blacklist.sol | 18 ++++++++++++++++++ test/Blacklist.js | 25 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 contracts/helpers/Blacklist.sol create mode 100644 test/Blacklist.js diff --git a/contracts/helpers/Blacklist.sol b/contracts/helpers/Blacklist.sol new file mode 100644 index 00000000..cba2a79c --- /dev/null +++ b/contracts/helpers/Blacklist.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.23; + +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract Blacklist is Ownable { + mapping(address => bool) public blacklisted; + + constructor(address owner) Ownable(owner) {} + + event BlacklistAddress(address pool, bool isBlacklisted); + + function toggleBlacklistAddress(address pool) external onlyOwner { + blacklisted[pool] = !blacklisted[pool]; + emit BlacklistAddress(pool, blacklisted[pool]); + } +} diff --git a/test/Blacklist.js b/test/Blacklist.js new file mode 100644 index 00000000..0e3a09ab --- /dev/null +++ b/test/Blacklist.js @@ -0,0 +1,25 @@ +const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); +const { ethers } = require('hardhat'); +const { expect, deployContract } = require('@1inch/solidity-utils'); +const { tokens } = require('./helpers.js'); + +describe('Blacklist', function () { + async function initContracts () { + const [owner, alice] = await ethers.getSigners(); + const blacklist = await deployContract('Blacklist', [owner]); + return { owner, alice, blacklist }; + } + + it('should revert by non-owner', async function () { + const { alice, blacklist } = await loadFixture(initContracts); + await expect(blacklist.connect(alice).toggleBlacklistAddress(tokens.ETH)).to.be.revertedWithCustomError(blacklist, 'OwnableUnauthorizedAccount'); + }); + + it('should togle record state', async function () { + const { owner, blacklist } = await loadFixture(initContracts); + await blacklist.connect(owner).toggleBlacklistAddress(tokens.ETH); + expect(await blacklist.blacklisted(tokens.ETH)).to.be.true; + await blacklist.connect(owner).toggleBlacklistAddress(tokens.ETH); + expect(await blacklist.blacklisted(tokens.ETH)).to.be.false; + }); +}); From 6bcb0f86e9356d6eaa45d876fbceb639c5d7aa4c Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 24 Jun 2024 13:20:04 +0100 Subject: [PATCH 2/6] Integrate blacklist to CurveOracle --- contracts/oracles/CurveOracle.sol | 9 +++++++-- test/oracles/CurveOracle.js | 8 ++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/contracts/oracles/CurveOracle.sol b/contracts/oracles/CurveOracle.sol index beb82660..c3fc14d1 100644 --- a/contracts/oracles/CurveOracle.sol +++ b/contracts/oracles/CurveOracle.sol @@ -9,8 +9,9 @@ import "../interfaces/ICurveProvider.sol"; import "../interfaces/ICurveRegistry.sol"; import "../interfaces/ICurveSwap.sol"; import "../libraries/OraclePrices.sol"; +import "../helpers/Blacklist.sol"; -contract CurveOracle is IOracle { +contract CurveOracle is IOracle, Blacklist { using OraclePrices for OraclePrices.Data; using Math for uint256; @@ -40,7 +41,7 @@ contract CurveOracle is IOracle { ICurveRegistry[11] public registries; CurveRegistryType[11] public registryTypes; - constructor(ICurveProvider _addressProvider, uint256 _maxPools, uint256[] memory _registryIds, CurveRegistryType[] memory _registryTypes) { + constructor(ICurveProvider _addressProvider, uint256 _maxPools, uint256[] memory _registryIds, CurveRegistryType[] memory _registryTypes, address owner) Blacklist(owner) { MAX_POOLS = _maxPools; REGISTRIES_COUNT = _registryIds.length; unchecked { @@ -61,6 +62,10 @@ contract CurveOracle is IOracle { uint256 registryIndex = 0; address pool = registries[i].find_pool_for_coins(address(srcToken), address(dstToken), registryIndex); while (pool != address(0) && index < MAX_POOLS) { + if (blacklisted[pool]) { + pool = registries[i].find_pool_for_coins(address(srcToken), address(dstToken), ++registryIndex); + continue; + } index++; // call `get_coin_indices` and set (srcTokenIndex, dstTokenIndex, isUnderlying) variables bool isUnderlying; diff --git a/test/oracles/CurveOracle.js b/test/oracles/CurveOracle.js index e67cf766..9ff34b80 100644 --- a/test/oracles/CurveOracle.js +++ b/test/oracles/CurveOracle.js @@ -1,6 +1,6 @@ const { loadFixture } = require('@nomicfoundation/hardhat-network-helpers'); const { ethers } = require('hardhat'); -const { expect, deployContract } = require('@1inch/solidity-utils'); +const { expect, deployContract, constants } = require('@1inch/solidity-utils'); const { tokens, deployParams: { AaveWrapperV2, Curve, Uniswap, UniswapV2, UniswapV3 }, @@ -12,7 +12,7 @@ const { describe('CurveOracle', function () { async function initContracts () { - const curveOracle = await deployContract('CurveOracle', [Curve.provider, Curve.maxPools, Curve.registryIds, Curve.registryTypes]); + const curveOracle = await deployContract('CurveOracle', [Curve.provider, Curve.maxPools, Curve.registryIds, Curve.registryTypes, constants.EEE_ADDRESS]); const uniswapV3Oracle = await deployContract('UniswapV3LikeOracle', [UniswapV3.factory, UniswapV3.initcodeHash, UniswapV3.fees]); return { curveOracle, uniswapV3Oracle }; } @@ -107,7 +107,7 @@ describe('CurveOracle', function () { }, ]; - const curveOracle = await deployContract('CurveOracle', [Curve.provider, Curve.maxPools, [Curve.registryIds[registryIndex]], [Curve.registryTypes[registryIndex]]]); + const curveOracle = await deployContract('CurveOracle', [Curve.provider, Curve.maxPools, [Curve.registryIds[registryIndex]], [Curve.registryTypes[registryIndex]], constants.EEE_ADDRESS]); const curveProvider = await ethers.getContractAt('ICurveProvider', Curve.provider); const registryAddress = await curveProvider.get_address(Curve.registryIds[registryIndex]); const registry = await ethers.getContractAt('ICurveRegistry', registryAddress); @@ -141,7 +141,7 @@ describe('CurveOracle', function () { const [deployer] = await ethers.getSigners(); const uniswapV2LikeOracle = await deployContract('UniswapV2LikeOracle', [UniswapV2.factory, UniswapV2.initcodeHash]); - const curveOracle = await deployContract('CurveOracle', [Curve.provider, Curve.maxPools, Curve.registryIds, Curve.registryTypes]); + const curveOracle = await deployContract('CurveOracle', [Curve.provider, Curve.maxPools, Curve.registryIds, Curve.registryTypes, constants.EEE_ADDRESS]); const uniswapOracle = await deployContract('UniswapOracle', [Uniswap.factory]); const mooniswapOracle = await deployContract('MooniswapOracle', [tokens.oneInchLP1]); const wethWrapper = await deployContract('BaseCoinWrapper', [tokens.ETH, tokens.WETH]); From 3fbb6ce465f9a21351351d2dd1680d226bed97f3 Mon Sep 17 00:00:00 2001 From: zZoMROT Date: Mon, 24 Jun 2024 14:38:03 +0100 Subject: [PATCH 3/6] Update test/Blacklist.js Co-authored-by: Xenia <94478708+byshape@users.noreply.github.com> --- test/Blacklist.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Blacklist.js b/test/Blacklist.js index 0e3a09ab..fb2c30c1 100644 --- a/test/Blacklist.js +++ b/test/Blacklist.js @@ -15,7 +15,7 @@ describe('Blacklist', function () { await expect(blacklist.connect(alice).toggleBlacklistAddress(tokens.ETH)).to.be.revertedWithCustomError(blacklist, 'OwnableUnauthorizedAccount'); }); - it('should togle record state', async function () { + it('should toggle record state', async function () { const { owner, blacklist } = await loadFixture(initContracts); await blacklist.connect(owner).toggleBlacklistAddress(tokens.ETH); expect(await blacklist.blacklisted(tokens.ETH)).to.be.true; From 325814e605eeb6b17a16be778cd1d93ae5855123 Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 24 Jun 2024 14:39:49 +0100 Subject: [PATCH 4/6] Rename event --- contracts/helpers/Blacklist.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/helpers/Blacklist.sol b/contracts/helpers/Blacklist.sol index cba2a79c..84c44627 100644 --- a/contracts/helpers/Blacklist.sol +++ b/contracts/helpers/Blacklist.sol @@ -9,10 +9,10 @@ contract Blacklist is Ownable { constructor(address owner) Ownable(owner) {} - event BlacklistAddress(address pool, bool isBlacklisted); + event BlacklistUpdated(address pool, bool isBlacklisted); function toggleBlacklistAddress(address pool) external onlyOwner { blacklisted[pool] = !blacklisted[pool]; - emit BlacklistAddress(pool, blacklisted[pool]); + emit BlacklistUpdated(pool, blacklisted[pool]); } } From 2e892029695b31a721359e5e76a0f565d71286cf Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 24 Jun 2024 20:06:02 +0100 Subject: [PATCH 5/6] Add init blacklist --- contracts/helpers/Blacklist.sol | 10 +++++++--- contracts/oracles/CurveOracle.sol | 9 ++++++++- test/Blacklist.js | 2 +- test/oracles/CurveOracle.js | 8 +++++--- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/contracts/helpers/Blacklist.sol b/contracts/helpers/Blacklist.sol index 84c44627..83af413e 100644 --- a/contracts/helpers/Blacklist.sol +++ b/contracts/helpers/Blacklist.sol @@ -5,11 +5,15 @@ pragma solidity 0.8.23; import "@openzeppelin/contracts/access/Ownable.sol"; contract Blacklist is Ownable { - mapping(address => bool) public blacklisted; + event BlacklistUpdated(address pool, bool isBlacklisted); - constructor(address owner) Ownable(owner) {} + mapping(address => bool) public blacklisted; - event BlacklistUpdated(address pool, bool isBlacklisted); + constructor(address[] memory initialBlacklist, address owner) Ownable(owner) { + for (uint256 i = 0; i < initialBlacklist.length; i++) { + blacklisted[initialBlacklist[i]] = true; + } + } function toggleBlacklistAddress(address pool) external onlyOwner { blacklisted[pool] = !blacklisted[pool]; diff --git a/contracts/oracles/CurveOracle.sol b/contracts/oracles/CurveOracle.sol index c3fc14d1..ce0759ec 100644 --- a/contracts/oracles/CurveOracle.sol +++ b/contracts/oracles/CurveOracle.sol @@ -41,7 +41,14 @@ contract CurveOracle is IOracle, Blacklist { ICurveRegistry[11] public registries; CurveRegistryType[11] public registryTypes; - constructor(ICurveProvider _addressProvider, uint256 _maxPools, uint256[] memory _registryIds, CurveRegistryType[] memory _registryTypes, address owner) Blacklist(owner) { + constructor( + ICurveProvider _addressProvider, + uint256 _maxPools, + uint256[] memory _registryIds, + CurveRegistryType[] memory _registryTypes, + address[] memory initialBlacklist, + address owner + ) Blacklist(initialBlacklist, owner) { MAX_POOLS = _maxPools; REGISTRIES_COUNT = _registryIds.length; unchecked { diff --git a/test/Blacklist.js b/test/Blacklist.js index fb2c30c1..14347bf2 100644 --- a/test/Blacklist.js +++ b/test/Blacklist.js @@ -6,7 +6,7 @@ const { tokens } = require('./helpers.js'); describe('Blacklist', function () { async function initContracts () { const [owner, alice] = await ethers.getSigners(); - const blacklist = await deployContract('Blacklist', [owner]); + const blacklist = await deployContract('Blacklist', [[], owner]); return { owner, alice, blacklist }; } diff --git a/test/oracles/CurveOracle.js b/test/oracles/CurveOracle.js index 9ff34b80..99299e37 100644 --- a/test/oracles/CurveOracle.js +++ b/test/oracles/CurveOracle.js @@ -12,7 +12,7 @@ const { describe('CurveOracle', function () { async function initContracts () { - const curveOracle = await deployContract('CurveOracle', [Curve.provider, Curve.maxPools, Curve.registryIds, Curve.registryTypes, constants.EEE_ADDRESS]); + const curveOracle = await deployContract('CurveOracle', [Curve.provider, Curve.maxPools, Curve.registryIds, Curve.registryTypes, [], constants.EEE_ADDRESS]); const uniswapV3Oracle = await deployContract('UniswapV3LikeOracle', [UniswapV3.factory, UniswapV3.initcodeHash, UniswapV3.fees]); return { curveOracle, uniswapV3Oracle }; } @@ -107,7 +107,9 @@ describe('CurveOracle', function () { }, ]; - const curveOracle = await deployContract('CurveOracle', [Curve.provider, Curve.maxPools, [Curve.registryIds[registryIndex]], [Curve.registryTypes[registryIndex]], constants.EEE_ADDRESS]); + const curveOracle = await deployContract('CurveOracle', [ + Curve.provider, Curve.maxPools, [Curve.registryIds[registryIndex]], [Curve.registryTypes[registryIndex]], [], constants.EEE_ADDRESS, + ]); const curveProvider = await ethers.getContractAt('ICurveProvider', Curve.provider); const registryAddress = await curveProvider.get_address(Curve.registryIds[registryIndex]); const registry = await ethers.getContractAt('ICurveRegistry', registryAddress); @@ -141,7 +143,7 @@ describe('CurveOracle', function () { const [deployer] = await ethers.getSigners(); const uniswapV2LikeOracle = await deployContract('UniswapV2LikeOracle', [UniswapV2.factory, UniswapV2.initcodeHash]); - const curveOracle = await deployContract('CurveOracle', [Curve.provider, Curve.maxPools, Curve.registryIds, Curve.registryTypes, constants.EEE_ADDRESS]); + const curveOracle = await deployContract('CurveOracle', [Curve.provider, Curve.maxPools, Curve.registryIds, Curve.registryTypes, [], constants.EEE_ADDRESS]); const uniswapOracle = await deployContract('UniswapOracle', [Uniswap.factory]); const mooniswapOracle = await deployContract('MooniswapOracle', [tokens.oneInchLP1]); const wethWrapper = await deployContract('BaseCoinWrapper', [tokens.ETH, tokens.WETH]); From 1402e6b21cc4adedc350fa8d9734f5b1b562a0fe Mon Sep 17 00:00:00 2001 From: Denis Date: Tue, 25 Jun 2024 12:18:14 +0100 Subject: [PATCH 6/6] Bump tests timeout --- hardhat.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardhat.config.js b/hardhat.config.js index cf23ac76..a3cb934f 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -37,7 +37,7 @@ module.exports = { deploy: 'deploy/commands', }, mocha: { - timeout: 120000, + timeout: 180000, }, tracer: { enableAllOpcodes: true,