Skip to content

Commit

Permalink
wip: subscription manager draft
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec committed Apr 16, 2024
1 parent 851eb5e commit 91f5f21
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 3 deletions.
7 changes: 4 additions & 3 deletions contracts/contracts/coordination/ManagedAllowList.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import "./GlobalAllowList.sol";
import "./Coordinator.sol";

contract ManagedAllowList is GlobalAllowList {

mapping(bytes32 => uint256) public administrators; // TODO: Rename to allowances?

event AdministratorCapSet(uint32 indexed ritualId, address indexed _address, uint256 cap);
Expand Down Expand Up @@ -34,7 +33,10 @@ contract ManagedAllowList is GlobalAllowList {
address[] calldata addresses,
uint256 value
) internal {
require(coordinator.isRitualActive(ritualId), "Only active rituals can set administrator caps");
require(
coordinator.isRitualActive(ritualId),
"Only active rituals can set administrator caps"
);
for (uint256 i = 0; i < addresses.length; i++) {
administrators[lookupKey(ritualId, addresses[i])] = value;
emit AdministratorCapSet(ritualId, addresses[i], value);
Expand All @@ -55,5 +57,4 @@ contract ManagedAllowList is GlobalAllowList {
) external onlyCohortAuthority(ritualId) {
setAdministratorCaps(ritualId, addresses, 0);
}

}
118 changes: 118 additions & 0 deletions contracts/contracts/coordination/SubscriptionManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

pragma solidity ^0.8.0;

import "./ManagedAllowList.sol";

contract SubscriptionManager is ManagedAllowList {
struct Subscription {
address subscriber;
uint256 amount;
uint256 period; // Represents the end timestamp of the subscription
}

mapping(bytes32 => Subscription) public subscriptions;

event SubscriptionCreated(
uint32 indexed ritualId,
address indexed subscriber,
uint256 amount,
uint256 period
);
event SubscriptionTerminated(uint32 indexed ritualId, address indexed subscriber);
event SubscriptionRenewed(
uint32 indexed ritualId,
address indexed subscriber,
uint256 amount,
uint256 period
);

function createSubscription(
uint32 ritualId,
address _subscriber,
uint256 _amount,
uint256 _period
) external onlyCohortAuthority(ritualId) {
bytes32 key = lookupKey(ritualId, _subscriber);
require(
subscriptions[key].subscriber == address(0),
"Subscriber already has an active subscription"
);

Subscription memory newSubscription = Subscription({
subscriber: _subscriber,
amount: _amount,
period: _period
});

subscriptions[key] = newSubscription;

emit SubscriptionCreated(ritualId, _subscriber, _amount, _period);
}

function terminateSubscription(
uint32 ritualId,
address _subscriber
) external onlySubscriber(ritualId, _subscriber) {
bytes32 key = lookupKey(ritualId, _subscriber);
require(
subscriptions[key].subscriber != address(0),
"No active subscription found for the subscriber"
);

delete subscriptions[key];

emit SubscriptionTerminated(ritualId, _subscriber);

// TODO: Return the _amount to the subscriber. Is it a native asset or ERC20?
}

// TODO: Handle a native asset or ERC20 as _amount
function renewSubscription(
uint32 ritualId,
address _subscriber,
uint256 _amount,
uint256 _period
) external onlyCohortAuthority(ritualId) {
bytes32 key = lookupKey(ritualId, _subscriber);
require(
subscriptions[key].subscriber != address(0),
"No active subscription found for the subscriber"
);

Subscription storage subscription = subscriptions[key];
subscription.amount = _amount;
subscription.period = _period;

emit SubscriptionRenewed(ritualId, _subscriber, _amount, _period);
}

function _beforeIsAuthorized(
uint32 ritualId,
bytes memory evidence,
bytes memory ciphertextHeader
) internal view override {
bytes32 digest = keccak256(ciphertextHeader);
address recoveredAddress = digest.toEthSignedMessageHash().recover(evidence);
Subscription memory subscription = subscriptions[lookupKey(ritualId, recoveredAddress)];
require(
subscription.subscriber != address(0) && subscription.period >= block.timestamp,
"Subscriber is not authorized or subscription has expired"
);
}

// TODO: What do I do with the `bool value`?
function _beforeSetAuthorization(
uint32 ritualId,
address[] calldata addresses,
bool value

Check failure on line 108 in contracts/contracts/coordination/SubscriptionManager.sol

View workflow job for this annotation

GitHub Actions / linting

Variable "value" is unused
) internal override {
for (uint256 i = 0; i < addresses.length; i++) {
Subscription memory subscription = subscriptions[lookupKey(ritualId, addresses[i])];
require(
subscription.subscriber != address(0) && subscription.period >= block.timestamp,
"Subscriber is not authorized or subscription has expired"
);
}
}
}

0 comments on commit 91f5f21

Please sign in to comment.