@@ -26,6 +26,10 @@ contract AggregationModePaymentService is Initializable, OwnableUpgradeable, UUP
2626 /// @notice The amount of subscriptions for the current month
2727 uint256 public monthlySubscriptionsAmount;
2828
29+ /// @notice Maximum amount of time (in seconds) an address can be subscribed ahead of the current block timestamp.
30+ /// Prevents stacking multiple short subscriptions and paying them over an extended period.
31+ uint256 public maxSubscriptionTimeAhead;
32+
2933 /// @notice The amount of addresses currently subscribed. expirationTime is UTC seconds, to be
3034 /// compared against block timestamps
3135 mapping (address subscriber = > uint256 expirationTime ) public subscribedAddresses;
@@ -55,6 +59,10 @@ contract AggregationModePaymentService is Initializable, OwnableUpgradeable, UUP
5559 /// @param newSubscriptionsAmount the new monthly subscription amount.
5660 event MonthlySubscriptionsAmountUpdated (uint256 indexed newSubscriptionsAmount );
5761
62+ /// @notice Event emitted when the max subscription time ahead is updated
63+ /// @param newMaxSubscriptionTimeAhead the max time allowed to subscribe ahead the current timestamp.
64+ event MaxSubscriptionTimeAheadUpdated (uint256 indexed newMaxSubscriptionTimeAhead );
65+
5866 /// @notice Event emitted when the funds recipient is updated
5967 /// @param newFundsRecipient the new address for receiving the funds on withdrawal.
6068 event FundsRecipientUpdated (address indexed newFundsRecipient );
@@ -68,7 +76,7 @@ contract AggregationModePaymentService is Initializable, OwnableUpgradeable, UUP
6876
6977 error SubscriptionLimitReached (uint256 subscriptionLimit );
7078
71- error SubscriptionNotExpired (uint256 expiration , uint256 currentTime );
79+ error SubscriptionTimeExceedsLimit (uint256 newSubscriptionTime , uint256 timeLimit );
7280
7381 /**
7482 * @notice Disables initializers for the implementation contract.
@@ -91,7 +99,8 @@ contract AggregationModePaymentService is Initializable, OwnableUpgradeable, UUP
9199 address _paymentFundsRecipient ,
92100 uint256 _amountToPayInWei ,
93101 uint256 _paymentExpirationTimeSeconds ,
94- uint256 _subscriptionLimit
102+ uint256 _subscriptionLimit ,
103+ uint256 _maxSubscriptionTimeAhead
95104 ) public initializer {
96105 __Ownable_init ();
97106 __UUPSUpgradeable_init ();
@@ -101,6 +110,7 @@ contract AggregationModePaymentService is Initializable, OwnableUpgradeable, UUP
101110 amountToPayInWei = _amountToPayInWei;
102111 paymentFundsRecipient = _paymentFundsRecipient;
103112 subscriptionLimit = _subscriptionLimit;
113+ maxSubscriptionTimeAhead = _maxSubscriptionTimeAhead;
104114 }
105115
106116 /**
@@ -162,6 +172,16 @@ contract AggregationModePaymentService is Initializable, OwnableUpgradeable, UUP
162172
163173 emit MonthlySubscriptionsAmountUpdated (newSubscriptionsAmount);
164174 }
175+
176+ /**
177+ * @notice Sets the max subscription time ahead to the value received by parameter. Only callable by the owner
178+ * @param newMaxSubscriptionTimeAhead max time allowed to subscribe ahead the current timestamp.
179+ */
180+ function setMaxSubscriptionTimeAhead (uint256 newMaxSubscriptionTimeAhead ) public onlyOwner () {
181+ maxSubscriptionTimeAhead = newMaxSubscriptionTimeAhead;
182+
183+ emit MaxSubscriptionTimeAheadUpdated (newMaxSubscriptionTimeAhead);
184+ }
165185
166186 /**
167187 * @notice Adds an array of addresses to the payment map and emits the Payment event.
@@ -194,17 +214,12 @@ contract AggregationModePaymentService is Initializable, OwnableUpgradeable, UUP
194214 revert SubscriptionLimitReached (subscriptionLimit);
195215 }
196216
197- // Check if the user has already payed a subscription for this month
198- uint256 insertedExpiration = subscribedAddresses[msg .sender ];
199- if (insertedExpiration == 0 ) {
200- // this means the sender has not payed for a subscription before
201- subscribedAddresses[msg .sender ] = block .timestamp + paymentExpirationTimeSeconds;
202- } else if (insertedExpiration > block .timestamp ) {
203- // this means the sender has an expired subscription
204- subscribedAddresses[msg .sender ] = block .timestamp + paymentExpirationTimeSeconds;
205- } else {
206- // this means the sender has a subscription that has not expired yet
207- revert SubscriptionNotExpired (insertedExpiration, block .timestamp );
217+ subscribedAddresses[msg .sender ] = block .timestamp + paymentExpirationTimeSeconds;
218+
219+ uint256 newExpiration = subscribedAddresses[msg .sender ];
220+
221+ if (newExpiration - block .timestamp > maxSubscriptionTimeAhead) {
222+ revert SubscriptionTimeExceedsLimit (newExpiration, maxSubscriptionTimeAhead);
208223 }
209224
210225 ++ monthlySubscriptionsAmount;
0 commit comments