Contract Address Details
contract
0x097df105fC970AeF9bc7277dc676D69E2a045197
Sponsored:
- Contract name:
- ProxyStorage
- Optimization enabled
- true
- Compiler version
- v0.4.26+commit.4563c3fc
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2023-10-02T01:58:21.208723Z
Contract source code
// File: contracts/eternal-storage/EternalStorage.sol
pragma solidity ^0.4.24;
/**
* @title EternalStorage
* @author LiorRabin
* @dev This contract holds all the necessary state variables to carry out the storage of any contract and to support the upgrade functionality.
*/
contract EternalStorage {
// Version number of the current implementation
uint256 internal version;
// Address of the current implementation
address internal implementation;
// Storage mappings
mapping(bytes32 => uint256) internal uintStorage;
mapping(bytes32 => string) internal stringStorage;
mapping(bytes32 => address) internal addressStorage;
mapping(bytes32 => bytes) internal bytesStorage;
mapping(bytes32 => bool) internal boolStorage;
mapping(bytes32 => int256) internal intStorage;
mapping(bytes32 => uint256[]) internal uintArrayStorage;
mapping(bytes32 => string[]) internal stringArrayStorage;
mapping(bytes32 => address[]) internal addressArrayStorage;
mapping(bytes32 => bytes[]) internal bytesArrayStorage;
mapping(bytes32 => bool[]) internal boolArrayStorage;
mapping(bytes32 => int256[]) internal intArrayStorage;
mapping(bytes32 => bytes32[]) internal bytes32ArrayStorage;
function isInitialized() public view returns(bool) {
return boolStorage[keccak256(abi.encodePacked("isInitialized"))];
}
function setInitialized(bool _status) internal {
boolStorage[keccak256(abi.encodePacked("isInitialized"))] = _status;
}
}
// File: contracts/eternal-storage/EternalStorageProxy.sol
pragma solidity ^0.4.24;
/**
* @title EternalStorageProxy
* @author LiorRabin
* @dev This proxy holds the storage of the token contract and delegates every call to the current implementation set.
* Besides, it allows to upgrade the token's behaviour towards further implementations, and provides authorization control functionalities
*/
contract EternalStorageProxy is EternalStorage {
/**
* @dev This event will be emitted every time the implementation gets upgraded
* @param version representing the version number of the upgraded implementation
* @param implementation representing the address of the upgraded implementation
*/
event Upgraded(uint256 version, address indexed implementation);
/**
* @dev This event will be emitted when ownership is renounces
* @param previousOwner address which is renounced from ownership
*/
event OwnershipRenounced(address indexed previousOwner);
/**
* @dev This event will be emitted when ownership is transferred
* @param previousOwner address which represents the previous owner
* @param newOwner address which represents the new owner
*/
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev This modifier verifies that msg.sender is the ProxyStorage contract
*/
modifier onlyProxyStorage() {
require(msg.sender == getProxyStorage());
_;
}
/**
* @dev This modifier verifies that msg.sender is the owner of the contract
*/
modifier onlyOwner() {
require(msg.sender == getOwner());
_;
}
/**
* @dev Constructor
* @param _proxyStorage address representing the ProxyStorage contract
* @param _implementation address representing the implementation contract
*/
constructor(address _proxyStorage, address _implementation) public {
require(_implementation != address(0));
if (_proxyStorage != address(0)) {
_setProxyStorage(_proxyStorage);
} else {
_setProxyStorage(address(this));
}
_setImplementation(_implementation);
_setOwner(msg.sender);
}
/**
* @dev Fallback function allowing to perform a delegatecall to the given implementation.
* This function will return whatever the implementation call returns
*/
// solhint-disable no-complex-fallback, no-inline-assembly
function() payable public {
address _impl = getImplementation();
require(_impl != address(0));
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0
calldatacopy(0, 0, calldatasize)
// Call the implementation.
// out and outsize are 0 because we don't know the size yet
let result := delegatecall(gas, _impl, 0, calldatasize, 0, 0)
// Copy the returned data
returndatacopy(0, 0, returndatasize)
switch result
// delegatecall returns 0 on error
case 0 { revert(0, returndatasize) }
default { return(0, returndatasize) }
}
}
// solhint-enable no-complex-fallback, no-inline-assembly
/**
* @dev Allows ProxyStorage contract (only) to upgrade the current implementation.
* @param _newImplementation representing the address of the new implementation to be set.
*/
function upgradeTo(address _newImplementation) public onlyProxyStorage returns(bool) {
if (_newImplementation == address(0)) return false;
if (getImplementation() == _newImplementation) return false;
uint256 _newVersion = getVersion() + 1;
_setVersion(_newVersion);
_setImplementation(_newImplementation);
emit Upgraded(_newVersion, _newImplementation);
return true;
}
/**
* @dev Allows the current owner to relinquish ownership.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(getOwner());
_setOwner(address(0));
}
/**
* @dev Allows the current owner to transfer control of the contract to a _newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function transferOwnership(address _newOwner) public onlyOwner {
require(_newOwner != address(0));
emit OwnershipTransferred(getOwner(), _newOwner);
_setOwner(_newOwner);
}
function getOwner() public view returns(address) {
return addressStorage[keccak256(abi.encodePacked("owner"))];
}
function _setOwner(address _owner) private {
addressStorage[keccak256(abi.encodePacked("owner"))] = _owner;
}
function getVersion() public view returns(uint256) {
return version;
}
function _setVersion(uint256 _newVersion) private {
version = _newVersion;
}
function getImplementation() public view returns(address) {
return implementation;
}
function _setImplementation(address _newImplementation) private {
implementation = _newImplementation;
}
function getProxyStorage() public view returns(address) {
return addressStorage[keccak256(abi.encodePacked("proxyStorage"))];
}
function _setProxyStorage(address _proxyStorage) private {
addressStorage[keccak256(abi.encodePacked("proxyStorage"))] = _proxyStorage;
}
}
// File: openzeppelin-solidity/contracts/math/SafeMath.sol
pragma solidity ^0.4.24;
/**
* @title SafeMath
* @dev Math operations with safety checks that revert on error
*/
library SafeMath {
int256 constant private INT256_MIN = -2**255;
/**
* @dev Multiplies two unsigned integers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Multiplies two signed integers, reverts on overflow.
*/
function mul(int256 a, int256 b) internal pure returns (int256) {
// 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;
}
require(!(a == -1 && b == INT256_MIN)); // This is the only case of overflow not detected by the check below
int256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
*/
function div(int256 a, int256 b) internal pure returns (int256) {
require(b != 0); // Solidity only automatically asserts when dividing by 0
require(!(b == -1 && a == INT256_MIN)); // This is the only case of overflow
int256 c = a / b;
return c;
}
/**
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Subtracts two signed integers, reverts on overflow.
*/
function sub(int256 a, int256 b) internal pure returns (int256) {
int256 c = a - b;
require((b >= 0 && c <= a) || (b < 0 && c > a));
return c;
}
/**
* @dev Adds two unsigned integers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Adds two signed integers, reverts on overflow.
*/
function add(int256 a, int256 b) internal pure returns (int256) {
int256 c = a + b;
require((b >= 0 && c >= a) || (b < 0 && c < a));
return c;
}
/**
* @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
* reverts when dividing by zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
// File: contracts/ProxyStorage.sol
pragma solidity ^0.4.24;
/**
* @title Contract used for access and upgradeability to all network contracts
* @author LiorRabin
*/
contract ProxyStorage is EternalStorage {
using SafeMath for uint256;
/**
* @dev Available contract types on the network
*/
enum ContractTypes {
Invalid,
Consensus,
BlockReward,
ProxyStorage,
Voting
}
/**
* @dev This event will be emitted when all contract addresses have been initialized by the contract owner
*/
event ProxyInitialized(
address consensus,
address blockReward,
address voting
);
/**
* @dev This event will be emitted each time a contract address is updated
* @param contractType contract type (See ContractTypes enum)
* @param contractAddress contract address set for the contract type
*/
event AddressSet(uint256 contractType, address contractAddress);
/**
* @dev This modifier verifies that msg.sender is the owner of the contract
*/
modifier onlyOwner() {
require(msg.sender == addressStorage[OWNER]);
_;
}
/**
* @dev This modifier verifies that msg.sender is the voting contract which implement proxy address change
*/
modifier onlyVoting() {
require(msg.sender == getVoting());
_;
}
/**
* @dev Function to be called on contract initialization
* @param _consensus address of the network consensus contract
*/
function initialize(address _consensus) external onlyOwner {
require(!isInitialized());
require(_consensus != address(0));
require(_consensus != address(this));
_setConsensus(_consensus);
setInitialized(true);
}
/**
* @dev Function to be called to initialize all available contract types addresses
*/
function initializeAddresses(address _blockReward, address _voting) external onlyOwner {
require(!boolStorage[PROXY_STORAGE_ADDRESSES_INITIALIZED]);
addressStorage[BLOCK_REWARD] = _blockReward;
addressStorage[VOTING] = _voting;
boolStorage[PROXY_STORAGE_ADDRESSES_INITIALIZED] = true;
emit ProxyInitialized(
getConsensus(),
_blockReward,
_voting
);
}
/**
* @dev Function to be called to set specific contract type address
* @param _contractType contract type (See ContractTypes enum)
* @param _contractAddress contract address set for the contract type
*/
function setContractAddress(uint256 _contractType, address _contractAddress) external onlyVoting returns(bool) {
if (!isInitialized()) return false;
if (_contractAddress == address(0)) return false;
bool success = false;
if (_contractType == uint256(ContractTypes.Consensus)) {
success = EternalStorageProxy(getConsensus()).upgradeTo(_contractAddress);
} else if (_contractType == uint256(ContractTypes.BlockReward)) {
success = EternalStorageProxy(getBlockReward()).upgradeTo(_contractAddress);
} else if (_contractType == uint256(ContractTypes.ProxyStorage)) {
success = EternalStorageProxy(this).upgradeTo(_contractAddress);
} else if (_contractType == uint256(ContractTypes.Voting)) {
success = EternalStorageProxy(getVoting()).upgradeTo(_contractAddress);
}
if (success) {
emit AddressSet(_contractType, _contractAddress);
}
return success;
}
/**
* @dev Function checking if a contract type is valid one for proxy usage
* @param _contractType contract type to check if valid
*/
function isValidContractType(uint256 _contractType) external pure returns(bool) {
return
_contractType == uint256(ContractTypes.Consensus) ||
_contractType == uint256(ContractTypes.BlockReward) ||
_contractType == uint256(ContractTypes.ProxyStorage) ||
_contractType == uint256(ContractTypes.Voting);
}
bytes32 internal constant OWNER = keccak256(abi.encodePacked("owner"));
bytes32 internal constant CONSENSUS = keccak256(abi.encodePacked("consensus"));
bytes32 internal constant BLOCK_REWARD = keccak256(abi.encodePacked("blockReward"));
bytes32 internal constant VOTING = keccak256(abi.encodePacked("voting"));
bytes32 internal constant PROXY_STORAGE_ADDRESSES_INITIALIZED = keccak256(abi.encodePacked("proxyStorageAddressesInitialized"));
function _setConsensus(address _consensus) private {
addressStorage[CONSENSUS] = _consensus;
}
function getConsensus() public view returns(address){
return addressStorage[CONSENSUS];
}
function getBlockReward() public view returns(address){
return addressStorage[BLOCK_REWARD];
}
function getVoting() public view returns(address){
return addressStorage[VOTING];
}
}
Contract ABI
[{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":""}],"name":"getBlockReward","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":""}],"name":"getConsensus","inputs":[],"constant":true},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":""}],"name":"getVoting","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"_consensus"}],"constant":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initializeAddresses","inputs":[{"type":"address","name":"_blockReward"},{"type":"address","name":"_voting"}],"constant":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":""}],"name":"isInitialized","inputs":[],"constant":true},{"type":"function","stateMutability":"pure","outputs":[{"type":"bool","name":""}],"name":"isValidContractType","inputs":[{"type":"uint256","name":"_contractType"}],"constant":true},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":""}],"name":"setContractAddress","inputs":[{"type":"uint256","name":"_contractType"},{"type":"address","name":"_contractAddress"}],"constant":false},{"type":"event","name":"AddressSet","inputs":[{"type":"uint256","name":"contractType","indexed":false},{"type":"address","name":"contractAddress","indexed":false}],"anonymous":false},{"type":"event","name":"ProxyInitialized","inputs":[{"type":"address","name":"consensus","indexed":false},{"type":"address","name":"blockReward","indexed":false},{"type":"address","name":"voting","indexed":false}],"anonymous":false}]
Contract Creation Code
0x608060405234801561001057600080fd5b50610d87806100206000396000f3006080604052600436106100745763ffffffff60e060020a600035041663179e740b81146100795780631986d376146100aa57806330b7bdad146100bf57806333875fdd146100e8578063392e53cd14610114578063bb0165b114610129578063c4d66de81461014d578063f89d40861461016e575b600080fd5b34801561008557600080fd5b5061008e610183565b60408051600160a060020a039092168252519081900360200190f35b3480156100b657600080fd5b5061008e610241565b3480156100cb57600080fd5b506100e6600160a060020a03600435811690602435166102b5565b005b3480156100f457600080fd5b506101006004356106f3565b604080519115158252519081900360200190f35b34801561012057600080fd5b50610100610720565b34801561013557600080fd5b50610100600435600160a060020a03602435166107d8565b34801561015957600080fd5b506100e6600160a060020a0360043516610a32565b34801561017a57600080fd5b5061008e610b49565b60006004600060405160200180807f636f6e73656e737573000000000000000000000000000000000000000000000081525060090190506040516020818303038152906040526040518082805190602001908083835b602083106101f85780518252601f1990920191602091820191016101d9565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a0316949350505050565b60006004600060405160200180807f766f74696e6700000000000000000000000000000000000000000000000000008152506006019050604051602081830303815290604052604051808280519060200190808383602083106101f85780518252601f1990920191602091820191016101d9565b6004600060405160200180807f6f776e657200000000000000000000000000000000000000000000000000000081525060050190506040516020818303038152906040526040518082805190602001908083835b602083106103285780518252601f199092019160209182019101610309565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a03163314925061037991505057600080fd5b6006600060405160200180807f70726f787953746f72616765416464726573736573496e697469616c697a656481525060200190506040516020818303038152906040526040518082805190602001908083835b602083106103ec5780518252601f1990920191602091820191016103cd565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1615925061043691505057600080fd5b816004600060405160200180807f626c6f636b526577617264000000000000000000000000000000000000000000815250600b0190506040516020818303038152906040526040518082805190602001908083835b602083106104aa5780518252601f19909201916020918201910161048b565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285810196909652509283016000908120805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039790971696909617909555505080517f766f74696e67000000000000000000000000000000000000000000000000000081840152815160068183030181526026909101918290528051859460049490939182918401908083835b6020831061057e5780518252601f19909201916020918201910161055f565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285810196909652509283016000908120805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039790971696909617909555505080517f70726f787953746f72616765416464726573736573496e697469616c697a65648184015281518082038401815290820191829052805160019460069490939182918401908083835b602083106106505780518252601f199092019160209182019101610631565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff191694151594909417909355507fffcbdc3faa9d3a4dbee5296e7b8671c3962abe5cc9defb4144df40382ad4713c91506106c59050610183565b60408051600160a060020a039283168152828616602082015291841682820152519081900360600190a15050565b600060018214806107045750600282145b8061070f5750600382145b8061071a5750600482145b92915050565b60006006600060405160200180807f6973496e697469616c697a656400000000000000000000000000000000000000815250600d0190506040516020818303038152906040526040518082805190602001908083835b602083106107955780518252601f199092019160209182019101610776565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff16949350505050565b6000806107e3610241565b600160a060020a031633146107f757600080fd5b6107ff610720565b151561080e5760009150610a2b565b600160a060020a03831615156108275760009150610a2b565b50600060018414156108c85761083b610183565b600160a060020a0316633659cfe6846040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801561089557600080fd5b505af11580156108a9573d6000803e3d6000fd5b505050506040513d60208110156108bf57600080fd5b505190506109dd565b60028414156108d95761083b610b49565b600384141561094357604080517f3659cfe6000000000000000000000000000000000000000000000000000000008152600160a060020a038516600482015290513091633659cfe69160248083019260209291908290030181600087803b15801561089557600080fd5b60048414156109dd57610954610241565b600160a060020a0316633659cfe6846040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b1580156109ae57600080fd5b505af11580156109c2573d6000803e3d6000fd5b505050506040513d60208110156109d857600080fd5b505190505b8015610a275760408051858152600160a060020a038516602082015281517fcb8f0f32182a0f756b1e065dab832c24d2c48fa533912c33552252a7f25bf4ae929181900390910190a15b8091505b5092915050565b6004600060405160200180807f6f776e657200000000000000000000000000000000000000000000000000000081525060050190506040516020818303038152906040526040518082805190602001908083835b60208310610aa55780518252601f199092019160209182019101610a86565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a031633149250610af691505057600080fd5b610afe610720565b15610b0857600080fd5b600160a060020a0381161515610b1d57600080fd5b600160a060020a038116301415610b3357600080fd5b610b3c81610bbd565b610b466001610c9a565b50565b60006004600060405160200180807f626c6f636b526577617264000000000000000000000000000000000000000000815250600b019050604051602081830303815290604052604051808280519060200190808383602083106101f85780518252601f1990920191602091820191016101d9565b806004600060405160200180807f636f6e73656e737573000000000000000000000000000000000000000000000081525060090190506040516020818303038152906040526040518082805190602001908083835b60208310610c315780518252601f199092019160209182019101610c12565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03959095169490941790935550505050565b806006600060405160200180807f6973496e697469616c697a656400000000000000000000000000000000000000815250600d0190506040516020818303038152906040526040518082805190602001908083835b60208310610d0e5780518252601f199092019160209182019101610cef565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff191694151594909417909355505050505600a165627a7a72305820c2c2c12433da6ee0a930d11c09d871bead2991a3b6973295c9bd855ed02302b40029
Deployed ByteCode
0x6080604052600436106100745763ffffffff60e060020a600035041663179e740b81146100795780631986d376146100aa57806330b7bdad146100bf57806333875fdd146100e8578063392e53cd14610114578063bb0165b114610129578063c4d66de81461014d578063f89d40861461016e575b600080fd5b34801561008557600080fd5b5061008e610183565b60408051600160a060020a039092168252519081900360200190f35b3480156100b657600080fd5b5061008e610241565b3480156100cb57600080fd5b506100e6600160a060020a03600435811690602435166102b5565b005b3480156100f457600080fd5b506101006004356106f3565b604080519115158252519081900360200190f35b34801561012057600080fd5b50610100610720565b34801561013557600080fd5b50610100600435600160a060020a03602435166107d8565b34801561015957600080fd5b506100e6600160a060020a0360043516610a32565b34801561017a57600080fd5b5061008e610b49565b60006004600060405160200180807f636f6e73656e737573000000000000000000000000000000000000000000000081525060090190506040516020818303038152906040526040518082805190602001908083835b602083106101f85780518252601f1990920191602091820191016101d9565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a0316949350505050565b60006004600060405160200180807f766f74696e6700000000000000000000000000000000000000000000000000008152506006019050604051602081830303815290604052604051808280519060200190808383602083106101f85780518252601f1990920191602091820191016101d9565b6004600060405160200180807f6f776e657200000000000000000000000000000000000000000000000000000081525060050190506040516020818303038152906040526040518082805190602001908083835b602083106103285780518252601f199092019160209182019101610309565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a03163314925061037991505057600080fd5b6006600060405160200180807f70726f787953746f72616765416464726573736573496e697469616c697a656481525060200190506040516020818303038152906040526040518082805190602001908083835b602083106103ec5780518252601f1990920191602091820191016103cd565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff1615925061043691505057600080fd5b816004600060405160200180807f626c6f636b526577617264000000000000000000000000000000000000000000815250600b0190506040516020818303038152906040526040518082805190602001908083835b602083106104aa5780518252601f19909201916020918201910161048b565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285810196909652509283016000908120805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039790971696909617909555505080517f766f74696e67000000000000000000000000000000000000000000000000000081840152815160068183030181526026909101918290528051859460049490939182918401908083835b6020831061057e5780518252601f19909201916020918201910161055f565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285810196909652509283016000908120805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039790971696909617909555505080517f70726f787953746f72616765416464726573736573496e697469616c697a65648184015281518082038401815290820191829052805160019460069490939182918401908083835b602083106106505780518252601f199092019160209182019101610631565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff191694151594909417909355507fffcbdc3faa9d3a4dbee5296e7b8671c3962abe5cc9defb4144df40382ad4713c91506106c59050610183565b60408051600160a060020a039283168152828616602082015291841682820152519081900360600190a15050565b600060018214806107045750600282145b8061070f5750600382145b8061071a5750600482145b92915050565b60006006600060405160200180807f6973496e697469616c697a656400000000000000000000000000000000000000815250600d0190506040516020818303038152906040526040518082805190602001908083835b602083106107955780518252601f199092019160209182019101610776565b51815160209384036101000a600019018019909216911617905260408051929094018290039091208652850195909552929092016000205460ff16949350505050565b6000806107e3610241565b600160a060020a031633146107f757600080fd5b6107ff610720565b151561080e5760009150610a2b565b600160a060020a03831615156108275760009150610a2b565b50600060018414156108c85761083b610183565b600160a060020a0316633659cfe6846040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b15801561089557600080fd5b505af11580156108a9573d6000803e3d6000fd5b505050506040513d60208110156108bf57600080fd5b505190506109dd565b60028414156108d95761083b610b49565b600384141561094357604080517f3659cfe6000000000000000000000000000000000000000000000000000000008152600160a060020a038516600482015290513091633659cfe69160248083019260209291908290030181600087803b15801561089557600080fd5b60048414156109dd57610954610241565b600160a060020a0316633659cfe6846040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a03168152602001915050602060405180830381600087803b1580156109ae57600080fd5b505af11580156109c2573d6000803e3d6000fd5b505050506040513d60208110156109d857600080fd5b505190505b8015610a275760408051858152600160a060020a038516602082015281517fcb8f0f32182a0f756b1e065dab832c24d2c48fa533912c33552252a7f25bf4ae929181900390910190a15b8091505b5092915050565b6004600060405160200180807f6f776e657200000000000000000000000000000000000000000000000000000081525060050190506040516020818303038152906040526040518082805190602001908083835b60208310610aa55780518252601f199092019160209182019101610a86565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002054600160a060020a031633149250610af691505057600080fd5b610afe610720565b15610b0857600080fd5b600160a060020a0381161515610b1d57600080fd5b600160a060020a038116301415610b3357600080fd5b610b3c81610bbd565b610b466001610c9a565b50565b60006004600060405160200180807f626c6f636b526577617264000000000000000000000000000000000000000000815250600b019050604051602081830303815290604052604051808280519060200190808383602083106101f85780518252601f1990920191602091820191016101d9565b806004600060405160200180807f636f6e73656e737573000000000000000000000000000000000000000000000081525060090190506040516020818303038152906040526040518082805190602001908083835b60208310610c315780518252601f199092019160209182019101610c12565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03959095169490941790935550505050565b806006600060405160200180807f6973496e697469616c697a656400000000000000000000000000000000000000815250600d0190506040516020818303038152906040526040518082805190602001908083835b60208310610d0e5780518252601f199092019160209182019101610cef565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120865285019590955292909201600020805460ff191694151594909417909355505050505600a165627a7a72305820c2c2c12433da6ee0a930d11c09d871bead2991a3b6973295c9bd855ed02302b40029