-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.17; | ||
|
||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; | ||
|
||
interface IMynt { | ||
function burn(address _account, uint256 _amount) external; | ||
} | ||
|
||
contract FixedRateConverter { | ||
using SafeERC20 for IERC20; | ||
|
||
address public admin; | ||
address public myntContractAddress; | ||
address public sovContractAddress; | ||
uint256 public conversionFixedRate; | ||
|
||
event SetAdmin(address indexed sender, address indexed oldAdmin, address indexed newAdmin); | ||
event SetMyntContractAddress( | ||
address indexed sender, | ||
address indexed oldMyntContractAddress, | ||
address indexed newMyntContractAddreess | ||
); | ||
event SetSovContractAddress( | ||
address indexed sender, | ||
address indexed oldSovContractAddress, | ||
address indexed newSovContractAddreess | ||
); | ||
event SetConversionFixedRate( | ||
address indexed sender, | ||
uint256 indexed oldConversionFixedrate, | ||
uint256 indexed newConversionFixedRate | ||
); | ||
event SovWithdrawn(address indexed recipient, uint256 amountWithdrawn); | ||
event Convert(address indexed sender, uint256 myntSent, uint256 sovReceived); | ||
|
||
/// @dev TODO: Check for restrictions in this contract. | ||
modifier onlyAdmin() { | ||
require(msg.sender == admin, "unauthorized"); | ||
_; | ||
} | ||
|
||
constructor( | ||
address _myntContractAddress, | ||
address _sovContractAddress, | ||
uint256 _conversionFixedRate | ||
) { | ||
Check warning on line 48 in contracts/converter/FixedRateConverter.sol GitHub Actions / build
|
||
_setAdmin(msg.sender); | ||
setMyntContractAddress(_myntContractAddress); | ||
setSovContractAddress(_sovContractAddress); | ||
setConversionFixedRate(_conversionFixedRate); | ||
} | ||
|
||
/** | ||
* @notice Public function to set admin account. | ||
* | ||
* @param _newAdmin new admin address. | ||
* only admin can perform this action. | ||
*/ | ||
function setAdmin(address _newAdmin) public onlyAdmin { | ||
_setAdmin(_newAdmin); | ||
} | ||
|
||
/** | ||
* @notice Set the MYNT contract address. | ||
* | ||
* only admin can perform this action. | ||
* | ||
* @param _newMyntContractAddress The new MYNT contract address. | ||
* */ | ||
function setMyntContractAddress(address _newMyntContractAddress) public onlyAdmin { | ||
address oldMyntContractAddress = myntContractAddress; | ||
|
||
myntContractAddress = _newMyntContractAddress; | ||
emit SetMyntContractAddress(msg.sender, oldMyntContractAddress, myntContractAddress); | ||
} | ||
|
||
/** | ||
* @notice Set the sov contract address. | ||
* | ||
* only admin can perform this action. | ||
* | ||
* @param _newSovContractAddress The new sov contract address. | ||
* */ | ||
function setSovContractAddress(address _newSovContractAddress) public onlyAdmin { | ||
address oldSovContractAddress = sovContractAddress; | ||
|
||
sovContractAddress = _newSovContractAddress; | ||
emit SetSovContractAddress(msg.sender, oldSovContractAddress, sovContractAddress); | ||
} | ||
|
||
/** | ||
* @notice Set the conversion fixed rate. | ||
* | ||
* only admin can perform this action. | ||
* | ||
* @param _newConversionFixedRate The new conversion fixed rate. | ||
* */ | ||
function setConversionFixedRate(uint256 _newConversionFixedRate) public onlyAdmin { | ||
uint256 oldConversionFixedRate = conversionFixedRate; | ||
|
||
conversionFixedRate = _newConversionFixedRate; | ||
emit SetConversionFixedRate(msg.sender, oldConversionFixedRate, conversionFixedRate); | ||
} | ||
|
||
/** | ||
* @dev function to convert MYNT to SOV | ||
* | ||
* @param _myntAmount MYNT amount that will be converted. | ||
*/ | ||
function convert(uint256 _myntAmount) external { | ||
require(_myntAmount > 0, "Error: amount must be > 0"); | ||
|
||
uint256 senderMyntBalance = IERC20(myntContractAddress).balanceOf(msg.sender); | ||
Check warning on line 115 in contracts/converter/FixedRateConverter.sol GitHub Actions / build
|
||
require(senderMyntBalance >= _myntAmount, "Error: amount exceeds MYNT balance"); | ||
|
||
uint256 totalConvertedSov = convertAmount(_myntAmount); | ||
|
||
IERC20(myntContractAddress).safeTransferFrom(msg.sender, address(this), _myntAmount); | ||
Check warning on line 120 in contracts/converter/FixedRateConverter.sol GitHub Actions / build
|
||
IERC20(sovContractAddress).safeTransfer(msg.sender, totalConvertedSov); | ||
Check warning on line 121 in contracts/converter/FixedRateConverter.sol GitHub Actions / build
|
||
|
||
IMynt(myntContractAddress).burn(address(this), _myntAmount); | ||
Check warning on line 123 in contracts/converter/FixedRateConverter.sol GitHub Actions / build
|
||
|
||
emit Convert(msg.sender, _myntAmount, totalConvertedSov); | ||
} | ||
|
||
/** | ||
* @dev external function to calculate how many SOV will be converted with the given MYNT amount | ||
* | ||
* @param _myntAmount total MYNT to be converted to SOV. | ||
* @return converted SOV amount. | ||
*/ | ||
function convertAmount(uint256 _myntAmount) public view returns (uint256) { | ||
return (_myntAmount * conversionFixedRate) / 1e18; | ||
} | ||
|
||
/** | ||
* @dev external function to calculate how many MYNT that can be converted based on the current contract's SOV Balance | ||
* | ||
* @return max amount of MYNT that can be converted. | ||
*/ | ||
function convertMax() external view returns (uint256) { | ||
uint256 sovBalance = IERC20(sovContractAddress).balanceOf(address(this)); | ||
Check warning on line 144 in contracts/converter/FixedRateConverter.sol GitHub Actions / build
|
||
return (sovBalance * 1e18) / conversionFixedRate; | ||
} | ||
|
||
/** | ||
* @dev withdraw the whole SOV balance of this contract | ||
* The whole SOV will be withdrawn to the admin account. | ||
* only admin can perform this action. | ||
* | ||
*/ | ||
function withdrawSov() external onlyAdmin { | ||
uint256 sovBalance = IERC20(sovContractAddress).balanceOf(address(this)); | ||
Check warning on line 155 in contracts/converter/FixedRateConverter.sol GitHub Actions / build
|
||
address recipient = msg.sender; | ||
IERC20(sovContractAddress).safeTransfer(recipient, sovBalance); | ||
Check warning on line 157 in contracts/converter/FixedRateConverter.sol GitHub Actions / build
|
||
|
||
emit SovWithdrawn(recipient, sovBalance); | ||
} | ||
|
||
/** Internal function */ | ||
/** | ||
* @dev internal function set the admin account. | ||
* @param _newAdmin new admin address | ||
*/ | ||
function _setAdmin(address _newAdmin) internal { | ||
require(_newAdmin != address(0), "Invalid address"); | ||
address oldAdmin = admin; | ||
admin = _newAdmin; | ||
emit SetAdmin(msg.sender, oldAdmin, admin); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.17; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
import "@openzeppelin/contracts/access/Ownable.sol"; | ||
|
||
|
||
contract MockMyntToken is ERC20, Ownable { | ||
uint8 private _decimals; | ||
|
||
/** | ||
* @notice Constructor called on deployment, initiates the contract. | ||
* @param _name The name of the token. | ||
* @param _symbol The symbol of the token. | ||
* @param _decimalsValue The decimals of the token. | ||
* */ | ||
constructor(string memory _name, string memory _symbol, uint8 _decimalsValue) ERC20(_name, _symbol) { | ||
_decimals = _decimalsValue; | ||
} | ||
|
||
function decimals() public view virtual override returns (uint8) { | ||
return _decimals; | ||
} | ||
|
||
/** | ||
* @notice Creates new tokens and sends them to the recipient. | ||
* @param _account The recipient address to get the minted tokens. | ||
* @param _amount The amount of tokens to be minted. | ||
* */ | ||
function mint(address _account, uint256 _amount) public onlyOwner { | ||
_mint(_account, _amount); | ||
} | ||
|
||
/** | ||
* @notice Burns tokens for the given account. | ||
* @param _account The recipient address to get the minted tokens. | ||
* @param _amount The amount of tokens to be minted. | ||
* */ | ||
function burn(address _account, uint256 _amount) public { | ||
_burn(_account, _amount); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { DeployFunction } from "hardhat-deploy/types"; | ||
|
||
const func: DeployFunction = async ({ | ||
deployments: { deploy, get, log }, | ||
getNamedAccounts, | ||
}) => { | ||
const { deployer } = await getNamedAccounts(); | ||
const deployedMynt = await get("Mynt"); | ||
const deployedSov = await get("Sov"); | ||
const deployedMultisig = await get("MultiSigWallet"); | ||
await deploy("FixedRateConverter", { | ||
from: deployer, | ||
contract: "FixedRateConverter", | ||
log: true, | ||
skipIfAlreadyDeployed: true, | ||
args: [ | ||
deployedMynt.address, | ||
deployedSov.address, | ||
4723550439442834 // sov rate per 1 Mynt; 0.004723550439442834 | ||
], | ||
}); | ||
}; | ||
|
||
func.tags = ["FixedRateConverter"]; | ||
|
||
export default func; |