-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: create
CardPaymentProcessor
v2 (#1)
- Loading branch information
1 parent
e353cc3
commit 79e98ef
Showing
34 changed files
with
22,095 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.20; | ||
|
||
import { ICardPaymentProcessorTypes } from "./interfaces/ICardPaymentProcessor.sol"; | ||
import { ICardPaymentCashbackTypes } from "./interfaces/ICardPaymentCashback.sol"; | ||
|
||
/// @title CardPaymentProcessor storage version 1 | ||
abstract contract CardPaymentProcessorStorageV1 is ICardPaymentProcessorTypes, ICardPaymentCashbackTypes { | ||
/// @dev The address of the underlying token. | ||
address internal _token; | ||
|
||
/// @dev The account to transfer confirmed tokens to. | ||
address internal _cashOutAccount; | ||
|
||
/// @dev The mapping of a payment for a given payment ID. | ||
mapping(bytes32 => Payment) internal _payments; | ||
|
||
/// @dev The payment statistics. | ||
PaymentStatistics internal _paymentStatistics; | ||
|
||
/// @dev The address of the cashback treasury. | ||
address internal _cashbackTreasury; | ||
|
||
/// @dev The enable flag of the cashback operations for new payments. Does not affect the existing payments. | ||
bool internal _cashbackEnabled; | ||
|
||
/// @dev The default cashback rate for new payments in units of `CASHBACK_FACTOR`. | ||
uint16 internal _cashbackRate; | ||
|
||
/// @dev The mapping of an account cashback structure for a given account address. | ||
mapping(address => AccountCashbackState) internal _accountCashbackStates; | ||
} | ||
|
||
/** | ||
* @title CardPaymentProcessor storage | ||
* @dev Contains storage variables of the {CardPaymentProcessor} contract. | ||
* | ||
* We are following Compound's approach of upgrading new contract implementations. | ||
* See https://github.com/compound-finance/compound-protocol. | ||
* When we need to add new storage variables, we create a new version of CardPaymentProcessorStorage | ||
* e.g. CardPaymentProcessorStorage<versionNumber>, so finally it would look like | ||
* "contract CardPaymentProcessorStorage is CardPaymentProcessorStorageV1, CardPaymentProcessorStorageV2". | ||
*/ | ||
abstract contract CardPaymentProcessorStorage is CardPaymentProcessorStorageV1 { | ||
/** | ||
* @dev This empty reserved space is put in place to allow future versions to add new | ||
* variables without shifting down storage in the inheritance chain. | ||
*/ | ||
uint256[43] private __gap; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.20; | ||
|
||
import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; | ||
|
||
/** | ||
* @title AccessControlExtUpgradeable base contract | ||
* @author CloudWalk Inc. | ||
* @dev Extends the OpenZeppelin's {AccessControlUpgradeable} contract by adding the `grantRoleBatch` and | ||
* `revokeRoleBatch` function. | ||
* | ||
* This contract is used through inheritance. It introduces the `grantRoleBatch` and `revokeRoleBatch` functions | ||
* that is allowed to grant and revoke roles in batch. | ||
*/ | ||
abstract contract AccessControlExtUpgradeable is AccessControlUpgradeable { | ||
// ------------------ Initializers ---------------------------- // | ||
|
||
/** | ||
* @dev The internal initializer of the upgradable contract. | ||
* | ||
* See details https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable. | ||
*/ | ||
function __AccessControlExt_init() internal onlyInitializing { | ||
__Context_init_unchained(); | ||
__ERC165_init_unchained(); | ||
__AccessControl_init_unchained(); | ||
|
||
__AccessControlExt_init_unchained(); | ||
} | ||
|
||
/** | ||
* @dev The unchained internal initializer of the upgradable contract. | ||
* | ||
* See {AccessControlExtUpgradeable-__AccessControlExt_init}. | ||
*/ | ||
function __AccessControlExt_init_unchained() internal onlyInitializing {} | ||
|
||
// ------------------ Functions ------------------------------- // | ||
|
||
/** | ||
* @dev Grants `role` to `account` in batch. | ||
* | ||
* If `accounts` had not been already granted `role`, emits a {RoleGranted} | ||
* event. | ||
* | ||
* Requirements: | ||
* | ||
* - the caller must have ``role``'s admin role. | ||
* | ||
* May emit a {RoleGranted} event for each account. | ||
*/ | ||
function grantRoleBatch(bytes32 role, address[] memory accounts) public virtual onlyRole(getRoleAdmin(role)) { | ||
for (uint i = 0; i < accounts.length; i++) { | ||
_grantRole(role, accounts[i]); | ||
} | ||
} | ||
|
||
/** | ||
* @dev Revokes `role` from `account` in batch. | ||
* | ||
* If `accounts` had been granted `role`, emits a {RoleRevoked} event. | ||
* | ||
* Requirements: | ||
* | ||
* - the caller must have ``role``'s admin role. | ||
* | ||
* May emit a {RoleRevoked} event for each account. | ||
*/ | ||
function revokeRoleBatch(bytes32 role, address[] memory accounts) public virtual onlyRole(getRoleAdmin(role)) { | ||
for (uint i = 0; i < accounts.length; i++) { | ||
_revokeRole(role, accounts[i]); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.20; | ||
|
||
import { AccessControlExtUpgradeable } from "./AccessControlExtUpgradeable.sol"; | ||
|
||
/** | ||
* @title BlocklistableUpgradeable base contract | ||
* @author CloudWalk Inc. | ||
* @dev Allows to blocklist and unblocklist accounts using the {BLOCKLISTER_ROLE} role. | ||
* | ||
* This contract is used through inheritance. It makes available the modifier `notBlocklisted`, | ||
* which can be applied to functions to restrict their usage to not blocklisted accounts only. | ||
*/ | ||
abstract contract BlocklistableUpgradeable is AccessControlExtUpgradeable { | ||
/// @dev The role of the blocklister that is allowed to blocklist and unblocklist accounts. | ||
bytes32 public constant BLOCKLISTER_ROLE = keccak256("BLOCKLISTER_ROLE"); | ||
|
||
/** | ||
* @dev The first storage slot of the contract data. | ||
* | ||
* Calculated as: | ||
* keccak256(abi.encode(uint256(keccak256("cloudwalk.storage.Blocklistable")) - 1)) & ~bytes32(uint256(0xff)) | ||
*/ | ||
bytes32 private constant BlocklistableStorageLocation = | ||
0x9a5d41467ec00b9c4ff3b10f2ab1b7fef3c7f16bd8fba9cd308a28e3cd7ef400; | ||
|
||
/** | ||
* @dev The structure that contains all the data of the Blocklistable contract. | ||
* @custom:storage-location erc7201:cloudwalk.storage.Blocklistable | ||
*/ | ||
struct BlocklistableStorage { | ||
mapping(address => bool) blocklisted; // Mapping of presence in the blocklist for a given address. | ||
} | ||
|
||
// ------------------ Events ---------------------------------- // | ||
|
||
/// @dev Emitted when an account is blocklisted. | ||
event Blocklisted(address indexed account); | ||
|
||
/// @dev Emitted when an account is unblocklisted. | ||
event UnBlocklisted(address indexed account); | ||
|
||
/// @dev Emitted when an account is self blocklisted. | ||
event SelfBlocklisted(address indexed account); | ||
|
||
// ------------------ Errors ---------------------------------- // | ||
|
||
/// @dev The account is blocklisted. | ||
error BlocklistedAccount(address account); | ||
|
||
// ------------------ Modifiers ------------------------------- // | ||
|
||
/** | ||
* @dev Throws if called by a blocklisted account. | ||
* @param account The address to check for presence in the blocklist. | ||
*/ | ||
modifier notBlocklisted(address account) { | ||
if (_getBlocklistableStorage().blocklisted[account]) { | ||
revert BlocklistedAccount(account); | ||
} | ||
_; | ||
} | ||
|
||
// ------------------ Initializers ---------------------------- // | ||
|
||
/** | ||
* @dev The internal initializer of the upgradable contract. | ||
* | ||
* See details https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable. | ||
*/ | ||
function __Blocklistable_init(bytes32 blocklisterRoleAdmin) internal onlyInitializing { | ||
__Context_init_unchained(); | ||
__ERC165_init_unchained(); | ||
__AccessControl_init_unchained(); | ||
__AccessControlExt_init_unchained(); | ||
|
||
__Blocklistable_init_unchained(blocklisterRoleAdmin); | ||
} | ||
|
||
/** | ||
* @dev The unchained internal initializer of the upgradable contract. | ||
* | ||
* See {BlocklistableUpgradeable-__Blocklistable_init}. | ||
*/ | ||
function __Blocklistable_init_unchained(bytes32 blocklisterRoleAdmin) internal onlyInitializing { | ||
_setRoleAdmin(BLOCKLISTER_ROLE, blocklisterRoleAdmin); | ||
} | ||
|
||
// ------------------ Functions ------------------------------- // | ||
|
||
/** | ||
* @dev Adds an account to the blocklist. | ||
* | ||
* Requirements: | ||
* | ||
* - The caller must have the {BLOCKLISTER_ROLE} role. | ||
* | ||
* Emits a {Blocklisted} event. | ||
* | ||
* @param account The address to blocklist. | ||
*/ | ||
function blocklist(address account) public onlyRole(BLOCKLISTER_ROLE) { | ||
BlocklistableStorage storage s = _getBlocklistableStorage(); | ||
if (s.blocklisted[account]) { | ||
return; | ||
} | ||
|
||
s.blocklisted[account] = true; | ||
|
||
emit Blocklisted(account); | ||
} | ||
|
||
/** | ||
* @dev Removes an account from the blocklist. | ||
* | ||
* Requirements: | ||
* | ||
* - The caller must have the {BLOCKLISTER_ROLE} role. | ||
* | ||
* Emits an {UnBlocklisted} event. | ||
* | ||
* @param account The address to remove from the blocklist. | ||
*/ | ||
function unBlocklist(address account) public onlyRole(BLOCKLISTER_ROLE) { | ||
BlocklistableStorage storage s = _getBlocklistableStorage(); | ||
if (!s.blocklisted[account]) { | ||
return; | ||
} | ||
|
||
s.blocklisted[account] = false; | ||
|
||
emit UnBlocklisted(account); | ||
} | ||
|
||
/** | ||
* @dev Adds the message sender to the blocklist. | ||
* | ||
* Emits a {SelfBlocklisted} event. | ||
* Emits a {Blocklisted} event. | ||
*/ | ||
function selfBlocklist() public { | ||
address sender = _msgSender(); | ||
BlocklistableStorage storage s = _getBlocklistableStorage(); | ||
|
||
if (s.blocklisted[sender]) { | ||
return; | ||
} | ||
|
||
s.blocklisted[sender] = true; | ||
|
||
emit SelfBlocklisted(sender); | ||
emit Blocklisted(sender); | ||
} | ||
|
||
// ------------------ View functions -------------------------- // | ||
|
||
/** | ||
* @dev Checks if an account is blocklisted. | ||
* @param account The address to check for presence in the blocklist. | ||
* @return True if the account is present in the blocklist. | ||
*/ | ||
function isBlocklisted(address account) public view returns (bool) { | ||
return _getBlocklistableStorage().blocklisted[account]; | ||
} | ||
|
||
// ------------------ Private functions ----------------------- // | ||
|
||
/** | ||
* @dev Returns the contract storage structure. | ||
*/ | ||
function _getBlocklistableStorage() private pure returns (BlocklistableStorage storage $) { | ||
assembly { | ||
$.slot := BlocklistableStorageLocation | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.20; | ||
|
||
import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol"; | ||
|
||
import { AccessControlExtUpgradeable } from "./AccessControlExtUpgradeable.sol"; | ||
|
||
/** | ||
* @title PausableExtUpgradeable base contract | ||
* @author CloudWalk Inc. | ||
* @dev Extends the OpenZeppelin's {PausableUpgradeable} contract by adding the {PAUSER_ROLE} role. | ||
* | ||
* This contract is used through inheritance. It introduces the {PAUSER_ROLE} role that is allowed to | ||
* trigger the paused or unpaused state of the contract that is inherited from this one. | ||
*/ | ||
abstract contract PausableExtUpgradeable is AccessControlExtUpgradeable, PausableUpgradeable { | ||
/// @dev The role of pauser that is allowed to trigger the paused or unpaused state of the contract. | ||
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); | ||
|
||
// ------------------ Initializers ---------------------------- // | ||
|
||
/** | ||
* @dev The internal initializer of the upgradable contract. | ||
* | ||
* See details https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable. | ||
*/ | ||
function __PausableExt_init(bytes32 pauserRoleAdmin) internal onlyInitializing { | ||
__Context_init_unchained(); | ||
__ERC165_init_unchained(); | ||
__AccessControl_init_unchained(); | ||
__AccessControlExt_init_unchained(); | ||
__Pausable_init_unchained(); | ||
|
||
__PausableExt_init_unchained(pauserRoleAdmin); | ||
} | ||
|
||
/** | ||
* @dev The unchained internal initializer of the upgradable contract. | ||
* | ||
* See {PausableExtUpgradeable-__PausableExt_init}. | ||
*/ | ||
function __PausableExt_init_unchained(bytes32 pauserRoleAdmin) internal onlyInitializing { | ||
_setRoleAdmin(PAUSER_ROLE, pauserRoleAdmin); | ||
} | ||
|
||
// ------------------ Functions ------------------------------- // | ||
|
||
/** | ||
* @dev Triggers the paused state of the contract. | ||
* | ||
* Requirements: | ||
* | ||
* - The caller must have the {PAUSER_ROLE} role. | ||
*/ | ||
function pause() public onlyRole(PAUSER_ROLE) { | ||
_pause(); | ||
} | ||
|
||
/** | ||
* @dev Triggers the unpaused state of the contract. | ||
* | ||
* Requirements: | ||
* | ||
* - The caller must have the {PAUSER_ROLE} role. | ||
*/ | ||
function unpause() public onlyRole(PAUSER_ROLE) { | ||
_unpause(); | ||
} | ||
} |
Oops, something went wrong.