Skip to content

Instantly share code, notes, and snippets.

@publu
Created October 23, 2021 22:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save publu/9d505d65333ca3cdcc19989cbe061c01 to your computer and use it in GitHub Desktop.
Save publu/9d505d65333ca3cdcc19989cbe061c01 to your computer and use it in GitHub Desktop.
// contracts/crosschainMai.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
/*
crosschainToken:
Use a central minter with pre-approved (& allowance-based) contracts for each bridge.
Now you can swap 1:1 between AnySwap or AllBridge, or whatever bridge, into a token controlled by our system.
This lets us add/remove bridges and all participate in the same liquidity.
Definitely use this behind a multisig!
*/
interface DEC {
function decimals() external view returns (uint8);
}
contract crosschainMai is ERC20, ERC20Detailed, Ownable {
using SafeERC20 for IERC20;
constructor(string memory name, string memory symbol, uint8 decimals)
ERC20Detailed(name, symbol, decimals)
public {}
struct list {
bool allowed;
bool paused;
uint256 limit;
}
mapping(address => list) public _able;
modifier able(address _token) {
require(_able[_token].allowed, "not a whitelisted asset.");
require(!_able[_token].paused, "this asset's swaps have been paused.");
_;
}
string public _name;
string public _symbol;
function name() public view returns (string memory){
return _name;
}
function symbol() public view returns (string memory){
return _symbol;
}
function setName(string memory name_) public onlyOwner() {
_name=name_;
}
function setSymbol(string memory symbol_) public onlyOwner() {
_symbol=symbol_;
}
function pauseAsset(address _token) public onlyOwner() {
require(_able[_token].allowed,"pauseAsset: token not added yet.");
require(!_able[_token].paused,"pauseAsset: token already paused.");
_able[_token].paused = true;
}
function unPauseAsset(address _token) public onlyOwner() {
require(_able[_token].allowed,"pauseAsset: token not added yet.");
require(_able[_token].paused,"pauseAsset: token already running.");
_able[_token].paused = false;
}
function setLimit(address _token, uint256 _limit) public onlyOwner() {
require(_able[_token].allowed,"pauseAsset: token not added yet.");
// set limit for balance to be held by contract
// allowances protect the system from suffering greatly from a hack.
_able[_token].limit = _limit;
}
// accepted assets
function addAsset(address _token) public onlyOwner() {
require(!_able[_token].allowed,"addAsset: _token already added.");
IERC20(_token).balanceOf( address(this) );
// require it wasn't added yet
// check if it has 18 decimals (at the very least!)
require(DEC(_token).decimals() == decimals(), "addAsset: decimal mismatch.");
//after all then we add it
_able[_token].allowed = true;
}
function removeAsset(address _token) public onlyOwner() {
// require asset balance of this == 0;
require(IERC20(_token).balanceOf( address(this) ) == 0, "removeAsset: Cannot remove an asset if we're still holding it.");
_able[_token].allowed = false;
}
function swapIn(address _token, uint256 _amount) public able(_token) {
require(_able[_token].limit > 0 && (IERC20(_token).balanceOf(address(this))).add(_amount) <= _able[_token].limit, "swapIn: bridge limit has been reached for now.");
IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);
_mint(msg.sender, _amount);
}
function swapOut(address _token, uint256 _amount) public able(_token) {
IERC20(_token).safeTransferFrom(address(this), msg.sender, _amount);
_burn(msg.sender, _amount);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment