Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ForeignBridgeErcToErc
Compiler Version
v0.4.24+commit.e67f0147
Optimization Enabled:
Yes with 200 runs
Other Settings:
byzantium EvmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-09-03 */ // File: contracts/upgradeability/EternalStorage.sol pragma solidity 0.4.24; /** * @title EternalStorage * @dev This contract holds all the necessary state variables to carry out the storage of any contract. */ contract EternalStorage { mapping(bytes32 => uint256) internal uintStorage; mapping(bytes32 => string) internal stringStorage; mapping(bytes32 => address) internal addressStorage; mapping(bytes32 => bytes) internal bytesStorage; mapping(bytes32 => bool) internal boolStorage; mapping(bytes32 => int256) internal intStorage; } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol pragma solidity ^0.4.24; /** * @title ERC20Basic * @dev Simpler version of ERC20 interface * See https://github.com/ethereum/EIPs/issues/179 */ contract ERC20Basic { function totalSupply() public view returns (uint256); function balanceOf(address _who) public view returns (uint256); function transfer(address _to, uint256 _value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); } // File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol pragma solidity ^0.4.24; /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ contract ERC20 is ERC20Basic { function allowance(address _owner, address _spender) public view returns (uint256); function transferFrom(address _from, address _to, uint256 _value) public returns (bool); function approve(address _spender, uint256 _value) public returns (bool); event Approval( address indexed owner, address indexed spender, uint256 value ); } // File: contracts/interfaces/IBridgeValidators.sol pragma solidity 0.4.24; interface IBridgeValidators { function isValidator(address _validator) external view returns (bool); function requiredSignatures() external view returns (uint256); function owner() external view returns (address); } // File: contracts/upgradeable_contracts/ValidatorStorage.sol pragma solidity 0.4.24; contract ValidatorStorage { bytes32 internal constant VALIDATOR_CONTRACT = 0x5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe; // keccak256(abi.encodePacked("validatorContract")) } // File: contracts/upgradeable_contracts/Validatable.sol pragma solidity 0.4.24; contract Validatable is EternalStorage, ValidatorStorage { function validatorContract() public view returns (IBridgeValidators) { return IBridgeValidators(addressStorage[VALIDATOR_CONTRACT]); } modifier onlyValidator() { require(validatorContract().isValidator(msg.sender)); /* solcov ignore next */ _; } function requiredSignatures() public view returns (uint256) { return validatorContract().requiredSignatures(); } } // File: contracts/libraries/Message.sol pragma solidity 0.4.24; library Message { function addressArrayContains(address[] array, address value) internal pure returns (bool) { for (uint256 i = 0; i < array.length; i++) { if (array[i] == value) { return true; } } return false; } // layout of message :: bytes: // offset 0: 32 bytes :: uint256 - message length // offset 32: 20 bytes :: address - recipient address // offset 52: 32 bytes :: uint256 - value // offset 84: 32 bytes :: bytes32 - transaction hash // offset 104: 20 bytes :: address - contract address to prevent double spending // mload always reads 32 bytes. // so we can and have to start reading recipient at offset 20 instead of 32. // if we were to read at 32 the address would contain part of value and be corrupted. // when reading from offset 20 mload will read 12 bytes (most of them zeros) followed // by the 20 recipient address bytes and correctly convert it into an address. // this saves some storage/gas over the alternative solution // which is padding address to 32 bytes and reading recipient at offset 32. // for more details see discussion in: // https://github.com/paritytech/parity-bridge/issues/61 function parseMessage(bytes message) internal pure returns (address recipient, uint256 amount, bytes32 txHash, address contractAddress) { require(isMessageValid(message)); assembly { recipient := mload(add(message, 20)) amount := mload(add(message, 52)) txHash := mload(add(message, 84)) contractAddress := mload(add(message, 104)) } } function isMessageValid(bytes _msg) internal pure returns (bool) { return _msg.length == requiredMessageLength(); } function requiredMessageLength() internal pure returns (uint256) { return 104; } function recoverAddressFromSignedMessage(bytes signature, bytes message, bool isAMBMessage) internal pure returns (address) { require(signature.length == 65); bytes32 r; bytes32 s; bytes1 v; assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := mload(add(signature, 0x60)) } require(uint8(v) == 27 || uint8(v) == 28); require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0); return ecrecover(hashMessage(message, isAMBMessage), uint8(v), r, s); } function hashMessage(bytes message, bool isAMBMessage) internal pure returns (bytes32) { bytes memory prefix = "\x19Ethereum Signed Message:\n"; if (isAMBMessage) { return keccak256(abi.encodePacked(prefix, uintToString(message.length), message)); } else { string memory msgLength = "104"; return keccak256(abi.encodePacked(prefix, msgLength, message)); } } /** * @dev Validates provided signatures, only first requiredSignatures() number * of signatures are going to be validated, these signatures should be from different validators. * @param _message bytes message used to generate signatures * @param _signatures bytes blob with signatures to be validated. * First byte X is a number of signatures in a blob, * next X bytes are v components of signatures, * next 32 * X bytes are r components of signatures, * next 32 * X bytes are s components of signatures. * @param _validatorContract contract, which conforms to the IBridgeValidators interface, * where info about current validators and required signatures is stored. * @param isAMBMessage true if _message is an AMB message with arbitrary length. */ function hasEnoughValidSignatures( bytes _message, bytes _signatures, IBridgeValidators _validatorContract, bool isAMBMessage ) internal view { require(isAMBMessage || isMessageValid(_message)); uint256 requiredSignatures = _validatorContract.requiredSignatures(); uint256 amount; assembly { amount := and(mload(add(_signatures, 1)), 0xff) } require(amount >= requiredSignatures); bytes32 hash = hashMessage(_message, isAMBMessage); address[] memory encounteredAddresses = new address[](requiredSignatures); for (uint256 i = 0; i < requiredSignatures; i++) { uint8 v; bytes32 r; bytes32 s; uint256 posr = 33 + amount + 32 * i; uint256 poss = posr + 32 * amount; assembly { v := mload(add(_signatures, add(2, i))) r := mload(add(_signatures, posr)) s := mload(add(_signatures, poss)) } address recoveredAddress = ecrecover(hash, v, r, s); require(_validatorContract.isValidator(recoveredAddress)); require(!addressArrayContains(encounteredAddresses, recoveredAddress)); encounteredAddresses[i] = recoveredAddress; } } function uintToString(uint256 i) internal pure returns (string) { if (i == 0) return "0"; uint256 j = i; uint256 length; while (j != 0) { length++; j /= 10; } bytes memory bstr = new bytes(length); uint256 k = length - 1; while (i != 0) { bstr[k--] = bytes1(48 + (i % 10)); i /= 10; } return string(bstr); } } // File: contracts/upgradeable_contracts/MessageRelay.sol pragma solidity 0.4.24; contract MessageRelay is EternalStorage { function relayedMessages(bytes32 _txHash) public view returns (bool) { return boolStorage[keccak256(abi.encodePacked("relayedMessages", _txHash))]; } function setRelayedMessages(bytes32 _txHash, bool _status) internal { boolStorage[keccak256(abi.encodePacked("relayedMessages", _txHash))] = _status; } } // File: contracts/interfaces/IUpgradeabilityOwnerStorage.sol pragma solidity 0.4.24; interface IUpgradeabilityOwnerStorage { function upgradeabilityOwner() external view returns (address); } // File: contracts/upgradeable_contracts/Upgradeable.sol pragma solidity 0.4.24; contract Upgradeable { // Avoid using onlyUpgradeabilityOwner name to prevent issues with implementation from proxy contract modifier onlyIfUpgradeabilityOwner() { require(msg.sender == IUpgradeabilityOwnerStorage(this).upgradeabilityOwner()); /* solcov ignore next */ _; } } // File: contracts/upgradeable_contracts/Initializable.sol pragma solidity 0.4.24; contract Initializable is EternalStorage { bytes32 internal constant INITIALIZED = 0x0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba; // keccak256(abi.encodePacked("isInitialized")) function setInitialize() internal { boolStorage[INITIALIZED] = true; } function isInitialized() public view returns (bool) { return boolStorage[INITIALIZED]; } } // File: contracts/upgradeable_contracts/InitializableBridge.sol pragma solidity 0.4.24; contract InitializableBridge is Initializable { bytes32 internal constant DEPLOYED_AT_BLOCK = 0xb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b0; // keccak256(abi.encodePacked("deployedAtBlock")) function deployedAtBlock() external view returns (uint256) { return uintStorage[DEPLOYED_AT_BLOCK]; } } // File: openzeppelin-solidity/contracts/AddressUtils.sol pragma solidity ^0.4.24; /** * Utility library of inline functions on addresses */ library AddressUtils { /** * Returns whether the target address is a contract * @dev This function will return false if invoked during the constructor of a contract, * as the code is not actually created until after the constructor finishes. * @param _addr address to check * @return whether the target address is a contract */ function isContract(address _addr) internal view returns (bool) { uint256 size; // XXX Currently there is no better way to check if there is a contract in an address // than to check the size of the code at that address. // See https://ethereum.stackexchange.com/a/14016/36603 // for more details about how this works. // TODO Check this again before the Serenity release, because all addresses will be // contracts then. // solium-disable-next-line security/no-inline-assembly assembly { size := extcodesize(_addr) } return size > 0; } } // File: contracts/upgradeable_contracts/Ownable.sol pragma solidity 0.4.24; /** * @title Ownable * @dev This contract has an owner address providing basic authorization control */ contract Ownable is EternalStorage { bytes4 internal constant UPGRADEABILITY_OWNER = 0x6fde8202; // upgradeabilityOwner() /** * @dev Event to show ownership has been transferred * @param previousOwner representing the address of the previous owner * @param newOwner representing the address of the new owner */ event OwnershipTransferred(address previousOwner, address newOwner); /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(msg.sender == owner()); /* solcov ignore next */ _; } /** * @dev Throws if called by any account other than contract itself or owner. */ modifier onlyRelevantSender() { // proxy owner if used through proxy, address(0) otherwise require( !address(this).call(abi.encodeWithSelector(UPGRADEABILITY_OWNER)) || // covers usage without calling through storage proxy msg.sender == IUpgradeabilityOwnerStorage(this).upgradeabilityOwner() || // covers usage through regular proxy calls msg.sender == address(this) // covers calls through upgradeAndCall proxy method ); /* solcov ignore next */ _; } bytes32 internal constant OWNER = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0; // keccak256(abi.encodePacked("owner")) /** * @dev Tells the address of the owner * @return the address of the owner */ function owner() public view returns (address) { return addressStorage[OWNER]; } /** * @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) external onlyOwner { _setOwner(newOwner); } /** * @dev Sets a new owner address */ function _setOwner(address newOwner) internal { require(newOwner != address(0)); emit OwnershipTransferred(owner(), newOwner); addressStorage[OWNER] = newOwner; } } // File: contracts/upgradeable_contracts/Sacrifice.sol pragma solidity 0.4.24; contract Sacrifice { constructor(address _recipient) public payable { selfdestruct(_recipient); } } // File: contracts/libraries/Address.sol pragma solidity 0.4.24; /** * @title Address * @dev Helper methods for Address type. */ library Address { /** * @dev Try to send native tokens to the address. If it fails, it will force the transfer by creating a selfdestruct contract * @param _receiver address that will receive the native tokens * @param _value the amount of native tokens to send */ function safeSendValue(address _receiver, uint256 _value) internal { if (!_receiver.send(_value)) { (new Sacrifice).value(_value)(_receiver); } } } // File: openzeppelin-solidity/contracts/math/SafeMath.sol pragma solidity ^0.4.24; /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { /** * @dev Multiplies two numbers, throws on overflow. */ function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) { // Gas optimization: this is cheaper than asserting '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; } c = _a * _b; assert(c / _a == _b); return c; } /** * @dev Integer division of two numbers, truncating the quotient. */ function div(uint256 _a, uint256 _b) internal pure returns (uint256) { // assert(_b > 0); // Solidity automatically throws 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 _a / _b; } /** * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 _a, uint256 _b) internal pure returns (uint256) { assert(_b <= _a); return _a - _b; } /** * @dev Adds two numbers, throws on overflow. */ function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) { c = _a + _b; assert(c >= _a); return c; } } // File: contracts/interfaces/ERC677.sol pragma solidity 0.4.24; contract ERC677 is ERC20 { event Transfer(address indexed from, address indexed to, uint256 value, bytes data); function transferAndCall(address, uint256, bytes) external returns (bool); function increaseAllowance(address spender, uint256 addedValue) public returns (bool); function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool); } contract LegacyERC20 { function transfer(address _spender, uint256 _value) public; // returns (bool); function transferFrom(address _owner, address _spender, uint256 _value) public; // returns (bool); } // File: contracts/libraries/SafeERC20.sol pragma solidity 0.4.24; /** * @title SafeERC20 * @dev Helper methods for safe token transfers. * Functions perform additional checks to be sure that token transfer really happened. */ library SafeERC20 { using SafeMath for uint256; /** * @dev Same as ERC20.transfer(address,uint256) but with extra consistency checks. * @param _token address of the token contract * @param _to address of the receiver * @param _value amount of tokens to send */ function safeTransfer(address _token, address _to, uint256 _value) internal { LegacyERC20(_token).transfer(_to, _value); assembly { if returndatasize { returndatacopy(0, 0, 32) if iszero(mload(0)) { revert(0, 0) } } } } /** * @dev Same as ERC20.transferFrom(address,address,uint256) but with extra consistency checks. * @param _token address of the token contract * @param _from address of the sender * @param _value amount of tokens to send */ function safeTransferFrom(address _token, address _from, uint256 _value) internal { LegacyERC20(_token).transferFrom(_from, address(this), _value); assembly { if returndatasize { returndatacopy(0, 0, 32) if iszero(mload(0)) { revert(0, 0) } } } } } // File: contracts/upgradeable_contracts/Claimable.sol pragma solidity 0.4.24; /** * @title Claimable * @dev Implementation of the claiming utils that can be useful for withdrawing accidentally sent tokens that are not used in bridge operations. */ contract Claimable { using SafeERC20 for address; /** * Throws if a given address is equal to address(0) */ modifier validAddress(address _to) { require(_to != address(0)); /* solcov ignore next */ _; } /** * @dev Withdraws the erc20 tokens or native coins from this contract. * Caller should additionally check that the claimed token is not a part of bridge operations (i.e. that token != erc20token()). * @param _token address of the claimed token or address(0) for native coins. * @param _to address of the tokens/coins receiver. */ function claimValues(address _token, address _to) internal validAddress(_to) { if (_token == address(0)) { claimNativeCoins(_to); } else { claimErc20Tokens(_token, _to); } } /** * @dev Internal function for withdrawing all native coins from the contract. * @param _to address of the coins receiver. */ function claimNativeCoins(address _to) internal { uint256 value = address(this).balance; Address.safeSendValue(_to, value); } /** * @dev Internal function for withdrawing all tokens of ssome particular ERC20 contract from this contract. * @param _token address of the claimed ERC20 token. * @param _to address of the tokens receiver. */ function claimErc20Tokens(address _token, address _to) internal { ERC20Basic token = ERC20Basic(_token); uint256 balance = token.balanceOf(this); _token.safeTransfer(_to, balance); } } // File: contracts/upgradeable_contracts/VersionableBridge.sol pragma solidity 0.4.24; contract VersionableBridge { function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) { return (5, 2, 0); } /* solcov ignore next */ function getBridgeMode() external pure returns (bytes4); } // File: contracts/upgradeable_contracts/DecimalShiftBridge.sol pragma solidity 0.4.24; contract DecimalShiftBridge is EternalStorage { using SafeMath for uint256; bytes32 internal constant DECIMAL_SHIFT = 0x1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee5; // keccak256(abi.encodePacked("decimalShift")) /** * @dev Internal function for setting the decimal shift for bridge operations. * Decimal shift can be positive, negative, or equal to zero. * It has the following meaning: N tokens in the foreign chain are equivalent to N * pow(10, shift) tokens on the home side. * @param _shift new value of decimal shift. */ function _setDecimalShift(int256 _shift) internal { // since 1 wei * 10**77 > 2**255, it does not make any sense to use higher values require(_shift > -77 && _shift < 77); uintStorage[DECIMAL_SHIFT] = uint256(_shift); } /** * @dev Returns the value of foreign-to-home decimal shift. * @return decimal shift. */ function decimalShift() public view returns (int256) { return int256(uintStorage[DECIMAL_SHIFT]); } /** * @dev Converts the amount of home tokens into the equivalent amount of foreign tokens. * @param _value amount of home tokens. * @return equivalent amount of foreign tokens. */ function _unshiftValue(uint256 _value) internal view returns (uint256) { return _shiftUint(_value, -decimalShift()); } /** * @dev Converts the amount of foreign tokens into the equivalent amount of home tokens. * @param _value amount of foreign tokens. * @return equivalent amount of home tokens. */ function _shiftValue(uint256 _value) internal view returns (uint256) { return _shiftUint(_value, decimalShift()); } /** * @dev Calculates _value * pow(10, _shift). * @param _value amount of tokens. * @param _shift decimal shift to apply. * @return shifted value. */ function _shiftUint(uint256 _value, int256 _shift) private pure returns (uint256) { if (_shift == 0) { return _value; } if (_shift > 0) { return _value.mul(10**uint256(_shift)); } return _value.div(10**uint256(-_shift)); } } // File: contracts/upgradeable_contracts/BasicBridge.sol pragma solidity 0.4.24; contract BasicBridge is InitializableBridge, Validatable, Ownable, Upgradeable, Claimable, VersionableBridge, DecimalShiftBridge { event GasPriceChanged(uint256 gasPrice); event RequiredBlockConfirmationChanged(uint256 requiredBlockConfirmations); bytes32 internal constant GAS_PRICE = 0x55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b; // keccak256(abi.encodePacked("gasPrice")) bytes32 internal constant REQUIRED_BLOCK_CONFIRMATIONS = 0x916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d79407230071; // keccak256(abi.encodePacked("requiredBlockConfirmations")) /** * @dev Public setter for fallback gas price value. Only bridge owner can call this method. * @param _gasPrice new value for the gas price. */ function setGasPrice(uint256 _gasPrice) external onlyOwner { _setGasPrice(_gasPrice); } function gasPrice() external view returns (uint256) { return uintStorage[GAS_PRICE]; } function setRequiredBlockConfirmations(uint256 _blockConfirmations) external onlyOwner { _setRequiredBlockConfirmations(_blockConfirmations); } function _setRequiredBlockConfirmations(uint256 _blockConfirmations) internal { require(_blockConfirmations > 0); uintStorage[REQUIRED_BLOCK_CONFIRMATIONS] = _blockConfirmations; emit RequiredBlockConfirmationChanged(_blockConfirmations); } function requiredBlockConfirmations() external view returns (uint256) { return uintStorage[REQUIRED_BLOCK_CONFIRMATIONS]; } /** * @dev Internal function for updating fallback gas price value. * @param _gasPrice new value for the gas price, zero gas price is allowed. */ function _setGasPrice(uint256 _gasPrice) internal { uintStorage[GAS_PRICE] = _gasPrice; emit GasPriceChanged(_gasPrice); } } // File: contracts/upgradeable_contracts/BasicTokenBridge.sol pragma solidity 0.4.24; contract BasicTokenBridge is EternalStorage, Ownable, DecimalShiftBridge { using SafeMath for uint256; event DailyLimitChanged(uint256 newLimit); event ExecutionDailyLimitChanged(uint256 newLimit); bytes32 internal constant MIN_PER_TX = 0xbbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d1; // keccak256(abi.encodePacked("minPerTx")) bytes32 internal constant MAX_PER_TX = 0x0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c; // keccak256(abi.encodePacked("maxPerTx")) bytes32 internal constant DAILY_LIMIT = 0x4a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a5; // keccak256(abi.encodePacked("dailyLimit")) bytes32 internal constant EXECUTION_MAX_PER_TX = 0xc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d5; // keccak256(abi.encodePacked("executionMaxPerTx")) bytes32 internal constant EXECUTION_DAILY_LIMIT = 0x21dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d237; // keccak256(abi.encodePacked("executionDailyLimit")) function totalSpentPerDay(uint256 _day) public view returns (uint256) { return uintStorage[keccak256(abi.encodePacked("totalSpentPerDay", _day))]; } function totalExecutedPerDay(uint256 _day) public view returns (uint256) { return uintStorage[keccak256(abi.encodePacked("totalExecutedPerDay", _day))]; } function dailyLimit() public view returns (uint256) { return uintStorage[DAILY_LIMIT]; } function executionDailyLimit() public view returns (uint256) { return uintStorage[EXECUTION_DAILY_LIMIT]; } function maxPerTx() public view returns (uint256) { return uintStorage[MAX_PER_TX]; } function executionMaxPerTx() public view returns (uint256) { return uintStorage[EXECUTION_MAX_PER_TX]; } function minPerTx() public view returns (uint256) { return uintStorage[MIN_PER_TX]; } function withinLimit(uint256 _amount) public view returns (bool) { uint256 nextLimit = totalSpentPerDay(getCurrentDay()).add(_amount); return dailyLimit() >= nextLimit && _amount <= maxPerTx() && _amount >= minPerTx(); } function withinExecutionLimit(uint256 _amount) public view returns (bool) { uint256 nextLimit = totalExecutedPerDay(getCurrentDay()).add(_amount); return executionDailyLimit() >= nextLimit && _amount <= executionMaxPerTx(); } function getCurrentDay() public view returns (uint256) { // solhint-disable-next-line not-rely-on-time return now / 1 days; } function addTotalSpentPerDay(uint256 _day, uint256 _value) internal { uintStorage[keccak256(abi.encodePacked("totalSpentPerDay", _day))] = totalSpentPerDay(_day).add(_value); } function addTotalExecutedPerDay(uint256 _day, uint256 _value) internal { uintStorage[keccak256(abi.encodePacked("totalExecutedPerDay", _day))] = totalExecutedPerDay(_day).add(_value); } function setDailyLimit(uint256 _dailyLimit) external onlyOwner { require(_dailyLimit > maxPerTx() || _dailyLimit == 0); uintStorage[DAILY_LIMIT] = _dailyLimit; emit DailyLimitChanged(_dailyLimit); } function setExecutionDailyLimit(uint256 _dailyLimit) external onlyOwner { require(_dailyLimit > executionMaxPerTx() || _dailyLimit == 0); uintStorage[EXECUTION_DAILY_LIMIT] = _dailyLimit; emit ExecutionDailyLimitChanged(_dailyLimit); } function setExecutionMaxPerTx(uint256 _maxPerTx) external onlyOwner { require(_maxPerTx < executionDailyLimit()); uintStorage[EXECUTION_MAX_PER_TX] = _maxPerTx; } function setMaxPerTx(uint256 _maxPerTx) external onlyOwner { require(_maxPerTx == 0 || (_maxPerTx > minPerTx() && _maxPerTx < dailyLimit())); uintStorage[MAX_PER_TX] = _maxPerTx; } function setMinPerTx(uint256 _minPerTx) external onlyOwner { require(_minPerTx > 0 && _minPerTx < dailyLimit() && _minPerTx < maxPerTx()); uintStorage[MIN_PER_TX] = _minPerTx; } /** * @dev Retrieves maximum available bridge amount per one transaction taking into account maxPerTx() and dailyLimit() parameters. * @return minimum of maxPerTx parameter and remaining daily quota. */ function maxAvailablePerTx() public view returns (uint256) { uint256 _maxPerTx = maxPerTx(); uint256 _dailyLimit = dailyLimit(); uint256 _spent = totalSpentPerDay(getCurrentDay()); uint256 _remainingOutOfDaily = _dailyLimit > _spent ? _dailyLimit - _spent : 0; return _maxPerTx < _remainingOutOfDaily ? _maxPerTx : _remainingOutOfDaily; } function _setLimits(uint256[3] _limits) internal { require( _limits[2] > 0 && // minPerTx > 0 _limits[1] > _limits[2] && // maxPerTx > minPerTx _limits[0] > _limits[1] // dailyLimit > maxPerTx ); uintStorage[DAILY_LIMIT] = _limits[0]; uintStorage[MAX_PER_TX] = _limits[1]; uintStorage[MIN_PER_TX] = _limits[2]; emit DailyLimitChanged(_limits[0]); } function _setExecutionLimits(uint256[2] _limits) internal { require(_limits[1] < _limits[0]); // foreignMaxPerTx < foreignDailyLimit uintStorage[EXECUTION_DAILY_LIMIT] = _limits[0]; uintStorage[EXECUTION_MAX_PER_TX] = _limits[1]; emit ExecutionDailyLimitChanged(_limits[0]); } } // File: contracts/upgradeable_contracts/BasicForeignBridge.sol pragma solidity 0.4.24; contract BasicForeignBridge is EternalStorage, Validatable, BasicBridge, BasicTokenBridge, MessageRelay { /// triggered when relay of deposit from HomeBridge is complete event RelayedMessage(address recipient, uint256 value, bytes32 transactionHash); event UserRequestForAffirmation(address recipient, uint256 value); /** * @dev Validates provided signatures and relays a given message * @param message bytes to be relayed * @param signatures bytes blob with signatures to be validated */ function executeSignatures(bytes message, bytes signatures) external { Message.hasEnoughValidSignatures(message, signatures, validatorContract(), false); address recipient; uint256 amount; bytes32 txHash; address contractAddress; (recipient, amount, txHash, contractAddress) = Message.parseMessage(message); if (withinExecutionLimit(amount)) { require(contractAddress == address(this)); require(!relayedMessages(txHash)); setRelayedMessages(txHash, true); require(onExecuteMessage(recipient, amount, txHash)); emit RelayedMessage(recipient, amount, txHash); } else { onFailedMessage(recipient, amount, txHash); } } /** * @dev Internal function for updating fallback gas price value. * @param _gasPrice new value for the gas price, zero gas price is not allowed. */ function _setGasPrice(uint256 _gasPrice) internal { require(_gasPrice > 0); super._setGasPrice(_gasPrice); } /* solcov ignore next */ function onExecuteMessage(address, uint256, bytes32) internal returns (bool); /* solcov ignore next */ function onFailedMessage(address, uint256, bytes32) internal; } // File: contracts/upgradeable_contracts/erc20_to_erc20/BasicForeignBridgeErcToErc.sol pragma solidity 0.4.24; contract BasicForeignBridgeErcToErc is BasicForeignBridge { using SafeERC20 for ERC20; function _initialize( address _validatorContract, address _erc20token, uint256 _requiredBlockConfirmations, uint256 _gasPrice, uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = _dailyLimit, 1 = _maxPerTx, 2 = _minPerTx ] uint256[2] _homeDailyLimitHomeMaxPerTxArray, // [ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ] address _owner, int256 _decimalShift ) internal { require(!isInitialized()); require(AddressUtils.isContract(_validatorContract)); addressStorage[VALIDATOR_CONTRACT] = _validatorContract; setErc20token(_erc20token); uintStorage[DEPLOYED_AT_BLOCK] = block.number; _setRequiredBlockConfirmations(_requiredBlockConfirmations); _setGasPrice(_gasPrice); _setLimits(_dailyLimitMaxPerTxMinPerTxArray); _setExecutionLimits(_homeDailyLimitHomeMaxPerTxArray); _setDecimalShift(_decimalShift); _setOwner(_owner); setInitialize(); } function getBridgeMode() external pure returns (bytes4 _data) { return 0xba4690f5; // bytes4(keccak256(abi.encodePacked("erc-to-erc-core"))) } /** * @dev Withdraws the erc20 tokens or native coins from this contract. Bridged token cannot be withdrawn by this function. * @param _token address of the claimed token or address(0) for native coins. * @param _to address of the tokens/coins receiver. */ function claimTokens(address _token, address _to) external onlyIfUpgradeabilityOwner { // Since bridged tokens are locked at this contract, it is not allowed to claim them with the use of claimTokens function require(_token != address(erc20token())); claimValues(_token, _to); } function onExecuteMessage( address _recipient, uint256 _amount, bytes32 /*_txHash*/ ) internal returns (bool) { addTotalExecutedPerDay(getCurrentDay(), _amount); uint256 amount = _unshiftValue(_amount); erc20token().safeTransfer(_recipient, amount); return true; } function onFailedMessage(address, uint256, bytes32) internal { revert(); } /* solcov ignore next */ function erc20token() public view returns (ERC20); /* solcov ignore next */ function setErc20token(address _token) internal; } // File: contracts/upgradeable_contracts/ERC20Bridge.sol pragma solidity 0.4.24; contract ERC20Bridge is BasicForeignBridge { using SafeERC20 for ERC20; bytes32 internal constant ERC20_TOKEN = 0x15d63b18dbc21bf4438b7972d80076747e1d93c4f87552fe498c90cbde51665e; // keccak256(abi.encodePacked("erc20token")) function erc20token() public view returns (ERC20) { return ERC20(addressStorage[ERC20_TOKEN]); } function setErc20token(address _token) internal { require(AddressUtils.isContract(_token)); addressStorage[ERC20_TOKEN] = _token; } function relayTokens(address _receiver, uint256 _amount) external { require(_receiver != address(0)); require(_receiver != address(this)); require(_amount > 0); require(withinLimit(_amount)); addTotalSpentPerDay(getCurrentDay(), _amount); erc20token().safeTransferFrom(msg.sender, _amount); emit UserRequestForAffirmation(_receiver, _amount); } } // File: contracts/upgradeable_contracts/erc20_to_erc20/ForeignBridgeErcToErc.sol pragma solidity 0.4.24; contract ForeignBridgeErcToErc is BasicForeignBridgeErcToErc, ERC20Bridge { function initialize( address _validatorContract, address _erc20token, uint256 _requiredBlockConfirmations, uint256 _gasPrice, uint256[3] _dailyLimitMaxPerTxMinPerTxArray, // [ 0 = _dailyLimit, 1 = _maxPerTx, 2 = _minPerTx ] uint256[2] _homeDailyLimitHomeMaxPerTxArray, // [ 0 = _homeDailyLimit, 1 = _homeMaxPerTx ] address _owner, int256 _decimalShift ) external onlyRelevantSender returns (bool) { _initialize( _validatorContract, _erc20token, _requiredBlockConfirmations, _gasPrice, _dailyLimitMaxPerTxMinPerTxArray, _homeDailyLimitHomeMaxPerTxArray, _owner, _decimalShift ); return isInitialized(); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":false,"inputs":[{"name":"_receiver","type":"address"},{"name":"_amount","type":"uint256"}],"name":"relayTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_validatorContract","type":"address"},{"name":"_erc20token","type":"address"},{"name":"_requiredBlockConfirmations","type":"uint256"},{"name":"_gasPrice","type":"uint256"},{"name":"_dailyLimitMaxPerTxMinPerTxArray","type":"uint256[3]"},{"name":"_homeDailyLimitHomeMaxPerTxArray","type":"uint256[2]"},{"name":"_owner","type":"address"},{"name":"_decimalShift","type":"int256"}],"name":"initialize","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"erc20token","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_txHash","type":"bytes32"}],"name":"relayedMessages","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_day","type":"uint256"}],"name":"totalSpentPerDay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isInitialized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_dailyLimit","type":"uint256"}],"name":"setExecutionDailyLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentDay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"requiredBlockConfirmations","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"message","type":"bytes"},{"name":"signatures","type":"bytes"}],"name":"executeSignatures","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getBridgeMode","outputs":[{"name":"_data","type":"bytes4"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"executionDailyLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_day","type":"uint256"}],"name":"totalExecutedPerDay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"dailyLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_to","type":"address"}],"name":"claimTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_amount","type":"uint256"}],"name":"withinExecutionLimit","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"executionMaxPerTx","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"requiredSignatures","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxAvailablePerTx","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"validatorContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"deployedAtBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBridgeInterfacesVersion","outputs":[{"name":"major","type":"uint64"},{"name":"minor","type":"uint64"},{"name":"patch","type":"uint64"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_minPerTx","type":"uint256"}],"name":"setMinPerTx","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_blockConfirmations","type":"uint256"}],"name":"setRequiredBlockConfirmations","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_dailyLimit","type":"uint256"}],"name":"setDailyLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_gasPrice","type":"uint256"}],"name":"setGasPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_maxPerTx","type":"uint256"}],"name":"setMaxPerTx","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimalShift","outputs":[{"name":"","type":"int256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minPerTx","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_amount","type":"uint256"}],"name":"withinLimit","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxPerTx","type":"uint256"}],"name":"setExecutionMaxPerTx","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"maxPerTx","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"gasPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"recipient","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"transactionHash","type":"bytes32"}],"name":"RelayedMessage","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"recipient","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"UserRequestForAffirmation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newLimit","type":"uint256"}],"name":"DailyLimitChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newLimit","type":"uint256"}],"name":"ExecutionDailyLimitChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"gasPrice","type":"uint256"}],"name":"GasPriceChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"requiredBlockConfirmations","type":"uint256"}],"name":"RequiredBlockConfirmationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousOwner","type":"address"},{"indexed":false,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]
Contract Creation Code
608060405234801561001057600080fd5b506128cc806100206000396000f30060806040526004361061019d5763ffffffff60e060020a60003504166301e4f53a81146101a25780630e6a39db146101c85780631dcea4271461021c57806321d800ec1461024d5780632bd0bb0514610265578063392e53cd1461028f5780633dd95d1b146102a45780633e6968b6146102bc5780633f0a9f65146102d15780633f7658fd146102e6578063437764df1461031257806343b37dd31461035c5780634fb3fef71461037157806367eeba0c1461038957806369ffa08a1461039e578063879ce676146103c55780638aa1949a146103dd5780638d068043146103f25780638da5cb5b1461040757806395e54a171461041c57806399439089146104315780639a454b99146104465780639cb7595a1461045b578063a2a6ca271461049c578063acf5c689146104b4578063b20d30a9146104cc578063bf1fe420146104e4578063c6f6f216146104fc578063dae5f0fd14610514578063df25f3f014610529578063ea9f49681461053e578063f20151e114610556578063f2fde38b1461056e578063f968adbe1461058f578063fe173b97146105a4575b600080fd5b3480156101ae57600080fd5b506101c6600160a060020a03600435166024356105b9565b005b3480156101d457600080fd5b50610208600160a060020a03600435811690602435811690604435906064359060849060e490610124351661014435610681565b604080519115158252519081900360200190f35b34801561022857600080fd5b5061023161083b565b60408051600160a060020a039092168252519081900360200190f35b34801561025957600080fd5b50610208600435610892565b34801561027157600080fd5b5061027d60043561095b565b60408051918252519081900360200190f35b34801561029b57600080fd5b50610208610a18565b3480156102b057600080fd5b506101c6600435610a69565b3480156102c857600080fd5b5061027d610b29565b3480156102dd57600080fd5b5061027d610b32565b3480156102f257600080fd5b506101c66024600480358281019290820135918135918201910135610b80565b34801561031e57600080fd5b50610327610cf5565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b34801561036857600080fd5b5061027d610d19565b34801561037d57600080fd5b5061027d600435610d67565b34801561039557600080fd5b5061027d610de2565b3480156103aa57600080fd5b506101c6600160a060020a0360043581169060243516610e30565b3480156103d157600080fd5b50610208600435610edc565b3480156103e957600080fd5b5061027d610f26565b3480156103fe57600080fd5b5061027d610f74565b34801561041357600080fd5b50610231610fec565b34801561042857600080fd5b5061027d611043565b34801561043d57600080fd5b5061023161109d565b34801561045257600080fd5b5061027d6110f4565b34801561046757600080fd5b50610470611142565b6040805167ffffffffffffffff9485168152928416602084015292168183015290519081900360600190f35b3480156104a857600080fd5b506101c660043561114d565b3480156104c057600080fd5b506101c66004356111e9565b3480156104d857600080fd5b506101c6600435611211565b3480156104f057600080fd5b506101c66004356112d1565b34801561050857600080fd5b506101c66004356112f6565b34801561052057600080fd5b5061027d61138e565b34801561053557600080fd5b5061027d6113dc565b34801561054a57600080fd5b5061020860043561142a565b34801561056257600080fd5b506101c6600435611475565b34801561057a57600080fd5b506101c6600160a060020a03600435166114f1565b34801561059b57600080fd5b5061027d611516565b3480156105b057600080fd5b5061027d611564565b600160a060020a03821615156105ce57600080fd5b600160a060020a0382163014156105e457600080fd5b600081116105f157600080fd5b6105fa8161142a565b151561060557600080fd5b610616610610610b29565b826115b2565b610639338261062361083b565b600160a060020a0316919063ffffffff61167b16565b60408051600160a060020a03841681526020810183905281517f1d491a427d1f8cc0d447496f300fac39f7306122481d8e663451eb268274146b929181900390910190a15050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f6fde8202000000000000000000000000000000000000000000000000000000001781529151815160009330939291829190808383895b838110156107025781810151838201526020016106ea565b50505050905090810190601f16801561072f5780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af191505015806107c1575030600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561078957600080fd5b505af115801561079d573d6000803e3d6000fd5b505050506040513d60208110156107b357600080fd5b5051600160a060020a031633145b806107cb57503330145b15156107d657600080fd5b61082689898989896003806020026040519081016040528092919082600360200280828437505060408051808201825293508d925060029150839083908082843782019150505050508989611723565b61082e610a18565b9998505050505050505050565b7f15d63b18dbc21bf4438b7972d80076747e1d93c4f87552fe498c90cbde51665e60005260026020527f70dfdbaec92bfd068fb9a67f8c22440e995abe75330f5b6b79a478c9bc8ccbd154600160a060020a031690565b6000600460008360405160200180807f72656c617965644d657373616765730000000000000000000000000000000000815250600f0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106109175780518252601f1990920191602091820191016108f8565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1695945050505050565b60008060008360405160200180807f746f74616c5370656e74506572446179000000000000000000000000000000008152506010018281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106109d75780518252601f1990920191602091820191016109b8565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205495945050505050565b7f0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba60005260046020527f078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc5460ff1690565b610a71610fec565b600160a060020a03163314610a8557600080fd5b610a8d610f26565b811180610a98575080155b1515610aa357600080fd5b7f21dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d237600090815260209081527fadd938dbd083a16bae12238cd914fca0afc7a30edb55b1cd5c7f1823f1b0e4218290556040805183815290517f9bebf928b90863f24cc31f726a3a7545efd409f1dcf552301b1ee3710da70d3b929181900390910190a150565b62015180420490565b7f916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d7940723007160009081526020527fd2ea0feb732edb0ffe32efd33a6b9d24d46b16eb34a4d07ce256537b6f131e425490565b600080600080610bf888888080601f0160208091040260200160405190810160405280939291908181526020018383808284375050604080516020601f8e018190048102820181019092528c815294508c93508b9250829150840183828082843750610bf1945061109d9350505050565b600061184c565b610c3188888080601f01602080910402602001604051908101604052809392919081815260200183838082843750611ad6945050505050565b92965090945092509050610c4483610edc565b15610ce057600160a060020a0381163014610c5e57600080fd5b610c6782610892565b15610c7157600080fd5b610c7c826001611b11565b610c87848484611be3565b1515610c9257600080fd5b60408051600160a060020a03861681526020810185905280820184905290517f4ab7d581336d92edbea22636a613e8e76c99ac7f91137c1523db38dbfb3bf3299181900360600190a1610ceb565b610ceb84848461019d565b5050505050505050565b7fba4690f50000000000000000000000000000000000000000000000000000000090565b7f21dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d23760009081526020527fadd938dbd083a16bae12238cd914fca0afc7a30edb55b1cd5c7f1823f1b0e4215490565b60008060008360405160200180807f746f74616c457865637574656450657244617900000000000000000000000000815250601301828152602001915050604051602081830303815290604052604051808280519060200190808383602083106109d75780518252601f1990920191602091820191016109b8565b7f4a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a560009081526020527f1ab29a5cca988aee50edccdd61c5bcaa7ad4b29a03b7ee50f298ceccfe14cc4e5490565b30600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015610e6e57600080fd5b505af1158015610e82573d6000803e3d6000fd5b505050506040513d6020811015610e9857600080fd5b5051600160a060020a03163314610eae57600080fd5b610eb661083b565b600160a060020a0383811691161415610ece57600080fd5b610ed88282611c30565b5050565b600080610eff83610ef3610eee610b29565b610d67565b9063ffffffff611c6e16565b905080610f0a610d19565b10158015610f1f5750610f1b610f26565b8311155b9392505050565b7fc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d560009081526020527ff8e983ee86e5e377e9e34c9131b266382c3f04113d20de077f9e12663c7a646b5490565b6000610f7e61109d565b600160a060020a0316638d0680436040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015610fbb57600080fd5b505af1158015610fcf573d6000803e3d6000fd5b505050506040513d6020811015610fe557600080fd5b5051905090565b7f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060005260026020527fb7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e54600160a060020a031690565b6000806000806000611053611516565b935061105d610de2565b925061106f61106a610b29565b61095b565b915081831161107f576000611083565b8183035b90508084106110925780611094565b835b94505050505090565b7f5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe60005260026020527fab54f3fbbe62c59b7876a9bf9bd5e0c22dbae93f4d8ee0438f7ce62b198eb0e054600160a060020a031690565b7fb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b060009081526020527fe66bef0282a446f9848e2903380099bb6e431483ee78778868f33b4a154c818b5490565b600560026000909192565b611155610fec565b600160a060020a0316331461116957600080fd5b60008111801561117f575061117c610de2565b81105b8015611191575061118e611516565b81105b151561119c57600080fd5b7fbbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d160009081526020527f8df5c48c6b6e11d97548adc824ba0c99103ec09830fa5d53a179984085e6eaa055565b6111f1610fec565b600160a060020a0316331461120557600080fd5b61120e81611c81565b50565b611219610fec565b600160a060020a0316331461122d57600080fd5b611235611516565b811180611240575080155b151561124b57600080fd5b7f4a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a5600090815260209081527f1ab29a5cca988aee50edccdd61c5bcaa7ad4b29a03b7ee50f298ceccfe14cc4e8290556040805183815290517fad4123ae17c414d9c6d2fec478b402e6b01856cc250fd01fbfd252fda0089d3c929181900390910190a150565b6112d9610fec565b600160a060020a031633146112ed57600080fd5b61120e81611d14565b6112fe610fec565b600160a060020a0316331461131257600080fd5b80158061133657506113226113dc565b811180156113365750611333610de2565b81105b151561134157600080fd5b7f0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c60009081526020527f9de0f81379b4d8e60fe509315d071b56e7b732abaf193e74e0d15808b0951d0955565b7f1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee560009081526020527fd5c78dd9468716ca9bb96be25d56436811b20aab3523a9904b12deef1cab239d5490565b7fbbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d160009081526020527f8df5c48c6b6e11d97548adc824ba0c99103ec09830fa5d53a179984085e6eaa05490565b60008061143c83610ef361106a610b29565b905080611447610de2565b1015801561145c5750611458611516565b8311155b8015610f1f575061146b6113dc565b9092101592915050565b61147d610fec565b600160a060020a0316331461149157600080fd5b611499610d19565b81106114a457600080fd5b7fc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d560009081526020527ff8e983ee86e5e377e9e34c9131b266382c3f04113d20de077f9e12663c7a646b55565b6114f9610fec565b600160a060020a0316331461150d57600080fd5b61120e81611d2a565b7f0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c60009081526020527f9de0f81379b4d8e60fe509315d071b56e7b732abaf193e74e0d15808b0951d095490565b7f55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b60009081526020527ff7d5eefab3776d7f0450bd0193564bcb4f832ce313ff2836c450fc63a4b944195490565b6115bf81610ef38461095b565b6000808460405160200180807f746f74616c5370656e74506572446179000000000000000000000000000000008152506010018281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106116395780518252601f19909201916020918201910161161a565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020939093555050505050565b604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a038481166004830152306024830152604482018490529151918516916323b872dd9160648082019260009290919082900301818387803b1580156116ec57600080fd5b505af1158015611700573d6000803e3d6000fd5b505050503d1561171e5760206000803e600051151561171e57600080fd5b505050565b61172b610a18565b1561173557600080fd5b61173e88611e01565b151561174957600080fd5b7f5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe60005260026020527fab54f3fbbe62c59b7876a9bf9bd5e0c22dbae93f4d8ee0438f7ce62b198eb0e0805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038a161790556117c287611e09565b7fb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b06000908152602052437fe66bef0282a446f9848e2903380099bb6e431483ee78778868f33b4a154c818b5561181786611c81565b61182085611d14565b61182984611e94565b61183283611ff1565b61183b816120c6565b61184482611d2a565b610ceb61212f565b6000806000606060008060008060008060008b8061186e575061186e8f612186565b151561187957600080fd5b8c600160a060020a0316638d0680436040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156118b757600080fd5b505af11580156118cb573d6000803e3d6000fd5b505050506040513d60208110156118e157600080fd5b505160018f0151909b5060ff1699508a8a10156118fd57600080fd5b6119078f8d61219a565b98508a604051908082528060200260200182016040528015611933578160200160208202803883390190505b509750600096505b8a871015611ac557866020028a6021010192508960200283019150866002018e01519550828e01519450818e01519350600189878787604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af11580156119e2573d6000803e3d6000fd5b5050506020604051035190508c600160a060020a031663facd743b826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015611a4957600080fd5b505af1158015611a5d573d6000803e3d6000fd5b505050506040513d6020811015611a7357600080fd5b50511515611a8057600080fd5b611a8a88826123b4565b15611a9457600080fd5b808888815181101515611aa357fe5b600160a060020a0390921660209283029091019091015260019096019561193b565b505050505050505050505050505050565b600080600080611ae585612186565b1515611af057600080fd5b50505050601481015160348201516054830151606890930151919390929190565b80600460008460405160200180807f72656c617965644d657373616765730000000000000000000000000000000000815250600f0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b60208310611b955780518252601f199092019160209182019101611b76565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff1916941515949094179093555050505050565b600080611bf7611bf1610b29565b8561240f565b611c0084612495565b9050611c258582611c0f61083b565b600160a060020a0316919063ffffffff6124ab16565b506001949350505050565b80600160a060020a0381161515611c4657600080fd5b600160a060020a0383161515611c6457611c5f8261250e565b61171e565b61171e838361251a565b81810182811015611c7b57fe5b92915050565b60008111611c8e57600080fd5b7f916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d79407230071600090815260209081527fd2ea0feb732edb0ffe32efd33a6b9d24d46b16eb34a4d07ce256537b6f131e428290556040805183815290517f4fb76205cd57c896b21511d2114137d8e901b4ccd659e1a0f97d6306795264fb929181900390910190a150565b60008111611d2157600080fd5b61120e816125cd565b600160a060020a0381161515611d3f57600080fd5b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0611d68610fec565b60408051600160a060020a03928316815291841660208301528051918290030190a17f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060005260026020527fb7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6000903b1190565b611e1281611e01565b1515611e1d57600080fd5b7f15d63b18dbc21bf4438b7972d80076747e1d93c4f87552fe498c90cbde51665e60005260026020527f70dfdbaec92bfd068fb9a67f8c22440e995abe75330f5b6b79a478c9bc8ccbd1805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60408101516000108015611eaf575060408101516020820151115b8015611ebf575060208101518151115b1515611eca57600080fd5b80517f4a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a5600090815260208181527f1ab29a5cca988aee50edccdd61c5bcaa7ad4b29a03b7ee50f298ceccfe14cc4e92909255908201517f0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c82527f9de0f81379b4d8e60fe509315d071b56e7b732abaf193e74e0d15808b0951d095560408201517fbbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d182527f8df5c48c6b6e11d97548adc824ba0c99103ec09830fa5d53a179984085e6eaa0557fad4123ae17c414d9c6d2fec478b402e6b01856cc250fd01fbfd252fda0089d3c9082905b60200201516040518082815260200191505060405180910390a150565b805160208201511061200257600080fd5b80517f21dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d237600090815260208181527fadd938dbd083a16bae12238cd914fca0afc7a30edb55b1cd5c7f1823f1b0e42192909255908201517fc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d582527ff8e983ee86e5e377e9e34c9131b266382c3f04113d20de077f9e12663c7a646b557f9bebf928b90863f24cc31f726a3a7545efd409f1dcf552301b1ee3710da70d3b908290611fd4565b604c19811380156120d75750604d81125b15156120e257600080fd5b7f1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee560009081526020527fd5c78dd9468716ca9bb96be25d56436811b20aab3523a9904b12deef1cab239d55565b7f0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba60005260046020527f078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc805460ff19166001179055565b6000612190612653565b8251149050919050565b60408051808201909152601a81527f19457468657265756d205369676e6564204d6573736167653a0a00000000000060208201526000906060831561234057816121e48651612658565b866040516020018084805190602001908083835b602083106122175780518252601f1990920191602091820191016121f8565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b6020831061225f5780518252601f199092019160209182019101612240565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106122a75780518252601f199092019160209182019101612288565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b6020831061230c5780518252601f1990920191602091820191016122ed565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902092506123ac565b6040805190810160405280600381526020017f31303400000000000000000000000000000000000000000000000000000000008152509050818186604051602001808480519060200190808383602083106122175780518252601f1990920191602091820191016121f8565b505092915050565b6000805b83518110156124035782600160a060020a031684828151811015156123d957fe5b90602001906020020151600160a060020a031614156123fb5760019150612408565b6001016123b8565b600091505b5092915050565b61241c81610ef384610d67565b6000808460405160200180807f746f74616c457865637574656450657244617900000000000000000000000000815250601301828152602001915050604051602081830303815290604052604051808280519060200190808383602083106116395780518252601f19909201916020918201910161161a565b6000611c7b826124a361138e565b60000361277f565b82600160a060020a031663a9059cbb83836040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b1580156116ec57600080fd5b3031610ed882826127ca565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290518391600091600160a060020a038416916370a0823191602480830192602092919082900301818787803b15801561257f57600080fd5b505af1158015612593573d6000803e3d6000fd5b505050506040513d60208110156125a957600080fd5b505190506125c7600160a060020a038516848363ffffffff6124ab16565b50505050565b7f55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b600090815260209081527ff7d5eefab3776d7f0450bd0193564bcb4f832ce313ff2836c450fc63a4b944198290556040805183815290517f52264b89e0fceafb26e79fd49ef8a366eb6297483bf4035b027f0c99a7ad512e929181900390910190a150565b606890565b606060008082818515156126a15760408051808201909152600181527f300000000000000000000000000000000000000000000000000000000000000060208201529450612776565b8593505b83156126bc57600190920191600a840493506126a5565b826040519080825280601f01601f1916602001820160405280156126ea578160200160208202803883390190505b5091505060001982015b85156127725781516000198201917f01000000000000000000000000000000000000000000000000000000000000006030600a8a06010291849190811061273757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a860495506126f4565b8194505b50505050919050565b600081151561278f575081611c7b565b60008213156127b3576127ac83600a84900a63ffffffff61283216565b9050611c7b565b610f1f836000849003600a0a63ffffffff61285b16565b604051600160a060020a0383169082156108fc029083906000818181858888f193505050501515610ed85780826127ff612870565b600160a060020a039091168152604051908190036020019082f08015801561282b573d6000803e3d6000fd5b5050505050565b600082151561284357506000611c7b565b5081810281838281151561285357fe5b0414611c7b57fe5b6000818381151561286857fe5b049392505050565b604051602180612880833901905600608060405260405160208060218339810160405251600160a060020a038116ff00a165627a7a723058202f0e2dccf7a13b5017a1bf75fe0cfa2077f327354e12aa432c9c8403a53b29da0029
Deployed Bytecode
0x60806040526004361061019d5763ffffffff60e060020a60003504166301e4f53a81146101a25780630e6a39db146101c85780631dcea4271461021c57806321d800ec1461024d5780632bd0bb0514610265578063392e53cd1461028f5780633dd95d1b146102a45780633e6968b6146102bc5780633f0a9f65146102d15780633f7658fd146102e6578063437764df1461031257806343b37dd31461035c5780634fb3fef71461037157806367eeba0c1461038957806369ffa08a1461039e578063879ce676146103c55780638aa1949a146103dd5780638d068043146103f25780638da5cb5b1461040757806395e54a171461041c57806399439089146104315780639a454b99146104465780639cb7595a1461045b578063a2a6ca271461049c578063acf5c689146104b4578063b20d30a9146104cc578063bf1fe420146104e4578063c6f6f216146104fc578063dae5f0fd14610514578063df25f3f014610529578063ea9f49681461053e578063f20151e114610556578063f2fde38b1461056e578063f968adbe1461058f578063fe173b97146105a4575b600080fd5b3480156101ae57600080fd5b506101c6600160a060020a03600435166024356105b9565b005b3480156101d457600080fd5b50610208600160a060020a03600435811690602435811690604435906064359060849060e490610124351661014435610681565b604080519115158252519081900360200190f35b34801561022857600080fd5b5061023161083b565b60408051600160a060020a039092168252519081900360200190f35b34801561025957600080fd5b50610208600435610892565b34801561027157600080fd5b5061027d60043561095b565b60408051918252519081900360200190f35b34801561029b57600080fd5b50610208610a18565b3480156102b057600080fd5b506101c6600435610a69565b3480156102c857600080fd5b5061027d610b29565b3480156102dd57600080fd5b5061027d610b32565b3480156102f257600080fd5b506101c66024600480358281019290820135918135918201910135610b80565b34801561031e57600080fd5b50610327610cf5565b604080517fffffffff000000000000000000000000000000000000000000000000000000009092168252519081900360200190f35b34801561036857600080fd5b5061027d610d19565b34801561037d57600080fd5b5061027d600435610d67565b34801561039557600080fd5b5061027d610de2565b3480156103aa57600080fd5b506101c6600160a060020a0360043581169060243516610e30565b3480156103d157600080fd5b50610208600435610edc565b3480156103e957600080fd5b5061027d610f26565b3480156103fe57600080fd5b5061027d610f74565b34801561041357600080fd5b50610231610fec565b34801561042857600080fd5b5061027d611043565b34801561043d57600080fd5b5061023161109d565b34801561045257600080fd5b5061027d6110f4565b34801561046757600080fd5b50610470611142565b6040805167ffffffffffffffff9485168152928416602084015292168183015290519081900360600190f35b3480156104a857600080fd5b506101c660043561114d565b3480156104c057600080fd5b506101c66004356111e9565b3480156104d857600080fd5b506101c6600435611211565b3480156104f057600080fd5b506101c66004356112d1565b34801561050857600080fd5b506101c66004356112f6565b34801561052057600080fd5b5061027d61138e565b34801561053557600080fd5b5061027d6113dc565b34801561054a57600080fd5b5061020860043561142a565b34801561056257600080fd5b506101c6600435611475565b34801561057a57600080fd5b506101c6600160a060020a03600435166114f1565b34801561059b57600080fd5b5061027d611516565b3480156105b057600080fd5b5061027d611564565b600160a060020a03821615156105ce57600080fd5b600160a060020a0382163014156105e457600080fd5b600081116105f157600080fd5b6105fa8161142a565b151561060557600080fd5b610616610610610b29565b826115b2565b610639338261062361083b565b600160a060020a0316919063ffffffff61167b16565b60408051600160a060020a03841681526020810183905281517f1d491a427d1f8cc0d447496f300fac39f7306122481d8e663451eb268274146b929181900390910190a15050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f6fde8202000000000000000000000000000000000000000000000000000000001781529151815160009330939291829190808383895b838110156107025781810151838201526020016106ea565b50505050905090810190601f16801561072f5780820380516001836020036101000a031916815260200191505b509150506000604051808303816000865af191505015806107c1575030600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b15801561078957600080fd5b505af115801561079d573d6000803e3d6000fd5b505050506040513d60208110156107b357600080fd5b5051600160a060020a031633145b806107cb57503330145b15156107d657600080fd5b61082689898989896003806020026040519081016040528092919082600360200280828437505060408051808201825293508d925060029150839083908082843782019150505050508989611723565b61082e610a18565b9998505050505050505050565b7f15d63b18dbc21bf4438b7972d80076747e1d93c4f87552fe498c90cbde51665e60005260026020527f70dfdbaec92bfd068fb9a67f8c22440e995abe75330f5b6b79a478c9bc8ccbd154600160a060020a031690565b6000600460008360405160200180807f72656c617965644d657373616765730000000000000000000000000000000000815250600f0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b602083106109175780518252601f1990920191602091820191016108f8565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1695945050505050565b60008060008360405160200180807f746f74616c5370656e74506572446179000000000000000000000000000000008152506010018281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106109d75780518252601f1990920191602091820191016109b8565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205495945050505050565b7f0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba60005260046020527f078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc5460ff1690565b610a71610fec565b600160a060020a03163314610a8557600080fd5b610a8d610f26565b811180610a98575080155b1515610aa357600080fd5b7f21dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d237600090815260209081527fadd938dbd083a16bae12238cd914fca0afc7a30edb55b1cd5c7f1823f1b0e4218290556040805183815290517f9bebf928b90863f24cc31f726a3a7545efd409f1dcf552301b1ee3710da70d3b929181900390910190a150565b62015180420490565b7f916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d7940723007160009081526020527fd2ea0feb732edb0ffe32efd33a6b9d24d46b16eb34a4d07ce256537b6f131e425490565b600080600080610bf888888080601f0160208091040260200160405190810160405280939291908181526020018383808284375050604080516020601f8e018190048102820181019092528c815294508c93508b9250829150840183828082843750610bf1945061109d9350505050565b600061184c565b610c3188888080601f01602080910402602001604051908101604052809392919081815260200183838082843750611ad6945050505050565b92965090945092509050610c4483610edc565b15610ce057600160a060020a0381163014610c5e57600080fd5b610c6782610892565b15610c7157600080fd5b610c7c826001611b11565b610c87848484611be3565b1515610c9257600080fd5b60408051600160a060020a03861681526020810185905280820184905290517f4ab7d581336d92edbea22636a613e8e76c99ac7f91137c1523db38dbfb3bf3299181900360600190a1610ceb565b610ceb84848461019d565b5050505050505050565b7fba4690f50000000000000000000000000000000000000000000000000000000090565b7f21dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d23760009081526020527fadd938dbd083a16bae12238cd914fca0afc7a30edb55b1cd5c7f1823f1b0e4215490565b60008060008360405160200180807f746f74616c457865637574656450657244617900000000000000000000000000815250601301828152602001915050604051602081830303815290604052604051808280519060200190808383602083106109d75780518252601f1990920191602091820191016109b8565b7f4a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a560009081526020527f1ab29a5cca988aee50edccdd61c5bcaa7ad4b29a03b7ee50f298ceccfe14cc4e5490565b30600160a060020a0316636fde82026040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015610e6e57600080fd5b505af1158015610e82573d6000803e3d6000fd5b505050506040513d6020811015610e9857600080fd5b5051600160a060020a03163314610eae57600080fd5b610eb661083b565b600160a060020a0383811691161415610ece57600080fd5b610ed88282611c30565b5050565b600080610eff83610ef3610eee610b29565b610d67565b9063ffffffff611c6e16565b905080610f0a610d19565b10158015610f1f5750610f1b610f26565b8311155b9392505050565b7fc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d560009081526020527ff8e983ee86e5e377e9e34c9131b266382c3f04113d20de077f9e12663c7a646b5490565b6000610f7e61109d565b600160a060020a0316638d0680436040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015610fbb57600080fd5b505af1158015610fcf573d6000803e3d6000fd5b505050506040513d6020811015610fe557600080fd5b5051905090565b7f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060005260026020527fb7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e54600160a060020a031690565b6000806000806000611053611516565b935061105d610de2565b925061106f61106a610b29565b61095b565b915081831161107f576000611083565b8183035b90508084106110925780611094565b835b94505050505090565b7f5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe60005260026020527fab54f3fbbe62c59b7876a9bf9bd5e0c22dbae93f4d8ee0438f7ce62b198eb0e054600160a060020a031690565b7fb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b060009081526020527fe66bef0282a446f9848e2903380099bb6e431483ee78778868f33b4a154c818b5490565b600560026000909192565b611155610fec565b600160a060020a0316331461116957600080fd5b60008111801561117f575061117c610de2565b81105b8015611191575061118e611516565b81105b151561119c57600080fd5b7fbbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d160009081526020527f8df5c48c6b6e11d97548adc824ba0c99103ec09830fa5d53a179984085e6eaa055565b6111f1610fec565b600160a060020a0316331461120557600080fd5b61120e81611c81565b50565b611219610fec565b600160a060020a0316331461122d57600080fd5b611235611516565b811180611240575080155b151561124b57600080fd5b7f4a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a5600090815260209081527f1ab29a5cca988aee50edccdd61c5bcaa7ad4b29a03b7ee50f298ceccfe14cc4e8290556040805183815290517fad4123ae17c414d9c6d2fec478b402e6b01856cc250fd01fbfd252fda0089d3c929181900390910190a150565b6112d9610fec565b600160a060020a031633146112ed57600080fd5b61120e81611d14565b6112fe610fec565b600160a060020a0316331461131257600080fd5b80158061133657506113226113dc565b811180156113365750611333610de2565b81105b151561134157600080fd5b7f0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c60009081526020527f9de0f81379b4d8e60fe509315d071b56e7b732abaf193e74e0d15808b0951d0955565b7f1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee560009081526020527fd5c78dd9468716ca9bb96be25d56436811b20aab3523a9904b12deef1cab239d5490565b7fbbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d160009081526020527f8df5c48c6b6e11d97548adc824ba0c99103ec09830fa5d53a179984085e6eaa05490565b60008061143c83610ef361106a610b29565b905080611447610de2565b1015801561145c5750611458611516565b8311155b8015610f1f575061146b6113dc565b9092101592915050565b61147d610fec565b600160a060020a0316331461149157600080fd5b611499610d19565b81106114a457600080fd5b7fc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d560009081526020527ff8e983ee86e5e377e9e34c9131b266382c3f04113d20de077f9e12663c7a646b55565b6114f9610fec565b600160a060020a0316331461150d57600080fd5b61120e81611d2a565b7f0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c60009081526020527f9de0f81379b4d8e60fe509315d071b56e7b732abaf193e74e0d15808b0951d095490565b7f55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b60009081526020527ff7d5eefab3776d7f0450bd0193564bcb4f832ce313ff2836c450fc63a4b944195490565b6115bf81610ef38461095b565b6000808460405160200180807f746f74616c5370656e74506572446179000000000000000000000000000000008152506010018281526020019150506040516020818303038152906040526040518082805190602001908083835b602083106116395780518252601f19909201916020918201910161161a565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020939093555050505050565b604080517f23b872dd000000000000000000000000000000000000000000000000000000008152600160a060020a038481166004830152306024830152604482018490529151918516916323b872dd9160648082019260009290919082900301818387803b1580156116ec57600080fd5b505af1158015611700573d6000803e3d6000fd5b505050503d1561171e5760206000803e600051151561171e57600080fd5b505050565b61172b610a18565b1561173557600080fd5b61173e88611e01565b151561174957600080fd5b7f5a74bb7e202fb8e4bf311841c7d64ec19df195fee77d7e7ae749b27921b6ddfe60005260026020527fab54f3fbbe62c59b7876a9bf9bd5e0c22dbae93f4d8ee0438f7ce62b198eb0e0805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038a161790556117c287611e09565b7fb120ceec05576ad0c710bc6e85f1768535e27554458f05dcbb5c65b8c7a749b06000908152602052437fe66bef0282a446f9848e2903380099bb6e431483ee78778868f33b4a154c818b5561181786611c81565b61182085611d14565b61182984611e94565b61183283611ff1565b61183b816120c6565b61184482611d2a565b610ceb61212f565b6000806000606060008060008060008060008b8061186e575061186e8f612186565b151561187957600080fd5b8c600160a060020a0316638d0680436040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156118b757600080fd5b505af11580156118cb573d6000803e3d6000fd5b505050506040513d60208110156118e157600080fd5b505160018f0151909b5060ff1699508a8a10156118fd57600080fd5b6119078f8d61219a565b98508a604051908082528060200260200182016040528015611933578160200160208202803883390190505b509750600096505b8a871015611ac557866020028a6021010192508960200283019150866002018e01519550828e01519450818e01519350600189878787604051600081526020016040526040518085600019166000191681526020018460ff1660ff1681526020018360001916600019168152602001826000191660001916815260200194505050505060206040516020810390808403906000865af11580156119e2573d6000803e3d6000fd5b5050506020604051035190508c600160a060020a031663facd743b826040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b158015611a4957600080fd5b505af1158015611a5d573d6000803e3d6000fd5b505050506040513d6020811015611a7357600080fd5b50511515611a8057600080fd5b611a8a88826123b4565b15611a9457600080fd5b808888815181101515611aa357fe5b600160a060020a0390921660209283029091019091015260019096019561193b565b505050505050505050505050505050565b600080600080611ae585612186565b1515611af057600080fd5b50505050601481015160348201516054830151606890930151919390929190565b80600460008460405160200180807f72656c617965644d657373616765730000000000000000000000000000000000815250600f0182600019166000191681526020019150506040516020818303038152906040526040518082805190602001908083835b60208310611b955780518252601f199092019160209182019101611b76565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff1916941515949094179093555050505050565b600080611bf7611bf1610b29565b8561240f565b611c0084612495565b9050611c258582611c0f61083b565b600160a060020a0316919063ffffffff6124ab16565b506001949350505050565b80600160a060020a0381161515611c4657600080fd5b600160a060020a0383161515611c6457611c5f8261250e565b61171e565b61171e838361251a565b81810182811015611c7b57fe5b92915050565b60008111611c8e57600080fd5b7f916daedf6915000ff68ced2f0b6773fe6f2582237f92c3c95bb4d79407230071600090815260209081527fd2ea0feb732edb0ffe32efd33a6b9d24d46b16eb34a4d07ce256537b6f131e428290556040805183815290517f4fb76205cd57c896b21511d2114137d8e901b4ccd659e1a0f97d6306795264fb929181900390910190a150565b60008111611d2157600080fd5b61120e816125cd565b600160a060020a0381161515611d3f57600080fd5b7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0611d68610fec565b60408051600160a060020a03928316815291841660208301528051918290030190a17f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c060005260026020527fb7802e97e87ef2842a6cce7da7ffaeaedaa2f61a6a7870b23d9d01fc9b73712e805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b6000903b1190565b611e1281611e01565b1515611e1d57600080fd5b7f15d63b18dbc21bf4438b7972d80076747e1d93c4f87552fe498c90cbde51665e60005260026020527f70dfdbaec92bfd068fb9a67f8c22440e995abe75330f5b6b79a478c9bc8ccbd1805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60408101516000108015611eaf575060408101516020820151115b8015611ebf575060208101518151115b1515611eca57600080fd5b80517f4a6a899679f26b73530d8cf1001e83b6f7702e04b6fdb98f3c62dc7e47e041a5600090815260208181527f1ab29a5cca988aee50edccdd61c5bcaa7ad4b29a03b7ee50f298ceccfe14cc4e92909255908201517f0f8803acad17c63ee38bf2de71e1888bc7a079a6f73658e274b08018bea4e29c82527f9de0f81379b4d8e60fe509315d071b56e7b732abaf193e74e0d15808b0951d095560408201517fbbb088c505d18e049d114c7c91f11724e69c55ad6c5397e2b929e68b41fa05d182527f8df5c48c6b6e11d97548adc824ba0c99103ec09830fa5d53a179984085e6eaa0557fad4123ae17c414d9c6d2fec478b402e6b01856cc250fd01fbfd252fda0089d3c9082905b60200201516040518082815260200191505060405180910390a150565b805160208201511061200257600080fd5b80517f21dbcab260e413c20dc13c28b7db95e2b423d1135f42bb8b7d5214a92270d237600090815260208181527fadd938dbd083a16bae12238cd914fca0afc7a30edb55b1cd5c7f1823f1b0e42192909255908201517fc0ed44c192c86d1cc1ba51340b032c2766b4a2b0041031de13c46dd7104888d582527ff8e983ee86e5e377e9e34c9131b266382c3f04113d20de077f9e12663c7a646b557f9bebf928b90863f24cc31f726a3a7545efd409f1dcf552301b1ee3710da70d3b908290611fd4565b604c19811380156120d75750604d81125b15156120e257600080fd5b7f1e8ecaafaddea96ed9ac6d2642dcdfe1bebe58a930b1085842d8fc122b371ee560009081526020527fd5c78dd9468716ca9bb96be25d56436811b20aab3523a9904b12deef1cab239d55565b7f0a6f646cd611241d8073675e00d1a1ff700fbf1b53fcf473de56d1e6e4b714ba60005260046020527f078d888f9b66f3f8bfa10909e31f1e16240db73449f0500afdbbe3a70da457cc805460ff19166001179055565b6000612190612653565b8251149050919050565b60408051808201909152601a81527f19457468657265756d205369676e6564204d6573736167653a0a00000000000060208201526000906060831561234057816121e48651612658565b866040516020018084805190602001908083835b602083106122175780518252601f1990920191602091820191016121f8565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b6020831061225f5780518252601f199092019160209182019101612240565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b602083106122a75780518252601f199092019160209182019101612288565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040526040518082805190602001908083835b6020831061230c5780518252601f1990920191602091820191016122ed565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902092506123ac565b6040805190810160405280600381526020017f31303400000000000000000000000000000000000000000000000000000000008152509050818186604051602001808480519060200190808383602083106122175780518252601f1990920191602091820191016121f8565b505092915050565b6000805b83518110156124035782600160a060020a031684828151811015156123d957fe5b90602001906020020151600160a060020a031614156123fb5760019150612408565b6001016123b8565b600091505b5092915050565b61241c81610ef384610d67565b6000808460405160200180807f746f74616c457865637574656450657244617900000000000000000000000000815250601301828152602001915050604051602081830303815290604052604051808280519060200190808383602083106116395780518252601f19909201916020918201910161161a565b6000611c7b826124a361138e565b60000361277f565b82600160a060020a031663a9059cbb83836040518363ffffffff1660e060020a0281526004018083600160a060020a0316600160a060020a0316815260200182815260200192505050600060405180830381600087803b1580156116ec57600080fd5b3031610ed882826127ca565b604080517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290518391600091600160a060020a038416916370a0823191602480830192602092919082900301818787803b15801561257f57600080fd5b505af1158015612593573d6000803e3d6000fd5b505050506040513d60208110156125a957600080fd5b505190506125c7600160a060020a038516848363ffffffff6124ab16565b50505050565b7f55b3774520b5993024893d303890baa4e84b1244a43c60034d1ced2d3cf2b04b600090815260209081527ff7d5eefab3776d7f0450bd0193564bcb4f832ce313ff2836c450fc63a4b944198290556040805183815290517f52264b89e0fceafb26e79fd49ef8a366eb6297483bf4035b027f0c99a7ad512e929181900390910190a150565b606890565b606060008082818515156126a15760408051808201909152600181527f300000000000000000000000000000000000000000000000000000000000000060208201529450612776565b8593505b83156126bc57600190920191600a840493506126a5565b826040519080825280601f01601f1916602001820160405280156126ea578160200160208202803883390190505b5091505060001982015b85156127725781516000198201917f01000000000000000000000000000000000000000000000000000000000000006030600a8a06010291849190811061273757fe5b9060200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a860495506126f4565b8194505b50505050919050565b600081151561278f575081611c7b565b60008213156127b3576127ac83600a84900a63ffffffff61283216565b9050611c7b565b610f1f836000849003600a0a63ffffffff61285b16565b604051600160a060020a0383169082156108fc029083906000818181858888f193505050501515610ed85780826127ff612870565b600160a060020a039091168152604051908190036020019082f08015801561282b573d6000803e3d6000fd5b5050505050565b600082151561284357506000611c7b565b5081810281838281151561285357fe5b0414611c7b57fe5b6000818381151561286857fe5b049392505050565b604051602180612880833901905600608060405260405160208060218339810160405251600160a060020a038116ff00a165627a7a723058202f0e2dccf7a13b5017a1bf75fe0cfa2077f327354e12aa432c9c8403a53b29da0029
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.