Skip to content

Commit

Permalink
fix: pr comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Debugger022 committed Dec 4, 2023
1 parent b9c63a8 commit 8d8f8c7
Show file tree
Hide file tree
Showing 9 changed files with 268 additions and 44 deletions.
4 changes: 2 additions & 2 deletions contracts/ProtocolReserve/RiskFundV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { IRiskFund } from "../Interfaces/IRiskFund.sol";
import { IRiskFundConverter } from "../Interfaces/IRiskFundConverter.sol";

import { ensureNonzeroAddress, ensureNonzeroValue } from "../Utils/Validators.sol";
import { EXP_SCALE } from "../Utils/Constants.sol";

import { RiskFundV2Storage } from "./RiskFundStorage.sol";

Expand Down Expand Up @@ -126,6 +125,7 @@ contract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund {
/// @param amount Amount need to sweep for the pool
/// @custom:event Emits SweepToken event on success
/// @custom:error ZeroAddressNotAllowed is thrown when tokenAddress/to address is zero
/// @custom:error ZeroValueNotAllowed is thrown when amount is zero
/// @custom:access Only Governance
function sweepToken(
address tokenAddress,
Expand Down Expand Up @@ -172,7 +172,7 @@ contract RiskFundV2 is AccessControlledV8, RiskFundV2Storage, IRiskFund {
emit PoolAssetsIncreased(comptroller, asset, amount);
}

/// @notice Operations to perform before sweeping tokens
/// @dev Operations to perform before sweeping tokens
/// @param tokenAddress Address of the token
/// @param amount Amount transferred to address(to)
/// @custom:error InsufficientBalance is thrown when amount entered is greater than balance
Expand Down
1 change: 1 addition & 0 deletions contracts/Test/Mocks/MockACM.sol
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.13;

import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol";
Expand Down
99 changes: 75 additions & 24 deletions contracts/TokenConverter/AbstractTokenConverter.sol

Large diffs are not rendered by default.

63 changes: 63 additions & 0 deletions contracts/TokenConverter/IAbstractTokenConverter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,67 @@ interface IAbstractTokenConverter {
address tokenAddressOut,
address to
) external;

/// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn
/// @param amountInMantissa Amount of tokenAddressIn
/// @param tokenAddressIn Address of the token to convert
/// @param tokenAddressOut Address of the token to get after conversion
/// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion
/// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion
/// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
/// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
function getUpdatedAmountOut(
uint256 amountInMantissa,
address tokenAddressIn,
address tokenAddressOut
) external returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);

/// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut
/// @param amountOutMantissa Amount of tokenAddressOut user wants to receive
/// @param tokenAddressIn Address of the token to convert
/// @param tokenAddressOut Address of the token to get after conversion
/// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion
/// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion
/// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
/// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
function getUpdatedAmountIn(
uint256 amountOutMantissa,
address tokenAddressIn,
address tokenAddressOut
) external returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);

/// @notice To get the amount of tokenAddressIn tokens sender would send on receiving amountOutMantissa tokens of tokenAddressOut
/// @dev This function retrieves values without altering token prices.
/// @param amountOutMantissa Amount of tokenAddressOut user wants to receive
/// @param tokenAddressIn Address of the token to convert
/// @param tokenAddressOut Address of the token to get after conversion
/// @return amountConvertedMantissa Amount of tokenAddressOut should be transferred after conversion
/// @return amountInMantissa Amount of the tokenAddressIn sender would send to contract before conversion
/// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
/// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
function getAmountIn(
uint256 amountOutMantissa,
address tokenAddressIn,
address tokenAddressOut
) external view returns (uint256 amountConvertedMantissa, uint256 amountInMantissa);

