Skip to content

Commit

Permalink
Merge pull request #31 from DAM-Protocol/issue12-fix
Browse files Browse the repository at this point in the history
Fixed issue 12 and modified tests.
  • Loading branch information
ngmachado authored Jun 20, 2022
2 parents a53a188 + ca2cfac commit 23ca766
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 13 deletions.
28 changes: 25 additions & 3 deletions smart-contracts/contracts/StrollManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "@openzeppelin/contracts/access/Ownable.sol";
import "./interfaces/IERC20Mod.sol";
import "./interfaces/IStrollManager.sol";


// solhint-disable not-rely-on-time
/// @title StrollManager
/// @author Harsh Prakash <[email protected]>
Expand All @@ -29,6 +30,9 @@ contract StrollManager is IStrollManager, Ownable {
uint64 _minLower,
uint64 _minUpper
) {
if (_icfa == address(0)) revert ZeroAddress();
if (_minLower >= _minUpper) revert WrongLimits(_minLower, _minUpper);

CFA_V1 = IConstantFlowAgreementV1(_icfa);
minLower = _minLower;
minUpper = _minUpper;
Expand Down Expand Up @@ -149,6 +153,20 @@ contract StrollManager is IStrollManager, Ownable {
}
}

/// @dev IStrollManager.setLimits implementation.
function setLimits(uint64 _lowerLimit, uint64 _upperLimit)
external
onlyOwner
{
if (_lowerLimit >= _upperLimit)
revert WrongLimits(_lowerLimit, _upperLimit);

minLower = _lowerLimit;
minUpper = _upperLimit;

emit LimitsChanged(_lowerLimit, _upperLimit);
}

