Skip to content

Commit

Permalink
customizable redemption to address (#139)
Browse files Browse the repository at this point in the history
`redeem` can now be called with any `to` address.
  • Loading branch information
sirnicolaz authored Apr 12, 2024
1 parent 05c35d0 commit 7b30b63
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 27 deletions.
5 changes: 3 additions & 2 deletions contracts/InternalMarket/InternalMarket.sol
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,11 @@ contract InternalMarket is Initializable, HasRole, InternalMarketBase {

/**
* @dev Redeem the locked tokens.
* @param to The address of the receiver.
* @param amount The amount of tokens to redeem.
*/
function redeem(uint amount) public {
_redeem(_msgSender(), amount);
function redeem(address to, uint amount) public {
_redeem(to, amount);
}

/**
Expand Down
26 changes: 13 additions & 13 deletions test/Integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ describe("Integration", async () => {
e(4)
);

await internalMarket.connect(user1).redeem(e(10));
await internalMarket.redeem(user1.address, e(10));
// Chaining two changeTokenBalances seems to execute the "redeem"
// function twice. Anyway, this second redeem should fail.
/*
Expand All @@ -1111,7 +1111,7 @@ describe("Integration", async () => {
);
expect(await tokenMock.balanceOf(internalMarket.address)).equal(0);

await expect(internalMarket.connect(user1).redeem(e(4))).revertedWith(
await expect(internalMarket.redeem(user1.address, e(4))).revertedWith(
"Redemption controller: amount exceeds redeemable balance"
);

Expand All @@ -1121,17 +1121,17 @@ describe("Integration", async () => {
await internalMarket.connect(user2).withdraw(free2.address, e(90));
await timeTravel(redemptionStartDays - offerDurationDays, true);
// then tries to redeem but fails because not enough balance.
await expect(internalMarket.connect(user2).redeem(e(90))).revertedWith(
await expect(internalMarket.redeem(user2.address, e(90))).revertedWith(
"ERC20: burn amount exceeds balance"
);

// then tries to redeem 6 and succeeds.
await internalMarket.connect(user2).redeem(e(6));
await internalMarket.redeem(user2.address, e(6));

// then 4 after the redeem window and fails
await timeTravel(redemptionWindowDays, true);

await expect(internalMarket.connect(user2).redeem(e(4))).revertedWith(
await expect(internalMarket.redeem(user2.address, e(4))).revertedWith(
"Redemption controller: amount exceeds redeemable balance"
);
});
Expand All @@ -1156,12 +1156,12 @@ describe("Integration", async () => {
// user2 offer all tokens, hoping to redeem all of them...
await internalMarket.connect(user1).makeOffer(e(20));
await timeTravel(redemptionStartDays, true);
await expect(internalMarket.connect(user1).redeem(e(20))).revertedWith(
await expect(internalMarket.redeem(user1.address, e(20))).revertedWith(
"Redemption controller: amount exceeds redeemable balance"
);

// ...but they can only redeem those that were minted directly to them
await internalMarket.connect(user1).redeem(e(10));
await internalMarket.redeem(user1.address, e(10));
expect(await tokenMock.balanceOf(user1.address)).equal(
e(INITIAL_USDC + 10)
);
Expand Down Expand Up @@ -1247,15 +1247,15 @@ describe("Integration", async () => {
// 53 days later (60 since beginning) user1 redeems 3 tokens
await timeTravel(redemptionStartDays - offerDurationDays, true);
daysSinceMinting += redemptionStartDays - offerDurationDays;
await internalMarket.connect(user1).redeem(e(3));
await internalMarket.redeem(user1.address, e(3));
tokensRedeemed += 3;

// at the end of the redemption window, redemption of the 7 remaining
// tokens fails
await timeTravel(redemptionWindowDays, true);
daysSinceMinting += redemptionWindowDays;

await expect(internalMarket.connect(user1).redeem(e(7))).revertedWith(
await expect(internalMarket.redeem(user1.address, e(7))).revertedWith(
"Redemption controller: amount exceeds redeemable balance"
);

Expand All @@ -1265,7 +1265,7 @@ describe("Integration", async () => {
// after 60 days, user1 redeems 4 tokens
await timeTravel(redemptionStartDays, true);
daysSinceMinting += redemptionStartDays;
await internalMarket.connect(user1).redeem(e(4));
await internalMarket.redeem(user1.address, e(4));
tokensRedeemed += 4;

// redemption window expires
Expand All @@ -1287,7 +1287,7 @@ describe("Integration", async () => {
// 67 days later, redemption fails
await timeTravel(redemptionStartDays + redemptionWindowDays, true);

await expect(internalMarket.connect(user1).redeem(e(3))).revertedWith(
await expect(internalMarket.redeem(user1.address, e(3))).revertedWith(
"Redemption controller: amount exceeds redeemable balance"
);

Expand All @@ -1311,7 +1311,7 @@ describe("Integration", async () => {
);

// user1 redeems their only token and withdraws the others, sobbing again
await internalMarket.connect(user1).redeem(e(1));
await internalMarket.redeem(user1.address, e(1));
tokensRedeemed += 1;
await internalMarket.connect(user1).withdraw(user1.address, e(13));
await internalMarket.connect(user1).deposit(e(13));
Expand Down Expand Up @@ -1538,7 +1538,7 @@ describe("Integration", async () => {
});

await timeTravel(redemptionStartDays, true);
await internalMarket.connect(user1).redeem(e(20));
await internalMarket.redeem(user1.address, e(20));
await check({
// -20
internalSupply: 95,
Expand Down
24 changes: 12 additions & 12 deletions test/InternalMarket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ describe("InternalMarket", async () => {
await mineEVMBlock();
});
it("should call afterRedeem on redemptionController", async () => {
await internalMarket.connect(alice).redeem(50);
await internalMarket.redeem(alice.address, 50);

expect(redemption.afterRedeem).calledWith(alice.address, 50);
});
Expand All @@ -237,7 +237,7 @@ describe("InternalMarket", async () => {
});

it("should burn the 10 DAO tokens for 10 USDC of the reserve", async () => {
await internalMarket.connect(alice).redeem(parseEther("10"));
await internalMarket.redeem(alice.address, parseEther("10"));
expect(governanceToken.burn).calledWith(
internalMarket.address,
parseEther("10")
Expand All @@ -263,7 +263,7 @@ describe("InternalMarket", async () => {
});

it("should burn 10 DAO token for 20 USDC", async () => {
await internalMarket.connect(alice).redeem(parseEther("10"));
await internalMarket.redeem(alice.address, parseEther("10"));

expect(governanceToken.burn).calledWith(
internalMarket.address,
Expand All @@ -290,7 +290,7 @@ describe("InternalMarket", async () => {
});

it("should burn the 10 DAO tokens for 11.222444 USDC", async () => {
await internalMarket.connect(alice).redeem(parseEther("10"));
await internalMarket.redeem(alice.address, parseEther("10"));
expect(governanceToken.burn).calledWith(
internalMarket.address,
parseEther("10")
Expand All @@ -316,7 +316,7 @@ describe("InternalMarket", async () => {
});

it("should burn the 11 DAO tokens for 5.5 USDC", async () => {
await internalMarket.connect(alice).redeem(parseEther("11"));
await internalMarket.redeem(alice.address, parseEther("11"));
expect(governanceToken.burn).calledWith(
internalMarket.address,
parseEther("11")
Expand All @@ -329,7 +329,7 @@ describe("InternalMarket", async () => {
});

it("should exchange the 1 DAO token sat for 0 USDC sats", async () => {
await internalMarket.connect(alice).redeem(1);
await internalMarket.redeem(alice.address, 1);
expect(governanceToken.burn).calledWith(internalMarket.address, 1);
expect(usdc.transferFrom).calledWith(
reserve.address,
Expand Down Expand Up @@ -361,7 +361,7 @@ describe("InternalMarket", async () => {
.reverts("ERC20: burn amount exceeds balance");
// smock2 bug causes this error rather than the faked one
await expect(
internalMarket.connect(alice).redeem(parseEther("70"))
internalMarket.redeem(alice.address, parseEther("70"))
).revertedWith("function returned an unexpected amount of data");
});

Expand All @@ -372,13 +372,13 @@ describe("InternalMarket", async () => {
.whenCalledWith(alice.address, parseEther("10"))
.reverts("ERC20: burn amount exceeds balance");
await expect(
internalMarket.connect(alice).redeem(parseEther("60"))
internalMarket.redeem(alice.address, parseEther("60"))
).revertedWith("function returned an unexpected amount of data");
});

describe("when user redeems 50 tokens", async () => {
beforeEach(async () => {
await internalMarket.connect(alice).redeem(parseEther("50"));
await internalMarket.redeem(alice.address, parseEther("50"));
});

it("should burn 50 tokens from market", async () => {
Expand Down Expand Up @@ -408,13 +408,13 @@ describe("InternalMarket", async () => {

it("should fail when the user redeems 70 tokens", async () => {
await expect(
internalMarket.connect(alice).redeem(parseEther("70"))
internalMarket.redeem(alice.address, parseEther("70"))
).revertedWith("function returned an unexpected amount of data");
});

describe("when the user redeems 60 tokens", async () => {
beforeEach(async () => {
await internalMarket.connect(alice).redeem(parseEther("60"));
await internalMarket.redeem(alice.address, parseEther("60"));
});

it("should burn 10 tokens from alice", async () => {
Expand Down Expand Up @@ -442,7 +442,7 @@ describe("InternalMarket", async () => {

describe("when the user redeems 50 tokens", async () => {
beforeEach(async () => {
await internalMarket.connect(alice).redeem(parseEther("50"));
await internalMarket.redeem(alice.address, parseEther("50"));
});

it("should not burn 10 tokens from alice", async () => {
Expand Down

0 comments on commit 7b30b63

Please sign in to comment.