Skip to content

Commit

Permalink
chore: remove payment splitting logic
Browse files Browse the repository at this point in the history
  • Loading branch information
0xChin committed Nov 11, 2024
1 parent 3321cc9 commit 49ca3af
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 306 deletions.
157 changes: 20 additions & 137 deletions src/contracts/Grateful.sol
Original file line number Diff line number Diff line change
Expand Up @@ -151,72 +151,7 @@ contract Grateful is IGrateful, Ownable2Step {
uint256 _amount,
uint256 _id
) external onlyWhenTokenWhitelisted(_token) {
_processPayment(msg.sender, _merchant, _token, _amount, _id, new address[](0), new uint256[](0));
}

/// @inheritdoc IGrateful
function pay(
address _merchant,
address _token,
uint256 _amount,
uint256 _id,
address[] calldata _recipients,
uint256[] calldata _percentages
) external onlyWhenTokenWhitelisted(_token) {
_processPayment(msg.sender, _merchant, _token, _amount, _id, _recipients, _percentages);
}

/// @inheritdoc IGrateful
function createOneTimePayment(
address _merchant,
address[] memory _tokens,
uint256 _amount,
uint256 _salt,
uint256 _paymentId,
address precomputed,
address[] calldata _recipients,
uint256[] calldata _percentages
) external onlyWhenTokensWhitelisted(_tokens) returns (OneTime oneTime) {
oneTimePayments[precomputed] = true;
oneTime = new OneTime{salt: bytes32(_salt)}(
IGrateful(address(this)), _tokens, _merchant, _amount, _paymentId, _recipients, _percentages
);
emit OneTimePaymentCreated(_merchant, _tokens, _amount);
}

/// @inheritdoc IGrateful
function receiveOneTimePayment(
address _merchant,
address _token,
uint256 _paymentId,
uint256 _amount,
address[] calldata _recipients,
uint256[] calldata _percentages
) external {
if (!oneTimePayments[msg.sender]) {
revert Grateful_OneTimeNotFound();
}
_processPayment(msg.sender, _merchant, _token, _amount, _paymentId, _recipients, _percentages);
}

/// @inheritdoc IGrateful
function computeOneTimeAddress(
address _merchant,
address[] memory _tokens,
uint256 _amount,
uint256 _salt,
uint256 _paymentId,
address[] calldata _recipients,
uint256[] calldata _percentages
) external view returns (OneTime oneTime) {
bytes memory bytecode = abi.encodePacked(
type(OneTime).creationCode,
abi.encode(address(this), _tokens, _merchant, _amount, _paymentId, _recipients, _percentages)
);
bytes32 bytecodeHash = keccak256(bytecode);
bytes32 addressHash = keccak256(abi.encodePacked(bytes1(0xff), address(this), bytes32(_salt), bytecodeHash));
address computedAddress = address(uint160(uint256(addressHash)));
return OneTime(computedAddress);
_processPayment(msg.sender, _merchant, _token, _amount, _id);
}

/// @inheritdoc IGrateful
Expand All @@ -229,29 +164,16 @@ contract Grateful is IGrateful, Ownable2Step {
address precomputed
) external onlyWhenTokensWhitelisted(_tokens) returns (OneTime oneTime) {
oneTimePayments[precomputed] = true;
oneTime = new OneTime{salt: bytes32(_salt)}(
IGrateful(address(this)), _tokens, _merchant, _amount, _paymentId, new address[](0), new uint256[](0)
);
oneTime = new OneTime{salt: bytes32(_salt)}(IGrateful(address(this)), _tokens, _merchant, _amount, _paymentId);
emit OneTimePaymentCreated(_merchant, _tokens, _amount);
}

