Skip to content

Commit 23ca766

Browse files
authored
Merge pull request #31 from DAM-Protocol/issue12-fix
Fixed issue 12 and modified tests.
2 parents a53a188 + ca2cfac commit 23ca766

3 files changed

Lines changed: 134 additions & 13 deletions

File tree

smart-contracts/contracts/StrollManager.sol

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import "@openzeppelin/contracts/access/Ownable.sol";
66
import "./interfaces/IERC20Mod.sol";
77
import "./interfaces/IStrollManager.sol";
88

9+
910
// solhint-disable not-rely-on-time
1011
/// @title StrollManager
1112
/// @author Harsh Prakash <0xharsh@proton.me>
@@ -29,6 +30,9 @@ contract StrollManager is IStrollManager, Ownable {
2930
uint64 _minLower,
3031
uint64 _minUpper
3132
) {
33+
if (_icfa == address(0)) revert ZeroAddress();
34+
if (_minLower >= _minUpper) revert WrongLimits(_minLower, _minUpper);
35+
3236
CFA_V1 = IConstantFlowAgreementV1(_icfa);
3337
minLower = _minLower;
3438
minUpper = _minUpper;
@@ -149,6 +153,20 @@ contract StrollManager is IStrollManager, Ownable {
149153
}
150154
}
151155

