/**
* SPDX-License-Identifier: MIT
*
* Copyright (c) 2016-2019 zOS Global Limited
*
*/pragmasolidity ^0.8.0;/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see `ERC20Detailed`.
*/interfaceIERC20{
functionname() externalviewreturns (stringmemory);
functionsymbol() externalviewreturns (stringmemory);
functiondecimals() externalviewreturns (uint8);
/**
* @dev Returns the amount of tokens in existence.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/functionbalanceOf(address account) externalviewreturns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns always true. Throws error on failure.
*
* Emits a `Transfer` event.
*/functiontransfer(address recipient, uint256 amount) externalreturns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through `transferFrom`. This is
* zero by default.
*
* This value can change when `approve` or `transferFrom` are called.
*/functionallowance(address owner, address spender) externalviewreturns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* > Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an `Approval` event.
*/functionapprove(address spender, uint256 amount) externalreturns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns always true. Throws error on failure.
*
* Emits a `Transfer` event.
*/functiontransferFrom(address sender, address recipient, uint256 amount) externalreturns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to `approve`. `value` is the new allowance.
*/eventApproval(addressindexed owner, addressindexed spender, uint256 value);
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import"./interface/IERC20.sol";
import"./interface/IERC677Receiver.sol";
import"./interface/IFrankencoin.sol";
/**
* @title Stable Coin Bridge
* @notice A minting contract for another Swiss franc stablecoin ('source stablecoin') that we trust.
* @author Frankencoin
*/contractStablecoinBridge{
IERC20 publicimmutable chf; // the source stablecoin
IFrankencoin publicimmutable zchf; // the Frankencoin/**
* @notice The time horizon after which this bridge expires and needs to be replaced by a new contract.
*/uint256publicimmutable horizon;
/**
* The maximum amount of outstanding converted source stablecoins.
*/uint256publicimmutable limit;
uint256public minted;
errorLimit(uint256 amount, uint256 limit);
errorExpired(uint256 time, uint256 expiration);
errorUnsupportedToken(address token);
constructor(address other, address zchfAddress, uint256 limit_) {
chf = IERC20(other);
zchf = IFrankencoin(zchfAddress);
horizon =block.timestamp+52weeks;
limit = limit_;
minted =0;
}
/**
* @notice Convenience method for mint(msg.sender, amount)
*/functionmint(uint256 amount) external{
mintTo(msg.sender, amount);
}
/**
* @notice Mint the target amount of Frankencoins, taking the equal amount of source coins from the sender.
* @dev This only works if an allowance for the source coins has been set and the caller has enough of them.
*/functionmintTo(address target, uint256 amount) public{
chf.transferFrom(msg.sender, address(this), amount);
_mint(target, amount);
}
function_mint(address target, uint256 amount) internal{
if (block.timestamp> horizon) revert Expired(block.timestamp, horizon);
zchf.mint(target, amount);
minted += amount;
if (minted > limit) revert Limit(amount, limit);
}
/**
* @notice Convenience method for burnAndSend(msg.sender, amount)
*/functionburn(uint256 amount) external{
_burn(msg.sender, msg.sender, amount);
}
/**
* @notice Burn the indicated amount of Frankencoin and send the same number of source coin to the caller.
*/functionburnAndSend(address target, uint256 amount) external{
_burn(msg.sender, target, amount);
}
function_burn(address zchfHolder, address target, uint256 amount) internal{
zchf.burnFrom(zchfHolder, amount);
chf.transfer(target, amount);
minted -= amount;
}
}