pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
contract DecentralizedStableCoin is ERC20, Ownable {
string private constant NAME = "Decentralized Stable Coin";
string private constant SYMBOL = "DSC";
uint8 private constant DECIMALS = 18;
uint256 private constant TIMEOUT = 72 * 3600;
address public oracleContract;
address public minter;
uint256 private _totalSupply;
mapping(address => bool) public allowedCollaterals;
mapping(address => mapping(address => uint256)) public collateralBalances;
event CollateralAdded(address indexed token);
event CollateralDeposited(address indexed user, address indexed token, uint256 amount);
event CollateralWithdrawn(address indexed user, address indexed token, uint256 amount);
event StablecoinMinted(address indexed to, uint256 amount);
event StablecoinBurned(address indexed from, uint256 amount);
constructor(address oracle, address minterAddress) ERC20(NAME, SYMBOL) {
oracleContract = oracle;
minter = minterAddress;
_totalSupply = 0;
}
modifier onlyMinter() {
require(msg.sender == owner() || msg.sender == minter, "Only owner or minter allowed");
_;
}
function addAllowedCollateral(address token) external onlyOwner {
allowedCollaterals[token] = true;
emit CollateralAdded(token);
}
function depositCollateral(address token, uint256 amount) external {
require(allowedCollaterals[token], "Token not allowed as collateral");
require(amount > 0, "Amount must be greater than zero");
_checkPriceFreshness(token);
IERC20(token).transferFrom(msg.sender, address(this), amount);
collateralBalances[msg.sender][token] += amount;
emit CollateralDeposited(msg.sender, token, amount);
}
function withdrawCollateral(address token, uint256 amount) external {
require(collateralBalances[msg.sender][token] >= amount, "Insufficient collateral balance");
_checkPriceFreshness(token);
collateralBalances[msg.sender][token] -= amount;
IERC20(token).transfer(msg.sender, amount);
emit CollateralWithdrawn(msg.sender, token, amount);
}
function mint(address to, uint256 amount) external onlyMinter {
require(_collateralizationCheck(), "Insufficient collateral to mint stablecoins");
_mint(to, amount);
_totalSupply += amount;
emit StablecoinMinted(to, amount);
}
function burn(address from, uint256 amount) external onlyMinter {
_burn(from, amount);
_totalSupply -= amount;
emit StablecoinBurned(from, amount);
}
function _checkPriceFreshness(address token) internal view {
AggregatorV3Interface oracle = AggregatorV3Interface(oracleContract);
(, , , uint256 updatedAt, ) = oracle.latestRoundData();
require(block.timestamp - updatedAt <= TIMEOUT, "Price data is stale");
}
function _collateralizationCheck() internal view returns (bool) {
return true;
}
}
Overdependence on Oracle which may not be updated in realtime may cause different outcomes especially during transactions.
Collateral token validity and also transfer verifier may cause issues during transactions or minting.