156+
/// @dev IStrollManager.setLimits implementation.
157+
function setLimits(uint64 _lowerLimit, uint64 _upperLimit)
158+
external
159+
onlyOwner
160+
{
161+
if (_lowerLimit >= _upperLimit)
162+
revert WrongLimits(_lowerLimit, _upperLimit);
163+
164+
minLower = _lowerLimit;
165+
minUpper = _upperLimit;
166+
167+
emit LimitsChanged(_lowerLimit, _upperLimit);
168+
}
169+
152170
/// @dev IStrollManager.getTopUp implementation.
153171
function getTopUp(
154172
address _user,
@@ -194,7 +212,7 @@ contract StrollManager is IStrollManager, Ownable {
194212
TopUp storage topUp = topUps[_index];
195213

196214
address user = topUp.user;
197-
215+
198216
if (user != msg.sender && topUp.expiry >= block.timestamp)
199217
revert UnauthorizedCaller(msg.sender, user);
200218

@@ -244,8 +262,12 @@ contract StrollManager is IStrollManager, Ownable {
244262
uint256 superBalance = topUp.superToken.balanceOf(topUp.user);
245263
uint256 positiveFlowRate = uint256(uint96(-1 * flowRate));
246264

247-
if (superBalance <= (positiveFlowRate * topUp.lowerLimit)) {
248-
return positiveFlowRate * topUp.upperLimit;
265+
// Selecting max between user defined limits and global limits.
266+
uint64 maxLowerLimit = (topUp.lowerLimit < minLower)? minLower: topUp.lowerLimit;
267+
uint64 maxUpperLimit = (topUp.upperLimit < minUpper)? minUpper: topUp.upperLimit;
268+
269+
if (superBalance <= (positiveFlowRate * maxLowerLimit)) {
270+
return positiveFlowRate * maxUpperLimit;
249271
}
250272
}
251273

smart-contracts/contracts/interfaces/IStrollManager.sol

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,17 @@ interface IStrollManager {
1515
uint256 lowerLimit,
1616
uint256 upperLimit
1717
);
18-
event TopUpDeleted(bytes32 indexed id, address indexed user, address indexed superToken, address strategy, address liquidityToken);
18+
event TopUpDeleted(
19+
bytes32 indexed id,
20+
address indexed user,
21+
address indexed superToken,
22+
address strategy,
23+
address liquidityToken
24+
);
1925
event PerformedTopUp(bytes32 indexed id, uint256 topUpAmount);
2026
event AddedApprovedStrategy(address indexed strategy);
2127
event RemovedApprovedStrategy(address indexed strategy);
28+
event LimitsChanged(uint64 lowerLimit, uint64 upperLimit);
2229

2330
/// Custom error to indicate that null address has been passed.
2431
error ZeroAddress();
@@ -50,6 +57,11 @@ interface IStrollManager {
5057
/// @param minLimit Minimum limit (upper/lower) expected.
5158
error InsufficientLimits(uint64 limitGiven, uint64 minLimit);
5259

60+
/// Custom error to indicate that the limits are wrong (lower limit >= upper limit).
61+
/// @param lowerLimit Limit (upper/lower) given by the user.
62+
/// @param upperLimit Minimum limit (upper/lower) expected.
63+
error WrongLimits(uint64 lowerLimit, uint64 upperLimit);
64+
5365
/**
5466
* @notice Struct representing a top-up.
5567
* @param user Address of the user who created the top-up.
@@ -82,6 +94,15 @@ interface IStrollManager {
8294
*/
8395
function removeApprovedStrategy(address _strategy) external;
8496

97+
/**
98+
* @notice Sets the global limits for top-ups.
99+
* @param _lowerLimit Triggers top up if stream can't be continued for this amount of seconds.
100+
* @param _upperLimit Increase supertoken balance to continue stream for this amount of seconds.
101+
* @dev If the previous top-ups don't adhere to the current global limits, the global limits will be enforced.
102+
* i.e., max(global limit, user defined limit) is always taken.
103+
*/
104+
function setLimits(uint64 _lowerLimit, uint64 _upperLimit) external;
105+
85106
/**
86107
* @notice Creates a new top up task.
87108
* @param _superToken The supertoken to monitor/top up.
@@ -118,7 +139,10 @@ interface IStrollManager {
118139
* @param _index Index of top up.
119140
* @return The top up.
120141
*/
121-
function getTopUpByIndex(bytes32 _index) external view returns (TopUp memory);
142+
function getTopUpByIndex(bytes32 _index)
143+
external
144+
view
145+
returns (TopUp memory);
122146

123147
/**
124148
* @notice Gets a top up by index.
@@ -138,7 +162,10 @@ interface IStrollManager {
138162
* @param _index Index of top up.
139163
* @return _amount The amount of supertoken to top up.
140164
*/
141-
function checkTopUpByIndex(bytes32 _index) external view returns (uint256 _amount);
165+
function checkTopUpByIndex(bytes32 _index)
166+
external
167+
view
168+
returns (uint256 _amount);
142169

143170
/**
144171
* @notice Checks if a top up is required.

smart-contracts/test/StrollManager.test.js

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
/* eslint-disable no-undef */
44

55
const { parseUnits } = require("@ethersproject/units");
6-
const { expect } = require("chai");
6+
const { expect, assert } = require("chai");
77

88
const zeroAddress = "0x0000000000000000000000000000000000000000";
99
const helper = require("./../helpers/helpers");
1010
const devEnv = require("./utils/setEnv");
1111

12-
const MIN_LOWER = 2;
13-
const MIN_UPPER = 7;
12+
const MIN_LOWER = helper.getSeconds(2);
13+
const MIN_UPPER = helper.getSeconds(5);
1414

1515
let accounts, owner, user, streamReceiver;
1616
let env;
@@ -370,16 +370,24 @@ describe("#3 - StrollManager: Register TopUps", function () {
370370
strategy.address,
371371
dai.address,
372372
expiry + 1000,
373-
20,
374-
20
373+
helper.getSeconds(20),
374+
helper.getSeconds(20)
375375
);
376376
const topUp = await strollManager.getTopUp(
377377
user.address,
378378
daix.address,
379379
dai.address
380380
);
381-
assert.equal(topUp.lowerLimit, 20, "wrong lowerLimit on update");
382-
assert.equal(topUp.upperLimit, 20, "wrong upperLimit on update");
381+
assert.equal(
382+
topUp.lowerLimit,
383+
helper.getSeconds(20),
384+
"wrong lowerLimit on update"
385+
);
386+
assert.equal(
387+
topUp.upperLimit,
388+
helper.getSeconds(20),
389+
"wrong upperLimit on update"
390+
);
383391
assert.equal(topUp.expiry, expiry + 1000, "wrong expiry on update");
384392
});
385393
});
@@ -799,4 +807,68 @@ describe("#6 - perform Top Up", function () {
799807
strollManager.performTopUp(user.address, daix.address, dai.address)
800808
).to.be.revertedWith(`TopUpNotRequired("${result}")`);
801809
});
810+
it("Case #6.4 - TopUp using max values (global limits)", async () => {
811+
const flowRate = parseUnits("300", 18).div(
812+
helper.getBigNumber(helper.getSeconds(30))
813+
);
814+
await strollManager
815+
.connect(user)
816+
.createTopUp(
817+
daix.address,
818+
strategy.address,
819+
dai.address,
820+
helper.getTimeStampNow() + helper.getSeconds(365),
821+
helper.getSeconds(5),
822+
helper.getSeconds(5)
823+
);
824+
825+
let tx = await strollManager.setLimits(
826+
helper.getSeconds(6),
827+
helper.getSeconds(8)
828+
);
829+
const limitsChangedEvent = await helper.getEvents(tx, "LimitsChanged");
830+
assert.equal(
831+
limitsChangedEvent[0].args.lowerLimit,
832+
helper.getSeconds(6),
833+
"wrong lower limit"
834+
);
835+
assert.equal(
836+
limitsChangedEvent[0].args.upperLimit,
837+
helper.getSeconds(8),
838+
"wrong upper limit"
839+
);
840+
841+
// approve superToken
842+
await dai.connect(user).approve(daix.address, parseUnits("10000", 18));
843+
// approve strategy
844+
await dai.connect(user).approve(strategy.address, parseUnits("10000", 18));
845+
// get some superToken
846+
await daix.connect(user).upgrade(parseUnits("20", 18));
847+
await createStream(daix, user, streamReceiver, flowRate.toString(), "0x");
848+
849+
let balance = await daix.balanceOf(user.address);
850+
console.log("Balance before increase time: ", balance.toString());
851+
852+
await helper.increaseTime(3600 * 24 * 5);
853+
854+
balance = await daix.balanceOf(user.address);
855+
console.log("Balance after increase time: ", balance.toString());
856+
857+
tx = await strollManager.performTopUp(
858+
user.address,
859+
daix.address,
860+
dai.address
861+
);
862+
863+
const TopUpEvent = await helper.getEvents(tx, "PerformedTopUp");
864+
const after = await daix.balanceOf(user.address);
865+
866+
console.log("After: ", after.toString());
867+
868+
expect(after.sub(balance)).to.be.closeTo(
869+
TopUpEvent[0].args.topUpAmount,
870+
parseUnits("0.01", 18)
871+
);
872+
assert.isAbove(after, balance, "balance should go up");
873+
});
802874
});

0 commit comments

Comments
 (0)