From be25145b147ae334f936cd8ee6bb26dbe0b1c7da Mon Sep 17 00:00:00 2001 From: user Date: Thu, 23 Nov 2023 11:13:35 +1030 Subject: [PATCH] Add tests for new blacklist feature and fix some old tests --- contracts/ethereum/contracts/Token.sol | 2 +- contracts/ethereum/mainnet-constants.ts | 2 +- .../scripts/deploy-token-beacon-proxy.ts | 11 ++-- ...tend-to-be-address-and-redeem-in-future.ts | 2 +- .../ethereum/test/lootbox-staking-deployed.ts | 2 +- contracts/ethereum/test/setup-common.ts | 2 + contracts/ethereum/test/setup-mainnet.ts | 2 + contracts/ethereum/test/token.ts | 51 +++++++++++++++++++ contracts/ethereum/types.ts | 1 + 9 files changed, 67 insertions(+), 8 deletions(-) diff --git a/contracts/ethereum/contracts/Token.sol b/contracts/ethereum/contracts/Token.sol index 1159c1cdd..e1c863f18 100644 --- a/contracts/ethereum/contracts/Token.sol +++ b/contracts/ethereum/contracts/Token.sol @@ -328,7 +328,7 @@ contract Token is uint256 _amount ) internal returns (uint256) { // check if the account isn't blacklisted - require(isAddressAllowed(_sender)); + require(isAddressAllowed(_sender), "address blacklisted"); // take the user's fluid tokens diff --git a/contracts/ethereum/mainnet-constants.ts b/contracts/ethereum/mainnet-constants.ts index 29ff8291f..25aac527a 100644 --- a/contracts/ethereum/mainnet-constants.ts +++ b/contracts/ethereum/mainnet-constants.ts @@ -1,5 +1,5 @@ -import type { Token } from "../types"; +import type { Token } from "./types"; export const USDT_ADDR = "0xdac17f958d2ee523a2206206994597c13d831ec7"; export const CUSDT_ADDR = "0xf650c3d88d12db855b8bf7d11be6c55a4e07dcc9"; diff --git a/contracts/ethereum/scripts/deploy-token-beacon-proxy.ts b/contracts/ethereum/scripts/deploy-token-beacon-proxy.ts index c703534a2..e9540e543 100644 --- a/contracts/ethereum/scripts/deploy-token-beacon-proxy.ts +++ b/contracts/ethereum/scripts/deploy-token-beacon-proxy.ts @@ -59,6 +59,9 @@ const main = async () => { let pool: ethers.Contract; + let aToken: string; + let aavePool: string; + switch (backend) { case "compound": const cToken = mustEnv(ENV_COMPOUND_CTOKEN); @@ -72,8 +75,8 @@ const main = async () => { break; case "aaveV2": - const aToken = mustEnv(ENV_AAVE_V2_ATOKEN); - const aavePool = mustEnv(ENV_AAVE_V2_ADDRESS_PROVIDER); + aToken = mustEnv(ENV_AAVE_V2_ATOKEN); + aavePool = mustEnv(ENV_AAVE_V2_ADDRESS_PROVIDER); console.log(`deploying aave v2 pool with beacon ${poolAddress}, atoken ${aToken}, aave pool ${aavePool}`); pool = await hre.upgrades.deployBeaconProxy( poolAddress, @@ -84,8 +87,8 @@ const main = async () => { break; case "aaveV3": - const aToken = mustEnv(ENV_AAVE_V3_ATOKEN); - const aavePool = mustEnv(ENV_AAVE_V3_ADDRESS_PROVIDER); + aToken = mustEnv(ENV_AAVE_V3_ATOKEN); + aavePool = mustEnv(ENV_AAVE_V3_ADDRESS_PROVIDER); console.log(`deploying aave v3 pool with beacon ${poolAddress}, atoken ${aToken}, aave pool ${aavePool}`); pool = await hre.upgrades.deployBeaconProxy( poolAddress, diff --git a/contracts/ethereum/scripts/lootbox-staking-pretend-to-be-address-and-redeem-in-future.ts b/contracts/ethereum/scripts/lootbox-staking-pretend-to-be-address-and-redeem-in-future.ts index cb39c8353..d903be12e 100644 --- a/contracts/ethereum/scripts/lootbox-staking-pretend-to-be-address-and-redeem-in-future.ts +++ b/contracts/ethereum/scripts/lootbox-staking-pretend-to-be-address-and-redeem-in-future.ts @@ -97,7 +97,7 @@ const main = async () => { to: impersonatedAddr }); - const [ fusdcRedeemed, usdcRedeemed, wethRedeemed ] = await redeem(staking); + const [ fusdcRedeemed, usdcRedeemed, wethRedeemed ] = await redeem(staking, 0, 0, 0); console.log( `redeemed for addr ${impersonatedAddr}, fusdc redeemed ${fusdcRedeemed}, usdc redeemed ${usdcRedeemed}, weth redeemed ${wethRedeemed}` diff --git a/contracts/ethereum/test/lootbox-staking-deployed.ts b/contracts/ethereum/test/lootbox-staking-deployed.ts index d1c13cbc6..0d0593ec3 100644 --- a/contracts/ethereum/test/lootbox-staking-deployed.ts +++ b/contracts/ethereum/test/lootbox-staking-deployed.ts @@ -97,7 +97,7 @@ describe("LootboxStaking deployed infra", async () => { method: "hardhat_setBalance", params: [ stakingOperatorAddr, - ethers.constants.MaxUint256.toHexString() + MaxUint256.toHexString() ] }); diff --git a/contracts/ethereum/test/setup-common.ts b/contracts/ethereum/test/setup-common.ts index 6355956d0..73f89e040 100644 --- a/contracts/ethereum/test/setup-common.ts +++ b/contracts/ethereum/test/setup-common.ts @@ -50,6 +50,7 @@ before(async function () { fwEthAccountSigner, veGovSigner, registrySigner, + blacklistedSigner ] = await hre.ethers.getSigners(); const councilAddress = await operatorCouncilSigner.getAddress(); @@ -146,6 +147,7 @@ before(async function () { emergencyCouncil: tokenCouncilSigner, externalOperator: tokenOperatorSigner, externalOracle: externalOracleSigner, + blacklistedSigner: blacklistedSigner, }, operator: { diff --git a/contracts/ethereum/test/setup-mainnet.ts b/contracts/ethereum/test/setup-mainnet.ts index a9e9f95cd..9e36c14ec 100644 --- a/contracts/ethereum/test/setup-mainnet.ts +++ b/contracts/ethereum/test/setup-mainnet.ts @@ -44,6 +44,7 @@ export let bindings: typeof commonBindings & { oracleBoundOperator: ethers.Contract, externalOperator: ethers.Contract, emergencyCouncil: ethers.Contract, + blacklistedSpender: ethers.Contract }, fei: { base: ethers.Contract, @@ -168,6 +169,7 @@ before(async function () { fluidAccount2: contracts.usdt.deployedToken.connect(signers.userAccount2), externalOperator: contracts.usdt.deployedToken.connect(signers.token.externalOperator), emergencyCouncil: contracts.usdt.deployedToken.connect(signers.token.emergencyCouncil), + blacklistedSpender: contracts.usdt.deployedToken.connect(signers.token.blacklistedSigner), oracleBoundOperator: contracts.operator.connect(signers.token.externalOracle), }, fei: { diff --git a/contracts/ethereum/test/token.ts b/contracts/ethereum/test/token.ts index 4b14dc370..e639f9995 100644 --- a/contracts/ethereum/test/token.ts +++ b/contracts/ethereum/test/token.ts @@ -1,4 +1,6 @@ +import * as hre from "hardhat"; + import * as ethers from 'ethers'; import { BigNumber } from 'ethers'; @@ -20,11 +22,15 @@ function fluidityReward(...winners: [string, number][]) { ]]; } +const MaxUint256 = ethers.constants.MaxUint256; + describe("Token", async function () { let fUsdtOperator: ethers.Contract; let fUsdtAccount: ethers.Contract; let fUsdtOracle: ethers.Contract; let fUsdtCouncil: ethers.Contract; + let fUsdtBlacklistedSpender: ethers.Contract; + let fluidToken: string; let accountAddr: string; @@ -38,6 +44,7 @@ describe("Token", async function () { fluidAccount1: fUsdtAccount, oracleBoundOperator: fUsdtOracle, emergencyCouncil: fUsdtCouncil, + blacklistedSpender: fUsdtBlacklistedSpender, }, } = bindings); accountAddr = await signers.userAccount1.getAddress(); @@ -180,4 +187,48 @@ describe("Token", async function () { it("does approvals correctly using eip2612", async () => { }); + + it("ensures that the address is blacklisted and enforced correctly", async () => { + const blacklistedAddr = await signers.token.blacklistedSigner.getAddress(); + const fUsdtOperatorAddr = await fUsdtOperator.signer.getAddress(); + + await hre.network.provider.request({ + method: "hardhat_setBalance", + params: [blacklistedAddr, MaxUint256.toHexString()] + }); + + await fUsdtOperator.blacklistAddress(blacklistedAddr, true); + + await expect(fUsdtBlacklistedSpender.transfer(fUsdtOperatorAddr, MaxUint256)) + .to.be.revertedWith("address blacklisted"); + + fUsdtBlacklistedSpender.approve(fUsdtOperatorAddr, MaxUint256); + + await expect(fUsdtOperator.transferFrom(blacklistedAddr, fUsdtOperatorAddr, MaxUint256)) + .to.be.revertedWith("address blacklisted"); + + await expect(fUsdtBlacklistedSpender.transferFrom(fUsdtOperatorAddr, blacklistedAddr, MaxUint256)) + .to.be.revertedWith("address blacklisted"); + + await expect(fUsdtBlacklistedSpender.erc20In(MaxUint256)) + .to.be.revertedWith("address blacklisted"); + + await expect(fUsdtBlacklistedSpender.erc20Out(MaxUint256)) + .to.be.revertedWith("address blacklisted"); + + await fUsdtOperator.blacklistAddress(blacklistedAddr, false); + + await expect(fUsdtOperator.transferFrom(blacklistedAddr, fUsdtOperatorAddr, MaxUint256)) + .to.be.revertedWith("ERC20: transfer amount exceeds balance"); + + await expect(fUsdtBlacklistedSpender.transferFrom(fUsdtOperatorAddr, blacklistedAddr, MaxUint256)) + .to.be.revertedWith("insufficient allowance"); + + await expect(fUsdtBlacklistedSpender.erc20In(MaxUint256)) + .to.be.revertedWith("SafeERC20: low-level call failed"); + + await expect(fUsdtBlacklistedSpender.erc20Out(MaxUint256)) + .to.be.revertedWith("ERC20: burn amount exceeds balance"); + + }); }); diff --git a/contracts/ethereum/types.ts b/contracts/ethereum/types.ts index 49cf921ea..10f1a9695 100644 --- a/contracts/ethereum/types.ts +++ b/contracts/ethereum/types.ts @@ -63,6 +63,7 @@ export type FluiditySigners = { emergencyCouncil: ethers.Signer, externalOperator: ethers.Signer, externalOracle: ethers.Signer, + blacklistedSigner: ethers.Signer, }, operator: {