Skip to content

Commit

Permalink
refactor: remove subscriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
0xChin committed Oct 10, 2024
1 parent b327f6a commit 5183061
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 389 deletions.
150 changes: 6 additions & 144 deletions src/contracts/Grateful.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,9 @@ contract Grateful is IGrateful, Ownable2Step {
/// @inheritdoc IGrateful
mapping(address => mapping(address => uint256)) public shares;

mapping(uint256 => Subscription) public subscriptions;

/// @inheritdoc IGrateful
mapping(address => bool) public oneTimePayments;

/// @inheritdoc IGrateful
uint256 public subscriptionCount;

/// @inheritdoc IGrateful
uint256 public fee;

Expand Down Expand Up @@ -140,16 +135,7 @@ contract Grateful is IGrateful, Ownable2Step {
uint256 _amount,
uint256 _id
) external onlyWhenTokenWhitelisted(_token) {
_processPayment(
msg.sender,
_merchant,
_token,
_amount,
_id,
0, // 0 because no subscription is involved
new address[](0),
new uint256[](0)
);
_processPayment(msg.sender, _merchant, _token, _amount, _id, new address[](0), new uint256[](0));
}

/// @inheritdoc IGrateful
Expand All @@ -161,129 +147,7 @@ contract Grateful is IGrateful, Ownable2Step {
address[] calldata _recipients,
uint256[] calldata _percentages
) external onlyWhenTokenWhitelisted(_token) {
_processPayment(
msg.sender,
_merchant,
_token,
_amount,
_id,
0, // 0 because no subscription is involved
_recipients,
_percentages
);
}

/// @inheritdoc IGrateful
function subscribe(
address _token,
address _receiver,
uint256 _amount,
uint256 _subscriptionPlanId,
uint40 _interval,
uint16 _paymentsAmount,
address[] memory _recipients,
uint256[] memory _percentages
) public onlyWhenTokenWhitelisted(_token) returns (uint256 subscriptionId) {
if (_recipients.length != _percentages.length) {
revert Grateful_MismatchedArrays();
}

subscriptionId = subscriptionCount++;

// Store the subscription details
Subscription storage subscription = subscriptions[subscriptionId];
subscription.token = _token;
subscription.sender = msg.sender;
subscription.amount = _amount;
subscription.subscriptionPlanId = _subscriptionPlanId;
subscription.receiver = _receiver;
subscription.interval = _interval;
subscription.paymentsAmount = _paymentsAmount - 1;
subscription.lastPaymentTime = uint40(block.timestamp);
subscription.recipients = _recipients;
subscription.percentages = _percentages;

// Precompute paymentId
uint256 paymentId = calculateId(msg.sender, _receiver, _token, _amount);

emit SubscriptionCreated(subscriptionId, msg.sender, _receiver, _amount, _subscriptionPlanId);

// Call _processPayment
_processPayment(msg.sender, _receiver, _token, _amount, paymentId, subscriptionId, _recipients, _percentages);
}

/// @inheritdoc IGrateful
function subscribe(
address _token,
address _receiver,
uint256 _amount,
uint256 _subscriptionPlanId,
uint40 _interval,
uint16 _paymentsAmount
) external onlyWhenTokenWhitelisted(_token) returns (uint256 subscriptionId) {
return subscribe(
_token, _receiver, _amount, _subscriptionPlanId, _interval, _paymentsAmount, new address[](0), new uint256[](0)
);
}

/// @inheritdoc IGrateful
function processSubscription(
uint256 subscriptionId
) external {
Subscription storage subscription = subscriptions[subscriptionId];

if (subscription.amount == 0) {
revert Grateful_SubscriptionDoesNotExist();
}
if (block.timestamp < subscription.lastPaymentTime + subscription.interval) {
revert Grateful_TooEarlyForNextPayment();
}
if (subscription.paymentsAmount == 0) {
revert Grateful_PaymentsAmountReached();
}

_processPayment(
subscription.sender,
subscription.receiver,
subscription.token,
subscription.amount,
calculateId(subscription.sender, subscription.receiver, subscription.token, subscription.amount),
subscriptionId,
subscription.recipients,
subscription.percentages
);
subscription.lastPaymentTime = uint40(block.timestamp);
subscription.paymentsAmount--;
}

/// @inheritdoc IGrateful
function extendSubscription(uint256 subscriptionId, uint16 additionalPayments) external {
Subscription storage subscription = subscriptions[subscriptionId];

if (subscription.amount == 0) {
revert Grateful_SubscriptionDoesNotExist();
}
if (subscription.sender != msg.sender) {
revert Grateful_OnlySenderCanExtendSubscription();
}

subscription.paymentsAmount += additionalPayments;
}

/// @inheritdoc IGrateful
function cancelSubscription(
uint256 subscriptionId
) external {
Subscription storage subscription = subscriptions[subscriptionId];

if (subscription.amount == 0) {
revert Grateful_SubscriptionDoesNotExist();
}
if (subscription.sender != msg.sender && subscription.receiver != msg.sender) {
revert Grateful_OnlySenderOrReceiverCanCancelSubscription();
}

delete subscriptions[subscriptionId];
_processPayment(msg.sender, _merchant, _token, _amount, _id, _recipients, _percentages);
}

/// @inheritdoc IGrateful
Expand Down Expand Up @@ -316,7 +180,7 @@ contract Grateful is IGrateful, Ownable2Step {
if (!oneTimePayments[msg.sender]) {
revert Grateful_OneTimeNotFound();
}
_processPayment(msg.sender, _merchant, _token, _amount, _paymentId, 0, _recipients, _percentages);
_processPayment(msg.sender, _merchant, _token, _amount, _paymentId, _recipients, _percentages);
}

/// @inheritdoc IGrateful
Expand Down Expand Up @@ -368,7 +232,7 @@ contract Grateful is IGrateful, Ownable2Step {
for (uint256 i = 0; i < _tokens.length; i++) {
if (_tokens[i].balanceOf(msg.sender) >= _amount) {
_processPayment(
msg.sender, _merchant, address(_tokens[i]), _amount, _paymentId, 0, new address[](0), new uint256[](0)
msg.sender, _merchant, address(_tokens[i]), _amount, _paymentId, new address[](0), new uint256[](0)
);
}
}
Expand Down Expand Up @@ -427,8 +291,7 @@ contract Grateful is IGrateful, Ownable2Step {
* @param _merchant Address of the merchant.
* @param _token Address of the token.
* @param _amount Amount of the token.
* @param _paymentId ID of the payment.
* @param _subscriptionId ID of the subscription, 0 if it is one-time.
* @param _paymentId ID of the payment
* @param _recipients List of recipients for payment splitting.
* @param _percentages Corresponding percentages for each recipient.
*/
Expand All @@ -438,7 +301,6 @@ contract Grateful is IGrateful, Ownable2Step {
address _token,
uint256 _amount,
uint256 _paymentId,
uint256 _subscriptionId,
address[] memory _recipients,
uint256[] memory _percentages
) internal {
Expand Down Expand Up @@ -504,6 +366,6 @@ contract Grateful is IGrateful, Ownable2Step {
}
}

emit PaymentProcessed(_sender, _merchant, _token, _amount, yieldingFunds[_merchant], _paymentId, _subscriptionId);
emit PaymentProcessed(_sender, _merchant, _token, _amount, yieldingFunds[_merchant], _paymentId);
}
}
113 changes: 2 additions & 111 deletions src/interfaces/IGrateful.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,32 +11,6 @@ import {AaveV3ERC4626, IPool} from "yield-daddy/aave-v3/AaveV3ERC4626.sol";
* @notice Interface for the Grateful contract that allows payments in whitelisted tokens with optional yield via AAVE.
*/
interface IGrateful {
/*//////////////////////////////////////////////////////////////
STRUCTS
//////////////////////////////////////////////////////////////*/

struct Subscription {
address token;
address sender;
uint256 amount;
uint256 subscriptionPlanId;
address receiver;
uint40 interval;
uint16 paymentsAmount;
uint40 lastPaymentTime;
address[] recipients;
uint256[] percentages;
}

struct PaymentDetails {
address merchant;
address token;
uint256 amount;
uint256 id;
address[] recipients;
uint256[] percentages;
}

/*///////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
Expand All @@ -48,17 +22,15 @@ interface IGrateful {
* @param token Address of the token.
* @param amount Amount of the token.
* @param yielded Indicates if the payment was yielded.
* @param paymentId ID of the payment.
* @param subscriptionId ID of the subscription.
* @param paymentId ID of the payment
*/
event PaymentProcessed(
address indexed sender,
address indexed merchant,
address indexed token,
uint256 amount,
bool yielded,
uint256 paymentId,
uint256 subscriptionId
uint256 paymentId
);

/**
Expand All @@ -69,14 +41,6 @@ interface IGrateful {
*/
event OneTimePaymentCreated(address indexed merchant, address[] indexed tokens, uint256 amount);

event SubscriptionCreated(
uint256 indexed subscriptionId,
address indexed sender,
address indexed receiver,
uint256 amount,
uint256 subscriptionPlanId
);

/*///////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
Expand All @@ -96,24 +60,9 @@ interface IGrateful {
/// @notice Thrown when a token transfer fails.
error Grateful_TransferFailed();

/// @notice Thrown when the subscription does not exist.
error Grateful_SubscriptionDoesNotExist();

/// @notice Thrown when it's too early for the next subscription payment.
error Grateful_TooEarlyForNextPayment();

/// @notice Thrown when the maximum number of payments has been reached.
error Grateful_PaymentsAmountReached();

/// @notice Thrown when the one-time payment is not found.
error Grateful_OneTimeNotFound();

/// @notice Thrown when only the sender or receiver can cancel the subscription.
error Grateful_OnlySenderOrReceiverCanCancelSubscription();

/// @notice Thrown when only the sender can extend subscription.
error Grateful_OnlySenderCanExtendSubscription();

/*///////////////////////////////////////////////////////////////
VARIABLES
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -155,10 +104,6 @@ interface IGrateful {
address _address
) external view returns (bool);

/// @notice Returns the total number of subscriptions.
/// @return Number of subscriptions.
function subscriptionCount() external view returns (uint256);

/// @notice Returns the fee applied to the payments.
/// @return Fee in basis points (10000 = 100%).
function fee() external view returns (uint256);
Expand Down Expand Up @@ -209,60 +154,6 @@ interface IGrateful {
uint256[] calldata _percentages
) external;

/**
* @notice Subscribes to a service with recurring payments.
* @param _token Address of the token.
* @param _receiver Address of the payment receiver.
* @param _amount Amount per payment.
* @param _interval Interval in seconds between payments.
* @param _paymentsAmount Total number of payments.
* @param _recipients List of recipients for payment splitting.
* @param _percentages Corresponding percentages for each recipient.
* @return subscriptionId ID of the created subscription.
*/
function subscribe(
address _token,
address _receiver,
uint256 _amount,
uint256 _subscriptionPlanId,
uint40 _interval,
uint16 _paymentsAmount,
address[] calldata _recipients,
uint256[] calldata _percentages
) external returns (uint256 subscriptionId);

/**
* @notice Subscribes to a service with recurring payments.
* @param _token Address of the token.
* @param _receiver Address of the payment receiver.
* @param _amount Amount per payment.
* @param _interval Interval in seconds between payments.
* @param _paymentsAmount Total number of payments.
* @return subscriptionId ID of the created subscription.
*/
function subscribe(
address _token,
address _receiver,
uint256 _amount,
uint256 _subscriptionPlanId,
uint40 _interval,
uint16 _paymentsAmount
) external returns (uint256 subscriptionId);

function cancelSubscription(
uint256 subscriptionId
) external;

function extendSubscription(uint256 subscriptionId, uint16 additionalPayments) external;

/**
* @notice Processes a subscription payment.
* @param subscriptionId ID of the subscription.
*/
function processSubscription(
uint256 subscriptionId
) external;

/**
* @notice Creates a one-time payment.
* @param _merchant Address of the merchant.
Expand Down
Loading

0 comments on commit 5183061

Please sign in to comment.