Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 3,104 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Call Sell | 12351782 | 1304 days ago | IN | 0 ETH | 0.00715828 | ||||
Call Sell | 12126717 | 1339 days ago | IN | 0 ETH | 0.01718501 | ||||
Call Sell | 11952960 | 1366 days ago | IN | 0.01 ETH | 0.01768174 | ||||
Call Sell | 11952342 | 1366 days ago | IN | 0.93793 ETH | 0.03209604 | ||||
Call Sell | 11951335 | 1366 days ago | IN | 0.557048 ETH | 0.02842018 | ||||
Call Sell | 11951333 | 1366 days ago | IN | 0.55793 ETH | 0.02846464 | ||||
Call Sell | 11950583 | 1366 days ago | IN | 0.1 ETH | 0.01517788 | ||||
Call Sell | 11949800 | 1366 days ago | IN | 0.15 ETH | 0.02276592 | ||||
Call Sell | 11949797 | 1366 days ago | IN | 0.15 ETH | 0.02323958 | ||||
Call Sell | 11949767 | 1366 days ago | IN | 1.025872 ETH | 0.0327304 | ||||
Call Sell | 11947432 | 1367 days ago | IN | 0.02 ETH | 0.0252795 | ||||
Call Sell | 11947410 | 1367 days ago | IN | 0.02 ETH | 0.02628266 | ||||
Call Sell | 11946141 | 1367 days ago | IN | 0.02 ETH | 0.01559455 | ||||
Call Sell | 11946054 | 1367 days ago | IN | 0.025872 ETH | 0.03006038 | ||||
Call Sell | 11945121 | 1367 days ago | IN | 0.1 ETH | 0.0231924 | ||||
Call Sell | 11943326 | 1367 days ago | IN | 0.04 ETH | 0.0172987 | ||||
Call Sell | 11942753 | 1367 days ago | IN | 0.01 ETH | 0.01817769 | ||||
Call Sell | 11942175 | 1367 days ago | IN | 0.01 ETH | 0.01534827 | ||||
Call Sell | 11940012 | 1368 days ago | IN | 0.4 ETH | 0.03250669 | ||||
Call Sell | 11939978 | 1368 days ago | IN | 0.021315 ETH | 0.06242845 | ||||
Call Sell | 11939349 | 1368 days ago | IN | 0.01 ETH | 0.02857435 | ||||
Call Sell | 11939254 | 1368 days ago | IN | 0.022932 ETH | 0.03002729 | ||||
Call Sell | 11938279 | 1368 days ago | IN | 0.2 ETH | 0.02234173 | ||||
Call Sell | 11938126 | 1368 days ago | IN | 0.005 ETH | 0.0195895 | ||||
Call Sell | 11937182 | 1368 days ago | IN | 0.030282 ETH | 0.0339402 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
11952960 | 1366 days ago | 0.01 ETH | ||||
11952342 | 1366 days ago | 0.93793 ETH | ||||
11951335 | 1366 days ago | 0.557048 ETH | ||||
11951333 | 1366 days ago | 0.55793 ETH | ||||
11950583 | 1366 days ago | 0.1 ETH | ||||
11949800 | 1366 days ago | 0.15 ETH | ||||
11949797 | 1366 days ago | 0.15 ETH | ||||
11949767 | 1366 days ago | 1.025872 ETH | ||||
11947432 | 1367 days ago | 0.02 ETH | ||||
11947410 | 1367 days ago | 0.02 ETH | ||||
11946141 | 1367 days ago | 0.02 ETH | ||||
11946054 | 1367 days ago | 0.025872 ETH | ||||
11945121 | 1367 days ago | 0.1 ETH | ||||
11943326 | 1367 days ago | 0.04 ETH | ||||
11942753 | 1367 days ago | 0.01 ETH | ||||
11942175 | 1367 days ago | 0.01 ETH | ||||
11940012 | 1368 days ago | 0.4 ETH | ||||
11939978 | 1368 days ago | 0.021315 ETH | ||||
11939349 | 1368 days ago | 0.01 ETH | ||||
11939254 | 1368 days ago | 0.022932 ETH | ||||
11938279 | 1368 days ago | 0.2 ETH | ||||
11938126 | 1368 days ago | 0.005 ETH | ||||
11937182 | 1368 days ago | 0.030282 ETH | ||||
11935990 | 1368 days ago | 0.03 ETH | ||||
11935990 | 1368 days ago | 0.072 ETH |
Loading...
Loading
Contract Name:
AllowanceProxy
Compiler Version
v0.6.6+commit.6c089d02
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-08-01 */ pragma solidity ^0.6.0; pragma experimental ABIEncoderV2; interface ERC20 { 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); function decimals() external view returns (uint256 digits); event Approval(address indexed _owner, address indexed _spender, uint256 _value); } library Address { function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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"); return _functionCallWithValue(target, data, value, 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"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // SPDX-License-Identifier: MIT 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 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 mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { 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; // assert(a == b * c + a % b); // There is no case in which this doesn't hold 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; } } library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(ERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. */ function safeApprove(ERC20 token, address spender, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(ERC20 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(ERC20 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(ERC20 token, bytes memory data) private { bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } contract AdminAuth { using SafeERC20 for ERC20; address public owner; address public admin; modifier onlyOwner() { require(owner == msg.sender); _; } constructor() public { owner = msg.sender; } /// @notice Admin is set by owner first time, after that admin is super role and has permission to change owner /// @param _admin Address of multisig that becomes admin function setAdminByOwner(address _admin) public { require(msg.sender == owner); require(admin == address(0)); admin = _admin; } /// @notice Admin is able to set new admin /// @param _admin Address of multisig that becomes new admin function setAdminByAdmin(address _admin) public { require(msg.sender == admin); admin = _admin; } /// @notice Admin is able to change owner /// @param _owner Address of new owner function setOwnerByAdmin(address _owner) public { require(msg.sender == admin); owner = _owner; } /// @notice Destroy the contract function kill() public onlyOwner { selfdestruct(payable(owner)); } /// @notice withdraw stuck funds function withdrawStuckFunds(address _token, uint _amount) public onlyOwner { if (_token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) { payable(owner).transfer(_amount); } else { ERC20(_token).safeTransfer(owner, _amount); } } } abstract contract GasTokenInterface is ERC20 { function free(uint256 value) public virtual returns (bool success); function freeUpTo(uint256 value) public virtual returns (uint256 freed); function freeFrom(address from, uint256 value) public virtual returns (bool success); function freeFromUpTo(address from, uint256 value) public virtual returns (uint256 freed); } contract DSMath { function add(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x + y) >= x); } function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { require((z = x - y) <= x); } function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { require(y == 0 || (z = x * y) / y == x); } function div(uint256 x, uint256 y) internal pure returns (uint256 z) { return x / y; } function min(uint256 x, uint256 y) internal pure returns (uint256 z) { return x <= y ? x : y; } function max(uint256 x, uint256 y) internal pure returns (uint256 z) { return x >= y ? x : y; } function imin(int256 x, int256 y) internal pure returns (int256 z) { return x <= y ? x : y; } function imax(int256 x, int256 y) internal pure returns (int256 z) { return x >= y ? x : y; } uint256 constant WAD = 10**18; uint256 constant RAY = 10**27; function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) { z = add(mul(x, y), WAD / 2) / WAD; } function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) { z = add(mul(x, y), RAY / 2) / RAY; } function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) { z = add(mul(x, WAD), y / 2) / y; } function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) { z = add(mul(x, RAY), y / 2) / y; } // This famous algorithm is called "exponentiation by squaring" // and calculates x^n with x as fixed-point and n as regular unsigned. // // It's O(log n), instead of O(n) for naive repeated multiplication. // // These facts are why it works: // // If n is even, then x^n = (x^2)^(n/2). // If n is odd, then x^n = x * x^(n-1), // and applying the equation for even x gives // x^n = x * (x^2)^((n-1) / 2). // // Also, EVM division is flooring and // floor[(n-1) / 2] = floor[n / 2]. // function rpow(uint256 x, uint256 n) internal pure returns (uint256 z) { z = n % 2 != 0 ? x : RAY; for (n /= 2; n != 0; n /= 2) { x = rmul(x, x); if (n % 2 != 0) { z = rmul(z, x); } } } } abstract contract TokenInterface { function allowance(address, address) public virtual returns (uint256); function balanceOf(address) public virtual 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 virtual payable; function withdraw(uint256) public virtual; } interface ExchangeInterfaceV2 { function sell(address _srcAddr, address _destAddr, uint _srcAmount) external payable returns (uint); function buy(address _srcAddr, address _destAddr, uint _destAmount) external payable returns(uint); function getSellRate(address _srcAddr, address _destAddr, uint _srcAmount) external view returns (uint); function getBuyRate(address _srcAddr, address _destAddr, uint _srcAmount) external view returns (uint); } contract ZrxAllowlist is AdminAuth { mapping (address => bool) public zrxAllowlist; function setAllowlistAddr(address _zrxAddr, bool _state) public onlyOwner { zrxAllowlist[_zrxAddr] = _state; } function isZrxAddr(address _zrxAddr) public view returns (bool) { return zrxAllowlist[_zrxAddr]; } } contract Discount { address public owner; mapping(address => CustomServiceFee) public serviceFees; uint256 constant MAX_SERVICE_FEE = 400; struct CustomServiceFee { bool active; uint256 amount; } constructor() public { owner = msg.sender; } function isCustomFeeSet(address _user) public view returns (bool) { return serviceFees[_user].active; } function getCustomServiceFee(address _user) public view returns (uint256) { return serviceFees[_user].amount; } function setServiceFee(address _user, uint256 _fee) public { require(msg.sender == owner, "Only owner"); require(_fee >= MAX_SERVICE_FEE || _fee == 0); serviceFees[_user] = CustomServiceFee({active: true, amount: _fee}); } function disableServiceFee(address _user) public { require(msg.sender == owner, "Only owner"); serviceFees[_user] = CustomServiceFee({active: false, amount: 0}); } } contract SaverExchangeHelper { using SafeERC20 for ERC20; address public constant KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; address public constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; address public constant DGD_ADDRESS = 0xE0B7927c4aF23765Cb51314A0E0521A9645F0E2A; address payable public constant WALLET_ID = 0x322d58b9E75a6918f7e7849AEe0fF09369977e08; address public constant DISCOUNT_ADDRESS = 0x1b14E8D511c9A4395425314f849bD737BAF8208F; address public constant SAVER_EXCHANGE_REGISTRY = 0x25dd3F51e0C3c3Ff164DDC02A8E4D65Bb9cBB12D; address public constant KYBER_WRAPPER = 0x42A9237b872368E1bec4Ca8D26A928D7d39d338C; address public constant UNISWAP_WRAPPER = 0x880A845A85F843a5c67DB2061623c6Fc3bB4c511; address public constant OASIS_WRAPPER = 0x4c9B55f2083629A1F7aDa257ae984E03096eCD25; address public constant ERC20_PROXY_0X = 0x95E6F48254609A6ee006F7D493c8e5fB97094ceF; address public constant ZRX_ALLOWLIST_ADDR = 0x019739e288973F92bDD3c1d87178E206E51fd911; function getDecimals(address _token) internal view returns (uint256) { if (_token == DGD_ADDRESS) return 9; if (_token == KYBER_ETH_ADDRESS) return 18; return ERC20(_token).decimals(); } function getBalance(address _tokenAddr) internal view returns (uint balance) { if (_tokenAddr == KYBER_ETH_ADDRESS) { balance = address(this).balance; } else { balance = ERC20(_tokenAddr).balanceOf(address(this)); } } function approve0xProxy(address _tokenAddr, uint _amount) internal { if (_tokenAddr != KYBER_ETH_ADDRESS) { ERC20(_tokenAddr).safeApprove(address(ERC20_PROXY_0X), _amount); } } function sendLeftover(address _srcAddr, address _destAddr, address payable _to) internal { // send back any leftover ether or tokens if (address(this).balance > 0) { _to.transfer(address(this).balance); } if (getBalance(_srcAddr) > 0) { ERC20(_srcAddr).safeTransfer(_to, getBalance(_srcAddr)); } if (getBalance(_destAddr) > 0) { ERC20(_destAddr).safeTransfer(_to, getBalance(_destAddr)); } } function sliceUint(bytes memory bs, uint256 start) internal pure returns (uint256) { require(bs.length >= start + 32, "slicing out of range"); uint256 x; assembly { x := mload(add(bs, add(0x20, start))) } return x; } } contract SaverExchangeRegistry is AdminAuth { mapping(address => bool) private wrappers; constructor() public { wrappers[0x880A845A85F843a5c67DB2061623c6Fc3bB4c511] = true; wrappers[0x4c9B55f2083629A1F7aDa257ae984E03096eCD25] = true; wrappers[0x42A9237b872368E1bec4Ca8D26A928D7d39d338C] = true; } function addWrapper(address _wrapper) public onlyOwner { wrappers[_wrapper] = true; } function removeWrapper(address _wrapper) public onlyOwner { wrappers[_wrapper] = false; } function isWrapper(address _wrapper) public view returns(bool) { return wrappers[_wrapper]; } } contract SaverExchangeCore is SaverExchangeHelper, DSMath { // first is empty to keep the legacy order in place enum ExchangeType { _, OASIS, KYBER, UNISWAP, ZEROX } enum ActionType { SELL, BUY } struct ExchangeData { address srcAddr; address destAddr; uint srcAmount; uint destAmount; uint minPrice; address wrapper; address exchangeAddr; bytes callData; uint256 price0x; } /// @notice Internal method that preforms a sell on 0x/on-chain /// @dev Usefull for other DFS contract to integrate for exchanging /// @param exData Exchange data struct /// @return (address, uint) Address of the wrapper used and destAmount function _sell(ExchangeData memory exData) internal returns (address, uint) { address wrapper; uint swapedTokens; bool success; uint tokensLeft = exData.srcAmount; // if selling eth, convert to weth if (exData.srcAddr == KYBER_ETH_ADDRESS) { exData.srcAddr = ethToWethAddr(exData.srcAddr); TokenInterface(WETH_ADDRESS).deposit.value(exData.srcAmount)(); } // Try 0x first and then fallback on specific wrapper if (exData.price0x > 0) { approve0xProxy(exData.srcAddr, exData.srcAmount); (success, swapedTokens, tokensLeft) = takeOrder(exData, address(this).balance, ActionType.SELL); if (success) { wrapper = exData.exchangeAddr; } } // fallback to desired wrapper if 0x failed if (!success) { swapedTokens = saverSwap(exData, ActionType.SELL); wrapper = exData.wrapper; } require(getBalance(exData.destAddr) >= wmul(exData.minPrice, exData.srcAmount), "Final amount isn't correct"); // if anything is left in weth, pull it to user as eth if (getBalance(WETH_ADDRESS) > 0) { TokenInterface(WETH_ADDRESS).withdraw( TokenInterface(WETH_ADDRESS).balanceOf(address(this)) ); } return (wrapper, swapedTokens); } /// @notice Internal method that preforms a buy on 0x/on-chain /// @dev Usefull for other DFS contract to integrate for exchanging /// @param exData Exchange data struct /// @return (address, uint) Address of the wrapper used and srcAmount function _buy(ExchangeData memory exData) internal returns (address, uint) { address wrapper; uint swapedTokens; bool success; require(exData.destAmount != 0, "Dest amount must be specified"); // if selling eth, convert to weth if (exData.srcAddr == KYBER_ETH_ADDRESS) { exData.srcAddr = ethToWethAddr(exData.srcAddr); TokenInterface(WETH_ADDRESS).deposit.value(exData.srcAmount)(); } if (exData.price0x > 0) { approve0xProxy(exData.srcAddr, exData.srcAmount); (success, swapedTokens,) = takeOrder(exData, address(this).balance, ActionType.BUY); if (success) { wrapper = exData.exchangeAddr; } } // fallback to desired wrapper if 0x failed if (!success) { swapedTokens = saverSwap(exData, ActionType.BUY); wrapper = exData.wrapper; } require(getBalance(exData.destAddr) >= exData.destAmount, "Final amount isn't correct"); // if anything is left in weth, pull it to user as eth if (getBalance(WETH_ADDRESS) > 0) { TokenInterface(WETH_ADDRESS).withdraw( TokenInterface(WETH_ADDRESS).balanceOf(address(this)) ); } return (wrapper, getBalance(exData.destAddr)); } /// @notice Takes order from 0x and returns bool indicating if it is successful /// @param _exData Exchange data /// @param _ethAmount Ether fee needed for 0x order function takeOrder( ExchangeData memory _exData, uint256 _ethAmount, ActionType _type ) private returns (bool success, uint256, uint256) { // write in the exact amount we are selling/buing in an order if (_type == ActionType.SELL) { writeUint256(_exData.callData, 36, _exData.srcAmount); } else { writeUint256(_exData.callData, 36, _exData.destAmount); } if (ZrxAllowlist(ZRX_ALLOWLIST_ADDR).isZrxAddr(_exData.exchangeAddr)) { (success, ) = _exData.exchangeAddr.call{value: _ethAmount}(_exData.callData); } else { success = false; } uint256 tokensSwaped = 0; uint256 tokensLeft = _exData.srcAmount; if (success) { // check to see if any _src tokens are left over after exchange tokensLeft = getBalance(_exData.srcAddr); // convert weth -> eth if needed if (_exData.destAddr == KYBER_ETH_ADDRESS) { TokenInterface(WETH_ADDRESS).withdraw( TokenInterface(WETH_ADDRESS).balanceOf(address(this)) ); } // get the current balance of the swaped tokens tokensSwaped = getBalance(_exData.destAddr); } return (success, tokensSwaped, tokensLeft); } /// @notice Returns the best estimated price from 2 exchanges /// @param _amount Amount of source tokens you want to exchange /// @param _srcToken Address of the source token /// @param _destToken Address of the destination token /// @param _exchangeType Which exchange will be used /// @param _type Type of action SELL|BUY /// @return (address, uint) The address of the best exchange and the exchange price function getBestPrice( uint256 _amount, address _srcToken, address _destToken, ExchangeType _exchangeType, ActionType _type ) public returns (address, uint256) { if (_exchangeType == ExchangeType.OASIS) { return (OASIS_WRAPPER, getExpectedRate(OASIS_WRAPPER, _srcToken, _destToken, _amount, _type)); } if (_exchangeType == ExchangeType.KYBER) { return (KYBER_WRAPPER, getExpectedRate(KYBER_WRAPPER, _srcToken, _destToken, _amount, _type)); } if (_exchangeType == ExchangeType.UNISWAP) { return (UNISWAP_WRAPPER, getExpectedRate(UNISWAP_WRAPPER, _srcToken, _destToken, _amount, _type)); } uint expectedRateKyber = getExpectedRate(KYBER_WRAPPER, _srcToken, _destToken, _amount, _type); uint expectedRateUniswap = getExpectedRate(UNISWAP_WRAPPER, _srcToken, _destToken, _amount, _type); uint expectedRateOasis = getExpectedRate(OASIS_WRAPPER, _srcToken, _destToken, _amount, _type); if (_type == ActionType.SELL) { return getBiggestRate(expectedRateKyber, expectedRateUniswap, expectedRateOasis); } else { return getSmallestRate(expectedRateKyber, expectedRateUniswap, expectedRateOasis); } } /// @notice Return the expected rate from the exchange wrapper /// @dev In case of Oasis/Uniswap handles the different precision tokens /// @param _wrapper Address of exchange wrapper /// @param _srcToken From token /// @param _destToken To token /// @param _amount Amount to be exchanged /// @param _type Type of action SELL|BUY function getExpectedRate( address _wrapper, address _srcToken, address _destToken, uint256 _amount, ActionType _type ) public returns (uint256) { bool success; bytes memory result; if (_type == ActionType.SELL) { (success, result) = _wrapper.call(abi.encodeWithSignature( "getSellRate(address,address,uint256)", _srcToken, _destToken, _amount )); } else { (success, result) = _wrapper.call(abi.encodeWithSignature( "getBuyRate(address,address,uint256)", _srcToken, _destToken, _amount )); } if (success) { uint rate = sliceUint(result, 0); if (_wrapper != KYBER_WRAPPER) { rate = rate * (10**(18 - getDecimals(_destToken))); } return rate; } return 0; } /// @notice Calls wraper contract for exchage to preform an on-chain swap /// @param _exData Exchange data struct /// @param _type Type of action SELL|BUY /// @return swapedTokens For Sell that the destAmount, for Buy thats the srcAmount function saverSwap(ExchangeData memory _exData, ActionType _type) internal returns (uint swapedTokens) { require(SaverExchangeRegistry(SAVER_EXCHANGE_REGISTRY).isWrapper(_exData.wrapper), "Wrapper is not valid"); uint ethValue = 0; ERC20(_exData.srcAddr).safeTransfer(_exData.wrapper, _exData.srcAmount); if (_type == ActionType.SELL) { swapedTokens = ExchangeInterfaceV2(_exData.wrapper). sell{value: ethValue}(_exData.srcAddr, _exData.destAddr, _exData.srcAmount); } else { swapedTokens = ExchangeInterfaceV2(_exData.wrapper). buy{value: ethValue}(_exData.srcAddr, _exData.destAddr, _exData.destAmount); } } /// @notice Finds the biggest rate between exchanges, needed for sell rate /// @param _expectedRateKyber Kyber rate /// @param _expectedRateUniswap Uniswap rate /// @param _expectedRateOasis Oasis rate function getBiggestRate( uint _expectedRateKyber, uint _expectedRateUniswap, uint _expectedRateOasis ) internal pure returns (address, uint) { if ( (_expectedRateUniswap >= _expectedRateKyber) && (_expectedRateUniswap >= _expectedRateOasis) ) { return (UNISWAP_WRAPPER, _expectedRateUniswap); } if ( (_expectedRateKyber >= _expectedRateUniswap) && (_expectedRateKyber >= _expectedRateOasis) ) { return (KYBER_WRAPPER, _expectedRateKyber); } if ( (_expectedRateOasis >= _expectedRateKyber) && (_expectedRateOasis >= _expectedRateUniswap) ) { return (OASIS_WRAPPER, _expectedRateOasis); } } /// @notice Finds the smallest rate between exchanges, needed for buy rate /// @param _expectedRateKyber Kyber rate /// @param _expectedRateUniswap Uniswap rate /// @param _expectedRateOasis Oasis rate function getSmallestRate( uint _expectedRateKyber, uint _expectedRateUniswap, uint _expectedRateOasis ) internal pure returns (address, uint) { if ( (_expectedRateUniswap <= _expectedRateKyber) && (_expectedRateUniswap <= _expectedRateOasis) ) { return (UNISWAP_WRAPPER, _expectedRateUniswap); } if ( (_expectedRateKyber <= _expectedRateUniswap) && (_expectedRateKyber <= _expectedRateOasis) ) { return (KYBER_WRAPPER, _expectedRateKyber); } if ( (_expectedRateOasis <= _expectedRateKyber) && (_expectedRateOasis <= _expectedRateUniswap) ) { return (OASIS_WRAPPER, _expectedRateOasis); } } function writeUint256(bytes memory _b, uint256 _index, uint _input) internal pure { if (_b.length < _index + 32) { revert("Incorrent lengt while writting bytes32"); } bytes32 input = bytes32(_input); _index += 32; // Read the bytes32 from array memory assembly { mstore(add(_b, _index), input) } } /// @notice Converts Kybers Eth address -> Weth /// @param _src Input address function ethToWethAddr(address _src) internal pure returns (address) { return _src == KYBER_ETH_ADDRESS ? WETH_ADDRESS : _src; } // solhint-disable-next-line no-empty-blocks receive() external virtual payable {} } contract DefisaverLogger { event LogEvent( address indexed contractAddress, address indexed caller, string indexed logName, bytes data ); // solhint-disable-next-line func-name-mixedcase function Log(address _contract, address _caller, string memory _logName, bytes memory _data) public { emit LogEvent(_contract, _caller, _logName, _data); } } contract GasBurner { // solhint-disable-next-line const-name-snakecase GasTokenInterface public constant gasToken = GasTokenInterface(0x0000000000b3F879cb30FE243b4Dfee438691c04); modifier burnGas(uint _amount) { uint gst2Amount = _amount; if (_amount == 0) { gst2Amount = (gasleft() + 14154) / (2 * 24000 - 6870); gst2Amount = gst2Amount - (gst2Amount / 3); // 33.3% less because of gaslimit != gas_used } if (gasToken.balanceOf(address(this)) >= gst2Amount) { gasToken.free(gst2Amount); } _; } } contract SaverExchange is SaverExchangeCore, AdminAuth, GasBurner { using SafeERC20 for ERC20; uint256 public constant SERVICE_FEE = 800; // 0.125% Fee // solhint-disable-next-line const-name-snakecase DefisaverLogger public constant logger = DefisaverLogger(0x5c55B921f590a89C1Ebe84dF170E655a82b62126); uint public burnAmount = 10; /// @notice Takes a src amount of tokens and converts it into the dest token /// @dev Takes fee from the _srcAmount before the exchange /// @param exData [srcAddr, destAddr, srcAmount, destAmount, minPrice, exchangeType, exchangeAddr, callData, price0x] /// @param _user User address who called the exchange function sell(ExchangeData memory exData, address payable _user) public payable burnGas(burnAmount) { // take fee uint dfsFee = getFee(exData.srcAmount, exData.srcAddr); exData.srcAmount = sub(exData.srcAmount, dfsFee); // Perform the exchange (address wrapper, uint destAmount) = _sell(exData); // send back any leftover ether or tokens sendLeftover(exData.srcAddr, exData.destAddr, _user); // log the event logger.Log(address(this), msg.sender, "ExchangeSell", abi.encode(wrapper, exData.srcAddr, exData.destAddr, exData.srcAmount, destAmount)); } /// @notice Takes a dest amount of tokens and converts it from the src token /// @dev Send always more than needed for the swap, extra will be returned /// @param exData [srcAddr, destAddr, srcAmount, destAmount, minPrice, exchangeType, exchangeAddr, callData, price0x] /// @param _user User address who called the exchange function buy(ExchangeData memory exData, address payable _user) public payable burnGas(burnAmount){ uint dfsFee = getFee(exData.srcAmount, exData.srcAddr); exData.srcAmount = sub(exData.srcAmount, dfsFee); // Perform the exchange (address wrapper, uint srcAmount) = _buy(exData); // send back any leftover ether or tokens sendLeftover(exData.srcAddr, exData.destAddr, _user); // log the event logger.Log(address(this), msg.sender, "ExchangeBuy", abi.encode(wrapper, exData.srcAddr, exData.destAddr, srcAmount, exData.destAmount)); } /// @notice Takes a feePercentage and sends it to wallet /// @param _amount Dai amount of the whole trade /// @param _token Address of the token /// @return feeAmount Amount in Dai owner earned on the fee function getFee(uint256 _amount, address _token) internal returns (uint256 feeAmount) { uint256 fee = SERVICE_FEE; if (Discount(DISCOUNT_ADDRESS).isCustomFeeSet(msg.sender)) { fee = Discount(DISCOUNT_ADDRESS).getCustomServiceFee(msg.sender); } if (fee == 0) { feeAmount = 0; } else { feeAmount = _amount / fee; if (_token == KYBER_ETH_ADDRESS) { WALLET_ID.transfer(feeAmount); } else { ERC20(_token).safeTransfer(WALLET_ID, feeAmount); } } } /// @notice Changes the amount of gas token we burn for each call /// @dev Only callable by the owner /// @param _newBurnAmount New amount of gas tokens to be burned function changeBurnAmount(uint _newBurnAmount) public { require(owner == msg.sender); burnAmount = _newBurnAmount; } } contract AllowanceProxy is AdminAuth { using SafeERC20 for ERC20; address public constant KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // TODO: Real saver exchange address SaverExchange saverExchange = SaverExchange(0x235abFAd01eb1BDa28Ef94087FBAA63E18074926); function callSell(SaverExchangeCore.ExchangeData memory exData) public payable { pullAndSendTokens(exData.srcAddr, exData.srcAmount); saverExchange.sell{value: msg.value}(exData, msg.sender); } function callBuy(SaverExchangeCore.ExchangeData memory exData) public payable { pullAndSendTokens(exData.srcAddr, exData.srcAmount); saverExchange.buy{value: msg.value}(exData, msg.sender); } function pullAndSendTokens(address _tokenAddr, uint _amount) internal { if (_tokenAddr == KYBER_ETH_ADDRESS) { require(msg.value >= _amount, "msg.value smaller than amount"); } else { ERC20(_tokenAddr).safeTransferFrom(msg.sender, address(saverExchange), _amount); } } function ownerChangeExchange(address payable _newExchange) public onlyOwner { saverExchange = SaverExchange(_newExchange); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"KYBER_ETH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"srcAddr","type":"address"},{"internalType":"address","name":"destAddr","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"},{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"address","name":"exchangeAddr","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint256","name":"price0x","type":"uint256"}],"internalType":"struct SaverExchangeCore.ExchangeData","name":"exData","type":"tuple"}],"name":"callBuy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"srcAddr","type":"address"},{"internalType":"address","name":"destAddr","type":"address"},{"internalType":"uint256","name":"srcAmount","type":"uint256"},{"internalType":"uint256","name":"destAmount","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"},{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"address","name":"exchangeAddr","type":"address"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint256","name":"price0x","type":"uint256"}],"internalType":"struct SaverExchangeCore.ExchangeData","name":"exData","type":"tuple"}],"name":"callSell","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"kill","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_newExchange","type":"address"}],"name":"ownerChangeExchange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"setAdminByAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_admin","type":"address"}],"name":"setAdminByOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwnerByAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawStuckFunds","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052600280546001600160a01b031990811673235abfad01eb1bda28ef94087fbaa63e18074926179091556000805490911633179055610b83806100476000396000f3fe60806040526004361061009c5760003560e01c80638da5cb5b116100645780638da5cb5b14610136578063a5a7daeb1461014b578063a707fe111461015e578063a7304bf71461017e578063deca5f881461019e578063f851a440146101be5761009c565b80631e48907b146100a157806329f7fc9e146100c35780633a128322146100ee57806341c0e1b51461010e578063822ad7e114610123575b600080fd5b3480156100ad57600080fd5b506100c16100bc366004610787565b6101d3565b005b3480156100cf57600080fd5b506100d861020c565b6040516100e59190610923565b60405180910390f35b3480156100fa57600080fd5b506100c16101093660046107a3565b610224565b34801561011a57600080fd5b506100c16102c3565b6100c16101313660046107ee565b6102e8565b34801561014257600080fd5b506100d8610366565b6100c16101593660046107ee565b610375565b34801561016a57600080fd5b506100c1610179366004610787565b6103bb565b34801561018a57600080fd5b506100c1610199366004610787565b6103f4565b3480156101aa57600080fd5b506100c16101b9366004610787565b61042d565b3480156101ca57600080fd5b506100d861045a565b6001546001600160a01b031633146101ea57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b6000546001600160a01b0316331461023b57600080fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b038316141561029f57600080546040516001600160a01b039091169183156108fc02918491818181858888f19350505050158015610299573d6000803e3d6000fd5b506102bf565b6000546102bf906001600160a01b0384811691168363ffffffff61046916565b5050565b6000546001600160a01b031633146102da57600080fd5b6000546001600160a01b0316ff5b6102fa816000015182604001516104c4565b60025460405160016247333960e01b031981526001600160a01b039091169063ffb8ccc79034906103319085903390600401610a3f565b6000604051808303818588803b15801561034a57600080fd5b505af115801561035e573d6000803e3d6000fd5b505050505050565b6000546001600160a01b031681565b610387816000015182604001516104c4565b6002546040516311dce64f60e01b81526001600160a01b03909116906311dce64f9034906103319085903390600401610a3f565b6000546001600160a01b031633146103d257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b0316331461040b57600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461044457600080fd5b6001546001600160a01b03161561040b57600080fd5b6001546001600160a01b031681565b6104bf8363a9059cbb60e01b848460405160240161048892919061095b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610539565b505050565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561051757803410156105125760405162461bcd60e51b815260040161050990610987565b60405180910390fd5b6102bf565b6002546102bf906001600160a01b03848116913391168463ffffffff6105c816565b606061058e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166105ef9092919063ffffffff16565b8051909150156104bf57808060200190518101906105ac91906107ce565b6104bf5760405162461bcd60e51b8152600401610509906109f5565b6105e9846323b872dd60e01b85858560405160240161048893929190610937565b50505050565b60606105fe8484600085610608565b90505b9392505050565b6060610613856106d4565b61062f5760405162461bcd60e51b8152600401610509906109be565b60006060866001600160a01b0316858760405161064c9190610907565b60006040518083038185875af1925050503d8060008114610689576040519150601f19603f3d011682016040523d82523d6000602084013e61068e565b606091505b509150915081156106a25791506106cc9050565b8051156106b25780518082602001fd5b8360405162461bcd60e51b81526004016105099190610974565b949350505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906106cc575050151592915050565b803561071881610b35565b92915050565b600082601f83011261072e578081fd5b813567ffffffffffffffff811115610744578182fd5b610757601f8201601f1916602001610ae2565b915080825283602082850101111561076e57600080fd5b8060208401602084013760009082016020015292915050565b600060208284031215610798578081fd5b813561060181610b35565b600080604083850312156107b5578081fd5b82356107c081610b35565b946020939093013593505050565b6000602082840312156107df578081fd5b81518015158114610601578182fd5b6000602082840312156107ff578081fd5b813567ffffffffffffffff80821115610816578283fd5b61012091840180860383131561082a578384fd5b61083383610ae2565b61083d878361070d565b815261084c876020840161070d565b602082015260408201356040820152606082013560608201526080820135608082015261087c8760a0840161070d565b60a082015261088e8760c0840161070d565b60c082015260e08201359350828411156108a6578485fd5b6108b28785840161071e565b60e0820152610100918201359181019190915295945050505050565b6001600160a01b03169052565b600081518084526108f3816020860160208601610b09565b601f01601f19169290920160200192915050565b60008251610919818460208701610b09565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b60006020825261060160208301846108db565b6020808252601d908201527f6d73672e76616c756520736d616c6c6572207468616e20616d6f756e74000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b600060408252610a536040830185516108ce565b6020840151610a6560608401826108ce565b5060408401516080830152606084015160a0830152608084015160c083015260a0840151610a9660e08401826108ce565b5060c0840151610100610aab818501836108ce565b60e0860151610120858101529150610ac76101608501836108db565b908601516101408501529150610601905060208301846108ce565b60405181810167ffffffffffffffff81118282101715610b0157600080fd5b604052919050565b60005b83811015610b24578181015183820152602001610b0c565b838111156105e95750506000910152565b6001600160a01b0381168114610b4a57600080fd5b5056fea2646970667358221220eb7a09dc60d85408087b9904038c487e382ce10fe3c039f1ce09804c83bfaa2064736f6c63430006060033
Deployed Bytecode
0x60806040526004361061009c5760003560e01c80638da5cb5b116100645780638da5cb5b14610136578063a5a7daeb1461014b578063a707fe111461015e578063a7304bf71461017e578063deca5f881461019e578063f851a440146101be5761009c565b80631e48907b146100a157806329f7fc9e146100c35780633a128322146100ee57806341c0e1b51461010e578063822ad7e114610123575b600080fd5b3480156100ad57600080fd5b506100c16100bc366004610787565b6101d3565b005b3480156100cf57600080fd5b506100d861020c565b6040516100e59190610923565b60405180910390f35b3480156100fa57600080fd5b506100c16101093660046107a3565b610224565b34801561011a57600080fd5b506100c16102c3565b6100c16101313660046107ee565b6102e8565b34801561014257600080fd5b506100d8610366565b6100c16101593660046107ee565b610375565b34801561016a57600080fd5b506100c1610179366004610787565b6103bb565b34801561018a57600080fd5b506100c1610199366004610787565b6103f4565b3480156101aa57600080fd5b506100c16101b9366004610787565b61042d565b3480156101ca57600080fd5b506100d861045a565b6001546001600160a01b031633146101ea57600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b6000546001600160a01b0316331461023b57600080fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b038316141561029f57600080546040516001600160a01b039091169183156108fc02918491818181858888f19350505050158015610299573d6000803e3d6000fd5b506102bf565b6000546102bf906001600160a01b0384811691168363ffffffff61046916565b5050565b6000546001600160a01b031633146102da57600080fd5b6000546001600160a01b0316ff5b6102fa816000015182604001516104c4565b60025460405160016247333960e01b031981526001600160a01b039091169063ffb8ccc79034906103319085903390600401610a3f565b6000604051808303818588803b15801561034a57600080fd5b505af115801561035e573d6000803e3d6000fd5b505050505050565b6000546001600160a01b031681565b610387816000015182604001516104c4565b6002546040516311dce64f60e01b81526001600160a01b03909116906311dce64f9034906103319085903390600401610a3f565b6000546001600160a01b031633146103d257600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b0316331461040b57600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b0316331461044457600080fd5b6001546001600160a01b03161561040b57600080fd5b6001546001600160a01b031681565b6104bf8363a9059cbb60e01b848460405160240161048892919061095b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152610539565b505050565b6001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561051757803410156105125760405162461bcd60e51b815260040161050990610987565b60405180910390fd5b6102bf565b6002546102bf906001600160a01b03848116913391168463ffffffff6105c816565b606061058e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166105ef9092919063ffffffff16565b8051909150156104bf57808060200190518101906105ac91906107ce565b6104bf5760405162461bcd60e51b8152600401610509906109f5565b6105e9846323b872dd60e01b85858560405160240161048893929190610937565b50505050565b60606105fe8484600085610608565b90505b9392505050565b6060610613856106d4565b61062f5760405162461bcd60e51b8152600401610509906109be565b60006060866001600160a01b0316858760405161064c9190610907565b60006040518083038185875af1925050503d8060008114610689576040519150601f19603f3d011682016040523d82523d6000602084013e61068e565b606091505b509150915081156106a25791506106cc9050565b8051156106b25780518082602001fd5b8360405162461bcd60e51b81526004016105099190610974565b949350505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906106cc575050151592915050565b803561071881610b35565b92915050565b600082601f83011261072e578081fd5b813567ffffffffffffffff811115610744578182fd5b610757601f8201601f1916602001610ae2565b915080825283602082850101111561076e57600080fd5b8060208401602084013760009082016020015292915050565b600060208284031215610798578081fd5b813561060181610b35565b600080604083850312156107b5578081fd5b82356107c081610b35565b946020939093013593505050565b6000602082840312156107df578081fd5b81518015158114610601578182fd5b6000602082840312156107ff578081fd5b813567ffffffffffffffff80821115610816578283fd5b61012091840180860383131561082a578384fd5b61083383610ae2565b61083d878361070d565b815261084c876020840161070d565b602082015260408201356040820152606082013560608201526080820135608082015261087c8760a0840161070d565b60a082015261088e8760c0840161070d565b60c082015260e08201359350828411156108a6578485fd5b6108b28785840161071e565b60e0820152610100918201359181019190915295945050505050565b6001600160a01b03169052565b600081518084526108f3816020860160208601610b09565b601f01601f19169290920160200192915050565b60008251610919818460208701610b09565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b60006020825261060160208301846108db565b6020808252601d908201527f6d73672e76616c756520736d616c6c6572207468616e20616d6f756e74000000604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b600060408252610a536040830185516108ce565b6020840151610a6560608401826108ce565b5060408401516080830152606084015160a0830152608084015160c083015260a0840151610a9660e08401826108ce565b5060c0840151610100610aab818501836108ce565b60e0860151610120858101529150610ac76101608501836108db565b908601516101408501529150610601905060208301846108ce565b60405181810167ffffffffffffffff81118282101715610b0157600080fd5b604052919050565b60005b83811015610b24578181015183820152602001610b0c565b838111156105e95750506000910152565b6001600160a01b0381168114610b4a57600080fd5b5056fea2646970667358221220eb7a09dc60d85408087b9904038c487e382ce10fe3c039f1ce09804c83bfaa2064736f6c63430006060033
Deployed Bytecode Sourcemap
34464:1238:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;8435:122:0;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;8435:122:0;;;;;;;;:::i;:::-;;34544:86;;5:9:-1;2:2;;;27:1;24;17:12;2:2;34544:86:0;;;:::i;:::-;;;;;;;;;;;;;;;;8730:285;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;8730:285:0;;;;;;;;:::i;8603:80::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;8603:80:0;;;:::i;34777:218::-;;;;;;;;;:::i;7542:20::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;7542:20:0;;;:::i;35003:216::-;;;;;;;;;:::i;35561:138::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;35561:138:0;;;;;;;;:::i;8214:122::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;8214:122:0;;;;;;;;:::i;7931:161::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;-1:-1;7931:161:0;;;;;;;;:::i;7569:20::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;7569:20:0;;;:::i;8435:122::-;8516:5;;-1:-1:-1;;;;;8516:5:0;8502:10;:19;8494:28;;12:1:-1;9;2:12;8494:28:0;8535:5;:14;;-1:-1:-1;;;;;;8535:14:0;-1:-1:-1;;;;;8535:14:0;;;;;;;;;;8435:122::o;34544:86::-;34588:42;34544:86;:::o;8730:285::-;7638:5;;-1:-1:-1;;;;;7638:5:0;7647:10;7638:19;7630:28;;12:1:-1;9;2:12;7630:28:0;8830:42:::1;-1:-1:-1::0;;;;;8820:52:0;::::1;;8816:192;;;8897:5;::::0;;8889:32:::1;::::0;-1:-1:-1;;;;;8897:5:0;;::::1;::::0;8889:32;::::1;;;::::0;8913:7;;8889:32;8897:5;8889:32;8913:7;8897:5;8889:32;::::1;;;;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;8889:32:0;8816:192;;;8981:5;::::0;8954:42:::1;::::0;-1:-1:-1;;;;;8954:26:0;;::::1;::::0;8981:5:::1;8988:7:::0;8954:42:::1;:26;:42;:::i;:::-;8730:285:::0;;:::o;8603:80::-;7638:5;;-1:-1:-1;;;;;7638:5:0;7647:10;7638:19;7630:28;;12:1:-1;9;2:12;7630:28:0;8668:5:::1;::::0;-1:-1:-1;;;;;8668:5:0::1;8647:28;34777:218:::0;34867:51;34885:6;:14;;;34901:6;:16;;;34867:17;:51::i;:::-;34931:13;;:56;;-1:-1:-1;;;;;;34931:56:0;;-1:-1:-1;;;;;34931:13:0;;;;:18;;34957:9;;34931:56;;34968:6;;34976:10;;34931:56;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;34931:56:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;34931:56:0;;;;;34777:218;:::o;7542:20::-;;;-1:-1:-1;;;;;7542:20:0;;:::o;35003:216::-;35092:51;35110:6;:14;;;35126:6;:16;;;35092:17;:51::i;:::-;35156:13;;:55;;-1:-1:-1;;;35156:55:0;;-1:-1:-1;;;;;35156:13:0;;;;:17;;35181:9;;35156:55;;35192:6;;35200:10;;35156:55;;;;35561:138;7638:5;;-1:-1:-1;;;;;7638:5:0;7647:10;7638:19;7630:28;;12:1:-1;9;2:12;7630:28:0;35648:13:::1;:43:::0;;-1:-1:-1;;;;;;35648:43:0::1;-1:-1:-1::0;;;;;35648:43:0;;;::::1;::::0;;;::::1;::::0;;35561:138::o;8214:122::-;8295:5;;-1:-1:-1;;;;;8295:5:0;8281:10;:19;8273:28;;12:1:-1;9;2:12;8273:28:0;8314:5;:14;;-1:-1:-1;;;;;;8314:14:0;-1:-1:-1;;;;;8314:14:0;;;;;;;;;;8214:122::o;7931:161::-;8012:5;;-1:-1:-1;;;;;8012:5:0;7998:10;:19;7990:28;;12:1:-1;9;2:12;7990:28:0;8037:5;;-1:-1:-1;;;;;8037:5:0;:19;8029:28;;12:1:-1;9;2:12;7569:20:0;;;-1:-1:-1;;;;;7569:20:0;;:::o;5682:176::-;5764:86;5784:5;5814:23;;;5839:2;5843:5;5791:58;;;;;;;;;;;;;;-1:-1:-1;;26:21;;;22:32;6:49;;5791:58:0;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;;;;5791:58:0;;;179:29:-1;;;;160:49;;;5764:19:0;:86::i;:::-;5682:176;;;:::o;35227:326::-;-1:-1:-1;;;;;35312:31:0;;34588:42;35312:31;35308:238;;;35381:7;35368:9;:20;;35360:62;;;;-1:-1:-1;;;35360:62:0;;;;;;;;;;;;;;;;;35308:238;;;35510:13;;35455:79;;-1:-1:-1;;;;;35455:34:0;;;;35490:10;;35510:13;35526:7;35455:79;:34;:79;:::i;7054:419::-;7136:23;7162:69;7190:4;7162:69;;;;;;;;;;;;;;;;;7170:5;-1:-1:-1;;;;;7162:27:0;;;:69;;;;;:::i;:::-;7246:17;;7136:95;;-1:-1:-1;7246:21:0;7242:224;;7388:10;7377:30;;;;;;;;;;;;;;7369:85;;;;-1:-1:-1;;;7369:85:0;;;;;;;;5866:204;5966:96;5986:5;6016:27;;;6045:4;6051:2;6055:5;5993:68;;;;;;;;;;;5966:96;5866:204;;;;:::o;2036:196::-;2139:12;2171:53;2194:6;2202:4;2208:1;2211:12;2171:22;:53::i;:::-;2164:60;;2036:196;;;;;;:::o;2798:979::-;2928:12;2961:18;2972:6;2961:10;:18::i;:::-;2953:60;;;;-1:-1:-1;;;2953:60:0;;;;;;;;;3087:12;3101:23;3128:6;-1:-1:-1;;;;;3128:11:0;3148:8;3159:4;3128:36;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;3086:78:0;;;;3179:7;3175:595;;;3210:10;-1:-1:-1;3203:17:0;;-1:-1:-1;3203:17:0;3175:595;3324:17;;:21;3320:439;;3587:10;3581:17;3648:15;3635:10;3631:2;3627:19;3620:44;3535:148;3730:12;3723:20;;-1:-1:-1;;;3723:20:0;;;;;;;;;2798:979;;;;;;;:::o;823:619::-;883:4;1351:20;;1194:66;1391:23;;;;;;:42;;-1:-1:-1;;1418:15:0;;;1383:51;-1:-1:-1;;823:619:0:o;5:130:-1:-;72:20;;97:33;72:20;97:33;;;57:78;;;;;431:440;;532:3;525:4;517:6;513:17;509:27;499:2;;-1:-1;;540:12;499:2;587:6;574:20;12495:18;12487:6;12484:30;12481:2;;;-1:-1;;12517:12;12481:2;609:64;12590:9;12571:17;;-1:-1;;12567:33;12658:4;12648:15;609:64;;;600:73;;693:6;686:5;679:21;797:3;12658:4;788:6;721;779:16;;776:25;773:2;;;814:1;;804:12;773:2;14008:6;12658:4;721:6;717:17;12658:4;755:5;751:16;13985:30;14064:1;14046:16;;;12658:4;14046:16;14039:27;755:5;492:379;-1:-1;;492:379;2693:241;;2797:2;2785:9;2776:7;2772:23;2768:32;2765:2;;;-1:-1;;2803:12;2765:2;85:6;72:20;97:33;124:5;97:33;;3205:366;;;3326:2;3314:9;3305:7;3301:23;3297:32;3294:2;;;-1:-1;;3332:12;3294:2;85:6;72:20;97:33;124:5;97:33;;;3384:63;3484:2;3523:22;;;;2623:20;;-1:-1;;;3288:283;3578:257;;3690:2;3678:9;3669:7;3665:23;3661:32;3658:2;;;-1:-1;;3696:12;3658:2;376:6;370:13;14807:5;13693:13;13686:21;14785:5;14782:32;14772:2;;-1:-1;;14818:12;3842:387;;3976:2;3964:9;3955:7;3951:23;3947:32;3944:2;;;-1:-1;;3982:12;3944:2;4040:17;4027:31;4078:18;;4070:6;4067:30;4064:2;;;-1:-1;;4100:12;4064:2;1042:6;;4181:22;;1021:19;;;1017:32;-1:-1;1014:2;;;-1:-1;;1052:12;1014:2;1080:22;1042:6;1080:22;;;1187:49;1232:3;1208:22;1187:49;;;1169:16;1162:75;1335:49;1380:3;3976:2;1360:9;1356:22;1335:49;;;3976:2;1321:5;1317:16;1310:75;1451:2;1509:9;1505:22;2623:20;1451:2;1470:5;1466:16;1459:75;1601:2;1659:9;1655:22;2623:20;1601:2;1620:5;1616:16;1609:75;1749:3;1808:9;1804:22;2623:20;1749:3;1769:5;1765:16;1758:75;1931:49;1976:3;1897;1956:9;1952:22;1931:49;;;1897:3;1917:5;1913:16;1906:75;2084:49;2129:3;2050;2109:9;2105:22;2084:49;;;2050:3;2070:5;2066:16;2059:75;2227:3;2216:9;2212:19;2199:33;2185:47;;4078:18;2244:6;2241:30;2238:2;;;-1:-1;;2274:12;2238:2;2319:58;2373:3;2364:6;2353:9;2349:22;2319:58;;;2227:3;2301:16;;2294:84;2442:3;2499:22;;;2623:20;2458:18;;;2451:77;;;;2305:5;3938:291;-1:-1;;;;;3938:291;4236:137;-1:-1;;;;;13781:54;4323:45;;4317:56;4610:323;;4742:5;12767:12;13042:6;13037:3;13030:19;4825:52;4870:6;13079:4;13074:3;13070:14;13079:4;4851:5;4847:16;4825:52;;;12590:9;14425:14;-1:-1;;14421:28;4889:39;;;;13079:4;4889:39;;4690:243;-1:-1;;4690:243;8746:262;;5100:5;12767:12;5211:52;5256:6;5251:3;5244:4;5237:5;5233:16;5211:52;;;5275:16;;;;;8871:137;-1:-1;;8871:137;9015:213;-1:-1;;;;;13781:54;;;;4323:45;;9133:2;9118:18;;9104:124;9235:435;-1:-1;;;;;13781:54;;;4323:45;;13781:54;;;;9573:2;9558:18;;4323:45;9656:2;9641:18;;8577:37;;;;9409:2;9394:18;;9380:290;9677:324;-1:-1;;;;;13781:54;;;;4323:45;;9987:2;9972:18;;8577:37;9823:2;9808:18;;9794:207;10008:301;;10146:2;10167:17;10160:47;10221:78;10146:2;10135:9;10131:18;10285:6;10221:78;;10316:407;10507:2;10521:47;;;5882:2;10492:18;;;13030:19;5918:31;13070:14;;;5898:52;5969:12;;;10478:245;10730:407;10921:2;10935:47;;;6220:2;10906:18;;;13030:19;6256:31;13070:14;;;6236:52;6307:12;;;10892:245;11144:407;11335:2;11349:47;;;6558:2;11320:18;;;13030:19;6594:34;13070:14;;;6574:55;-1:-1;;;6649:12;;;6642:34;6695:12;;;11306:245;11558:524;;11780:2;11801:17;11794:47;7067:63;11780:2;11769:9;11765:18;7044:16;7038:23;7067:63;;;7213:4;7206:5;7202:16;7196:23;7225:63;7273:14;11769:9;7273:14;7259:12;7225:63;;;;11780:2;7365:5;7361:16;7355:23;7432:14;11769:9;7432:14;8577:37;7273:14;7525:5;7521:16;7515:23;7592:14;11769:9;7592:14;8577:37;7432:14;7683:5;7679:16;7673:23;7750:14;11769:9;7750:14;8577:37;7592:14;7840:5;7836:16;7830:23;7859:63;7907:14;11769:9;7907:14;7893:12;7859:63;;;;7750:14;8002:5;7998:16;7992:23;8069:14;8021:63;8069:14;11769:9;8069:14;8055:12;8021:63;;;7907:14;8156:16;;8150:23;6967:6;8193:14;;;8186:38;8150:23;-1:-1;8239:71;6958:16;;;8150:23;8239:71;;;8387:18;;;8381:25;8460:16;;;8577:37;11847:126;-1:-1;11984:88;;-1:-1;7213:4;12053:18;;12044:6;11984:88;;12089:256;12151:2;12145:9;12177:17;;;12252:18;12237:34;;12273:22;;;12234:62;12231:2;;;12309:1;;12299:12;12231:2;12151;12318:22;12129:216;;-1:-1;12129:216;14081:268;14146:1;14153:101;14167:6;14164:1;14161:13;14153:101;;;14234:11;;;14228:18;14215:11;;;14208:39;14189:2;14182:10;14153:101;;;14269:6;14266:1;14263:13;14260:2;;;-1:-1;;14146:1;14316:16;;14309:27;14130:219;14462:117;-1:-1;;;;;13781:54;;14521:35;;14511:2;;14570:1;;14560:12;14511:2;14505:74;
Swarm Source
ipfs://eb7a09dc60d85408087b9904038c487e382ce10fe3c039f1ce09804c83bfaa20
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.