// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IBankPrecompile {
function send(address fromAddress, address toAddress, string memory denom, uint256 amount) external returns (bool success);
function sendNative(string memory toNativeAddress) payable external returns (bool success);
function balance(address acc, string memory denom) external view returns (uint256 amount);
function all_balances(address acc) external view returns (Coin[] memory response);
function name(string memory denom) external view returns (string memory response);
function symbol(string memory denom) external view returns (string memory response);
function decimals(string memory denom) external view returns (uint8 response);
function supply(string memory denom) external view returns (uint256 response);
}
struct Coin {
uint256 amount;
string denom;
}
contract ComprehensiveTokenManager {
IBankPrecompile constant BANK = IBankPrecompile(0x0000000000000000000000000000000000001001);
// Events
event PaymentProcessed(address indexed from, string to, uint256 amount, string denom);
event TokenTransfer(address indexed from, address indexed to, string denom, uint256 amount);
event BatchTransferCompleted(address indexed sender, uint256 totalRecipients);
// State variables
mapping(address => bool) public authorizedOperators;
mapping(string => bool) public supportedTokens;
address public owner;
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can execute");
_;
}
modifier onlyAuthorized() {
require(authorizedOperators[msg.sender] || msg.sender == owner, "Not authorized");
_;
}
constructor() {
owner = msg.sender;
authorizedOperators[msg.sender] = true;
supportedTokens["usei"] = true;
}
// =============
// Payment Functions
// =============
function processPayment(
string memory recipient,
uint256 amount
) external payable {
require(msg.value >= amount, "Insufficient payment");
bool success = BANK.sendNative{value: amount}(recipient);
require(success, "Payment failed");
// Refund excess
if (msg.value > amount) {
payable(msg.sender).transfer(msg.value - amount);
}
emit PaymentProcessed(msg.sender, recipient, amount, "usei");
}
function processTokenPayment(
address recipient,
string memory denom,
uint256 amount
) external onlyAuthorized {
require(supportedTokens[denom], "Token not supported");
bool success = BANK.send(msg.sender, recipient, denom, amount);
require(success, "Token payment failed");
emit TokenTransfer(msg.sender, recipient, denom, amount);
}
// =============
// Batch Operations
// =============
function batchSeiTransfer(
string[] memory recipients,
uint256[] memory amounts
) external payable {
require(recipients.length == amounts.length, "Array length mismatch");
require(recipients.length <= 50, "Too many recipients");
uint256 totalAmount = 0;
for (uint256 i = 0; i < amounts.length; i++) {
totalAmount += amounts[i];
}
require(msg.value >= totalAmount, "Insufficient total payment");
for (uint256 i = 0; i < recipients.length; i++) {
bool success = BANK.sendNative{value: amounts[i]}(recipients[i]);
require(success, "Batch transfer failed");
emit PaymentProcessed(msg.sender, recipients[i], amounts[i], "usei");
}
// Refund excess
if (msg.value > totalAmount) {
payable(msg.sender).transfer(msg.value - totalAmount);
}
emit BatchTransferCompleted(msg.sender, recipients.length);
}
function batchTokenTransfer(
address[] memory recipients,
string memory denom,
uint256[] memory amounts
) external onlyAuthorized {
require(recipients.length == amounts.length, "Array length mismatch");
require(recipients.length <= 20, "Too many recipients");
require(supportedTokens[denom], "Token not supported");
for (uint256 i = 0; i < recipients.length; i++) {
bool success = BANK.send(msg.sender, recipients[i], denom, amounts[i]);
require(success, "Batch token transfer failed");
emit TokenTransfer(msg.sender, recipients[i], denom, amounts[i]);
}
emit BatchTransferCompleted(msg.sender, recipients.length);
}
// =============
// Query Functions
// =============
function getUserPortfolio(address user) external view returns (Coin[] memory) {
return BANK.all_balances(user);
}
function getUserBalance(address user, string memory denom) external view returns (uint256) {
return BANK.balance(user, denom);
}
function getTokenInfo(string memory denom) external view returns (
string memory name,
string memory symbol,
uint8 decimals,
uint256 totalSupply
) {
name = BANK.name(denom);
symbol = BANK.symbol(denom);
decimals = BANK.decimals(denom);
totalSupply = BANK.supply(denom);
}
function checkSufficientBalance(
address user,
string memory denom,
uint256 requiredAmount
) external view returns (bool) {
uint256 balance = BANK.balance(user, denom);
return balance >= requiredAmount;
}
function batchBalanceCheck(
address[] memory users,
string memory denom
) external view returns (uint256[] memory balances) {
balances = new uint256[](users.length);
for (uint256 i = 0; i < users.length; i++) {
balances[i] = BANK.balance(users[i], denom);
}
}
// =============
// Admin Functions
// =============
function addSupportedToken(string memory denom) external onlyOwner {
supportedTokens[denom] = true;
}
function removeSupportedToken(string memory denom) external onlyOwner {
supportedTokens[denom] = false;
}
function addOperator(address operator) external onlyOwner {
authorizedOperators[operator] = true;
}
function removeOperator(address operator) external onlyOwner {
require(operator != owner, "Cannot remove owner");
authorizedOperators[operator] = false;
}
// Emergency withdraw function
function emergencyWithdraw() external onlyOwner {
payable(owner).transfer(address(this).balance);
}
// =============
// Utility Functions
// =============
function convertSeiToUsei(uint256 seiAmount) pure external returns (uint256) {
return seiAmount * 1e6;
}
function convertUseiToSei(uint256 useiAmount) pure external returns (uint256) {
return useiAmount / 1e6;
}
receive() external payable {}
}