文件 1 的 11:Address.sol
pragma solidity 0.7.5;
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 _functionCallWithValue(
address target,
bytes memory data,
uint256 weiValue,
string memory errorMessage
) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: weiValue}(
data
);
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(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);
}
}
}
function addressToString(
address _address
) internal pure returns (string memory) {
bytes32 _bytes = bytes32(uint256(_address));
bytes memory HEX = "0123456789abcdef";
bytes memory _addr = new bytes(42);
_addr[0] = "0";
_addr[1] = "x";
for (uint256 i = 0; i < 20; i++) {
_addr[2 + i * 2] = HEX[uint8(_bytes[i + 12] >> 4)];
_addr[3 + i * 2] = HEX[uint8(_bytes[i + 12] & 0x0f)];
}
return string(_addr);
}
}
文件 2 的 11:IERC20.sol
pragma solidity 0.7.5;
interface IERC20 {
function decimals() external view returns (uint8);
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
);
}
文件 3 的 11:IERC20Mintable.sol
pragma solidity 0.7.5;
interface IERC20Mintable {
function mint(uint256 amount_) external;
function mint(address account_, uint256 ammount_) external;
}
文件 4 的 11:IOwnable.sol
pragma solidity 0.7.5;
interface IOwnable {
function owner() external view returns (address);
function renounceOwnership() external;
function transferOwnership(address newOwner_) external;
}
文件 5 的 11:IOwnableManagement.sol
pragma solidity 0.7.5;
interface IOwnableManagement {
function manager() external view returns (address);
function renounceManagement() external;
function pushManagement(address newOwner_) external;
function pullManagement() external;
}
文件 6 的 11:ISyncus.sol
pragma solidity 0.7.5;
interface ISyncus {
function burn(uint256 amount) external;
function burnFrom(address account_, uint256 amount_) external;
}
文件 7 的 11:ISyncusCalculator.sol
pragma solidity 0.7.5;
interface ISyncusCalculator {
function valuation(
address pair_,
uint amount_
) external view returns (uint _value);
function valuationEther(uint amount_) external view returns (uint _value);
function markdown(address _pair) external view returns (uint);
}
文件 8 的 11:OwnableManagement.sol
pragma solidity 0.7.5;
import "./lib/IOwnableManagement.sol";
contract OwnableManagement is IOwnableManagement {
address internal _owner;
address internal _newOwner;
event OwnershipPushed(address indexed previousOwner, address indexed newOwner);
event OwnershipPulled(address indexed previousOwner, address indexed newOwner);
constructor () {
_owner = msg.sender;
emit OwnershipPushed( address(0), _owner );
}
function manager() public view override returns (address) {
return _owner;
}
modifier onlyManager() {
require( _owner == msg.sender, "Ownable: caller is not the owner" );
_;
}
function renounceManagement() public virtual override onlyManager() {
emit OwnershipPushed( _owner, address(0) );
_owner = address(0);
}
function pushManagement( address newOwner_ ) public virtual override onlyManager() {
require( newOwner_ != address(0), "Ownable: new owner is the zero address");
emit OwnershipPushed( _owner, newOwner_ );
_newOwner = newOwner_;
}
function pullManagement() public virtual override {
require( msg.sender == _newOwner, "Ownable: must be new owner to pull");
emit OwnershipPulled( _owner, _newOwner );
_owner = _newOwner;
}
}
文件 9 的 11:SafeERC20.sol
pragma solidity 0.7.5;
import "./SafeMath.sol";
import "./Address.sol";
import "./IERC20.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 {
require(address(token).isContract(), "SafeERC20: call to non-contract");
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 10 的 11:SafeMath.sol
pragma solidity 0.7.5;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function add32(uint32 a, uint32 b) internal pure returns (uint32) {
uint32 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function sub32(uint32 a, uint32 b) internal pure returns (uint32) {
return sub32(a, b, "SafeMath: subtraction overflow");
}
function sub32(
uint32 a,
uint32 b,
string memory errorMessage
) internal pure returns (uint32) {
require(b <= a, errorMessage);
uint32 c = a - b;
return c;
}
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 mul32(uint32 a, uint32 b) internal pure returns (uint32) {
if (a == 0) {
return 0;
}
uint32 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
function sqrrt(uint256 a) internal pure returns (uint c) {
if (a > 3) {
c = a;
uint b = add(div(a, 2), 1);
while (b < c) {
c = b;
b = div(add(div(a, b), b), 2);
}
} else if (a != 0) {
c = 1;
}
}
function percentageAmount(
uint256 total_,
uint8 percentage_
) internal pure returns (uint256 percentAmount_) {
return div(mul(total_, percentage_), 1000);
}
function substractPercentage(
uint256 total_,
uint8 percentageToSub_
) internal pure returns (uint256 result_) {
return sub(total_, div(mul(total_, percentageToSub_), 1000));
}
function percentageOfTotal(
uint256 part_,
uint256 total_
) internal pure returns (uint256 percent_) {
return div(mul(part_, 100), total_);
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2);
}
function quadraticPricing(
uint256 payment_,
uint256 multiplier_
) internal pure returns (uint256) {
return sqrrt(mul(multiplier_, payment_));
}
function bondingCurve(
uint256 supply_,
uint256 multiplier_
) internal pure returns (uint256) {
return mul(multiplier_, supply_);
}
}
文件 11 的 11:SyncusTreasury.sol
pragma solidity 0.7.5;
import "./lib/SafeMath.sol";
import "./lib/Address.sol";
import "./lib/IERC20.sol";
import "./lib/SafeERC20.sol";
import "./lib/ISyncus.sol";
import "./lib/IERC20Mintable.sol";
import "./lib/ISyncusCalculator.sol";
import "./lib/IOwnable.sol";
import "./OwnableManagement.sol";
contract SyncusTreasury is OwnableManagement {
using SafeMath for uint;
using SafeMath for uint32;
using SafeERC20 for IERC20;
event Deposit(address indexed token, uint amount, uint value);
event Withdrawal(address indexed token, uint amount, uint value);
event CreateDebt(
address indexed debtor,
address indexed token,
uint amount,
uint value
);
event RepayDebt(
address indexed debtor,
address indexed token,
uint amount,
uint value
);
event ReservesManaged(address indexed token, uint amount);
event ReservesUpdated(uint indexed totalReserves);
event ReservesAudited(uint indexed totalReserves);
event RewardsMinted(
address indexed caller,
address indexed recipient,
uint amount
);
event ChangeQueued(MANAGING indexed managing, address queued);
event ChangeActivated(
MANAGING indexed managing,
address activated,
bool result
);
enum MANAGING {
RESERVEDEPOSITOR,
RESERVESPENDER,
RESERVETOKEN,
RESERVEMANAGER,
LIQUIDITYDEPOSITOR,
LIQUIDITYTOKEN,
LIQUIDITYMANAGER,
DEBTOR,
REWARDMANAGER,
VESYNC
}
address public immutable Sync;
uint32 public secondsNeededForQueue;
address[] public reserveTokens;
mapping(address => bool) public isReserveToken;
mapping(address => uint32) public reserveTokenQueue;
address[] public reserveDepositors;
mapping(address => bool) public isReserveDepositor;
mapping(address => uint32) public reserveDepositorQueue;
address[] public reserveSpenders;
mapping(address => bool) public isReserveSpender;
mapping(address => uint32) public reserveSpenderQueue;
address[] public liquidityTokens;
mapping(address => bool) public isLiquidityToken;
mapping(address => uint32) public LiquidityTokenQueue;
address[] public liquidityDepositors;
mapping(address => bool) public isLiquidityDepositor;
mapping(address => uint32) public LiquidityDepositorQueue;
mapping(address => address) public syncusCalculator;
address[] public reserveManagers;
mapping(address => bool) public isReserveManager;
mapping(address => uint32) public ReserveManagerQueue;
address[] public liquidityManagers;
mapping(address => bool) public isLiquidityManager;
mapping(address => uint32) public LiquidityManagerQueue;
address[] public debtors;
mapping(address => bool) public isDebtor;
mapping(address => uint32) public debtorQueue;
mapping(address => uint) public debtorBalance;
address[] public rewardManagers;
mapping(address => bool) public isRewardManager;
mapping(address => uint32) public rewardManagerQueue;
address public veSYNC;
uint public veSYNCQueue;
uint public totalReserves;
uint public totalDebt;
bool isBackingEnabled = false;
receive() external payable {}
constructor(address _Sync, address _USDC, address _etherCalculator) {
require(_Sync != address(0));
require(_USDC != address(0));
require(_etherCalculator != address(0));
Sync = _Sync;
isReserveToken[_USDC] = true;
reserveTokens.push(_USDC);
syncusCalculator[address(0)] = _etherCalculator;
}
function deposit(
uint _amount,
address _token,
uint _profit
) external returns (uint send_) {
require(
isReserveToken[_token] || isLiquidityToken[_token],
"Not accepted"
);
IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);
if (isReserveToken[_token]) {
require(isReserveDepositor[msg.sender], "Not approved");
} else {
require(isLiquidityDepositor[msg.sender], "Not approved");
}
uint value = valueOf(_token, _amount);
send_ = value.sub(_profit);
IERC20Mintable(Sync).mint(msg.sender, send_);
totalReserves = totalReserves.add(value);
emit ReservesUpdated(totalReserves);
emit Deposit(_token, _amount, value);
}
function withdraw(uint _amount, address _token) external {
require(isReserveToken[_token], "Not accepted");
require(isReserveSpender[msg.sender] == true, "Not approved");
uint value = valueOf(_token, _amount);
ISyncus(Sync).burnFrom(msg.sender, value);
totalReserves = totalReserves.sub(value);
emit ReservesUpdated(totalReserves);
IERC20(_token).safeTransfer(msg.sender, _amount);
emit Withdrawal(_token, _amount, value);
}
function incurDebt(uint _amount, address _token) external {
require(isDebtor[msg.sender], "Not approved");
require(isReserveToken[_token], "Not accepted");
uint value = valueOf(_token, _amount);
uint maximumDebt = IERC20(veSYNC).balanceOf(msg.sender);
uint availableDebt = maximumDebt.sub(debtorBalance[msg.sender]);
require(value <= availableDebt, "Exceeds debt limit");
debtorBalance[msg.sender] = debtorBalance[msg.sender].add(value);
totalDebt = totalDebt.add(value);
totalReserves = totalReserves.sub(value);
emit ReservesUpdated(totalReserves);
IERC20(_token).transfer(msg.sender, _amount);
emit CreateDebt(msg.sender, _token, _amount, value);
}
function repayDebtWithReserve(uint _amount, address _token) external {
require(isDebtor[msg.sender], "Not approved");
require(isReserveToken[_token], "Not accepted");
IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);
uint value = valueOf(_token, _amount);
debtorBalance[msg.sender] = debtorBalance[msg.sender].sub(value);
totalDebt = totalDebt.sub(value);
totalReserves = totalReserves.add(value);
emit ReservesUpdated(totalReserves);
emit RepayDebt(msg.sender, _token, _amount, value);
}
function repayDebtWithSYNC(uint _amount) external {
require(isDebtor[msg.sender], "Not approved");
ISyncus(Sync).burnFrom(msg.sender, _amount);
debtorBalance[msg.sender] = debtorBalance[msg.sender].sub(_amount);
totalDebt = totalDebt.sub(_amount);
emit RepayDebt(msg.sender, Sync, _amount, _amount);
}
function manage(address _token, uint _amount) external {
if (isLiquidityToken[_token]) {
require(isLiquidityManager[msg.sender], "Not approved");
} else {
require(isReserveManager[msg.sender], "Not approved");
}
uint value = valueOf(_token, _amount);
if (isBackingEnabled) {
require(value <= excessReserves(), "Insufficient reserves");
}
totalReserves = totalReserves.sub(value);
emit ReservesUpdated(totalReserves);
IERC20(_token).safeTransfer(msg.sender, _amount);
emit ReservesManaged(_token, _amount);
}
function mintRewards(address _recipient, uint _amount) external {
require(isRewardManager[msg.sender], "Not approved");
if (isBackingEnabled) {
require(_amount <= excessReserves(), "Insufficient reserves");
}
IERC20Mintable(Sync).mint(_recipient, _amount);
emit RewardsMinted(msg.sender, _recipient, _amount);
}
function excessReserves() public view returns (uint) {
uint supply = IERC20(Sync).totalSupply().sub(totalDebt);
if (supply > totalReserves) {
return 0;
}
return totalReserves.sub(supply);
}
function auditReserves() external onlyManager {
uint reserves;
for (uint i = 0; i < reserveTokens.length; i++) {
reserves = reserves.add(
valueOf(
reserveTokens[i],
IERC20(reserveTokens[i]).balanceOf(address(this))
)
);
}
for (uint i = 0; i < liquidityTokens.length; i++) {
reserves = reserves.add(
valueOf(
liquidityTokens[i],
IERC20(liquidityTokens[i]).balanceOf(address(this))
)
);
}
reserves = reserves.add(valueOf(address(0), address(this).balance));
totalReserves = reserves;
emit ReservesUpdated(reserves);
emit ReservesAudited(reserves);
}
function valueOf(
address _token,
uint _amount
) public view returns (uint value_) {
if (_token == address(0)) {
value_ = ISyncusCalculator(syncusCalculator[_token]).valuationEther(
_amount
);
} else if (isReserveToken[_token]) {
value_ = _amount.mul(10 ** IERC20(Sync).decimals()).div(
10 ** IERC20(_token).decimals()
);
} else if (isLiquidityToken[_token]) {
value_ = ISyncusCalculator(syncusCalculator[_token]).valuation(
_token,
_amount
);
}
}
function queue(
MANAGING _managing,
address _address
) external onlyManager returns (bool) {
require(_address != address(0));
if (_managing == MANAGING.RESERVEDEPOSITOR) {
reserveDepositorQueue[_address] = uint32(block.timestamp).add32(
secondsNeededForQueue
);
} else if (_managing == MANAGING.RESERVESPENDER) {
reserveSpenderQueue[_address] = uint32(block.timestamp).add32(
secondsNeededForQueue
);
} else if (_managing == MANAGING.RESERVETOKEN) {
reserveTokenQueue[_address] = uint32(block.timestamp).add32(
secondsNeededForQueue
);
} else if (_managing == MANAGING.RESERVEMANAGER) {
ReserveManagerQueue[_address] = uint32(block.timestamp).add32(
secondsNeededForQueue.mul32(2)
);
} else if (_managing == MANAGING.LIQUIDITYDEPOSITOR) {
LiquidityDepositorQueue[_address] = uint32(block.timestamp).add32(
secondsNeededForQueue
);
} else if (_managing == MANAGING.LIQUIDITYTOKEN) {
LiquidityTokenQueue[_address] = uint32(block.timestamp).add32(
secondsNeededForQueue
);
} else if (_managing == MANAGING.LIQUIDITYMANAGER) {
LiquidityManagerQueue[_address] = uint32(block.timestamp).add32(
secondsNeededForQueue.mul32(2)
);
} else if (_managing == MANAGING.DEBTOR) {
debtorQueue[_address] = uint32(block.timestamp).add32(
secondsNeededForQueue
);
} else if (_managing == MANAGING.REWARDMANAGER) {
rewardManagerQueue[_address] = uint32(block.timestamp).add32(
secondsNeededForQueue
);
} else if (_managing == MANAGING.VESYNC) {
veSYNCQueue = uint32(block.timestamp).add32(secondsNeededForQueue);
} else return false;
emit ChangeQueued(_managing, _address);
return true;
}
function toggle(
MANAGING _managing,
address _address,
address _calculator
) external onlyManager returns (bool) {
require(_address != address(0));
bool result;
if (_managing == MANAGING.RESERVEDEPOSITOR) {
if (
requirements(
reserveDepositorQueue,
isReserveDepositor,
_address
)
) {
reserveDepositorQueue[_address] = 0;
if (!listContains(reserveDepositors, _address)) {
reserveDepositors.push(_address);
}
}
result = !isReserveDepositor[_address];
isReserveDepositor[_address] = result;
} else if (_managing == MANAGING.RESERVESPENDER) {
if (requirements(reserveSpenderQueue, isReserveSpender, _address)) {
reserveSpenderQueue[_address] = 0;
if (!listContains(reserveSpenders, _address)) {
reserveSpenders.push(_address);
}
}
result = !isReserveSpender[_address];
isReserveSpender[_address] = result;
} else if (_managing == MANAGING.RESERVETOKEN) {
if (requirements(reserveTokenQueue, isReserveToken, _address)) {
reserveTokenQueue[_address] = 0;
if (!listContains(reserveTokens, _address)) {
reserveTokens.push(_address);
}
}
result = !isReserveToken[_address];
isReserveToken[_address] = result;
} else if (_managing == MANAGING.RESERVEMANAGER) {
if (requirements(ReserveManagerQueue, isReserveManager, _address)) {
reserveManagers.push(_address);
ReserveManagerQueue[_address] = 0;
if (!listContains(reserveManagers, _address)) {
reserveManagers.push(_address);
}
}
result = !isReserveManager[_address];
isReserveManager[_address] = result;
} else if (_managing == MANAGING.LIQUIDITYDEPOSITOR) {
if (
requirements(
LiquidityDepositorQueue,
isLiquidityDepositor,
_address
)
) {
liquidityDepositors.push(_address);
LiquidityDepositorQueue[_address] = 0;
if (!listContains(liquidityDepositors, _address)) {
liquidityDepositors.push(_address);
}
}
result = !isLiquidityDepositor[_address];
isLiquidityDepositor[_address] = result;
} else if (_managing == MANAGING.LIQUIDITYTOKEN) {
if (requirements(LiquidityTokenQueue, isLiquidityToken, _address)) {
LiquidityTokenQueue[_address] = 0;
if (!listContains(liquidityTokens, _address)) {
liquidityTokens.push(_address);
}
}
result = !isLiquidityToken[_address];
isLiquidityToken[_address] = result;
syncusCalculator[_address] = _calculator;
} else if (_managing == MANAGING.LIQUIDITYMANAGER) {
if (
requirements(
LiquidityManagerQueue,
isLiquidityManager,
_address
)
) {
LiquidityManagerQueue[_address] = 0;
if (!listContains(liquidityManagers, _address)) {
liquidityManagers.push(_address);
}
}
result = !isLiquidityManager[_address];
isLiquidityManager[_address] = result;
} else if (_managing == MANAGING.DEBTOR) {
if (requirements(debtorQueue, isDebtor, _address)) {
debtorQueue[_address] = 0;
if (!listContains(debtors, _address)) {
debtors.push(_address);
}
}
result = !isDebtor[_address];
isDebtor[_address] = result;
} else if (_managing == MANAGING.REWARDMANAGER) {
if (requirements(rewardManagerQueue, isRewardManager, _address)) {
rewardManagerQueue[_address] = 0;
if (!listContains(rewardManagers, _address)) {
rewardManagers.push(_address);
}
}
result = !isRewardManager[_address];
isRewardManager[_address] = result;
} else if (_managing == MANAGING.VESYNC) {
veSYNCQueue = 0;
veSYNC = _address;
result = true;
} else return false;
emit ChangeActivated(_managing, _address, result);
return true;
}
function requirements(
mapping(address => uint32) storage queue_,
mapping(address => bool) storage status_,
address _address
) internal view returns (bool) {
if (!status_[_address]) {
require(queue_[_address] != 0, "Must queue");
require(
queue_[_address] <= uint32(block.timestamp),
"Queue not expired"
);
return true;
}
return false;
}
function listContains(
address[] storage _list,
address _token
) internal view returns (bool) {
for (uint i = 0; i < _list.length; i++) {
if (_list[i] == _token) {
return true;
}
}
return false;
}
function setEtherCalculator(address _calculator) external onlyManager {
syncusCalculator[address(0)] = _calculator;
}
function setIsBackingEnabled(bool _isBackingEnabled) external onlyManager {
isBackingEnabled = _isBackingEnabled;
}
function withdrawEther(uint _amount) external onlyManager {
msg.sender.transfer(_amount);
}
function withdrawToken(address _token, uint _amount) external onlyManager {
IERC20(_token).safeTransfer(msg.sender, _amount);
}
function emergencyWithdrawEther(address _recipient) external onlyManager {
require(_recipient != address(0), "Invalid recipient address");
uint balance = address(this).balance;
(bool success, ) = _recipient.call{value: balance}("");
require(success, "Transfer failed");
}
}
{
"compilationTarget": {
"src/SyncusTreasury.sol": "SyncusTreasury"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":openzeppelin/=lib/openzeppelin-contracts/contracts/"
]
}
[{"inputs":[{"internalType":"address","name":"_Sync","type":"address"},{"internalType":"address","name":"_USDC","type":"address"},{"internalType":"address","name":"_etherCalculator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum SyncusTreasury.MANAGING","name":"managing","type":"uint8"},{"indexed":false,"internalType":"address","name":"activated","type":"address"},{"indexed":false,"internalType":"bool","name":"result","type":"bool"}],"name":"ChangeActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"enum SyncusTreasury.MANAGING","name":"managing","type":"uint8"},{"indexed":false,"internalType":"address","name":"queued","type":"address"}],"name":"ChangeQueued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"debtor","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"CreateDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipPulled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipPushed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"debtor","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"RepayDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"totalReserves","type":"uint256"}],"name":"ReservesAudited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReservesManaged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"totalReserves","type":"uint256"}],"name":"ReservesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Withdrawal","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"LiquidityDepositorQueue","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"LiquidityManagerQueue","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"LiquidityTokenQueue","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"ReserveManagerQueue","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Sync","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"auditReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"debtorBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"debtorQueue","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"debtors","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_profit","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"send_","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"}],"name":"emergencyWithdrawEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"excessReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"incurDebt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isDebtor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isLiquidityDepositor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isLiquidityManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isLiquidityToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isReserveDepositor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isReserveManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isReserveSpender","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isReserveToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isRewardManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"liquidityDepositors","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"liquidityManagers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"liquidityTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"manage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"manager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mintRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pullManagement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner_","type":"address"}],"name":"pushManagement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum SyncusTreasury.MANAGING","name":"_managing","type":"uint8"},{"internalType":"address","name":"_address","type":"address"}],"name":"queue","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceManagement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"repayDebtWithReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"repayDebtWithSYNC","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"reserveDepositorQueue","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"reserveDepositors","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"reserveManagers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"reserveSpenderQueue","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"reserveSpenders","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"reserveTokenQueue","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"reserveTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewardManagerQueue","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardManagers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secondsNeededForQueue","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_calculator","type":"address"}],"name":"setEtherCalculator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isBackingEnabled","type":"bool"}],"name":"setIsBackingEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"syncusCalculator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum SyncusTreasury.MANAGING","name":"_managing","type":"uint8"},{"internalType":"address","name":"_address","type":"address"},{"internalType":"address","name":"_calculator","type":"address"}],"name":"toggle","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"valueOf","outputs":[{"internalType":"uint256","name":"value_","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"veSYNC","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"veSYNCQueue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]