/// @dev IStrollManager.getTopUp implementation.
function getTopUp(
address _user,
Expand Down Expand Up @@ -194,7 +212,7 @@ contract StrollManager is IStrollManager, Ownable {
TopUp storage topUp = topUps[_index];

address user = topUp.user;

if (user != msg.sender && topUp.expiry >= block.timestamp)
revert UnauthorizedCaller(msg.sender, user);

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

if (superBalance <= (positiveFlowRate * topUp.lowerLimit)) {
return positiveFlowRate * topUp.upperLimit;
// Selecting max between user defined limits and global limits.
uint64 maxLowerLimit = (topUp.lowerLimit < minLower)? minLower: topUp.lowerLimit;
uint64 maxUpperLimit = (topUp.upperLimit < minUpper)? minUpper: topUp.upperLimit;

if (superBalance <= (positiveFlowRate * maxLowerLimit)) {
return positiveFlowRate * maxUpperLimit;
}
}

Expand Down
33 changes: 30 additions & 3 deletions smart-contracts/contracts/interfaces/IStrollManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,17 @@ interface IStrollManager {
uint256 lowerLimit,
uint256 upperLimit
);
event TopUpDeleted(bytes32 indexed id, address indexed user, address indexed superToken, address strategy, address liquidityToken);
event TopUpDeleted(
bytes32 indexed id,
address indexed user,
address indexed superToken,
address strategy,
address liquidityToken
);
event PerformedTopUp(bytes32 indexed id, uint256 topUpAmount);
event AddedApprovedStrategy(address indexed strategy);
event RemovedApprovedStrategy(address indexed strategy);
event LimitsChanged(uint64 lowerLimit, uint64 upperLimit);

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

/// Custom error to indicate that the limits are wrong (lower limit >= upper limit).
/// @param lowerLimit Limit (upper/lower) given by the user.
/// @param upperLimit Minimum limit (upper/lower) expected.
error WrongLimits(uint64 lowerLimit, uint64 upperLimit);

/**
* @notice Struct representing a top-up.
* @param user Address of the user who created the top-up.
Expand Down Expand Up @@ -82,6 +94,15 @@ interface IStrollManager {
*/
function removeApprovedStrategy(address _strategy) external;

/**
* @notice Sets the global limits for top-ups.
* @param _lowerLimit Triggers top up if stream can't be continued for this amount of seconds.
* @param _upperLimit Increase supertoken balance to continue stream for this amount of seconds.
* @dev If the previous top-ups don't adhere to the current global limits, the global limits will be enforced.
* i.e., max(global limit, user defined limit) is always taken.
*/
function setLimits(uint64 _lowerLimit, uint64 _upperLimit) external;

/**
* @notice Creates a new top up task.
* @param _superToken The supertoken to monitor/top up.
Expand Down Expand Up @@ -118,7 +139,10 @@ interface IStrollManager {
* @param _index Index of top up.
* @return The top up.
*/
function getTopUpByIndex(bytes32 _index) external view returns (TopUp memory);
function getTopUpByIndex(bytes32 _index)
external
view
returns (TopUp memory);

/**
* @notice Gets a top up by index.
Expand All @@ -138,7 +162,10 @@ interface IStrollManager {
* @param _index Index of top up.
* @return _amount The amount of supertoken to top up.
*/
function checkTopUpByIndex(bytes32 _index) external view returns (uint256 _amount);
function checkTopUpByIndex(bytes32 _index)
external
view
returns (uint256 _amount);

/**
* @notice Checks if a top up is required.
Expand Down
86 changes: 79 additions & 7 deletions smart-contracts/test/StrollManager.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
/* eslint-disable no-undef */

const { parseUnits } = require("@ethersproject/units");
const { expect } = require("chai");
const { expect, assert } = require("chai");

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

const MIN_LOWER = 2;
const MIN_UPPER = 7;
const MIN_LOWER = helper.getSeconds(2);
const MIN_UPPER = helper.getSeconds(5);

let accounts, owner, user, streamReceiver;
let env;
Expand Down Expand Up @@ -370,16 +370,24 @@ describe("#3 - StrollManager: Register TopUps", function () {
strategy.address,
dai.address,
expiry + 1000,
20,
20
helper.getSeconds(20),
helper.getSeconds(20)
);
const topUp = await strollManager.getTopUp(
user.address,
daix.address,
dai.address
);
assert.equal(topUp.lowerLimit, 20, "wrong lowerLimit on update");
assert.equal(topUp.upperLimit, 20, "wrong upperLimit on update");
assert.equal(
topUp.lowerLimit,
helper.getSeconds(20),
"wrong lowerLimit on update"
);
assert.equal(
topUp.upperLimit,
helper.getSeconds(20),
"wrong upperLimit on update"
);
assert.equal(topUp.expiry, expiry + 1000, "wrong expiry on update");
});
});
Expand Down Expand Up @@ -799,4 +807,68 @@ describe("#6 - perform Top Up", function () {
strollManager.performTopUp(user.address, daix.address, dai.address)
).to.be.revertedWith(`TopUpNotRequired("${result}")`);
});
it("Case #6.4 - TopUp using max values (global limits)", async () => {
const flowRate = parseUnits("300", 18).div(
helper.getBigNumber(helper.getSeconds(30))
);
await strollManager
.connect(user)
.createTopUp(
daix.address,
strategy.address,
dai.address,
helper.getTimeStampNow() + helper.getSeconds(365),
helper.getSeconds(5),
helper.getSeconds(5)
);

let tx = await strollManager.setLimits(
helper.getSeconds(6),
helper.getSeconds(8)
);
const limitsChangedEvent = await helper.getEvents(tx, "LimitsChanged");
assert.equal(
limitsChangedEvent[0].args.lowerLimit,
helper.getSeconds(6),
"wrong lower limit"
);
assert.equal(
limitsChangedEvent[0].args.upperLimit,
helper.getSeconds(8),
"wrong upper limit"
);

// approve superToken
await dai.connect(user).approve(daix.address, parseUnits("10000", 18));
// approve strategy
await dai.connect(user).approve(strategy.address, parseUnits("10000", 18));
// get some superToken
await daix.connect(user).upgrade(parseUnits("20", 18));
await createStream(daix, user, streamReceiver, flowRate.toString(), "0x");

let balance = await daix.balanceOf(user.address);
console.log("Balance before increase time: ", balance.toString());

await helper.increaseTime(3600 * 24 * 5);

balance = await daix.balanceOf(user.address);
console.log("Balance after increase time: ", balance.toString());

tx = await strollManager.performTopUp(
user.address,
daix.address,
dai.address
);

const TopUpEvent = await helper.getEvents(tx, "PerformedTopUp");
const after = await daix.balanceOf(user.address);

console.log("After: ", after.toString());

expect(after.sub(balance)).to.be.closeTo(
TopUpEvent[0].args.topUpAmount,
parseUnits("0.01", 18)
);
assert.isAbove(after, balance, "balance should go up");
});
});

0 comments on commit 23ca766

Please sign in to comment.