编译器
0.8.19+commit.7dd6d404
文件 1 的 14:AccessControl.sol
pragma solidity 0.8.19;
import {Ownable} from "src/utils/Ownable.sol";
abstract contract AccessControl is Ownable {
address public exclusiveUser;
mapping(address => bool) public isGuard;
mapping(address => bool) public isKeeper;
mapping(address => bool) public isUser;
mapping(address => bool) public isSwapper;
mapping(address => bool) public isIncentiveManager;
event ExclusiveUserSet(address indexed);
event GuardAdded(address indexed);
event GuardRemoved(address indexed);
event KeeperAdded(address indexed);
event KeeperRemoved(address indexed);
event UserAdded(address indexed);
event UserRemoved(address indexed);
event IncentiveManagerAdded(address indexed);
event IncentiveManagerRemoved(address indexed);
event SwapperAdded(address indexed);
event SwapperRemoved(address indexed);
function setExclusiveUser(address _exclusiveUser) external onlyOwner {
exclusiveUser = _exclusiveUser;
emit ExclusiveUserSet(_exclusiveUser);
}
function addGuard(address _guard) external onlyOwner {
isGuard[_guard] = true;
emit GuardAdded(_guard);
}
function removeGuard(address _guard) external onlyOwner {
isGuard[_guard] = false;
emit GuardRemoved(_guard);
}
function addKeeper(address _keeper) external onlyOwner {
isKeeper[_keeper] = true;
emit KeeperAdded(_keeper);
}
function removeKeeper(address _keeper) external onlyOwner {
isKeeper[_keeper] = false;
emit KeeperRemoved(_keeper);
}
function addUser(address[] calldata _user) external onlyOwner {
for (uint256 i; i < _user.length; ++i) {
isUser[_user[i]] = true;
emit UserAdded(_user[i]);
}
}
function removeUser(address[] calldata _user) external onlyOwner {
for (uint256 i; i < _user.length; ++i) {
isUser[_user[i]] = false;
emit UserRemoved(_user[i]);
}
}
function addIncentiveManager(address _incentiveManager) external onlyOwner {
isIncentiveManager[_incentiveManager] = true;
emit IncentiveManagerAdded(_incentiveManager);
}
function removeIncentiveManager(address _incentiveManager) external onlyOwner {
isIncentiveManager[_incentiveManager] = false;
emit IncentiveManagerRemoved(_incentiveManager);
}
function addSwapper(address _swapper) external onlyOwner {
isSwapper[_swapper] = true;
emit SwapperAdded(_swapper);
}
function removeSwapper(address _swapper) external onlyOwner {
isSwapper[_swapper] = false;
emit SwapperRemoved(_swapper);
}
modifier onlyKeeper() {
if (!isKeeper[msg.sender]) revert Unauthorized();
_;
}
modifier onlyGuard() {
if (!isGuard[msg.sender]) revert Unauthorized();
_;
}
modifier onlyUser() {
if (!isUser[address(0x0)] && !isUser[msg.sender]) revert Unauthorized();
if (exclusiveUser != address(0x0) && exclusiveUser != msg.sender) revert Unauthorized();
_;
}
modifier onlySwapper() {
if (!isSwapper[address(0x0)] && !isSwapper[msg.sender]) revert Unauthorized();
if (exclusiveUser != address(0x0) && exclusiveUser != msg.sender) revert Unauthorized();
_;
}
}
文件 2 的 14:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 3 的 14:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, 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 from, address to, uint256 amount) external returns (bool);
}
文件 4 的 14:IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 5 的 14:IFyde.sol
pragma solidity 0.8.19;
import {RequestData, RebalanceParam, ProcessParam, AssetInfo} from "src/core/Structs.sol";
interface IFyde {
function protocolData() external view returns (uint256, uint72, uint16, uint48, uint72, uint48);
function assetInfo(address) external view returns (AssetInfo memory);
function isAnyNotSupported(address[] calldata _assets) external view returns (address);
function isSwapAllowed(address[] calldata _assets) external view returns (address);
function computeProtocolAUM() external view returns (uint256);
function getProtocolAUM() external view returns (uint256);
function updateProtocolAUM(uint256) external;
function processDeposit(uint256, RequestData calldata) external returns (uint256);
function processWithdraw(uint256, RequestData calldata) external returns (uint256);
function totalSupply() external view returns (uint256);
function setOracleModule(address _oracle) external;
function oracleModule() external view returns (address);
function setRelayer(address _relayer) external;
function RELAYER() external view returns (address);
function totalAssetAccounting(address) external view returns (uint256);
function proxyAssetAccounting(address) external view returns (uint256);
function standardAssetAccounting(address) external view returns (uint256);
function getQuote(address, uint256) external view returns (uint256);
function getAssetDecimals(address) external view returns (uint8);
function collectManagementFee() external;
function getAssetsListLength() external view returns (uint256);
function assetsList(uint256 index) external view returns (address);
function processSwap(uint256, RequestData calldata) external returns (int256);
function owner() external view returns (address);
function getProcessParamDeposit(RequestData memory _req, uint256 _protocolAUM)
external
view
returns (
ProcessParam[] memory processParam,
uint256 sharesToMint,
uint256 taxInTRSY,
uint256 totalUsdDeposit
);
function getProcessParamWithdraw(RequestData calldata _req, uint256 _protocolAUM)
external
view
returns (
ProcessParam[] memory processParam,
uint256 totalSharesToBurn,
uint256 sharesToBurnBeforeTax,
uint256 taxInTRSY,
uint256 totalUsdWithdraw
);
function acceptOwnership() external;
function transferAsset(address _asset, address _recipient, uint256 _amount) external;
function getRebalanceParams(address _asset) external view returns (RebalanceParam memory);
function updateAssetProxyAmount(address _asset, uint256 _amount) external;
}
文件 6 的 14:IGovernanceModule.sol
pragma solidity 0.8.19;
interface IGovernanceModule {
function fyde() external view returns (address);
function proxyImplementation() external view returns (address);
function proxyBalance(address proxy, address asset) external view returns (uint256);
function strsyBalance(address _user, address _govToken) external view returns (uint256 balance);
function assetToStrsy(address _asset) external view returns (address);
function userToProxy(address _user) external view returns (address);
function proxyToUser(address _proxy) external view returns (address);
function isOnGovernanceWhitelist(address _asset) external view returns (bool);
function getAllGovUsers() external view returns (address[] memory);
function isAnyNotOnGovWhitelist(address[] calldata _assets) external view returns (address);
function getUserGTAllowance(uint256 _TRSYAmount, address _token) external view returns (uint256);
function govDeposit(
address _depositor,
address[] calldata _govToken,
uint256[] calldata _amount,
uint256[] calldata _amountTRSY,
uint256 _totalTRSY
) external returns (address proxy);
function govWithdraw(
address _user,
address _asset,
uint256 _amountToWithdraw,
uint256 _trsyToBurn
) external;
function onStrsyTransfer(address sender, address _recipient) external;
function unstakeGov(uint256 _amount, address _asset) external;
function rebalanceProxy(address _proxy, address _asset, address[] memory _usersToRebalance)
external;
function acceptOwnership() external;
}
文件 7 的 14:IOracle.sol
pragma solidity 0.8.19;
import {AssetInfo} from "../core/Structs.sol";
interface IOracle {
function getPriceInUSD(address, AssetInfo calldata) external view returns (uint256);
function getGweiPrice() external view returns (uint256);
function useCache(address[] calldata addr, AssetInfo[] calldata assetInfo) external;
function disableCache() external;
}
文件 8 的 14:ITaxModule.sol
pragma solidity 0.8.19;
import {RequestData, ProcessParam} from "src/core/Structs.sol";
interface ITaxModule {
function getProcessParamDeposit(RequestData memory _req, uint256 _protocolAUM)
external
view
returns (
ProcessParam[] memory processParam,
uint256 sharesToMint,
uint256 taxInTRSY,
uint256 totalUsdDeposit
);
function getProcessParamWithdraw(RequestData calldata _req, uint256 _protocolAUM)
external
view
returns (
ProcessParam[] memory processParam,
uint256 totalSharesToBurn,
uint256 sharesToBurnBeforeTax,
uint256 taxInTRSY,
uint256 totalUsdWithdraw
);
function getSwapAmountOut(
address _assetIn,
uint256 _amountIn,
address _assetOut,
uint256 _protocolAUM
) external view returns (uint256, int256);
}
文件 9 的 14:Ownable.sol
pragma solidity 0.8.19;
abstract contract Ownable {
address public owner;
address public pendingOwner;
event OwnershipTransferred(address indexed user, address indexed newOner);
event OwnershipTransferStarted(address indexed user, address indexed newOwner);
event OwnershipTransferCanceled(address indexed pendingOwner);
error Unauthorized();
constructor(address _owner) {
owner = _owner;
emit OwnershipTransferred(address(0), _owner);
}
function transferOwnership(address newOwner) external onlyOwner {
pendingOwner = newOwner;
emit OwnershipTransferStarted(msg.sender, pendingOwner);
}
function acceptOwnership() external {
if (msg.sender != pendingOwner) revert Unauthorized();
address oldOwner = owner;
owner = pendingOwner;
delete pendingOwner;
emit OwnershipTransferred(oldOwner, owner);
}
function cancelTransferOwnership() external onlyOwner {
emit OwnershipTransferCanceled(pendingOwner);
delete pendingOwner;
}
modifier onlyOwner() {
if (msg.sender != owner) revert Unauthorized();
_;
}
}
文件 10 的 14:PercentageMath.sol
pragma solidity 0.8.19;
library PercentageMath {
uint256 internal constant PERCENTAGE_FACTOR = 1e4;
uint256 internal constant HALF_PERCENTAGE_FACTOR = 0.5e4;
uint256 internal constant MAX_UINT256 = 2 ** 256 - 1;
uint256 internal constant MAX_UINT256_MINUS_HALF_PERCENTAGE = 2 ** 256 - 1 - 0.5e4;
function _isInRange(uint256 valA, uint256 valB, uint256 deviationThreshold)
internal
pure
returns (bool)
{
uint256 lowerBound = percentSub(valA, deviationThreshold);
uint256 upperBound = percentAdd(valA, deviationThreshold);
if (valB < lowerBound || valB > upperBound) return false;
else return true;
}
function percentAdd(uint256 x, uint256 percentage) internal pure returns (uint256 y) {
assembly {
y := add(PERCENTAGE_FACTOR, percentage)
if or(
gt(percentage, sub(MAX_UINT256, PERCENTAGE_FACTOR)),
gt(x, div(MAX_UINT256_MINUS_HALF_PERCENTAGE, y))
) { revert(0, 0) }
y := div(add(mul(x, y), HALF_PERCENTAGE_FACTOR), PERCENTAGE_FACTOR)
}
}
function percentSub(uint256 x, uint256 percentage) internal pure returns (uint256 y) {
assembly {
y := sub(PERCENTAGE_FACTOR, percentage)
if or(
gt(percentage, PERCENTAGE_FACTOR), mul(y, gt(x, div(MAX_UINT256_MINUS_HALF_PERCENTAGE, y)))
) { revert(0, 0) }
y := div(add(mul(x, y), HALF_PERCENTAGE_FACTOR), PERCENTAGE_FACTOR)
}
}
}
文件 11 的 14:QuarantineList.sol
pragma solidity 0.8.19;
import {AccessControl} from "./AccessControl.sol";
abstract contract QuarantineList is AccessControl {
uint256 public min_quarantine_duration = 1 days;
mapping(address => uint128) public quarantineList;
event AddedToQuarantine(address asset, uint128 expirationTime);
event RemovedFromQuarantine(address asset);
error AssetIsQuarantined(address asset);
error AssetIsNotQuarantined(address asset);
error ShortenedExpiration(uint128 currentExpiration, uint128 expiration);
error ShortQurantineDuration(uint128 duration);
function set_min_quarantine_duration(uint256 _min_quarantine_duration) external onlyOwner {
min_quarantine_duration = _min_quarantine_duration;
}
function addToQuarantine(address _asset, uint128 _duration) external onlyGuard {
if (_duration < min_quarantine_duration) revert ShortQurantineDuration(_duration);
uint128 expiration = uint128(block.timestamp) + _duration;
uint128 currentExpiration = quarantineList[_asset];
if (expiration <= currentExpiration) revert ShortenedExpiration(currentExpiration, expiration);
quarantineList[_asset] = expiration;
emit AddedToQuarantine(_asset, expiration);
}
function removeFromQuarantine(address _asset) external onlyGuard {
if (quarantineList[_asset] < uint128(block.timestamp)) revert AssetIsNotQuarantined(_asset);
quarantineList[_asset] = 0;
emit RemovedFromQuarantine(_asset);
}
function isQuarantined(address _asset) public view returns (bool) {
return quarantineList[_asset] >= uint128(block.timestamp);
}
function isAnyQuarantined(address[] memory _assets) public view returns (address) {
for (uint256 i = 0; i < _assets.length;) {
if (isQuarantined(_assets[i])) return _assets[i];
unchecked {
++i;
}
}
return address(0x0);
}
}
文件 12 的 14:RelayerV2.sol
pragma solidity 0.8.19;
import {QuarantineList} from "./core/QuarantineList.sol";
import {UserRequest, RequestData, ProcessParam, AssetInfo} from "./core/Structs.sol";
import {Ownable} from "./utils/Ownable.sol";
import {PercentageMath} from "./utils/PercentageMath.sol";
import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol";
import {IFyde} from "./interfaces/IFyde.sol";
import {IGovernanceModule} from "./interfaces/IGovernanceModule.sol";
import {IOracle} from "./interfaces/IOracle.sol";
import {ITaxModule} from "./interfaces/ITaxModule.sol";
contract RelayerV2 is QuarantineList {
using SafeERC20 for IERC20;
IFyde public fyde;
IOracle public oracleModule;
IGovernanceModule public immutable GOVERNANCE_MODULE;
ITaxModule public taxModule;
uint32 public nonce;
uint16 public deviationThreshold;
bool public paused;
bool public swapPaused;
error ValueOutOfBounds();
error ActionPaused();
error SlippageExceed();
error SwapDisabled(address asset);
error AssetNotAllowedInGovernancePool(address asset);
error DuplicatesAssets();
event Pause(uint256 timestamp);
event Unpause(uint256 timestamp);
event Deposit(uint32 requestId, RequestData request);
event Withdraw(uint32 requestId, RequestData request);
event Swap(uint32 requestId, RequestData request);
constructor(address _oracleModule, address _govModule, uint8 _deviationThreshold)
Ownable(msg.sender)
{
oracleModule = IOracle(_oracleModule);
GOVERNANCE_MODULE = IGovernanceModule(_govModule);
updateDeviationThreshold(_deviationThreshold);
}
function pauseProtocol() public onlyGuard {
paused = true;
emit Pause(block.timestamp);
}
function pauseSwap() external onlyGuard {
swapPaused = true;
emit Pause(block.timestamp);
}
function setFyde(address _fyde) external onlyOwner {
fyde = IFyde(_fyde);
}
function setOracleModule(address _oracleModule) external onlyOwner {
oracleModule = IOracle(_oracleModule);
}
function setTaxModule(address _taxModule) external onlyOwner {
taxModule = ITaxModule(_taxModule);
}
function updateDeviationThreshold(uint16 _threshold) public onlyOwner {
if (_threshold < 10 || _threshold > 1000) revert ValueOutOfBounds();
deviationThreshold = _threshold;
}
function approveFyde(address[] calldata _assets) external onlyOwner {
for (uint256 i; i < _assets.length; ++i) {
IERC20(_assets[i]).safeApprove(address(fyde), type(uint256).max);
}
}
function collectFees(address _asset, address _recipient, uint256 _amount) external onlyOwner {
IERC20(_asset).safeTransfer(_recipient, _amount);
}
function unpauseProtocol() external onlyOwner {
paused = false;
emit Unpause(block.timestamp);
}
function unpauseSwap() external onlyOwner {
swapPaused = false;
emit Unpause(block.timestamp);
}
function deposit(
UserRequest[] calldata _userRequest,
bool _keepGovRights,
uint256 _minTRSYExpected
) external whenNotPaused onlyUser {
address[] memory assetIn = new address[](_userRequest.length);
uint256[] memory amountIn = new uint256[](_userRequest.length);
for (uint256 i; i < _userRequest.length; ++i) {
assetIn[i] = _userRequest[i].asset;
amountIn[i] = _userRequest[i].amount;
}
_checkForDuplicates(assetIn);
if (_keepGovRights) _checkIsAllowedInGov(assetIn);
RequestData memory req = RequestData({
id: nonce,
requestor: address(this),
assetIn: assetIn,
amountIn: amountIn,
assetOut: new address[](0),
amountOut: new uint256[](0),
keepGovRights: _keepGovRights,
slippageChecker: _minTRSYExpected
});
nonce++;
uint256 currentAUM = fyde.getProtocolAUM();
_enableOracleCache(assetIn);
(ProcessParam[] memory processParam, uint256 sharesToMint,,) =
taxModule.getProcessParamDeposit(req, currentAUM);
if (req.slippageChecker > sharesToMint) revert SlippageExceed();
for (uint256 i; i < req.assetIn.length; ++i) {
IERC20(req.assetIn[i]).safeTransferFrom(msg.sender, address(this), req.amountIn[i]);
}
fyde.processDeposit(currentAUM, req);
if (_keepGovRights) {
for (uint256 i; i < processParam.length; ++i) {
address sTrsy = GOVERNANCE_MODULE.assetToStrsy(req.assetIn[i]);
uint256 strsyBal = IERC20(sTrsy).balanceOf(address(this));
uint256 toTransfer =
strsyBal >= processParam[i].sharesAfterTax ? processParam[i].sharesAfterTax : strsyBal;
IERC20(sTrsy).transfer(msg.sender, toTransfer);
uint256 taxTrsy = strsyBal - toTransfer;
if (taxTrsy != 0) GOVERNANCE_MODULE.unstakeGov(taxTrsy, req.assetIn[i]);
}
} else {
IERC20(address(fyde)).transfer(msg.sender, sharesToMint);
}
_disableOracleCache();
emit Deposit(req.id, req);
}
function withdraw(UserRequest[] calldata _userRequest, uint256 _maxTRSYToPay)
external
whenNotPaused
onlyUser
{
address[] memory assetOut = new address[](_userRequest.length);
uint256[] memory amountOut = new uint256[](_userRequest.length);
for (uint256 i; i < _userRequest.length; i++) {
assetOut[i] = _userRequest[i].asset;
amountOut[i] = _userRequest[i].amount;
}
_checkForDuplicates(assetOut);
RequestData memory req = RequestData({
id: nonce,
requestor: address(this),
assetIn: new address[](0),
amountIn: new uint256[](0),
assetOut: assetOut,
amountOut: amountOut,
keepGovRights: false,
slippageChecker: _maxTRSYToPay
});
nonce++;
uint256 currentAUM = fyde.getProtocolAUM();
_enableOracleCache(assetOut);
(, uint256 totalSharesToBurn,,,) = taxModule.getProcessParamWithdraw(req, currentAUM);
if (totalSharesToBurn > req.slippageChecker) revert SlippageExceed();
IERC20(address(fyde)).transferFrom(msg.sender, address(this), totalSharesToBurn);
fyde.processWithdraw(currentAUM, req);
for (uint256 i; i < req.assetOut.length; ++i) {
IERC20(req.assetOut[i]).safeTransfer(msg.sender, req.amountOut[i]);
}
_disableOracleCache();
emit Withdraw(req.id, req);
}
function governanceWithdraw(UserRequest memory _userRequest, address _user, uint256 _maxTRSYToPay)
external
whenNotPaused
onlyUser
{
if (msg.sender != _user && msg.sender != owner) revert Unauthorized();
address[] memory assetOut = new address[](1);
uint256[] memory amountOut = new uint256[](1);
assetOut[0] = _userRequest.asset;
amountOut[0] = _userRequest.amount;
RequestData memory request = RequestData({
id: nonce,
requestor: _user,
assetIn: new address[](0),
amountIn: new uint256[](0),
assetOut: assetOut,
amountOut: amountOut,
keepGovRights: true,
slippageChecker: _maxTRSYToPay
});
nonce++;
uint256 currentAUM = fyde.getProtocolAUM();
fyde.processWithdraw(currentAUM, request);
emit Withdraw(request.id, request);
}
function swap(address _assetIn, uint256 _amountIn, address _assetOut, uint256 _minAmountOut)
external
whenSwapNotPaused
onlySwapper
{
address[] memory assetIn = new address[](1);
uint256[] memory amountIn = new uint256[](1);
address[] memory assetOut = new address[](1);
uint256[] memory amountOut = new uint256[](1);
assetIn[0] = _assetIn;
amountIn[0] = _amountIn;
assetOut[0] = _assetOut;
RequestData memory req = RequestData({
id: nonce,
requestor: address(this),
assetIn: assetIn,
amountIn: amountIn,
assetOut: assetOut,
amountOut: amountOut,
keepGovRights: false,
slippageChecker: _minAmountOut
});
nonce++;
uint256 currentAUM = fyde.getProtocolAUM();
address[] memory assetsSwap = new address[](2);
assetsSwap[0] = _assetIn;
assetsSwap[1] = _assetOut;
_enableOracleCache(assetsSwap);
(uint256 amountOutTaxed,) =
taxModule.getSwapAmountOut(req.assetIn[0], req.amountIn[0], req.assetOut[0], currentAUM);
IERC20(req.assetIn[0]).safeTransferFrom(msg.sender, address(this), req.amountIn[0]);
fyde.processSwap(currentAUM, req);
uint256 tokenBalance = IERC20(assetOut[0]).balanceOf(address(this));
amountOutTaxed = amountOutTaxed > tokenBalance ? tokenBalance : amountOutTaxed;
if (amountOutTaxed < req.slippageChecker) revert SlippageExceed();
IERC20(req.assetOut[0]).safeTransfer(msg.sender, amountOutTaxed);
emit Swap(req.id, req);
amountIn[0] = tokenBalance - amountOutTaxed;
if (amountIn[0] > 0) {
req = RequestData({
id: nonce,
requestor: address(this),
assetIn: assetOut,
amountIn: amountIn,
assetOut: new address[](0),
amountOut: new uint256[](0),
keepGovRights: false,
slippageChecker: 0
});
nonce++;
currentAUM = fyde.getProtocolAUM();
fyde.processDeposit(currentAUM, req);
}
_disableOracleCache();
}
function checkUpkeep(bytes calldata checkData)
external
view
returns (bool upkeepNeeded, bytes memory performData)
{
(uint256 updateFactor, uint256 pauseFactor, bool isChainlink) =
abi.decode(checkData, (uint256, uint256, bool));
uint256 aum = fyde.getProtocolAUM();
uint256 nAum = fyde.computeProtocolAUM();
if (PercentageMath._isInRange(aum, nAum, updateFactor * deviationThreshold / 100)) {
return (false, "AUM is in range");
}
if (!PercentageMath._isInRange(aum, nAum, pauseFactor * deviationThreshold / 100) && !paused) {
if (isChainlink) return (true, abi.encode(false, 0));
return (true, abi.encodeCall(this.performUpkeep, (abi.encode(false, 0))));
}
int256 diffAUM = int256(nAum) - int256(aum);
if (isChainlink) return (true, abi.encode(true, diffAUM));
return (true, abi.encodeCall(this.performUpkeep, (abi.encode(true, diffAUM))));
}
function performUpkeep(bytes calldata performData) external {
(bool updateAum, int256 diffAUM) = abi.decode(performData, (bool, int256));
if (!updateAum) {
pauseProtocol();
} else {
uint256 nAum = uint256(int256(fyde.getProtocolAUM()) + diffAUM);
updateProtocolAUM(nAum);
}
}
function updateProtocolAUM(uint256 nAum) public onlyKeeper {
fyde.updateProtocolAUM(nAum);
}
function _enableOracleCache(address[] memory assets) internal {
AssetInfo[] memory assetInfos = new AssetInfo[](assets.length);
for (uint256 i; i < assets.length; ++i) {
assetInfos[i] = fyde.assetInfo(assets[i]);
}
oracleModule.useCache(assets, assetInfos);
}
function _disableOracleCache() internal {
oracleModule.disableCache();
}
function _checkIsAllowedInGov(address[] memory _assets) internal view {
address notAllowedInGovAsset = GOVERNANCE_MODULE.isAnyNotOnGovWhitelist(_assets);
if (notAllowedInGovAsset != address(0x0)) {
revert AssetNotAllowedInGovernancePool(notAllowedInGovAsset);
}
}
function _checkForDuplicates(address[] memory _assetList) internal pure {
for (uint256 idx; idx < _assetList.length - 1; idx++) {
for (uint256 idx2 = idx + 1; idx2 < _assetList.length; idx2++) {
if (_assetList[idx] == _assetList[idx2]) revert DuplicatesAssets();
}
}
}
function _uint2str(uint256 _i) internal pure returns (string memory) {
if (_i == 0) return "0";
uint256 j = _i;
uint256 len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint256 k = len;
while (_i != 0) {
k = k - 1;
uint8 temp = (48 + uint8(_i - (_i / 10) * 10));
bytes1 b1 = bytes1(temp);
bstr[k] = b1;
_i /= 10;
}
return string(bstr);
}
modifier whenNotPaused() {
if (paused) revert ActionPaused();
_;
}
modifier whenSwapNotPaused() {
if (swapPaused) revert ActionPaused();
_;
}
}
文件 13 的 14:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
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 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
文件 14 的 14:Structs.sol
pragma solidity 0.8.19;
struct AssetInfo {
uint72 targetConcentration;
address uniswapPool;
int72 incentiveFactor;
uint8 assetDecimals;
uint8 quoteTokenDecimals;
address uniswapQuoteToken;
bool isSupported;
}
struct ProtocolData {
uint256 aum;
uint72 taxFactor;
uint16 maxAumDeviationAllowed;
uint48 lastAUMUpdateBlock;
uint72 managementFee;
uint48 lastFeeCollectionTime;
}
struct UserRequest {
address asset;
uint256 amount;
}
struct RequestData {
uint32 id;
address requestor;
address[] assetIn;
uint256[] amountIn;
address[] assetOut;
uint256[] amountOut;
bool keepGovRights;
uint256 slippageChecker;
}
struct RequestQ {
uint64 start;
uint64 end;
mapping(uint64 => RequestData) requestData;
}
struct ProcessParam {
uint256 targetConc;
uint256 currentConc;
uint256 usdValue;
uint256 taxableAmount;
uint256 taxInUSD;
uint256 sharesBeforeTax;
uint256 sharesAfterTax;
}
struct RebalanceParam {
address asset;
uint256 assetTotalAmount;
uint256 assetProxyAmount;
uint256 assetPrice;
uint256 sTrsyTotalSupply;
uint256 trsyPrice;
}
{
"compilationTarget": {
"src/RelayerV2.sol": "RelayerV2"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":@uniswap/v3-core/=lib/v3-core/",
":@uniswap/v3-periphery/=lib/v3-periphery/",
":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-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
":openzeppelin/=lib/openzeppelin-contracts/contracts/",
":solmate/=lib/solmate/src/",
":synthetix-v3/=lib/synthetix-v3/",
":v3-core/=lib/v3-core/contracts/",
":v3-periphery/=lib/v3-periphery/contracts/"
]
}
[{"inputs":[{"internalType":"address","name":"_oracleModule","type":"address"},{"internalType":"address","name":"_govModule","type":"address"},{"internalType":"uint8","name":"_deviationThreshold","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ActionPaused","type":"error"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"AssetIsNotQuarantined","type":"error"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"AssetIsQuarantined","type":"error"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"AssetNotAllowedInGovernancePool","type":"error"},{"inputs":[],"name":"DuplicatesAssets","type":"error"},{"inputs":[{"internalType":"uint128","name":"duration","type":"uint128"}],"name":"ShortQurantineDuration","type":"error"},{"inputs":[{"internalType":"uint128","name":"currentExpiration","type":"uint128"},{"internalType":"uint128","name":"expiration","type":"uint128"}],"name":"ShortenedExpiration","type":"error"},{"inputs":[],"name":"SlippageExceed","type":"error"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"SwapDisabled","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"ValueOutOfBounds","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint128","name":"expirationTime","type":"uint128"}],"name":"AddedToQuarantine","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"requestId","type":"uint32"},{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"address","name":"requestor","type":"address"},{"internalType":"address[]","name":"assetIn","type":"address[]"},{"internalType":"uint256[]","name":"amountIn","type":"uint256[]"},{"internalType":"address[]","name":"assetOut","type":"address[]"},{"internalType":"uint256[]","name":"amountOut","type":"uint256[]"},{"internalType":"bool","name":"keepGovRights","type":"bool"},{"internalType":"uint256","name":"slippageChecker","type":"uint256"}],"indexed":false,"internalType":"struct RequestData","name":"request","type":"tuple"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"ExclusiveUserSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"GuardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"GuardRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"IncentiveManagerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"IncentiveManagerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"KeeperAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"KeeperRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipTransferCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"asset","type":"address"}],"name":"RemovedFromQuarantine","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"requestId","type":"uint32"},{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"address","name":"requestor","type":"address"},{"internalType":"address[]","name":"assetIn","type":"address[]"},{"internalType":"uint256[]","name":"amountIn","type":"uint256[]"},{"internalType":"address[]","name":"assetOut","type":"address[]"},{"internalType":"uint256[]","name":"amountOut","type":"uint256[]"},{"internalType":"bool","name":"keepGovRights","type":"bool"},{"internalType":"uint256","name":"slippageChecker","type":"uint256"}],"indexed":false,"internalType":"struct RequestData","name":"request","type":"tuple"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"SwapperAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"SwapperRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"UserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"","type":"address"}],"name":"UserRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"requestId","type":"uint32"},{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"address","name":"requestor","type":"address"},{"internalType":"address[]","name":"assetIn","type":"address[]"},{"internalType":"uint256[]","name":"amountIn","type":"uint256[]"},{"internalType":"address[]","name":"assetOut","type":"address[]"},{"internalType":"uint256[]","name":"amountOut","type":"uint256[]"},{"internalType":"bool","name":"keepGovRights","type":"bool"},{"internalType":"uint256","name":"slippageChecker","type":"uint256"}],"indexed":false,"internalType":"struct RequestData","name":"request","type":"tuple"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"GOVERNANCE_MODULE","outputs":[{"internalType":"contract IGovernanceModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"addGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_incentiveManager","type":"address"}],"name":"addIncentiveManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"addKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_swapper","type":"address"}],"name":"addSwapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint128","name":"_duration","type":"uint128"}],"name":"addToQuarantine","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_user","type":"address[]"}],"name":"addUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_assets","type":"address[]"}],"name":"approveFyde","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelTransferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"checkData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"collectFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct UserRequest[]","name":"_userRequest","type":"tuple[]"},{"internalType":"bool","name":"_keepGovRights","type":"bool"},{"internalType":"uint256","name":"_minTRSYExpected","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deviationThreshold","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"exclusiveUser","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fyde","outputs":[{"internalType":"contract IFyde","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct UserRequest","name":"_userRequest","type":"tuple"},{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_maxTRSYToPay","type":"uint256"}],"name":"governanceWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_assets","type":"address[]"}],"name":"isAnyQuarantined","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isGuard","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isIncentiveManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isKeeper","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"}],"name":"isQuarantined","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isSwapper","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isUser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"min_quarantine_duration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleModule","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"performUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"quarantineList","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"}],"name":"removeFromQuarantine","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guard","type":"address"}],"name":"removeGuard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_incentiveManager","type":"address"}],"name":"removeIncentiveManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keeper","type":"address"}],"name":"removeKeeper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_swapper","type":"address"}],"name":"removeSwapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_user","type":"address[]"}],"name":"removeUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_exclusiveUser","type":"address"}],"name":"setExclusiveUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fyde","type":"address"}],"name":"setFyde","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_oracleModule","type":"address"}],"name":"setOracleModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_taxModule","type":"address"}],"name":"setTaxModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_min_quarantine_duration","type":"uint256"}],"name":"set_min_quarantine_duration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_assetIn","type":"address"},{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"address","name":"_assetOut","type":"address"},{"internalType":"uint256","name":"_minAmountOut","type":"uint256"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxModule","outputs":[{"internalType":"contract ITaxModule","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseProtocol","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_threshold","type":"uint16"}],"name":"updateDeviationThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nAum","type":"uint256"}],"name":"updateProtocolAUM","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct UserRequest[]","name":"_userRequest","type":"tuple[]"},{"internalType":"uint256","name":"_maxTRSYToPay","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]