Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Multichain Info
No addresses found
Latest 25 from a total of 205 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Remove Tokens | 20112253 | 285 days ago | IN | 0 ETH | 0.0057759 | ||||
Set Token Redeem... | 20112248 | 285 days ago | IN | 0 ETH | 0.00086466 | ||||
Set Token Redeem... | 20112133 | 285 days ago | IN | 0 ETH | 0.00090163 | ||||
Update Token Rat... | 15391201 | 950 days ago | IN | 0 ETH | 0.00170532 | ||||
Update Token Rat... | 12964743 | 1332 days ago | IN | 0 ETH | 0.00341348 | ||||
Add Tokens | 12964722 | 1332 days ago | IN | 0 ETH | 0.00689644 | ||||
Update Token Rat... | 12549405 | 1397 days ago | IN | 0 ETH | 0.00256011 | ||||
Update Token Rat... | 12549405 | 1397 days ago | IN | 0 ETH | 0.00255975 | ||||
Update Token Rat... | 12549405 | 1397 days ago | IN | 0 ETH | 0.00255975 | ||||
Update Token Rat... | 12549399 | 1397 days ago | IN | 0 ETH | 0.00256011 | ||||
Update Token Rat... | 12549399 | 1397 days ago | IN | 0 ETH | 0.00255975 | ||||
Update Token Rat... | 12549396 | 1397 days ago | IN | 0 ETH | 0.00256011 | ||||
Update Token Rat... | 12549395 | 1397 days ago | IN | 0 ETH | 0.00256047 | ||||
Update Token Rat... | 12549395 | 1397 days ago | IN | 0 ETH | 0.00255975 | ||||
Update Token Rat... | 12549390 | 1397 days ago | IN | 0 ETH | 0.00255939 | ||||
Update Token Rat... | 12549390 | 1397 days ago | IN | 0 ETH | 0.00256011 | ||||
Update Token Rat... | 12549390 | 1397 days ago | IN | 0 ETH | 0.00255939 | ||||
Update Token Rat... | 12549390 | 1397 days ago | IN | 0 ETH | 0.00256011 | ||||
Update Token Rat... | 12549390 | 1397 days ago | IN | 0 ETH | 0.00256083 | ||||
Update Token Rat... | 12549380 | 1397 days ago | IN | 0 ETH | 0.00256083 | ||||
Update Token Rat... | 12549379 | 1397 days ago | IN | 0 ETH | 0.00255975 | ||||
Update Token Rat... | 12549375 | 1397 days ago | IN | 0 ETH | 0.00256047 | ||||
Update Token Rat... | 12549375 | 1397 days ago | IN | 0 ETH | 0.00256047 | ||||
Update Token Rat... | 12549374 | 1397 days ago | IN | 0 ETH | 0.00256011 | ||||
Update Token Rat... | 12549370 | 1397 days ago | IN | 0 ETH | 0.00256011 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
TokenWhitelist
Compiler Version
v0.5.10+commit.5a6ea5b1
Contract Source Code (Solidity Multiple files format)
/** * TokenWhitelist - The Consumer Contract Wallet * Copyright (C) 2019 The Contract Wallet Company Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity ^0.5.10; import "./controllable.sol"; import "./transferrable.sol"; import "./bytesUtils.sol"; import "./strings.sol"; import "./SafeMath.sol"; /// @title The ITokenWhitelist interface provides access to a whitelist of tokens. interface ITokenWhitelist { function getTokenInfo(address) external view returns (string memory, uint256, uint256, bool, bool, bool, uint256); function getStablecoinInfo() external view returns (string memory, uint256, uint256, bool, bool, bool, uint256); function tokenAddressArray() external view returns (address[] memory); function redeemableTokens() external view returns (address[] memory); function methodIdWhitelist(bytes4) external view returns (bool); function getERC20RecipientAndAmount(address, bytes calldata) external view returns (address, uint); function stablecoin() external view returns (address); function updateTokenRate(address, uint, uint) external; } /// @title TokenWhitelist stores a list of tokens used by the Consumer Contract Wallet, the Oracle, the TKN Holder and the TKN Licence Contract contract TokenWhitelist is ENSResolvable, Controllable, Transferrable { using strings for *; using SafeMath for uint256; using BytesUtils for bytes; event UpdatedTokenRate(address _sender, address _token, uint _rate); event UpdatedTokenLoadable(address _sender, address _token, bool _loadable); event UpdatedTokenRedeemable(address _sender, address _token, bool _redeemable); event AddedToken(address _sender, address _token, string _symbol, uint _magnitude, bool _loadable, bool _redeemable); event RemovedToken(address _sender, address _token); event AddedMethodId(bytes4 _methodId); event RemovedMethodId(bytes4 _methodId); event AddedExclusiveMethod(address _token, bytes4 _methodId); event RemovedExclusiveMethod(address _token, bytes4 _methodId); event Claimed(address _to, address _asset, uint _amount); /// @dev these are the methods whitelisted by default in executeTransaction() for protected tokens bytes4 private constant _APPROVE = 0x095ea7b3; // keccak256(approve(address,uint256)) => 0x095ea7b3 bytes4 private constant _BURN = 0x42966c68; // keccak256(burn(uint256)) => 0x42966c68 bytes4 private constant _TRANSFER= 0xa9059cbb; // keccak256(transfer(address,uint256)) => 0xa9059cbb bytes4 private constant _TRANSFER_FROM = 0x23b872dd; // keccak256(transferFrom(address,address,uint256)) => 0x23b872dd struct Token { string symbol; // Token symbol uint magnitude; // 10^decimals uint rate; // Token exchange rate in wei bool available; // Flags if the token is available or not bool loadable; // Flags if token is loadable to the TokenCard bool redeemable; // Flags if token is redeemable in the TKN Holder contract uint lastUpdate; // Time of the last rate update } mapping(address => Token) private _tokenInfoMap; // @notice specifies whitelisted methodIds for protected tokens in wallet's excuteTranaction() e.g. keccak256(transfer(address,uint256)) => 0xa9059cbb mapping(bytes4 => bool) private _methodIdWhitelist; address[] private _tokenAddressArray; /// @notice keeping track of how many redeemable tokens are in the tokenWhitelist uint private _redeemableCounter; /// @notice Address of the stablecoin. address private _stablecoin; /// @notice is registered ENS node identifying the oracle contract. bytes32 private _oracleNode; /// @notice Constructor initializes ENSResolvable, and Controllable. /// @param _ens_ is the ENS registry address. /// @param _oracleNode_ is the ENS node of the Oracle. /// @param _controllerNode_ is our Controllers node. /// @param _stablecoinAddress_ is the address of the stablecoint used by the wallet for the card load limit. constructor(address _ens_, bytes32 _oracleNode_, bytes32 _controllerNode_, address _stablecoinAddress_) ENSResolvable(_ens_) Controllable(_controllerNode_) public { _oracleNode = _oracleNode_; _stablecoin = _stablecoinAddress_; //a priori ERC20 whitelisted methods _methodIdWhitelist[_APPROVE] = true; _methodIdWhitelist[_BURN] = true; _methodIdWhitelist[_TRANSFER] = true; _methodIdWhitelist[_TRANSFER_FROM] = true; } modifier onlyAdminOrOracle() { address oracleAddress = _ensResolve(_oracleNode); require (_isAdmin(msg.sender) || msg.sender == oracleAddress, "either oracle or admin"); _; } /// @notice Add ERC20 tokens to the list of whitelisted tokens. /// @param _tokens ERC20 token contract addresses. /// @param _symbols ERC20 token names. /// @param _magnitude 10 to the power of number of decimal places used by each ERC20 token. /// @param _loadable is a bool that states whether or not a token is loadable to the TokenCard. /// @param _redeemable is a bool that states whether or not a token is redeemable in the TKN Holder Contract. /// @param _lastUpdate is a unit representing an ISO datetime e.g. 20180913153211. function addTokens(address[] calldata _tokens, bytes32[] calldata _symbols, uint[] calldata _magnitude, bool[] calldata _loadable, bool[] calldata _redeemable, uint _lastUpdate) external onlyAdmin { // Require that all parameters have the same length. require(_tokens.length == _symbols.length && _tokens.length == _magnitude.length && _tokens.length == _loadable.length && _tokens.length == _loadable.length, "parameter lengths do not match"); // Add each token to the list of supported tokens. for (uint i = 0; i < _tokens.length; i++) { // Require that the token isn't already available. require(!_tokenInfoMap[_tokens[i]].available, "token already available"); // Store the intermediate values. string memory symbol = _symbols[i].toSliceB32().toString(); // Add the token to the token list. _tokenInfoMap[_tokens[i]] = Token({ symbol : symbol, magnitude : _magnitude[i], rate : 0, available : true, loadable : _loadable[i], redeemable: _redeemable[i], lastUpdate : _lastUpdate }); // Add the token address to the address list. _tokenAddressArray.push(_tokens[i]); //if the token is redeemable increase the redeemableCounter if (_redeemable[i]){ _redeemableCounter = _redeemableCounter.add(1); } // Emit token addition event. emit AddedToken(msg.sender, _tokens[i], symbol, _magnitude[i], _loadable[i], _redeemable[i]); } } /// @notice Remove ERC20 tokens from the whitelist of tokens. /// @param _tokens ERC20 token contract addresses. function removeTokens(address[] calldata _tokens) external onlyAdmin { // Delete each token object from the list of supported tokens based on the addresses provided. for (uint i = 0; i < _tokens.length; i++) { // Store the token address. address token = _tokens[i]; //token must be available, reverts on duplicates as well require(_tokenInfoMap[token].available, "token is not available"); //if the token is redeemable decrease the redeemableCounter if (_tokenInfoMap[token].redeemable){ _redeemableCounter = _redeemableCounter.sub(1); } // Delete the token object. delete _tokenInfoMap[token]; // Remove the token address from the address list. for (uint j = 0; j < _tokenAddressArray.length.sub(1); j++) { if (_tokenAddressArray[j] == token) { _tokenAddressArray[j] = _tokenAddressArray[_tokenAddressArray.length.sub(1)]; break; } } _tokenAddressArray.length--; // Emit token removal event. emit RemovedToken(msg.sender, token); } } /// @notice based on the method it returns the recipient address and amount/value, ERC20 specific. /// @param _data is the transaction payload. function getERC20RecipientAndAmount(address _token, bytes calldata _data) external view returns (address, uint) { // Require that there exist enough bytes for encoding at least a method signature + data in the transaction payload: // 4 (signature) + 32(address or uint256) require(_data.length >= 4 + 32, "not enough method-encoding bytes"); // Get the method signature bytes4 signature = _data._bytesToBytes4(0); // Check if method Id is supported require(isERC20MethodSupported(_token, signature), "unsupported method"); // returns the recipient's address and amount is the value to be transferred if (signature == _BURN) { // 4 (signature) + 32(uint256) return (_token, _data._bytesToUint256(4)); } else if (signature == _TRANSFER_FROM) { // 4 (signature) + 32(address) + 32(address) + 32(uint256) require(_data.length >= 4 + 32 + 32 + 32, "not enough data for transferFrom"); return ( _data._bytesToAddress(4 + 32 + 12), _data._bytesToUint256(4 + 32 + 32)); } else { //transfer or approve // 4 (signature) + 32(address) + 32(uint) require(_data.length >= 4 + 32 + 32, "not enough data for transfer/appprove"); return (_data._bytesToAddress(4 + 12), _data._bytesToUint256(4 + 32)); } } /// @notice Toggles whether or not a token is loadable or not. function setTokenLoadable(address _token, bool _loadable) external onlyAdmin { // Require that the token exists. require(_tokenInfoMap[_token].available, "token is not available"); // this sets the loadable flag to the value passed in _tokenInfoMap[_token].loadable = _loadable; emit UpdatedTokenLoadable(msg.sender, _token, _loadable); } /// @notice Toggles whether or not a token is redeemable or not. function setTokenRedeemable(address _token, bool _redeemable) external onlyAdmin { // Require that the token exists. require(_tokenInfoMap[_token].available, "token is not available"); // this sets the redeemable flag to the value passed in _tokenInfoMap[_token].redeemable = _redeemable; emit UpdatedTokenRedeemable(msg.sender, _token, _redeemable); } /// @notice Update ERC20 token exchange rate. /// @param _token ERC20 token contract address. /// @param _rate ERC20 token exchange rate in wei. /// @param _updateDate date for the token updates. This will be compared to when oracle updates are received. function updateTokenRate(address _token, uint _rate, uint _updateDate) external onlyAdminOrOracle { // Require that the token exists. require(_tokenInfoMap[_token].available, "token is not available"); // Update the token's rate. _tokenInfoMap[_token].rate = _rate; // Update the token's last update timestamp. _tokenInfoMap[_token].lastUpdate = _updateDate; // Emit the rate update event. emit UpdatedTokenRate(msg.sender, _token, _rate); } //// @notice Withdraw tokens from the smart contract to the specified account. function claim(address payable _to, address _asset, uint _amount) external onlyAdmin { _safeTransfer(_to, _asset, _amount); emit Claimed(_to, _asset, _amount); } /// @notice This returns all of the fields for a given token. /// @param _a is the address of a given token. /// @return string of the token's symbol. /// @return uint of the token's magnitude. /// @return uint of the token's exchange rate to ETH. /// @return bool whether the token is available. /// @return bool whether the token is loadable to the TokenCard. /// @return bool whether the token is redeemable to the TKN Holder Contract. /// @return uint of the lastUpdated time of the token's exchange rate. function getTokenInfo(address _a) external view returns (string memory, uint256, uint256, bool, bool, bool, uint256) { Token storage tokenInfo = _tokenInfoMap[_a]; return (tokenInfo.symbol, tokenInfo.magnitude, tokenInfo.rate, tokenInfo.available, tokenInfo.loadable, tokenInfo.redeemable, tokenInfo.lastUpdate); } /// @notice This returns all of the fields for our StableCoin. /// @return string of the token's symbol. /// @return uint of the token's magnitude. /// @return uint of the token's exchange rate to ETH. /// @return bool whether the token is available. /// @return bool whether the token is loadable to the TokenCard. /// @return bool whether the token is redeemable to the TKN Holder Contract. /// @return uint of the lastUpdated time of the token's exchange rate. function getStablecoinInfo() external view returns (string memory, uint256, uint256, bool, bool, bool, uint256) { Token storage stablecoinInfo = _tokenInfoMap[_stablecoin]; return (stablecoinInfo.symbol, stablecoinInfo.magnitude, stablecoinInfo.rate, stablecoinInfo.available, stablecoinInfo.loadable, stablecoinInfo.redeemable, stablecoinInfo.lastUpdate); } /// @notice This returns an array of all whitelisted token addresses. /// @return address[] of whitelisted tokens. function tokenAddressArray() external view returns (address[] memory) { return _tokenAddressArray; } /// @notice This returns an array of all redeemable token addresses. /// @return address[] of redeemable tokens. function redeemableTokens() external view returns (address[] memory) { address[] memory redeemableAddresses = new address[](_redeemableCounter); uint redeemableIndex = 0; for (uint i = 0; i < _tokenAddressArray.length; i++) { address token = _tokenAddressArray[i]; if (_tokenInfoMap[token].redeemable){ redeemableAddresses[redeemableIndex] = token; redeemableIndex += 1; } } return redeemableAddresses; } /// @notice This returns true if a method Id is supported for the specific token. /// @return true if _methodId is supported in general or just for the specific token. function isERC20MethodSupported(address _token, bytes4 _methodId) public view returns (bool) { require(_tokenInfoMap[_token].available, "non-existing token"); return (_methodIdWhitelist[_methodId]); } /// @notice This returns true if the method is supported for all protected tokens. /// @return true if _methodId is in the method whitelist. function isERC20MethodWhitelisted(bytes4 _methodId) external view returns (bool) { return (_methodIdWhitelist[_methodId]); } /// @notice This returns the number of redeemable tokens. /// @return current # of redeemables. function redeemableCounter() external view returns (uint) { return _redeemableCounter; } /// @notice This returns the address of our stablecoin of choice. /// @return the address of the stablecoin contract. function stablecoin() external view returns (address) { return _stablecoin; } /// @notice this returns the node hash of our Oracle. /// @return the oracle node registered in ENS. function oracleNode() external view returns (bytes32) { return _oracleNode; } }
pragma solidity ^0.5.0; import "./ResolverBase.sol"; contract ABIResolver is ResolverBase { bytes4 constant private ABI_INTERFACE_ID = 0x2203ab56; event ABIChanged(bytes32 indexed node, uint256 indexed contentType); mapping(bytes32=>mapping(uint256=>bytes)) abis; /** * Sets the ABI associated with an ENS node. * Nodes may have one ABI of each content type. To remove an ABI, set it to * the empty string. * @param node The node to update. * @param contentType The content type of the ABI * @param data The ABI data. */ function setABI(bytes32 node, uint256 contentType, bytes calldata data) external authorised(node) { // Content types must be powers of 2 require(((contentType - 1) & contentType) == 0); abis[node][contentType] = data; emit ABIChanged(node, contentType); } /** * Returns the ABI associated with an ENS node. * Defined in EIP205. * @param node The ENS node to query * @param contentTypes A bitwise OR of the ABI formats accepted by the caller. * @return contentType The content type of the return value * @return data The ABI data */ function ABI(bytes32 node, uint256 contentTypes) external view returns (uint256, bytes memory) { mapping(uint256=>bytes) storage abiset = abis[node]; for (uint256 contentType = 1; contentType <= contentTypes; contentType <<= 1) { if ((contentType & contentTypes) != 0 && abiset[contentType].length > 0) { return (contentType, abiset[contentType]); } } return (0, bytes("")); } function supportsInterface(bytes4 interfaceID) public pure returns(bool) { return interfaceID == ABI_INTERFACE_ID || super.supportsInterface(interfaceID); } }
pragma solidity ^0.5.0; /** * @dev Collection of functions related to the address type, */ library Address { /** * @dev Returns true if `account` is a contract. * * This test is non-exhaustive, and there may be false-negatives: during the * execution of a contract's constructor, its address will be reported as * not containing a contract. * * > It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. */ function isContract(address account) internal view returns (bool) { // This method relies in extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } }
pragma solidity ^0.5.0; import "./ResolverBase.sol"; contract AddrResolver is ResolverBase { bytes4 constant private ADDR_INTERFACE_ID = 0x3b3b57de; event AddrChanged(bytes32 indexed node, address a); mapping(bytes32=>address) addresses; /** * Sets the address associated with an ENS node. * May only be called by the owner of that node in the ENS registry. * @param node The node to update. * @param addr The address to set. */ function setAddr(bytes32 node, address addr) external authorised(node) { addresses[node] = addr; emit AddrChanged(node, addr); } /** * Returns the address associated with an ENS node. * @param node The ENS node to query. * @return The associated address. */ function addr(bytes32 node) public view returns (address) { return addresses[node]; } function supportsInterface(bytes4 interfaceID) public pure returns(bool) { return interfaceID == ADDR_INTERFACE_ID || super.supportsInterface(interfaceID); } }
/** * BytesUtils - The Consumer Contract Wallet * Copyright (C) 2019 The Contract Wallet Company Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity ^0.5.10; import "./SafeMath.sol"; /// @title BytesUtils provides basic byte slicing and casting functionality. library BytesUtils { using SafeMath for uint256; /// @dev This function converts to an address /// @param _bts bytes /// @param _from start position function _bytesToAddress(bytes memory _bts, uint _from) internal pure returns (address) { require(_bts.length >= _from.add(20), "slicing out of range"); bytes20 convertedAddress; uint startByte = _from.add(32); //first 32 bytes denote the array length assembly { convertedAddress := mload(add(_bts, startByte)) } return address(convertedAddress); } /// @dev This function slices bytes into bytes4 /// @param _bts some bytes /// @param _from start position function _bytesToBytes4(bytes memory _bts, uint _from) internal pure returns (bytes4) { require(_bts.length >= _from.add(4), "slicing out of range"); bytes4 slicedBytes4; uint startByte = _from.add(32); //first 32 bytes denote the array length assembly { slicedBytes4 := mload(add(_bts, startByte)) } return slicedBytes4; } /// @dev This function slices a uint /// @param _bts some bytes /// @param _from start position // credit to https://ethereum.stackexchange.com/questions/51229/how-to-convert-bytes-to-uint-in-solidity // and Nick Johnson https://ethereum.stackexchange.com/questions/4170/how-to-convert-a-uint-to-bytes-in-solidity/4177#4177 function _bytesToUint256(bytes memory _bts, uint _from) internal pure returns (uint) { require(_bts.length >= _from.add(32), "slicing out of range"); uint convertedUint256; uint startByte = _from.add(32); //first 32 bytes denote the array length assembly { convertedUint256 := mload(add(_bts, startByte)) } return convertedUint256; } }
pragma solidity ^0.5.0; import "./ResolverBase.sol"; contract ContentHashResolver is ResolverBase { bytes4 constant private CONTENT_HASH_INTERFACE_ID = 0xbc1c58d1; event ContenthashChanged(bytes32 indexed node, bytes hash); mapping(bytes32=>bytes) hashes; /** * Sets the contenthash associated with an ENS node. * May only be called by the owner of that node in the ENS registry. * @param node The node to update. * @param hash The contenthash to set */ function setContenthash(bytes32 node, bytes calldata hash) external authorised(node) { hashes[node] = hash; emit ContenthashChanged(node, hash); } /** * Returns the contenthash associated with an ENS node. * @param node The ENS node to query. * @return The associated contenthash. */ function contenthash(bytes32 node) external view returns (bytes memory) { return hashes[node]; } function supportsInterface(bytes4 interfaceID) public pure returns(bool) { return interfaceID == CONTENT_HASH_INTERFACE_ID || super.supportsInterface(interfaceID); } }
/** * Controllable - The Consumer Contract Wallet * Copyright (C) 2019 The Contract Wallet Company Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity ^0.5.10; import "./controller.sol"; import "./ensResolvable.sol"; /// @title Controllable implements access control functionality of the Controller found via ENS. contract Controllable is ENSResolvable { /// @dev Is the registered ENS node identifying the controller contract. bytes32 private _controllerNode; /// @notice Constructor initializes the controller contract object. /// @param _controllerNode_ is the ENS node of the Controller. constructor(bytes32 _controllerNode_) internal { _controllerNode = _controllerNode_; } /// @notice Checks if message sender is a controller. modifier onlyController() { require(_isController(msg.sender), "sender is not a controller"); _; } /// @notice Checks if message sender is an admin. modifier onlyAdmin() { require(_isAdmin(msg.sender), "sender is not an admin"); _; } /// @return the controller node registered in ENS. function controllerNode() external view returns (bytes32) { return _controllerNode; } /// @return true if the provided account is a controller. function _isController(address _account) internal view returns (bool) { return IController(_ensResolve(_controllerNode)).isController(_account); } /// @return true if the provided account is an admin. function _isAdmin(address _account) internal view returns (bool) { return IController(_ensResolve(_controllerNode)).isAdmin(_account); } }
/** * Controller - The Consumer Contract Wallet * Copyright (C) 2019 The Contract Wallet Company Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity ^0.5.10; import "./ownable.sol"; import "./transferrable.sol"; /// @title The IController interface provides access to the isController and isAdmin checks. interface IController { function isController(address) external view returns (bool); function isAdmin(address) external view returns (bool); } /// @title Controller stores a list of controller addresses that can be used for authentication in other contracts. /// @notice The Controller implements a hierarchy of concepts, Owner, Admin, and the Controllers. /// @dev Owner can change the Admins /// @dev Admins and can the Controllers /// @dev Controllers are used by the application. contract Controller is IController, Ownable, Transferrable { event AddedController(address _sender, address _controller); event RemovedController(address _sender, address _controller); event AddedAdmin(address _sender, address _admin); event RemovedAdmin(address _sender, address _admin); event Claimed(address _to, address _asset, uint _amount); event Stopped(address _sender); event Started(address _sender); mapping (address => bool) private _isAdmin; uint private _adminCount; mapping (address => bool) private _isController; uint private _controllerCount; bool private _stopped; /// @notice Constructor initializes the owner with the provided address. /// @param _ownerAddress_ address of the owner. constructor(address payable _ownerAddress_) Ownable(_ownerAddress_, false) public {} /// @notice Checks if message sender is an admin. modifier onlyAdmin() { require(isAdmin(msg.sender), "sender is not an admin"); _; } /// @notice Check if Owner or Admin modifier onlyAdminOrOwner() { require(_isOwner(msg.sender) || isAdmin(msg.sender), "sender is not an admin"); _; } /// @notice Check if controller is stopped modifier notStopped() { require(!isStopped(), "controller is stopped"); _; } /// @notice Add a new admin to the list of admins. /// @param _account address to add to the list of admins. function addAdmin(address _account) external onlyOwner notStopped { _addAdmin(_account); } /// @notice Remove a admin from the list of admins. /// @param _account address to remove from the list of admins. function removeAdmin(address _account) external onlyOwner { _removeAdmin(_account); } /// @return the current number of admins. function adminCount() external view returns (uint) { return _adminCount; } /// @notice Add a new controller to the list of controllers. /// @param _account address to add to the list of controllers. function addController(address _account) external onlyAdminOrOwner notStopped { _addController(_account); } /// @notice Remove a controller from the list of controllers. /// @param _account address to remove from the list of controllers. function removeController(address _account) external onlyAdminOrOwner { _removeController(_account); } /// @notice count the Controllers /// @return the current number of controllers. function controllerCount() external view returns (uint) { return _controllerCount; } /// @notice is an address an Admin? /// @return true if the provided account is an admin. function isAdmin(address _account) public view notStopped returns (bool) { return _isAdmin[_account]; } /// @notice is an address a Controller? /// @return true if the provided account is a controller. function isController(address _account) public view notStopped returns (bool) { return _isController[_account]; } /// @notice this function can be used to see if the controller has been stopped /// @return true is the Controller has been stopped function isStopped() public view returns (bool) { return _stopped; } /// @notice Internal-only function that adds a new admin. function _addAdmin(address _account) private { require(!_isAdmin[_account], "provided account is already an admin"); require(!_isController[_account], "provided account is already a controller"); require(!_isOwner(_account), "provided account is already the owner"); require(_account != address(0), "provided account is the zero address"); _isAdmin[_account] = true; _adminCount++; emit AddedAdmin(msg.sender, _account); } /// @notice Internal-only function that removes an existing admin. function _removeAdmin(address _account) private { require(_isAdmin[_account], "provided account is not an admin"); _isAdmin[_account] = false; _adminCount--; emit RemovedAdmin(msg.sender, _account); } /// @notice Internal-only function that adds a new controller. function _addController(address _account) private { require(!_isAdmin[_account], "provided account is already an admin"); require(!_isController[_account], "provided account is already a controller"); require(!_isOwner(_account), "provided account is already the owner"); require(_account != address(0), "provided account is the zero address"); _isController[_account] = true; _controllerCount++; emit AddedController(msg.sender, _account); } /// @notice Internal-only function that removes an existing controller. function _removeController(address _account) private { require(_isController[_account], "provided account is not a controller"); _isController[_account] = false; _controllerCount--; emit RemovedController(msg.sender, _account); } /// @notice stop our controllers and admins from being useable function stop() external onlyAdminOrOwner { _stopped = true; emit Stopped(msg.sender); } /// @notice start our controller again function start() external onlyOwner { _stopped = false; emit Started(msg.sender); } //// @notice Withdraw tokens from the smart contract to the specified account. function claim(address payable _to, address _asset, uint _amount) external onlyAdmin notStopped { _safeTransfer(_to, _asset, _amount); emit Claimed(_to, _asset, _amount); } }
/** * BSD 2-Clause License * * Copyright (c) 2018, True Names Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ pragma solidity ^0.5.0; interface ENS { // Logged when the owner of a node assigns a new owner to a subnode. event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); // Logged when the owner of a node transfers ownership to a new account. event Transfer(bytes32 indexed node, address owner); // Logged when the resolver for a node changes. event NewResolver(bytes32 indexed node, address resolver); // Logged when the TTL of a node changes event NewTTL(bytes32 indexed node, uint64 ttl); function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external; function setResolver(bytes32 node, address resolver) external; function setOwner(bytes32 node, address owner) external; function setTTL(bytes32 node, uint64 ttl) external; function owner(bytes32 node) external view returns (address); function resolver(bytes32 node) external view returns (address); function ttl(bytes32 node) external view returns (uint64); }
/** * ENSResolvable - The Consumer Contract Wallet * Copyright (C) 2019 The Contract Wallet Company Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity ^0.5.10; import "./ENS.sol"; import "./PublicResolver.sol"; ///@title ENSResolvable - Ethereum Name Service Resolver ///@notice contract should be used to get an address for an ENS node contract ENSResolvable { /// @notice _ens is an instance of ENS ENS private _ens; /// @notice _ensRegistry points to the ENS registry smart contract. address private _ensRegistry; /// @param _ensReg_ is the ENS registry used constructor(address _ensReg_) internal { _ensRegistry = _ensReg_; _ens = ENS(_ensRegistry); } /// @notice this is used to that one can observe which ENS registry is being used function ensRegistry() external view returns (address) { return _ensRegistry; } /// @notice helper function used to get the address of a node /// @param _node of the ENS entry that needs resolving /// @return the address of the said node function _ensResolve(bytes32 _node) internal view returns (address) { return PublicResolver(_ens.resolver(_node)).addr(_node); } }
pragma solidity ^0.5.10; /// @title ERC20 interface is a subset of the ERC20 specification. /// @notice see https://github.com/ethereum/EIPs/issues/20 interface ERC20 { function allowance(address _owner, address _spender) external view returns (uint256); function approve(address _spender, uint256 _value) external returns (bool); function balanceOf(address _who) external view returns (uint256); function totalSupply() external view returns (uint256); function transfer(address _to, uint256 _value) external returns (bool); function transferFrom(address _from, address _to, uint256 _value) external returns (bool); }
pragma solidity ^0.5.0; import "./ResolverBase.sol"; import "./AddrResolver.sol"; contract InterfaceResolver is ResolverBase, AddrResolver { bytes4 constant private INTERFACE_INTERFACE_ID = bytes4(keccak256("interfaceImplementer(bytes32,bytes4)")); bytes4 private constant INTERFACE_META_ID = 0x01ffc9a7; event InterfaceChanged(bytes32 indexed node, bytes4 indexed interfaceID, address implementer); mapping(bytes32=>mapping(bytes4=>address)) interfaces; /** * Sets an interface associated with a name. * Setting the address to 0 restores the default behaviour of querying the contract at `addr()` for interface support. * @param node The node to update. * @param interfaceID The EIP 168 interface ID. * @param implementer The address of a contract that implements this interface for this node. */ function setInterface(bytes32 node, bytes4 interfaceID, address implementer) external authorised(node) { interfaces[node][interfaceID] = implementer; emit InterfaceChanged(node, interfaceID, implementer); } /** * Returns the address of a contract that implements the specified interface for this name. * If an implementer has not been set for this interfaceID and name, the resolver will query * the contract at `addr()`. If `addr()` is set, a contract exists at that address, and that * contract implements EIP168 and returns `true` for the specified interfaceID, its address * will be returned. * @param node The ENS node to query. * @param interfaceID The EIP 168 interface ID to check for. * @return The address that implements this interface, or 0 if the interface is unsupported. */ function interfaceImplementer(bytes32 node, bytes4 interfaceID) external view returns (address) { address implementer = interfaces[node][interfaceID]; if(implementer != address(0)) { return implementer; } address a = addr(node); if(a == address(0)) { return address(0); } (bool success, bytes memory returnData) = a.staticcall(abi.encodeWithSignature("supportsInterface(bytes4)", INTERFACE_META_ID)); if(!success || returnData.length < 32 || returnData[31] == 0) { // EIP 168 not supported by target return address(0); } (success, returnData) = a.staticcall(abi.encodeWithSignature("supportsInterface(bytes4)", interfaceID)); if(!success || returnData.length < 32 || returnData[31] == 0) { // Specified interface not supported by target return address(0); } return a; } function supportsInterface(bytes4 interfaceID) public pure returns(bool) { return interfaceID == INTERFACE_INTERFACE_ID || super.supportsInterface(interfaceID); } }
pragma solidity ^0.5.0; import "./ResolverBase.sol"; contract NameResolver is ResolverBase { bytes4 constant private NAME_INTERFACE_ID = 0x691f3431; event NameChanged(bytes32 indexed node, string name); mapping(bytes32=>string) names; /** * Sets the name associated with an ENS node, for reverse records. * May only be called by the owner of that node in the ENS registry. * @param node The node to update. * @param name The name to set. */ function setName(bytes32 node, string calldata name) external authorised(node) { names[node] = name; emit NameChanged(node, name); } /** * Returns the name associated with an ENS node, for reverse records. * Defined in EIP181. * @param node The ENS node to query. * @return The associated name. */ function name(bytes32 node) external view returns (string memory) { return names[node]; } function supportsInterface(bytes4 interfaceID) public pure returns(bool) { return interfaceID == NAME_INTERFACE_ID || super.supportsInterface(interfaceID); } }
/** * Ownable - The Consumer Contract Wallet * Copyright (C) 2019 The Contract Wallet Company Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity ^0.5.10; /// @title Ownable has an owner address and provides basic authorization control functions. /// This contract is modified version of the MIT OpenZepplin Ownable contract /// This contract allows for the transferOwnership operation to be made impossible /// https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ownership/Ownable.sol contract Ownable { event TransferredOwnership(address _from, address _to); event LockedOwnership(address _locked); address payable private _owner; bool private _isTransferable; /// @notice Constructor sets the original owner of the contract and whether or not it is one time transferable. constructor(address payable _account_, bool _transferable_) internal { _owner = _account_; _isTransferable = _transferable_; // Emit the LockedOwnership event if no longer transferable. if (!_isTransferable) { emit LockedOwnership(_account_); } emit TransferredOwnership(address(0), _account_); } /// @notice Reverts if called by any account other than the owner. modifier onlyOwner() { require(_isOwner(msg.sender), "sender is not an owner"); _; } /// @notice Allows the current owner to transfer control of the contract to a new address. /// @param _account address to transfer ownership to. /// @param _transferable indicates whether to keep the ownership transferable. function transferOwnership(address payable _account, bool _transferable) external onlyOwner { // Require that the ownership is transferable. require(_isTransferable, "ownership is not transferable"); // Require that the new owner is not the zero address. require(_account != address(0), "owner cannot be set to zero address"); // Set the transferable flag to the value _transferable passed in. _isTransferable = _transferable; // Emit the LockedOwnership event if no longer transferable. if (!_transferable) { emit LockedOwnership(_account); } // Emit the ownership transfer event. emit TransferredOwnership(_owner, _account); // Set the owner to the provided address. _owner = _account; } /// @notice check if the ownership is transferable. /// @return true if the ownership is transferable. function isTransferable() external view returns (bool) { return _isTransferable; } /// @notice Allows the current owner to relinquish control of the contract. /// @dev Renouncing to ownership will leave the contract without an owner and unusable. /// @dev It will not be possible to call the functions with the `onlyOwner` modifier anymore. function renounceOwnership() external onlyOwner { // Require that the ownership is transferable. require(_isTransferable, "ownership is not transferable"); // note that this could be terminal _owner = address(0); emit TransferredOwnership(_owner, address(0)); } /// @notice Find out owner address /// @return address of the owner. function owner() public view returns (address payable) { return _owner; } /// @notice Check if owner address /// @return true if sender is the owner of the contract. function _isOwner(address _address) internal view returns (bool) { return _address == _owner; } }
pragma solidity ^0.5.0; import "./ResolverBase.sol"; contract PubkeyResolver is ResolverBase { bytes4 constant private PUBKEY_INTERFACE_ID = 0xc8690233; event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y); struct PublicKey { bytes32 x; bytes32 y; } mapping(bytes32=>PublicKey) pubkeys; /** * Sets the SECP256k1 public key associated with an ENS node. * @param node The ENS node to query * @param x the X coordinate of the curve point for the public key. * @param y the Y coordinate of the curve point for the public key. */ function setPubkey(bytes32 node, bytes32 x, bytes32 y) external authorised(node) { pubkeys[node] = PublicKey(x, y); emit PubkeyChanged(node, x, y); } /** * Returns the SECP256k1 public key associated with an ENS node. * Defined in EIP 619. * @param node The ENS node to query * @return x, y the X and Y coordinates of the curve point for the public key. */ function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y) { return (pubkeys[node].x, pubkeys[node].y); } function supportsInterface(bytes4 interfaceID) public pure returns(bool) { return interfaceID == PUBKEY_INTERFACE_ID || super.supportsInterface(interfaceID); } }
/** * BSD 2-Clause License * * Copyright (c) 2018, True Names Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ pragma solidity ^0.5.0; import "./ENS.sol"; import "./ABIResolver.sol"; import "./AddrResolver.sol"; import "./ContentHashResolver.sol"; import "./InterfaceResolver.sol"; import "./NameResolver.sol"; import "./PubkeyResolver.sol"; import "./TextResolver.sol"; /** * A simple resolver anyone can use; only allows the owner of a node to set its * address. */ contract PublicResolver is ABIResolver, AddrResolver, ContentHashResolver, InterfaceResolver, NameResolver, PubkeyResolver, TextResolver { ENS ens; /** * A mapping of authorisations. An address that is authorised for a name * may make any changes to the name that the owner could, but may not update * the set of authorisations. * (node, owner, caller) => isAuthorised */ mapping(bytes32=>mapping(address=>mapping(address=>bool))) public authorisations; event AuthorisationChanged(bytes32 indexed node, address indexed owner, address indexed target, bool isAuthorised); constructor(ENS _ens) public { ens = _ens; } /** * @dev Sets or clears an authorisation. * Authorisations are specific to the caller. Any account can set an authorisation * for any name, but the authorisation that is checked will be that of the * current owner of a name. Thus, transferring a name effectively clears any * existing authorisations, and new authorisations can be set in advance of * an ownership transfer if desired. * * @param node The name to change the authorisation on. * @param target The address that is to be authorised or deauthorised. * @param isAuthorised True if the address should be authorised, or false if it should be deauthorised. */ function setAuthorisation(bytes32 node, address target, bool isAuthorised) external { authorisations[node][msg.sender][target] = isAuthorised; emit AuthorisationChanged(node, msg.sender, target, isAuthorised); } function isAuthorised(bytes32 node) internal view returns(bool) { address owner = ens.owner(node); return owner == msg.sender || authorisations[node][owner][msg.sender]; } }
pragma solidity ^0.5.0; contract ResolverBase { bytes4 private constant INTERFACE_META_ID = 0x01ffc9a7; function supportsInterface(bytes4 interfaceID) public pure returns(bool) { return interfaceID == INTERFACE_META_ID; } function isAuthorised(bytes32 node) internal view returns(bool); modifier authorised(bytes32 node) { require(isAuthorised(node)); _; } }
/** * The MIT License (MIT) * * Copyright (c) 2016-2019 zOS Global Limited * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ pragma solidity ^0.5.0; import "./ERC20.sol"; import "./SafeMath.sol"; import "./Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(ERC20 token, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(ERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(ERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(ERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function callOptionalReturn(ERC20 token, bytes memory data) internal { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot 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, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, "SafeMath: division by zero"); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, "SafeMath: modulo by zero"); return a % b; } }
/* * Copyright 2016 Nick Johnson * * 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 String & slice utility library for Solidity contracts. * @author Nick Johnson <[email protected]> * * @dev Functionality in this library is largely implemented using an * abstraction called a 'slice'. A slice represents a part of a string - * anything from the entire string to a single character, or even no * characters at all (a 0-length slice). Since a slice only has to specify * an offset and a length, copying and manipulating slices is a lot less * expensive than copying and manipulating the strings they reference. * * To further reduce gas costs, most functions on slice that need to return * a slice modify the original one instead of allocating a new one; for * instance, `s.split(".")` will return the text up to the first '.', * modifying s to only contain the remainder of the string after the '.'. * In situations where you do not want to modify the original slice, you * can make a copy first with `.copy()`, for example: * `s.copy().split(".")`. Try and avoid using this idiom in loops; since * Solidity has no memory management, it will result in allocating many * short-lived slices that are later discarded. * * Functions that return two slices come in two versions: a non-allocating * version that takes the second slice as an argument, modifying it in * place, and an allocating version that allocates and returns the second * slice; see `nextRune` for example. * * Functions that have to copy string data will return strings rather than * slices; these can be cast back to slices for further processing if * required. * * For convenience, some functions are provided with non-modifying * variants that create a new slice and return both; for instance, * `s.splitNew('.')` leaves s unmodified, and returns two values * corresponding to the left and right parts of the string. */ pragma solidity ^0.5.0; library strings { struct slice { uint _len; uint _ptr; } function memcpy(uint dest, uint src, uint len) private pure { // Copy word-length chunks while possible for(; len >= 32; len -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } // Copy remaining bytes uint mask = 256 ** (32 - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } /* * @dev Returns a slice containing the entire string. * @param self The string to make a slice from. * @return A newly allocated slice containing the entire string. */ function toSlice(string memory self) internal pure returns (slice memory) { uint ptr; assembly { ptr := add(self, 0x20) } return slice(bytes(self).length, ptr); } /* * @dev Returns the length of a null-terminated bytes32 string. * @param self The value to find the length of. * @return The length of the string, from 0 to 32. */ function len(bytes32 self) internal pure returns (uint) { uint ret; if (self == 0) return 0; if (uint(self) & 0xffffffffffffffffffffffffffffffff == 0) { ret += 16; self = bytes32(uint(self) / 0x100000000000000000000000000000000); } if (uint(self) & 0xffffffffffffffff == 0) { ret += 8; self = bytes32(uint(self) / 0x10000000000000000); } if (uint(self) & 0xffffffff == 0) { ret += 4; self = bytes32(uint(self) / 0x100000000); } if (uint(self) & 0xffff == 0) { ret += 2; self = bytes32(uint(self) / 0x10000); } if (uint(self) & 0xff == 0) { ret += 1; } return 32 - ret; } /* * @dev Returns a slice containing the entire bytes32, interpreted as a * null-terminated utf-8 string. * @param self The bytes32 value to convert to a slice. * @return A new slice containing the value of the input argument up to the * first null. */ function toSliceB32(bytes32 self) internal pure returns (slice memory ret) { // Allocate space for `self` in memory, copy it there, and point ret at it assembly { let ptr := mload(0x40) mstore(0x40, add(ptr, 0x20)) mstore(ptr, self) mstore(add(ret, 0x20), ptr) } ret._len = len(self); } /* * @dev Returns a new slice containing the same data as the current slice. * @param self The slice to copy. * @return A new slice containing the same data as `self`. */ function copy(slice memory self) internal pure returns (slice memory) { return slice(self._len, self._ptr); } /* * @dev Copies a slice to a new string. * @param self The slice to copy. * @return A newly allocated string containing the slice's text. */ function toString(slice memory self) internal pure returns (string memory) { string memory ret = new string(self._len); uint retptr; assembly { retptr := add(ret, 32) } memcpy(retptr, self._ptr, self._len); return ret; } /* * @dev Returns the length in runes of the slice. Note that this operation * takes time proportional to the length of the slice; avoid using it * in loops, and call `slice.empty()` if you only need to know whether * the slice is empty or not. * @param self The slice to operate on. * @return The length of the slice in runes. */ function len(slice memory self) internal pure returns (uint l) { // Starting at ptr-31 means the LSB will be the byte we care about uint ptr = self._ptr - 31; uint end = ptr + self._len; for (l = 0; ptr < end; l++) { uint8 b; assembly { b := and(mload(ptr), 0xFF) } if (b < 0x80) { ptr += 1; } else if (b < 0xE0) { ptr += 2; } else if (b < 0xF0) { ptr += 3; } else if (b < 0xF8) { ptr += 4; } else if (b < 0xFC) { ptr += 5; } else { ptr += 6; } } } /* * @dev Returns true if the slice is empty (has a length of 0). * @param self The slice to operate on. * @return True if the slice is empty, False otherwise. */ function empty(slice memory self) internal pure returns (bool) { return self._len == 0; } /* * @dev Returns a positive number if `other` comes lexicographically after * `self`, a negative number if it comes before, or zero if the * contents of the two slices are equal. Comparison is done per-rune, * on unicode codepoints. * @param self The first slice to compare. * @param other The second slice to compare. * @return The result of the comparison. */ function compare(slice memory self, slice memory other) internal pure returns (int) { uint shortest = self._len; if (other._len < self._len) shortest = other._len; uint selfptr = self._ptr; uint otherptr = other._ptr; for (uint idx = 0; idx < shortest; idx += 32) { uint a; uint b; assembly { a := mload(selfptr) b := mload(otherptr) } if (a != b) { // Mask out irrelevant bytes and check again uint256 mask = uint256(-1); // 0xffff... if (shortest < 32) { mask = ~(2 ** (8 * (32 - shortest + idx)) - 1); } uint256 diff = (a & mask) - (b & mask); if (diff != 0) return int(diff); } selfptr += 32; otherptr += 32; } return int(self._len) - int(other._len); } /* * @dev Returns true if the two slices contain the same text. * @param self The first slice to compare. * @param self The second slice to compare. * @return True if the slices are equal, false otherwise. */ function equals(slice memory self, slice memory other) internal pure returns (bool) { return compare(self, other) == 0; } /* * @dev Extracts the first rune in the slice into `rune`, advancing the * slice to point to the next rune and returning `self`. * @param self The slice to operate on. * @param rune The slice that will contain the first rune. * @return `rune`. */ function nextRune(slice memory self, slice memory rune) internal pure returns (slice memory) { rune._ptr = self._ptr; if (self._len == 0) { rune._len = 0; return rune; } uint l; uint b; // Load the first byte of the rune into the LSBs of b assembly { b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) } if (b < 0x80) { l = 1; } else if (b < 0xE0) { l = 2; } else if (b < 0xF0) { l = 3; } else { l = 4; } // Check for truncated codepoints if (l > self._len) { rune._len = self._len; self._ptr += self._len; self._len = 0; return rune; } self._ptr += l; self._len -= l; rune._len = l; return rune; } /* * @dev Returns the first rune in the slice, advancing the slice to point * to the next rune. * @param self The slice to operate on. * @return A slice containing only the first rune from `self`. */ function nextRune(slice memory self) internal pure returns (slice memory ret) { nextRune(self, ret); } /* * @dev Returns the number of the first codepoint in the slice. * @param self The slice to operate on. * @return The number of the first codepoint in the slice. */ function ord(slice memory self) internal pure returns (uint ret) { if (self._len == 0) { return 0; } uint word; uint length; uint divisor = 2 ** 248; // Load the rune into the MSBs of b assembly { word:= mload(mload(add(self, 32))) } uint b = word / divisor; if (b < 0x80) { ret = b; length = 1; } else if (b < 0xE0) { ret = b & 0x1F; length = 2; } else if (b < 0xF0) { ret = b & 0x0F; length = 3; } else { ret = b & 0x07; length = 4; } // Check for truncated codepoints if (length > self._len) { return 0; } for (uint i = 1; i < length; i++) { divisor = divisor / 256; b = (word / divisor) & 0xFF; if (b & 0xC0 != 0x80) { // Invalid UTF-8 sequence return 0; } ret = (ret * 64) | (b & 0x3F); } return ret; } /* * @dev Returns the keccak-256 hash of the slice. * @param self The slice to hash. * @return The hash of the slice. */ function keccak(slice memory self) internal pure returns (bytes32 ret) { assembly { ret := keccak256(mload(add(self, 32)), mload(self)) } } /* * @dev Returns true if `self` starts with `needle`. * @param self The slice to operate on. * @param needle The slice to search for. * @return True if the slice starts with the provided text, false otherwise. */ function startsWith(slice memory self, slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } if (self._ptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` starts with `needle`, `needle` is removed from the * beginning of `self`. Otherwise, `self` is unmodified. * @param self The slice to operate on. * @param needle The slice to search for. * @return `self` */ function beyond(slice memory self, slice memory needle) internal pure returns (slice memory) { if (self._len < needle._len) { return self; } bool equal = true; if (self._ptr != needle._ptr) { assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; self._ptr += needle._len; } return self; } /* * @dev Returns true if the slice ends with `needle`. * @param self The slice to operate on. * @param needle The slice to search for. * @return True if the slice starts with the provided text, false otherwise. */ function endsWith(slice memory self, slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } uint selfptr = self._ptr + self._len - needle._len; if (selfptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` ends with `needle`, `needle` is removed from the * end of `self`. Otherwise, `self` is unmodified. * @param self The slice to operate on. * @param needle The slice to search for. * @return `self` */ function until(slice memory self, slice memory needle) internal pure returns (slice memory) { if (self._len < needle._len) { return self; } uint selfptr = self._ptr + self._len - needle._len; bool equal = true; if (selfptr != needle._ptr) { assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; } return self; } // Returns the memory address of the first byte of the first occurrence of // `needle` in `self`, or the first byte after `self` if not found. function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr = selfptr; uint idx; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } uint end = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr >= end) return selfptr + selflen; ptr++; assembly { ptrdata := and(mload(ptr), mask) } } return ptr; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } for (idx = 0; idx <= selflen - needlelen; idx++) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr; ptr += 1; } } } return selfptr + selflen; } // Returns the memory address of the first byte after the last occurrence of // `needle` in `self`, or the address of `self` if not found. function rfindPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } ptr = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr <= selfptr) return selfptr; ptr--; assembly { ptrdata := and(mload(ptr), mask) } } return ptr + needlelen; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } ptr = selfptr + (selflen - needlelen); while (ptr >= selfptr) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr + needlelen; ptr -= 1; } } } return selfptr; } /* * @dev Modifies `self` to contain everything from the first occurrence of * `needle` to the end of the slice. `self` is set to the empty slice * if `needle` is not found. * @param self The slice to search and modify. * @param needle The text to search for. * @return `self`. */ function find(slice memory self, slice memory needle) internal pure returns (slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); self._len -= ptr - self._ptr; self._ptr = ptr; return self; } /* * @dev Modifies `self` to contain the part of the string from the start of * `self` to the end of the first occurrence of `needle`. If `needle` * is not found, `self` is set to the empty slice. * @param self The slice to search and modify. * @param needle The text to search for. * @return `self`. */ function rfind(slice memory self, slice memory needle) internal pure returns (slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); self._len = ptr - self._ptr; return self; } /* * @dev Splits the slice, setting `self` to everything after the first * occurrence of `needle`, and `token` to everything before it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and `token` is set to the entirety of `self`. * @param self The slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function split(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = self._ptr; token._len = ptr - self._ptr; if (ptr == self._ptr + self._len) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; self._ptr = ptr + needle._len; } return token; } /* * @dev Splits the slice, setting `self` to everything after the first * occurrence of `needle`, and returning everything before it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and the entirety of `self` is returned. * @param self The slice to split. * @param needle The text to search for in `self`. * @return The part of `self` up to the first occurrence of `delim`. */ function split(slice memory self, slice memory needle) internal pure returns (slice memory token) { split(self, needle, token); } /* * @dev Splits the slice, setting `self` to everything before the last * occurrence of `needle`, and `token` to everything after it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and `token` is set to the entirety of `self`. * @param self The slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function rsplit(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = ptr; token._len = self._len - (ptr - self._ptr); if (ptr == self._ptr) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; } return token; } /* * @dev Splits the slice, setting `self` to everything before the last * occurrence of `needle`, and returning everything after it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and the entirety of `self` is returned. * @param self The slice to split. * @param needle The text to search for in `self`. * @return The part of `self` after the last occurrence of `delim`. */ function rsplit(slice memory self, slice memory needle) internal pure returns (slice memory token) { rsplit(self, needle, token); } /* * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`. * @param self The slice to search. * @param needle The text to search for in `self`. * @return The number of occurrences of `needle` found in `self`. */ function count(slice memory self, slice memory needle) internal pure returns (uint cnt) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len; while (ptr <= self._ptr + self._len) { cnt++; ptr = findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + needle._len; } } /* * @dev Returns True if `self` contains `needle`. * @param self The slice to search. * @param needle The text to search for in `self`. * @return True if `needle` is found in `self`, false otherwise. */ function contains(slice memory self, slice memory needle) internal pure returns (bool) { return rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr; } /* * @dev Returns a newly allocated string containing the concatenation of * `self` and `other`. * @param self The first slice to concatenate. * @param other The second slice to concatenate. * @return The concatenation of the two strings. */ function concat(slice memory self, slice memory other) internal pure returns (string memory) { string memory ret = new string(self._len + other._len); uint retptr; assembly { retptr := add(ret, 32) } memcpy(retptr, self._ptr, self._len); memcpy(retptr + self._len, other._ptr, other._len); return ret; } /* * @dev Joins an array of slices, using `self` as a delimiter, returning a * newly allocated string. * @param self The delimiter to use. * @param parts A list of slices to join. * @return A newly allocated string containing all the slices in `parts`, * joined with `self`. */ function join(slice memory self, slice[] memory parts) internal pure returns (string memory) { if (parts.length == 0) return ""; uint length = self._len * (parts.length - 1); for (uint i = 0; i < parts.length; i++) { length += parts[i]._len; } string memory ret = new string(length); uint retptr; assembly { retptr := add(ret, 32) } for (uint i = 0; i < parts.length; i++) { memcpy(retptr, parts[i]._ptr, parts[i]._len); retptr += parts[i]._len; if (i < parts.length - 1) { memcpy(retptr, self._ptr, self._len); retptr += self._len; } } return ret; } }
pragma solidity ^0.5.0; import "./ResolverBase.sol"; contract TextResolver is ResolverBase { bytes4 constant private TEXT_INTERFACE_ID = 0x59d1d43c; event TextChanged(bytes32 indexed node, string indexedKey, string key); mapping(bytes32=>mapping(string=>string)) texts; /** * Sets the text data associated with an ENS node and key. * May only be called by the owner of that node in the ENS registry. * @param node The node to update. * @param key The key to set. * @param value The text data value to set. */ function setText(bytes32 node, string calldata key, string calldata value) external authorised(node) { texts[node][key] = value; emit TextChanged(node, key, key); } /** * Returns the text data associated with an ENS node and key. * @param node The ENS node to query. * @param key The text data key to query. * @return The associated text data. */ function text(bytes32 node, string calldata key) external view returns (string memory) { return texts[node][key]; } function supportsInterface(bytes4 interfaceID) public pure returns(bool) { return interfaceID == TEXT_INTERFACE_ID || super.supportsInterface(interfaceID); } }
/** * Transferrable - The Consumer Contract Wallet * Copyright (C) 2019 The Contract Wallet Company Limited * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ pragma solidity ^0.5.10; import "./ERC20.sol"; import "./SafeERC20.sol"; /// @title SafeTransfer, allowing contract to withdraw tokens accidentally sent to itself contract Transferrable { using SafeERC20 for ERC20; /// @dev This function is used to move tokens sent accidentally to this contract method. /// @dev The owner can chose the new destination address /// @param _to is the recipient's address. /// @param _asset is the address of an ERC20 token or 0x0 for ether. /// @param _amount is the amount to be transferred in base units. function _safeTransfer(address payable _to, address _asset, uint _amount) internal { // address(0) is used to denote ETH if (_asset == address(0)) { _to.transfer(_amount); } else { ERC20(_asset).safeTransfer(_to, _amount); } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"constant":true,"inputs":[],"name":"redeemableCounter","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_methodId","type":"bytes4"}],"name":"isERC20MethodWhitelisted","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_a","type":"address"}],"name":"getTokenInfo","outputs":[{"name":"","type":"string"},{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"bool"},{"name":"","type":"bool"},{"name":"","type":"bool"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokens","type":"address[]"},{"name":"_symbols","type":"bytes32[]"},{"name":"_magnitude","type":"uint256[]"},{"name":"_loadable","type":"bool[]"},{"name":"_redeemable","type":"bool[]"},{"name":"_lastUpdate","type":"uint256"}],"name":"addTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getStablecoinInfo","outputs":[{"name":"","type":"string"},{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"bool"},{"name":"","type":"bool"},{"name":"","type":"bool"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tokenAddressArray","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"redeemableTokens","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_redeemable","type":"bool"}],"name":"setTokenRedeemable","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"},{"name":"_methodId","type":"bytes4"}],"name":"isERC20MethodSupported","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_tokens","type":"address[]"}],"name":"removeTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ensRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oracleNode","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_loadable","type":"bool"}],"name":"setTokenLoadable","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_asset","type":"address"},{"name":"_amount","type":"uint256"}],"name":"claim","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_token","type":"address"},{"name":"_data","type":"bytes"}],"name":"getERC20RecipientAndAmount","outputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_rate","type":"uint256"},{"name":"_updateDate","type":"uint256"}],"name":"updateTokenRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"controllerNode","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stablecoin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_ens_","type":"address"},{"name":"_oracleNode_","type":"bytes32"},{"name":"_controllerNode_","type":"bytes32"},{"name":"_stablecoinAddress_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_sender","type":"address"},{"indexed":false,"name":"_token","type":"address"},{"indexed":false,"name":"_rate","type":"uint256"}],"name":"UpdatedTokenRate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_sender","type":"address"},{"indexed":false,"name":"_token","type":"address"},{"indexed":false,"name":"_loadable","type":"bool"}],"name":"UpdatedTokenLoadable","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_sender","type":"address"},{"indexed":false,"name":"_token","type":"address"},{"indexed":false,"name":"_redeemable","type":"bool"}],"name":"UpdatedTokenRedeemable","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_sender","type":"address"},{"indexed":false,"name":"_token","type":"address"},{"indexed":false,"name":"_symbol","type":"string"},{"indexed":false,"name":"_magnitude","type":"uint256"},{"indexed":false,"name":"_loadable","type":"bool"},{"indexed":false,"name":"_redeemable","type":"bool"}],"name":"AddedToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_sender","type":"address"},{"indexed":false,"name":"_token","type":"address"}],"name":"RemovedToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_methodId","type":"bytes4"}],"name":"AddedMethodId","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_methodId","type":"bytes4"}],"name":"RemovedMethodId","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_token","type":"address"},{"indexed":false,"name":"_methodId","type":"bytes4"}],"name":"AddedExclusiveMethod","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_token","type":"address"},{"indexed":false,"name":"_methodId","type":"bytes4"}],"name":"RemovedExclusiveMethod","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_to","type":"address"},{"indexed":false,"name":"_asset","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"Claimed","type":"event"}]
Contract Creation Code
608060405234801561001057600080fd5b506040516123893803806123898339818101604052608081101561003357600080fd5b5080516020808301516040840151606090940151600180546001600160a01b039586166001600160a01b03199182161780835560008054831691881691909117815560029790975560089390935560078054959092169490921693909317909255600490527fa329885c08741397fd3c8a6391655875994b8b3f4267d51f002324c79dfda7c7805460ff1990811683179091557f272caa52cdef72c610b5313d50ca07262761e093a56fa2fa7114c2b7a13aca6180548216831790557ffe246a62db334be0c21bf6bcd2dda5f5c4dd84ad286b6c507001745ea44cfc4c80548216831790557f23b872dd000000000000000000000000000000000000000000000000000000009092527f64f10a4788acb6e7f7bb8cb159bb306107fb979e4655d590b30c3f1bbc4b1a5e8054909216179055612215806101746000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c80636c3824ef116100a2578063996cba6811610071578063996cba6814610584578063afc72e93146105ba578063d545782e1461065b578063e2b4ce971461068d578063e9cbd8221461069557610116565b80636c3824ef146104bc5780637d73b2311461052a57806380cc0dda1461054e578063872773061461055657610116565b80633efec5e9116100e95780633efec5e9146103f0578063443dd2a4146103f857806344b049bc146104505780635d793a7d146104585780636a1744dc1461048657610116565b806313d5e8461461011b5780631d3a069f146101355780631f69565f1461017057806334c73edc14610240575b600080fd5b61012361069d565b60408051918252519081900360200190f35b61015c6004803603602081101561014b57600080fd5b50356001600160e01b0319166106a4565b604080519115158252519081900360200190f35b6101966004803603602081101561018657600080fd5b50356001600160a01b03166106c7565b6040805160208082018990529181018790528515156060820152841515608082015283151560a082015260c0810183905260e08082528951908201528851909182916101008301918b019080838360005b838110156101ff5781810151838201526020016101e7565b50505050905090810190601f16801561022c5780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390f35b6103ee600480360360c081101561025657600080fd5b810190602081018135600160201b81111561027057600080fd5b82018360208201111561028257600080fd5b803590602001918460208302840111600160201b831117156102a357600080fd5b919390929091602081019035600160201b8111156102c057600080fd5b8201836020820111156102d257600080fd5b803590602001918460208302840111600160201b831117156102f357600080fd5b919390929091602081019035600160201b81111561031057600080fd5b82018360208201111561032257600080fd5b803590602001918460208302840111600160201b8311171561034357600080fd5b919390929091602081019035600160201b81111561036057600080fd5b82018360208201111561037257600080fd5b803590602001918460208302840111600160201b8311171561039357600080fd5b919390929091602081019035600160201b8111156103b057600080fd5b8201836020820111156103c257600080fd5b803590602001918460208302840111600160201b831117156103e357600080fd5b9193509150356107c2565b005b610196610c54565b610400610d4f565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561043c578181015183820152602001610424565b505050509050019250505060405180910390f35b610400610db1565b6103ee6004803603604081101561046e57600080fd5b506001600160a01b0381351690602001351515610e7e565b61015c6004803603604081101561049c57600080fd5b5080356001600160a01b031690602001356001600160e01b031916610fb6565b6103ee600480360360208110156104d257600080fd5b810190602081018135600160201b8111156104ec57600080fd5b8201836020820111156104fe57600080fd5b803590602001918460208302840111600160201b8311171561051f57600080fd5b50909250905061103d565b6105326112e1565b604080516001600160a01b039092168252519081900360200190f35b6101236112f0565b6103ee6004803603604081101561056c57600080fd5b506001600160a01b03813516906020013515156112f6565b6103ee6004803603606081101561059a57600080fd5b506001600160a01b0381358116916020810135909116906040013561142c565b610638600480360360408110156105d057600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156105fa57600080fd5b82018360208201111561060c57600080fd5b803590602001918460018302840111600160201b8311171561062d57600080fd5b5090925090506114d9565b604080516001600160a01b03909316835260208301919091528051918290030190f35b6103ee6004803603606081101561067157600080fd5b506001600160a01b03813516906020810135906040013561181d565b610123611968565b61053261196e565b6006545b90565b6001600160e01b0319811660009081526004602052604090205460ff165b919050565b6001600160a01b0381166000908152600360208181526040808420600180820154600280840154968401546004850154855487516101009682161587026000190190911693909304601f8101899004890284018901909752868352606099988998899889988998899891978897929660ff8085169693850481169562010000909504169390928991908301828280156107a15780601f10610776576101008083540402835291602001916107a1565b820191906000526020600020905b81548152906001019060200180831161078457829003601f168201915b50505050509650975097509750975097509750975050919395979092949650565b6107cb3361197d565b610815576040805162461bcd60e51b815260206004820152601660248201527539b2b73232b91034b9903737ba1030b71030b236b4b760511b604482015290519081900360640190fd5b898814801561082357508986145b801561082e57508984145b801561083957508984145b61088a576040805162461bcd60e51b815260206004820152601e60248201527f706172616d65746572206c656e6774687320646f206e6f74206d617463680000604482015290519081900360640190fd5b60005b8a811015610c4657600360008d8d848181106108a557fe5b602090810292909201356001600160a01b03168352508101919091526040016000206003015460ff1615610920576040805162461bcd60e51b815260206004820152601760248201527f746f6b656e20616c726561647920617661696c61626c65000000000000000000604482015290519081900360640190fd5b60606109456109408c8c8581811061093457fe5b90506020020135611a11565b611a3d565b90506040518060e001604052808281526020018a8a8581811061096457fe5b9050602002013581526020016000815260200160011515815260200188888581811061098c57fe5b905060200201351515151581526020018686858181106109a857fe5b9050602002013515151515815260200184815250600360008f8f868181106109cc57fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b031681526020019081526020016000206000820151816000019080519060200190610a18929190612074565b5060208201516001820155604082015160028201556060820151600382018054608085015160a08601511515620100000262ff0000199115156101000261ff001995151560ff199094169390931794909416919091171691909117905560c09091015160049091015560058d8d84818110610a8f57fe5b835460018101855560009485526020948590200180546001600160a01b0319166001600160a01b039590920293909301359390931692909217905550848483818110610ad757fe5b9050602002013515610afb57600654610af790600163ffffffff611a9416565b6006555b7f1802e89da3f6ef84e024e37454c226b1e13bf846ce71cd2a1d24faef9cbf779b338e8e85818110610b2957fe5b905060200201356001600160a01b0316838c8c87818110610b4657fe5b905060200201358b8b88818110610b5957fe5b9050602002013515158a8a89818110610b6e57fe5b90506020020135151560405180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001806020018581526020018415151515815260200183151515158152602001828103825286818151815260200191508051906020019080838360005b83811015610bfe578181015183820152602001610be6565b50505050905090810190601f168015610c2b5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390a15060010161088d565b505050505050505050505050565b6007546001600160a01b03166000908152600360208181526040808420600180820154600280840154968401546004850154855487516101009682161587026000190190911693909304601f8101899004890284018901909752868352606099988998899889988998899891978897929660ff808516969385048116956201000090950416939092899190830182828015610d305780601f10610d0557610100808354040283529160200191610d30565b820191906000526020600020905b815481529060010190602001808311610d1357829003601f168201915b5050505050965097509750975097509750975097505090919293949596565b60606005805480602002602001604051908101604052809291908181526020018280548015610da757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610d89575b5050505050905090565b606080600654604051908082528060200260200182016040528015610de0578160200160208202803883390190505b5090506000805b600554811015610e7657600060058281548110610e0057fe5b60009182526020808320909101546001600160a01b03168083526003918290526040909220015490915060ff620100009091041615610e6d5780848481518110610e4657fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506001830192505b50600101610de7565b509091505090565b610e873361197d565b610ed1576040805162461bcd60e51b815260206004820152601660248201527539b2b73232b91034b9903737ba1030b71030b236b4b760511b604482015290519081900360640190fd5b6001600160a01b0382166000908152600360208190526040909120015460ff16610f3b576040805162461bcd60e51b8152602060048201526016602482015275746f6b656e206973206e6f7420617661696c61626c6560501b604482015290519081900360640190fd5b6001600160a01b038216600081815260036020818152604092839020909101805485151562010000810262ff0000199092169190911790915582513381529182019390935280820192909252517fcaa111d70d53608b9c8e3278c634595491de54f572a17a297dedad20f517039d9181900360600190a15050565b6001600160a01b03821660009081526003602081905260408220015460ff1661101b576040805162461bcd60e51b81526020600482015260126024820152713737b716b2bc34b9ba34b733903a37b5b2b760711b604482015290519081900360640190fd5b506001600160e01b03191660009081526004602052604090205460ff16919050565b6110463361197d565b611090576040805162461bcd60e51b815260206004820152601660248201527539b2b73232b91034b9903737ba1030b71030b236b4b760511b604482015290519081900360640190fd5b60005b818110156112dc5760008383838181106110a957fe5b602090810292909201356001600160a01b0316600081815260039384905260409020909201549192505060ff16611120576040805162461bcd60e51b8152602060048201526016602482015275746f6b656e206973206e6f7420617661696c61626c6560501b604482015290519081900360640190fd5b6001600160a01b0381166000908152600360208190526040909120015462010000900460ff16156111635760065461115f90600163ffffffff611af516565b6006555b6001600160a01b03811660009081526003602052604081209061118682826120f2565b506000600182018190556002820181905560038201805462ffffff1916905560049091018190555b6005546111c290600163ffffffff611af516565b81101561127b57816001600160a01b0316600582815481106111e057fe5b6000918252602090912001546001600160a01b03161415611273576005805461121090600163ffffffff611af516565b8154811061121a57fe5b600091825260209091200154600580546001600160a01b03909216918390811061124057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555061127b565b6001016111ae565b50600580549061128f906000198301612139565b50604080513381526001600160a01b038316602082015281517f703f7e3f084d5b8dcc12fddcfd9a70d65b6b21ec7659e4608dbaf4419ede3ad0929181900390910190a150600101611093565b505050565b6001546001600160a01b031690565b60085490565b6112ff3361197d565b611349576040805162461bcd60e51b815260206004820152601660248201527539b2b73232b91034b9903737ba1030b71030b236b4b760511b604482015290519081900360640190fd5b6001600160a01b0382166000908152600360208190526040909120015460ff166113b3576040805162461bcd60e51b8152602060048201526016602482015275746f6b656e206973206e6f7420617661696c61626c6560501b604482015290519081900360640190fd5b6001600160a01b0382166000818152600360208181526040928390209091018054851515610100810261ff00199092169190911790915582513381529182019390935280820192909252517f0e086282e8e406857ef1dce65e04a192ad8405e48484524cb2ddbf28e5d84eec9181900360600190a15050565b6114353361197d565b61147f576040805162461bcd60e51b815260206004820152601660248201527539b2b73232b91034b9903737ba1030b71030b236b4b760511b604482015290519081900360640190fd5b61148a838383611b52565b604080516001600160a01b0380861682528416602082015280820183905290517ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd39926839181900360600190a1505050565b6000806024831015611532576040805162461bcd60e51b815260206004820181905260248201527f6e6f7420656e6f756768206d6574686f642d656e636f64696e67206279746573604482015290519081900360640190fd5b600061157e600086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff611bb6169050565b905061158a8682610fb6565b6115d0576040805162461bcd60e51b81526020600482015260126024820152711d5b9cdd5c1c1bdc9d1959081b595d1a1bd960721b604482015290519081900360640190fd5b6001600160e01b03198116630852cd8d60e31b141561163e5785611634600487878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff611c35169050565b9250925050611815565b6001600160e01b031981166323b872dd60e01b14156117415760648410156116ad576040805162461bcd60e51b815260206004820181905260248201527f6e6f7420656e6f756768206461746120666f72207472616e7366657246726f6d604482015290519081900360640190fd5b6116f7603086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff611c48169050565b611634604487878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff611c35169050565b60448410156117815760405162461bcd60e51b81526004018080602001828103825260258152602001806121926025913960400191505060405180910390fd5b6117cb601086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff611c48169050565b611634602487878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff611c35169050565b935093915050565b600061182a600854611cca565b90506118353361197d565b806118485750336001600160a01b038216145b611892576040805162461bcd60e51b815260206004820152601660248201527532b4ba3432b91037b930b1b6329037b91030b236b4b760511b604482015290519081900360640190fd5b6001600160a01b0384166000908152600360208190526040909120015460ff166118fc576040805162461bcd60e51b8152602060048201526016602482015275746f6b656e206973206e6f7420617661696c61626c6560501b604482015290519081900360640190fd5b6001600160a01b03841660008181526003602090815260409182902060028101879055600401859055815133815290810192909252818101859052517fdb3a4cfb4cd8ac94343ff7440cee8d05ade309056203f0e53ca49b6db8197c7d9181900360600190a150505050565b60025490565b6007546001600160a01b031690565b600061198a600254611cca565b6001600160a01b03166324d7806c836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156119df57600080fd5b505afa1580156119f3573d6000803e3d6000fd5b505050506040513d6020811015611a0957600080fd5b505192915050565b611a1961215d565b6040516020810160405282815280602083015250611a3682611d8c565b8152919050565b60608082600001516040519080825280601f01601f191660200182016040528015611a6f576020820181803883390190505b5090506000602082019050611a8d8185602001518660000151611e25565b5092915050565b600082820183811015611aee576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b600082821115611b4c576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b038216611b9c576040516001600160a01b0384169082156108fc029083906000818181858888f19350505050158015611b96573d6000803e3d6000fd5b506112dc565b6112dc6001600160a01b038316848363ffffffff611e6316565b6000611bc982600463ffffffff611a9416565b83511015611c15576040805162461bcd60e51b8152602060048201526014602482015273736c6963696e67206f7574206f662072616e676560601b604482015290519081900360640190fd5b600080611c2984602063ffffffff611a9416565b90940151949350505050565b6000611bc982602063ffffffff611a9416565b6000611c5b82601463ffffffff611a9416565b83511015611ca7576040805162461bcd60e51b8152602060048201526014602482015273736c6963696e67206f7574206f662072616e676560601b604482015290519081900360640190fd5b600080611cbb84602063ffffffff611a9416565b9094015160601c949350505050565b6000805460408051630178b8bf60e01b81526004810185905290516001600160a01b0390921691630178b8bf91602480820192602092909190829003018186803b158015611d1757600080fd5b505afa158015611d2b573d6000803e3d6000fd5b505050506040513d6020811015611d4157600080fd5b505160408051631d9dabef60e11b81526004810185905290516001600160a01b0390921691633b3b57de91602480820192602092909190829003018186803b1580156119df57600080fd5b60008082611d9e5760009150506106c2565b6fffffffffffffffffffffffffffffffff8316611dc257601001600160801b830492505b67ffffffffffffffff8316611de35760080168010000000000000000830492505b63ffffffff8316611dfb57600401600160201b830492505b61ffff8316611e105760020162010000830492505b60ff8316611e1c576001015b60200392915050565b5b60208110611e45578151835260209283019290910190601f1901611e26565b905182516020929092036101000a6000190180199091169116179052565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526112dc908490611ec2826001600160a01b031661206e565b611f13576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310611f515780518252601f199092019160209182019101611f32565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611fb3576040519150601f19603f3d011682016040523d82523d6000602084013e611fb8565b606091505b50915091508161200f576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156120685780806020019051602081101561202b57600080fd5b50516120685760405162461bcd60e51b815260040180806020018281038252602a8152602001806121b7602a913960400191505060405180910390fd5b50505050565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106120b557805160ff19168380011785556120e2565b828001600101855582156120e2579182015b828111156120e25782518255916020019190600101906120c7565b506120ee929150612177565b5090565b50805460018160011615610100020316600290046000825580601f106121185750612136565b601f0160209004906000526020600020908101906121369190612177565b50565b8154818355818111156112dc576000838152602090206112dc918101908301612177565b604051806040016040528060008152602001600081525090565b6106a191905b808211156120ee576000815560010161217d56fe6e6f7420656e6f756768206461746120666f72207472616e736665722f61707070726f76655361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a72305820b9d0cff30fd06ec46b310e69c7459f33f14b7e95655e2e7621c17dae70fc575464736f6c634300050a0032000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b3e6619339eb0a070dc69fcbd6cad36c338032c0c9750e26b8b76ab1ec06aa3d87f2ce995617d2816b426c5c8698c5ec2952f7a34bb10f38326f74933d5893697000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101165760003560e01c80636c3824ef116100a2578063996cba6811610071578063996cba6814610584578063afc72e93146105ba578063d545782e1461065b578063e2b4ce971461068d578063e9cbd8221461069557610116565b80636c3824ef146104bc5780637d73b2311461052a57806380cc0dda1461054e578063872773061461055657610116565b80633efec5e9116100e95780633efec5e9146103f0578063443dd2a4146103f857806344b049bc146104505780635d793a7d146104585780636a1744dc1461048657610116565b806313d5e8461461011b5780631d3a069f146101355780631f69565f1461017057806334c73edc14610240575b600080fd5b61012361069d565b60408051918252519081900360200190f35b61015c6004803603602081101561014b57600080fd5b50356001600160e01b0319166106a4565b604080519115158252519081900360200190f35b6101966004803603602081101561018657600080fd5b50356001600160a01b03166106c7565b6040805160208082018990529181018790528515156060820152841515608082015283151560a082015260c0810183905260e08082528951908201528851909182916101008301918b019080838360005b838110156101ff5781810151838201526020016101e7565b50505050905090810190601f16801561022c5780820380516001836020036101000a031916815260200191505b509850505050505050505060405180910390f35b6103ee600480360360c081101561025657600080fd5b810190602081018135600160201b81111561027057600080fd5b82018360208201111561028257600080fd5b803590602001918460208302840111600160201b831117156102a357600080fd5b919390929091602081019035600160201b8111156102c057600080fd5b8201836020820111156102d257600080fd5b803590602001918460208302840111600160201b831117156102f357600080fd5b919390929091602081019035600160201b81111561031057600080fd5b82018360208201111561032257600080fd5b803590602001918460208302840111600160201b8311171561034357600080fd5b919390929091602081019035600160201b81111561036057600080fd5b82018360208201111561037257600080fd5b803590602001918460208302840111600160201b8311171561039357600080fd5b919390929091602081019035600160201b8111156103b057600080fd5b8201836020820111156103c257600080fd5b803590602001918460208302840111600160201b831117156103e357600080fd5b9193509150356107c2565b005b610196610c54565b610400610d4f565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561043c578181015183820152602001610424565b505050509050019250505060405180910390f35b610400610db1565b6103ee6004803603604081101561046e57600080fd5b506001600160a01b0381351690602001351515610e7e565b61015c6004803603604081101561049c57600080fd5b5080356001600160a01b031690602001356001600160e01b031916610fb6565b6103ee600480360360208110156104d257600080fd5b810190602081018135600160201b8111156104ec57600080fd5b8201836020820111156104fe57600080fd5b803590602001918460208302840111600160201b8311171561051f57600080fd5b50909250905061103d565b6105326112e1565b604080516001600160a01b039092168252519081900360200190f35b6101236112f0565b6103ee6004803603604081101561056c57600080fd5b506001600160a01b03813516906020013515156112f6565b6103ee6004803603606081101561059a57600080fd5b506001600160a01b0381358116916020810135909116906040013561142c565b610638600480360360408110156105d057600080fd5b6001600160a01b038235169190810190604081016020820135600160201b8111156105fa57600080fd5b82018360208201111561060c57600080fd5b803590602001918460018302840111600160201b8311171561062d57600080fd5b5090925090506114d9565b604080516001600160a01b03909316835260208301919091528051918290030190f35b6103ee6004803603606081101561067157600080fd5b506001600160a01b03813516906020810135906040013561181d565b610123611968565b61053261196e565b6006545b90565b6001600160e01b0319811660009081526004602052604090205460ff165b919050565b6001600160a01b0381166000908152600360208181526040808420600180820154600280840154968401546004850154855487516101009682161587026000190190911693909304601f8101899004890284018901909752868352606099988998899889988998899891978897929660ff8085169693850481169562010000909504169390928991908301828280156107a15780601f10610776576101008083540402835291602001916107a1565b820191906000526020600020905b81548152906001019060200180831161078457829003601f168201915b50505050509650975097509750975097509750975050919395979092949650565b6107cb3361197d565b610815576040805162461bcd60e51b815260206004820152601660248201527539b2b73232b91034b9903737ba1030b71030b236b4b760511b604482015290519081900360640190fd5b898814801561082357508986145b801561082e57508984145b801561083957508984145b61088a576040805162461bcd60e51b815260206004820152601e60248201527f706172616d65746572206c656e6774687320646f206e6f74206d617463680000604482015290519081900360640190fd5b60005b8a811015610c4657600360008d8d848181106108a557fe5b602090810292909201356001600160a01b03168352508101919091526040016000206003015460ff1615610920576040805162461bcd60e51b815260206004820152601760248201527f746f6b656e20616c726561647920617661696c61626c65000000000000000000604482015290519081900360640190fd5b60606109456109408c8c8581811061093457fe5b90506020020135611a11565b611a3d565b90506040518060e001604052808281526020018a8a8581811061096457fe5b9050602002013581526020016000815260200160011515815260200188888581811061098c57fe5b905060200201351515151581526020018686858181106109a857fe5b9050602002013515151515815260200184815250600360008f8f868181106109cc57fe5b905060200201356001600160a01b03166001600160a01b03166001600160a01b031681526020019081526020016000206000820151816000019080519060200190610a18929190612074565b5060208201516001820155604082015160028201556060820151600382018054608085015160a08601511515620100000262ff0000199115156101000261ff001995151560ff199094169390931794909416919091171691909117905560c09091015160049091015560058d8d84818110610a8f57fe5b835460018101855560009485526020948590200180546001600160a01b0319166001600160a01b039590920293909301359390931692909217905550848483818110610ad757fe5b9050602002013515610afb57600654610af790600163ffffffff611a9416565b6006555b7f1802e89da3f6ef84e024e37454c226b1e13bf846ce71cd2a1d24faef9cbf779b338e8e85818110610b2957fe5b905060200201356001600160a01b0316838c8c87818110610b4657fe5b905060200201358b8b88818110610b5957fe5b9050602002013515158a8a89818110610b6e57fe5b90506020020135151560405180876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001806020018581526020018415151515815260200183151515158152602001828103825286818151815260200191508051906020019080838360005b83811015610bfe578181015183820152602001610be6565b50505050905090810190601f168015610c2b5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390a15060010161088d565b505050505050505050505050565b6007546001600160a01b03166000908152600360208181526040808420600180820154600280840154968401546004850154855487516101009682161587026000190190911693909304601f8101899004890284018901909752868352606099988998899889988998899891978897929660ff808516969385048116956201000090950416939092899190830182828015610d305780601f10610d0557610100808354040283529160200191610d30565b820191906000526020600020905b815481529060010190602001808311610d1357829003601f168201915b5050505050965097509750975097509750975097505090919293949596565b60606005805480602002602001604051908101604052809291908181526020018280548015610da757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610d89575b5050505050905090565b606080600654604051908082528060200260200182016040528015610de0578160200160208202803883390190505b5090506000805b600554811015610e7657600060058281548110610e0057fe5b60009182526020808320909101546001600160a01b03168083526003918290526040909220015490915060ff620100009091041615610e6d5780848481518110610e4657fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506001830192505b50600101610de7565b509091505090565b610e873361197d565b610ed1576040805162461bcd60e51b815260206004820152601660248201527539b2b73232b91034b9903737ba1030b71030b236b4b760511b604482015290519081900360640190fd5b6001600160a01b0382166000908152600360208190526040909120015460ff16610f3b576040805162461bcd60e51b8152602060048201526016602482015275746f6b656e206973206e6f7420617661696c61626c6560501b604482015290519081900360640190fd5b6001600160a01b038216600081815260036020818152604092839020909101805485151562010000810262ff0000199092169190911790915582513381529182019390935280820192909252517fcaa111d70d53608b9c8e3278c634595491de54f572a17a297dedad20f517039d9181900360600190a15050565b6001600160a01b03821660009081526003602081905260408220015460ff1661101b576040805162461bcd60e51b81526020600482015260126024820152713737b716b2bc34b9ba34b733903a37b5b2b760711b604482015290519081900360640190fd5b506001600160e01b03191660009081526004602052604090205460ff16919050565b6110463361197d565b611090576040805162461bcd60e51b815260206004820152601660248201527539b2b73232b91034b9903737ba1030b71030b236b4b760511b604482015290519081900360640190fd5b60005b818110156112dc5760008383838181106110a957fe5b602090810292909201356001600160a01b0316600081815260039384905260409020909201549192505060ff16611120576040805162461bcd60e51b8152602060048201526016602482015275746f6b656e206973206e6f7420617661696c61626c6560501b604482015290519081900360640190fd5b6001600160a01b0381166000908152600360208190526040909120015462010000900460ff16156111635760065461115f90600163ffffffff611af516565b6006555b6001600160a01b03811660009081526003602052604081209061118682826120f2565b506000600182018190556002820181905560038201805462ffffff1916905560049091018190555b6005546111c290600163ffffffff611af516565b81101561127b57816001600160a01b0316600582815481106111e057fe5b6000918252602090912001546001600160a01b03161415611273576005805461121090600163ffffffff611af516565b8154811061121a57fe5b600091825260209091200154600580546001600160a01b03909216918390811061124057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555061127b565b6001016111ae565b50600580549061128f906000198301612139565b50604080513381526001600160a01b038316602082015281517f703f7e3f084d5b8dcc12fddcfd9a70d65b6b21ec7659e4608dbaf4419ede3ad0929181900390910190a150600101611093565b505050565b6001546001600160a01b031690565b60085490565b6112ff3361197d565b611349576040805162461bcd60e51b815260206004820152601660248201527539b2b73232b91034b9903737ba1030b71030b236b4b760511b604482015290519081900360640190fd5b6001600160a01b0382166000908152600360208190526040909120015460ff166113b3576040805162461bcd60e51b8152602060048201526016602482015275746f6b656e206973206e6f7420617661696c61626c6560501b604482015290519081900360640190fd5b6001600160a01b0382166000818152600360208181526040928390209091018054851515610100810261ff00199092169190911790915582513381529182019390935280820192909252517f0e086282e8e406857ef1dce65e04a192ad8405e48484524cb2ddbf28e5d84eec9181900360600190a15050565b6114353361197d565b61147f576040805162461bcd60e51b815260206004820152601660248201527539b2b73232b91034b9903737ba1030b71030b236b4b760511b604482015290519081900360640190fd5b61148a838383611b52565b604080516001600160a01b0380861682528416602082015280820183905290517ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd39926839181900360600190a1505050565b6000806024831015611532576040805162461bcd60e51b815260206004820181905260248201527f6e6f7420656e6f756768206d6574686f642d656e636f64696e67206279746573604482015290519081900360640190fd5b600061157e600086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff611bb6169050565b905061158a8682610fb6565b6115d0576040805162461bcd60e51b81526020600482015260126024820152711d5b9cdd5c1c1bdc9d1959081b595d1a1bd960721b604482015290519081900360640190fd5b6001600160e01b03198116630852cd8d60e31b141561163e5785611634600487878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff611c35169050565b9250925050611815565b6001600160e01b031981166323b872dd60e01b14156117415760648410156116ad576040805162461bcd60e51b815260206004820181905260248201527f6e6f7420656e6f756768206461746120666f72207472616e7366657246726f6d604482015290519081900360640190fd5b6116f7603086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff611c48169050565b611634604487878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff611c35169050565b60448410156117815760405162461bcd60e51b81526004018080602001828103825260258152602001806121926025913960400191505060405180910390fd5b6117cb601086868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff611c48169050565b611634602487878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929392505063ffffffff611c35169050565b935093915050565b600061182a600854611cca565b90506118353361197d565b806118485750336001600160a01b038216145b611892576040805162461bcd60e51b815260206004820152601660248201527532b4ba3432b91037b930b1b6329037b91030b236b4b760511b604482015290519081900360640190fd5b6001600160a01b0384166000908152600360208190526040909120015460ff166118fc576040805162461bcd60e51b8152602060048201526016602482015275746f6b656e206973206e6f7420617661696c61626c6560501b604482015290519081900360640190fd5b6001600160a01b03841660008181526003602090815260409182902060028101879055600401859055815133815290810192909252818101859052517fdb3a4cfb4cd8ac94343ff7440cee8d05ade309056203f0e53ca49b6db8197c7d9181900360600190a150505050565b60025490565b6007546001600160a01b031690565b600061198a600254611cca565b6001600160a01b03166324d7806c836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156119df57600080fd5b505afa1580156119f3573d6000803e3d6000fd5b505050506040513d6020811015611a0957600080fd5b505192915050565b611a1961215d565b6040516020810160405282815280602083015250611a3682611d8c565b8152919050565b60608082600001516040519080825280601f01601f191660200182016040528015611a6f576020820181803883390190505b5090506000602082019050611a8d8185602001518660000151611e25565b5092915050565b600082820183811015611aee576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b600082821115611b4c576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6001600160a01b038216611b9c576040516001600160a01b0384169082156108fc029083906000818181858888f19350505050158015611b96573d6000803e3d6000fd5b506112dc565b6112dc6001600160a01b038316848363ffffffff611e6316565b6000611bc982600463ffffffff611a9416565b83511015611c15576040805162461bcd60e51b8152602060048201526014602482015273736c6963696e67206f7574206f662072616e676560601b604482015290519081900360640190fd5b600080611c2984602063ffffffff611a9416565b90940151949350505050565b6000611bc982602063ffffffff611a9416565b6000611c5b82601463ffffffff611a9416565b83511015611ca7576040805162461bcd60e51b8152602060048201526014602482015273736c6963696e67206f7574206f662072616e676560601b604482015290519081900360640190fd5b600080611cbb84602063ffffffff611a9416565b9094015160601c949350505050565b6000805460408051630178b8bf60e01b81526004810185905290516001600160a01b0390921691630178b8bf91602480820192602092909190829003018186803b158015611d1757600080fd5b505afa158015611d2b573d6000803e3d6000fd5b505050506040513d6020811015611d4157600080fd5b505160408051631d9dabef60e11b81526004810185905290516001600160a01b0390921691633b3b57de91602480820192602092909190829003018186803b1580156119df57600080fd5b60008082611d9e5760009150506106c2565b6fffffffffffffffffffffffffffffffff8316611dc257601001600160801b830492505b67ffffffffffffffff8316611de35760080168010000000000000000830492505b63ffffffff8316611dfb57600401600160201b830492505b61ffff8316611e105760020162010000830492505b60ff8316611e1c576001015b60200392915050565b5b60208110611e45578151835260209283019290910190601f1901611e26565b905182516020929092036101000a6000190180199091169116179052565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526112dc908490611ec2826001600160a01b031661206e565b611f13576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310611f515780518252601f199092019160209182019101611f32565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114611fb3576040519150601f19603f3d011682016040523d82523d6000602084013e611fb8565b606091505b50915091508161200f576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156120685780806020019051602081101561202b57600080fd5b50516120685760405162461bcd60e51b815260040180806020018281038252602a8152602001806121b7602a913960400191505060405180910390fd5b50505050565b3b151590565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106120b557805160ff19168380011785556120e2565b828001600101855582156120e2579182015b828111156120e25782518255916020019190600101906120c7565b506120ee929150612177565b5090565b50805460018160011615610100020316600290046000825580601f106121185750612136565b601f0160209004906000526020600020908101906121369190612177565b50565b8154818355818111156112dc576000838152602090206112dc918101908301612177565b604051806040016040528060008152602001600081525090565b6106a191905b808211156120ee576000815560010161217d56fe6e6f7420656e6f756768206461746120666f72207472616e736665722f61707070726f76655361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a72305820b9d0cff30fd06ec46b310e69c7459f33f14b7e95655e2e7621c17dae70fc575464736f6c634300050a0032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b3e6619339eb0a070dc69fcbd6cad36c338032c0c9750e26b8b76ab1ec06aa3d87f2ce995617d2816b426c5c8698c5ec2952f7a34bb10f38326f74933d5893697000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
-----Decoded View---------------
Arg [0] : _ens_ (address): 0x314159265dD8dbb310642f98f50C066173C1259b
Arg [1] : _oracleNode_ (bytes32): 0x3e6619339eb0a070dc69fcbd6cad36c338032c0c9750e26b8b76ab1ec06aa3d8
Arg [2] : _controllerNode_ (bytes32): 0x7f2ce995617d2816b426c5c8698c5ec2952f7a34bb10f38326f74933d5893697
Arg [3] : _stablecoinAddress_ (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b
Arg [1] : 3e6619339eb0a070dc69fcbd6cad36c338032c0c9750e26b8b76ab1ec06aa3d8
Arg [2] : 7f2ce995617d2816b426c5c8698c5ec2952f7a34bb10f38326f74933d5893697
Arg [3] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Deployed Bytecode Sourcemap
1872:14610:20:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1872:14610:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15955:100;;;:::i;:::-;;;;;;;;;;;;;;;;15709:136;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15709:136:20;-1:-1:-1;;;;;;15709:136:20;;:::i;:::-;;;;;;;;;;;;;;;;;;13053:334;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;13053:334:20;-1:-1:-1;;;;;13053:334:20;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;13053:334:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5945:1670;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;5945:1670:20;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;5945:1670:20;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;5945:1670:20;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;5945:1670:20;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;5945:1670:20;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;5945:1670:20;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;5945:1670:20;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;5945:1670:20;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;5945:1670:20;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;5945:1670:20;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;5945:1670:20;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;5945:1670:20;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;5945:1670:20;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;5945:1670:20;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;5945:1670:20;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;5945:1670:20;;-1:-1:-1;5945:1670:20;-1:-1:-1;5945:1670:20;;:::i;:::-;;13889:378;;;:::i;14396:112::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;14396:112:20;;;;;;;;;;;;;;;;;14635:516;;;:::i;11047:398::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;11047:398:20;;;;;;;;;;:::i;15334:220::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15334:220:20;;-1:-1:-1;;;;;15334:220:20;;;;;-1:-1:-1;;;;;;15334:220:20;;:::i;7742:1230::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;7742:1230:20;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;7742:1230:20;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;7742:1230:20;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;7742:1230:20;;-1:-1:-1;7742:1230:20;-1:-1:-1;7742:1230:20;:::i;1434:91:17:-;;;:::i;:::-;;;;-1:-1:-1;;;;;1434:91:17;;;;;;;;;;;;;;16391:89:20;;;:::i;10588:384::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;10588:384:20;;;;;;;;;;:::i;12320:181::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;12320:181:20;;;;;;;;;;;;;;;;;:::i;9130:1385::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;9130:1385:20;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;9130:1385:20;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;9130:1385:20;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;-1:-1;9130:1385:20;;-1:-1:-1;9130:1385:20;-1:-1:-1;9130:1385:20;:::i;:::-;;;;-1:-1:-1;;;;;9130:1385:20;;;;;;;;;;;;;;;;;;;;;11722:509;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;11722:509:20;;;;;;;;;;;;;:::i;1758:97:15:-;;;:::i;16187:89:20:-;;;:::i;15955:100::-;16030:18;;15955:100;;:::o;15709:136::-;-1:-1:-1;;;;;;15808:29:20;;15784:4;15808:29;;;:18;:29;;;;;;;;15709:136;;;;:::o;13053:334::-;-1:-1:-1;;;;;13206:17:20;;13125:7;13206:17;;;:13;:17;;;;;;;;13259:19;;;;;13280:14;;;;;13296:19;;;;13359:20;;;;13233:147;;;;13296:19;13233:147;;;;;;-1:-1:-1;;13233:147:20;;;;;;;;;;;;;;;;;;;;;;;;;;13110:13;;13125:7;;;;;;;;;;;13206:17;;;;13259:19;;13296;;;;;13317:18;;;;;;13337:20;;;;;;13359;;13206:17;;13233:147;;;13206:17;13233:147;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13053:334;;;;;;;;;:::o;5945:1670::-;1632:20:15;1641:10;1632:8;:20::i;:::-;1624:55;;;;;-1:-1:-1;;;1624:55:15;;;;;;;;;;;;-1:-1:-1;;;1624:55:15;;;;;;;;;;;;;;;6221:33:20;;;:72;;;;-1:-1:-1;6258:35:20;;;6221:72;:110;;;;-1:-1:-1;6297:34:20;;;6221:110;:148;;;;-1:-1:-1;6335:34:20;;;6221:148;6213:191;;;;;-1:-1:-1;;;6213:191:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;6478:6;6473:1136;6490:18;;;6473:1136;;;6601:13;:25;6615:7;;6623:1;6615:10;;;;;;;;;;;;;;;;-1:-1:-1;;;;;6615:10:20;6601:25;;-1:-1:-1;6601:25:20;;;;;;;;-1:-1:-1;6601:25:20;:35;;;;;6600:36;6592:72;;;;;-1:-1:-1;;;6592:72:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;6724:20;6747:35;:24;:8;;6756:1;6747:11;;;;;;;;;;;;;:22;:24::i;:::-;:33;:35::i;:::-;6724:58;;6872:288;;;;;;;;6905:6;6872:288;;;;6941:10;;6952:1;6941:13;;;;;;;;;;;;;6872:288;;;;6979:1;6872:288;;;;7010:4;6872:288;;;;;;7043:9;;7053:1;7043:12;;;;;;;;;;;;;;;6872:288;;;;;;7085:11;;7097:1;7085:14;;;;;;;;;;;;;;;6872:288;;;;;;7130:11;6872:288;;;6844:13;:25;6858:7;;6866:1;6858:10;;;;;;;;;;;;;-1:-1:-1;;;;;6858:10:20;-1:-1:-1;;;;;6844:25:20;-1:-1:-1;;;;;6844:25:20;;;;;;;;;;;;:316;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;6844:316:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6844:316:20;;;;;-1:-1:-1;;6844:316:20;;;-1:-1:-1;;6844:316:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7232:18;7256:7;;7264:1;7256:10;;;;;;;27::-1;;39:1;23:18;;45:23;;-1:-1;7232:35:20;;;7256:10;7232:35;;;;;;;-1:-1:-1;;;;;;7232:35:20;-1:-1:-1;;;;;7256:10:20;;;;;;;;;;;;;7232:35;;;;;;-1:-1:-1;7357:11:20;;7369:1;7357:14;;;;;;;;;;;;;;7353:98;;7411:18;;:25;;7434:1;7411:25;:22;:25;:::i;:::-;7390:18;:46;7353:98;7511:87;7522:10;7534:7;;7542:1;7534:10;;;;;;;;;;;;;-1:-1:-1;;;;;7534:10:20;7546:6;7554:10;;7565:1;7554:13;;;;;;;;;;;;;7569:9;;7579:1;7569:12;;;;;;;;;;;;;;;7583:11;;7595:1;7583:14;;;;;;;;;;;;;;;7511:87;;;;-1:-1:-1;;;;;7511:87:20;-1:-1:-1;;;;;7511:87:20;;;;;;-1:-1:-1;;;;;7511:87:20;-1:-1:-1;;;;;7511:87:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;7511:87:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6510:3:20;;6473:1136;;;;5945:1670;;;;;;;;;;;:::o;13889:378::-;14056:11;;-1:-1:-1;;;;;14056:11:20;13956:7;14042:26;;;:13;:26;;;;;;;;14056:11;14109:24;;;;14135:19;;;;;14156:24;;;;14234:25;;;;14078:182;;;;14056:11;14078:182;;;;;;-1:-1:-1;;14078:182:20;;;;;;;;;;;;;;;;;;;;;;;;;;13941:13;;13956:7;;;;;;;;;;;14042:26;;;;14109:24;;14156;;;;;14182:23;;;;;;14207:25;;;;;;14234;;14042:26;;14078:182;;;14042:26;14078:182;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13889:378;;;;;;;:::o;14396:112::-;14448:16;14483:18;14476:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;14476:25:20;;;;;;;;;;;;;;;;;;;;;;;14396:112;:::o;14635:516::-;14686:16;14714:36;14767:18;;14753:33;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;14753:33:20;-1:-1:-1;14714:72:20;-1:-1:-1;14796:20:20;;14830:279;14851:18;:25;14847:29;;14830:279;;;14897:13;14913:18;14932:1;14913:21;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;14913:21:20;14952:20;;;:13;:20;;;;;;;;:31;;14913:21;;-1:-1:-1;14952:31:20;;;;;;14948:151;;;15041:5;15002:19;15022:15;15002:36;;;;;;;;;;;;;:44;-1:-1:-1;;;;;15002:44:20;;;-1:-1:-1;;;;;15002:44:20;;;;;15083:1;15064:20;;;;14948:151;-1:-1:-1;14878:3:20;;14830:279;;;-1:-1:-1;15125:19:20;;-1:-1:-1;;14635:516:20;:::o;11047:398::-;1632:20:15;1641:10;1632:8;:20::i;:::-;1624:55;;;;;-1:-1:-1;;;1624:55:15;;;;;;;;;;;;-1:-1:-1;;;1624:55:15;;;;;;;;;;;;;;;-1:-1:-1;;;;;11188:21:20;;;;;;:13;:21;;;;;;;;:31;;;;11180:66;;;;;-1:-1:-1;;;11180:66:20;;;;;;;;;;;;-1:-1:-1;;;11180:66:20;;;;;;;;;;;;;;;-1:-1:-1;;;;;11321:21:20;;;;;;:13;:21;;;;;;;;;:32;;;:46;;;;;;;;-1:-1:-1;;11321:46:20;;;;;;;;;;11383:55;;11406:10;11383:55;;;;;;;;;;;;;;;;;;;;;;;;;;11047:398;;:::o;15334:220::-;-1:-1:-1;;;;;15445:21:20;;15421:4;15445:21;;;:13;:21;;;;;;;:31;;;;15437:62;;;;;-1:-1:-1;;;15437:62:20;;;;;;;;;;;;-1:-1:-1;;;15437:62:20;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;15517:29:20;;;;;:18;:29;;;;;;;;;15334:220;-1:-1:-1;15334:220:20:o;7742:1230::-;1632:20:15;1641:10;1632:8;:20::i;:::-;1624:55;;;;;-1:-1:-1;;;1624:55:15;;;;;;;;;;;;-1:-1:-1;;;1624:55:15;;;;;;;;;;;;;;;7929:6:20;7924:1042;7941:18;;;7924:1042;;;8020:13;8036:7;;8044:1;8036:10;;;;;;;;;;;;;;;;-1:-1:-1;;;;;8036:10:20;8137:20;;;;:13;:20;;;;;;;:30;;;;8036:10;;-1:-1:-1;;8137:30:20;;8129:65;;;;;-1:-1:-1;;;8129:65:20;;;;;;;;;;;;-1:-1:-1;;;8129:65:20;;;;;;;;;;;;;;;-1:-1:-1;;;;;8284:20:20;;;;;;:13;:20;;;;;;;;:31;;;;;;;8280:115;;;8355:18;;:25;;8378:1;8355:25;:22;:25;:::i;:::-;8334:18;:46;8280:115;-1:-1:-1;;;;;8455:20:20;;;;;;:13;:20;;;;;;8448:27;8455:20;;8448:27;:::i;:::-;-1:-1:-1;8448:27:20;;;;;;;;;;;;;;;;;;-1:-1:-1;;8448:27:20;;;;;;;;;;8552:272;8573:18;:25;:32;;8603:1;8573:32;:29;:32;:::i;:::-;8569:1;:36;8552:272;;;8659:5;-1:-1:-1;;;;;8634:30:20;:18;8653:1;8634:21;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;8634:21:20;:30;8630:180;;;8712:18;8731:25;;:32;;8761:1;8731:32;:29;:32;:::i;:::-;8712:52;;;;;;;;;;;;;;;;;;8688:18;:21;;-1:-1:-1;;;;;8712:52:20;;;;8707:1;;8688:21;;;;;;;;;;;;;;:76;;;;;-1:-1:-1;;;;;8688:76:20;;;;;-1:-1:-1;;;;;8688:76:20;;;;;;8786:5;;8630:180;8607:3;;8552:272;;;-1:-1:-1;8837:18:20;:27;;;;;-1:-1:-1;;8837:27:20;;;:::i;:::-;-1:-1:-1;8924:31:20;;;8937:10;8924:31;;-1:-1:-1;;;;;8924:31:20;;;;;;;;;;;;;;;;;;;-1:-1:-1;7961:3:20;;7924:1042;;;;7742:1230;;:::o;1434:91:17:-;1506:12;;-1:-1:-1;;;;;1506:12:17;1434:91;:::o;16391:89:20:-;16462:11;;16391:89;:::o;10588:384::-;1632:20:15;1641:10;1632:8;:20::i;:::-;1624:55;;;;;-1:-1:-1;;;1624:55:15;;;;;;;;;;;;-1:-1:-1;;;1624:55:15;;;;;;;;;;;;;;;-1:-1:-1;;;;;10725:21:20;;;;;;:13;:21;;;;;;;;:31;;;;10717:66;;;;;-1:-1:-1;;;10717:66:20;;;;;;;;;;;;-1:-1:-1;;;10717:66:20;;;;;;;;;;;;;;;-1:-1:-1;;;;;10856:21:20;;;;;;:13;:21;;;;;;;;;:30;;;:42;;;;;;;;-1:-1:-1;;10856:42:20;;;;;;;;;;10914:51;;10935:10;10914:51;;;;;;;;;;;;;;;;;;;;;;;;;;10588:384;;:::o;12320:181::-;1632:20:15;1641:10;1632:8;:20::i;:::-;1624:55;;;;;-1:-1:-1;;;1624:55:15;;;;;;;;;;;;-1:-1:-1;;;1624:55:15;;;;;;;;;;;;;;;12415:35:20;12429:3;12434:6;12442:7;12415:13;:35::i;:::-;12465:29;;;-1:-1:-1;;;;;12465:29:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;12320:181;;;:::o;9130:1385::-;9227:7;;9452:6;9436:22;;;9428:67;;;;;-1:-1:-1;;;9428:67:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9541:16;9560:23;9581:1;9560:5;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;9560:20:20;;:23;-1:-1:-1;;9560:23:20;:20;:23;;-1:-1:-1;9560:23:20:i;:::-;9541:42;;9644:41;9667:6;9675:9;9644:22;:41::i;:::-;9636:72;;;;;-1:-1:-1;;;9636:72:20;;;;;;;;;;;;-1:-1:-1;;;9636:72:20;;;;;;;;;;;;;;;-1:-1:-1;;;;;;9807:18:20;;-1:-1:-1;;;9807:18:20;9803:706;;;9892:6;9900:24;9922:1;9900:5;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;9900:21:20;;:24;-1:-1:-1;;9900:24:20;:21;:24;;-1:-1:-1;9900:24:20:i;:::-;9884:41;;;;;;;9803:706;-1:-1:-1;;;;;;9946:27:20;;-1:-1:-1;;;9946:27:20;9942:567;;;10084:16;10068:32;;;10060:77;;;;;-1:-1:-1;;;10060:77:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10160:34;10182:11;10160:5;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;10160:21:20;;:34;-1:-1:-1;;10160:34:20;:21;:34;;-1:-1:-1;10160:34:20:i;:::-;10196;10218:11;10196:5;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;10196:21:20;;:34;-1:-1:-1;;10196:34:20;:21;:34;;-1:-1:-1;10196:34:20:i;9942:567::-;10362:11;10346:27;;;10338:77;;;;-1:-1:-1;;;10338:77:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10437:29;10459:6;10437:5;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;10437:21:20;;:29;-1:-1:-1;;10437:29:20;:21;:29;;-1:-1:-1;10437:29:20:i;:::-;10468;10490:6;10468:5;;:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;10468:21:20;;:29;-1:-1:-1;;10468:29:20;:21;:29;;-1:-1:-1;10468:29:20:i;9130:1385::-;;;;;;;:::o;11722:509::-;5213:21;5237:24;5249:11;;5237;:24::i;:::-;5213:48;;5280:20;5289:10;5280:8;:20::i;:::-;:51;;;-1:-1:-1;5304:10:20;-1:-1:-1;;;;;5304:27:20;;;5280:51;5271:87;;;;;-1:-1:-1;;;5271:87:20;;;;;;;;;;;;-1:-1:-1;;;5271:87:20;;;;;;;;;;;;;;;-1:-1:-1;;;;;11880:21:20;;;;;;:13;:21;;;;;;;;:31;;;;11872:66;;;;;-1:-1:-1;;;11872:66:20;;;;;;;;;;;;-1:-1:-1;;;11872:66:20;;;;;;;;;;;;;;;-1:-1:-1;;;;;11984:21:20;;;;;;:13;:21;;;;;;;;;:26;;;:34;;;12081:32;;:46;;;12181:43;;12198:10;12181:43;;;;;;;;;;;;;;;;;;;;;;;;;11722:509;;;;:::o;1758:97:15:-;1833:15;;1758:97;:::o;16187:89:20:-;16258:11;;-1:-1:-1;;;;;16258:11:20;16187:89;:::o;2145:148:15:-;2204:4;2239:28;2251:15;;2239:11;:28::i;:::-;-1:-1:-1;;;;;2227:49:15;;2277:8;2227:59;;;;;;;;;;;;;-1:-1:-1;;;;;2227:59:15;-1:-1:-1;;;;;2227:59:15;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2227:59:15;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;2227:59:15;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;2227:59:15;;2145:148;-1:-1:-1;;2145:148:15:o;4943:370:19:-;5000:16;;:::i;:::-;5151:4;5145:11;5191:4;5186:3;5182:14;5176:4;5169:28;5222:4;5217:3;5210:17;5263:3;5256:4;5251:3;5247:14;5240:27;5120:157;5297:9;5301:4;5297:3;:9::i;:::-;5286:20;;:3;4943:370;-1:-1:-1;4943:370:19:o;5807:265::-;5867:13;5892:17;5923:4;:9;;;5912:21;;;;;;;;;;;;;;;;;;;;;;;;;21:6:-1;;104:10;5912:21:19;87:34:-1;135:17;;-1:-1;5912:21:19;;5892:41;;5943:11;5994:2;5989:3;5985:12;5975:22;;6009:36;6016:6;6024:4;:9;;;6035:4;:9;;;6009:6;:36::i;:::-;-1:-1:-1;6062:3:19;5807:265;-1:-1:-1;;5807:265:19:o;834:176:12:-;892:7;923:5;;;946:6;;;;938:46;;;;;-1:-1:-1;;;938:46:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;1002:1;834:176;-1:-1:-1;;;834:176:12:o;1274:179::-;1332:7;1364:1;1359;:6;;1351:49;;;;;-1:-1:-1;;;1351:49:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1422:5:12;;;1274:179::o;1346:286:21:-;-1:-1:-1;;;;;1487:20:21;;1483:143;;1523:21;;-1:-1:-1;;;;;1523:12:21;;;:21;;;;;1536:7;;1523:21;;;;1536:7;1523:12;:21;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1523:21:21;1483:143;;;1575:40;-1:-1:-1;;;;;1575:26:21;;1602:3;1607:7;1575:40;:26;:40;:::i;1611:391:14:-;1689:6;1730:12;:5;1740:1;1730:12;:9;:12;:::i;:::-;1715:4;:11;:27;;1707:60;;;;;-1:-1:-1;;;1707:60:14;;;;;;;;;;;;-1:-1:-1;;;1707:60:14;;;;;;;;;;;;;;;1778:19;;1824:13;:5;1834:2;1824:13;:9;:13;:::i;:::-;1934:20;;;1928:27;;1611:391;-1:-1:-1;;;;1611:391:14:o;2352:408::-;2431:4;2470:13;:5;2480:2;2470:13;:9;:13;:::i;1070:416::-;1149:7;1192:13;:5;1202:2;1192:13;:9;:13;:::i;:::-;1177:4;:11;:28;;1169:61;;;;;-1:-1:-1;;;1169:61:14;;;;;;;;;;;;-1:-1:-1;;;1169:61:14;;;;;;;;;;;;;;;1241:24;;1292:13;:5;1302:2;1292:13;:9;:13;:::i;:::-;1406:20;;;1400:27;1454:25;;;1070:416;-1:-1:-1;;;;1070:416:14:o;1701:140:17:-;1760:7;1801:4;;:20;;;-1:-1:-1;;;1801:20:17;;;;;;;;;;-1:-1:-1;;;;;1801:4:17;;;;:13;;:20;;;;;;;;;;;;;;;:4;:20;;;5:2:-1;;;;30:1;27;20:12;5:2;1801:20:17;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;1801:20:17;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;1801:20:17;1786:48;;;-1:-1:-1;;;1786:48:17;;;;;;;;;;-1:-1:-1;;;;;1786:41:17;;;;;;:48;;;;;1801:20;;1786:48;;;;;;;;:41;:48;;;5:2:-1;;;;30:1;27;20:12;3839:798:19;3889:4;;3927:9;3923:35;;3957:1;3950:8;;;;;3923:35;3985:34;3972:47;;3968:170;;4047:2;4040:9;-1:-1:-1;;;4083:4:19;4078:48;;-1:-1:-1;3968:170:19;4164:18;4151:31;;4147:137;;4210:1;4203:8;4253:19;4245:4;4240:32;;-1:-1:-1;4147:137:19;4310:10;4297:23;;4293:121;;4348:1;4341:8;-1:-1:-1;;;4383:4:19;4378:24;;-1:-1:-1;4293:121:19;4440:6;4427:19;;4423:113;;4474:1;4467:8;4517:7;4509:4;4504:20;;-1:-1:-1;4423:113:19;4562:4;4549:17;;4545:61;;4594:1;4587:8;4545:61;4622:2;:8;;3839:798;-1:-1:-1;;3839:798:19:o;2685:548::-;2805:164;2818:2;2811:3;:9;2805:164;;2887:10;;2874:24;;2933:2;2925:10;;;;2949:9;;;;-1:-1:-1;;2822:9:19;2805:164;;;3096:10;;3151:11;;3031:2;:8;;;;3023:3;:17;-1:-1:-1;;3023:21:19;3108:9;;3092:26;;;3147:22;;3195:21;3182:35;;3063:164::o;1803:173:11:-;1910:58;;;-1:-1:-1;;;;;1910:58:11;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;1910:58:11;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;1884:85:11;;1903:5;;4352:27;4360:5;-1:-1:-1;;;;;4352:25:11;;:27::i;:::-;4344:71;;;;;-1:-1:-1;;;4344:71:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;4486:12;4500:23;4535:5;-1:-1:-1;;;;;4527:19:11;4547:4;4527:25;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;4527:25:11;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;4485:67:11;;;;4570:7;4562:52;;;;;-1:-1:-1;;;4562:52:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4629:17;;:21;4625:221;;4769:10;4758:30;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;4758:30:11;4750:85;;;;-1:-1:-1;;;4750:85:11;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3757:1095;;;;:::o;542:413:2:-;902:20;940:8;;;542:413::o;1872:14610:20:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1872:14610:20;;;-1:-1:-1;1872:14610:20;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;
Swarm Source
bzzr://b9d0cff30fd06ec46b310e69c7459f33f14b7e95655e2e7621c17dae70fc5754
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.