/// @inheritdoc IGrateful
function receiveOneTimePayment(
address _merchant,
IERC20[] memory _tokens,
uint256 _paymentId,
uint256 _amount
) external {
function receiveOneTimePayment(address _merchant, address _token, uint256 _paymentId, uint256 _amount) external {
if (!oneTimePayments[msg.sender]) {
revert Grateful_OneTimeNotFound();
}
for (uint256 i = 0; i < _tokens.length; i++) {
if (_tokens[i].balanceOf(msg.sender) >= _amount) {
_processPayment(
msg.sender, _merchant, address(_tokens[i]), _amount, _paymentId, new address[](0), new uint256[](0)
);
}
}
_processPayment(msg.sender, _merchant, _token, _amount, _paymentId);
}

/// @inheritdoc IGrateful
Expand All @@ -262,10 +184,8 @@ contract Grateful is IGrateful, Ownable2Step {
uint256 _salt,
uint256 _paymentId
) external view returns (OneTime oneTime) {
bytes memory bytecode = abi.encodePacked(
type(OneTime).creationCode,
abi.encode(address(this), _tokens, _merchant, _amount, _paymentId, new address[](0), new uint256[](0))
);
bytes memory bytecode =
abi.encodePacked(type(OneTime).creationCode, abi.encode(address(this), _tokens, _merchant, _amount, _paymentId));
bytes32 bytecodeHash = keccak256(bytecode);
bytes32 addressHash = keccak256(abi.encodePacked(bytes1(0xff), address(this), bytes32(_salt), bytecodeHash));
address computedAddress = address(uint160(uint256(addressHash)));
Expand Down Expand Up @@ -379,18 +299,14 @@ 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 _recipients List of recipients for payment splitting.
* @param _percentages Corresponding percentages for each recipient.
* @param _paymentId ID of the payment
*/
function _processPayment(
address _sender,
address _merchant,
address _token,
uint256 _amount,
uint256 _paymentId,
address[] memory _recipients,
uint256[] memory _percentages
uint256 _paymentId
) internal {
// Transfer the full amount from the sender to this contract
IERC20(_token).safeTransferFrom(_sender, address(this), _amount);
Expand All @@ -400,61 +316,28 @@ contract Grateful is IGrateful, Ownable2Step {
revert Grateful_PaymentIdAlreadyUsed();
}

paymentIds[_paymentId] = true;

// Apply the fee
uint256 amountWithFee = applyFee(_merchant, _amount);

// Transfer fee to owner
IERC20(_token).safeTransfer(owner(), _amount - amountWithFee);

// If payment splitting is requested
if (_recipients.length > 0) {
if (_recipients.length != _percentages.length) {
revert Grateful_MismatchedArrays();
}
uint256 totalPercentage = 0;
for (uint256 i = 0; i < _percentages.length; i++) {
totalPercentage += _percentages[i];
}
if (totalPercentage != 10_000) {
revert Grateful_InvalidTotalPercentage();
}

// Distribute amountWithFee among recipients
for (uint256 i = 0; i < _recipients.length; i++) {
address recipient = _recipients[i];
uint256 recipientShare = (amountWithFee * _percentages[i]) / 10_000;

if (yieldingFunds[recipient]) {
AaveV3ERC4626 vault = vaults[_token];
if (address(vault) == address(0)) {
IERC20(_token).safeTransfer(recipient, recipientShare);
} else {
uint256 _shares = vault.deposit(recipientShare, address(this));
shares[recipient][_token] += _shares;
}
} else {
// Transfer tokens to recipient
IERC20(_token).safeTransfer(recipient, recipientShare);
}
}
} else {
// Proceed as before, paying the merchant
if (yieldingFunds[_merchant]) {
AaveV3ERC4626 vault = vaults[_token];
if (address(vault) == address(0)) {
IERC20(_token).safeTransfer(_merchant, amountWithFee);
} else {
uint256 _shares = vault.deposit(amountWithFee, address(this));
shares[_merchant][_token] += _shares;
}
} else {
// Transfer tokens to merchant
// Proceed as before, paying the merchant
if (yieldingFunds[_merchant]) {
AaveV3ERC4626 vault = vaults[_token];
if (address(vault) == address(0)) {
IERC20(_token).safeTransfer(_merchant, amountWithFee);
} else {
uint256 _shares = vault.deposit(amountWithFee, address(this));
shares[_merchant][_token] += _shares;
}
} else {
// Transfer tokens to merchant
IERC20(_token).safeTransfer(_merchant, amountWithFee);
}

paymentIds[_paymentId] = true;

emit PaymentProcessed(_sender, _merchant, _token, _amount, yieldingFunds[_merchant], _paymentId);
}
}
12 changes: 2 additions & 10 deletions src/contracts/OneTime.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,14 @@ contract OneTime {

IGrateful immutable grateful;

Check warning on line 14 in src/contracts/OneTime.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Explicitly mark visibility of state

Check warning on line 14 in src/contracts/OneTime.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

Immutable variables name should be capitalized SNAKE_CASE

Check warning on line 14 in src/contracts/OneTime.sol

View workflow job for this annotation

GitHub Actions / Lint Commit Messages

'grateful' should start with _

constructor(
IGrateful _grateful,
address[] memory _tokens,
address _merchant,
uint256 _amount,
uint256 _paymentId,
address[] memory _recipients,
uint256[] memory _percentages
) {
constructor(IGrateful _grateful, address[] memory _tokens, address _merchant, uint256 _amount, uint256 _paymentId) {
grateful = _grateful;

for (uint256 i = 0; i < _tokens.length; i++) {
IERC20 token = IERC20(_tokens[i]);
if (token.balanceOf(address(this)) >= _amount) {
token.safeIncreaseAllowance(address(_grateful), _amount);
_grateful.receiveOneTimePayment(_merchant, address(token), _paymentId, _amount, _recipients, _percentages);
_grateful.receiveOneTimePayment(_merchant, address(token), _paymentId, _amount);
}
}
}
Expand Down
89 changes: 2 additions & 87 deletions src/interfaces/IGrateful.sol
Original file line number Diff line number Diff line change
Expand Up @@ -177,47 +177,6 @@ interface IGrateful {
*/
function pay(address _merchant, address _token, uint256 _amount, uint256 _id) external;

/**
* @notice Makes a payment to a merchant with payment splitting.
* @param _merchant Address of the merchant receiving payment.
* @param _token Address of the token used for payment.
* @param _amount Amount of the token to be paid.
* @param _id ID of the payment.
* @param _recipients List of recipients for payment splitting.
* @param _percentages Corresponding percentages for each recipient (in basis points, 10000 = 100%).
*/
function pay(
address _merchant,
address _token,
uint256 _amount,
uint256 _id,
address[] calldata _recipients,
uint256[] calldata _percentages
) external;

/**
* @notice Creates a one-time payment with payment splitting.
* @param _merchant Address of the merchant.
* @param _tokens Array of token addresses.
* @param _amount Amount of the token.
* @param _salt Salt used for address computation.
* @param _paymentId ID of the payment.
* @param precomputed Precomputed address of the OneTime contract.
* @param _recipients List of recipients for payment splitting.
* @param _percentages Corresponding percentages for each recipient.
* @return oneTime Address of the created OneTime contract.
*/
function createOneTimePayment(
address _merchant,
address[] memory _tokens,
uint256 _amount,
uint256 _salt,
uint256 _paymentId,
address precomputed,
address[] calldata _recipients,
uint256[] calldata _percentages
) external returns (OneTime oneTime);

/**
* @notice Creates a one-time payment without payment splitting.
* @param _merchant Address of the merchant.
Expand All @@ -237,58 +196,14 @@ interface IGrateful {
address precomputed
) external returns (OneTime oneTime);

/**
* @notice Receives a one-time payment with payment splitting.
* @param _merchant Address of the merchant.
* @param _token Address of the token.
* @param _paymentId ID of the payment.
* @param _amount Amount of the token.
* @param _recipients List of recipients for payment splitting.
* @param _percentages Corresponding percentages for each recipient.
*/
function receiveOneTimePayment(
address _merchant,
address _token,
uint256 _paymentId,
uint256 _amount,
address[] calldata _recipients,
uint256[] calldata _percentages
) external;

/**
* @notice Receives a one-time payment without payment splitting.
* @param _merchant Address of the merchant.
* @param _tokens Array of token addresses.
* @param _token Token address.
* @param _paymentId ID of the payment.
* @param _amount Amount of the token.
*/
function receiveOneTimePayment(
address _merchant,
IERC20[] memory _tokens,
uint256 _paymentId,
uint256 _amount
) external;

/**
* @notice Computes the address of a one-time payment contract with payment splitting.
* @param _merchant Address of the merchant.
* @param _tokens Array of token addresses.
* @param _amount Amount of the token.
* @param _salt Salt used for address computation.
* @param _paymentId ID of the payment.
* @param _recipients List of recipients for payment splitting.
* @param _percentages Corresponding percentages for each recipient.
* @return oneTime Address of the computed OneTime contract.
*/
function computeOneTimeAddress(
address _merchant,
address[] memory _tokens,
uint256 _amount,
uint256 _salt,
uint256 _paymentId,
address[] calldata _recipients,
uint256[] calldata _percentages
) external view returns (OneTime oneTime);
function receiveOneTimePayment(address _merchant, address _token, uint256 _paymentId, uint256 _amount) external;

/**
* @notice Computes the address of a one-time payment contract without payment splitting.
Expand Down
Loading

0 comments on commit 49ca3af

Please sign in to comment.