More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 785 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Perform Rebalanc... | 8077481 | 1864 days ago | IN | 0.01027813 ETH | 0.00248656 | ||||
Perform Rebalanc... | 7952141 | 1884 days ago | IN | 0 ETH | 0.0013309 | ||||
Perform Rebalanc... | 7865139 | 1898 days ago | IN | 0 ETH | 0.02240438 | ||||
Perform Rebalanc... | 7770632 | 1912 days ago | IN | 0 ETH | 0.00741126 | ||||
Perform Rebalanc... | 7770080 | 1913 days ago | IN | 0 ETH | 0.00709662 | ||||
Perform Rebalanc... | 7770053 | 1913 days ago | IN | 0 ETH | 0.01872275 | ||||
Perform Rebalanc... | 7770045 | 1913 days ago | IN | 0 ETH | 0.01872032 | ||||
Perform Rebalanc... | 7769974 | 1913 days ago | IN | 0 ETH | 0.01671494 | ||||
Perform Rebalanc... | 7736865 | 1918 days ago | IN | 0 ETH | 0.00385899 | ||||
Perform Rebalanc... | 7684207 | 1926 days ago | IN | 3.19425119 ETH | 0.00081752 | ||||
Perform Rebalanc... | 7659618 | 1930 days ago | IN | 0 ETH | 0.00255098 | ||||
Perform Rebalanc... | 7657015 | 1930 days ago | IN | 0.06830339 ETH | 0.0022864 | ||||
Perform Rebalanc... | 7642454 | 1932 days ago | IN | 0 ETH | 0.01612819 | ||||
Perform Rebalanc... | 7640179 | 1933 days ago | IN | 0.06791089 ETH | 0.01066365 | ||||
Perform Rebalanc... | 7632267 | 1934 days ago | IN | 0.16551224 ETH | 0.00134943 | ||||
Perform Rebalanc... | 7622336 | 1936 days ago | IN | 0 ETH | 0.00679194 | ||||
Perform Rebalanc... | 7609358 | 1938 days ago | IN | 0 ETH | 0.00171734 | ||||
Perform Rebalanc... | 7609109 | 1938 days ago | IN | 0 ETH | 0.00166632 | ||||
Perform Rebalanc... | 7607340 | 1938 days ago | IN | 0 ETH | 0.00053061 | ||||
Perform Rebalanc... | 7594532 | 1940 days ago | IN | 0 ETH | 0.00321925 | ||||
Perform Rebalanc... | 7569119 | 1944 days ago | IN | 0 ETH | 0.00181649 | ||||
Perform Rebalanc... | 7566358 | 1944 days ago | IN | 1.34947328 ETH | 0.00204716 | ||||
Perform Rebalanc... | 7541010 | 1948 days ago | IN | 0 ETH | 0.0011882 | ||||
Perform Rebalanc... | 7536503 | 1949 days ago | IN | 0.08658035 ETH | 0.0005403 | ||||
Perform Rebalanc... | 7536293 | 1949 days ago | IN | 0 ETH | 0.00420097 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
16695123 | 533 days ago | 0.00363543 ETH | ||||
16695123 | 533 days ago | 0.00363543 ETH | ||||
16695123 | 533 days ago | 0.11660993 ETH | ||||
16695123 | 533 days ago | 0.11660993 ETH | ||||
8077481 | 1864 days ago | 0.0003292 ETH | ||||
8077481 | 1864 days ago | 0.00994892 ETH | ||||
7952141 | 1884 days ago | 0.07969411 ETH | ||||
7952141 | 1884 days ago | 0.07969411 ETH | ||||
7865139 | 1898 days ago | 0.1382985 ETH | ||||
7865139 | 1898 days ago | 0.13884726 ETH | ||||
7865139 | 1898 days ago | 0.05336029 ETH | ||||
7770632 | 1912 days ago | 1.16277978 ETH | ||||
7770632 | 1912 days ago | 1.16277978 ETH | ||||
7770080 | 1913 days ago | 0.04111644 ETH | ||||
7770080 | 1913 days ago | 0.04127552 ETH | ||||
7770053 | 1913 days ago | 0.3728103 ETH | ||||
7770053 | 1913 days ago | 0.37424743 ETH | ||||
7770045 | 1913 days ago | 0.03825287 ETH | ||||
7770045 | 1913 days ago | 0.03840032 ETH | ||||
7769974 | 1913 days ago | 0.58222592 ETH | ||||
7769974 | 1913 days ago | 0.20940035 ETH | ||||
7769974 | 1913 days ago | 0.37282556 ETH | ||||
7736865 | 1918 days ago | 35.85525514 ETH | ||||
7736865 | 1918 days ago | 32.80770367 ETH | ||||
7736865 | 1918 days ago | 3.01193966 ETH |
Loading...
Loading
Contract Name:
TotlePrimary
Compiler Version
v0.4.25+commit.59dbf8f1
Optimization Enabled:
Yes with 999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2018-12-14 */ pragma solidity 0.4.25; pragma experimental ABIEncoderV2; /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ contract Ownable { address public owner; event OwnershipRenounced(address indexed previousOwner); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ constructor() public { owner = msg.sender; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(msg.sender == owner); _; } /** * @dev Allows the current owner to relinquish control of the contract. * @notice Renouncing to ownership will leave the contract without an owner. * It will not be possible to call the functions with the `onlyOwner` * modifier anymore. */ function renounceOwnership() public onlyOwner { emit OwnershipRenounced(owner); owner = address(0); } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param _newOwner The address to transfer ownership to. */ function transferOwnership(address _newOwner) public onlyOwner { _transferOwnership(_newOwner); } /** * @dev Transfers control of the contract to a newOwner. * @param _newOwner The address to transfer ownership to. */ function _transferOwnership(address _newOwner) internal { require(_newOwner != address(0)); emit OwnershipTransferred(owner, _newOwner); owner = _newOwner; } } library ERC20SafeTransfer { function safeTransfer(address _tokenAddress, address _to, uint256 _value) internal returns (bool success) { require(_tokenAddress.call(bytes4(keccak256("transfer(address,uint256)")), _to, _value)); return fetchReturnData(); } function safeTransferFrom(address _tokenAddress, address _from, address _to, uint256 _value) internal returns (bool success) { require(_tokenAddress.call(bytes4(keccak256("transferFrom(address,address,uint256)")), _from, _to, _value)); return fetchReturnData(); } function safeApprove(address _tokenAddress, address _spender, uint256 _value) internal returns (bool success) { require(_tokenAddress.call(bytes4(keccak256("approve(address,uint256)")), _spender, _value)); return fetchReturnData(); } function fetchReturnData() internal returns (bool success){ assembly { switch returndatasize() case 0 { success := 1 } case 32 { returndatacopy(0, 0, 32) success := mload(0) } default { revert(0, 0) } } } } /// @title A contract which allows its owner to withdraw any ether which is contained inside contract Withdrawable is Ownable { /// @notice Withdraw ether contained in this contract and send it back to owner /// @dev onlyOwner modifier only allows the contract owner to run the code /// @param _token The address of the token that the user wants to withdraw /// @param _amount The amount of tokens that the caller wants to withdraw /// @return bool value indicating whether the transfer was successful function withdrawToken(address _token, uint256 _amount) external onlyOwner returns (bool) { return ERC20SafeTransfer.safeTransfer(_token, owner, _amount); } /// @notice Withdraw ether contained in this contract and send it back to owner /// @dev onlyOwner modifier only allows the contract owner to run the code /// @param _amount The amount of ether that the caller wants to withdraw function withdrawETH(uint256 _amount) external onlyOwner { owner.transfer(_amount); } } /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ contract ERC20 { function totalSupply() public view returns (uint256); function balanceOf(address _who) public view returns (uint256); function allowance(address _owner, address _spender) public view returns (uint256); function transfer(address _to, uint256 _value) public returns (bool); function approve(address _spender, uint256 _value) public returns (bool); function transferFrom(address _from, address _to, uint256 _value) public returns (bool); function decimals() public view returns (uint256); event Transfer( address indexed from, address indexed to, uint256 value ); event Approval( address indexed owner, address indexed spender, uint256 value ); } /* Copyright 2018 ZeroEx Intl. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /// @title TokenTransferProxy - Transfers tokens on behalf of contracts that have been approved via decentralized governance. /// @author Amir Bandeali - <[email protected]>, Will Warren - <[email protected]> contract TokenTransferProxy is Ownable { /// @dev Only authorized addresses can invoke functions with this modifier. modifier onlyAuthorized { require(authorized[msg.sender]); _; } modifier targetAuthorized(address target) { require(authorized[target]); _; } modifier targetNotAuthorized(address target) { require(!authorized[target]); _; } mapping (address => bool) public authorized; address[] public authorities; event LogAuthorizedAddressAdded(address indexed target, address indexed caller); event LogAuthorizedAddressRemoved(address indexed target, address indexed caller); /* * Public functions */ /// @dev Authorizes an address. /// @param target Address to authorize. function addAuthorizedAddress(address target) public onlyOwner targetNotAuthorized(target) { authorized[target] = true; authorities.push(target); emit LogAuthorizedAddressAdded(target, msg.sender); } /// @dev Removes authorizion of an address. /// @param target Address to remove authorization from. function removeAuthorizedAddress(address target) public onlyOwner targetAuthorized(target) { delete authorized[target]; for (uint i = 0; i < authorities.length; i++) { if (authorities[i] == target) { authorities[i] = authorities[authorities.length - 1]; authorities.length -= 1; break; } } emit LogAuthorizedAddressRemoved(target, msg.sender); } /// @dev Calls into ERC20 Token contract, invoking transferFrom. /// @param token Address of token to transfer. /// @param from Address to transfer token from. /// @param to Address to transfer token to. /// @param value Amount of token to transfer. /// @return Success of transfer. function transferFrom( address token, address from, address to, uint value) public onlyAuthorized returns (bool) { require(ERC20SafeTransfer.safeTransferFrom(token, from, to, value)); return true; } /* * Public constant functions */ /// @dev Gets all authorized addresses. /// @return Array of authorized addresses. function getAuthorizedAddresses() public view returns (address[]) { return authorities; } } /** * @title Pausable * @dev Base contract which allows children to implement an emergency stop mechanism. */ contract Pausable is Ownable { event Paused(); event Unpaused(); bool private _paused = false; /** * @return true if the contract is paused, false otherwise. */ function paused() public view returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!_paused, "Contract is paused."); _; } /** * @dev Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { require(_paused, "Contract not paused."); _; } /** * @dev called by the owner to pause, triggers stopped state */ function pause() public onlyOwner whenNotPaused { _paused = true; emit Paused(); } /** * @dev called by the owner to unpause, returns to normal state */ function unpause() public onlyOwner whenPaused { _paused = false; emit Unpaused(); } } /** * @title SafeMath * @dev Math operations with safety checks that revert on error */ library SafeMath { /** * @dev Multiplies two numbers, reverts on overflow. */ 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-solidity/pull/522 if (_a == 0) { return 0; } uint256 c = _a * _b; require(c / _a == _b); return c; } /** * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. */ function div(uint256 _a, uint256 _b) internal pure returns (uint256) { require(_b > 0); // Solidity only automatically asserts when dividing by 0 uint256 c = _a / _b; // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold return c; } /** * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 _a, uint256 _b) internal pure returns (uint256) { require(_b <= _a); uint256 c = _a - _b; return c; } /** * @dev Adds two numbers, reverts on overflow. */ function add(uint256 _a, uint256 _b) internal pure returns (uint256) { uint256 c = _a + _b; require(c >= _a); return c; } /** * @dev Divides two numbers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0); return a % b; } } /* Modified Util contract as used by Kyber Network */ library Utils { uint256 constant internal PRECISION = (10**18); uint256 constant internal MAX_QTY = (10**28); // 10B tokens uint256 constant internal MAX_RATE = (PRECISION * 10**6); // up to 1M tokens per ETH uint256 constant internal MAX_DECIMALS = 18; uint256 constant internal ETH_DECIMALS = 18; uint256 constant internal MAX_UINT = 2**256-1; // Currently constants can't be accessed from other contracts, so providing functions to do that here function precision() internal pure returns (uint256) { return PRECISION; } function max_qty() internal pure returns (uint256) { return MAX_QTY; } function max_rate() internal pure returns (uint256) { return MAX_RATE; } function max_decimals() internal pure returns (uint256) { return MAX_DECIMALS; } function eth_decimals() internal pure returns (uint256) { return ETH_DECIMALS; } function max_uint() internal pure returns (uint256) { return MAX_UINT; } /// @notice Retrieve the number of decimals used for a given ERC20 token /// @dev As decimals are an optional feature in ERC20, this contract uses `call` to /// ensure that an exception doesn't cause transaction failure /// @param token the token for which we should retrieve the decimals /// @return decimals the number of decimals in the given token function getDecimals(address token) internal view returns (uint256 decimals) { bytes4 functionSig = bytes4(keccak256("decimals()")); /// @dev Using assembly due to issues with current solidity `address.call()` /// implementation: https://github.com/ethereum/solidity/issues/2884 assembly { // Pointer to next free memory slot let ptr := mload(0x40) // Store functionSig variable at ptr mstore(ptr,functionSig) let functionSigLength := 0x04 let wordLength := 0x20 let success := call( 5000, // Amount of gas token, // Address to call 0, // ether to send ptr, // ptr to input data functionSigLength, // size of data ptr, // where to store output data (overwrite input) wordLength // size of output data (32 bytes) ) switch success case 0 { decimals := 18 // If the token doesn't implement `decimals()`, return 18 as default } case 1 { decimals := mload(ptr) // Set decimals to return data from call } mstore(0x40,add(ptr,0x04)) // Reset the free memory pointer to the next known free location } } /// @dev Checks that a given address has its token allowance and balance set above the given amount /// @param tokenOwner the address which should have custody of the token /// @param tokenAddress the address of the token to check /// @param tokenAmount the amount of the token which should be set /// @param addressToAllow the address which should be allowed to transfer the token /// @return bool true if the allowance and balance is set, false if not function tokenAllowanceAndBalanceSet( address tokenOwner, address tokenAddress, uint256 tokenAmount, address addressToAllow ) internal view returns (bool) { return ( ERC20(tokenAddress).allowance(tokenOwner, addressToAllow) >= tokenAmount && ERC20(tokenAddress).balanceOf(tokenOwner) >= tokenAmount ); } function calcDstQty(uint srcQty, uint srcDecimals, uint dstDecimals, uint rate) internal pure returns (uint) { if (dstDecimals >= srcDecimals) { require((dstDecimals - srcDecimals) <= MAX_DECIMALS); return (srcQty * rate * (10**(dstDecimals - srcDecimals))) / PRECISION; } else { require((srcDecimals - dstDecimals) <= MAX_DECIMALS); return (srcQty * rate) / (PRECISION * (10**(srcDecimals - dstDecimals))); } } function calcSrcQty(uint dstQty, uint srcDecimals, uint dstDecimals, uint rate) internal pure returns (uint) { //source quantity is rounded up. to avoid dest quantity being too low. uint numerator; uint denominator; if (srcDecimals >= dstDecimals) { require((srcDecimals - dstDecimals) <= MAX_DECIMALS); numerator = (PRECISION * dstQty * (10**(srcDecimals - dstDecimals))); denominator = rate; } else { require((dstDecimals - srcDecimals) <= MAX_DECIMALS); numerator = (PRECISION * dstQty); denominator = (rate * (10**(dstDecimals - srcDecimals))); } return (numerator + denominator - 1) / denominator; //avoid rounding down errors } function calcDestAmount(ERC20 src, ERC20 dest, uint srcAmount, uint rate) internal view returns (uint) { return calcDstQty(srcAmount, getDecimals(src), getDecimals(dest), rate); } function calcSrcAmount(ERC20 src, ERC20 dest, uint destAmount, uint rate) internal view returns (uint) { return calcSrcQty(destAmount, getDecimals(src), getDecimals(dest), rate); } function calcRateFromQty(uint srcAmount, uint destAmount, uint srcDecimals, uint dstDecimals) internal pure returns (uint) { require(srcAmount <= MAX_QTY); require(destAmount <= MAX_QTY); if (dstDecimals >= srcDecimals) { require((dstDecimals - srcDecimals) <= MAX_DECIMALS); return (destAmount * PRECISION / ((10 ** (dstDecimals - srcDecimals)) * srcAmount)); } else { require((srcDecimals - dstDecimals) <= MAX_DECIMALS); return (destAmount * PRECISION * (10 ** (srcDecimals - dstDecimals)) / srcAmount); } } /// @notice Bringing this in from the Math library as we've run out of space in TotlePrimary (see EIP-170) function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } } contract ErrorReporter { function revertTx(string reason) public pure { revert(reason); } } /// @title A contract which can be used to ensure only the TotlePrimary contract can call /// some functions /// @dev Defines a modifier which should be used when only the totle contract should /// able able to call a function contract TotleControl is Ownable { address public totlePrimary; /// @dev A modifier which only allows code execution if msg.sender equals totlePrimary address modifier onlyTotle() { require(msg.sender == totlePrimary); _; } /// @notice Contract constructor /// @dev As this contract inherits ownable, msg.sender will become the contract owner /// @param _totlePrimary the address of the contract to be set as totlePrimary constructor(address _totlePrimary) public { require(_totlePrimary != address(0x0)); totlePrimary = _totlePrimary; } /// @notice A function which allows only the owner to change the address of totlePrimary /// @dev onlyOwner modifier only allows the contract owner to run the code /// @param _totlePrimary the address of the contract to be set as totlePrimary function setTotle( address _totlePrimary ) external onlyOwner { require(_totlePrimary != address(0x0)); totlePrimary = _totlePrimary; } } contract SelectorProvider { bytes4 constant getAmountToGive = bytes4(keccak256("getAmountToGive(bytes)")); bytes4 constant staticExchangeChecks = bytes4(keccak256("staticExchangeChecks(bytes)")); bytes4 constant performBuyOrder = bytes4(keccak256("performBuyOrder(bytes,uint256)")); bytes4 constant performSellOrder = bytes4(keccak256("performSellOrder(bytes,uint256)")); function getSelector(bytes4 genericSelector) public pure returns (bytes4); } /// @title Interface for all exchange handler contracts contract ExchangeHandler is TotleControl, Withdrawable, Pausable { /* * State Variables */ SelectorProvider public selectorProvider; ErrorReporter public errorReporter; /* Logger public logger; */ /* * Modifiers */ modifier onlySelf() { require(msg.sender == address(this)); _; } /// @notice Constructor /// @dev Calls the constructor of the inherited TotleControl /// @param _selectorProvider the provider for this exchanges function selectors /// @param totlePrimary the address of the totlePrimary contract constructor( address _selectorProvider, address totlePrimary, address _errorReporter /* ,address _logger */ ) TotleControl(totlePrimary) public { require(_selectorProvider != address(0x0)); require(_errorReporter != address(0x0)); /* require(_logger != address(0x0)); */ selectorProvider = SelectorProvider(_selectorProvider); errorReporter = ErrorReporter(_errorReporter); /* logger = Logger(_logger); */ } /// @notice Gets the amount that Totle needs to give for this order /// @param genericPayload the data for this order in a generic format /// @return amountToGive amount taker needs to give in order to fill the order function getAmountToGive( bytes genericPayload ) public view onlyTotle whenNotPaused returns (uint256 amountToGive) { bool success; bytes4 functionSelector = selectorProvider.getSelector(this.getAmountToGive.selector); assembly { let functionSelectorLength := 0x04 let functionSelectorOffset := 0x1C let scratchSpace := 0x0 let wordLength := 0x20 let bytesLength := mload(genericPayload) let totalLength := add(functionSelectorLength, bytesLength) let startOfNewData := add(genericPayload, functionSelectorOffset) mstore(add(scratchSpace, functionSelectorOffset), functionSelector) let functionSelectorCorrect := mload(scratchSpace) mstore(genericPayload, functionSelectorCorrect) success := call( gas, address, // This address of the current contract callvalue, startOfNewData, // Start data at the beginning of the functionSelector totalLength, // Total length of all data, including functionSelector scratchSpace, // Use the first word of memory (scratch space) to store our return variable. wordLength // Length of return variable is one word ) amountToGive := mload(scratchSpace) if eq(success, 0) { revert(0, 0) } } } /// @notice Perform exchange-specific checks on the given order /// @dev this should be called to check for payload errors /// @param genericPayload the data for this order in a generic format /// @return checksPassed value representing pass or fail function staticExchangeChecks( bytes genericPayload ) public view onlyTotle whenNotPaused returns (bool checksPassed) { bool success; bytes4 functionSelector = selectorProvider.getSelector(this.staticExchangeChecks.selector); assembly { let functionSelectorLength := 0x04 let functionSelectorOffset := 0x1C let scratchSpace := 0x0 let wordLength := 0x20 let bytesLength := mload(genericPayload) let totalLength := add(functionSelectorLength, bytesLength) let startOfNewData := add(genericPayload, functionSelectorOffset) mstore(add(scratchSpace, functionSelectorOffset), functionSelector) let functionSelectorCorrect := mload(scratchSpace) mstore(genericPayload, functionSelectorCorrect) success := call( gas, address, // This address of the current contract callvalue, startOfNewData, // Start data at the beginning of the functionSelector totalLength, // Total length of all data, including functionSelector scratchSpace, // Use the first word of memory (scratch space) to store our return variable. wordLength // Length of return variable is one word ) checksPassed := mload(scratchSpace) if eq(success, 0) { revert(0, 0) } } } /// @notice Perform a buy order at the exchange /// @param genericPayload the data for this order in a generic format /// @param amountToGiveForOrder amount that should be spent on this order /// @return amountSpentOnOrder the amount that would be spent on the order /// @return amountReceivedFromOrder the amount that was received from this order function performBuyOrder( bytes genericPayload, uint256 amountToGiveForOrder ) public payable onlyTotle whenNotPaused returns (uint256 amountSpentOnOrder, uint256 amountReceivedFromOrder) { bool success; bytes4 functionSelector = selectorProvider.getSelector(this.performBuyOrder.selector); assembly { let callDataOffset := 0x44 let functionSelectorOffset := 0x1C let functionSelectorLength := 0x04 let scratchSpace := 0x0 let wordLength := 0x20 let startOfFreeMemory := mload(0x40) calldatacopy(startOfFreeMemory, callDataOffset, calldatasize) let bytesLength := mload(startOfFreeMemory) let totalLength := add(add(functionSelectorLength, bytesLength), wordLength) mstore(add(scratchSpace, functionSelectorOffset), functionSelector) let functionSelectorCorrect := mload(scratchSpace) mstore(startOfFreeMemory, functionSelectorCorrect) mstore(add(startOfFreeMemory, add(wordLength, bytesLength)), amountToGiveForOrder) let startOfNewData := add(startOfFreeMemory,functionSelectorOffset) success := call( gas, address, // This address of the current contract callvalue, startOfNewData, // Start data at the beginning of the functionSelector totalLength, // Total length of all data, including functionSelector scratchSpace, // Use the first word of memory (scratch space) to store our return variable. mul(wordLength, 0x02) // Length of return variables is two words ) amountSpentOnOrder := mload(scratchSpace) amountReceivedFromOrder := mload(add(scratchSpace, wordLength)) if eq(success, 0) { revert(0, 0) } } } /// @notice Perform a sell order at the exchange /// @param genericPayload the data for this order in a generic format /// @param amountToGiveForOrder amount that should be spent on this order /// @return amountSpentOnOrder the amount that would be spent on the order /// @return amountReceivedFromOrder the amount that was received from this order function performSellOrder( bytes genericPayload, uint256 amountToGiveForOrder ) public onlyTotle whenNotPaused returns (uint256 amountSpentOnOrder, uint256 amountReceivedFromOrder) { bool success; bytes4 functionSelector = selectorProvider.getSelector(this.performSellOrder.selector); assembly { let callDataOffset := 0x44 let functionSelectorOffset := 0x1C let functionSelectorLength := 0x04 let scratchSpace := 0x0 let wordLength := 0x20 let startOfFreeMemory := mload(0x40) calldatacopy(startOfFreeMemory, callDataOffset, calldatasize) let bytesLength := mload(startOfFreeMemory) let totalLength := add(add(functionSelectorLength, bytesLength), wordLength) mstore(add(scratchSpace, functionSelectorOffset), functionSelector) let functionSelectorCorrect := mload(scratchSpace) mstore(startOfFreeMemory, functionSelectorCorrect) mstore(add(startOfFreeMemory, add(wordLength, bytesLength)), amountToGiveForOrder) let startOfNewData := add(startOfFreeMemory,functionSelectorOffset) success := call( gas, address, // This address of the current contract callvalue, startOfNewData, // Start data at the beginning of the functionSelector totalLength, // Total length of all data, including functionSelector scratchSpace, // Use the first word of memory (scratch space) to store our return variable. mul(wordLength, 0x02) // Length of return variables is two words ) amountSpentOnOrder := mload(scratchSpace) amountReceivedFromOrder := mload(add(scratchSpace, wordLength)) if eq(success, 0) { revert(0, 0) } } } } /// @title The primary contract for Totle contract TotlePrimary is Withdrawable, Pausable { /* * State Variables */ mapping(address => bool) public handlerWhitelistMap; address[] public handlerWhitelistArray; address public tokenTransferProxy; ErrorReporter public errorReporter; /* Logger public logger; */ /* * Types */ // Structs struct Trade { bool isSell; address tokenAddress; uint256 tokenAmount; bool optionalTrade; uint256 minimumExchangeRate; uint256 minimumAcceptableTokenAmount; Order[] orders; } struct Order { address exchangeHandler; bytes genericPayload; } struct TradeFlag { bool ignoreTrade; bool[] ignoreOrder; } struct CurrentAmounts { uint256 amountSpentOnTrade; uint256 amountReceivedFromTrade; uint256 amountLeftToSpendOnTrade; } /* * Events */ event LogRebalance( bytes32 id ); /* * Modifiers */ modifier handlerWhitelisted(address handler) { if (!handlerWhitelistMap[handler]) { errorReporter.revertTx("Handler not in whitelist"); } _; } modifier handlerNotWhitelisted(address handler) { if (handlerWhitelistMap[handler]) { errorReporter.revertTx("Handler already whitelisted"); } _; } /// @notice Constructor /// @param _tokenTransferProxy address of the TokenTransferProxy /// @param _errorReporter the address of the error reporter contract constructor (address _tokenTransferProxy, address _errorReporter/*, address _logger*/) public { require(_tokenTransferProxy != address(0x0)); require(_errorReporter != address(0x0)); /* require(_logger != address(0x0)); */ tokenTransferProxy = _tokenTransferProxy; errorReporter = ErrorReporter(_errorReporter); /* logger = Logger(_logger); */ } /* * Public functions */ /// @notice Add an exchangeHandler address to the whitelist /// @dev onlyOwner modifier only allows the contract owner to run the code /// @param handler Address of the exchange handler which permission needs adding function addHandlerToWhitelist(address handler) public onlyOwner handlerNotWhitelisted(handler) { handlerWhitelistMap[handler] = true; handlerWhitelistArray.push(handler); } /// @notice Remove an exchangeHandler address from the whitelist /// @dev onlyOwner modifier only allows the contract owner to run the code /// @param handler Address of the exchange handler which permission needs removing function removeHandlerFromWhitelist(address handler) public onlyOwner handlerWhitelisted(handler) { delete handlerWhitelistMap[handler]; for (uint i = 0; i < handlerWhitelistArray.length; i++) { if (handlerWhitelistArray[i] == handler) { handlerWhitelistArray[i] = handlerWhitelistArray[handlerWhitelistArray.length - 1]; handlerWhitelistArray.length -= 1; break; } } } /// @notice Performs the requested portfolio rebalance /// @param trades A dynamic array of trade structs function performRebalance( Trade[] trades, bytes32 id ) public payable whenNotPaused { emit LogRebalance(id); /* logger.log("Starting Rebalance..."); */ TradeFlag[] memory tradeFlags = initialiseTradeFlags(trades); staticChecks(trades, tradeFlags); /* logger.log("Static checks passed."); */ transferTokens(trades, tradeFlags); /* logger.log("Tokens transferred."); */ uint256 etherBalance = msg.value; /* logger.log("Ether balance arg2: etherBalance.", etherBalance); */ for (uint256 i; i < trades.length; i++) { Trade memory thisTrade = trades[i]; TradeFlag memory thisTradeFlag = tradeFlags[i]; CurrentAmounts memory amounts = CurrentAmounts({ amountSpentOnTrade: 0, amountReceivedFromTrade: 0, amountLeftToSpendOnTrade: thisTrade.isSell ? thisTrade.tokenAmount : calculateMaxEtherSpend(thisTrade, etherBalance) }); /* logger.log("Going to perform trade. arg2: amountLeftToSpendOnTrade", amounts.amountLeftToSpendOnTrade); */ performTrade( thisTrade, thisTradeFlag, amounts ); /* logger.log("Finished performing trade arg2: amountReceivedFromTrade, arg3: amountSpentOnTrade.", amounts.amountReceivedFromTrade, amounts.amountSpentOnTrade); */ if (amounts.amountReceivedFromTrade == 0 && thisTrade.optionalTrade) { /* logger.log("Received 0 from trade and this is an optional trade. Skipping."); */ continue; } /* logger.log( "Going to check trade acceptable amounts arg2: amountSpentOnTrade, arg2: amountReceivedFromTrade.", amounts.amountSpentOnTrade, amounts.amountReceivedFromTrade ); */ if (!checkIfTradeAmountsAcceptable(thisTrade, amounts.amountSpentOnTrade, amounts.amountReceivedFromTrade)) { errorReporter.revertTx("Amounts spent/received in trade not acceptable"); } /* logger.log("Trade passed the acceptable amounts check."); */ if (thisTrade.isSell) { /* logger.log( "This is a sell trade, adding ether to our balance arg2: etherBalance, arg3: amountReceivedFromTrade", etherBalance, amounts.amountReceivedFromTrade ); */ etherBalance = SafeMath.add(etherBalance, amounts.amountReceivedFromTrade); } else { /* logger.log( "This is a buy trade, deducting ether from our balance arg2: etherBalance, arg3: amountSpentOnTrade", etherBalance, amounts.amountSpentOnTrade ); */ etherBalance = SafeMath.sub(etherBalance, amounts.amountSpentOnTrade); } /* logger.log("Transferring tokens to the user arg:6 tokenAddress.", 0,0,0,0, thisTrade.tokenAddress); */ transferTokensToUser( thisTrade.tokenAddress, thisTrade.isSell ? amounts.amountLeftToSpendOnTrade : amounts.amountReceivedFromTrade ); } if(etherBalance > 0) { /* logger.log("Got a positive ether balance, sending to the user arg2: etherBalance.", etherBalance); */ msg.sender.transfer(etherBalance); } } /// @notice Performs static checks on the rebalance payload before execution /// @dev This function is public so a rebalance can be checked before performing a rebalance /// @param trades A dynamic array of trade structs /// @param tradeFlags A dynamic array of flags indicating trade and order status function staticChecks( Trade[] trades, TradeFlag[] tradeFlags ) public view whenNotPaused { bool previousBuyOccured = false; for (uint256 i; i < trades.length; i++) { Trade memory thisTrade = trades[i]; if (thisTrade.isSell) { if (previousBuyOccured) { errorReporter.revertTx("A buy has occured before this sell"); } if (!Utils.tokenAllowanceAndBalanceSet(msg.sender, thisTrade.tokenAddress, thisTrade.tokenAmount, tokenTransferProxy)) { if (!thisTrade.optionalTrade) { errorReporter.revertTx("Taker has not sent allowance/balance on a non-optional trade"); } /* logger.log( "Attempt to sell a token without allowance or sufficient balance arg2: tokenAmount, arg6: tokenAddress . Otional trade, ignoring.", thisTrade.tokenAmount, 0, 0, 0, thisTrade.tokenAddress ); */ tradeFlags[i].ignoreTrade = true; continue; } } else { previousBuyOccured = true; } /* logger.log("Checking that all the handlers are whitelisted."); */ for (uint256 j; j < thisTrade.orders.length; j++) { Order memory thisOrder = thisTrade.orders[j]; if ( !handlerWhitelistMap[thisOrder.exchangeHandler] ) { /* logger.log( "Trying to use a handler that is not whitelisted arg6: exchangeHandler.", 0, 0, 0, 0, thisOrder.exchangeHandler ); */ tradeFlags[i].ignoreOrder[j] = true; continue; } } } } /* * Internal functions */ /// @notice Initialises the trade flag struct /// @param trades the trades used to initialise the flags /// @return tradeFlags the initialised flags function initialiseTradeFlags(Trade[] trades) internal returns (TradeFlag[]) { /* logger.log("Initializing trade flags."); */ TradeFlag[] memory tradeFlags = new TradeFlag[](trades.length); for (uint256 i = 0; i < trades.length; i++) { tradeFlags[i].ignoreOrder = new bool[](trades[i].orders.length); } return tradeFlags; } /// @notice Transfers the given amount of tokens back to the msg.sender /// @param tokenAddress the address of the token to transfer /// @param tokenAmount the amount of tokens to transfer function transferTokensToUser( address tokenAddress, uint256 tokenAmount ) internal { /* logger.log("Transfering tokens to the user arg2: tokenAmount, arg6: .tokenAddress", tokenAmount, 0, 0, 0, tokenAddress); */ if (tokenAmount > 0) { if (!ERC20SafeTransfer.safeTransfer(tokenAddress, msg.sender, tokenAmount)) { errorReporter.revertTx("Unable to transfer tokens to user"); } } } /// @notice Executes the given trade /// @param trade a struct containing information about the trade /// @param tradeFlag a struct containing trade status information /// @param amounts a struct containing information about amounts spent /// and received in the rebalance function performTrade( Trade trade, TradeFlag tradeFlag, CurrentAmounts amounts ) internal { /* logger.log("Performing trade"); */ for (uint256 j; j < trade.orders.length; j++) { /* logger.log("Processing order arg2: orderIndex", j); */ //TODO: Change to the amount of tokens that we are trying to get if( amounts.amountReceivedFromTrade >= trade.minimumAcceptableTokenAmount ) { /* logger.log( "Got the desired amount from the trade arg2: amountReceivedFromTrade, arg3: minimumAcceptableTokenAmount", amounts.amountReceivedFromTrade, trade.minimumAcceptableTokenAmount ); */ return; } if (tradeFlag.ignoreOrder[j] || amounts.amountLeftToSpendOnTrade == 0) { /* logger.log( "Order ignore flag is set to true or have nothing left to spend arg2: amountLeftToSpendOnTrade", amounts.amountLeftToSpendOnTrade ); */ continue; } uint256 amountSpentOnOrder = 0; uint256 amountReceivedFromOrder = 0; Order memory thisOrder = trade.orders[j]; /* logger.log("Setting order exchange handler arg6: exchangeHandler.", 0, 0, 0, 0, thisOrder.exchangeHandler); */ ExchangeHandler thisHandler = ExchangeHandler(thisOrder.exchangeHandler); uint256 amountToGiveForOrder = Utils.min( thisHandler.getAmountToGive(thisOrder.genericPayload), amounts.amountLeftToSpendOnTrade ); if (amountToGiveForOrder == 0) { /* logger.log( "MASSIVE ERROR: amountToGiveForOrder was found to be 0, this hasn't been caught in preTradeChecks, which means dynamicExchangeChecks isnt written correctly!" ); */ continue; } /* logger.log( "Calculating amountToGiveForOrder arg2: amountToGiveForOrder, arg3: amountLeftToSpendOnTrade.", amountToGiveForOrder, amounts.amountLeftToSpendOnTrade ); */ if( !thisHandler.staticExchangeChecks(thisOrder.genericPayload) ) { /* logger.log("Order did not pass checks, skipping."); */ continue; } if (trade.isSell) { /* logger.log("This is a sell.."); */ if (!ERC20SafeTransfer.safeTransfer(trade.tokenAddress,address(thisHandler), amountToGiveForOrder)) { if( !trade.optionalTrade ) errorReporter.revertTx("Unable to transfer tokens to handler"); else { /* logger.log("Unable to transfer tokens to handler but the trade is optional"); */ return; } } /* logger.log("Going to perform a sell order."); */ (amountSpentOnOrder, amountReceivedFromOrder) = thisHandler.performSellOrder(thisOrder.genericPayload, amountToGiveForOrder); /* logger.log("Sell order performed arg2: amountSpentOnOrder, arg3: amountReceivedFromOrder", amountSpentOnOrder, amountReceivedFromOrder); */ } else { /* logger.log("Going to perform a buy order."); */ (amountSpentOnOrder, amountReceivedFromOrder) = thisHandler.performBuyOrder.value(amountToGiveForOrder)(thisOrder.genericPayload, amountToGiveForOrder); /* logger.log("Buy order performed arg2: amountSpentOnOrder, arg3: amountReceivedFromOrder", amountSpentOnOrder, amountReceivedFromOrder); */ } if (amountReceivedFromOrder > 0) { amounts.amountLeftToSpendOnTrade = SafeMath.sub(amounts.amountLeftToSpendOnTrade, amountSpentOnOrder); amounts.amountSpentOnTrade = SafeMath.add(amounts.amountSpentOnTrade, amountSpentOnOrder); amounts.amountReceivedFromTrade = SafeMath.add(amounts.amountReceivedFromTrade, amountReceivedFromOrder); /* logger.log( "Updated amounts arg2: amountLeftToSpendOnTrade, arg3: amountSpentOnTrade, arg4: amountReceivedFromTrade.", amounts.amountLeftToSpendOnTrade, amounts.amountSpentOnTrade, amounts.amountReceivedFromTrade ); */ } } } /// @notice Check if the amounts spent and gained on a trade are within the /// user"s set limits /// @param trade contains information on the given trade /// @param amountSpentOnTrade the amount that was spent on the trade /// @param amountReceivedFromTrade the amount that was received from the trade /// @return bool whether the trade passes the checks function checkIfTradeAmountsAcceptable( Trade trade, uint256 amountSpentOnTrade, uint256 amountReceivedFromTrade ) internal view returns (bool passed) { /* logger.log("Checking if trade amounts are acceptable."); */ uint256 tokenAmount = trade.isSell ? amountSpentOnTrade : amountReceivedFromTrade; passed = tokenAmount >= trade.minimumAcceptableTokenAmount; if( !passed ) { /* logger.log( "Received less than minimum acceptable tokens arg2: tokenAmount , arg3: minimumAcceptableTokenAmount.", tokenAmount, trade.minimumAcceptableTokenAmount ); */ } if (passed) { uint256 tokenDecimals = Utils.getDecimals(ERC20(trade.tokenAddress)); uint256 srcDecimals = trade.isSell ? tokenDecimals : Utils.eth_decimals(); uint256 destDecimals = trade.isSell ? Utils.eth_decimals() : tokenDecimals; uint256 actualRate = Utils.calcRateFromQty(amountSpentOnTrade, amountReceivedFromTrade, srcDecimals, destDecimals); passed = actualRate >= trade.minimumExchangeRate; } if( !passed ) { /* logger.log( "Order rate was lower than minimum acceptable, rate arg2: actualRate, arg3: minimumExchangeRate.", actualRate, trade.minimumExchangeRate ); */ } } /// @notice Iterates through a list of token orders, transfer the SELL orders to this contract & calculates if we have the ether needed /// @param trades A dynamic array of trade structs /// @param tradeFlags A dynamic array of flags indicating trade and order status function transferTokens(Trade[] trades, TradeFlag[] tradeFlags) internal { for (uint256 i = 0; i < trades.length; i++) { if (trades[i].isSell && !tradeFlags[i].ignoreTrade) { /* logger.log( "Transfering tokens arg2: tokenAmount, arg5: tokenAddress.", trades[i].tokenAmount, 0, 0, 0, trades[i].tokenAddress ); */ if ( !TokenTransferProxy(tokenTransferProxy).transferFrom( trades[i].tokenAddress, msg.sender, address(this), trades[i].tokenAmount ) ) { errorReporter.revertTx("TTP unable to transfer tokens to primary"); } } } } /// @notice Calculates the maximum amount that should be spent on a given buy trade /// @param trade the buy trade to return the spend amount for /// @param etherBalance the amount of ether that we currently have to spend /// @return uint256 the maximum amount of ether we should spend on this trade function calculateMaxEtherSpend(Trade trade, uint256 etherBalance) internal view returns (uint256) { /// @dev This function should never be called for a sell assert(!trade.isSell); uint256 tokenDecimals = Utils.getDecimals(ERC20(trade.tokenAddress)); uint256 srcDecimals = trade.isSell ? tokenDecimals : Utils.eth_decimals(); uint256 destDecimals = trade.isSell ? Utils.eth_decimals() : tokenDecimals; uint256 maxSpendAtMinRate = Utils.calcSrcQty(trade.tokenAmount, srcDecimals, destDecimals, trade.minimumExchangeRate); return Utils.min(etherBalance, maxSpendAtMinRate); } /* * Payable fallback function */ /// @notice payable fallback to allow handler or exchange contracts to return ether /// @dev only accounts containing code (ie. contracts) can send ether to this contract function() public payable whenNotPaused { // Check in here that the sender is a contract! (to stop accidents) uint256 size; address sender = msg.sender; assembly { size := extcodesize(sender) } if (size == 0) { errorReporter.revertTx("EOA cannot send ether to primary fallback"); } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":true,"inputs":[{"components":[{"name":"isSell","type":"bool"},{"name":"tokenAddress","type":"address"},{"name":"tokenAmount","type":"uint256"},{"name":"optionalTrade","type":"bool"},{"name":"minimumExchangeRate","type":"uint256"},{"name":"minimumAcceptableTokenAmount","type":"uint256"},{"components":[{"name":"exchangeHandler","type":"address"},{"name":"genericPayload","type":"bytes"}],"name":"orders","type":"tuple[]"}],"name":"trades","type":"tuple[]"},{"components":[{"name":"ignoreTrade","type":"bool"},{"name":"ignoreOrder","type":"bool[]"}],"name":"tradeFlags","type":"tuple[]"}],"name":"staticChecks","outputs":[],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"components":[{"name":"isSell","type":"bool"},{"name":"tokenAddress","type":"address"},{"name":"tokenAmount","type":"uint256"},{"name":"optionalTrade","type":"bool"},{"name":"minimumExchangeRate","type":"uint256"},{"name":"minimumAcceptableTokenAmount","type":"uint256"},{"components":[{"name":"exchangeHandler","type":"address"},{"name":"genericPayload","type":"bytes"}],"name":"orders","type":"tuple[]"}],"name":"trades","type":"tuple[]"},{"name":"id","type":"bytes32"}],"name":"performRebalance","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"tokenTransferProxy","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"handlerWhitelistArray","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"handler","type":"address"}],"name":"addHandlerToWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"errorReporter","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"handler","type":"address"}],"name":"removeHandlerFromWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"handlerWhitelistMap","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_amount","type":"uint256"}],"name":"withdrawToken","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"withdrawETH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_tokenTransferProxy","type":"address"},{"name":"_errorReporter","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"id","type":"bytes32"}],"name":"LogRebalance","type":"event"},{"anonymous":false,"inputs":[],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]
Contract Creation Code
60806040526000805460a060020a60ff02191690553480156200002157600080fd5b50604051604080620028a98339810180604052620000439190810190620000c8565b60008054600160a060020a03191633179055600160a060020a03821615156200006b57600080fd5b600160a060020a03811615156200008157600080fd5b60038054600160a060020a03938416600160a060020a0319918216179091556004805492909316911617905562000113565b6000620000c1825162000107565b9392505050565b60008060408385031215620000dc57600080fd5b6000620000ea8585620000b3565b9250506020620000fd85828601620000b3565b9150509250929050565b600160a060020a031690565b61278680620001236000396000f3006080604052600436106100e55763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630bc8f44681146101d05780630ccd90e3146101f25780630eefdbad1461020557806315447070146102305780631b468ed81461025057806332a7f760146102705780633f4ba83a1461029257806355beb15d146102a75780635c975abb146102c757806370332e30146102e9578063715018a6146103095780638456cb591461031e5780638da5cb5b146103335780639e281a9814610348578063f14210a614610368578063f2fde38b14610388575b60008054819074010000000000000000000000000000000000000000900460ff1615610146576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161013d90612666565b60405180910390fd5b505033803b908115156101cc57600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe9161019991016125f6565b600060405180830381600087803b1580156101b357600080fd5b505af11580156101c7573d6000803e3d6000fd5b505050505b5050005b3480156101dc57600080fd5b506101f06101eb36600461206c565b6103a8565b005b6101f06102003660046120cb565b610648565b34801561021157600080fd5b5061021a6108e7565b6040516102279190612504565b60405180910390f35b34801561023c57600080fd5b5061021a61024b36600461211f565b6108f6565b34801561025c57600080fd5b506101f061026b366004612014565b61091e565b34801561027c57600080fd5b50610285610a43565b60405161022791906125b8565b34801561029e57600080fd5b506101f0610a52565b3480156102b357600080fd5b506101f06102c2366004612014565b610b06565b3480156102d357600080fd5b506102dc610cb3565b604051610227919061256b565b3480156102f557600080fd5b506102dc610304366004612014565b610cd5565b34801561031557600080fd5b506101f0610cea565b34801561032a57600080fd5b506101f0610d56565b34801561033f57600080fd5b5061021a610e20565b34801561035457600080fd5b506102dc610363366004612032565b610e2f565b34801561037457600080fd5b506101f061038336600461211f565b610e68565b34801561039457600080fd5b506101f06103a3366004612014565b610ebc565b6000806103b3611bca565b60006103bd611c15565b60005474010000000000000000000000000000000000000000900460ff1615610412576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161013d90612666565b600094505b865184101561063f57868481518110151561042e57fe5b9060200190602002015192508260000151156105995784156104c357600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe916104909101612636565b600060405180830381600087803b1580156104aa57600080fd5b505af11580156104be573d6000803e3d6000fd5b505050505b602083015160408401516003546104e69233929091600160a060020a0316610edf565b1515610594578260600151151561057057600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe9161053d9101612626565b600060405180830381600087803b15801561055757600080fd5b505af115801561056b573d6000803e3d6000fd5b505050505b6001868581518110151561058057fe5b602090810290910101519015159052610634565b61059e565b600194505b8260c00151518210156106345760c08301518051839081106105bc57fe5b60209081029091018101518051600160a060020a03166000908152600190925260409091205490915060ff16151561062957600186858151811015156105fe57fe5b90602001906020020151602001518381518110151561061957fe5b9115156020928302909101909101525b60019091019061059e565b600190930192610417565b50505050505050565b6060600080610655611bca565b61065d611c15565b610665611c2d565b60005474010000000000000000000000000000000000000000900460ff16156106ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161013d90612666565b7fa959ee32a2995f503e81e3e83b690f875793f02ee5219df0de8ae534489c04ae876040516106e99190612579565b60405180910390a16106fa8861102e565b955061070688876103a8565b61071088876110f0565b3494505b87518410156108a557878481518110151561072b57fe5b906020019060200201519250858481518110151561074557fe5b906020019060200201519150606060405190810160405280600081526020016000815260200184600001516107835761077e858861129f565b610789565b84604001515b90529050610798838383611320565b60208101511580156107ab575082606001515b156107b55761089a565b6107c8838260000151836020015161174a565b151561084757600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe916108149101612606565b600060405180830381600087803b15801561082e57600080fd5b505af1158015610842573d6000803e3d6000fd5b505050505b8251156108635761085c8582602001516117d9565b9450610874565b6108718582600001516117f2565b94505b61089a8360200151846000015161088f578260200151610895565b82604001515b611809565b600190930192610714565b60008511156108dd57604051339086156108fc029087906000818181858888f193505050501580156108db573d6000803e3d6000fd5b505b5050505050505050565b600354600160a060020a031681565b600280548290811061090457fe5b600091825260209091200154600160a060020a0316905081565b600054600160a060020a0316331461093557600080fd5b600160a060020a038116600090815260016020526040902054819060ff16156109d157600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe9161099e9101612616565b600060405180830381600087803b1580156109b857600080fd5b505af11580156109cc573d6000803e3d6000fd5b505050505b50600160a060020a031660008181526001602081905260408220805460ff1916821790556002805491820181559091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace01805473ffffffffffffffffffffffffffffffffffffffff19169091179055565b600454600160a060020a031681565b600054600160a060020a03163314610a6957600080fd5b60005474010000000000000000000000000000000000000000900460ff161515610abf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161013d906125c6565b6000805474ff0000000000000000000000000000000000000000191681556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d169339190a1565b60008054600160a060020a03163314610b1e57600080fd5b600160a060020a038216600090815260016020526040902054829060ff161515610bbb57600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe91610b889101612656565b600060405180830381600087803b158015610ba257600080fd5b505af1158015610bb6573d6000803e3d6000fd5b505050505b600160a060020a0383166000908152600160205260408120805460ff1916905591505b600254821015610cae5782600160a060020a0316600283815481101515610c0157fe5b600091825260209091200154600160a060020a03161415610ca357600280546000198101908110610c2e57fe5b60009182526020909120015460028054600160a060020a039092169184908110610c5457fe5b6000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055600280546000190190610c9d9082611c4f565b50610cae565b600190910190610bde565b505050565b60005474010000000000000000000000000000000000000000900460ff165b90565b60016020526000908152604090205460ff1681565b600054600160a060020a03163314610d0157600080fd5b60008054604051600160a060020a03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600054600160a060020a03163314610d6d57600080fd5b60005474010000000000000000000000000000000000000000900460ff1615610dc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161013d90612666565b6000805474ff00000000000000000000000000000000000000001916740100000000000000000000000000000000000000001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b600054600160a060020a031681565b60008054600160a060020a03163314610e4757600080fd5b600054610e5f908490600160a060020a03168461189f565b90505b92915050565b600054600160a060020a03163314610e7f57600080fd5b60008054604051600160a060020a039091169183156108fc02918491818181858888f19350505050158015610eb8573d6000803e3d6000fd5b5050565b600054600160a060020a03163314610ed357600080fd5b610edc81611979565b50565b60008284600160a060020a031663dd62ed3e87856040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401610f2c929190612512565b602060405180830381600087803b158015610f4657600080fd5b505af1158015610f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f7e919081019061213d565b1015801561102357506040517f70a082310000000000000000000000000000000000000000000000000000000081528390600160a060020a038616906370a0823190610fce908990600401612504565b602060405180830381600087803b158015610fe857600080fd5b505af1158015610ffc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611020919081019061213d565b10155b90505b949350505050565b6060806000835160405190808252806020026020018201604052801561106e57816020015b61105b611c15565b8152602001906001900390816110535790505b509150600090505b83518110156110e957838181518110151561108d57fe5b9060200190602002015160c00151516040519080825280602002602001820160405280156110c5578160200160208202803883390190505b5082828151811015156110d457fe5b60209081029091018101510152600101611076565b5092915050565b60005b8251811015610cae57828181518110151561110a57fe5b602090810290910101515180156111375750818181518110151561112a57fe5b6020908102909101015151155b15611297576003548351600160a060020a03909116906315dacbea9085908490811061115f57fe5b90602001906020020151602001513330878681518110151561117d57fe5b90602001906020020151604001516040518563ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016111c6949392919061252d565b602060405180830381600087803b1580156111e057600080fd5b505af11580156111f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506112189190810190612101565b151561129757600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe916112649101612646565b600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b505050505b6001016110f3565b600080600080600086600001511515156112b557fe5b6112c287602001516119f6565b87519094506112d8576112d3611a6e565b6112da565b835b87519093506112e957836112f1565b6112f1611a6e565b9150611307876040015184848a60800151611a73565b90506113138682611aea565b94505b5050505092915050565b600080600061132d611c15565b6000805b8860c00151518610156108db5760a0890151602088015110611352576108db565b602088015180518790811061136357fe5b906020019060200201518061137a57506040870151155b156113845761173f565b60c08901518051600096508695508790811061139c57fe5b9060200190602002015192508260000151915061145a82600160a060020a031663bd4191da85602001516040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016113fe9190612587565b602060405180830381600087803b15801561141857600080fd5b505af115801561142c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611450919081019061213d565b8860400151611aea565b90508015156114685761173f565b60208301516040517fbeb2c9b0000000000000000000000000000000000000000000000000000000008152600160a060020a0384169163beb2c9b0916114b19190600401612587565b602060405180830381600087803b1580156114cb57600080fd5b505af11580156114df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115039190810190612101565b151561150e5761173f565b88511561165d576115248960200151838361189f565b15156115b757886060015115156115b257600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe9161157b91016125e6565b600060405180830381600087803b15801561159557600080fd5b505af11580156115a9573d6000803e3d6000fd5b505050506115b7565b6108db565b60208301516040517f7cdcffbb000000000000000000000000000000000000000000000000000000008152600160a060020a03841691637cdcffbb9161160291908590600401612598565b6040805180830381600087803b15801561161b57600080fd5b505af115801561162f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611653919081019061215b565b9095509350611700565b60208301516040517fd592a1ea000000000000000000000000000000000000000000000000000000008152600160a060020a0384169163d592a1ea9184916116a9918390600401612598565b60408051808303818588803b1580156116c157600080fd5b505af11580156116d5573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052506116fa919081019061215b565b90955093505b600084111561173f576117178760400151866117f2565b6040880152865161172890866117d9565b8752602087015161173990856117d9565b60208801525b600190950194611331565b60008060008060008088600001516117625786611764565b875b94508860a00151851015955085156117cd5761178389602001516119f6565b895190945061179957611794611a6e565b61179b565b835b89519093506117aa57836117b2565b6117b2611a6e565b91506117c088888585611b00565b9050886080015181101595505b50505050509392505050565b6000828201838110156117eb57600080fd5b9392505050565b6000808383111561180257600080fd5b5050900390565b6000811115610eb85761181d82338361189f565b1515610eb857600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe9161186991016125d6565b600060405180830381600087803b15801561188357600080fd5b505af1158015611897573d6000803e3d6000fd5b505050505050565b600083600160a060020a031660405180807f7472616e7366657228616464726573732c75696e743235362900000000000000815250601901905060405180910390207c0100000000000000000000000000000000000000000000000000000000900484846040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083600160a060020a0316600160a060020a03168152602001828152602001925050506000604051808303816000875af192505050151561197157600080fd5b611026611b9b565b600160a060020a038116151561198e57600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b604080517f646563696d616c732829000000000000000000000000000000000000000000008152905190819003600a0181208082526000916004602080838381888a611388f1808015611a505760018114611a5957611a5e565b60129650611a5e565b845196505b5050505060040160405250919050565b601290565b60008080848610611aa85760128587031115611a8e57600080fd5b5050828403600a0a8502670de0b6b3a76400000282611ace565b60128686031115611ab857600080fd5b5050670de0b6b3a76400008502848403600a0a83025b80600182840103811515611ade57fe5b04979650505050505050565b6000818310611af95781610e5f565b5090919050565b60006b204fce5e3e25026110000000851115611b1b57600080fd5b6b204fce5e3e25026110000000841115611b3457600080fd5b828210611b6f5760128383031115611b4b57600080fd5b84838303600a0a02670de0b6b3a76400008502811515611b6757fe5b049050611026565b60128284031115611b7f57600080fd5b84828403600a0a670de0b6b3a7640000860202811515611b6757fe5b60003d8015611bb15760208114611bba57600080fd5b60019150611bc6565b60206000803e60005191505b5090565b60e0604051908101604052806000151581526020016000600160a060020a03168152602001600081526020016000151581526020016000815260200160008152602001606081525090565b60408051808201909152600081526060602082015290565b6060604051908101604052806000815260200160008152602001600081525090565b815481835581811115610cae57600083815260209020610cae918101908301610cd291905b80821115611bc65760008155600101611c74565b6000610e5f82356126ea565b6000601f82018313611ca557600080fd5b8135611cb8611cb38261269d565b612676565b91508181835260208401935060208101905083856020840282011115611cdd57600080fd5b60005b838110156113165781611cf38882611e20565b8452506020928301929190910190600101611ce0565b6000601f82018313611d1a57600080fd5b8135611d28611cb38261269d565b81815260209384019390925082018360005b838110156113165781358601611d508882611e93565b8452506020928301929190910190600101611d3a565b6000601f82018313611d7757600080fd5b8135611d85611cb38261269d565b81815260209384019390925082018360005b838110156113165781358601611dad8882611ef2565b8452506020928301929190910190600101611d97565b6000601f82018313611dd457600080fd5b8135611de2611cb38261269d565b81815260209384019390925082018360005b838110156113165781358601611e0a8882611f45565b8452506020928301929190910190600101611df4565b6000610e5f82356126f6565b6000610e5f82516126f6565b6000610e5f8235610cd2565b6000601f82018313611e5557600080fd5b8135611e63611cb3826126be565b91508082526020830160208301858383011115611e7f57600080fd5b611e8a838284612706565b50505092915050565b600060408284031215611ea557600080fd5b611eaf6040612676565b90506000611ebd8484611c88565b825250602082013567ffffffffffffffff811115611eda57600080fd5b611ee684828501611e44565b60208301525092915050565b600060408284031215611f0457600080fd5b611f0e6040612676565b90506000611f1c8484611e20565b825250602082013567ffffffffffffffff811115611f3957600080fd5b611ee684828501611c94565b600060e08284031215611f5757600080fd5b611f6160e0612676565b90506000611f6f8484611e20565b8252506020611f8084848301611c88565b6020830152506040611f9484828501611e38565b6040830152506060611fa884828501611e20565b6060830152506080611fbc84828501611e38565b60808301525060a0611fd084828501611e38565b60a08301525060c082013567ffffffffffffffff811115611ff057600080fd5b611ffc84828501611d09565b60c08301525092915050565b6000610e5f8251610cd2565b60006020828403121561202657600080fd5b60006110268484611c88565b6000806040838503121561204557600080fd5b60006120518585611c88565b925050602061206285828601611e38565b9150509250929050565b6000806040838503121561207f57600080fd5b823567ffffffffffffffff81111561209657600080fd5b6120a285828601611dc3565b925050602083013567ffffffffffffffff8111156120bf57600080fd5b61206285828601611d66565b600080604083850312156120de57600080fd5b823567ffffffffffffffff8111156120f557600080fd5b61205185828601611dc3565b60006020828403121561211357600080fd5b60006110268484611e2c565b60006020828403121561213157600080fd5b60006110268484611e38565b60006020828403121561214f57600080fd5b60006110268484612008565b6000806040838503121561216e57600080fd5b600061217a8585612008565b925050602061206285828601612008565b612194816126ea565b82525050565b612194816126f6565b61219481610cd2565b60006121b7826126e6565b8084526121cb816020860160208601612712565b6121d481612742565b9093016020019392505050565b612194816126fb565b601481527f436f6e7472616374206e6f74207061757365642e000000000000000000000000602082015260400190565b602181527f556e61626c6520746f207472616e7366657220746f6b656e7320746f2075736560208201527f7200000000000000000000000000000000000000000000000000000000000000604082015260600190565b602481527f556e61626c6520746f207472616e7366657220746f6b656e7320746f2068616e60208201527f646c657200000000000000000000000000000000000000000000000000000000604082015260600190565b602981527f454f412063616e6e6f742073656e6420657468657220746f207072696d61727960208201527f2066616c6c6261636b0000000000000000000000000000000000000000000000604082015260600190565b602e81527f416d6f756e7473207370656e742f726563656976656420696e2074726164652060208201527f6e6f742061636365707461626c65000000000000000000000000000000000000604082015260600190565b601b81527f48616e646c657220616c72656164792077686974656c69737465640000000000602082015260400190565b603c81527f54616b657220686173206e6f742073656e7420616c6c6f77616e63652f62616c60208201527f616e6365206f6e2061206e6f6e2d6f7074696f6e616c20747261646500000000604082015260600190565b602281527f412062757920686173206f636375726564206265666f7265207468697320736560208201527f6c6c000000000000000000000000000000000000000000000000000000000000604082015260600190565b602881527f54545020756e61626c6520746f207472616e7366657220746f6b656e7320746f60208201527f207072696d617279000000000000000000000000000000000000000000000000604082015260600190565b601881527f48616e646c6572206e6f7420696e2077686974656c6973740000000000000000602082015260400190565b601381527f436f6e7472616374206973207061757365642e00000000000000000000000000602082015260400190565b60208101610e62828461218b565b60408101612520828561218b565b6117eb602083018461218b565b6080810161253b828761218b565b612548602083018661218b565b612555604083018561218b565b61256260608301846121a3565b95945050505050565b60208101610e62828461219a565b60208101610e6282846121a3565b60208082528101610e5f81846121ac565b604080825281016125a981856121ac565b90506117eb60208301846121a3565b60208101610e6282846121e1565b60208082528101610e62816121ea565b60208082528101610e628161221a565b60208082528101610e6281612270565b60208082528101610e62816122c6565b60208082528101610e628161231c565b60208082528101610e6281612372565b60208082528101610e62816123a2565b60208082528101610e62816123f8565b60208082528101610e628161244e565b60208082528101610e62816124a4565b60208082528101610e62816124d4565b60405181810167ffffffffffffffff8111828210171561269557600080fd5b604052919050565b600067ffffffffffffffff8211156126b457600080fd5b5060209081020190565b600067ffffffffffffffff8211156126d557600080fd5b506020601f91909101601f19160190565b5190565b600160a060020a031690565b151590565b6000610e62826126ea565b82818337506000910152565b60005b8381101561272d578181015183820152602001612715565b8381111561273c576000848401525b50505050565b601f01601f1916905600a265627a7a7230582063af84031bd747b60bdcb1ca40cc6a87f90c113b8b2ae5c3d9c85750ad819fd66c6578706572696d656e74616cf5003700000000000000000000000074758acfce059f503a7e6b0fc2c8737600f9f2c400000000000000000000000076b87390400359941561956632bbbe3f42439e32
Deployed Bytecode
0x6080604052600436106100e55763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630bc8f44681146101d05780630ccd90e3146101f25780630eefdbad1461020557806315447070146102305780631b468ed81461025057806332a7f760146102705780633f4ba83a1461029257806355beb15d146102a75780635c975abb146102c757806370332e30146102e9578063715018a6146103095780638456cb591461031e5780638da5cb5b146103335780639e281a9814610348578063f14210a614610368578063f2fde38b14610388575b60008054819074010000000000000000000000000000000000000000900460ff1615610146576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161013d90612666565b60405180910390fd5b505033803b908115156101cc57600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe9161019991016125f6565b600060405180830381600087803b1580156101b357600080fd5b505af11580156101c7573d6000803e3d6000fd5b505050505b5050005b3480156101dc57600080fd5b506101f06101eb36600461206c565b6103a8565b005b6101f06102003660046120cb565b610648565b34801561021157600080fd5b5061021a6108e7565b6040516102279190612504565b60405180910390f35b34801561023c57600080fd5b5061021a61024b36600461211f565b6108f6565b34801561025c57600080fd5b506101f061026b366004612014565b61091e565b34801561027c57600080fd5b50610285610a43565b60405161022791906125b8565b34801561029e57600080fd5b506101f0610a52565b3480156102b357600080fd5b506101f06102c2366004612014565b610b06565b3480156102d357600080fd5b506102dc610cb3565b604051610227919061256b565b3480156102f557600080fd5b506102dc610304366004612014565b610cd5565b34801561031557600080fd5b506101f0610cea565b34801561032a57600080fd5b506101f0610d56565b34801561033f57600080fd5b5061021a610e20565b34801561035457600080fd5b506102dc610363366004612032565b610e2f565b34801561037457600080fd5b506101f061038336600461211f565b610e68565b34801561039457600080fd5b506101f06103a3366004612014565b610ebc565b6000806103b3611bca565b60006103bd611c15565b60005474010000000000000000000000000000000000000000900460ff1615610412576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161013d90612666565b600094505b865184101561063f57868481518110151561042e57fe5b9060200190602002015192508260000151156105995784156104c357600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe916104909101612636565b600060405180830381600087803b1580156104aa57600080fd5b505af11580156104be573d6000803e3d6000fd5b505050505b602083015160408401516003546104e69233929091600160a060020a0316610edf565b1515610594578260600151151561057057600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe9161053d9101612626565b600060405180830381600087803b15801561055757600080fd5b505af115801561056b573d6000803e3d6000fd5b505050505b6001868581518110151561058057fe5b602090810290910101519015159052610634565b61059e565b600194505b8260c00151518210156106345760c08301518051839081106105bc57fe5b60209081029091018101518051600160a060020a03166000908152600190925260409091205490915060ff16151561062957600186858151811015156105fe57fe5b90602001906020020151602001518381518110151561061957fe5b9115156020928302909101909101525b60019091019061059e565b600190930192610417565b50505050505050565b6060600080610655611bca565b61065d611c15565b610665611c2d565b60005474010000000000000000000000000000000000000000900460ff16156106ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161013d90612666565b7fa959ee32a2995f503e81e3e83b690f875793f02ee5219df0de8ae534489c04ae876040516106e99190612579565b60405180910390a16106fa8861102e565b955061070688876103a8565b61071088876110f0565b3494505b87518410156108a557878481518110151561072b57fe5b906020019060200201519250858481518110151561074557fe5b906020019060200201519150606060405190810160405280600081526020016000815260200184600001516107835761077e858861129f565b610789565b84604001515b90529050610798838383611320565b60208101511580156107ab575082606001515b156107b55761089a565b6107c8838260000151836020015161174a565b151561084757600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe916108149101612606565b600060405180830381600087803b15801561082e57600080fd5b505af1158015610842573d6000803e3d6000fd5b505050505b8251156108635761085c8582602001516117d9565b9450610874565b6108718582600001516117f2565b94505b61089a8360200151846000015161088f578260200151610895565b82604001515b611809565b600190930192610714565b60008511156108dd57604051339086156108fc029087906000818181858888f193505050501580156108db573d6000803e3d6000fd5b505b5050505050505050565b600354600160a060020a031681565b600280548290811061090457fe5b600091825260209091200154600160a060020a0316905081565b600054600160a060020a0316331461093557600080fd5b600160a060020a038116600090815260016020526040902054819060ff16156109d157600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe9161099e9101612616565b600060405180830381600087803b1580156109b857600080fd5b505af11580156109cc573d6000803e3d6000fd5b505050505b50600160a060020a031660008181526001602081905260408220805460ff1916821790556002805491820181559091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace01805473ffffffffffffffffffffffffffffffffffffffff19169091179055565b600454600160a060020a031681565b600054600160a060020a03163314610a6957600080fd5b60005474010000000000000000000000000000000000000000900460ff161515610abf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161013d906125c6565b6000805474ff0000000000000000000000000000000000000000191681556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d169339190a1565b60008054600160a060020a03163314610b1e57600080fd5b600160a060020a038216600090815260016020526040902054829060ff161515610bbb57600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe91610b889101612656565b600060405180830381600087803b158015610ba257600080fd5b505af1158015610bb6573d6000803e3d6000fd5b505050505b600160a060020a0383166000908152600160205260408120805460ff1916905591505b600254821015610cae5782600160a060020a0316600283815481101515610c0157fe5b600091825260209091200154600160a060020a03161415610ca357600280546000198101908110610c2e57fe5b60009182526020909120015460028054600160a060020a039092169184908110610c5457fe5b6000918252602090912001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055600280546000190190610c9d9082611c4f565b50610cae565b600190910190610bde565b505050565b60005474010000000000000000000000000000000000000000900460ff165b90565b60016020526000908152604090205460ff1681565b600054600160a060020a03163314610d0157600080fd5b60008054604051600160a060020a03909116917ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482091a26000805473ffffffffffffffffffffffffffffffffffffffff19169055565b600054600160a060020a03163314610d6d57600080fd5b60005474010000000000000000000000000000000000000000900460ff1615610dc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161013d90612666565b6000805474ff00000000000000000000000000000000000000001916740100000000000000000000000000000000000000001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b600054600160a060020a031681565b60008054600160a060020a03163314610e4757600080fd5b600054610e5f908490600160a060020a03168461189f565b90505b92915050565b600054600160a060020a03163314610e7f57600080fd5b60008054604051600160a060020a039091169183156108fc02918491818181858888f19350505050158015610eb8573d6000803e3d6000fd5b5050565b600054600160a060020a03163314610ed357600080fd5b610edc81611979565b50565b60008284600160a060020a031663dd62ed3e87856040518363ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401610f2c929190612512565b602060405180830381600087803b158015610f4657600080fd5b505af1158015610f5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f7e919081019061213d565b1015801561102357506040517f70a082310000000000000000000000000000000000000000000000000000000081528390600160a060020a038616906370a0823190610fce908990600401612504565b602060405180830381600087803b158015610fe857600080fd5b505af1158015610ffc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611020919081019061213d565b10155b90505b949350505050565b6060806000835160405190808252806020026020018201604052801561106e57816020015b61105b611c15565b8152602001906001900390816110535790505b509150600090505b83518110156110e957838181518110151561108d57fe5b9060200190602002015160c00151516040519080825280602002602001820160405280156110c5578160200160208202803883390190505b5082828151811015156110d457fe5b60209081029091018101510152600101611076565b5092915050565b60005b8251811015610cae57828181518110151561110a57fe5b602090810290910101515180156111375750818181518110151561112a57fe5b6020908102909101015151155b15611297576003548351600160a060020a03909116906315dacbea9085908490811061115f57fe5b90602001906020020151602001513330878681518110151561117d57fe5b90602001906020020151604001516040518563ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016111c6949392919061252d565b602060405180830381600087803b1580156111e057600080fd5b505af11580156111f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506112189190810190612101565b151561129757600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe916112649101612646565b600060405180830381600087803b15801561127e57600080fd5b505af1158015611292573d6000803e3d6000fd5b505050505b6001016110f3565b600080600080600086600001511515156112b557fe5b6112c287602001516119f6565b87519094506112d8576112d3611a6e565b6112da565b835b87519093506112e957836112f1565b6112f1611a6e565b9150611307876040015184848a60800151611a73565b90506113138682611aea565b94505b5050505092915050565b600080600061132d611c15565b6000805b8860c00151518610156108db5760a0890151602088015110611352576108db565b602088015180518790811061136357fe5b906020019060200201518061137a57506040870151155b156113845761173f565b60c08901518051600096508695508790811061139c57fe5b9060200190602002015192508260000151915061145a82600160a060020a031663bd4191da85602001516040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004016113fe9190612587565b602060405180830381600087803b15801561141857600080fd5b505af115801561142c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611450919081019061213d565b8860400151611aea565b90508015156114685761173f565b60208301516040517fbeb2c9b0000000000000000000000000000000000000000000000000000000008152600160a060020a0384169163beb2c9b0916114b19190600401612587565b602060405180830381600087803b1580156114cb57600080fd5b505af11580156114df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115039190810190612101565b151561150e5761173f565b88511561165d576115248960200151838361189f565b15156115b757886060015115156115b257600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe9161157b91016125e6565b600060405180830381600087803b15801561159557600080fd5b505af11580156115a9573d6000803e3d6000fd5b505050506115b7565b6108db565b60208301516040517f7cdcffbb000000000000000000000000000000000000000000000000000000008152600160a060020a03841691637cdcffbb9161160291908590600401612598565b6040805180830381600087803b15801561161b57600080fd5b505af115801561162f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611653919081019061215b565b9095509350611700565b60208301516040517fd592a1ea000000000000000000000000000000000000000000000000000000008152600160a060020a0384169163d592a1ea9184916116a9918390600401612598565b60408051808303818588803b1580156116c157600080fd5b505af11580156116d5573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052506116fa919081019061215b565b90955093505b600084111561173f576117178760400151866117f2565b6040880152865161172890866117d9565b8752602087015161173990856117d9565b60208801525b600190950194611331565b60008060008060008088600001516117625786611764565b875b94508860a00151851015955085156117cd5761178389602001516119f6565b895190945061179957611794611a6e565b61179b565b835b89519093506117aa57836117b2565b6117b2611a6e565b91506117c088888585611b00565b9050886080015181101595505b50505050509392505050565b6000828201838110156117eb57600080fd5b9392505050565b6000808383111561180257600080fd5b5050900390565b6000811115610eb85761181d82338361189f565b1515610eb857600480546040517f037072fe000000000000000000000000000000000000000000000000000000008152600160a060020a039091169163037072fe9161186991016125d6565b600060405180830381600087803b15801561188357600080fd5b505af1158015611897573d6000803e3d6000fd5b505050505050565b600083600160a060020a031660405180807f7472616e7366657228616464726573732c75696e743235362900000000000000815250601901905060405180910390207c0100000000000000000000000000000000000000000000000000000000900484846040518363ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018083600160a060020a0316600160a060020a03168152602001828152602001925050506000604051808303816000875af192505050151561197157600080fd5b611026611b9b565b600160a060020a038116151561198e57600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b604080517f646563696d616c732829000000000000000000000000000000000000000000008152905190819003600a0181208082526000916004602080838381888a611388f1808015611a505760018114611a5957611a5e565b60129650611a5e565b845196505b5050505060040160405250919050565b601290565b60008080848610611aa85760128587031115611a8e57600080fd5b5050828403600a0a8502670de0b6b3a76400000282611ace565b60128686031115611ab857600080fd5b5050670de0b6b3a76400008502848403600a0a83025b80600182840103811515611ade57fe5b04979650505050505050565b6000818310611af95781610e5f565b5090919050565b60006b204fce5e3e25026110000000851115611b1b57600080fd5b6b204fce5e3e25026110000000841115611b3457600080fd5b828210611b6f5760128383031115611b4b57600080fd5b84838303600a0a02670de0b6b3a76400008502811515611b6757fe5b049050611026565b60128284031115611b7f57600080fd5b84828403600a0a670de0b6b3a7640000860202811515611b6757fe5b60003d8015611bb15760208114611bba57600080fd5b60019150611bc6565b60206000803e60005191505b5090565b60e0604051908101604052806000151581526020016000600160a060020a03168152602001600081526020016000151581526020016000815260200160008152602001606081525090565b60408051808201909152600081526060602082015290565b6060604051908101604052806000815260200160008152602001600081525090565b815481835581811115610cae57600083815260209020610cae918101908301610cd291905b80821115611bc65760008155600101611c74565b6000610e5f82356126ea565b6000601f82018313611ca557600080fd5b8135611cb8611cb38261269d565b612676565b91508181835260208401935060208101905083856020840282011115611cdd57600080fd5b60005b838110156113165781611cf38882611e20565b8452506020928301929190910190600101611ce0565b6000601f82018313611d1a57600080fd5b8135611d28611cb38261269d565b81815260209384019390925082018360005b838110156113165781358601611d508882611e93565b8452506020928301929190910190600101611d3a565b6000601f82018313611d7757600080fd5b8135611d85611cb38261269d565b81815260209384019390925082018360005b838110156113165781358601611dad8882611ef2565b8452506020928301929190910190600101611d97565b6000601f82018313611dd457600080fd5b8135611de2611cb38261269d565b81815260209384019390925082018360005b838110156113165781358601611e0a8882611f45565b8452506020928301929190910190600101611df4565b6000610e5f82356126f6565b6000610e5f82516126f6565b6000610e5f8235610cd2565b6000601f82018313611e5557600080fd5b8135611e63611cb3826126be565b91508082526020830160208301858383011115611e7f57600080fd5b611e8a838284612706565b50505092915050565b600060408284031215611ea557600080fd5b611eaf6040612676565b90506000611ebd8484611c88565b825250602082013567ffffffffffffffff811115611eda57600080fd5b611ee684828501611e44565b60208301525092915050565b600060408284031215611f0457600080fd5b611f0e6040612676565b90506000611f1c8484611e20565b825250602082013567ffffffffffffffff811115611f3957600080fd5b611ee684828501611c94565b600060e08284031215611f5757600080fd5b611f6160e0612676565b90506000611f6f8484611e20565b8252506020611f8084848301611c88565b6020830152506040611f9484828501611e38565b6040830152506060611fa884828501611e20565b6060830152506080611fbc84828501611e38565b60808301525060a0611fd084828501611e38565b60a08301525060c082013567ffffffffffffffff811115611ff057600080fd5b611ffc84828501611d09565b60c08301525092915050565b6000610e5f8251610cd2565b60006020828403121561202657600080fd5b60006110268484611c88565b6000806040838503121561204557600080fd5b60006120518585611c88565b925050602061206285828601611e38565b9150509250929050565b6000806040838503121561207f57600080fd5b823567ffffffffffffffff81111561209657600080fd5b6120a285828601611dc3565b925050602083013567ffffffffffffffff8111156120bf57600080fd5b61206285828601611d66565b600080604083850312156120de57600080fd5b823567ffffffffffffffff8111156120f557600080fd5b61205185828601611dc3565b60006020828403121561211357600080fd5b60006110268484611e2c565b60006020828403121561213157600080fd5b60006110268484611e38565b60006020828403121561214f57600080fd5b60006110268484612008565b6000806040838503121561216e57600080fd5b600061217a8585612008565b925050602061206285828601612008565b612194816126ea565b82525050565b612194816126f6565b61219481610cd2565b60006121b7826126e6565b8084526121cb816020860160208601612712565b6121d481612742565b9093016020019392505050565b612194816126fb565b601481527f436f6e7472616374206e6f74207061757365642e000000000000000000000000602082015260400190565b602181527f556e61626c6520746f207472616e7366657220746f6b656e7320746f2075736560208201527f7200000000000000000000000000000000000000000000000000000000000000604082015260600190565b602481527f556e61626c6520746f207472616e7366657220746f6b656e7320746f2068616e60208201527f646c657200000000000000000000000000000000000000000000000000000000604082015260600190565b602981527f454f412063616e6e6f742073656e6420657468657220746f207072696d61727960208201527f2066616c6c6261636b0000000000000000000000000000000000000000000000604082015260600190565b602e81527f416d6f756e7473207370656e742f726563656976656420696e2074726164652060208201527f6e6f742061636365707461626c65000000000000000000000000000000000000604082015260600190565b601b81527f48616e646c657220616c72656164792077686974656c69737465640000000000602082015260400190565b603c81527f54616b657220686173206e6f742073656e7420616c6c6f77616e63652f62616c60208201527f616e6365206f6e2061206e6f6e2d6f7074696f6e616c20747261646500000000604082015260600190565b602281527f412062757920686173206f636375726564206265666f7265207468697320736560208201527f6c6c000000000000000000000000000000000000000000000000000000000000604082015260600190565b602881527f54545020756e61626c6520746f207472616e7366657220746f6b656e7320746f60208201527f207072696d617279000000000000000000000000000000000000000000000000604082015260600190565b601881527f48616e646c6572206e6f7420696e2077686974656c6973740000000000000000602082015260400190565b601381527f436f6e7472616374206973207061757365642e00000000000000000000000000602082015260400190565b60208101610e62828461218b565b60408101612520828561218b565b6117eb602083018461218b565b6080810161253b828761218b565b612548602083018661218b565b612555604083018561218b565b61256260608301846121a3565b95945050505050565b60208101610e62828461219a565b60208101610e6282846121a3565b60208082528101610e5f81846121ac565b604080825281016125a981856121ac565b90506117eb60208301846121a3565b60208101610e6282846121e1565b60208082528101610e62816121ea565b60208082528101610e628161221a565b60208082528101610e6281612270565b60208082528101610e62816122c6565b60208082528101610e628161231c565b60208082528101610e6281612372565b60208082528101610e62816123a2565b60208082528101610e62816123f8565b60208082528101610e628161244e565b60208082528101610e62816124a4565b60208082528101610e62816124d4565b60405181810167ffffffffffffffff8111828210171561269557600080fd5b604052919050565b600067ffffffffffffffff8211156126b457600080fd5b5060209081020190565b600067ffffffffffffffff8211156126d557600080fd5b506020601f91909101601f19160190565b5190565b600160a060020a031690565b151590565b6000610e62826126ea565b82818337506000910152565b60005b8381101561272d578181015183820152602001612715565b8381111561273c576000848401525b50505050565b601f01601f1916905600a265627a7a7230582063af84031bd747b60bdcb1ca40cc6a87f90c113b8b2ae5c3d9c85750ad819fd66c6578706572696d656e74616cf50037
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000074758acfce059f503a7e6b0fc2c8737600f9f2c400000000000000000000000076b87390400359941561956632bbbe3f42439e32
-----Decoded View---------------
Arg [0] : _tokenTransferProxy (address): 0x74758AcFcE059f503a7E6B0fC2c8737600f9F2c4
Arg [1] : _errorReporter (address): 0x76b87390400359941561956632bBbE3F42439E32
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000074758acfce059f503a7e6b0fc2c8737600f9f2c4
Arg [1] : 00000000000000000000000076b87390400359941561956632bbbe3f42439e32
Swarm Source
bzzr://63af84031bd747b60bdcb1ca40cc6a87f90c113b8b2ae5c3d9c85750ad819fd6
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.102501 | 5 | $0.5125 |
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.