From a05eda1731d2060c1e12afc105bd3fdecacf001d Mon Sep 17 00:00:00 2001 From: mario Date: Mon, 5 Apr 2021 11:46:13 -0700 Subject: [PATCH 1/2] report all --- .../protocol/integration/lib/CompoundMock.sol | 19 +++++- .../integration/CompoundWrapAdapter.sol | 2 +- .../protocol/integration/lib/Compound.sol | 35 +++++++++- test/integration/compoundWrapModule.spec.ts | 19 ++---- .../integration/compoundWrapAdapter.spec.ts | 10 +-- .../protocol/integration/lib/compound.spec.ts | 68 ++++++++++++++++++- 6 files changed, 126 insertions(+), 27 deletions(-) diff --git a/contracts/mocks/protocol/integration/lib/CompoundMock.sol b/contracts/mocks/protocol/integration/lib/CompoundMock.sol index 61df04a70..16dae50ac 100644 --- a/contracts/mocks/protocol/integration/lib/CompoundMock.sol +++ b/contracts/mocks/protocol/integration/lib/CompoundMock.sol @@ -103,6 +103,21 @@ contract CompoundMock { Compound.invokeRedeemUnderlying(_setToken, _cToken, _redeemNotional); } + function testGetRedeemCalldata( + ICErc20 _cToken, + uint256 _redeemNotional + ) + external + pure + returns (address, uint256, bytes memory) + { + return Compound.getRedeemCalldata(_cToken, _redeemNotional); + } + + function testInvokeRedeem(ISetToken _setToken, ICErc20 _cToken, uint256 _redeemNotional) external { + Compound.invokeRedeem(_setToken, _cToken, _redeemNotional); + } + function testGetRepayBorrowCEtherCalldata( ICErc20 _cToken, uint256 _repayNotional @@ -131,7 +146,7 @@ contract CompoundMock { function testInvokeRepayBorrowCToken(ISetToken _setToken, ICErc20 _cToken, uint256 _repayNotional) external { Compound.invokeRepayBorrowCToken(_setToken, _cToken, _repayNotional); - } + } function testGetBorrowCalldata( ICErc20 _cToken, @@ -153,4 +168,4 @@ contract CompoundMock { function initializeModuleOnSet(ISetToken _setToken) external { _setToken.initializeModule(); } -} \ No newline at end of file +} diff --git a/contracts/protocol/integration/CompoundWrapAdapter.sol b/contracts/protocol/integration/CompoundWrapAdapter.sol index 13685dc7b..1366e035a 100644 --- a/contracts/protocol/integration/CompoundWrapAdapter.sol +++ b/contracts/protocol/integration/CompoundWrapAdapter.sol @@ -92,7 +92,7 @@ contract CompoundWrapAdapter { view returns (address, uint256, bytes memory) { - ( , , bytes memory callData) = ICErc20(_wrappedToken).getRedeemUnderlyingCalldata(_wrappedTokenUnits); + ( , , bytes memory callData) = ICErc20(_wrappedToken).getRedeemCalldata(_wrappedTokenUnits); return (_wrappedToken, 0, callData); } diff --git a/contracts/protocol/integration/lib/Compound.sol b/contracts/protocol/integration/lib/Compound.sol index 101089c7a..170010852 100644 --- a/contracts/protocol/integration/lib/Compound.sol +++ b/contracts/protocol/integration/lib/Compound.sol @@ -145,7 +145,7 @@ library Compound { } /** - * Get redeem calldata + * Get redeem underlying calldata */ function getRedeemUnderlyingCalldata( ICErc20 _cToken, @@ -166,9 +166,38 @@ library Compound { */ function invokeRedeemUnderlying(ISetToken _setToken, ICErc20 _cToken, uint256 _redeemNotional) external { ( , , bytes memory redeemUnderlyingCalldata) = getRedeemUnderlyingCalldata(_cToken, _redeemNotional); - + require( abi.decode(_setToken.invoke(address(_cToken), 0, redeemUnderlyingCalldata), (uint256)) == 0, + "Redeem underlying failed" + ); + } + + /** + * Get redeem calldata + */ + function getRedeemCalldata( + ICErc20 _cToken, + uint256 _redeemNotional + ) + public + pure + returns (address, uint256, bytes memory) + { + bytes memory callData = abi.encodeWithSignature("redeem(uint256)", _redeemNotional); + + return (address(_cToken), _redeemNotional, callData); + } + + + /** + * Invoke redeem from the SetToken + */ + function invokeRedeem(ISetToken _setToken, ICErc20 _cToken, uint256 _redeemNotional) external { + ( , , bytes memory redeemCalldata) = getRedeemCalldata(_cToken, _redeemNotional); + + require( + abi.decode(_setToken.invoke(address(_cToken), 0, redeemCalldata), (uint256)) == 0, "Redeem failed" ); } @@ -253,4 +282,4 @@ library Compound { "Borrow failed" ); } -} \ No newline at end of file +} diff --git a/test/integration/compoundWrapModule.spec.ts b/test/integration/compoundWrapModule.spec.ts index 9f3cd880d..51eaa12f1 100644 --- a/test/integration/compoundWrapModule.spec.ts +++ b/test/integration/compoundWrapModule.spec.ts @@ -4,7 +4,7 @@ import { BigNumber } from "@ethersproject/bignumber"; import { Address } from "@utils/types"; import { Account } from "@utils/test/types"; import { ADDRESS_ZERO } from "@utils/constants"; -import { CompoundWrapAdapter, SetToken, WrapModule } from "@utils/contracts"; +import { SetToken, WrapModule } from "@utils/contracts"; import { CERc20 } from "@utils/contracts/compound"; import DeployHelper from "@utils/deploys"; import { @@ -80,7 +80,7 @@ describe("compoundWrapModule", () => { let setToken: SetToken; let setTokensIssued: BigNumber; - before(async () => { + beforeEach(async () => { setToken = await setup.createSetToken( [setup.dai.address], [ether(1)], @@ -128,8 +128,6 @@ describe("compoundWrapModule", () => { it("should reduce the underlying quantity and mint the wrapped asset to the SetToken", async () => { const previousUnderlyingBalance = await setup.dai.balanceOf(setToken.address); - const previousWrappedBalance = await cDai.balanceOf(setToken.address); - await subject(); const underlyingBalance = await setup.dai.balanceOf(setToken.address); @@ -138,9 +136,6 @@ describe("compoundWrapModule", () => { expect(underlyingBalance).to.eq(expectedUnderlyingBalance); - const underlyingTokenDecimals = await setup.dai.decimals(); - const wrappedTokenDecimals = await cDai.decimals(); - const expectedWrappedBalance = preciseDiv(previousUnderlyingBalance, exchangeRate); expect(wrappedBalance).to.eq(expectedWrappedBalance); @@ -161,7 +156,7 @@ describe("compoundWrapModule", () => { subjectSetToken = setToken.address; subjectUnderlyingToken = setup.dai.address; subjectWrappedToken = cDai.address; - subjectWrappedTokenUnits = ether(0.5); + subjectWrappedTokenUnits = BigNumber.from("5000000000"); // ctokens have 8 decimals subjectIntegrationName = compoundWrapAdapterIntegrationName; subjectCaller = owner; @@ -187,20 +182,18 @@ describe("compoundWrapModule", () => { } it("should burn the wrapped asset to the SetToken and increase the underlying quantity", async () => { - const previousUnderlyingBalance = await setup.dai.balanceOf(setToken.address); const previousWrappedBalance = await cDai.balanceOf(setToken.address); await subject(); const underlyingBalance = await setup.dai.balanceOf(setToken.address); const wrappedBalance = await cDai.balanceOf(setToken.address); - const delta = preciseMul(setTokensIssued, wrappedQuantity.sub(subjectWrappedTokenUnits)); - const expectedUnderlyingBalance = previousUnderlyingBalance.add(delta); + const delta = preciseMul(setTokensIssued, subjectWrappedTokenUnits); + const expectedUnderlyingBalance = preciseMul(delta, exchangeRate); expect(underlyingBalance).to.eq(expectedUnderlyingBalance); - const wrappedTokenUnits = preciseDiv(delta, exchangeRate); - const expectedWrappedBalance = previousWrappedBalance.sub(wrappedTokenUnits); + const expectedWrappedBalance = previousWrappedBalance.sub(delta); expect(wrappedBalance).to.eq(expectedWrappedBalance); }); diff --git a/test/protocol/integration/compoundWrapAdapter.spec.ts b/test/protocol/integration/compoundWrapAdapter.spec.ts index 6fcae0485..09cee6e05 100644 --- a/test/protocol/integration/compoundWrapAdapter.spec.ts +++ b/test/protocol/integration/compoundWrapAdapter.spec.ts @@ -8,11 +8,7 @@ import { ETH_ADDRESS, ZERO } from "@utils/constants"; import { CompoundFixture, SystemFixture } from "@utils/fixtures"; import { CompoundWrapAdapter } from "@utils/contracts"; import DeployHelper from "@utils/deploys"; -import { - ether, - addressToData, - bigNumberToData -} from "@utils/index"; +import { ether } from "@utils/index"; import { addSnapshotBeforeRestoreAfterEach, getAccounts, @@ -34,7 +30,7 @@ describe("CompoundWrapAdapter", () => { before(async () => { [ - owner + owner, ] = await getAccounts(); deployer = new DeployHelper(owner.wallet); @@ -155,7 +151,7 @@ describe("CompoundWrapAdapter", () => { it("should return correct data", async () => { const [targetAddress, ethValue, callData] = await subject(); - const expectedCallData = cDai.interface.encodeFunctionData("redeemUnderlying", [subjectQuantity]); + const expectedCallData = cDai.interface.encodeFunctionData("redeem", [subjectQuantity]); expect(targetAddress).to.eq(subjectCToken); expect(ethValue).to.eq(ZERO); diff --git a/test/protocol/integration/lib/compound.spec.ts b/test/protocol/integration/lib/compound.spec.ts index 9903b8295..44573daba 100644 --- a/test/protocol/integration/lib/compound.spec.ts +++ b/test/protocol/integration/lib/compound.spec.ts @@ -415,6 +415,72 @@ describe("Compound", () => { expect(currentCTokenBalance).to.eq(expectedCTokenBalance); }); + describe("when redeeming underlying return data is a nonzero value", async () => { + beforeEach(async () => { + // Set redeem quantity to more than account liquidity + subjectQuantity = ether(10000); + }); + + it("should revert", async () => { + await expect(subject()).to.be.revertedWith("Redeem underlying failed"); + }); + }); + }); + + describe("#getRedeemCalldata", async () => { + let subjectCToken: Address; + let subjectQuantity: BigNumber; + + beforeEach(async () => { + subjectCToken = cDai.address; + subjectQuantity = ether(1); + }); + + async function subject(): Promise { + return compoundLibMock.testGetRedeemCalldata( + subjectCToken, + subjectQuantity, + ); + } + + it("should get correct data", async () => { + const [target, value, calldata] = await subject(); + const expectedCalldata = cDai.interface.encodeFunctionData("redeem", [subjectQuantity]); + + expect(target).to.eq(subjectCToken); + expect(value).to.eq(subjectQuantity); + expect(calldata).to.eq(expectedCalldata); + }); + }); + + describe("#invokeRedeem", async () => { + let subjectSetToken: Address; + let subjectCToken: Address; + let subjectQuantity: BigNumber; + + beforeEach(async () => { + subjectSetToken = setToken.address; + subjectCToken = cDai.address; + const exchangeRate = await cDai.exchangeRateStored(); + subjectQuantity = preciseDiv(ether(1), exchangeRate); + }); + + async function subject(): Promise { + return compoundLibMock.testInvokeRedeem( + subjectSetToken, + subjectCToken, + subjectQuantity, + ); + } + + it("should redeem cToken", async () => { + const previousCTokenBalance = await cDai.balanceOf(setToken.address); + await subject(); + const currentCTokenBalance = await cDai.balanceOf(setToken.address); + const expectedCTokenBalance = previousCTokenBalance.sub(subjectQuantity); + expect(currentCTokenBalance).to.eq(expectedCTokenBalance); + }); + describe("when redeeming return data is a nonzero value", async () => { beforeEach(async () => { // Set redeem quantity to more than account liquidity @@ -628,4 +694,4 @@ describe("Compound", () => { }); }); }); -}); \ No newline at end of file +}); From 19defa65dfd80fd4f7e153538ca6d6a1ed67b8d4 Mon Sep 17 00:00:00 2001 From: mario Date: Tue, 6 Apr 2021 12:46:43 -0700 Subject: [PATCH 2/2] fix tests --- test/protocol/modules/compoundLeverageModule.spec.ts | 4 ++-- test/protocol/modules/compoundLeverageModule2.spec.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/protocol/modules/compoundLeverageModule.spec.ts b/test/protocol/modules/compoundLeverageModule.spec.ts index 8009440b3..d65d8763f 100644 --- a/test/protocol/modules/compoundLeverageModule.spec.ts +++ b/test/protocol/modules/compoundLeverageModule.spec.ts @@ -1575,7 +1575,7 @@ describe("CompoundLeverageModule", () => { }); it("should revert", async () => { - await expect(subject()).to.be.revertedWith("Redeem failed"); + await expect(subject()).to.be.revertedWith("Redeem underlying failed"); }); }); @@ -1847,7 +1847,7 @@ describe("CompoundLeverageModule", () => { }); it("should revert", async () => { - await expect(subject()).to.be.revertedWith("Redeem failed"); + await expect(subject()).to.be.revertedWith("Redeem underlying failed"); }); }); diff --git a/test/protocol/modules/compoundLeverageModule2.spec.ts b/test/protocol/modules/compoundLeverageModule2.spec.ts index d2c736b67..fc5058f6c 100644 --- a/test/protocol/modules/compoundLeverageModule2.spec.ts +++ b/test/protocol/modules/compoundLeverageModule2.spec.ts @@ -343,7 +343,7 @@ describe("CompoundLeverageModule TestSuite 2", () => { }); it("should revert", async () => { - await expect(subject()).to.be.revertedWith("Redeem failed"); + await expect(subject()).to.be.revertedWith("Redeem underlying failed"); }); });