Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions contracts/mocks/protocol/integration/lib/CompoundMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -131,7 +146,7 @@ contract CompoundMock {

function testInvokeRepayBorrowCToken(ISetToken _setToken, ICErc20 _cToken, uint256 _repayNotional) external {
Compound.invokeRepayBorrowCToken(_setToken, _cToken, _repayNotional);
}
}

function testGetBorrowCalldata(
ICErc20 _cToken,
Expand All @@ -153,4 +168,4 @@ contract CompoundMock {
function initializeModuleOnSet(ISetToken _setToken) external {
_setToken.initializeModule();
}
}
}
2 changes: 1 addition & 1 deletion contracts/protocol/integration/CompoundWrapAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
35 changes: 32 additions & 3 deletions contracts/protocol/integration/lib/Compound.sol
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ library Compound {
}

/**
* Get redeem calldata
* Get redeem underlying calldata
*/
function getRedeemUnderlyingCalldata(
ICErc20 _cToken,
Expand All @@ -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"
);
}
Expand Down Expand Up @@ -253,4 +282,4 @@ library Compound {
"Borrow failed"
);
}
}
}
19 changes: 6 additions & 13 deletions test/integration/compoundWrapModule.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)],
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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;

Expand All @@ -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);
});
Expand Down
10 changes: 3 additions & 7 deletions test/protocol/integration/compoundWrapAdapter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -34,7 +30,7 @@ describe("CompoundWrapAdapter", () => {

before(async () => {
[
owner
owner,
] = await getAccounts();

deployer = new DeployHelper(owner.wallet);
Expand Down Expand Up @@ -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);
Expand Down
68 changes: 67 additions & 1 deletion test/protocol/integration/lib/compound.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<any> {
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<any> {
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
Expand Down Expand Up @@ -628,4 +694,4 @@ describe("Compound", () => {
});
});
});
});
});
4 changes: 2 additions & 2 deletions test/protocol/modules/compoundLeverageModule.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
});
});

Expand Down Expand Up @@ -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");
});
});

Expand Down
2 changes: 1 addition & 1 deletion test/protocol/modules/compoundLeverageModule2.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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");
});
});

Expand Down