/// @notice To get the amount of tokenAddressOut tokens sender could receive on providing amountInMantissa tokens of tokenAddressIn
/// @dev This function retrieves values without altering token prices.
/// @param amountInMantissa Amount of tokenAddressIn
/// @param tokenAddressIn Address of the token to convert
/// @param tokenAddressOut Address of the token to get after conversion
/// @return amountConvertedMantissa Amount of tokenAddressIn should be transferred after conversion
/// @return amountOutMantissa Amount of the tokenAddressOut sender should receive after conversion
/// @custom:error InsufficientInputAmount error is thrown when given input amount is zero
/// @custom:error ConversionConfigNotEnabled is thrown when conversion is disabled or config does not exist for given pair
function getAmountOut(
uint256 amountInMantissa,
address tokenAddressIn,
address tokenAddressOut
) external view returns (uint256 amountConvertedMantissa, uint256 amountOutMantissa);

/// @notice Get the balance for specific token
/// @param token Address of the token
/// @return tokenBalance Balance of the token the contract has
function balanceOf(address token) external view returns (uint256 tokenBalance);
}
14 changes: 7 additions & 7 deletions contracts/TokenConverter/RiskFundConverter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ contract RiskFundConverter is AbstractTokenConverter {
return pools;
}

/// @notice Hook to perform after converting tokens
/// @dev Hook to perform after converting tokens
/// @dev After transformation poolsAssetsReserves are settled by pool's reserves fraction
/// @param tokenInAddress Address of the tokenIn
/// @param tokenOutAddress Address of the tokenOut
Expand Down Expand Up @@ -262,7 +262,7 @@ contract RiskFundConverter is AbstractTokenConverter {
assetsReserves[tokenOutAddress] -= amountOut;
}

/// @notice Operations to perform before sweeping tokens
/// @dev Operations to perform before sweeping tokens
/// @param tokenAddress Address of the token
/// @param amount Amount transferred to address(to)
/// @custom:error InsufficientBalance is thrown when amount entered is greater than balance of token
Expand Down Expand Up @@ -300,7 +300,7 @@ contract RiskFundConverter is AbstractTokenConverter {
}
}

/// @notice Update the poolAssetsReserves upon transferring the tokens
/// @dev Update the poolAssetsReserves upon transferring the tokens
/// @param pool Address of the pool
/// @param tokenAddress Address of the token
/// @param amount Amount transferred to address(to)
Expand All @@ -317,7 +317,7 @@ contract RiskFundConverter is AbstractTokenConverter {
emit AssetsReservesUpdated(pool, tokenAddress, poolAmountShare);
}

/// @notice Update the poolsAssetsDirectTransfer mapping
/// @dev Update the poolsAssetsDirectTransfer mapping
/// @param comptrollers Addresses of the pools
/// @param assets Addresses of the assets need to be added for direct transfer
/// @param values Boolean value to indicate whether direct transfer is allowed for each asset.
Expand Down Expand Up @@ -357,7 +357,7 @@ contract RiskFundConverter is AbstractTokenConverter {
}
}

/// @notice This function checks for the given asset is listed in core pool or not
/// @dev This function checks for the given asset is listed in core pool or not
/// @param tokenAddress Address of the asset
/// @return isAssetListed true if the asset is listed
function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) {
Expand All @@ -379,7 +379,7 @@ contract RiskFundConverter is AbstractTokenConverter {
}
}

/// @notice This function checks for the given asset is listed or not
/// @dev This function checks for the given asset is listed or not
/// @param comptroller Address of the comptroller
/// @param asset Address of the asset
/// @return true if the asset is listed
Expand All @@ -391,7 +391,7 @@ contract RiskFundConverter is AbstractTokenConverter {
return IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);
}

/// @notice Get base asset address of the RiskFund
/// @dev Get base asset address of the RiskFund
function _getDestinationBaseAsset() internal view override returns (address) {
return IRiskFundGetters(destinationAddress).convertibleBaseAsset();
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/TokenConverter/SingleTokenConverter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ contract SingleTokenConverter is AbstractTokenConverter {
tokenBalance = token.balanceOf(address(this));
}

/// @notice Get base asset address
/// @dev Get base asset address
function _getDestinationBaseAsset() internal view override returns (address) {
return BASE_ASSET;
}
Expand Down
3 changes: 0 additions & 3 deletions contracts/Utils/Constants.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause
pragma solidity 0.8.13;

/// @dev The approximate number of blocks per year that is assumed by the interest rate model
uint256 constant BLOCKS_PER_YEAR = 10_512_000;

/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)
uint256 constant EXP_SCALE = 1e18;

