Files
smom-dbis-138/contracts/ops/EiMatrixMainnetBatchDrop.sol

79 lines
2.5 KiB
Solidity
Raw Normal View History

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/**
* @notice Batch ERC-20 drops for EI matrix mainnet top-ups (cWUSDT / cWUSDC).
* @dev Multicall3 transferFrom is not viable on mainnet cW* (allowance does not persist for MC3).
* Operator prefunds this contract, then calls dropPrefunded() ~100 recipients per tx.
* msg.sender must be owner (deployer EOA).
*/
contract EiMatrixMainnetBatchDrop {
using SafeERC20 for IERC20;
address public immutable owner;
event BatchDrop(address indexed token, address indexed operator, uint256 recipientCount, uint256 totalAmount);
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "EiMatrixBatchDrop: not owner");
_;
}
/// @dev Transfer `amounts[i]` from this contract's token balance to `recipients[i]`.
function dropPrefunded(
address token,
address[] calldata recipients,
uint256[] calldata amounts
) external onlyOwner {
uint256 n = recipients.length;
require(n == amounts.length, "EiMatrixBatchDrop: length mismatch");
uint256 total;
for (uint256 i; i < n; ) {
uint256 amount = amounts[i];
total += amount;
IERC20(token).safeTransfer(recipients[i], amount);
unchecked {
++i;
}
}
emit BatchDrop(token, msg.sender, n, total);
}
/// @dev Pull total from owner via transferFrom then distribute (one tx if allowance to this contract works).
function pullAndDrop(
address token,
address[] calldata recipients,
uint256[] calldata amounts
) external onlyOwner {
uint256 n = recipients.length;
require(n == amounts.length, "EiMatrixBatchDrop: length mismatch");
uint256 total;
for (uint256 i; i < n; ) {
total += amounts[i];
unchecked {
++i;
}
}
IERC20(token).safeTransferFrom(owner, address(this), total);
for (uint256 i; i < n; ) {
IERC20(token).safeTransfer(recipients[i], amounts[i]);
unchecked {
++i;
}
}
emit BatchDrop(token, msg.sender, n, total);
}
/// @dev Recover stray tokens (operator only).
function sweep(address token, address to, uint256 amount) external onlyOwner {
IERC20(token).safeTransfer(to, amount);
}
}