Skip to content
This repository was archived by the owner on Jan 18, 2023. It is now read-only.

Commit 0cc7cc8

Browse files
committed
implement redeem excluded
1 parent 0ed2568 commit 0cc7cc8

File tree

2 files changed

+61
-2
lines changed

2 files changed

+61
-2
lines changed

contracts/SetToken.sol

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,22 @@ contract SetToken is StandardToken, DetailedERC20("", "", 18), Set {
237237
return true;
238238
}
239239

240+
function redeemExcluded(uint quantity, address excludedComponent)
241+
public
242+
returns (bool success)
243+
{
244+
// Check there is enough balance
245+
uint remainingBalance = unredeemedComponents[excludedComponent][msg.sender].unredeemedBalance;
246+
require(remainingBalance >= quantity);
247+
248+
// To prevent re-entrancy attacks, decrement the user's Set balance
249+
unredeemedComponents[excludedComponent][msg.sender].unredeemedBalance = remainingBalance.sub(quantity);
250+
251+
assert(ERC20(excludedComponent).transfer(msg.sender, quantity));
252+
253+
return true;
254+
}
255+
240256
function componentCount() public view returns(uint componentsLength) {
241257
return components.length;
242258
}

test/setToken-base.spec.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ contract("{Set}", (accounts) => {
263263
);
264264
});
265265
});
266-
266+
267267
describe("of overflow units", async () => {
268268
it("should disallow issuing a quantity of tokens that would trigger an overflow", async () => {
269269
const overflowUnits = gWei(2).div(5);
@@ -295,7 +295,7 @@ contract("{Set}", (accounts) => {
295295
});
296296

297297
describe("Partial Redemption", async () => {
298-
const quantityIssued = new BigNumber(10);
298+
const quantityIssued = ether(10);
299299
let quantityA: BigNumber;
300300
let quantityB: BigNumber;
301301

@@ -343,4 +343,47 @@ contract("{Set}", (accounts) => {
343343
expect(postRedeemBalanceBofOwner).to.be.bignumber.equal(initialTokens, "Post Balance B");
344344
});
345345
});
346+
347+
describe("Redeem Excluded", async () => {
348+
const quantityIssued = ether(10);
349+
let quantityA: BigNumber;
350+
let quantityB: BigNumber;
351+
352+
// Create a Set two components with set tokens issued
353+
beforeEach(async () => {
354+
componentA = await StandardTokenMock.new(testAccount, initialTokens, "Component A", "A");
355+
componentB = await StandardTokenMock.new(testAccount, initialTokens, "Component B", "B");
356+
357+
setToken = await SetToken.new(
358+
[componentA.address, componentB.address],
359+
[unitsA, unitsB],
360+
TX_DEFAULTS,
361+
);
362+
363+
// Expected Quantities of tokens moved are divided by a gWei
364+
// to reflect the new units in set instantiation
365+
quantityA = unitsA.mul(quantityIssued).div(gWei(1));
366+
quantityB = unitsB.mul(quantityIssued).div(gWei(1));
367+
368+
await componentA.approve(setToken.address, quantityA, TX_DEFAULTS);
369+
await componentB.approve(setToken.address, quantityB, TX_DEFAULTS);
370+
371+
await setToken.issue(quantityIssued, TX_DEFAULTS);
372+
373+
// Perform a partial redeem
374+
await setToken.partialRedeem(quantityIssued, [componentA.address], TX_DEFAULTS);
375+
});
376+
377+
it("should successfully redeem excluded a standard Set", async () => {
378+
await setToken.redeemExcluded(quantityA, componentA.address, TX_DEFAULTS);
379+
380+
// The user should have a balance of TokenA
381+
const postRedeemBalanceAofOwner = await componentA.balanceOf(testAccount);
382+
expect(postRedeemBalanceAofOwner).to.be.bignumber.equal(initialTokens);
383+
384+
// The user should have no balance of Token A in excluded Tokens
385+
const [excludedBalanceAofOwner] = await setToken.unredeemedComponents(componentA.address, testAccount);
386+
expect(excludedBalanceAofOwner).to.be.bignumber.equal(0);
387+
});
388+
});
346389
});

0 commit comments

Comments
 (0)