1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "./Shifter.sol";
import "./Interfaces/ElasticIERC20.sol";
import "./Interfaces/SafeEERC20.sol";
import "./Interfaces/IOracle.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract XFTanon is Shifter, Pausable, Ownable {
using SafeEERC20 for ElasticIERC20;
ElasticIERC20 public immutable xft;
ElasticIERC20 public immutable token;
IOracle public oracle;
uint256 public tokenPrice;
address public xftPool;
address public tokenPool;
address public weth9;
address public chainlinkFeed;
uint256 public flexFeeThreshold;
bool public oracleActive = true;
event SetOracle(address oracle);
event SimpleShift(uint256 amount, address recipient, uint256 output);
event SetFlexFeeThreshold(uint256 _threshold);
event SetChainlinkFeed(address _chainlink);
event SetPool(address _pool);
constructor(
IVerifier _verifier,
IHasher _hasher,
IStorage _storage,
uint256 _denomination,
uint256 _ethDenomination,
uint32 _merkleTreeHeight,
ElasticIERC20 _xft,
ElasticIERC20 _token,
IOracle _oracle,
address _xftPool,
address _tokenPool,
address _weth9,
address _chainlinkFeed,
uint256 _flexFeeThreshold
) Shifter(_verifier, _hasher, _storage, _denomination, _ethDenomination, _merkleTreeHeight) {
if (_tokenPool == address(0x0) || _xftPool == address(0x0)) oracleActive = false;
oracle = _oracle;
xft = _xft;
token = _token;
xftPool = _xftPool;
tokenPool = _tokenPool;
weth9 = _weth9;
chainlinkFeed = _chainlinkFeed;
flexFeeThreshold = _flexFeeThreshold;
}
function pause() external onlyOwner {
_pause();
}
function setOracle(IOracle _oracle) external onlyOwner whenNotPaused {
oracle = _oracle;
emit SetOracle(address(_oracle));
}
function setChainlinkFeed(address _chainlink) external onlyOwner whenNotPaused {
chainlinkFeed = _chainlink;
emit SetChainlinkFeed(_chainlink);
}
function setXFTPool(address _xftPool) external onlyOwner whenNotPaused {
xftPool = _xftPool;
emit SetPool(_xftPool);
}
function setTokenPool(address _tokenPool) external onlyOwner whenNotPaused {
tokenPool = _tokenPool;
emit SetPool(_tokenPool);
}
function setFlexFeeThreshold(uint256 _threshold) external onlyOwner whenNotPaused {
flexFeeThreshold = _threshold;
emit SetFlexFeeThreshold(flexFeeThreshold);
}
function simpleShift(uint256 _amount, address _recipient) public whenNotPaused {
require(token.balanceOf(msg.sender) >= _amount, "Insufficient balance");
uint256 _output = oracle.getCostSimpleShift(_amount, chainlinkFeed, xftPool, tokenPool);
token.burn(msg.sender, _amount);
xft.mint(_recipient, _output);
emit SimpleShift(_amount, _recipient, _output);
}
function getDenomination() external view returns (uint256) {
return denomination;
}
function getCost(uint256 _amount) public view returns (uint256) {
if (!oracleActive) return _amount;
return oracle.getCost(_amount, chainlinkFeed, xftPool);
}
function _processDeposit() internal override whenNotPaused {
uint256 depositCost = getCost(denomination);
require(xft.balanceOf(msg.sender) >= depositCost, "Insufficient Balance");
xft.burn(msg.sender, depositCost);
}
function _processWithdraw (
address payable _recipient,
address payable _relayer,
uint256 _fee, // Fee is in USD
uint256 _refund
) internal override {
require(msg.value == _refund, "Incorrect refund amount received by the contract");
token.mint(_recipient, denomination - _fee);
if (_fee > 0) {
token.mint(_relayer, _fee);
}
if (_refund + ethDenomination > 0) {
(bool success, ) = _recipient.call{ value: _refund + ethDenomination }("");
if (!success) {
// let's return back to the relayer
_relayer.transfer(_refund + ethDenomination);
}
}
}
}