communities-contracts/contracts/CommunityVault.sol

116 lines
3.9 KiB
Solidity
Raw Normal View History

// SPDX-License-Identifier: Mozilla Public License 2.0
pragma solidity ^0.8.17;
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import { CommunityOwnable } from "./CommunityOwnable.sol";
/**
* @title CommunityVault
* @dev This contract acts as a Vault for storing ERC20 and ERC721 tokens.
* It allows any user to deposit tokens into the vault.
* Only community owners, as defined in the CommunityOwnable contract, have
* permissions to transfer these tokens out of the vault.
*/
contract CommunityVault is CommunityOwnable {
using SafeERC20 for IERC20;
event ERC20Deposited(address indexed depositor, address indexed token, uint256 amount);
event ERC721Deposited(address indexed depositor, address indexed token, uint256 tokenId);
error CommunityVault_LengthMismatch();
error CommunityVault_NoRecipients();
error CommunityVault_TransferAmountZero();
error CommunityVault_ERC20TransferAmountTooBig();
error CommunityVault_DepositAmountZero();
mapping(address => uint256) public erc20TokenBalances;
constructor(address _ownerToken, address _masterToken) CommunityOwnable(_ownerToken, _masterToken) { }
/**
* @dev Allows anyone to deposit ERC20 tokens into the vault.
* @param token The address of the ERC20 token to deposit.
* @param amount The amount of tokens to deposit.
*/
function depositERC20(address token, uint256 amount) external {
if (amount == 0) {
revert CommunityVault_DepositAmountZero();
}
// Transfer tokens from the sender to this contract
IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
// Update the total balance of the token in the vault
erc20TokenBalances[token] += amount;
// Emit an event for the deposit (optional, but recommended for tracking)
emit ERC20Deposited(msg.sender, token, amount);
}
/**
* @dev Transfers ERC20 tokens to a list of addresses.
* @param token The ERC20 token address.
* @param recipients The list of recipient addresses.
* @param amounts The list of amounts to transfer to each recipient.
*/
function transferERC20(
address token,
address[] calldata recipients,
uint256[] calldata amounts
)
external
onlyCommunityOwnerOrTokenMaster
{
if (recipients.length != amounts.length) {
revert CommunityVault_LengthMismatch();
}
if (recipients.length == 0) {
revert CommunityVault_NoRecipients();
}
for (uint256 i = 0; i < recipients.length; i++) {
if (amounts[i] == 0) {
revert CommunityVault_TransferAmountZero();
}
if (amounts[i] > erc20TokenBalances[token]) {
revert CommunityVault_ERC20TransferAmountTooBig();
}
erc20TokenBalances[token] -= amounts[i];
IERC20(token).safeTransfer(recipients[i], amounts[i]);
}
}
/**
* @dev Transfers ERC721 tokens to a list of addresses.
* @param token The ERC721 token address.
* @param recipients The list of recipient addresses.
* @param tokenIds The list of token IDs to transfer to each recipient.
*/
function transferERC721(
address token,
address[] calldata recipients,
uint256[] calldata tokenIds
)
external
onlyCommunityOwnerOrTokenMaster
{
if (recipients.length != tokenIds.length) {
revert CommunityVault_LengthMismatch();
}
if (recipients.length == 0) {
revert CommunityVault_NoRecipients();
}
for (uint256 i = 0; i < recipients.length; i++) {
IERC721(token).safeTransferFrom(address(this), recipients[i], tokenIds[i]);
}
}
}