Expand Down
46 changes: 42 additions & 4 deletions tests/TokenConverter/AbstractTokenConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,16 @@ describe("MockConverter: tests", () => {

await tx.wait();

await expect(tx).to.emit(converter, "ConvertedForExactTokens").withArgs(expectedResults[1], expectedResults[0]);
await expect(tx)
.to.emit(converter, "ConvertedForExactTokens")
.withArgs(
await owner.getAddress(),
await to.getAddress(),
tokenIn.address,
tokenOut.address,
expectedResults[1],
expectedResults[0],
);
});

it("Revert on lower amount out than expected", async () => {
Expand Down Expand Up @@ -173,7 +182,29 @@ describe("MockConverter: tests", () => {

await tx.wait();

await expect(tx).to.emit(converter, "ConvertedExactTokens").withArgs(expectedResults[0], expectedResults[1]);
await expect(tx)
.to.emit(converter, "ConvertedExactTokens")
.withArgs(
await owner.getAddress(),
await to.getAddress(),
tokenIn.address,
tokenOut.address,
expectedResults[0],
expectedResults[1],
);
});

it("Revert when to address is invalid", async () => {
await converter.setConversionConfig(tokenIn.address, tokenOut.address, ConversionConfig);
await expect(
converter.convertExactTokens(
convertToUnit(".5", 18),
convertToUnit("1.5", 18),
tokenIn.address,
tokenOut.address,
await ethers.constants.AddressZero,
),
).to.be.revertedWithCustomError(converter, "ZeroAddressNotAllowed");
});

it("Revert on lower amount out than expected", async () => {
Expand Down Expand Up @@ -274,7 +305,14 @@ describe("MockConverter: tests", () => {
),
)
.to.emit(converter, "ConvertedExactTokensSupportingFeeOnTransferTokens")
.withArgs(amountTransferredAfterFees, expectedResults[1]);
.withArgs(
await owner.getAddress(),
await to.getAddress(),
tokenInDeflationary.address,
tokenOut.address,
amountTransferredAfterFees,
expectedResults[1],
);
});

it("Revert on deflationary token transfer", async () => {
Expand Down Expand Up @@ -555,7 +593,7 @@ describe("MockConverter: tests", () => {
).to.be.revertedWithCustomError(converter, "ConversionConfigNotEnabled");
});

it("Success on conversing tokenIn to tokenOut for under tokenOut liquidity", async () => {
it("Success on converting tokenIn to tokenOut for under tokenOut liquidity", async () => {
await setConversionConfig();
await oracle.getPrice.whenCalledWith(tokenIn.address).returns(TOKEN_IN_PRICE);
await oracle.getPrice.whenCalledWith(tokenOut.address).returns(TOKEN_OUT_PRICE);
Expand Down
80 changes: 77 additions & 3 deletions tests/TokenConverter/RiskFundConverter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
MockRiskFundConverter__factory,
MockToken,
MockToken__factory,
ResilientOracleInterface,
ResilientOracle,
RiskFundV2,
} from "../../typechain";
import { convertToUnit } from "../utils";
Expand All @@ -29,7 +29,7 @@ let accessControl: FakeContract<IAccessControlManagerV8>;
let converter: MockContract<MockRiskFundConverter>;
let tokenIn: MockContract<MockToken>;
let tokenOut: MockContract<MockToken>;
let oracle: FakeContract<ResilientOracleInterface>;
let oracle: FakeContract<ResilientOracle>;
let poolRegistry: FakeContract<IPoolRegistry>;
let newPoolRegistry: FakeContract<IPoolRegistry>;
let riskFund: FakeContract<RiskFundV2>;
Expand Down Expand Up @@ -59,7 +59,7 @@ async function fixture(): Promise<void> {
WBNB = await smock.fake<MockToken>("MockToken");

accessControl = await smock.fake<IAccessControlManagerV8>("IAccessControlManagerV8");
oracle = await smock.fake<ResilientOracleInterface>("ResilientOracleInterface");
oracle = await smock.fake<ResilientOracle>("ResilientOracle");

const MockToken = await smock.mock<MockToken__factory>("MockToken");
const MockTokenDeflationary = await smock.mock<MockDeflatingToken__factory>("MockDeflatingToken");
Expand Down Expand Up @@ -244,6 +244,7 @@ describe("Risk fund Converter: tests", () => {

expect(await tokenIn.balanceOf(converter.address)).to.equal(0);
expect(await tokenIn.balanceOf(riskFund.address)).to.equal(POOL_A_AMOUNT);
expect(await converter.getAssetsReserves(tokenIn.address)).to.equal(0);
});

it("Revert on invalid parameters", async () => {
Expand All @@ -270,4 +271,77 @@ describe("Risk fund Converter: tests", () => {
).to.be.revertedWithCustomError(converter, "InvalidArguments");
});
});

describe("Converting function", () => {
const amount = convertToUnit("200", 18);
const amountTransferred = convertToUnit("50", 18);
const TOKEN_IN_PRICE = convertToUnit("1", 18);
const TOKEN_OUT_PRICE = convertToUnit("0.5", 18);
const INCENTIVE = convertToUnit("1", 17);

beforeEach(async () => {
newPoolRegistry.getPoolsSupportedByAsset.returns([poolC.address]);

await converter.setPoolsAssetsReserves(poolC.address, tokenIn.address, 0);
await converter.setPoolsAssetsReserves(poolC.address, tokenOut.address, 0);
await converter.setPoolsAssetsReserves(corePool.address, tokenIn.address, 0);
await converter.setPoolsAssetsReserves(corePool.address, tokenOut.address, 0);
await converter.setAssetsReserves(tokenIn.address, 0);
await converter.setAssetsReserves(tokenOut.address, 0);

await tokenIn.faucet(amount);
await tokenOut.faucet(amount);
await tokenIn.transfer(converter.address, amount);
await tokenOut.transfer(converter.address, amount);

await converter.updateAssetsState(poolC.address, tokenIn.address);
await converter.updateAssetsState(poolC.address, tokenOut.address);
});

it("Should update states correctly on conversion of tokens", async () => {
const [admin] = await ethers.getSigners();

expect(await converter.getAssetsReserves(tokenIn.address)).to.equal(amount);
expect(await converter.getAssetsReserves(tokenOut.address)).to.equal(amount);
await expect(await converter.getPoolAssetReserve(poolC.address, tokenOut.address)).to.equal(amount);
await expect(await converter.getPoolAssetReserve(poolC.address, tokenIn.address)).to.equal(amount);

await riskFund.convertibleBaseAsset.returns(tokenIn.address);

const ConversionConfig = {
tokenAddressIn: tokenIn.address,
tokenAddressOut: tokenOut.address,
incentive: INCENTIVE,
enabled: true,
};

await converter.connect(admin).setConversionConfig(tokenIn.address, tokenOut.address, ConversionConfig);

await oracle.getPrice.whenCalledWith(tokenIn.address).returns(TOKEN_IN_PRICE);
await oracle.getPrice.whenCalledWith(tokenOut.address).returns(TOKEN_OUT_PRICE);

const expectedResults = await converter.callStatic.getUpdatedAmountOut(
amountTransferred,
tokenIn.address,
tokenOut.address,
);

await tokenIn.approve(converter.address, amountTransferred);
await converter.convertExactTokens(
amountTransferred,
convertToUnit(".5", 18),
tokenIn.address,
tokenOut.address,
await unKnown.getAddress(),
);
await expect(await converter.getAssetsReserves(tokenOut.address)).to.equal(
BigNumber(amount).minus(Number(expectedResults[1])),
);
await expect(await converter.getAssetsReserves(tokenIn.address)).to.equal(amount);
await expect(await converter.getPoolAssetReserve(poolC.address, tokenOut.address)).to.equal(
BigNumber(amount).minus(Number(expectedResults[1])),
);
await expect(await converter.getPoolAssetReserve(poolC.address, tokenIn.address)).to.equal(amount);
});
});
});

0 comments on commit 8d8f8c7

Please sign in to comment.