编译器
0.6.12+commit.27d51765
文件 1 的 24:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 24:ContractRegistryClient.sol
pragma solidity 0.6.12;
import "./Owned.sol";
import "./Utils.sol";
import "./interfaces/IContractRegistry.sol";
contract ContractRegistryClient is Owned, Utils {
bytes32 internal constant CONTRACT_REGISTRY = "ContractRegistry";
bytes32 internal constant BANCOR_NETWORK = "BancorNetwork";
bytes32 internal constant CONVERTER_FACTORY = "ConverterFactory";
bytes32 internal constant CONVERSION_PATH_FINDER = "ConversionPathFinder";
bytes32 internal constant CONVERTER_UPGRADER = "BancorConverterUpgrader";
bytes32 internal constant CONVERTER_REGISTRY = "BancorConverterRegistry";
bytes32 internal constant CONVERTER_REGISTRY_DATA = "BancorConverterRegistryData";
bytes32 internal constant BNT_TOKEN = "BNTToken";
bytes32 internal constant BANCOR_X = "BancorX";
bytes32 internal constant BANCOR_X_UPGRADER = "BancorXUpgrader";
bytes32 internal constant LIQUIDITY_PROTECTION = "LiquidityProtection";
bytes32 internal constant NETWORK_SETTINGS = "NetworkSettings";
IContractRegistry private _registry;
IContractRegistry private _prevRegistry;
bool private _onlyOwnerCanUpdateRegistry;
modifier only(bytes32 contractName) {
_only(contractName);
_;
}
function _only(bytes32 contractName) internal view {
require(msg.sender == _addressOf(contractName), "ERR_ACCESS_DENIED");
}
constructor(IContractRegistry initialRegistry) internal validAddress(address(initialRegistry)) {
_registry = IContractRegistry(initialRegistry);
_prevRegistry = IContractRegistry(initialRegistry);
}
function updateRegistry() external {
require(msg.sender == owner() || !_onlyOwnerCanUpdateRegistry, "ERR_ACCESS_DENIED");
IContractRegistry newRegistry = IContractRegistry(_addressOf(CONTRACT_REGISTRY));
require(newRegistry != _registry && address(newRegistry) != address(0), "ERR_INVALID_REGISTRY");
require(newRegistry.addressOf(CONTRACT_REGISTRY) != address(0), "ERR_INVALID_REGISTRY");
_prevRegistry = _registry;
_registry = newRegistry;
}
function restoreRegistry() external ownerOnly {
_registry = _prevRegistry;
}
function restrictRegistryUpdate(bool restrictOwnerOnly) public ownerOnly {
_onlyOwnerCanUpdateRegistry = restrictOwnerOnly;
}
function registry() public view returns (IContractRegistry) {
return _registry;
}
function prevRegistry() external view returns (IContractRegistry) {
return _prevRegistry;
}
function onlyOwnerCanUpdateRegistry() external view returns (bool) {
return _onlyOwnerCanUpdateRegistry;
}
function _addressOf(bytes32 contractName) internal view returns (address) {
return _registry.addressOf(contractName);
}
}
文件 3 的 24:IBancorNetwork.sol
pragma solidity 0.6.12;
interface IBancorNetwork {
function rateByPath(address[] memory path, uint256 sourceAmount) external view returns (uint256);
function convertByPath(
address[] memory path,
uint256 sourceAmount,
uint256 minReturn,
address payable beneficiary,
address affiliateAccount,
uint256 affiliateFee
) external payable returns (uint256);
}
文件 4 的 24:IClaimable.sol
pragma solidity >=0.6.12;
interface IClaimable {
function owner() external view returns (address);
function transferOwnership(address newOwner) external;
function acceptOwnership() external;
}
文件 5 的 24:IContractRegistry.sol
pragma solidity 0.6.12;
interface IContractRegistry {
function addressOf(bytes32 contractName) external view returns (address);
}
文件 6 的 24:IConverter.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IConverterAnchor.sol";
import "../../utility/interfaces/IOwned.sol";
import "../../token/interfaces/IReserveToken.sol";
interface IConverter is IOwned {
function converterType() external pure returns (uint16);
function anchor() external view returns (IConverterAnchor);
function isActive() external view returns (bool);
function targetAmountAndFee(
IReserveToken sourceToken,
IReserveToken targetToken,
uint256 sourceAmount
) external view returns (uint256, uint256);
function convert(
IReserveToken sourceToken,
IReserveToken targetToken,
uint256 sourceAmount,
address trader,
address payable beneficiary
) external payable returns (uint256);
function conversionFee() external view returns (uint32);
function maxConversionFee() external view returns (uint32);
function reserveBalance(IReserveToken reserveToken) external view returns (uint256);
receive() external payable;
function transferAnchorOwnership(address newOwner) external;
function acceptAnchorOwnership() external;
function setConversionFee(uint32 fee) external;
function addReserve(IReserveToken token, uint32 weight) external;
function transferReservesOnUpgrade(address newConverter) external;
function onUpgradeComplete() external;
function token() external view returns (IConverterAnchor);
function transferTokenOwnership(address newOwner) external;
function acceptTokenOwnership() external;
function reserveTokenCount() external view returns (uint16);
function reserveTokens() external view returns (IReserveToken[] memory);
function connectors(IReserveToken reserveToken)
external
view
returns (
uint256,
uint32,
bool,
bool,
bool
);
function getConnectorBalance(IReserveToken connectorToken) external view returns (uint256);
function connectorTokens(uint256 index) external view returns (IReserveToken);
function connectorTokenCount() external view returns (uint16);
event Activation(uint16 indexed converterType, IConverterAnchor indexed anchor, bool indexed activated);
event Conversion(
IReserveToken indexed sourceToken,
IReserveToken indexed targetToken,
address indexed trader,
uint256 sourceAmount,
uint256 targetAmount,
int256 conversionFee
);
event TokenRateUpdate(address indexed token1, address indexed token2, uint256 rateN, uint256 rateD);
event ConversionFeeUpdate(uint32 prevFee, uint32 newFee);
}
文件 7 的 24:IConverterAnchor.sol
pragma solidity 0.6.12;
import "../../utility/interfaces/IOwned.sol";
interface IConverterAnchor is IOwned {
}
文件 8 的 24:IConverterRegistry.sol
pragma solidity 0.6.12;
import "../../token/interfaces/IReserveToken.sol";
import "./IConverterAnchor.sol";
interface IConverterRegistry {
function getAnchorCount() external view returns (uint256);
function getAnchors() external view returns (address[] memory);
function getAnchor(uint256 index) external view returns (IConverterAnchor);
function isAnchor(address value) external view returns (bool);
function getLiquidityPoolCount() external view returns (uint256);
function getLiquidityPools() external view returns (address[] memory);
function getLiquidityPool(uint256 index) external view returns (IConverterAnchor);
function isLiquidityPool(address value) external view returns (bool);
function getConvertibleTokenCount() external view returns (uint256);
function getConvertibleTokens() external view returns (address[] memory);
function getConvertibleToken(uint256 index) external view returns (IReserveToken);
function isConvertibleToken(address value) external view returns (bool);
function getConvertibleTokenAnchorCount(IReserveToken convertibleToken) external view returns (uint256);
function getConvertibleTokenAnchors(IReserveToken convertibleToken) external view returns (address[] memory);
function getConvertibleTokenAnchor(IReserveToken convertibleToken, uint256 index)
external
view
returns (IConverterAnchor);
function isConvertibleTokenAnchor(IReserveToken convertibleToken, address value) external view returns (bool);
function getLiquidityPoolByConfig(
uint16 converterType,
IReserveToken[] memory reserveTokens,
uint32[] memory reserveWeights
) external view returns (IConverterAnchor);
}
文件 9 的 24:IERC20.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 10 的 24:IMintableToken.sol
pragma solidity >=0.6.12;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IClaimable.sol";
interface IMintableToken is IERC20, IClaimable {
function issue(address to, uint256 amount) external;
function destroy(address from, uint256 amount) external;
}
文件 11 的 24:INetworkSettings.sol
pragma solidity 0.6.12;
import "./utility/interfaces/ITokenHolder.sol";
interface INetworkSettings {
function networkFeeParams() external view returns (ITokenHolder, uint32);
function networkFeeWallet() external view returns (ITokenHolder);
function networkFee() external view returns (uint32);
}
文件 12 的 24:IOwned.sol
pragma solidity 0.6.12;
interface IOwned {
function owner() external view returns (address);
function transferOwnership(address newOwner) external;
function acceptOwnership() external;
}
文件 13 的 24:IReserveToken.sol
pragma solidity 0.6.12;
interface IReserveToken {
}
文件 14 的 24:ITokenGovernance.sol
pragma solidity >=0.6.12;
import "./IMintableToken.sol";
interface ITokenGovernance {
function token() external view returns (IMintableToken);
function mint(address to, uint256 amount) external;
function burn(uint256 amount) external;
}
文件 15 的 24:ITokenHolder.sol
pragma solidity 0.6.12;
import "../../token/interfaces/IReserveToken.sol";
import "./IOwned.sol";
interface ITokenHolder is IOwned {
receive() external payable;
function withdrawTokens(
IReserveToken reserveToken,
address payable to,
uint256 amount
) external;
function withdrawTokensMultiple(
IReserveToken[] calldata reserveTokens,
address payable to,
uint256[] calldata amounts
) external;
}
文件 16 的 24:Math.sol
pragma solidity >=0.6.0 <0.8.0;
library Math {
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
}
}
文件 17 的 24:Owned.sol
pragma solidity 0.6.12;
import "./interfaces/IOwned.sol";
contract Owned is IOwned {
address private _owner;
address private _newOwner;
event OwnerUpdate(address indexed prevOwner, address indexed newOwner);
constructor() public {
_owner = msg.sender;
}
modifier ownerOnly() {
_ownerOnly();
_;
}
function _ownerOnly() private view {
require(msg.sender == _owner, "ERR_ACCESS_DENIED");
}
function transferOwnership(address newOwner) public override ownerOnly {
require(newOwner != _owner, "ERR_SAME_OWNER");
_newOwner = newOwner;
}
function acceptOwnership() public override {
require(msg.sender == _newOwner, "ERR_ACCESS_DENIED");
emit OwnerUpdate(_owner, _newOwner);
_owner = _newOwner;
_newOwner = address(0);
}
function owner() public view override returns (address) {
return _owner;
}
function newOwner() external view returns (address) {
return _newOwner;
}
}
文件 18 的 24:ReentrancyGuard.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 19 的 24:ReserveToken.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "./interfaces/IReserveToken.sol";
import "./SafeERC20Ex.sol";
library ReserveToken {
using SafeERC20 for IERC20;
using SafeERC20Ex for IERC20;
IReserveToken public constant NATIVE_TOKEN_ADDRESS = IReserveToken(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
function isNativeToken(IReserveToken reserveToken) internal pure returns (bool) {
return reserveToken == NATIVE_TOKEN_ADDRESS;
}
function balanceOf(IReserveToken reserveToken, address account) internal view returns (uint256) {
if (isNativeToken(reserveToken)) {
return account.balance;
}
return toIERC20(reserveToken).balanceOf(account);
}
function safeTransfer(
IReserveToken reserveToken,
address to,
uint256 amount
) internal {
if (amount == 0) {
return;
}
if (isNativeToken(reserveToken)) {
payable(to).transfer(amount);
} else {
toIERC20(reserveToken).safeTransfer(to, amount);
}
}
function safeTransferFrom(
IReserveToken reserveToken,
address from,
address to,
uint256 amount
) internal {
if (amount == 0 || isNativeToken(reserveToken)) {
return;
}
toIERC20(reserveToken).safeTransferFrom(from, to, amount);
}
function ensureApprove(
IReserveToken reserveToken,
address spender,
uint256 amount
) internal {
if (isNativeToken(reserveToken)) {
return;
}
toIERC20(reserveToken).ensureApprove(spender, amount);
}
function toIERC20(IReserveToken reserveToken) private pure returns (IERC20) {
return IERC20(address(reserveToken));
}
}
文件 20 的 24:SafeERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 21 的 24:SafeERC20Ex.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
library SafeERC20Ex {
using SafeERC20 for IERC20;
function ensureApprove(
IERC20 token,
address spender,
uint256 amount
) internal {
if (amount == 0) {
return;
}
uint256 allowance = token.allowance(address(this), spender);
if (allowance >= amount) {
return;
}
if (allowance > 0) {
token.safeApprove(spender, 0);
}
token.safeApprove(spender, amount);
}
}
文件 22 的 24:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
文件 23 的 24:Utils.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract Utils {
uint32 internal constant PPM_RESOLUTION = 1000000;
modifier greaterThanZero(uint256 value) {
_greaterThanZero(value);
_;
}
function _greaterThanZero(uint256 value) internal pure {
require(value > 0, "ERR_ZERO_VALUE");
}
modifier validAddress(address addr) {
_validAddress(addr);
_;
}
function _validAddress(address addr) internal pure {
require(addr != address(0), "ERR_INVALID_ADDRESS");
}
modifier validPortion(uint32 _portion) {
_validPortion(_portion);
_;
}
function _validPortion(uint32 _portion) internal pure {
require(_portion > 0 && _portion <= PPM_RESOLUTION, "ERR_INVALID_PORTION");
}
modifier validExternalAddress(address addr) {
_validExternalAddress(addr);
_;
}
function _validExternalAddress(address addr) internal view {
require(addr != address(0) && addr != address(this), "ERR_INVALID_EXTERNAL_ADDRESS");
}
modifier validFee(uint32 fee) {
_validFee(fee);
_;
}
function _validFee(uint32 fee) internal pure {
require(fee <= PPM_RESOLUTION, "ERR_INVALID_FEE");
}
}
文件 24 的 24:VortexBurner.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@bancor/token-governance/contracts/ITokenGovernance.sol";
import "../converter/interfaces/IConverterRegistry.sol";
import "../converter/interfaces/IConverter.sol";
import "../utility/ContractRegistryClient.sol";
import "../utility/Owned.sol";
import "../utility/Utils.sol";
import "../utility/interfaces/ITokenHolder.sol";
import "../token/ReserveToken.sol";
import "../INetworkSettings.sol";
import "../IBancorNetwork.sol";
interface IVortexBurner {
function totalBurnedAmount() external view returns (uint256);
}
interface IBancorNetworkV3 {
function tradeBySourceAmount(
IERC20 sourceToken,
IERC20 targetToken,
uint256 sourceAmount,
uint256 minReturnAmount,
uint256 deadline,
address beneficiary
) external payable returns (uint256);
}
contract VortexBurner is Owned, Utils, ReentrancyGuard, ContractRegistryClient {
using SafeMath for uint256;
using Math for uint256;
using ReserveToken for IReserveToken;
using SafeERC20 for IERC20;
using SafeERC20Ex for IERC20;
struct Strategy {
address[][] paths;
uint256[] amounts;
address[] govPath;
}
uint32 private constant STANDARD_POOL_RESERVE_WEIGHT = PPM_RESOLUTION / 2;
uint16 private constant STANDARD_POOL_CONVERTER_TYPE = 3;
IERC20 private immutable _networkToken;
IERC20 private immutable _govToken;
ITokenGovernance private immutable _govTokenGovernance;
IBancorNetworkV3 private immutable _networkV3;
uint32 private _burnReward;
uint256 private _maxBurnRewardAmount;
uint256 private _totalBurnedAmount;
event BurnRewardUpdated(
uint32 prevBurnReward,
uint32 newBurnReward,
uint256 prevMaxBurnRewardAmount,
uint256 newMaxBurnRewardAmount
);
event Converted(IReserveToken reserveToken, uint256 sourceAmount, uint256 targetAmount);
event Burned(IReserveToken[] reserveTokens, uint256 sourceAmount, uint256 burnedAmount);
constructor(
IERC20 networkToken,
ITokenGovernance govTokenGovernance,
IContractRegistry registry,
IVortexBurner prevBurner,
IBancorNetworkV3 networkV3
)
public
ContractRegistryClient(registry)
validAddress(address(networkToken))
validAddress(address(govTokenGovernance))
validAddress(address(networkV3))
{
_networkToken = networkToken;
_govTokenGovernance = govTokenGovernance;
_govToken = govTokenGovernance.token();
_networkV3 = networkV3;
if (address(prevBurner) != address(0x0)) {
_totalBurnedAmount = prevBurner.totalBurnedAmount();
}
}
receive() external payable {}
function burnReward() external view returns (uint32, uint256) {
return (_burnReward, _maxBurnRewardAmount);
}
function setBurnReward(uint32 newBurnReward, uint256 newMaxBurnRewardAmount)
external
ownerOnly
validFee(newBurnReward)
{
emit BurnRewardUpdated(_burnReward, newBurnReward, _maxBurnRewardAmount, newMaxBurnRewardAmount);
_burnReward = newBurnReward;
_maxBurnRewardAmount = newMaxBurnRewardAmount;
}
function totalBurnedAmount() external view returns (uint256) {
return _totalBurnedAmount;
}
function burn(IReserveToken[] calldata reserveTokens) external nonReentrant {
ITokenHolder feeWallet = _networkFeeWallet();
Strategy memory strategy = _burnStrategy(reserveTokens, feeWallet);
feeWallet.withdrawTokensMultiple(reserveTokens, address(this), strategy.amounts);
IBancorNetwork network = _bancorNetwork();
for (uint256 i = 0; i < strategy.paths.length; ++i) {
uint256 amount = strategy.amounts[i];
if (amount == 0) {
continue;
}
address[] memory path = strategy.paths[i];
IReserveToken reserveToken = IReserveToken(path[0]);
uint256 value = 0;
if (address(reserveToken) == address(_networkToken) || address(reserveToken) == address(_govToken)) {
continue;
}
if (reserveToken.isNativeToken()) {
value = amount;
} else {
reserveToken.ensureApprove(address(network), amount);
}
uint256 targetAmount = network.convertByPath{ value: value }(path, amount, 1, address(this), address(0), 0);
emit Converted(reserveToken, amount, targetAmount);
}
(uint256 sourceAmount, uint256 burnRewardAmount) = _netNetworkConversionAmounts();
if (sourceAmount > 0) {
_networkToken.ensureApprove(address(_networkV3), sourceAmount);
_networkV3.tradeBySourceAmount(_networkToken, _govToken, sourceAmount, 1, block.timestamp + 100, address(this));
}
uint256 govTokenBalance = _govToken.balanceOf(address(this));
require(govTokenBalance > 0, "ERR_ZERO_BURN_AMOUNT");
_totalBurnedAmount = _totalBurnedAmount.add(govTokenBalance);
_govTokenGovernance.burn(govTokenBalance);
if (burnRewardAmount > 0) {
_networkToken.transfer(msg.sender, burnRewardAmount);
}
emit Burned(reserveTokens, sourceAmount + burnRewardAmount, govTokenBalance);
}
function transferNetworkFeeWalletOwnership(address newOwner) external ownerOnly {
_networkFeeWallet().transferOwnership(newOwner);
}
function acceptNetworkFeeOwnership() external ownerOnly {
_networkFeeWallet().acceptOwnership();
}
function _burnStrategy(IReserveToken[] calldata reserveTokens, ITokenHolder feeWallet)
private
view
returns (Strategy memory)
{
IConverterRegistry registry = _converterRegistry();
Strategy memory strategy = Strategy({
paths: new address[][](reserveTokens.length),
amounts: new uint256[](reserveTokens.length),
govPath: new address[](3)
});
for (uint256 i = 0; i < reserveTokens.length; ++i) {
IReserveToken reserveToken = reserveTokens[i];
address[] memory path = new address[](3);
path[0] = address(reserveToken);
if (address(reserveToken) != address(_networkToken) && address(reserveToken) != address(_govToken)) {
path[1] = address(_networkTokenConverterAnchor(reserveToken, registry));
path[2] = address(_networkToken);
}
strategy.paths[i] = path;
strategy.amounts[i] = reserveToken.balanceOf(address(feeWallet));
}
strategy.govPath[0] = address(_networkToken);
strategy.govPath[1] = address(_networkTokenConverterAnchor(IReserveToken(address(_govToken)), registry));
strategy.govPath[2] = address(_govToken);
return strategy;
}
function _netNetworkConversionAmounts() private view returns (uint256, uint256) {
uint256 amount = _networkToken.balanceOf(address(this));
uint256 burnRewardAmount = Math.min(amount.mul(_burnReward) / PPM_RESOLUTION, _maxBurnRewardAmount);
return (amount - burnRewardAmount, burnRewardAmount);
}
function _networkTokenConverterAnchor(IReserveToken reserveToken, IConverterRegistry converterRegistry)
private
view
returns (IConverterAnchor)
{
IReserveToken[] memory reserveTokens = new IReserveToken[](2);
reserveTokens[0] = IReserveToken(address(_networkToken));
reserveTokens[1] = reserveToken;
uint32[] memory standardReserveWeights = new uint32[](2);
standardReserveWeights[0] = STANDARD_POOL_RESERVE_WEIGHT;
standardReserveWeights[1] = STANDARD_POOL_RESERVE_WEIGHT;
IConverterAnchor anchor = converterRegistry.getLiquidityPoolByConfig(
STANDARD_POOL_CONVERTER_TYPE,
reserveTokens,
standardReserveWeights
);
require(address(anchor) != address(0), "ERR_INVALID_RESERVE_TOKEN");
return anchor;
}
function _converterRegistry() private view returns (IConverterRegistry) {
return IConverterRegistry(_addressOf(CONVERTER_REGISTRY));
}
function _bancorNetwork() private view returns (IBancorNetwork) {
return IBancorNetwork(payable(_addressOf(BANCOR_NETWORK)));
}
function _networkSetting() private view returns (INetworkSettings) {
return INetworkSettings(_addressOf(NETWORK_SETTINGS));
}
function _networkFeeWallet() private view returns (ITokenHolder) {
return ITokenHolder(_networkSetting().networkFeeWallet());
}
}
{
"compilationTarget": {
"contracts/vortex/VortexBurner.sol": "VortexBurner"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IERC20","name":"networkToken","type":"address"},{"internalType":"contract ITokenGovernance","name":"govTokenGovernance","type":"address"},{"internalType":"contract IContractRegistry","name":"registry","type":"address"},{"internalType":"contract IVortexBurner","name":"prevBurner","type":"address"},{"internalType":"contract IBancorNetworkV3","name":"networkV3","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"prevBurnReward","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"newBurnReward","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"prevMaxBurnRewardAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMaxBurnRewardAmount","type":"uint256"}],"name":"BurnRewardUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IReserveToken[]","name":"reserveTokens","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burnedAmount","type":"uint256"}],"name":"Burned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IReserveToken","name":"reserveToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"sourceAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetAmount","type":"uint256"}],"name":"Converted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"prevOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerUpdate","type":"event"},{"inputs":[],"name":"acceptNetworkFeeOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IReserveToken[]","name":"reserveTokens","type":"address[]"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"burnReward","outputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"newOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onlyOwnerCanUpdateRegistry","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prevRegistry","outputs":[{"internalType":"contract IContractRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registry","outputs":[{"internalType":"contract IContractRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"restoreRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"restrictOwnerOnly","type":"bool"}],"name":"restrictRegistryUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newBurnReward","type":"uint32"},{"internalType":"uint256","name":"newMaxBurnRewardAmount","type":"uint256"}],"name":"setBurnReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalBurnedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferNetworkFeeWalletOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateRegistry","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]