// SPDX-License-Identifier: MIT
pragma solidity 0.8.6;
interface ibToken {
function mint(uint) external returns (uint);
function redeemUnderlying(uint) external returns (uint);
function exchangeRateStored() external view returns (uint);
function balanceOf(address) external view returns (uint);
}
contract FixedForex {
string public constant name = "Iron Bank CHF";
string public constant symbol = "ibCHF";
uint8 public constant decimals = 18;
ibToken public immutable ib;
address public gov;
address public nextgov;
uint public commitgov;
uint public constant delay = 1 days;
uint public liquidity;
constructor(ibToken _ib) {
ib = _ib;
gov = msg.sender;
}
modifier g() {
require(msg.sender == gov);
_;
}
function setGov(address _gov) external g {
nextgov = _gov;
commitgov = block.timestamp + delay;
}
function acceptGov() external {
require(msg.sender == nextgov && commitgov < block.timestamp);
gov = nextgov;
}
function balanceIB() public view returns (uint) {
return ib.balanceOf(address(this));
}
function balanceUnderlying() public view returns (uint) {
uint256 _b = balanceIB();
if (_b > 0) {
return _b * ib.exchangeRateStored() / 1e18;
}
return 0;
}
function _redeem(uint amount) internal {
require(ib.redeemUnderlying(amount) == 0, "ib: withdraw failed");
}
function profit() external {
uint _profit = balanceUnderlying() - liquidity;
_redeem(_profit);
_transferTokens(address(this), gov, _profit);
}
function withdraw(uint amount) external g {
liquidity -= amount;
_redeem(amount);
_burn(amount);
}
function deposit() external {
uint _amount = balances[address(this)];
allowances[address(this)][address(ib)] = _amount;
liquidity += _amount;
require(ib.mint(_amount) == 0, "ib: supply failed");
}
/// @notice Total number of tokens in circulation
uint public totalSupply = 0;
mapping(address => mapping (address => uint)) internal allowances;
mapping(address => uint) internal balances;
event Transfer(address indexed from, address indexed to, uint amount);
event Approval(address indexed owner, address indexed spender, uint amount);
function mint(uint amount) external g {
// mint the amount
totalSupply += amount;
// transfer the amount to the recipient
balances[address(this)] += amount;
emit Transfer(address(0), address(this), amount);
}
function burn(uint amount) external g {
_burn(amount);
}
function _burn(uint amount) internal {
// burn the amount
totalSupply -= amount;
// transfer the amount from the recipient
balances[address(this)] -= amount;
emit Transfer(address(this), address(0), amount);
}
function allowance(address account, address spender) external view returns (uint) {
return allowances[account][spender];
}
function approve(address spender, uint amount) external returns (bool) {
allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function balanceOf(address account) external view returns (uint) {
return balances[account];
}
function transfer(address dst, uint amount) external returns (bool) {
_transferTokens(msg.sender, dst, amount);
return true;
}
function transferFrom(address src, address dst, uint amount) external returns (bool) {
address spender = msg.sender;
uint spenderAllowance = allowances[src][spender];
if (spender != src && spenderAllowance != type(uint).max) {
uint newAllowance = spenderAllowance - amount;
allowances[src][spender] = newAllowance;
emit Approval(src, spender, newAllowance);
}
_transferTokens(src, dst, amount);
return true;
}
function _transferTokens(address src, address dst, uint amount) internal {
balances[src] -= amount;
balances[dst] += amount;
emit Transfer(src, dst, amount);
}
}
{
"compilationTarget": {
"ff.sol": "FixedForex"
},
"evmVersion": "berlin",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract ibToken","name":"_ib","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"acceptGov","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"balanceIB","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balanceUnderlying","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"commitgov","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"gov","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ib","outputs":[{"internalType":"contract ibToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextgov","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"profit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_gov","type":"address"}],"name":"setGov","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]