67 lines
2.2 KiB
Solidity
67 lines
2.2 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.20;
|
|
|
|
import "@openzeppelin/contracts/access/AccessControl.sol";
|
|
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
|
|
|
/**
|
|
* @title CWStabilityFund
|
|
* @notice Insurance / surplus buffer for bridge, oracle, and temporary depeg events.
|
|
*/
|
|
contract CWStabilityFund is AccessControl, ReentrancyGuard {
|
|
using SafeERC20 for IERC20;
|
|
|
|
bytes32 public constant EMERGENCY_ROLE = keccak256("EMERGENCY_ROLE");
|
|
bytes32 public constant DEPOSITOR_ROLE = keccak256("DEPOSITOR_ROLE");
|
|
|
|
mapping(address => bool) public supportedAsset;
|
|
|
|
event AssetSupported(address indexed asset, bool supported);
|
|
event Deposited(address indexed asset, address indexed from, uint256 amount);
|
|
event EmergencyWithdrawn(address indexed asset, address indexed to, uint256 amount, bytes32 reason);
|
|
|
|
error ZeroAddress();
|
|
error UnsupportedAsset();
|
|
|
|
constructor(address admin) {
|
|
if (admin == address(0)) {
|
|
revert ZeroAddress();
|
|
}
|
|
_grantRole(DEFAULT_ADMIN_ROLE, admin);
|
|
_grantRole(EMERGENCY_ROLE, admin);
|
|
_grantRole(DEPOSITOR_ROLE, admin);
|
|
}
|
|
|
|
function setSupportedAsset(address asset, bool supported) external onlyRole(DEFAULT_ADMIN_ROLE) {
|
|
supportedAsset[asset] = supported;
|
|
emit AssetSupported(asset, supported);
|
|
}
|
|
|
|
function deposit(address asset, uint256 amount) external onlyRole(DEPOSITOR_ROLE) nonReentrant {
|
|
if (!supportedAsset[asset]) {
|
|
revert UnsupportedAsset();
|
|
}
|
|
IERC20(asset).safeTransferFrom(msg.sender, address(this), amount);
|
|
emit Deposited(asset, msg.sender, amount);
|
|
}
|
|
|
|
function emergencyWithdraw(
|
|
address asset,
|
|
address to,
|
|
uint256 amount,
|
|
bytes32 reason
|
|
) external onlyRole(EMERGENCY_ROLE) nonReentrant {
|
|
if (to == address(0)) {
|
|
revert ZeroAddress();
|
|
}
|
|
IERC20(asset).safeTransfer(to, amount);
|
|
emit EmergencyWithdrawn(asset, to, amount, reason);
|
|
}
|
|
|
|
function balanceOf(address asset) external view returns (uint256) {
|
|
return IERC20(asset).balanceOf(address(this));
|
|
}
|
|
}
|