文件 1 的 1:KyberAggregatorWrapper.sol
pragma solidity =0.8.10;
contract MainnetAuthAddresses {
address internal constant ADMIN_VAULT_ADDR = 0xCCf3d848e08b94478Ed8f46fFead3008faF581fD;
address internal constant DSGUARD_FACTORY_ADDRESS = 0x5a15566417e6C1c9546523066500bDDBc53F88C7;
address internal constant ADMIN_ADDR = 0x25eFA336886C74eA8E282ac466BdCd0199f85BB9;
address internal constant PROXY_AUTH_ADDRESS = 0x149667b6FAe2c63D1B4317C716b0D0e4d3E2bD70;
address internal constant MODULE_AUTH_ADDRESS = 0x7407974DDBF539e552F1d051e44573090912CC3D;
}
contract AuthHelper is MainnetAuthAddresses {
}
contract AdminVault is AuthHelper {
address public owner;
address public admin;
error SenderNotAdmin();
constructor() {
owner = msg.sender;
admin = ADMIN_ADDR;
}
function changeOwner(address _owner) public {
if (admin != msg.sender){
revert SenderNotAdmin();
}
owner = _owner;
}
function changeAdmin(address _admin) public {
if (admin != msg.sender){
revert SenderNotAdmin();
}
admin = _admin;
}
}
interface IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint256 digits);
function totalSupply() external view returns (uint256 supply);
function balanceOf(address _owner) external view returns (uint256 balance);
function transfer(address _to, uint256 _value) external returns (bool success);
function transferFrom(
address _from,
address _to,
uint256 _value
) external returns (bool success);
function approve(address _spender, uint256 _value) external returns (bool success);
function allowance(address _owner, address _spender) external view returns (uint256 remaining);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
library Address {
error InsufficientBalance(uint256 available, uint256 required);
error SendingValueFail();
error InsufficientBalanceForCall(uint256 available, uint256 required);
error NonContractCall();
function isContract(address account) internal view returns (bool) {
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
assembly {
codehash := extcodehash(account)
}
return (codehash != accountHash && codehash != 0x0);
}
function sendValue(address payable recipient, uint256 amount) internal {
uint256 balance = address(this).balance;
if (balance < amount){
revert InsufficientBalance(balance, amount);
}
(bool success, ) = recipient.call{value: amount}("");
if (!(success)){
revert SendingValueFail();
}
}
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) {
uint256 balance = address(this).balance;
if (balance < value){
revert InsufficientBalanceForCall(balance, value);
}
return _functionCallWithValue(target, data, value, errorMessage);
}
function _functionCallWithValue(
address target,
bytes memory data,
uint256 weiValue,
string memory errorMessage
) private returns (bytes memory) {
if (!(isContract(target))){
revert NonContractCall();
}
(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);
}
}
}
}
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 {
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 _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(token).code.length > 0;
}
}
contract AdminAuth is AuthHelper {
using SafeERC20 for IERC20;
AdminVault public constant adminVault = AdminVault(ADMIN_VAULT_ADDR);
error SenderNotOwner();
error SenderNotAdmin();
modifier onlyOwner() {
if (adminVault.owner() != msg.sender){
revert SenderNotOwner();
}
_;
}
modifier onlyAdmin() {
if (adminVault.admin() != msg.sender){
revert SenderNotAdmin();
}
_;
}
function withdrawStuckFunds(address _token, address _receiver, uint256 _amount) public onlyOwner {
if (_token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) {
payable(_receiver).transfer(_amount);
} else {
IERC20(_token).safeTransfer(_receiver, _amount);
}
}
function kill() public onlyAdmin {
selfdestruct(payable(msg.sender));
}
}
contract DFSRegistry is AdminAuth {
error EntryAlreadyExistsError(bytes4);
error EntryNonExistentError(bytes4);
error EntryNotInChangeError(bytes4);
error ChangeNotReadyError(uint256,uint256);
error EmptyPrevAddrError(bytes4);
error AlreadyInContractChangeError(bytes4);
error AlreadyInWaitPeriodChangeError(bytes4);
event AddNewContract(address,bytes4,address,uint256);
event RevertToPreviousAddress(address,bytes4,address,address);
event StartContractChange(address,bytes4,address,address);
event ApproveContractChange(address,bytes4,address,address);
event CancelContractChange(address,bytes4,address,address);
event StartWaitPeriodChange(address,bytes4,uint256);
event ApproveWaitPeriodChange(address,bytes4,uint256,uint256);
event CancelWaitPeriodChange(address,bytes4,uint256,uint256);
struct Entry {
address contractAddr;
uint256 waitPeriod;
uint256 changeStartTime;
bool inContractChange;
bool inWaitPeriodChange;
bool exists;
}
mapping(bytes4 => Entry) public entries;
mapping(bytes4 => address) public previousAddresses;
mapping(bytes4 => address) public pendingAddresses;
mapping(bytes4 => uint256) public pendingWaitTimes;
function getAddr(bytes4 _id) public view returns (address) {
return entries[_id].contractAddr;
}
function isRegistered(bytes4 _id) public view returns (bool) {
return entries[_id].exists;
}
function addNewContract(
bytes4 _id,
address _contractAddr,
uint256 _waitPeriod
) public onlyOwner {
if (entries[_id].exists){
revert EntryAlreadyExistsError(_id);
}
entries[_id] = Entry({
contractAddr: _contractAddr,
waitPeriod: _waitPeriod,
changeStartTime: 0,
inContractChange: false,
inWaitPeriodChange: false,
exists: true
});
emit AddNewContract(msg.sender, _id, _contractAddr, _waitPeriod);
}
function revertToPreviousAddress(bytes4 _id) public onlyOwner {
if (!(entries[_id].exists)){
revert EntryNonExistentError(_id);
}
if (previousAddresses[_id] == address(0)){
revert EmptyPrevAddrError(_id);
}
address currentAddr = entries[_id].contractAddr;
entries[_id].contractAddr = previousAddresses[_id];
emit RevertToPreviousAddress(msg.sender, _id, currentAddr, previousAddresses[_id]);
}
function startContractChange(bytes4 _id, address _newContractAddr) public onlyOwner {
if (!entries[_id].exists){
revert EntryNonExistentError(_id);
}
if (entries[_id].inWaitPeriodChange){
revert AlreadyInWaitPeriodChangeError(_id);
}
entries[_id].changeStartTime = block.timestamp;
entries[_id].inContractChange = true;
pendingAddresses[_id] = _newContractAddr;
emit StartContractChange(msg.sender, _id, entries[_id].contractAddr, _newContractAddr);
}
function approveContractChange(bytes4 _id) public onlyOwner {
if (!entries[_id].exists){
revert EntryNonExistentError(_id);
}
if (!entries[_id].inContractChange){
revert EntryNotInChangeError(_id);
}
if (block.timestamp < (entries[_id].changeStartTime + entries[_id].waitPeriod)){
revert ChangeNotReadyError(block.timestamp, (entries[_id].changeStartTime + entries[_id].waitPeriod));
}
address oldContractAddr = entries[_id].contractAddr;
entries[_id].contractAddr = pendingAddresses[_id];
entries[_id].inContractChange = false;
entries[_id].changeStartTime = 0;
pendingAddresses[_id] = address(0);
previousAddresses[_id] = oldContractAddr;
emit ApproveContractChange(msg.sender, _id, oldContractAddr, entries[_id].contractAddr);
}
function cancelContractChange(bytes4 _id) public onlyOwner {
if (!entries[_id].exists){
revert EntryNonExistentError(_id);
}
if (!entries[_id].inContractChange){
revert EntryNotInChangeError(_id);
}
address oldContractAddr = pendingAddresses[_id];
pendingAddresses[_id] = address(0);
entries[_id].inContractChange = false;
entries[_id].changeStartTime = 0;
emit CancelContractChange(msg.sender, _id, oldContractAddr, entries[_id].contractAddr);
}
function startWaitPeriodChange(bytes4 _id, uint256 _newWaitPeriod) public onlyOwner {
if (!entries[_id].exists){
revert EntryNonExistentError(_id);
}
if (entries[_id].inContractChange){
revert AlreadyInContractChangeError(_id);
}
pendingWaitTimes[_id] = _newWaitPeriod;
entries[_id].changeStartTime = block.timestamp;
entries[_id].inWaitPeriodChange = true;
emit StartWaitPeriodChange(msg.sender, _id, _newWaitPeriod);
}
function approveWaitPeriodChange(bytes4 _id) public onlyOwner {
if (!entries[_id].exists){
revert EntryNonExistentError(_id);
}
if (!entries[_id].inWaitPeriodChange){
revert EntryNotInChangeError(_id);
}
if (block.timestamp < (entries[_id].changeStartTime + entries[_id].waitPeriod)){
revert ChangeNotReadyError(block.timestamp, (entries[_id].changeStartTime + entries[_id].waitPeriod));
}
uint256 oldWaitTime = entries[_id].waitPeriod;
entries[_id].waitPeriod = pendingWaitTimes[_id];
entries[_id].inWaitPeriodChange = false;
entries[_id].changeStartTime = 0;
pendingWaitTimes[_id] = 0;
emit ApproveWaitPeriodChange(msg.sender, _id, oldWaitTime, entries[_id].waitPeriod);
}
function cancelWaitPeriodChange(bytes4 _id) public onlyOwner {
if (!entries[_id].exists){
revert EntryNonExistentError(_id);
}
if (!entries[_id].inWaitPeriodChange){
revert EntryNotInChangeError(_id);
}
uint256 oldWaitPeriod = pendingWaitTimes[_id];
pendingWaitTimes[_id] = 0;
entries[_id].inWaitPeriodChange = false;
entries[_id].changeStartTime = 0;
emit CancelWaitPeriodChange(msg.sender, _id, oldWaitPeriod, entries[_id].waitPeriod);
}
}
contract MainnetCoreAddresses {
address internal constant REGISTRY_ADDR = 0x287778F121F134C66212FB16c9b53eC991D32f5b;
address internal constant PROXY_AUTH_ADDR = 0x149667b6FAe2c63D1B4317C716b0D0e4d3E2bD70;
address internal constant MODULE_AUTH_ADDR = 0x7407974DDBF539e552F1d051e44573090912CC3D;
address internal constant DEFISAVER_LOGGER = 0xcE7a977Cac4a481bc84AC06b2Da0df614e621cf3;
address internal constant SUB_STORAGE_ADDR = 0x1612fc28Ee0AB882eC99842Cde0Fc77ff0691e90;
address internal constant BUNDLE_STORAGE_ADDR = 0x223c6aDE533851Df03219f6E3D8B763Bd47f84cf;
address internal constant STRATEGY_STORAGE_ADDR = 0xF52551F95ec4A2B4299DcC42fbbc576718Dbf933;
address internal constant RECIPE_EXECUTOR_ADDR = 0x5029336642814bC51a42bA80BF83a6322110035D;
}
contract CoreHelper is MainnetCoreAddresses {
}
contract Discount is AdminAuth{
mapping(address => bool) public serviceFeesDisabled;
function reenableServiceFee(address _wallet) public onlyOwner{
serviceFeesDisabled[_wallet] = false;
}
function disableServiceFee(address _wallet) public onlyOwner{
serviceFeesDisabled[_wallet] = true;
}
}
abstract contract IWETH {
function allowance(address, address) public virtual view returns (uint256);
function balanceOf(address) public virtual view returns (uint256);
function approve(address, uint256) public virtual;
function transfer(address, uint256) public virtual returns (bool);
function transferFrom(
address,
address,
uint256
) public virtual returns (bool);
function deposit() public payable virtual;
function withdraw(uint256) public virtual;
}
library TokenUtils {
using SafeERC20 for IERC20;
address public constant WETH_ADDR = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address public constant ETH_ADDR = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
function approveToken(
address _tokenAddr,
address _to,
uint256 _amount
) internal {
if (_tokenAddr == ETH_ADDR) return;
if (IERC20(_tokenAddr).allowance(address(this), _to) < _amount) {
IERC20(_tokenAddr).safeApprove(_to, _amount);
}
}
function pullTokensIfNeeded(
address _token,
address _from,
uint256 _amount
) internal returns (uint256) {
if (_amount == type(uint256).max) {
_amount = getBalance(_token, _from);
}
if (_from != address(0) && _from != address(this) && _token != ETH_ADDR && _amount != 0) {
IERC20(_token).safeTransferFrom(_from, address(this), _amount);
}
return _amount;
}
function withdrawTokens(
address _token,
address _to,
uint256 _amount
) internal returns (uint256) {
if (_amount == type(uint256).max) {
_amount = getBalance(_token, address(this));
}
if (_to != address(0) && _to != address(this) && _amount != 0) {
if (_token != ETH_ADDR) {
IERC20(_token).safeTransfer(_to, _amount);
} else {
(bool success, ) = _to.call{value: _amount}("");
require(success, "Eth send fail");
}
}
return _amount;
}
function depositWeth(uint256 _amount) internal {
IWETH(WETH_ADDR).deposit{value: _amount}();
}
function withdrawWeth(uint256 _amount) internal {
IWETH(WETH_ADDR).withdraw(_amount);
}
function getBalance(address _tokenAddr, address _acc) internal view returns (uint256) {
if (_tokenAddr == ETH_ADDR) {
return _acc.balance;
} else {
return IERC20(_tokenAddr).balanceOf(_acc);
}
}
function getTokenDecimals(address _token) internal view returns (uint256) {
if (_token == ETH_ADDR) return 18;
return IERC20(_token).decimals();
}
}
contract DFSExchangeHelper {
using TokenUtils for address;
error InvalidOffchainData();
error OutOfRangeSlicingError();
error ZeroTokensSwapped();
using SafeERC20 for IERC20;
function sendLeftover(
address _srcAddr,
address _destAddr,
address payable _to
) internal {
TokenUtils.ETH_ADDR.withdrawTokens(_to, type(uint256).max);
_srcAddr.withdrawTokens(_to, type(uint256).max);
_destAddr.withdrawTokens(_to, type(uint256).max);
}
function sliceUint(bytes memory bs, uint256 start) internal pure returns (uint256) {
if (bs.length < start + 32){
revert OutOfRangeSlicingError();
}
uint256 x;
assembly {
x := mload(add(bs, add(0x20, start)))
}
return x;
}
function writeUint256(
bytes memory _b,
uint256 _index,
uint256 _input
) internal pure {
if (_b.length < _index + 32) {
revert InvalidOffchainData();
}
bytes32 input = bytes32(_input);
_index += 32;
assembly {
mstore(add(_b, _index), input)
}
}
}
contract DFSExchangeData {
struct OffchainData {
address wrapper;
address exchangeAddr;
address allowanceTarget;
uint256 price;
uint256 protocolFee;
bytes callData;
}
struct ExchangeData {
address srcAddr;
address destAddr;
uint256 srcAmount;
uint256 destAmount;
uint256 minPrice;
uint256 dfsFeeDivider;
address user;
address wrapper;
bytes wrapperData;
OffchainData offchainData;
}
}
abstract contract IOffchainWrapper is DFSExchangeData {
function takeOrder(
ExchangeData memory _exData
) virtual public payable returns (bool success, uint256);
}
interface IExecutorHelper {
struct Swap {
bytes data;
bytes32 selectorAndFlags;
}
struct SwapExecutorDescription {
Swap[][] swapSequences;
address tokenIn;
address tokenOut;
uint256 minTotalAmountOut;
address to;
uint256 deadline;
bytes positiveSlippageData;
}
struct UniSwap {
address pool;
address tokenIn;
address tokenOut;
address recipient;
uint256 collectAmount;
uint32 swapFee;
uint32 feePrecision;
uint32 tokenWeightInput;
}
struct StableSwap {
address pool;
address tokenFrom;
address tokenTo;
uint8 tokenIndexFrom;
uint8 tokenIndexTo;
uint256 dx;
uint256 poolLength;
address poolLp;
bool isSaddle;
}
struct CurveSwap {
address pool;
address tokenFrom;
address tokenTo;
int128 tokenIndexFrom;
int128 tokenIndexTo;
uint256 dx;
bool usePoolUnderlying;
bool useTriCrypto;
}
struct UniswapV3KSElastic {
address recipient;
address pool;
address tokenIn;
address tokenOut;
uint256 swapAmount;
uint160 sqrtPriceLimitX96;
bool isUniV3;
}
struct BalancerV2 {
address vault;
bytes32 poolId;
address assetIn;
address assetOut;
uint256 amount;
}
struct DODO {
address recipient;
address pool;
address tokenFrom;
address tokenTo;
uint256 amount;
address sellHelper;
bool isSellBase;
bool isVersion2;
}
struct GMX {
address vault;
address tokenIn;
address tokenOut;
uint256 amount;
address receiver;
}
struct Synthetix {
address synthetixProxy;
address tokenIn;
address tokenOut;
bytes32 sourceCurrencyKey;
uint256 sourceAmount;
bytes32 destinationCurrencyKey;
bool useAtomicExchange;
}
struct Platypus {
address pool;
address tokenIn;
address tokenOut;
address recipient;
uint256 collectAmount;
}
struct PSM {
address router;
address tokenIn;
address tokenOut;
uint256 amountIn;
address recipient;
}
struct WSTETH {
address pool;
uint256 amount;
bool isWrapping;
}
struct Maverick {
address pool;
address tokenIn;
address tokenOut;
address recipient;
uint256 swapAmount;
uint256 sqrtPriceLimitD18;
}
struct SyncSwap {
bytes _data;
address vault;
address tokenIn;
address pool;
uint256 collectAmount;
}
struct AlgebraV1 {
address recipient;
address pool;
address tokenIn;
address tokenOut;
uint256 swapAmount;
uint160 sqrtPriceLimitX96;
uint256 senderFeeOnTransfer;
}
struct BalancerBatch {
address vault;
bytes32[] poolIds;
address[] path;
bytes[] userDatas;
uint256 amountIn;
}
struct Mantis {
address pool;
address tokenIn;
address tokenOut;
uint256 amount;
address recipient;
}
struct IziSwap {
address pool;
address tokenIn;
address tokenOut;
address recipient;
uint256 swapAmount;
int24 limitPoint;
}
struct TraderJoeV2 {
address recipient;
address pool;
address tokenIn;
address tokenOut;
uint256 collectAmount;
}
struct LevelFiV2 {
address pool;
address fromToken;
address toToken;
uint256 amountIn;
uint256 minAmountOut;
address recipient;
}
struct GMXGLP {
address rewardRouter;
address stakedGLP;
address glpManager;
address yearnVault;
address tokenIn;
address tokenOut;
uint256 swapAmount;
address recipient;
}
struct Vooi {
address pool;
address fromToken;
address toToken;
uint256 fromID;
uint256 toID;
uint256 fromAmount;
address to;
}
struct VelocoreV2 {
address vault;
address tokenIn;
address tokenOut;
uint256 amount;
}
struct MaticMigrate {
address pool;
address tokenAddress;
uint256 amount;
address recipient;
}
function executeUniswap(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeStableSwap(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeCurve(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeKSClassic(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeUniV3KSElastic(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeRfq(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeBalV2(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeDODO(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeVelodrome(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeGMX(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executePlatypus(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeWrappedstETH(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeStEth(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeSynthetix(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeHashflow(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executePSM(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeFrax(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeCamelot(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeKyberLimitOrder(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeMaverick(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeSyncSwap(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeAlgebraV1(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeBalancerBatch(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeWombat(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeMantis(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeIziSwap(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeWooFiV2(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeTraderJoeV2(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executePancakeStableSwap(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeLevelFiV2(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeGMXGLP(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeVooi(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeVelocoreV2(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeMaticMigrate(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
function executeSmardex(
bytes memory data,
uint256 flagsAndPrevAmountOut
) external payable returns (uint256);
}
interface IAggregationExecutor {
function callBytes(bytes calldata data) external payable;
function swapSingleSequence(bytes calldata data) external;
function finalTransactionProcessing(
address tokenIn,
address tokenOut,
address to,
bytes calldata destTokenFeeData
) external;
}
interface IMetaAggregationRouterV2 {
struct SwapDescriptionV2 {
IERC20 srcToken;
IERC20 dstToken;
address[] srcReceivers;
uint256[] srcAmounts;
address[] feeReceivers;
uint256[] feeAmounts;
address dstReceiver;
uint256 amount;
uint256 minReturnAmount;
uint256 flags;
bytes permit;
}
struct SwapExecutionParams {
address callTarget;
address approveTarget;
bytes targetData;
SwapDescriptionV2 desc;
bytes clientData;
}
struct SimpleSwapData {
address[] firstPools;
uint256[] firstSwapAmounts;
bytes[] swapDatas;
uint256 deadline;
bytes positiveSlippageData;
}
function swap(
SwapExecutionParams calldata execution
) external payable returns (uint256, uint256);
function swapSimpleMode(
IAggregationExecutor caller,
SwapDescriptionV2 memory desc,
bytes calldata executorData,
bytes calldata clientData
) external returns (uint256, uint256);
}
contract KyberInputScalingHelper {
uint256 private constant _PARTIAL_FILL = 0x01;
uint256 private constant _REQUIRES_EXTRA_ETH = 0x02;
uint256 private constant _SHOULD_CLAIM = 0x04;
uint256 private constant _BURN_FROM_MSG_SENDER = 0x08;
uint256 private constant _BURN_FROM_TX_ORIGIN = 0x10;
uint256 private constant _SIMPLE_SWAP = 0x20;
struct PositiveSlippageFeeData {
uint256 partnerPSInfor;
uint256 expectedReturnAmount;
}
struct Swap {
bytes data;
bytes32 selectorAndFlags;
}
struct SimpleSwapData {
address[] firstPools;
uint256[] firstSwapAmounts;
bytes[] swapDatas;
uint256 deadline;
bytes positiveSlippageData;
}
struct SwapExecutorDescription {
Swap[][] swapSequences;
address tokenIn;
address tokenOut;
address to;
uint256 deadline;
bytes positiveSlippageData;
}
function getScaledInputData(
bytes calldata inputData,
uint256 newAmount
) public pure returns (bytes memory) {
bytes4 selector = bytes4(inputData[:4]);
bytes calldata dataToDecode = inputData[4:];
if (selector == IMetaAggregationRouterV2.swap.selector) {
IMetaAggregationRouterV2.SwapExecutionParams memory params = abi.decode(
dataToDecode,
(IMetaAggregationRouterV2.SwapExecutionParams)
);
(params.desc, params.targetData) = _getScaledInputDataV2(
params.desc,
params.targetData,
newAmount,
_flagsChecked(params.desc.flags, _SIMPLE_SWAP)
);
return abi.encodeWithSelector(selector, params);
} else if (selector == IMetaAggregationRouterV2.swapSimpleMode.selector) {
(
address callTarget,
IMetaAggregationRouterV2.SwapDescriptionV2 memory desc,
bytes memory targetData,
bytes memory clientData
) = abi.decode(
dataToDecode,
(address, IMetaAggregationRouterV2.SwapDescriptionV2, bytes, bytes)
);
(desc, targetData) = _getScaledInputDataV2(desc, targetData, newAmount, true);
return abi.encodeWithSelector(selector, callTarget, desc, targetData, clientData);
} else revert("InputScalingHelper: Invalid selector");
}
function _getScaledInputDataV2(
IMetaAggregationRouterV2.SwapDescriptionV2 memory desc,
bytes memory executorData,
uint256 newAmount,
bool isSimpleMode
) internal pure returns (IMetaAggregationRouterV2.SwapDescriptionV2 memory, bytes memory) {
uint256 oldAmount = desc.amount;
if (oldAmount == newAmount) {
return (desc, executorData);
}
if (isSimpleMode) {
return (
_scaledSwapDescriptionV2(desc, oldAmount, newAmount),
_scaledSimpleSwapData(executorData, oldAmount, newAmount)
);
}
return (
_scaledSwapDescriptionV2(desc, oldAmount, newAmount),
_scaledExecutorCallBytesData(executorData, oldAmount, newAmount)
);
}
function _scaledSwapDescriptionV2(
IMetaAggregationRouterV2.SwapDescriptionV2 memory desc,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (IMetaAggregationRouterV2.SwapDescriptionV2 memory) {
desc.minReturnAmount = (desc.minReturnAmount * newAmount) / oldAmount;
if (desc.minReturnAmount == 0) desc.minReturnAmount = 1;
desc.amount = newAmount;
uint256 nReceivers = desc.srcReceivers.length;
for (uint256 i = 0; i < nReceivers; ) {
desc.srcAmounts[i] = (desc.srcAmounts[i] * newAmount) / oldAmount;
unchecked {
++i;
}
}
return desc;
}
function _scaledSimpleSwapData(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
SimpleSwapData memory swapData = abi.decode(data, (SimpleSwapData));
uint256 nPools = swapData.firstPools.length;
for (uint256 i = 0; i < nPools; ) {
swapData.firstSwapAmounts[i] = (swapData.firstSwapAmounts[i] * newAmount) / oldAmount;
unchecked {
++i;
}
}
swapData.positiveSlippageData = _scaledPositiveSlippageFeeData(
swapData.positiveSlippageData,
oldAmount,
newAmount
);
return abi.encode(swapData);
}
function _scaledExecutorCallBytesData(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
SwapExecutorDescription memory executorDesc = abi.decode(data, (SwapExecutorDescription));
executorDesc.positiveSlippageData = _scaledPositiveSlippageFeeData(
executorDesc.positiveSlippageData,
oldAmount,
newAmount
);
uint256 nSequences = executorDesc.swapSequences.length;
for (uint256 i = 0; i < nSequences; ) {
Swap memory swap = executorDesc.swapSequences[i][0];
bytes4 functionSelector = bytes4(swap.selectorAndFlags);
if (functionSelector == IExecutorHelper.executeUniswap.selector) {
swap.data = newUniSwap(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeStableSwap.selector) {
swap.data = newStableSwap(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeCurve.selector) {
swap.data = newCurveSwap(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeKSClassic.selector) {
swap.data = newKyberDMM(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeUniV3KSElastic.selector) {
swap.data = newUniV3ProMM(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeRfq.selector) {
revert("InputScalingHelper: Can not scale RFQ swap");
} else if (functionSelector == IExecutorHelper.executeBalV2.selector) {
swap.data = newBalancerV2(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeWrappedstETH.selector) {
swap.data = newWrappedstETHSwap(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeStEth.selector) {
swap.data = newStETHSwap(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeDODO.selector) {
swap.data = newDODO(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeVelodrome.selector) {
swap.data = newVelodrome(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeGMX.selector) {
swap.data = newGMX(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeSynthetix.selector) {
swap.data = newSynthetix(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeHashflow.selector) {
revert("InputScalingHelper: Can not scale RFQ swap");
} else if (functionSelector == IExecutorHelper.executeCamelot.selector) {
swap.data = newCamelot(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeKyberLimitOrder.selector) {
revert("InputScalingHelper: Can not scale RFQ swap");
} else if (functionSelector == IExecutorHelper.executePSM.selector) {
swap.data = newPSM(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeFrax.selector) {
swap.data = newFrax(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executePlatypus.selector) {
swap.data = newPlatypus(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeMaverick.selector) {
swap.data = newMaverick(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeSyncSwap.selector) {
swap.data = newSyncSwap(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeAlgebraV1.selector) {
swap.data = newAlgebraV1(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeBalancerBatch.selector) {
swap.data = newBalancerBatch(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeWombat.selector) {
swap.data = newMantis(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeMantis.selector) {
swap.data = newMantis(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeIziSwap.selector) {
swap.data = newIziSwap(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeWooFiV2.selector) {
swap.data = newMantis(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executeTraderJoeV2.selector) {
swap.data = newTraderJoeV2(swap.data, oldAmount, newAmount);
} else if (functionSelector == IExecutorHelper.executePancakeStableSwap.selector) {
swap.data = newCurveSwap(swap.data, oldAmount, newAmount);
} else revert("AggregationExecutor: Dex type not supported");
unchecked {
++i;
}
}
return abi.encode(executorDesc);
}
function newUniSwap(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.UniSwap memory uniSwap = abi.decode(data, (IExecutorHelper.UniSwap));
uniSwap.collectAmount = (uniSwap.collectAmount * newAmount) / oldAmount;
return abi.encode(uniSwap);
}
function newStableSwap(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.StableSwap memory stableSwap = abi.decode(
data,
(IExecutorHelper.StableSwap)
);
stableSwap.dx = (stableSwap.dx * newAmount) / oldAmount;
return abi.encode(stableSwap);
}
function newCurveSwap(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.CurveSwap memory curveSwap = abi.decode(data, (IExecutorHelper.CurveSwap));
curveSwap.dx = (curveSwap.dx * newAmount) / oldAmount;
return abi.encode(curveSwap);
}
function newKyberDMM(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.UniSwap memory kyberDMMSwap = abi.decode(data, (IExecutorHelper.UniSwap));
kyberDMMSwap.collectAmount = (kyberDMMSwap.collectAmount * newAmount) / oldAmount;
return abi.encode(kyberDMMSwap);
}
function newUniV3ProMM(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.UniswapV3KSElastic memory uniSwapV3ProMM = abi.decode(
data,
(IExecutorHelper.UniswapV3KSElastic)
);
uniSwapV3ProMM.swapAmount = (uniSwapV3ProMM.swapAmount * newAmount) / oldAmount;
return abi.encode(uniSwapV3ProMM);
}
function newBalancerV2(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.BalancerV2 memory balancerV2 = abi.decode(
data,
(IExecutorHelper.BalancerV2)
);
balancerV2.amount = (balancerV2.amount * newAmount) / oldAmount;
return abi.encode(balancerV2);
}
function newDODO(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.DODO memory dodo = abi.decode(data, (IExecutorHelper.DODO));
dodo.amount = (dodo.amount * newAmount) / oldAmount;
return abi.encode(dodo);
}
function newVelodrome(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.UniSwap memory velodrome = abi.decode(data, (IExecutorHelper.UniSwap));
velodrome.collectAmount = (velodrome.collectAmount * newAmount) / oldAmount;
return abi.encode(velodrome);
}
function newGMX(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.GMX memory gmx = abi.decode(data, (IExecutorHelper.GMX));
gmx.amount = (gmx.amount * newAmount) / oldAmount;
return abi.encode(gmx);
}
function newSynthetix(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.Synthetix memory synthetix = abi.decode(data, (IExecutorHelper.Synthetix));
synthetix.sourceAmount = (synthetix.sourceAmount * newAmount) / oldAmount;
return abi.encode(synthetix);
}
function newCamelot(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.UniSwap memory camelot = abi.decode(data, (IExecutorHelper.UniSwap));
camelot.collectAmount = (camelot.collectAmount * newAmount) / oldAmount;
return abi.encode(camelot);
}
function newPlatypus(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.Platypus memory platypus = abi.decode(data, (IExecutorHelper.Platypus));
platypus.collectAmount = (platypus.collectAmount * newAmount) / oldAmount;
return abi.encode(platypus);
}
function newWrappedstETHSwap(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.WSTETH memory wstEthData = abi.decode(data, (IExecutorHelper.WSTETH));
wstEthData.amount = (wstEthData.amount * newAmount) / oldAmount;
return abi.encode(wstEthData);
}
function newPSM(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.PSM memory psm = abi.decode(data, (IExecutorHelper.PSM));
psm.amountIn = (psm.amountIn * newAmount) / oldAmount;
return abi.encode(psm);
}
function newFrax(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.UniSwap memory frax = abi.decode(data, (IExecutorHelper.UniSwap));
frax.collectAmount = (frax.collectAmount * newAmount) / oldAmount;
return abi.encode(frax);
}
function newStETHSwap(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
uint256 amount = abi.decode(data, (uint256));
amount = (amount * newAmount) / oldAmount;
return abi.encode(amount);
}
function newMaverick(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.Maverick memory maverick = abi.decode(data, (IExecutorHelper.Maverick));
maverick.swapAmount = (maverick.swapAmount * newAmount) / oldAmount;
return abi.encode(maverick);
}
function newSyncSwap(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.SyncSwap memory syncSwap = abi.decode(data, (IExecutorHelper.SyncSwap));
syncSwap.collectAmount = (syncSwap.collectAmount * newAmount) / oldAmount;
return abi.encode(syncSwap);
}
function newAlgebraV1(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.AlgebraV1 memory algebraV1Swap = abi.decode(
data,
(IExecutorHelper.AlgebraV1)
);
algebraV1Swap.swapAmount = (algebraV1Swap.swapAmount * newAmount) / oldAmount;
return abi.encode(algebraV1Swap);
}
function newBalancerBatch(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.BalancerBatch memory balancerBatch = abi.decode(
data,
(IExecutorHelper.BalancerBatch)
);
balancerBatch.amountIn = (balancerBatch.amountIn * newAmount) / oldAmount;
return abi.encode(balancerBatch);
}
function newMantis(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.Mantis memory mantis = abi.decode(data, (IExecutorHelper.Mantis));
mantis.amount = (mantis.amount * newAmount) / oldAmount;
return abi.encode(mantis);
}
function newIziSwap(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.IziSwap memory iZi = abi.decode(data, (IExecutorHelper.IziSwap));
iZi.swapAmount = (iZi.swapAmount * newAmount) / oldAmount;
return abi.encode(iZi);
}
function newTraderJoeV2(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory) {
IExecutorHelper.TraderJoeV2 memory traderJoe = abi.decode(
data,
(IExecutorHelper.TraderJoeV2)
);
traderJoe.collectAmount =
(traderJoe.collectAmount & (1 << 255)) |
((uint256((traderJoe.collectAmount << 1) >> 1) * newAmount) / oldAmount);
return abi.encode(traderJoe);
}
function _scaledPositiveSlippageFeeData(
bytes memory data,
uint256 oldAmount,
uint256 newAmount
) internal pure returns (bytes memory newData) {
if (data.length > 32) {
PositiveSlippageFeeData memory psData = abi.decode(data, (PositiveSlippageFeeData));
uint256 left = uint256(psData.expectedReturnAmount >> 128);
uint256 right = (uint256(uint128(psData.expectedReturnAmount)) * newAmount) / oldAmount;
require(right <= type(uint128).max, "Exceeded type range");
psData.expectedReturnAmount = right | (left << 128);
data = abi.encode(psData);
} else if (data.length == 32) {
uint256 expectedReturnAmount = abi.decode(data, (uint256));
uint256 left = uint256(expectedReturnAmount >> 128);
uint256 right = (uint256(uint128(expectedReturnAmount)) * newAmount) / oldAmount;
require(right <= type(uint128).max, "Exceeded type range");
expectedReturnAmount = right | (left << 128);
data = abi.encode(expectedReturnAmount);
}
return data;
}
function _flagsChecked(uint256 number, uint256 flag) internal pure returns (bool) {
return number & flag != 0;
}
}
contract KyberAggregatorWrapper is IOffchainWrapper, DFSExchangeHelper, AdminAuth, CoreHelper{
using TokenUtils for address;
using SafeERC20 for IERC20;
bytes4 constant SCALING_HELPER_ID = bytes4(keccak256("KyberInputScalingHelper"));
DFSRegistry public constant registry = DFSRegistry(REGISTRY_ADDR);
function takeOrder(
ExchangeData calldata _exData
) override public payable returns (bool success, uint256) {
IERC20(_exData.srcAddr).safeApprove(_exData.offchainData.allowanceTarget, _exData.srcAmount);
address scalingHelperAddr = registry.getAddr(SCALING_HELPER_ID);
bytes memory scaledCalldata = KyberInputScalingHelper(scalingHelperAddr).getScaledInputData(_exData.offchainData.callData, _exData.srcAmount);
uint256 tokensBefore = _exData.destAddr.getBalance(address(this));
(success, ) = _exData.offchainData.exchangeAddr.call(scaledCalldata);
uint256 tokensSwapped = 0;
if (success) {
tokensSwapped = _exData.destAddr.getBalance(address(this)) - tokensBefore;
if (tokensSwapped == 0){
revert ZeroTokensSwapped();
}
}
sendLeftover(_exData.srcAddr, _exData.destAddr, payable(msg.sender));
return (success, tokensSwapped);
}
receive() external virtual payable {}
}