Source Code
Overview
CELO Balance
CELO Value
$0.00Multichain Info
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Accounts
Compiler Version
v0.5.13+commit.5b0b510c
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.5.13;
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "./interfaces/IAccounts.sol";
import "../common/FixidityLib.sol";
import "../common/Initializable.sol";
import "../common/interfaces/ICeloVersionedContract.sol";
import "../common/Signatures.sol";
import "../common/UsingRegistry.sol";
import "../common/libraries/ReentrancyGuard.sol";
contract Accounts is
IAccounts,
ICeloVersionedContract,
Ownable,
ReentrancyGuard,
Initializable,
UsingRegistry
{
using FixidityLib for FixidityLib.Fraction;
using SafeMath for uint256;
struct Signers {
// The address that is authorized to vote in governance and validator elections on behalf of the
// account. The account can vote as well, whether or not a vote signing key has been specified.
address vote;
// The address that is authorized to manage a validator or validator group and sign consensus
// messages on behalf of the account. The account can manage the validator, whether or not a
// validator signing key has been specified. However, if a validator signing key has been
// specified, only that key may actually participate in consensus.
address validator;
// The address of the key with which this account wants to sign attestations on the Attestations
// contract
address attestation;
}
struct SignerAuthorization {
bool started;
bool completed;
}
struct Account {
bool exists;
// [Deprecated] Each account may authorize signing keys to use for voting,
// validating or attestation. These keys may not be keys of other accounts,
// and may not be authorized by any other account for any purpose.
Signers signers;
// The address at which the account expects to receive transfers. If it's empty/0x0, the
// account indicates that an address exchange should be initiated with the dataEncryptionKey
address walletAddress;
// An optional human readable identifier for the account
string name;
// The ECDSA public key used to encrypt and decrypt data for this account
bytes dataEncryptionKey;
// The URL under which an account adds metadata and claims
string metadataURL;
}
struct PaymentDelegation {
// Address that should receive a fraction of validator payments.
address beneficiary;
// Fraction of payment to delegate to `beneficiary`.
FixidityLib.Fraction fraction;
}
mapping(address => Account) internal accounts;
// Maps authorized signers to the account that provided the authorization.
mapping(address => address) public authorizedBy;
// Default signers by account (replaces the legacy Signers struct on Account)
mapping(address => mapping(bytes32 => address)) defaultSigners;
// All signers and their roles for a given account
// solhint-disable-next-line max-line-length
mapping(address => mapping(bytes32 => mapping(address => SignerAuthorization))) signerAuthorizations;
bytes32 public constant EIP712_AUTHORIZE_SIGNER_TYPEHASH =
keccak256("AuthorizeSigner(address account,address signer,bytes32 role)");
bytes32 public eip712DomainSeparator;
// A per-account list of CIP8 storage roots, bypassing CIP3.
mapping(address => bytes[]) public offchainStorageRoots;
// Optional per-account validator payment delegation information.
mapping(address => PaymentDelegation) internal paymentDelegations;
bytes32 constant ValidatorSigner = keccak256(abi.encodePacked("celo.org/core/validator"));
bytes32 constant AttestationSigner = keccak256(abi.encodePacked("celo.org/core/attestation"));
bytes32 constant VoteSigner = keccak256(abi.encodePacked("celo.org/core/vote"));
event AttestationSignerAuthorized(address indexed account, address signer);
event VoteSignerAuthorized(address indexed account, address signer);
event ValidatorSignerAuthorized(address indexed account, address signer);
event SignerAuthorized(address indexed account, address signer, bytes32 indexed role);
event SignerAuthorizationStarted(address indexed account, address signer, bytes32 indexed role);
event SignerAuthorizationCompleted(address indexed account, address signer, bytes32 indexed role);
event AttestationSignerRemoved(address indexed account, address oldSigner);
event VoteSignerRemoved(address indexed account, address oldSigner);
event ValidatorSignerRemoved(address indexed account, address oldSigner);
event IndexedSignerSet(address indexed account, address signer, bytes32 role);
event IndexedSignerRemoved(address indexed account, address oldSigner, bytes32 role);
event DefaultSignerSet(address indexed account, address signer, bytes32 role);
event DefaultSignerRemoved(address indexed account, address oldSigner, bytes32 role);
event LegacySignerSet(address indexed account, address signer, bytes32 role);
event LegacySignerRemoved(address indexed account, address oldSigner, bytes32 role);
event SignerRemoved(address indexed account, address oldSigner, bytes32 indexed role);
event AccountDataEncryptionKeySet(address indexed account, bytes dataEncryptionKey);
event AccountNameSet(address indexed account, string name);
event AccountMetadataURLSet(address indexed account, string metadataURL);
event AccountWalletAddressSet(address indexed account, address walletAddress);
event AccountCreated(address indexed account);
event OffchainStorageRootAdded(address indexed account, bytes url);
event OffchainStorageRootRemoved(address indexed account, bytes url, uint256 index);
event PaymentDelegationSet(address indexed beneficiary, uint256 fraction);
/**
* @notice Sets initialized == true on implementation contracts
* @param test Set to true to skip implementation initialization
*/
constructor(bool test) public Initializable(test) {}
/**
* @notice Used in place of the constructor to allow the contract to be upgradable via proxy.
* @param registryAddress The address of the registry core smart contract.
*/
function initialize(address registryAddress) external initializer {
_transferOwnership(msg.sender);
setRegistry(registryAddress);
_setEip712DomainSeparator();
}
/**
* @notice Sets the EIP712 domain separator for the Celo Accounts abstraction.
*/
function setEip712DomainSeparator() external {
_setEip712DomainSeparator();
}
/**
* @notice Convenience Setter for the dataEncryptionKey and wallet address for an account
* @param name A string to set as the name of the account
* @param dataEncryptionKey secp256k1 public key for data encryption. Preferably compressed.
* @param walletAddress The wallet address to set for the account
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
* @dev v, r, s constitute `signer`'s signature on `msg.sender` (unless the wallet address
* is 0x0 or msg.sender).
*/
function setAccount(
string calldata name,
bytes calldata dataEncryptionKey,
address walletAddress,
uint8 v,
bytes32 r,
bytes32 s
) external {
if (!isAccount(msg.sender)) {
createAccount();
}
setName(name);
setAccountDataEncryptionKey(dataEncryptionKey);
setWalletAddress(walletAddress, v, r, s);
}
/**
* @notice Setter for the metadata of an account.
* @param metadataURL The URL to access the metadata.
*/
function setMetadataURL(string calldata metadataURL) external {
require(isAccount(msg.sender), "Unknown account");
Account storage account = accounts[msg.sender];
account.metadataURL = metadataURL;
emit AccountMetadataURLSet(msg.sender, metadataURL);
}
/**
* @notice Adds a new CIP8 storage root.
* @param url The URL pointing to the offchain storage root.
*/
function addStorageRoot(bytes calldata url) external {
require(isAccount(msg.sender), "Unknown account");
offchainStorageRoots[msg.sender].push(url);
emit OffchainStorageRootAdded(msg.sender, url);
}
/**
* @notice Removes a CIP8 storage root.
* @param index The index of the storage root to be removed in the account's
* list of storage roots.
* @dev The order of storage roots may change after this operation (the last
* storage root will be moved to `index`), be aware of this if removing
* multiple storage roots at a time.
*/
function removeStorageRoot(uint256 index) external {
require(isAccount(msg.sender), "Unknown account");
require(index < offchainStorageRoots[msg.sender].length, "Invalid storage root index");
uint256 lastIndex = offchainStorageRoots[msg.sender].length - 1;
bytes memory url = offchainStorageRoots[msg.sender][index];
offchainStorageRoots[msg.sender][index] = offchainStorageRoots[msg.sender][lastIndex];
offchainStorageRoots[msg.sender].length--;
emit OffchainStorageRootRemoved(msg.sender, url, index);
}
/**
* @notice Authorizes an address to sign votes on behalf of the account.
* @param signer The address of the signing key to authorize.
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
* @dev v, r, s constitute `signer`'s signature on `msg.sender`.
*/
function authorizeVoteSigner(
address signer,
uint8 v,
bytes32 r,
bytes32 s
) external nonReentrant {
legacyAuthorizeSignerWithSignature(signer, VoteSigner, v, r, s);
setIndexedSigner(signer, VoteSigner);
emit VoteSignerAuthorized(msg.sender, signer);
}
/**
* @notice Authorizes an address to sign consensus messages on behalf of the account.
* @param signer The address of the signing key to authorize.
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
* @dev v, r, s constitute `signer`'s signature on `msg.sender`.
*/
function authorizeValidatorSigner(
address signer,
uint8 v,
bytes32 r,
bytes32 s
) external nonReentrant {
legacyAuthorizeSignerWithSignature(signer, ValidatorSigner, v, r, s);
setIndexedSigner(signer, ValidatorSigner);
require(!getValidators().isValidator(msg.sender), "Cannot authorize validator signer");
emit ValidatorSignerAuthorized(msg.sender, signer);
}
/**
* @notice Authorizes an address to sign consensus messages on behalf of the account.
* @param signer The address of the signing key to authorize.
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
* @param ecdsaPublicKey The ECDSA public key corresponding to `signer`.
* @dev v, r, s constitute `signer`'s signature on `msg.sender`.
*/
function authorizeValidatorSignerWithPublicKey(
address signer,
uint8 v,
bytes32 r,
bytes32 s,
bytes calldata ecdsaPublicKey
) external nonReentrant {
legacyAuthorizeSignerWithSignature(signer, ValidatorSigner, v, r, s);
setIndexedSigner(signer, ValidatorSigner);
require(
getValidators().updateEcdsaPublicKey(msg.sender, signer, ecdsaPublicKey),
"Failed to update ECDSA public key"
);
emit ValidatorSignerAuthorized(msg.sender, signer);
}
/**
* @notice Getter for the metadata of multiple accounts.
* @param accountsToQuery The addresses of the accounts to get the metadata for.
* @return The length of each string in bytes.
* @return All strings concatenated.
*/
function batchGetMetadataURL(
address[] calldata accountsToQuery
) external view returns (uint256[] memory, bytes memory) {
uint256 totalSize = 0;
uint256[] memory sizes = new uint256[](accountsToQuery.length);
for (uint256 i = 0; i < accountsToQuery.length; i = i.add(1)) {
sizes[i] = bytes(accounts[accountsToQuery[i]].metadataURL).length;
totalSize = totalSize.add(sizes[i]);
}
bytes memory data = new bytes(totalSize);
uint256 pointer = 0;
for (uint256 i = 0; i < accountsToQuery.length; i = i.add(1)) {
for (uint256 j = 0; j < sizes[i]; j = j.add(1)) {
data[pointer] = bytes(accounts[accountsToQuery[i]].metadataURL)[j];
pointer = pointer.add(1);
}
}
return (sizes, data);
}
/**
* @notice Returns the full list of offchain storage roots for an account.
* @param account The account whose storage roots to return.
* @return Concatenated storage root URLs.
* @return Lengths of storage root URLs.
*/
function getOffchainStorageRoots(
address account
) external view returns (bytes memory, uint256[] memory) {
require(isAccount(account), "Unknown account");
uint256 numberRoots = offchainStorageRoots[account].length;
uint256 totalLength = 0;
for (uint256 i = 0; i < numberRoots; i++) {
totalLength = totalLength.add(offchainStorageRoots[account][i].length);
}
bytes memory concatenated = new bytes(totalLength);
uint256 lastIndex = 0;
uint256[] memory lengths = new uint256[](numberRoots);
for (uint256 i = 0; i < numberRoots; i++) {
bytes storage root = offchainStorageRoots[account][i];
lengths[i] = root.length;
for (uint256 j = 0; j < lengths[i]; j++) {
concatenated[lastIndex] = root[j];
lastIndex++;
}
}
return (concatenated, lengths);
}
/**
* @notice Gets validator payment delegation settings.
* @param account Account of the validator.
* @return Beneficiary address of payment delegated.
* @return Fraction of payment delegated.
*/
function getPaymentDelegation(address account) external view returns (address, uint256) {
PaymentDelegation storage delegation = paymentDelegations[account];
return (delegation.beneficiary, delegation.fraction.unwrap());
}
/**
* @notice Returns the account associated with `signer`.
* @param signer The address of the account or currently authorized attestation signer.
* @dev Fails if the `signer` is not an account or currently authorized attestation signer.
* @return The associated account that the signer is authorized to attest for.
*/
function attestationSignerToAccount(address signer) external view returns (address) {
return signerToAccountWithRole(signer, AttestationSigner);
}
/**
* @notice Returns the account associated with `signer`.
* @param signer The address of the account or currently authorized vote signer.
* @dev Fails if the `signer` is not an account or currently authorized vote signer.
* @return The associated account that signer is authorized to vote for.
*/
function voteSignerToAccount(address signer) external view returns (address) {
return signerToAccountWithRole(signer, VoteSigner);
}
/**
* @notice Returns the account associated with `signer`.
* @param signer The address of the account or previously authorized signer.
* @dev Fails if the `signer` is not an account or previously authorized signer.
* @return The associated account.
*/
function signerToAccount(address signer) external view returns (address) {
address authorizingAccount = authorizedBy[signer];
if (authorizingAccount != address(0)) {
return authorizingAccount;
} else {
require(isAccount(signer), "Must first register address with Account.createAccount");
return signer;
}
}
/**
* @notice Checks whether or not the account has a signer
* registered for the plaintext role.
* @dev See `hasIndexedSigner` for more gas efficient call.
*/
function hasAuthorizedSigner(address account, string calldata role) external view returns (bool) {
return hasIndexedSigner(account, keccak256(abi.encodePacked(role)));
}
/**
* @notice Returns if account has specified a dedicated vote signer.
* @param account The address of the account.
* @return Whether the account has specified a dedicated vote signer.
*/
function hasAuthorizedVoteSigner(address account) external view returns (bool) {
return hasLegacySigner(account, VoteSigner);
}
/**
* @notice Returns if account has specified a dedicated validator signer.
* @param account The address of the account.
* @return Whether the account has specified a dedicated validator signer.
*/
function hasAuthorizedValidatorSigner(address account) external view returns (bool) {
return hasLegacySigner(account, ValidatorSigner);
}
/**
* @notice Returns if account has specified a dedicated attestation signer.
* @param account The address of the account.
* @return Whether the account has specified a dedicated attestation signer.
*/
function hasAuthorizedAttestationSigner(address account) external view returns (bool) {
return hasLegacySigner(account, AttestationSigner);
}
/**
* @notice Getter for the name of an account.
* @param account The address of the account to get the name for.
* @return name The name of the account.
*/
function getName(address account) external view returns (string memory) {
return accounts[account].name;
}
/**
* @notice Getter for the metadata of an account.
* @param account The address of the account to get the metadata for.
* @return metadataURL The URL to access the metadata.
*/
function getMetadataURL(address account) external view returns (string memory) {
return accounts[account].metadataURL;
}
/**
* @notice Getter for the data encryption key and version.
* @param account The address of the account to get the key for
* @return dataEncryptionKey secp256k1 public key for data encryption. Preferably compressed.
*/
function getDataEncryptionKey(address account) external view returns (bytes memory) {
return accounts[account].dataEncryptionKey;
}
/**
* @notice Getter for the wallet address for an account
* @param account The address of the account to get the wallet address for
* @return Wallet address
*/
function getWalletAddress(address account) external view returns (address) {
return accounts[account].walletAddress;
}
/**
* @notice Check if an address has been an authorized signer for an account.
* @param signer The possibly authorized address.
* @return Returns `true` if authorized. Returns `false` otherwise.
*/
function isAuthorizedSigner(address signer) external view returns (bool) {
return (authorizedBy[signer] != address(0));
}
/**
* @notice Returns the storage, major, minor, and patch version of the contract.
* @return Storage version of the contract.
* @return Major version of the contract.
* @return Minor version of the contract.
* @return Patch version of the contract.
*/
function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256) {
return (1, 2, 0, 0);
}
/**
* @notice Creates an account.
* @return True if account creation succeeded.
*/
function createAccount() public returns (bool) {
require(
isNotAccount(msg.sender) && isNotAuthorizedSigner(msg.sender),
"Account already exists or address is an authorized signer for another account"
);
Account storage account = accounts[msg.sender];
account.exists = true;
emit AccountCreated(msg.sender);
return true;
}
/**
* @notice Setter for the name of an account.
* @param name The name to set.
*/
function setName(string memory name) public {
require(isAccount(msg.sender), "Register with createAccount to set account name");
Account storage account = accounts[msg.sender];
account.name = name;
emit AccountNameSet(msg.sender, name);
}
/**
* @notice Setter for the wallet address for an account
* @param walletAddress The wallet address to set for the account
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
* @dev Wallet address can be zero. This means that the owner of the wallet
* does not want to be paid directly without interaction, and instead wants users to
* contact them, using the data encryption key, and arrange a payment.
* @dev v, r, s constitute `signer`'s signature on `msg.sender` (unless the wallet address
* is 0x0 or msg.sender).
*/
function setWalletAddress(address walletAddress, uint8 v, bytes32 r, bytes32 s) public {
require(isAccount(msg.sender), "Unknown account");
if (!(walletAddress == msg.sender || walletAddress == address(0x0))) {
address signer = Signatures.getSignerOfAddress(msg.sender, v, r, s);
require(signer == walletAddress, "Invalid signature");
}
Account storage account = accounts[msg.sender];
account.walletAddress = walletAddress;
emit AccountWalletAddressSet(msg.sender, walletAddress);
}
/**
* @notice Setter for the data encryption key and version.
* @param dataEncryptionKey secp256k1 public key for data encryption. Preferably compressed.
*/
function setAccountDataEncryptionKey(bytes memory dataEncryptionKey) public {
require(dataEncryptionKey.length >= 33, "data encryption key length <= 32");
Account storage account = accounts[msg.sender];
account.dataEncryptionKey = dataEncryptionKey;
emit AccountDataEncryptionKeySet(msg.sender, dataEncryptionKey);
}
/**
* @notice Sets validator payment delegation settings.
* @param beneficiary The address that should receive a portion of validator
* payments.
* @param fraction The fraction of the validator's payment that should be
* diverted to `beneficiary` every epoch, given as FixidityLib value. Must not
* be greater than 1.
* @dev Use `deletePaymentDelegation` to unset the payment delegation.
*/
function setPaymentDelegation(address beneficiary, uint256 fraction) public {
require(isAccount(msg.sender), "Must first register address with Account.createAccount");
require(beneficiary != address(0), "Beneficiary cannot be address 0x0");
FixidityLib.Fraction memory f = FixidityLib.wrap(fraction);
require(f.lte(FixidityLib.fixed1()), "Fraction must not be greater than 1");
paymentDelegations[msg.sender] = PaymentDelegation(beneficiary, f);
emit PaymentDelegationSet(beneficiary, fraction);
}
/**
* @notice Removes a validator's payment delegation by setting benficiary and
* fraction to 0.
*/
function deletePaymentDelegation() public {
require(isAccount(msg.sender), "Must first register address with Account.createAccount");
paymentDelegations[msg.sender] = PaymentDelegation(address(0x0), FixidityLib.wrap(0));
emit PaymentDelegationSet(address(0x0), 0);
}
/**
* @notice Set the indexed signer for a specific role
* @param signer the address to set as default
* @param role the role to register a default signer for
*/
function setIndexedSigner(address signer, bytes32 role) public {
require(isAccount(msg.sender), "Must first register address with Account.createAccount");
require(isNotAccount(signer), "Cannot authorize account as signer");
require(
isNotAuthorizedSignerForAnotherAccount(msg.sender, signer),
"Not a signer for this account"
);
require(isSigner(msg.sender, signer, role), "Must authorize signer before setting as default");
Account storage account = accounts[msg.sender];
if (isLegacyRole(role)) {
if (role == VoteSigner) {
account.signers.vote = signer;
} else if (role == AttestationSigner) {
account.signers.attestation = signer;
} else if (role == ValidatorSigner) {
account.signers.validator = signer;
}
emit LegacySignerSet(msg.sender, signer, role);
} else {
defaultSigners[msg.sender][role] = signer;
emit DefaultSignerSet(msg.sender, signer, role);
}
emit IndexedSignerSet(msg.sender, signer, role);
}
/**
* @notice Authorizes an address to act as a signer, for `role`, on behalf of the account.
* @param signer The address of the signing key to authorize.
* @param role The role to authorize signing for.
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
* @dev v, r, s constitute `signer`'s EIP712 signature over `role`, `msg.sender`
* and `signer`.
*/
function authorizeSignerWithSignature(
address signer,
bytes32 role,
uint8 v,
bytes32 r,
bytes32 s
) public {
authorizeAddressWithRole(signer, role, v, r, s);
signerAuthorizations[msg.sender][role][signer] = SignerAuthorization({
started: true,
completed: true
});
emit SignerAuthorized(msg.sender, signer, role);
}
/**
* @notice Authorizes an address to sign attestations on behalf of the account.
* @param signer The address of the signing key to authorize.
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
* @dev v, r, s constitute `signer`'s signature on `msg.sender`.
*/
function authorizeAttestationSigner(address signer, uint8 v, bytes32 r, bytes32 s) public {
legacyAuthorizeSignerWithSignature(signer, AttestationSigner, v, r, s);
setIndexedSigner(signer, AttestationSigner);
emit AttestationSignerAuthorized(msg.sender, signer);
}
/**
* @notice Begin the process of authorizing an address to sign on behalf of the account
* @param signer The address of the signing key to authorize.
* @param role The role to authorize signing for.
*/
function authorizeSigner(address signer, bytes32 role) public {
require(isAccount(msg.sender), "Must first register sender with Account.createAccount");
require(
isNotAccount(signer) && isNotAuthorizedSignerForAnotherAccount(msg.sender, signer),
"Cannot re-authorize address signer"
);
signerAuthorizations[msg.sender][role][signer] = SignerAuthorization({
started: true,
completed: false
});
emit SignerAuthorizationStarted(msg.sender, signer, role);
}
/**
* @notice Finish the process of authorizing an address to sign on behalf of the account.
* @param account The address of account that authorized signing.
* @param role The role to finish authorizing for.
*/
function completeSignerAuthorization(address account, bytes32 role) public {
require(
isAccount(account),
"Unknown Account: Address that authorized signing must be a registered Account"
);
require(
isNotAccount(msg.sender) && isNotAuthorizedSignerForAnotherAccount(account, msg.sender),
"Cannot re-authorize address signer"
);
require(
signerAuthorizations[account][role][msg.sender].started == true,
"Signer authorization not started"
);
authorizedBy[msg.sender] = account;
signerAuthorizations[account][role][msg.sender].completed = true;
emit SignerAuthorizationCompleted(account, msg.sender, role);
}
/**
* @notice Removes the signer for a default role.
* @param role The role that has been authorized.
*/
function removeDefaultSigner(bytes32 role) public {
address signer = defaultSigners[msg.sender][role];
defaultSigners[msg.sender][role] = address(0);
emit DefaultSignerRemoved(msg.sender, signer, role);
}
/**
* @notice Removes the currently authorized and indexed signer
* for a specific role
* @param role The role of the signer.
*/
function removeIndexedSigner(bytes32 role) public {
address oldSigner = getIndexedSigner(msg.sender, role);
isLegacyRole(role) ? removeLegacySigner(role) : removeDefaultSigner(role);
emit IndexedSignerRemoved(msg.sender, oldSigner, role);
}
/**
* @notice Removes the currently authorized signer for a specific role and
* if the signer is indexed, remove that as well.
* @param signer The address of the signer.
* @param role The role that has been authorized.
*/
function removeSigner(address signer, bytes32 role) public {
if (isIndexedSigner(msg.sender, signer, role)) {
removeIndexedSigner(role);
}
delete signerAuthorizations[msg.sender][role][signer];
emit SignerRemoved(msg.sender, signer, role);
}
/**
* @notice Removes the currently authorized vote signer for the account.
* Note that the signers cannot be reauthorized after they have been removed.
*/
function removeVoteSigner() public {
address signer = getLegacySigner(msg.sender, VoteSigner);
removeSigner(signer, VoteSigner);
emit VoteSignerRemoved(msg.sender, signer);
}
/**
* @notice Removes the currently authorized validator signer for the account
* Note that the signers cannot be reauthorized after they have been removed.
*/
function removeValidatorSigner() public {
address signer = getLegacySigner(msg.sender, ValidatorSigner);
removeSigner(signer, ValidatorSigner);
emit ValidatorSignerRemoved(msg.sender, signer);
}
/**
* @notice Removes the currently authorized attestation signer for the account
* Note that the signers cannot be reauthorized after they have been removed.
*/
function removeAttestationSigner() public {
address signer = getLegacySigner(msg.sender, AttestationSigner);
removeSigner(signer, AttestationSigner);
emit AttestationSignerRemoved(msg.sender, signer);
}
/**
* @notice Whether or not the signer has been registered as the legacy signer for role
* @param _account The address of account that authorized signing.
* @param signer The address of the signer.
* @param role The role that has been authorized.
*/
function isLegacySigner(
address _account,
address signer,
bytes32 role
) public view returns (bool) {
Account storage account = accounts[_account];
if (role == ValidatorSigner && account.signers.validator == signer) {
return true;
} else if (role == AttestationSigner && account.signers.attestation == signer) {
return true;
} else if (role == VoteSigner && account.signers.vote == signer) {
return true;
} else {
return false;
}
}
/**
* @notice Whether or not the signer has been registered as the default signer for role
* @param account The address of account that authorized signing.
* @param signer The address of the signer.
* @param role The role that has been authorized.
*/
function isDefaultSigner(
address account,
address signer,
bytes32 role
) public view returns (bool) {
return defaultSigners[account][role] == signer;
}
/**
* @notice Whether or not the signer has been registered as an indexed signer for role
* @param account The address of account that authorized signing.
* @param signer The address of the signer.
* @param role The role that has been authorized.
*/
function isIndexedSigner(
address account,
address signer,
bytes32 role
) public view returns (bool) {
return
isLegacyRole(role)
? isLegacySigner(account, signer, role)
: isDefaultSigner(account, signer, role);
}
/**
* @notice Whether or not the signer has been registered as a signer for role
* @param account The address of account that authorized signing.
* @param signer The address of the signer.
* @param role The role that has been authorized.
*/
function isSigner(address account, address signer, bytes32 role) public view returns (bool) {
return
isLegacySigner(account, signer, role) ||
(signerAuthorizations[account][role][signer].completed && authorizedBy[signer] == account);
}
/**
* @notice Returns the account associated with `signer`.
* @param signer The address of an account or currently authorized validator signer.
* @dev Fails if the `signer` is not an account or currently authorized validator.
* @return The associated account that signer is authorized to validate for.
*/
function validatorSignerToAccount(address signer) public view returns (address) {
return signerToAccountWithRole(signer, ValidatorSigner);
}
/**
* @notice Returns the legacy signer for the specified account and
* role. If no signer has been specified it will return the account itself.
* @param _account The address of the account.
* @param role The role of the signer.
*/
function getLegacySigner(address _account, bytes32 role) public view returns (address) {
require(isLegacyRole(role), "Role is not a legacy signer");
Account storage account = accounts[_account];
address signer;
if (role == ValidatorSigner) {
signer = account.signers.validator;
} else if (role == AttestationSigner) {
signer = account.signers.attestation;
} else if (role == VoteSigner) {
signer = account.signers.vote;
}
return signer == address(0) ? _account : signer;
}
/**
* @notice Returns the default signer for the specified account and
* role. If no signer has been specified it will return the account itself.
* @param account The address of the account.
* @param role The role of the signer.
*/
function getDefaultSigner(address account, bytes32 role) public view returns (address) {
address defaultSigner = defaultSigners[account][role];
return defaultSigner == address(0) ? account : defaultSigner;
}
/**
* @notice Returns the indexed signer for the specified account and role.
* If no signer has been specified it will return the account itself.
* @param account The address of the account.
* @param role The role of the signer.
*/
function getIndexedSigner(address account, bytes32 role) public view returns (address) {
return isLegacyRole(role) ? getLegacySigner(account, role) : getDefaultSigner(account, role);
}
/**
* @notice Returns the vote signer for the specified account.
* @param account The address of the account.
* @return The address with which the account can sign votes.
*/
function getVoteSigner(address account) public view returns (address) {
return getLegacySigner(account, VoteSigner);
}
/**
* @notice Returns the validator signer for the specified account.
* @param account The address of the account.
* @return The address with which the account can register a validator or group.
*/
function getValidatorSigner(address account) public view returns (address) {
return getLegacySigner(account, ValidatorSigner);
}
/**
* @notice Returns the attestation signer for the specified account.
* @param account The address of the account.
* @return The address with which the account can sign attestations.
*/
function getAttestationSigner(address account) public view returns (address) {
return getLegacySigner(account, AttestationSigner);
}
/**
* @notice Checks whether or not the account has an indexed signer
* registered for one of the legacy roles
*/
function hasLegacySigner(address account, bytes32 role) public view returns (bool) {
return getLegacySigner(account, role) != account;
}
/**
* @notice Checks whether or not the account has an indexed signer
* registered for a role
*/
function hasDefaultSigner(address account, bytes32 role) public view returns (bool) {
return getDefaultSigner(account, role) != account;
}
/**
* @notice Checks whether or not the account has an indexed signer
* registered for the role
*/
function hasIndexedSigner(address account, bytes32 role) public view returns (bool) {
return isLegacyRole(role) ? hasLegacySigner(account, role) : hasDefaultSigner(account, role);
}
/**
* @notice Check if an account already exists.
* @param account The address of the account
* @return Returns `true` if account exists. Returns `false` otherwise.
*/
function isAccount(address account) public view returns (bool) {
return (accounts[account].exists);
}
/**
* @notice Returns the address that signed the provided role authorization.
* @param account The `account` property signed over in the EIP712 signature
* @param signer The `signer` property signed over in the EIP712 signature
* @param role The `role` property signed over in the EIP712 signature
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
* @return The address that signed the provided role authorization.
*/
function getRoleAuthorizationSigner(
address account,
address signer,
bytes32 role,
uint8 v,
bytes32 r,
bytes32 s
) public view returns (address) {
bytes32 structHash = keccak256(
abi.encode(EIP712_AUTHORIZE_SIGNER_TYPEHASH, account, signer, role)
);
return Signatures.getSignerOfTypedDataHash(eip712DomainSeparator, structHash, v, r, s);
}
/**
* @notice Checks whether the role is one of Vote, Validator or Attestation
* @param role The role to check
*/
function isLegacyRole(bytes32 role) public pure returns (bool) {
return role == VoteSigner || role == ValidatorSigner || role == AttestationSigner;
}
/**
* @notice Sets the EIP712 domain separator for the Celo Accounts abstraction.
*/
function _setEip712DomainSeparator() internal {
uint256 chainId;
assembly {
chainId := chainid
}
eip712DomainSeparator = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes("Celo Core Contracts")),
keccak256("1.0"),
chainId,
address(this)
)
);
}
/**
* @notice Check if an account already exists.
* @param account The address of the account
* @return Returns `false` if account exists. Returns `true` otherwise.
*/
function isNotAccount(address account) internal view returns (bool) {
return (!accounts[account].exists);
}
/**
* @notice Check if an address has not been an authorized signer for an account.
* @param signer The possibly authorized address.
* @return Returns `false` if authorized. Returns `true` otherwise.
*/
function isNotAuthorizedSigner(address signer) internal view returns (bool) {
return (authorizedBy[signer] == address(0));
}
/**
* @notice Check if `signer` has not been authorized, and if it has been previously
* authorized that it was authorized by `account`.
* @param account The authorizing account address.
* @param signer The possibly authorized address.
* @return Returns `false` if authorized. Returns `true` otherwise.
*/
function isNotAuthorizedSignerForAnotherAccount(
address account,
address signer
) internal view returns (bool) {
return (authorizedBy[signer] == address(0) || authorizedBy[signer] == account);
}
function signerToAccountWithRole(address signer, bytes32 role) internal view returns (address) {
address account = authorizedBy[signer];
if (account != address(0)) {
require(isSigner(account, signer, role), "not active authorized signer for role");
return account;
}
require(isAccount(signer), "Must first register address with Account.createAccount");
return signer;
}
function legacyAuthorizeSignerWithSignature(
address signer,
bytes32 role,
uint8 v,
bytes32 r,
bytes32 s
) private {
authorizeAddress(signer, v, r, s);
signerAuthorizations[msg.sender][role][signer] = SignerAuthorization({
started: true,
completed: true
});
emit SignerAuthorized(msg.sender, signer, role);
}
/**
* @notice Remove one of the Validator, Attestation or
* Vote signers from an account. Should only be called from
* methods that check the role is a legacy signer.
* @param role The role that has been authorized.
*/
function removeLegacySigner(bytes32 role) private {
Account storage account = accounts[msg.sender];
address signer;
if (role == ValidatorSigner) {
signer = account.signers.validator;
account.signers.validator = address(0);
} else if (role == AttestationSigner) {
signer = account.signers.attestation;
account.signers.attestation = address(0);
} else if (role == VoteSigner) {
signer = account.signers.vote;
account.signers.vote = address(0);
}
emit LegacySignerRemoved(msg.sender, signer, role);
}
/**
* @notice Authorizes some role of `msg.sender`'s account to another address.
* @param authorized The address to authorize.
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
* @dev Fails if the address is already authorized to another account or is an account itself.
* @dev Note that once an address is authorized, it may never be authorized again.
* @dev v, r, s constitute `authorized`'s signature on `msg.sender`.
*/
function authorizeAddress(address authorized, uint8 v, bytes32 r, bytes32 s) private {
address signer = Signatures.getSignerOfAddress(msg.sender, v, r, s);
require(signer == authorized, "Invalid signature");
authorize(authorized);
}
/**
* @notice Authorizes a role of `msg.sender`'s account to another address (`authorized`).
* @param authorized The address to authorize.
* @param role The role to authorize.
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
* @dev Fails if the address is already authorized to another account or is an account itself.
* @dev Note that this signature is EIP712 compliant over the authorizing `account`
* (`msg.sender`), `signer` (`authorized`) and `role`.
*/
function authorizeAddressWithRole(
address authorized,
bytes32 role,
uint8 v,
bytes32 r,
bytes32 s
) private {
address signer = getRoleAuthorizationSigner(msg.sender, authorized, role, v, r, s);
require(signer == authorized, "Invalid signature");
authorize(authorized);
}
/**
* @notice Authorizes an address to `msg.sender`'s account
* @param authorized The address to authorize.
* @dev Fails if the address is already authorized for another account or is an account itself.
*/
function authorize(address authorized) private {
require(
isAccount(msg.sender),
"Unknown account: sender must register with createAccount first"
);
require(
isNotAccount(authorized) && isNotAuthorizedSignerForAnotherAccount(msg.sender, authorized),
"Cannot re-authorize address or locked gold account for another account"
);
authorizedBy[authorized] = msg.sender;
}
}pragma solidity ^0.5.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
contract Context {
// Empty internal constructor, to prevent people from mistakenly deploying
// an instance of this contract, which should be used via inheritance.
constructor () internal { }
// solhint-disable-previous-line no-empty-blocks
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}pragma solidity ^0.5.0;
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* NOTE: This call _does not revert_ if the signature is invalid, or
* if the signer is otherwise unable to be retrieved. In those scenarios,
* the zero address is returned.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
// Check the signature length
if (signature.length != 65) {
return (address(0));
}
// Divide the signature in r, s and v variables
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
// solhint-disable-next-line no-inline-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return address(0);
}
if (v != 27 && v != 28) {
return address(0);
}
// If the signature is valid (and not malleable), return the signer address
return ecrecover(hash, v, r, s);
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* replicates the behavior of the
* https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]
* JSON-RPC method.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
}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) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* _Available since v2.4.0._
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
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-contracts/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) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message 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.
*
* _Available since v2.4.0._
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @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) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message 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.
*
* _Available since v2.4.0._
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}pragma solidity ^0.5.0;
import "../GSN/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}pragma solidity ^0.5.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see {ERC20Detailed}.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
/**
* @title FixidityLib
* @author Gadi Guy, Alberto Cuesta Canada
* @notice This library provides fixed point arithmetic with protection against
* overflow.
* All operations are done with uint256 and the operands must have been created
* with any of the newFrom* functions, which shift the comma digits() to the
* right and check for limits, or with wrap() which expects a number already
* in the internal representation of a fraction.
* When using this library be sure to use maxNewFixed() as the upper limit for
* creation of fixed point numbers.
* @dev All contained functions are pure and thus marked internal to be inlined
* on consuming contracts at compile time for gas efficiency.
*/
library FixidityLib {
struct Fraction {
uint256 value;
}
uint256 private constant FIXED1_UINT = 1000000000000000000000000;
/**
* @notice Number of positions that the comma is shifted to the right.
*/
function digits() internal pure returns (uint8) {
return 24;
}
/**
* @notice This is 1 in the fixed point units used in this library.
* @dev Test fixed1() equals 10^digits()
* Hardcoded to 24 digits.
*/
function fixed1() internal pure returns (Fraction memory) {
return Fraction(FIXED1_UINT);
}
/**
* @notice Wrap a uint256 that represents a 24-decimal fraction in a Fraction
* struct.
* @param x Number that already represents a 24-decimal fraction.
* @return A Fraction struct with contents x.
*/
function wrap(uint256 x) internal pure returns (Fraction memory) {
return Fraction(x);
}
/**
* @notice Unwraps the uint256 inside of a Fraction struct.
*/
function unwrap(Fraction memory x) internal pure returns (uint256) {
return x.value;
}
/**
* @notice The amount of decimals lost on each multiplication operand.
* @dev Test mulPrecision() equals sqrt(fixed1)
*/
function mulPrecision() internal pure returns (uint256) {
return 1000000000000;
}
/**
* @notice Maximum value that can be converted to fixed point. Optimize for deployment.
* @dev
* Test maxNewFixed() equals maxUint256() / fixed1()
*/
function maxNewFixed() internal pure returns (uint256) {
return 115792089237316195423570985008687907853269984665640564;
}
/**
* @notice Converts a uint256 to fixed point Fraction
* @dev Test newFixed(0) returns 0
* Test newFixed(1) returns fixed1()
* Test newFixed(maxNewFixed()) returns maxNewFixed() * fixed1()
* Test newFixed(maxNewFixed()+1) fails
*/
function newFixed(uint256 x) internal pure returns (Fraction memory) {
require(x <= maxNewFixed(), "can't create fixidity number larger than maxNewFixed()");
return Fraction(x * FIXED1_UINT);
}
/**
* @notice Converts a uint256 in the fixed point representation of this
* library to a non decimal. All decimal digits will be truncated.
*/
function fromFixed(Fraction memory x) internal pure returns (uint256) {
return x.value / FIXED1_UINT;
}
/**
* @notice Converts two uint256 representing a fraction to fixed point units,
* equivalent to multiplying dividend and divisor by 10^digits().
* @param numerator numerator must be <= maxNewFixed()
* @param denominator denominator must be <= maxNewFixed() and denominator can't be 0
* @dev
* Test newFixedFraction(1,0) fails
* Test newFixedFraction(0,1) returns 0
* Test newFixedFraction(1,1) returns fixed1()
* Test newFixedFraction(1,fixed1()) returns 1
*/
function newFixedFraction(
uint256 numerator,
uint256 denominator
) internal pure returns (Fraction memory) {
Fraction memory convertedNumerator = newFixed(numerator);
Fraction memory convertedDenominator = newFixed(denominator);
return divide(convertedNumerator, convertedDenominator);
}
/**
* @notice Returns the integer part of a fixed point number.
* @dev
* Test integer(0) returns 0
* Test integer(fixed1()) returns fixed1()
* Test integer(newFixed(maxNewFixed())) returns maxNewFixed()*fixed1()
*/
function integer(Fraction memory x) internal pure returns (Fraction memory) {
return Fraction((x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow
}
/**
* @notice Returns the fractional part of a fixed point number.
* In the case of a negative number the fractional is also negative.
* @dev
* Test fractional(0) returns 0
* Test fractional(fixed1()) returns 0
* Test fractional(fixed1()-1) returns 10^24-1
*/
function fractional(Fraction memory x) internal pure returns (Fraction memory) {
return Fraction(x.value - (x.value / FIXED1_UINT) * FIXED1_UINT); // Can't overflow
}
/**
* @notice x+y.
* @dev The maximum value that can be safely used as an addition operator is defined as
* maxFixedAdd = maxUint256()-1 / 2, or
* 57896044618658097711785492504343953926634992332820282019728792003956564819967.
* Test add(maxFixedAdd,maxFixedAdd) equals maxFixedAdd + maxFixedAdd
* Test add(maxFixedAdd+1,maxFixedAdd+1) throws
*/
function add(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
uint256 z = x.value + y.value;
require(z >= x.value, "add overflow detected");
return Fraction(z);
}
/**
* @notice x-y.
* @dev
* Test subtract(6, 10) fails
*/
function subtract(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
require(x.value >= y.value, "substraction underflow detected");
return Fraction(x.value - y.value);
}
/**
* @notice x*y. If any of the operators is higher than the max multiplier value it
* might overflow.
* @dev The maximum value that can be safely used as a multiplication operator
* (maxFixedMul) is calculated as sqrt(maxUint256()*fixed1()),
* or 340282366920938463463374607431768211455999999999999
* Test multiply(0,0) returns 0
* Test multiply(maxFixedMul,0) returns 0
* Test multiply(0,maxFixedMul) returns 0
* Test multiply(fixed1()/mulPrecision(),fixed1()*mulPrecision()) returns fixed1()
* Test multiply(maxFixedMul,maxFixedMul) is around maxUint256()
* Test multiply(maxFixedMul+1,maxFixedMul+1) fails
*/
function multiply(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
if (x.value == 0 || y.value == 0) return Fraction(0);
if (y.value == FIXED1_UINT) return x;
if (x.value == FIXED1_UINT) return y;
// Separate into integer and fractional parts
// x = x1 + x2, y = y1 + y2
uint256 x1 = integer(x).value / FIXED1_UINT;
uint256 x2 = fractional(x).value;
uint256 y1 = integer(y).value / FIXED1_UINT;
uint256 y2 = fractional(y).value;
// (x1 + x2) * (y1 + y2) = (x1 * y1) + (x1 * y2) + (x2 * y1) + (x2 * y2)
uint256 x1y1 = x1 * y1;
if (x1 != 0) require(x1y1 / x1 == y1, "overflow x1y1 detected");
// x1y1 needs to be multiplied back by fixed1
// solium-disable-next-line mixedcase
uint256 fixed_x1y1 = x1y1 * FIXED1_UINT;
if (x1y1 != 0) require(fixed_x1y1 / x1y1 == FIXED1_UINT, "overflow x1y1 * fixed1 detected");
x1y1 = fixed_x1y1;
uint256 x2y1 = x2 * y1;
if (x2 != 0) require(x2y1 / x2 == y1, "overflow x2y1 detected");
uint256 x1y2 = x1 * y2;
if (x1 != 0) require(x1y2 / x1 == y2, "overflow x1y2 detected");
x2 = x2 / mulPrecision();
y2 = y2 / mulPrecision();
uint256 x2y2 = x2 * y2;
if (x2 != 0) require(x2y2 / x2 == y2, "overflow x2y2 detected");
// result = fixed1() * x1 * y1 + x1 * y2 + x2 * y1 + x2 * y2 / fixed1();
Fraction memory result = Fraction(x1y1);
result = add(result, Fraction(x2y1)); // Add checks for overflow
result = add(result, Fraction(x1y2)); // Add checks for overflow
result = add(result, Fraction(x2y2)); // Add checks for overflow
return result;
}
/**
* @notice 1/x
* @dev
* Test reciprocal(0) fails
* Test reciprocal(fixed1()) returns fixed1()
* Test reciprocal(fixed1()*fixed1()) returns 1 // Testing how the fractional is truncated
* Test reciprocal(1+fixed1()*fixed1()) returns 0 // Testing how the fractional is truncated
* Test reciprocal(newFixedFraction(1, 1e24)) returns newFixed(1e24)
*/
function reciprocal(Fraction memory x) internal pure returns (Fraction memory) {
require(x.value != 0, "can't call reciprocal(0)");
return Fraction((FIXED1_UINT * FIXED1_UINT) / x.value); // Can't overflow
}
/**
* @notice x/y. If the dividend is higher than the max dividend value, it
* might overflow. You can use multiply(x,reciprocal(y)) instead.
* @dev The maximum value that can be safely used as a dividend (maxNewFixed) is defined as
* divide(maxNewFixed,newFixedFraction(1,fixed1())) is around maxUint256().
* This yields the value 115792089237316195423570985008687907853269984665640564.
* Test maxNewFixed equals maxUint256()/fixed1()
* Test divide(maxNewFixed,1) equals maxNewFixed*(fixed1)
* Test divide(maxNewFixed+1,multiply(mulPrecision(),mulPrecision())) throws
* Test divide(fixed1(),0) fails
* Test divide(maxNewFixed,1) = maxNewFixed*(10^digits())
* Test divide(maxNewFixed+1,1) throws
*/
function divide(Fraction memory x, Fraction memory y) internal pure returns (Fraction memory) {
require(y.value != 0, "can't divide by 0");
uint256 X = x.value * FIXED1_UINT;
require(X / FIXED1_UINT == x.value, "overflow at divide");
return Fraction(X / y.value);
}
/**
* @notice x > y
*/
function gt(Fraction memory x, Fraction memory y) internal pure returns (bool) {
return x.value > y.value;
}
/**
* @notice x >= y
*/
function gte(Fraction memory x, Fraction memory y) internal pure returns (bool) {
return x.value >= y.value;
}
/**
* @notice x < y
*/
function lt(Fraction memory x, Fraction memory y) internal pure returns (bool) {
return x.value < y.value;
}
/**
* @notice x <= y
*/
function lte(Fraction memory x, Fraction memory y) internal pure returns (bool) {
return x.value <= y.value;
}
/**
* @notice x == y
*/
function equals(Fraction memory x, Fraction memory y) internal pure returns (bool) {
return x.value == y.value;
}
/**
* @notice x <= 1
*/
function isProperFraction(Fraction memory x) internal pure returns (bool) {
return lte(x, fixed1());
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
/**
* @title Used with proxied contracts that have an `initialize` function.
* @notice Ensures the `initialize` function:
* - gets called only once
* - cannot be called on the logic contract.
*/
contract Initializable {
bool public initialized;
/**
* @notice Ensures the initializer function cannot be called more than once.
*/
modifier initializer() {
require(!initialized, "contract already initialized");
initialized = true;
_;
}
/**
* @notice By default, ensures that the `initialize` function cannot be called
* on the logic contract.
* @param testingDeployment When set to true, allows the `initialize` function
* to be called, which is useful in testing when not setting up with a Proxy.
*/
constructor(bool testingDeployment) public {
if (!testingDeployment) {
initialized = true;
}
}
}pragma solidity ^0.5.13;
import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol";
library Signatures {
/**
* @notice Given a signed address, returns the signer of the address.
* @param message The address that was signed.
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
*/
function getSignerOfAddress(
address message,
uint8 v,
bytes32 r,
bytes32 s
) public pure returns (address) {
bytes32 hash = keccak256(abi.encodePacked(message));
return getSignerOfMessageHash(hash, v, r, s);
}
/**
* @notice Given a message hash, returns the signer of the address.
* @param messageHash The hash of a message.
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
*/
function getSignerOfMessageHash(
bytes32 messageHash,
uint8 v,
bytes32 r,
bytes32 s
) public pure returns (address) {
bytes memory signature = new bytes(65);
// Concatenate (r, s, v) into signature.
assembly {
mstore(add(signature, 32), r)
mstore(add(signature, 64), s)
mstore8(add(signature, 96), v)
}
bytes32 prefixedHash = ECDSA.toEthSignedMessageHash(messageHash);
return ECDSA.recover(prefixedHash, signature);
}
/**
* @notice Given a domain separator and a structHash, construct the typed data hash
* @param eip712DomainSeparator Context specific domain separator
* @param structHash hash of the typed data struct
* @return The EIP712 typed data hash
*/
function toEthSignedTypedDataHash(
bytes32 eip712DomainSeparator,
bytes32 structHash
) public pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", eip712DomainSeparator, structHash));
}
/**
* @notice Given a domain separator and a structHash and a signature return the signer
* @param eip712DomainSeparator Context specific domain separator
* @param structHash hash of the typed data struct
* @param v The recovery id of the incoming ECDSA signature.
* @param r Output value r of the ECDSA signature.
* @param s Output value s of the ECDSA signature.
*/
function getSignerOfTypedDataHash(
bytes32 eip712DomainSeparator,
bytes32 structHash,
uint8 v,
bytes32 r,
bytes32 s
) public pure returns (address) {
bytes memory signature = new bytes(65);
// Concatenate (r, s, v) into signature.
assembly {
mstore(add(signature, 32), r)
mstore(add(signature, 64), s)
mstore8(add(signature, 96), v)
}
bytes32 prefixedHash = toEthSignedTypedDataHash(eip712DomainSeparator, structHash);
return ECDSA.recover(prefixedHash, signature);
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.5.13;
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "./interfaces/IAccounts.sol";
import "./interfaces/IEpochManager.sol";
import "./interfaces/IFeeCurrencyWhitelist.sol";
import "./interfaces/IFreezer.sol";
import "./interfaces/IRegistry.sol";
import "./interfaces/ICeloUnreleasedTreasury.sol";
import "../governance/interfaces/IElection.sol";
import "../governance/interfaces/IEpochRewards.sol";
import "../governance/interfaces/IGovernance.sol";
import "../governance/interfaces/ILockedGold.sol";
import "../governance/interfaces/ILockedCelo.sol";
import "../governance/interfaces/IValidators.sol";
import "../identity/interfaces/IRandom.sol";
import "../identity/interfaces/IAttestations.sol";
import "../../lib/mento-core/contracts/interfaces/IExchange.sol";
import "../../lib/mento-core/contracts/interfaces/IReserve.sol";
import "../../lib/mento-core/contracts/interfaces/IStableToken.sol";
import "../stability/interfaces/ISortedOracles.sol";
contract UsingRegistry is Ownable {
// solhint-disable state-visibility
bytes32 constant ACCOUNTS_REGISTRY_ID = keccak256(abi.encodePacked("Accounts"));
bytes32 constant ATTESTATIONS_REGISTRY_ID = keccak256(abi.encodePacked("Attestations"));
bytes32 constant DOWNTIME_SLASHER_REGISTRY_ID = keccak256(abi.encodePacked("DowntimeSlasher"));
bytes32 constant DOUBLE_SIGNING_SLASHER_REGISTRY_ID =
keccak256(abi.encodePacked("DoubleSigningSlasher"));
bytes32 constant ELECTION_REGISTRY_ID = keccak256(abi.encodePacked("Election"));
bytes32 constant EXCHANGE_REGISTRY_ID = keccak256(abi.encodePacked("Exchange"));
bytes32 constant FEE_CURRENCY_WHITELIST_REGISTRY_ID =
keccak256(abi.encodePacked("FeeCurrencyWhitelist"));
bytes32 constant FREEZER_REGISTRY_ID = keccak256(abi.encodePacked("Freezer"));
bytes32 constant GOLD_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("GoldToken"));
bytes32 constant GOVERNANCE_REGISTRY_ID = keccak256(abi.encodePacked("Governance"));
bytes32 constant GOVERNANCE_SLASHER_REGISTRY_ID =
keccak256(abi.encodePacked("GovernanceSlasher"));
bytes32 constant LOCKED_GOLD_REGISTRY_ID = keccak256(abi.encodePacked("LockedGold"));
bytes32 constant RESERVE_REGISTRY_ID = keccak256(abi.encodePacked("Reserve"));
bytes32 constant RANDOM_REGISTRY_ID = keccak256(abi.encodePacked("Random"));
bytes32 constant SORTED_ORACLES_REGISTRY_ID = keccak256(abi.encodePacked("SortedOracles"));
bytes32 constant STABLE_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("StableToken"));
bytes32 constant VALIDATORS_REGISTRY_ID = keccak256(abi.encodePacked("Validators"));
bytes32 constant CELO_TOKEN_REGISTRY_ID = keccak256(abi.encodePacked("CeloToken"));
bytes32 constant LOCKED_CELO_REGISTRY_ID = keccak256(abi.encodePacked("LockedCelo"));
bytes32 constant CELO_UNRELEASED_TREASURY_REGISTRY_ID =
keccak256(abi.encodePacked("CeloUnreleasedTreasury"));
bytes32 constant EPOCH_REWARDS_REGISTRY_ID = keccak256(abi.encodePacked("EpochRewards"));
bytes32 constant EPOCH_MANAGER_ENABLER_REGISTRY_ID =
keccak256(abi.encodePacked("EpochManagerEnabler"));
bytes32 constant EPOCH_MANAGER_REGISTRY_ID = keccak256(abi.encodePacked("EpochManager"));
// solhint-enable state-visibility
IRegistry public registry;
event RegistrySet(address indexed registryAddress);
modifier onlyRegisteredContract(bytes32 identifierHash) {
require(registry.getAddressForOrDie(identifierHash) == msg.sender, "only registered contract");
_;
}
modifier onlyRegisteredContracts(bytes32[] memory identifierHashes) {
require(registry.isOneOf(identifierHashes, msg.sender), "only registered contracts");
_;
}
/**
* @notice Updates the address pointing to a Registry contract.
* @param registryAddress The address of a registry contract for routing to other contracts.
*/
function setRegistry(address registryAddress) public onlyOwner {
require(registryAddress != address(0), "Cannot register the null address");
registry = IRegistry(registryAddress);
emit RegistrySet(registryAddress);
}
function getAccounts() internal view returns (IAccounts) {
return IAccounts(registry.getAddressForOrDie(ACCOUNTS_REGISTRY_ID));
}
function getAttestations() internal view returns (IAttestations) {
return IAttestations(registry.getAddressForOrDie(ATTESTATIONS_REGISTRY_ID));
}
function getElection() internal view returns (IElection) {
return IElection(registry.getAddressForOrDie(ELECTION_REGISTRY_ID));
}
function getExchange() internal view returns (IExchange) {
return IExchange(registry.getAddressForOrDie(EXCHANGE_REGISTRY_ID));
}
function getFeeCurrencyWhitelistRegistry() internal view returns (IFeeCurrencyWhitelist) {
return IFeeCurrencyWhitelist(registry.getAddressForOrDie(FEE_CURRENCY_WHITELIST_REGISTRY_ID));
}
function getFreezer() internal view returns (IFreezer) {
return IFreezer(registry.getAddressForOrDie(FREEZER_REGISTRY_ID));
}
function getGoldToken() internal view returns (IERC20) {
return IERC20(registry.getAddressForOrDie(GOLD_TOKEN_REGISTRY_ID));
}
function getCeloToken() internal view returns (IERC20) {
return IERC20(registry.getAddressForOrDie(CELO_TOKEN_REGISTRY_ID));
}
function getGovernance() internal view returns (IGovernance) {
return IGovernance(registry.getAddressForOrDie(GOVERNANCE_REGISTRY_ID));
}
function getLockedGold() internal view returns (ILockedGold) {
return ILockedGold(registry.getAddressForOrDie(LOCKED_GOLD_REGISTRY_ID));
}
function getLockedCelo() internal view returns (ILockedCelo) {
return ILockedCelo(registry.getAddressForOrDie(LOCKED_CELO_REGISTRY_ID));
}
function getRandom() internal view returns (IRandom) {
return IRandom(registry.getAddressForOrDie(RANDOM_REGISTRY_ID));
}
function getReserve() internal view returns (IReserve) {
return IReserve(registry.getAddressForOrDie(RESERVE_REGISTRY_ID));
}
function getSortedOracles() internal view returns (ISortedOracles) {
return ISortedOracles(registry.getAddressForOrDie(SORTED_ORACLES_REGISTRY_ID));
}
function getStableToken() internal view returns (IStableToken) {
return IStableToken(registry.getAddressForOrDie(STABLE_TOKEN_REGISTRY_ID));
}
function getValidators() internal view returns (IValidators) {
return IValidators(registry.getAddressForOrDie(VALIDATORS_REGISTRY_ID));
}
function getCeloUnreleasedTreasury() internal view returns (ICeloUnreleasedTreasury) {
return
ICeloUnreleasedTreasury(registry.getAddressForOrDie(CELO_UNRELEASED_TREASURY_REGISTRY_ID));
}
function getEpochRewards() internal view returns (IEpochRewards) {
return IEpochRewards(registry.getAddressForOrDie(EPOCH_REWARDS_REGISTRY_ID));
}
function getEpochManager() internal view returns (IEpochManager) {
return IEpochManager(registry.getAddressForOrDie(EPOCH_MANAGER_REGISTRY_ID));
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IAccounts {
function setAccountDataEncryptionKey(bytes calldata) external;
function setMetadataURL(string calldata) external;
function setName(string calldata) external;
function setWalletAddress(address, uint8, bytes32, bytes32) external;
function setAccount(string calldata, bytes calldata, address, uint8, bytes32, bytes32) external;
function authorizeVoteSigner(address, uint8, bytes32, bytes32) external;
function authorizeValidatorSigner(address, uint8, bytes32, bytes32) external;
function authorizeValidatorSignerWithPublicKey(
address,
uint8,
bytes32,
bytes32,
bytes calldata
) external;
function authorizeAttestationSigner(address, uint8, bytes32, bytes32) external;
function setEip712DomainSeparator() external;
function createAccount() external returns (bool);
function setPaymentDelegation(address, uint256) external;
function isAccount(address) external view returns (bool);
function voteSignerToAccount(address) external view returns (address);
function validatorSignerToAccount(address) external view returns (address);
function attestationSignerToAccount(address) external view returns (address);
function signerToAccount(address) external view returns (address);
function getAttestationSigner(address) external view returns (address);
function getValidatorSigner(address) external view returns (address);
function getVoteSigner(address) external view returns (address);
function hasAuthorizedVoteSigner(address) external view returns (bool);
function hasAuthorizedValidatorSigner(address) external view returns (bool);
function hasAuthorizedAttestationSigner(address) external view returns (bool);
function batchGetMetadataURL(
address[] calldata
) external view returns (uint256[] memory, bytes memory);
function getDataEncryptionKey(address) external view returns (bytes memory);
function getWalletAddress(address) external view returns (address);
function getMetadataURL(address) external view returns (string memory);
function getName(address) external view returns (string memory);
function getPaymentDelegation(address) external view returns (address, uint256);
function isSigner(address, address, bytes32) external view returns (bool);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface ICeloUnreleasedTreasury {
/**
* @notice Releases the Celo to the specified address.
* @param to The address to release the amount to.
* @param amount The amount to release.
*/
function release(address to, uint256 amount) external;
function getRemainingBalanceToRelease() external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface ILockedGold {
function lock() external payable;
function incrementNonvotingAccountBalance(address, uint256) external;
function decrementNonvotingAccountBalance(address, uint256) external;
function unlock(uint256) external;
function relock(uint256, uint256) external;
function withdraw(uint256) external;
function slash(
address account,
uint256 penalty,
address reporter,
uint256 reward,
address[] calldata lessers,
address[] calldata greaters,
uint256[] calldata indices
) external;
function addSlasher(string calldata slasherIdentifier) external;
function getAccountTotalLockedGold(address) external view returns (uint256);
function getTotalLockedGold() external view returns (uint256);
function getPendingWithdrawals(
address
) external view returns (uint256[] memory, uint256[] memory);
function getPendingWithdrawal(
address account,
uint256 index
) external view returns (uint256, uint256);
function getTotalPendingWithdrawals(address) external view returns (uint256);
function isSlasher(address) external view returns (bool);
function getAccountTotalDelegatedFraction(address account) external view returns (uint256);
function getAccountTotalGovernanceVotingPower(address account) external view returns (uint256);
function unlockingPeriod() external view returns (uint256);
function getAccountNonvotingLockedGold(address account) external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IValidators {
function registerValidator(bytes calldata) external returns (bool);
function registerValidatorNoBls(bytes calldata ecdsaPublicKey) external returns (bool);
function deregisterValidator(uint256) external returns (bool);
function affiliate(address) external returns (bool);
function deaffiliate() external returns (bool);
function registerValidatorGroup(uint256) external returns (bool);
function deregisterValidatorGroup(uint256) external returns (bool);
function addMember(address) external returns (bool);
function addFirstMember(address, address, address) external returns (bool);
function removeMember(address) external returns (bool);
function reorderMember(address, address, address) external returns (bool);
function updateCommission() external;
function setNextCommissionUpdate(uint256) external;
function resetSlashingMultiplier() external;
// only owner
function setCommissionUpdateDelay(uint256) external;
function setMaxGroupSize(uint256) external returns (bool);
function setMembershipHistoryLength(uint256) external returns (bool);
function setGroupLockedGoldRequirements(uint256, uint256) external returns (bool);
function setValidatorLockedGoldRequirements(uint256, uint256) external returns (bool);
function setSlashingMultiplierResetPeriod(uint256) external;
// only registered contract
function updateEcdsaPublicKey(address, address, bytes calldata) external returns (bool);
function mintStableToEpochManager(uint256 amount) external;
// only slasher
function forceDeaffiliateIfValidator(address) external;
function halveSlashingMultiplier(address) external;
// view functions
function maxGroupSize() external view returns (uint256);
function getCommissionUpdateDelay() external view returns (uint256);
function getMembershipHistory(
address
) external view returns (uint256[] memory, address[] memory, uint256, uint256);
function getAccountLockedGoldRequirement(address) external view returns (uint256);
function meetsAccountLockedGoldRequirements(address) external view returns (bool);
function getValidator(
address account
) external view returns (bytes memory, bytes memory, address, uint256, address);
function getValidatorsGroup(address account) external view returns (address affiliation);
function getValidatorGroup(
address
)
external
view
returns (address[] memory, uint256, uint256, uint256, uint256[] memory, uint256, uint256);
function getGroupNumMembers(address) external view returns (uint256);
function getTopGroupValidators(address, uint256) external view returns (address[] memory);
function getTopGroupValidatorsAccounts(address, uint256) external view returns (address[] memory);
function getGroupsNumMembers(
address[] calldata accounts
) external view returns (uint256[] memory);
function getNumRegisteredValidators() external view returns (uint256);
function groupMembershipInEpoch(address, uint256, uint256) external view returns (address);
function getValidatorLockedGoldRequirements() external view returns (uint256, uint256);
function getGroupLockedGoldRequirements() external view returns (uint256, uint256);
function getRegisteredValidators() external view returns (address[] memory);
function getRegisteredValidatorGroups() external view returns (address[] memory);
function isValidatorGroup(address) external view returns (bool);
function isValidator(address) external view returns (bool);
function getValidatorGroupSlashingMultiplier(address) external view returns (uint256);
function getMembershipInLastEpoch(address) external view returns (address);
function getMembershipInLastEpochFromSigner(address) external view returns (address);
function computeEpochReward(
address account,
uint256 score,
uint256 maxPayment
) external view returns (uint256);
function getMembershipHistoryLength() external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IAttestations {
function revoke(bytes32, uint256) external;
function withdraw(address) external;
// only owner
function setAttestationRequestFee(address, uint256) external;
function setAttestationExpiryBlocks(uint256) external;
function setSelectIssuersWaitBlocks(uint256) external;
function setMaxAttestations(uint256) external;
// view functions
function getUnselectedRequest(bytes32, address) external view returns (uint32, uint32, address);
function getAttestationIssuers(bytes32, address) external view returns (address[] memory);
function getAttestationStats(bytes32, address) external view returns (uint32, uint32);
function batchGetAttestationStats(
bytes32[] calldata
) external view returns (uint256[] memory, address[] memory, uint64[] memory, uint64[] memory);
function getAttestationState(
bytes32,
address,
address
) external view returns (uint8, uint32, address);
function getCompletableAttestations(
bytes32,
address
) external view returns (uint32[] memory, address[] memory, uint256[] memory, bytes memory);
function getAttestationRequestFee(address) external view returns (uint256);
function getMaxAttestations() external view returns (uint256);
function validateAttestationCode(
bytes32,
address,
uint8,
bytes32,
bytes32
) external view returns (address);
function lookupAccountsForIdentifier(bytes32) external view returns (address[] memory);
function requireNAttestationsRequested(bytes32, address, uint32) external view;
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IRandom {
function revealAndCommit(bytes32, bytes32, address) external;
function randomnessBlockRetentionWindow() external view returns (uint256);
function random() external view returns (bytes32);
function getBlockRandomness(uint256) external view returns (bytes32);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface ISortedOracles {
function addOracle(address, address) external;
function removeOracle(address, address, uint256) external;
function report(address, uint256, address, address) external;
function removeExpiredReports(address, uint256) external;
function isOldestReportExpired(address token) external view returns (bool, address);
function numRates(address) external view returns (uint256);
function medianRate(address) external view returns (uint256, uint256);
function numTimestamps(address) external view returns (uint256);
function medianTimestamp(address) external view returns (uint256);
}pragma solidity ^0.5.13;
interface IExchange {
function buy(
uint256,
uint256,
bool
) external returns (uint256);
function sell(
uint256,
uint256,
bool
) external returns (uint256);
function exchange(
uint256,
uint256,
bool
) external returns (uint256);
function setUpdateFrequency(uint256) external;
function getBuyTokenAmount(uint256, bool) external view returns (uint256);
function getSellTokenAmount(uint256, bool) external view returns (uint256);
function getBuyAndSellBuckets(bool) external view returns (uint256, uint256);
}pragma solidity ^0.5.13;
interface IReserve {
function setTobinTaxStalenessThreshold(uint256) external;
function addToken(address) external returns (bool);
function removeToken(address, uint256) external returns (bool);
function transferGold(address payable, uint256) external returns (bool);
function transferExchangeGold(address payable, uint256) external returns (bool);
function getReserveGoldBalance() external view returns (uint256);
function getUnfrozenReserveGoldBalance() external view returns (uint256);
function getOrComputeTobinTax() external returns (uint256, uint256);
function getTokens() external view returns (address[] memory);
function getReserveRatio() external view returns (uint256);
function addExchangeSpender(address) external;
function removeExchangeSpender(address, uint256) external;
function addSpender(address) external;
function removeSpender(address) external;
}pragma solidity ^0.5.13;
/**
* @title This interface describes the functions specific to Celo Stable Tokens, and in the
* absence of interface inheritance is intended as a companion to IERC20.sol and ICeloToken.sol.
*/
interface IStableToken {
function mint(address, uint256) external returns (bool);
function burn(uint256) external returns (bool);
function setInflationParameters(uint256, uint256) external;
function valueToUnits(uint256) external view returns (uint256);
function unitsToValue(uint256) external view returns (uint256);
function getInflationParameters()
external
view
returns (
uint256,
uint256,
uint256,
uint256
);
// NOTE: duplicated with IERC20.sol, remove once interface inheritance is supported.
function balanceOf(address) external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface ICeloVersionedContract {
/**
* @notice Returns the storage, major, minor, and patch version of the contract.
* @return Storage version of the contract.
* @return Major version of the contract.
* @return Minor version of the contract.
* @return Patch version of the contract.
*/
function getVersionNumber() external pure returns (uint256, uint256, uint256, uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IEpochManager {
function initializeSystem(
uint256 firstEpochNumber,
uint256 firstEpochBlock,
address[] calldata firstElected
) external;
function startNextEpochProcess() external;
function finishNextEpochProcess(
address[] calldata groups,
address[] calldata lessers,
address[] calldata greaters
) external;
function setToProcessGroups() external;
function processGroup(address group, address lesser, address greater) external;
function sendValidatorPayment(address) external;
function getCurrentEpoch() external view returns (uint256, uint256, uint256, uint256);
function getEpochByNumber(
uint256 epochNumber
) external view returns (uint256, uint256, uint256, uint256);
function getEpochByBlockNumber(
uint256 blockNumber
) external view returns (uint256, uint256, uint256, uint256);
function getEpochNumberOfBlock(uint256) external view returns (uint256);
function getCurrentEpochNumber() external view returns (uint256);
function numberOfElectedInCurrentSet() external view returns (uint256);
function getElectedAccounts() external view returns (address[] memory);
function getElectedAccountByIndex(uint256 index) external view returns (address);
function getElectedSigners() external view returns (address[] memory);
function getElectedSignerByIndex(uint256 index) external view returns (address);
function epochDuration() external view returns (uint256);
function firstKnownEpoch() external view returns (uint256);
function getEpochProcessingState()
external
view
returns (uint256, uint256, uint256, uint256, uint256);
function systemAlreadyInitialized() external view returns (bool);
function isBlocked() external view returns (bool);
function isTimeForNextEpoch() external view returns (bool);
function isOnEpochProcess() external view returns (bool);
function getFirstBlockAtEpoch(uint256) external view returns (uint256);
function getLastBlockAtEpoch(uint256) external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IFeeCurrencyWhitelist {
function initialize() external;
function addToken(address) external;
function getWhitelist() external view returns (address[] memory);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IFreezer {
function freeze(address target) external;
function unfreeze(address target) external;
function isFrozen(address) external view returns (bool);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IRegistry {
function setAddressFor(string calldata, address) external;
function getAddressForOrDie(bytes32) external view returns (address);
function getAddressFor(bytes32) external view returns (address);
function getAddressForStringOrDie(string calldata identifier) external view returns (address);
function getAddressForString(string calldata identifier) external view returns (address);
function isOneOf(bytes32[] calldata, address) external view returns (bool);
}// SPDX-License-Identifier: LGPL-3.0-only pragma solidity >=0.5.13 <0.8.20; /** * @title Helps contracts guard against reentrancy attacks. * @author Remco Bloemen <remco@2π.com>, Eenae <[email protected]> * @dev If you mark a function `nonReentrant`, you should also * mark it `external`. */ contract ReentrancyGuard { /// @dev counter to allow mutex lock with only one SSTORE operation uint256 private _guardCounter; /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { _guardCounter += 1; uint256 localCounter = _guardCounter; _; require(localCounter == _guardCounter, "reentrant call"); } constructor() public { // The counter starts at one to prevent changing it from zero to a non-zero // value, which is a more expensive operation. _guardCounter = 1; } }
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IElection {
function vote(
address group,
uint256 value,
address lesser,
address greater
) external returns (bool);
function activate(address group) external returns (bool);
function revokeActive(
address group,
uint256 value,
address lesser,
address greater,
uint256 index
) external returns (bool);
function revokeAllActive(
address group,
address lesser,
address greater,
uint256 index
) external returns (bool);
function revokePending(
address group,
uint256 value,
address lesser,
address greater,
uint256 index
) external returns (bool);
function markGroupIneligible(address group) external;
function markGroupEligible(address group, address lesser, address greater) external;
function allowedToVoteOverMaxNumberOfGroups(address account) external returns (bool);
function forceDecrementVotes(
address account,
uint256 value,
address[] calldata lessers,
address[] calldata greaters,
uint256[] calldata indices
) external returns (uint256);
function setAllowedToVoteOverMaxNumberOfGroups(bool flag) external;
// only owner
function setElectableValidators(uint256 min, uint256 max) external returns (bool);
function setMaxNumGroupsVotedFor(uint256 _maxNumGroupsVotedFor) external returns (bool);
function setElectabilityThreshold(uint256 threshold) external returns (bool);
// only VM
function distributeEpochRewards(
address group,
uint256 value,
address lesser,
address greater
) external;
// view functions
function electValidatorSigners() external view returns (address[] memory);
function electValidatorAccounts() external view returns (address[] memory);
function electNValidatorSigners(
uint256 minElectableValidators,
uint256 maxElectableValidators
) external view returns (address[] memory);
function electNValidatorAccounts(
uint256 minElectableValidators,
uint256 maxElectableValidators
) external view returns (address[] memory);
function getElectableValidators() external view returns (uint256, uint256);
function getElectabilityThreshold() external view returns (uint256);
function getNumVotesReceivable(address group) external view returns (uint256);
function getTotalVotes() external view returns (uint256);
function getActiveVotes() external view returns (uint256);
function getTotalVotesByAccount(address account) external view returns (uint256);
function getPendingVotesForGroupByAccount(
address group,
address account
) external view returns (uint256);
function getActiveVotesForGroupByAccount(
address group,
address account
) external view returns (uint256);
function getTotalVotesForGroupByAccount(
address group,
address account
) external view returns (uint256);
function getActiveVoteUnitsForGroupByAccount(
address group,
address account
) external view returns (uint256);
function getTotalVotesForGroup(address group) external view returns (uint256);
function getActiveVotesForGroup(address group) external view returns (uint256);
function getPendingVotesForGroup(address group) external view returns (uint256);
function getGroupEligibility(address group) external view returns (bool);
function getGroupEpochRewardsBasedOnScore(
address group,
uint256 totalEpochRewards,
uint256 groupScore
) external view returns (uint256);
function getGroupsVotedForByAccount(address account) external view returns (address[] memory);
function getEligibleValidatorGroups() external view returns (address[] memory);
function getTotalVotesForEligibleValidatorGroups()
external
view
returns (address[] memory, uint256[] memory);
function getCurrentValidatorSigners() external view returns (address[] memory);
function canReceiveVotes(address group, uint256 value) external view returns (bool);
function hasActivatablePendingVotes(address account, address group) external view returns (bool);
function validatorSignerAddressFromCurrentSet(uint256 index) external view returns (address);
function numberValidatorsInCurrentSet() external view returns (uint256);
function owner() external view returns (address);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IEpochRewards {
function updateTargetVotingYield() external;
function calculateTargetEpochRewards() external view returns (uint256, uint256, uint256, uint256);
function getTargetVotingYieldParameters() external view returns (uint256, uint256, uint256);
function getRewardsMultiplierParameters() external view returns (uint256, uint256, uint256);
function getCommunityRewardFraction() external view returns (uint256);
function getCarbonOffsettingFraction() external view returns (uint256);
function getTargetVotingGoldFraction() external view returns (uint256);
function getRewardsMultiplier() external view returns (uint256);
function carbonOffsettingPartner() external view returns (address);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface IGovernance {
function removeVotesWhenRevokingDelegatedVotes(
address account,
uint256 maxAmountAllowed
) external;
function votePartially(
uint256 proposalId,
uint256 index,
uint256 yesVotes,
uint256 noVotes,
uint256 abstainVotes
) external returns (bool);
function setConstitution(address destination, bytes4 functionId, uint256 threshold) external;
function isVoting(address) external view returns (bool);
function getAmountOfGoldUsedForVoting(address account) external view returns (uint256);
function getProposal(
uint256 proposalId
) external view returns (address, uint256, uint256, uint256, string memory, uint256, bool);
function getReferendumStageDuration() external view returns (uint256);
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.5.13 <0.9.0;
interface ILockedCelo {
function lock() external payable;
function incrementNonvotingAccountBalance(address, uint256) external;
function decrementNonvotingAccountBalance(address, uint256) external;
function unlock(uint256) external;
function relock(uint256, uint256) external;
function withdraw(uint256) external;
function slash(
address account,
uint256 penalty,
address reporter,
uint256 reward,
address[] calldata lessers,
address[] calldata greaters,
uint256[] calldata indices
) external;
function addSlasher(string calldata slasherIdentifier) external;
function getAccountNonvotingLockedGold(address account) external view returns (uint256);
function getAccountTotalLockedCelo(address) external view returns (uint256);
function getTotalLockedCelo() external view returns (uint256);
function getPendingWithdrawals(
address
) external view returns (uint256[] memory, uint256[] memory);
function getPendingWithdrawal(
address account,
uint256 index
) external view returns (uint256, uint256);
function getTotalPendingWithdrawals(address) external view returns (uint256);
function isSlasher(address) external view returns (bool);
function getAccountTotalDelegatedFraction(address account) external view returns (uint256);
function getAccountTotalGovernanceVotingPower(address account) external view returns (uint256);
function unlockingPeriod() external view returns (uint256);
function getAccountNonvotingLockedCelo(address account) external view returns (uint256);
function getAccountTotalLockedGold(address account) external view returns (uint256);
}{
"metadata": {
"useLiteralContent": true
},
"optimizer": {
"runs": 200,
"enabled": false
},
"evmVersion": "istanbul",
"remappings": [],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"libraries": {
"project:/contracts/common/Accounts.sol": {
"Signatures": "0x69baecd458e7c08b13a18e11887dbb078fb3cbb4"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"bool","name":"test","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"AccountCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bytes","name":"dataEncryptionKey","type":"bytes"}],"name":"AccountDataEncryptionKeySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"string","name":"metadataURL","type":"string"}],"name":"AccountMetadataURLSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"AccountNameSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"walletAddress","type":"address"}],"name":"AccountWalletAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"AttestationSignerAuthorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"oldSigner","type":"address"}],"name":"AttestationSignerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"oldSigner","type":"address"},{"indexed":false,"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"DefaultSignerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"DefaultSignerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"oldSigner","type":"address"},{"indexed":false,"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"IndexedSignerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"IndexedSignerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"oldSigner","type":"address"},{"indexed":false,"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"LegacySignerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"},{"indexed":false,"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"LegacySignerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bytes","name":"url","type":"bytes"}],"name":"OffchainStorageRootAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bytes","name":"url","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"index","type":"uint256"}],"name":"OffchainStorageRootRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"fraction","type":"uint256"}],"name":"PaymentDelegationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"registryAddress","type":"address"}],"name":"RegistrySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"SignerAuthorizationCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"SignerAuthorizationStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"SignerAuthorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"oldSigner","type":"address"},{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"SignerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"ValidatorSignerAuthorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"oldSigner","type":"address"}],"name":"ValidatorSignerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"VoteSignerAuthorized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"address","name":"oldSigner","type":"address"}],"name":"VoteSignerRemoved","type":"event"},{"constant":true,"inputs":[],"name":"EIP712_AUTHORIZE_SIGNER_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"url","type":"bytes"}],"name":"addStorageRoot","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"attestationSignerToAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"authorizeAttestationSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"authorizeSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"authorizeSignerWithSignature","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"authorizeValidatorSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"bytes","name":"ecdsaPublicKey","type":"bytes"}],"name":"authorizeValidatorSignerWithPublicKey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"authorizeVoteSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"authorizedBy","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address[]","name":"accountsToQuery","type":"address[]"}],"name":"batchGetMetadataURL","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"completeSignerAuthorization","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"createAccount","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"deletePaymentDelegation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"eip712DomainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getAttestationSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getDataEncryptionKey","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getDefaultSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getIndexedSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getLegacySigner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getMetadataURL","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getName","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getOffchainStorageRoots","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getPaymentDelegation","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"getRoleAuthorizationSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getValidatorSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getVersionNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVoteSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getWalletAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"hasAuthorizedAttestationSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"string","name":"role","type":"string"}],"name":"hasAuthorizedSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"hasAuthorizedValidatorSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"hasAuthorizedVoteSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"hasDefaultSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"hasIndexedSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"hasLegacySigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"registryAddress","type":"address"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"initialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isAccount","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isAuthorizedSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"isDefaultSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"isIndexedSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"isLegacyRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"isLegacySigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"isSigner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"offchainStorageRoots","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"registry","outputs":[{"internalType":"contract IRegistry","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"removeAttestationSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"removeDefaultSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"removeIndexedSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"removeSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"removeStorageRoot","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"removeValidatorSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"removeVoteSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"bytes","name":"dataEncryptionKey","type":"bytes"},{"internalType":"address","name":"walletAddress","type":"address"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"setAccount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"dataEncryptionKey","type":"bytes"}],"name":"setAccountDataEncryptionKey","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"setEip712DomainSeparator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"setIndexedSigner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"metadataURL","type":"string"}],"name":"setMetadataURL","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"fraction","type":"uint256"}],"name":"setPaymentDelegation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"registryAddress","type":"address"}],"name":"setRegistry","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"walletAddress","type":"address"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"setWalletAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"signerToAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"validatorSignerToAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"voteSignerToAccount","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b5060405162008afd38038062008afd833981810160405260208110156200003757600080fd5b81019080805190602001909291905050508060006200005b6200012a60201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600180819055508062000122576001600260006101000a81548160ff0219169083151502179055505b505062000132565b600033905090565b6189bb80620001426000396000f3fe608060405234801561001057600080fd5b50600436106104125760003560e01c806387affe6811610220578063ae32fa0e11610130578063c48830d9116100b8578063f0c5658411610087578063f0c5658414612062578063f2fde38b14612080578063f333d836146120c4578063fbe3c3731461210a578063ff836d931461215857610412565b8063c48830d914611f3c578063c4d66de814611fc2578063e7a16e6b14612006578063e8d787cb1461203457610412565b8063ba40e4f6116100ff578063ba40e4f614611d05578063baf7ef0f14611db6578063bce2b8d614611e1b578063c2e0ee2014611e25578063c47f002714611e8157610412565b8063ae32fa0e14611a7c578063b062c84314611b39578063b5a664c214611bb2578063b6c6662514611c3657610412565b806392f90fbf116101b35780639f024f4b116101825780639f024f4b146118985780639f68297614611923578063a5ec94f914611971578063a8ae1a3d1461197b578063a91ee0dc14611a3857610412565b806392f90fbf1461171e57806393c5c4871461178d5780639cafb2a1146118115780639dca362f1461187657610412565b80638f32d59b116101ef5780638f32d59b146115195780638f9ae6dc1461153b57806390b12b471461158957806391cd074b1461169857610412565b806387affe68146112795780638adaf96f146113075780638bceca58146114415780638da5cb5b146114cf57610412565b80634ce38b5f116103265780636642d594116102ae57806376082c1f1161027d57806376082c1f14611075578063760fbbb21461113c57806376afa04c146111465780637b103999146111ab5780637b2434cb146111f557610412565b80636642d59414610f20578063715018a614610fa4578063727d079c14610fae578063747daec514610ffc57610412565b80635b6d9004116102f55780635b6d900414610c715780635fd4b08a14610cff578063614ed49314610dbc57806361bab1ae14610e1857806364439b4314610e9c57610412565b80634ce38b5f14610b4e57806354255be014610bd257806358b81ea814610c055780635b07fdd814610c5357610412565b8063158ef93e116103a95780633184b3c5116103785780633184b3c51461097957806341ddd880146109835780634282ee6d14610a07578063485a46d114610a6c57806349045e1614610af257610412565b8063158ef93e146107725780631fd9afa51461079457806325ca4c9c14610818578063289a13181461087457610412565b80630fa750d2116103e55780630fa750d21461058d5780630fe7abab1461064757806310c504b5146107025780631441ece71461070c57610412565b80630127dbed146104175780630185a2321461047357806305be6229146104a15780630b8e056214610507575b600080fd5b6104596004803603602081101561042d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506121be565b604051808215151515815260200191505060405180910390f35b61049f6004803603602081101561048957600080fd5b8101908080359060200190929190505050612217565b005b6104ed600480360360408110156104b757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506122d0565b604051808215151515815260200191505060405180910390f35b6105736004803603606081101561051d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612313565b604051808215151515815260200191505060405180910390f35b610645600480360360a08110156105a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff16906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561060157600080fd5b82018360208201111561061357600080fd5b8035906020019184600183028401116401000000008311171561063557600080fd5b90919293919293905050506123bd565b005b6107006004803603602081101561065d57600080fd5b810190808035906020019064010000000081111561067a57600080fd5b82018360208201111561068c57600080fd5b803590602001918460018302840111640100000000831117156106ae57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506126ef565b005b61070a61287a565b005b6107586004803603604081101561072257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061299b565b604051808215151515815260200191505060405180910390f35b61077a6129de565b604051808215151515815260200191505060405180910390f35b6107d6600480360360208110156107aa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506129f1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61085a6004803603602081101561082e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612a5d565b604051808215151515815260200191505060405180910390f35b6108b66004803603602081101561088a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612ab6565b604051808060200180602001838103835285818151815260200191508051906020019080838360005b838110156108fa5780820151818401526020810190506108df565b50505050905090810190601f1680156109275780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019060200280838360005b83811015610963578082015181840152602081019050610948565b5050505090500194505050505060405180910390f35b610981612e11565b005b6109c56004803603602081101561099957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612e1b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a6a60048036036080811015610a1d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050612e74565b005b610ad860048036036060811015610a8257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613026565b604051808215151515815260200191505060405180910390f35b610b3460048036036020811015610b0857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613177565b604051808215151515815260200191505060405180910390f35b610b9060048036036020811015610b6457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061320f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610bda613268565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b610c5160048036036040811015610c1b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061328f565b005b610c5b6134c7565b6040518082815260200191505060405180910390f35b610cbd60048036036040811015610c8757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506134cd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610d4160048036036020811015610d1557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613588565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610d81578082015181840152602081019050610d66565b50505050905090810190601f168015610dae5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610dfe60048036036020811015610dd257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061366c565b604051808215151515815260200191505060405180910390f35b610e5a60048036036020811015610e2e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506136c5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610ede60048036036020811015610eb257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061371e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610f6260048036036020811015610f3657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613777565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610fac6137d0565b005b610ffa60048036036040811015610fc457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613909565b005b6110736004803603602081101561101257600080fd5b810190808035906020019064010000000081111561102f57600080fd5b82018360208201111561104157600080fd5b8035906020019184600183028401116401000000008311171561106357600080fd5b9091929391929390505050613edb565b005b6110c16004803603604081101561108b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061402c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156111015780820151818401526020810190506110e6565b50505050905090810190601f16801561112e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6111446140f2565b005b6111a96004803603608081101561115c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050614213565b005b6111b3614336565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6112376004803603602081101561120b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061435c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6112c56004803603604081101561128f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506143b5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61137e6004803603602081101561131d57600080fd5b810190808035906020019064010000000081111561133a57600080fd5b82018360208201111561134c57600080fd5b8035906020019184602083028401116401000000008311171561136e57600080fd5b90919293919293905050506143e6565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156113c55780820151818401526020810190506113aa565b50505050905001838103825284818151815260200191508051906020019080838360005b838110156114045780820151818401526020810190506113e9565b50505050905090810190601f1680156114315780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b61148d6004803603604081101561145757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506146e5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6114d7614962565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61152161498b565b604051808215151515815260200191505060405180910390f35b6115876004803603604081101561155157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506149e9565b005b611696600480360360c081101561159f57600080fd5b81019080803590602001906401000000008111156115bc57600080fd5b8201836020820111156115ce57600080fd5b803590602001918460018302840111640100000000831117156115f057600080fd5b90919293919293908035906020019064010000000081111561161157600080fd5b82018360208201111561162357600080fd5b8035906020019184600183028401116401000000008311171561164557600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050614c6b565b005b611704600480360360608110156116ae57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050614d32565b604051808215151515815260200191505060405180910390f35b61178b600480360360a081101561173457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050614fa5565b005b6117cf600480360360208110156117a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061511f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6118746004803603608081101561182757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050615229565b005b61187e615590565b604051808215151515815260200191505060405180910390f35b6118da600480360360208110156118ae57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506156ac565b604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390f35b61196f6004803603604081101561193957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050615742565b005b611979615acd565b005b6119bd6004803603602081101561199157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615bee565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156119fd5780820151818401526020810190506119e2565b50505050905090810190601f168015611a2a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b611a7a60048036036020811015611a4e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615cd2565b005b611abe60048036036020811015611a9257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615e76565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015611afe578082015181840152602081019050611ae3565b50505050905090810190601f168015611b2b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b611bb060048036036020811015611b4f57600080fd5b8101908080359060200190640100000000811115611b6c57600080fd5b820183602082011115611b7e57600080fd5b80359060200191846001830284011164010000000083111715611ba057600080fd5b9091929391929390505050615f5a565b005b611bf460048036036020811015611bc857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506160d2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b611cc3600480360360c0811015611c4c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050616105565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b611d9c60048036036040811015611d1b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115611d5857600080fd5b820183602082011115611d6a57600080fd5b80359060200191846001830284011164010000000083111715611d8c57600080fd5b9091929391929390505050616278565b604051808215151515815260200191505060405180910390f35b611e1960048036036080811015611dcc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff16906020019092919080359060200190929190803590602001909291905050506162bc565b005b611e23616583565b005b611e6760048036036020811015611e3b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050616706565b604051808215151515815260200191505060405180910390f35b611f3a60048036036020811015611e9757600080fd5b8101908080359060200190640100000000811115611eb457600080fd5b820183602082011115611ec657600080fd5b80359060200191846001830284011164010000000083111715611ee857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061675f565b005b611fa860048036036060811015611f5257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506168d0565b604051808215151515815260200191505060405180910390f35b61200460048036036020811015611fd857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050616904565b005b6120326004803603602081101561201c57600080fd5b81019080803590602001909291905050506169bf565b005b6120606004803603602081101561204a57600080fd5b8101908080359060200190929190505050616b4a565b005b61206a616f92565b6040518082815260200191505060405180910390f35b6120c26004803603602081101561209657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050616fae565b005b6120f0600480360360208110156120da57600080fd5b8101908080359060200190929190505050617034565b604051808215151515815260200191505060405180910390f35b6121566004803603604081101561212057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050617126565b005b6121a46004803603604081101561216e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050617277565b604051808215151515815260200191505060405180910390f35b60006122108260405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f7200000000000000000081525060170190506040516020818303038152906040528051906020012061299b565b9050919050565b600061222333836143b5565b905061222e82617034565b6122405761223b826169bf565b61224a565b612249826172a8565b5b3373ffffffffffffffffffffffffffffffffffffffff167fccc97b55d227538f487c521e1218ba74768b73d088310238027c2ae3b43e9c918284604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a25050565b60008273ffffffffffffffffffffffffffffffffffffffff166122f384846134cd565b73ffffffffffffffffffffffffffffffffffffffff161415905092915050565b60008273ffffffffffffffffffffffffffffffffffffffff16600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161490509392505050565b60018060008282540192505081905550600060015490506124278760405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f720000000000000000008152506017019050604051602081830303815290604052805190602001208888886175be565b6124778760405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f72000000000000000000815250601701905060405160208183030381529060405280519060200120613909565b61247f617737565b73ffffffffffffffffffffffffffffffffffffffff16634e06fd8a338986866040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050602060405180830381600087803b15801561256557600080fd5b505af1158015612579573d6000803e3d6000fd5b505050506040513d602081101561258f57600080fd5b81019080805190602001909291905050506125f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806189666021913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f16e382723fb40543364faf68863212ba253a099607bf6d3a5b47e50a8bf9494388604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a260015481146126e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b50505050505050565b602181511015612767576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f6461746120656e6372797074696f6e206b6579206c656e677468203c3d20333281525060200191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050818160060190805190602001906127c292919061829d565b503373ffffffffffffffffffffffffffffffffffffffff167f43fdefe0a824cb0e3bbaf9c4bc97669187996136fe9282382baf10787f0d808d836040518080602001828103825283818151815260200191508051906020019080838360005b8381101561283c578082015181840152602081019050612821565b50505050905090810190601f1680156128695780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b60006128cc3360405160200180807f63656c6f2e6f72672f636f72652f766f746500000000000000000000000000008152506012019050604051602081830303815290604052805190602001206146e5565b905061291e8160405160200180807f63656c6f2e6f72672f636f72652f766f74650000000000000000000000000000815250601201905060405160208183030381529060405280519060200120617126565b3373ffffffffffffffffffffffffffffffffffffffff167fa197481f404d8a8082368ad7445380f01e75f27dea6b7aef234a4ce071127fae82604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250565b60008273ffffffffffffffffffffffffffffffffffffffff166129be84846146e5565b73ffffffffffffffffffffffffffffffffffffffff161415905092915050565b600260009054906101000a900460ff1681565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b606080612ac283612a5d565b612b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050600080905060008090505b82811015612c1857612c09600860008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110612bdb57fe5b906000526020600020018054600181600116156101000203166002900490508361783290919063ffffffff16565b91508080600101915050612b86565b506060816040519080825280601f01601f191660200182016040528015612c4e5781602001600182028038833980820191505090505b5090506000809050606084604051908082528060200260200182016040528015612c875781602001602082028038833980820191505090505b50905060008090505b85811015612e00576000600860008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110612ce457fe5b90600052602060002001905080805460018160011615610100020316600290049050838381518110612d1257fe5b60200260200101818152505060008090505b838381518110612d3057fe5b6020026020010151811015612df1578181815460018160011615610100020316600290048110612d5c57fe5b815460011615612d7b5790600052602060002090602091828204019190065b9054901a7f010000000000000000000000000000000000000000000000000000000000000002868681518110612dad57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535084806001019550508080600101915050612d24565b50508080600101915050612c90565b508281965096505050505050915091565b612e196178ba565b565b6000612e6d8260405160200180807f63656c6f2e6f72672f636f72652f766f746500000000000000000000000000008152506012019050604051602081830303815290604052805190602001206146e5565b9050919050565b6001806000828254019250508190555060006001549050612ede8560405160200180807f63656c6f2e6f72672f636f72652f766f746500000000000000000000000000008152506012019050604051602081830303815290604052805190602001208686866175be565b612f2e8560405160200180807f63656c6f2e6f72672f636f72652f766f74650000000000000000000000000000815250601201905060405160208183030381529060405280519060200120613909565b3373ffffffffffffffffffffffffffffffffffffffff167faab5f8a189373aaa290f42ae65ea5d7971b732366ca5bf66556e76263944af2886604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a2600154811461301f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050565b6000613033848484614d32565b8061316e5750600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900460ff16801561316d57508373ffffffffffffffffffffffffffffffffffffffff16600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60006132618260405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f720000000000000000008152506017019050604051602081830303815290604052805190602001206146e5565b9050919050565b60008060008060016002600080839350829250819150809050935093509350935090919293565b61329833612a5d565b6132ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260358152602001806188bb6035913960400191505060405180910390fd5b6132f6826179c4565b801561330857506133073383617a1e565b5b61335d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061891f6022913960400191505060405180910390fd5b604051806040016040528060011515815260200160001515815250600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff021916908315150217905550905050803373ffffffffffffffffffffffffffffffffffffffff167f7a162218a1b7bec7fb15b4bb95220fbf423fa3a49718133f5c50361ff1c8537684604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a35050565b60075481565b600080600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461357d578061357f565b835b91505092915050565b6060600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156136605780601f1061363557610100808354040283529160200191613660565b820191906000526020600020905b81548152906001019060200180831161364357829003601f168201915b50505050509050919050565b60006136be8260405160200180807f63656c6f2e6f72672f636f72652f766f7465000000000000000000000000000081525060120190506040516020818303038152906040528051906020012061299b565b9050919050565b60006137178260405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e000000000000008152506019019050604051602081830303815290604052805190602001206146e5565b9050919050565b60006137708260405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f72000000000000000000815250601701905060405160208183030381529060405280519060200120617b4b565b9050919050565b60006137c98260405160200180807f63656c6f2e6f72672f636f72652f766f74650000000000000000000000000000815250601201905060405160208183030381529060405280519060200120617b4b565b9050919050565b6137d861498b565b61384a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b61391233612a5d565b613967576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806185fd6036913960400191505060405180910390fd5b613970826179c4565b6139c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806186d36022913960400191505060405180910390fd5b6139cf3383617a1e565b613a41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4e6f742061207369676e657220666f722074686973206163636f756e7400000081525060200191505060405180910390fd5b613a4c338383613026565b613aa1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f8152602001806188f0602f913960400191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050613aed82617034565b15613d425760405160200180807f63656c6f2e6f72672f636f72652f766f74650000000000000000000000000000815250601201905060405160208183030381529060405280519060200120821415613b8b57828160010160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550613cbb565b60405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e00000000000000815250601901905060405160208183030381529060405280519060200120821415613c2457828160010160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550613cba565b60405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f72000000000000000000815250601701905060405160208183030381529060405280519060200120821415613cb957828160010160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b5b3373ffffffffffffffffffffffffffffffffffffffff167fc5cd67202a8095484f559b338b2b6fee0dd81af9f70c4814c6517fcf9a09564c8484604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a2613e54565b82600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f2613ed414d18d8152e86c896c04ccce344b75a2f06141f04d39ad069a38725238484604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a25b3373ffffffffffffffffffffffffffffffffffffffff167f8a00ae3e0722558391733230bfc96d425df2dd7b44f7ce506580785adcf171a28484604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a2505050565b613ee433612a5d565b613f56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508282826007019190613fac92919061831d565b503373ffffffffffffffffffffffffffffffffffffffff167f0b5629fec5b6b5a1c2cfe0de7495111627a8cf297dced72e0669527425d3f01b848460405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a2505050565b6008602052816000526040600020818154811061404557fe5b90600052602060002001600091509150508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156140ea5780601f106140bf576101008083540402835291602001916140ea565b820191906000526020600020905b8154815290600101906020018083116140cd57829003601f168201915b505050505081565b60006141443360405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e000000000000008152506019019050604051602081830303815290604052805190602001206146e5565b90506141968160405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e00000000000000815250601901905060405160208183030381529060405280519060200120617126565b3373ffffffffffffffffffffffffffffffffffffffff167f14670729407debb6ed03d885f8ba57155de89ce39bf17127ae4900ec7c2ad10382604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250565b6142668460405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e000000000000008152506019019050604051602081830303815290604052805190602001208585856175be565b6142b68460405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e00000000000000815250601901905060405160208183030381529060405280519060200120613909565b3373ffffffffffffffffffffffffffffffffffffffff167f9dfbc5a621c3e2d0d83beee687a17dfc796bbce2118793e5e254409bb265ca0b85604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250505050565b600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006143ae8260405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e00000000000000815250601901905060405160208183030381529060405280519060200120617b4b565b9050919050565b60006143c082617034565b6143d3576143ce83836134cd565b6143de565b6143dd83836146e5565b5b905092915050565b60608060008090506060858590506040519080825280602002602001820160405280156144225781602001602082028038833980820191505090505b50905060008090505b86869050811015614510576003600088888481811061444657fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018054600181600116156101000203166002900490508282815181106144c157fe5b6020026020010181815250506144f38282815181106144dc57fe5b60200260200101518461783290919063ffffffff16565b925061450960018261783290919063ffffffff16565b905061442b565b506060826040519080825280601f01601f1916602001820160405280156145465781602001600182028038833980820191505090505b509050600080905060008090505b888890508110156146d35760008090505b84828151811061457157fe5b60200260200101518110156146b757600360008b8b8581811061459057fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018181546001816001161561010002031660029004811061460657fe5b8154600116156146255790600052602060002090602091828204019190065b9054901a7f01000000000000000000000000000000000000000000000000000000000000000284848151811061465757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061469a60018461783290919063ffffffff16565b92506146b060018261783290919063ffffffff16565b9050614565565b506146cc60018261783290919063ffffffff16565b9050614554565b50828295509550505050509250929050565b60006146f082617034565b614762576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f526f6c65206973206e6f742061206c6567616379207369676e6572000000000081525060200191505060405180910390fd5b6000600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600060405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f72000000000000000000815250601701905060405160208183030381529060405280519060200120841415614824578160010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061491c565b60405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e000000000000008152506019019050604051602081830303815290604052805190602001208414156148a1578160010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061491b565b60405160200180807f63656c6f2e6f72672f636f72652f766f7465000000000000000000000000000081525060120190506040516020818303038152906040528051906020012084141561491a578160010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b5b5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146149565780614958565b845b9250505092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166149cd617cb6565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b6149f233612a5d565b614a47576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806185fd6036913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415614acd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806186f56021913960400191505060405180910390fd5b614ad561839d565b614ade82617cbe565b9050614afa614aeb617cdc565b82617d0290919063ffffffff16565b614b4f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806187cf6023913960400191505060405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff16815260200182815250600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001016000820151816000015550509050508273ffffffffffffffffffffffffffffffffffffffff167f3bff8b126c8f283f709ae37dc0d3fc03cae85ca4772cfb25b601f4b0b49ca6df836040518082815260200191505060405180910390a2505050565b614c7433612a5d565b614c8257614c80615590565b505b614ccf88888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061675f565b614d1c86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506126ef565b614d2884848484615229565b5050505050505050565b600080600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f7200000000000000000081525060170190506040516020818303038152906040528051906020012083148015614e1d57508373ffffffffffffffffffffffffffffffffffffffff168160010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b15614e2c576001915050614f9e565b60405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e0000000000000081525060190190506040516020818303038152906040528051906020012083148015614ed357508373ffffffffffffffffffffffffffffffffffffffff168160010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b15614ee2576001915050614f9e565b60405160200180807f63656c6f2e6f72672f636f72652f766f7465000000000000000000000000000081525060120190506040516020818303038152906040528051906020012083148015614f8957508373ffffffffffffffffffffffffffffffffffffffff168160010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b15614f98576001915050614f9e565b60009150505b9392505050565b614fb28585858585617d18565b604051806040016040528060011515815260200160011515815250600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600086815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff021916908315150217905550905050833373ffffffffffffffffffffffffffffffffffffffff167f6cc56bd06daacce5b10fdf5ad1dc781941e14d7a71d29d33e7001e2956d14e0787604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a35050505050565b600080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146151c15780915050615224565b6151ca83612a5d565b61521f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806185fd6036913960400191505060405180910390fd5b829150505b919050565b61523233612a5d565b6152a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061530a5750600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b6154895760007369baecd458e7c08b13a18e11887dbb078fb3cbb46396ef41a1338686866040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018460ff1660ff16815260200183815260200182815260200194505050505060206040518083038186803b1580156153a957600080fd5b505af41580156153bd573d6000803e3d6000fd5b505050506040513d60208110156153d357600080fd5b810190808051906020019092919050505090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614615487576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f496e76616c6964207369676e617475726500000000000000000000000000000081525060200191505060405180910390fd5b505b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050848160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167ff81d74398fd47e35c36b714019df15f200f623dde569b5b531d6a0b4da5c5f2686604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25050505050565b600061559b336179c4565b80156155ac57506155ab33617ddc565b5b615601576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604d81526020018061883f604d913960600191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060018160000160006101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167f805996f252884581e2f74cf3d2b03564d5ec26ccc90850ae12653dc1b72d1fa260405160405180910390a2600191505090565b6000806000600960008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661573882600101604051806020016040529081600082015481525050617e73565b9250925050915091565b61574b82612a5d565b6157a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604d8152602001806187f2604d913960600191505060405180910390fd5b6157a9336179c4565b80156157bb57506157ba8233617a1e565b5b615810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061891f6022913960400191505060405180910390fd5b60011515600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16151514615927576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f5369676e657220617574686f72697a6174696f6e206e6f74207374617274656481525060200191505060405180910390fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160016101000a81548160ff021916908315150217905550808273ffffffffffffffffffffffffffffffffffffffff167f9eeca140dda0bdb74fc9acfda0f1c0324e188a732bd48e078a96b16d97eb54e533604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a35050565b6000615b1f3360405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f720000000000000000008152506017019050604051602081830303815290604052805190602001206146e5565b9050615b718160405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f72000000000000000000815250601701905060405160208183030381529060405280519060200120617126565b3373ffffffffffffffffffffffffffffffffffffffff167fa54764c62865ff0cd3f271fb1d4635662bff10f0878694f1654fb7fbdecb830d82604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250565b6060600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015615cc65780601f10615c9b57610100808354040283529160200191615cc6565b820191906000526020600020905b815481529060010190602001808311615ca957829003601f168201915b50505050509050919050565b615cda61498b565b615d4c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415615def576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600260016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b6060600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206006018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015615f4e5780601f10615f2357610100808354040283529160200191615f4e565b820191906000526020600020905b815481529060010190602001808311615f3157829003601f168201915b50505050509050919050565b615f6333612a5d565b615fd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208282909180600181540180825580915050906001820390600052602060002001600090919293909192939091929091925091906160529291906183b0565b50503373ffffffffffffffffffffffffffffffffffffffff167f15dfb3066a1bbbdaf9a7f62c47db990114058ae1739fd70a90361ea715bbf3c8838360405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a25050565b60046020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806040518080618697603c9139603c0190506040518091039020888888604051602001808581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019450505050506040516020818303038152906040528051906020012090507369baecd458e7c08b13a18e11887dbb078fb3cbb46334d1a233600754838888886040518663ffffffff1660e01b8152600401808681526020018581526020018460ff1660ff1681526020018381526020018281526020019550505050505060206040518083038186803b15801561623057600080fd5b505af4158015616244573d6000803e3d6000fd5b505050506040513d602081101561625a57600080fd5b81019080805190602001909291905050509150509695505050505050565b60006162b384848460405160200180838380828437808301925050509250505060405160208183030381529060405280519060200120617277565b90509392505050565b60018060008282540192505081905550600060015490506163268560405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f720000000000000000008152506017019050604051602081830303815290604052805190602001208686866175be565b6163768560405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f72000000000000000000815250601701905060405160208183030381529060405280519060200120613909565b61637e617737565b73ffffffffffffffffffffffffffffffffffffffff1663facd743b336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156163fa57600080fd5b505afa15801561640e573d6000803e3d6000fd5b505050506040513d602081101561642457600080fd5b81019080805190602001909291905050501561648b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061875c6021913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f16e382723fb40543364faf68863212ba253a099607bf6d3a5b47e50a8bf9494386604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a2600154811461657c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050565b61658c33612a5d565b6165e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806185fd6036913960400191505060405180910390fd5b6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016166136000617cbe565b815250600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101600082015181600001555050905050600073ffffffffffffffffffffffffffffffffffffffff167f3bff8b126c8f283f709ae37dc0d3fc03cae85ca4772cfb25b601f4b0b49ca6df60006040518082815260200191505060405180910390a2565b60006167588260405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e0000000000000081525060190190506040516020818303038152906040528051906020012061299b565b9050919050565b61676833612a5d565b6167bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061888c602f913960400191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905081816005019080519060200190616818929190618430565b503373ffffffffffffffffffffffffffffffffffffffff167fa6e2c5a23bb917ba0a584c4b250257ddad698685829b66a8813c004b39934fe4836040518080602001828103825283818151815260200191508051906020019080838360005b83811015616892578082015181840152602081019050616877565b50505050905090810190601f1680156168bf5780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b60006168db82617034565b6168ef576168ea848484612313565b6168fb565b6168fa848484614d32565b5b90509392505050565b600260009054906101000a900460ff1615616987576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600260006101000a81548160ff0219169083151502179055506169ab33617e81565b6169b481615cd2565b6169bc6178ba565b50565b6000600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167fe553a3065d5a77d4ec2a0e0c31d49be4bf4d9f4c45883b2d67f61ba9c1b89c5d8284604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a25050565b616b5333612a5d565b616bc5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490508110616c7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f496e76616c69642073746f7261676520726f6f7420696e64657800000000000081525060200191505060405180910390fd5b60006001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490500390506060600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110616d1257fe5b906000526020600020018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015616db05780601f10616d8557610100808354040283529160200191616db0565b820191906000526020600020905b815481529060010190602001808311616d9357829003601f168201915b50505050509050600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110616e0157fe5b90600052602060002001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110616e5557fe5b906000526020600020019080546001816001161561010002031660029004616e7e9291906184b0565b50600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480919060019003616ed19190618537565b503373ffffffffffffffffffffffffffffffffffffffff167fae0f2fa495a3eb65d46fe97b0baea8b6fd7edb243175c70f2455e6e83bc6fbaf82856040518080602001838152602001828103825284818151815260200191508051906020019080838360005b83811015616f52578082015181840152602081019050616f37565b50505050905090810190601f168015616f7f5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a2505050565b6040518080618697603c9139603c019050604051809103902081565b616fb661498b565b617028576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61703181617e81565b50565b600060405160200180807f63656c6f2e6f72672f636f72652f766f746500000000000000000000000000008152506012019050604051602081830303815290604052805190602001208214806170cf575060405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f7200000000000000000081525060170190506040516020818303038152906040528051906020012082145b8061711f575060405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e0000000000000081525060190190506040516020818303038152906040528051906020012082145b9050919050565b6171313383836168d0565b156171405761713f81612217565b5b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549060ff02191690556000820160016101000a81549060ff02191690555050803373ffffffffffffffffffffffffffffffffffffffff167fde9ce22cf1f8631ae2b668300f0493971114f40edd305173bd099ce7100fbe0b84604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a35050565b600061728282617034565b6172955761729083836122d0565b6172a0565b61729f838361299b565b5b905092915050565b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600060405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f720000000000000000008152506017019050604051602081830303815290604052805190602001208314156173b1578160010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260010160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550617537565b60405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e00000000000000815250601901905060405160208183030381529060405280519060200120831415617475578160010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260010160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550617536565b60405160200180807f63656c6f2e6f72672f636f72652f766f74650000000000000000000000000000815250601201905060405160208183030381529060405280519060200120831415617535578160010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260010160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b5b3373ffffffffffffffffffffffffffffffffffffffff167fdd0b0d959c29750e7bfabbb7543a56957699d07edc512d2523ffe7502901ac198285604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a2505050565b6175ca85848484617fc5565b604051806040016040528060011515815260200160011515815250600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600086815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff021916908315150217905550905050833373ffffffffffffffffffffffffffffffffffffffff167f6cc56bd06daacce5b10fdf5ad1dc781941e14d7a71d29d33e7001e2956d14e0787604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a35050505050565b6000600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f56616c696461746f727300000000000000000000000000000000000000000000815250600a019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156177f257600080fd5b505afa158015617806573d6000803e3d6000fd5b505050506040513d602081101561781c57600080fd5b8101908080519060200190929190505050905090565b6000808284019050838110156178b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000469050604051808061877d60529139605201905060405180910390206040518060400160405280601381526020017f43656c6f20436f726520436f6e747261637473000000000000000000000000008152508051906020012060405180807f312e300000000000000000000000000000000000000000000000000000000000815250600301905060405180910390208330604051602001808681526020018581526020018481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001955050505050506040516020818303038152906040528051906020012060078190555050565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16159050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480617b4357508273ffffffffffffffffffffffffffffffffffffffff16600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b905092915050565b600080600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614617c4d57617bef818585613026565b617c44576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806189416025913960400191505060405180910390fd5b80915050617cb0565b617c5684612a5d565b617cab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806185fd6036913960400191505060405180910390fd5b839150505b92915050565b600033905090565b617cc661839d565b6040518060200160405280838152509050919050565b617ce461839d565b604051806020016040528069d3c21bcecceda1000000815250905090565b6000816000015183600001511115905092915050565b6000617d28338787878787616105565b90508573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614617dcb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f496e76616c6964207369676e617475726500000000000000000000000000000081525060200191505060405180910390fd5b617dd48661814e565b505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16149050919050565b600081600001519050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415617f07576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806186716026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60007369baecd458e7c08b13a18e11887dbb078fb3cbb46396ef41a1338686866040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018460ff1660ff16815260200183815260200182815260200194505050505060206040518083038186803b15801561806057600080fd5b505af4158015618074573d6000803e3d6000fd5b505050506040513d602081101561808a57600080fd5b810190808051906020019092919050505090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461813e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f496e76616c6964207369676e617475726500000000000000000000000000000081525060200191505060405180910390fd5b6181478561814e565b5050505050565b61815733612a5d565b6181ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603e815260200180618633603e913960400191505060405180910390fd5b6181b5816179c4565b80156181c757506181c63382617a1e565b5b61821c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260468152602001806187166046913960600191505060405180910390fd5b33600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106182de57805160ff191683800117855561830c565b8280016001018555821561830c579182015b8281111561830b5782518255916020019190600101906182f0565b5b5090506183199190618563565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061835e57803560ff191683800117855561838c565b8280016001018555821561838c579182015b8281111561838b578235825591602001919060010190618370565b5b5090506183999190618563565b5090565b6040518060200160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106183f157803560ff191683800117855561841f565b8280016001018555821561841f579182015b8281111561841e578235825591602001919060010190618403565b5b50905061842c9190618563565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061847157805160ff191683800117855561849f565b8280016001018555821561849f579182015b8281111561849e578251825591602001919060010190618483565b5b5090506184ac9190618563565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106184e95780548555618526565b8280016001018555821561852657600052602060002091601f016020900482015b8281111561852557825482559160010191906001019061850a565b5b5090506185339190618563565b5090565b81548183558181111561855e5781836000526020600020918201910161855d9190618588565b5b505050565b61858591905b80821115618581576000816000905550600101618569565b5090565b90565b6185b191905b808211156185ad57600081816185a491906185b4565b5060010161858e565b5090565b90565b50805460018160011615610100020316600290046000825580601f106185da57506185f9565b601f0160209004906000526020600020908101906185f89190618563565b5b5056fe4d75737420666972737420726567697374657220616464726573732077697468204163636f756e742e6372656174654163636f756e74556e6b6e6f776e206163636f756e743a2073656e646572206d7573742072656769737465722077697468206372656174654163636f756e742066697273744f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373417574686f72697a655369676e65722861646472657373206163636f756e742c61646472657373207369676e65722c6279746573333220726f6c652943616e6e6f7420617574686f72697a65206163636f756e74206173207369676e657242656e65666963696172792063616e6e6f7420626520616464726573732030783043616e6e6f742072652d617574686f72697a652061646472657373206f72206c6f636b656420676f6c64206163636f756e7420666f7220616e6f74686572206163636f756e7443616e6e6f7420617574686f72697a652076616c696461746f72207369676e6572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e7472616374294672616374696f6e206d757374206e6f742062652067726561746572207468616e2031556e6b6e6f776e204163636f756e743a2041646472657373207468617420617574686f72697a6564207369676e696e67206d75737420626520612072656769737465726564204163636f756e744163636f756e7420616c726561647920657869737473206f72206164647265737320697320616e20617574686f72697a6564207369676e657220666f7220616e6f74686572206163636f756e7452656769737465722077697468206372656174654163636f756e7420746f20736574206163636f756e74206e616d654d7573742066697273742072656769737465722073656e6465722077697468204163636f756e742e6372656174654163636f756e744d75737420617574686f72697a65207369676e6572206265666f72652073657474696e672061732064656661756c7443616e6e6f742072652d617574686f72697a652061646472657373207369676e65726e6f742061637469766520617574686f72697a6564207369676e657220666f7220726f6c654661696c656420746f20757064617465204543445341207075626c6963206b6579a265627a7a72315820c0fc4ba3b9ae1355f32ca611df67b02d52c491f199f7667c27a4a04273d28bc464736f6c634300050d00320000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106104125760003560e01c806387affe6811610220578063ae32fa0e11610130578063c48830d9116100b8578063f0c5658411610087578063f0c5658414612062578063f2fde38b14612080578063f333d836146120c4578063fbe3c3731461210a578063ff836d931461215857610412565b8063c48830d914611f3c578063c4d66de814611fc2578063e7a16e6b14612006578063e8d787cb1461203457610412565b8063ba40e4f6116100ff578063ba40e4f614611d05578063baf7ef0f14611db6578063bce2b8d614611e1b578063c2e0ee2014611e25578063c47f002714611e8157610412565b8063ae32fa0e14611a7c578063b062c84314611b39578063b5a664c214611bb2578063b6c6662514611c3657610412565b806392f90fbf116101b35780639f024f4b116101825780639f024f4b146118985780639f68297614611923578063a5ec94f914611971578063a8ae1a3d1461197b578063a91ee0dc14611a3857610412565b806392f90fbf1461171e57806393c5c4871461178d5780639cafb2a1146118115780639dca362f1461187657610412565b80638f32d59b116101ef5780638f32d59b146115195780638f9ae6dc1461153b57806390b12b471461158957806391cd074b1461169857610412565b806387affe68146112795780638adaf96f146113075780638bceca58146114415780638da5cb5b146114cf57610412565b80634ce38b5f116103265780636642d594116102ae57806376082c1f1161027d57806376082c1f14611075578063760fbbb21461113c57806376afa04c146111465780637b103999146111ab5780637b2434cb146111f557610412565b80636642d59414610f20578063715018a614610fa4578063727d079c14610fae578063747daec514610ffc57610412565b80635b6d9004116102f55780635b6d900414610c715780635fd4b08a14610cff578063614ed49314610dbc57806361bab1ae14610e1857806364439b4314610e9c57610412565b80634ce38b5f14610b4e57806354255be014610bd257806358b81ea814610c055780635b07fdd814610c5357610412565b8063158ef93e116103a95780633184b3c5116103785780633184b3c51461097957806341ddd880146109835780634282ee6d14610a07578063485a46d114610a6c57806349045e1614610af257610412565b8063158ef93e146107725780631fd9afa51461079457806325ca4c9c14610818578063289a13181461087457610412565b80630fa750d2116103e55780630fa750d21461058d5780630fe7abab1461064757806310c504b5146107025780631441ece71461070c57610412565b80630127dbed146104175780630185a2321461047357806305be6229146104a15780630b8e056214610507575b600080fd5b6104596004803603602081101561042d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506121be565b604051808215151515815260200191505060405180910390f35b61049f6004803603602081101561048957600080fd5b8101908080359060200190929190505050612217565b005b6104ed600480360360408110156104b757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506122d0565b604051808215151515815260200191505060405180910390f35b6105736004803603606081101561051d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612313565b604051808215151515815260200191505060405180910390f35b610645600480360360a08110156105a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff16906020019092919080359060200190929190803590602001909291908035906020019064010000000081111561060157600080fd5b82018360208201111561061357600080fd5b8035906020019184600183028401116401000000008311171561063557600080fd5b90919293919293905050506123bd565b005b6107006004803603602081101561065d57600080fd5b810190808035906020019064010000000081111561067a57600080fd5b82018360208201111561068c57600080fd5b803590602001918460018302840111640100000000831117156106ae57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506126ef565b005b61070a61287a565b005b6107586004803603604081101561072257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061299b565b604051808215151515815260200191505060405180910390f35b61077a6129de565b604051808215151515815260200191505060405180910390f35b6107d6600480360360208110156107aa57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506129f1565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61085a6004803603602081101561082e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612a5d565b604051808215151515815260200191505060405180910390f35b6108b66004803603602081101561088a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612ab6565b604051808060200180602001838103835285818151815260200191508051906020019080838360005b838110156108fa5780820151818401526020810190506108df565b50505050905090810190601f1680156109275780820380516001836020036101000a031916815260200191505b50838103825284818151815260200191508051906020019060200280838360005b83811015610963578082015181840152602081019050610948565b5050505090500194505050505060405180910390f35b610981612e11565b005b6109c56004803603602081101561099957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612e1b565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a6a60048036036080811015610a1d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050612e74565b005b610ad860048036036060811015610a8257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613026565b604051808215151515815260200191505060405180910390f35b610b3460048036036020811015610b0857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613177565b604051808215151515815260200191505060405180910390f35b610b9060048036036020811015610b6457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061320f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610bda613268565b6040518085815260200184815260200183815260200182815260200194505050505060405180910390f35b610c5160048036036040811015610c1b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061328f565b005b610c5b6134c7565b6040518082815260200191505060405180910390f35b610cbd60048036036040811015610c8757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506134cd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610d4160048036036020811015610d1557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613588565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610d81578082015181840152602081019050610d66565b50505050905090810190601f168015610dae5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610dfe60048036036020811015610dd257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061366c565b604051808215151515815260200191505060405180910390f35b610e5a60048036036020811015610e2e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506136c5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610ede60048036036020811015610eb257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061371e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610f6260048036036020811015610f3657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613777565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610fac6137d0565b005b610ffa60048036036040811015610fc457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613909565b005b6110736004803603602081101561101257600080fd5b810190808035906020019064010000000081111561102f57600080fd5b82018360208201111561104157600080fd5b8035906020019184600183028401116401000000008311171561106357600080fd5b9091929391929390505050613edb565b005b6110c16004803603604081101561108b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061402c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156111015780820151818401526020810190506110e6565b50505050905090810190601f16801561112e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6111446140f2565b005b6111a96004803603608081101561115c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050614213565b005b6111b3614336565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6112376004803603602081101561120b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061435c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6112c56004803603604081101561128f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506143b5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61137e6004803603602081101561131d57600080fd5b810190808035906020019064010000000081111561133a57600080fd5b82018360208201111561134c57600080fd5b8035906020019184602083028401116401000000008311171561136e57600080fd5b90919293919293905050506143e6565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156113c55780820151818401526020810190506113aa565b50505050905001838103825284818151815260200191508051906020019080838360005b838110156114045780820151818401526020810190506113e9565b50505050905090810190601f1680156114315780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b61148d6004803603604081101561145757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506146e5565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6114d7614962565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61152161498b565b604051808215151515815260200191505060405180910390f35b6115876004803603604081101561155157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506149e9565b005b611696600480360360c081101561159f57600080fd5b81019080803590602001906401000000008111156115bc57600080fd5b8201836020820111156115ce57600080fd5b803590602001918460018302840111640100000000831117156115f057600080fd5b90919293919293908035906020019064010000000081111561161157600080fd5b82018360208201111561162357600080fd5b8035906020019184600183028401116401000000008311171561164557600080fd5b9091929391929390803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050614c6b565b005b611704600480360360608110156116ae57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050614d32565b604051808215151515815260200191505060405180910390f35b61178b600480360360a081101561173457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050614fa5565b005b6117cf600480360360208110156117a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061511f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6118746004803603608081101561182757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050615229565b005b61187e615590565b604051808215151515815260200191505060405180910390f35b6118da600480360360208110156118ae57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506156ac565b604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390f35b61196f6004803603604081101561193957600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050615742565b005b611979615acd565b005b6119bd6004803603602081101561199157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615bee565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156119fd5780820151818401526020810190506119e2565b50505050905090810190601f168015611a2a5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b611a7a60048036036020811015611a4e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615cd2565b005b611abe60048036036020811015611a9257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050615e76565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015611afe578082015181840152602081019050611ae3565b50505050905090810190601f168015611b2b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b611bb060048036036020811015611b4f57600080fd5b8101908080359060200190640100000000811115611b6c57600080fd5b820183602082011115611b7e57600080fd5b80359060200191846001830284011164010000000083111715611ba057600080fd5b9091929391929390505050615f5a565b005b611bf460048036036020811015611bc857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506160d2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b611cc3600480360360c0811015611c4c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050616105565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b611d9c60048036036040811015611d1b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190640100000000811115611d5857600080fd5b820183602082011115611d6a57600080fd5b80359060200191846001830284011164010000000083111715611d8c57600080fd5b9091929391929390505050616278565b604051808215151515815260200191505060405180910390f35b611e1960048036036080811015611dcc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff16906020019092919080359060200190929190803590602001909291905050506162bc565b005b611e23616583565b005b611e6760048036036020811015611e3b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050616706565b604051808215151515815260200191505060405180910390f35b611f3a60048036036020811015611e9757600080fd5b8101908080359060200190640100000000811115611eb457600080fd5b820183602082011115611ec657600080fd5b80359060200191846001830284011164010000000083111715611ee857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061675f565b005b611fa860048036036060811015611f5257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506168d0565b604051808215151515815260200191505060405180910390f35b61200460048036036020811015611fd857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050616904565b005b6120326004803603602081101561201c57600080fd5b81019080803590602001909291905050506169bf565b005b6120606004803603602081101561204a57600080fd5b8101908080359060200190929190505050616b4a565b005b61206a616f92565b6040518082815260200191505060405180910390f35b6120c26004803603602081101561209657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050616fae565b005b6120f0600480360360208110156120da57600080fd5b8101908080359060200190929190505050617034565b604051808215151515815260200191505060405180910390f35b6121566004803603604081101561212057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050617126565b005b6121a46004803603604081101561216e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050617277565b604051808215151515815260200191505060405180910390f35b60006122108260405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f7200000000000000000081525060170190506040516020818303038152906040528051906020012061299b565b9050919050565b600061222333836143b5565b905061222e82617034565b6122405761223b826169bf565b61224a565b612249826172a8565b5b3373ffffffffffffffffffffffffffffffffffffffff167fccc97b55d227538f487c521e1218ba74768b73d088310238027c2ae3b43e9c918284604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a25050565b60008273ffffffffffffffffffffffffffffffffffffffff166122f384846134cd565b73ffffffffffffffffffffffffffffffffffffffff161415905092915050565b60008273ffffffffffffffffffffffffffffffffffffffff16600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161490509392505050565b60018060008282540192505081905550600060015490506124278760405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f720000000000000000008152506017019050604051602081830303815290604052805190602001208888886175be565b6124778760405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f72000000000000000000815250601701905060405160208183030381529060405280519060200120613909565b61247f617737565b73ffffffffffffffffffffffffffffffffffffffff16634e06fd8a338986866040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001806020018281038252848482818152602001925080828437600081840152601f19601f82011690508083019250505095505050505050602060405180830381600087803b15801561256557600080fd5b505af1158015612579573d6000803e3d6000fd5b505050506040513d602081101561258f57600080fd5b81019080805190602001909291905050506125f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806189666021913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f16e382723fb40543364faf68863212ba253a099607bf6d3a5b47e50a8bf9494388604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a260015481146126e6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b50505050505050565b602181511015612767576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f6461746120656e6372797074696f6e206b6579206c656e677468203c3d20333281525060200191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050818160060190805190602001906127c292919061829d565b503373ffffffffffffffffffffffffffffffffffffffff167f43fdefe0a824cb0e3bbaf9c4bc97669187996136fe9282382baf10787f0d808d836040518080602001828103825283818151815260200191508051906020019080838360005b8381101561283c578082015181840152602081019050612821565b50505050905090810190601f1680156128695780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b60006128cc3360405160200180807f63656c6f2e6f72672f636f72652f766f746500000000000000000000000000008152506012019050604051602081830303815290604052805190602001206146e5565b905061291e8160405160200180807f63656c6f2e6f72672f636f72652f766f74650000000000000000000000000000815250601201905060405160208183030381529060405280519060200120617126565b3373ffffffffffffffffffffffffffffffffffffffff167fa197481f404d8a8082368ad7445380f01e75f27dea6b7aef234a4ce071127fae82604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250565b60008273ffffffffffffffffffffffffffffffffffffffff166129be84846146e5565b73ffffffffffffffffffffffffffffffffffffffff161415905092915050565b600260009054906101000a900460ff1681565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff169050919050565b606080612ac283612a5d565b612b34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050600080905060008090505b82811015612c1857612c09600860008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110612bdb57fe5b906000526020600020018054600181600116156101000203166002900490508361783290919063ffffffff16565b91508080600101915050612b86565b506060816040519080825280601f01601f191660200182016040528015612c4e5781602001600182028038833980820191505090505b5090506000809050606084604051908082528060200260200182016040528015612c875781602001602082028038833980820191505090505b50905060008090505b85811015612e00576000600860008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110612ce457fe5b90600052602060002001905080805460018160011615610100020316600290049050838381518110612d1257fe5b60200260200101818152505060008090505b838381518110612d3057fe5b6020026020010151811015612df1578181815460018160011615610100020316600290048110612d5c57fe5b815460011615612d7b5790600052602060002090602091828204019190065b9054901a7f010000000000000000000000000000000000000000000000000000000000000002868681518110612dad57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535084806001019550508080600101915050612d24565b50508080600101915050612c90565b508281965096505050505050915091565b612e196178ba565b565b6000612e6d8260405160200180807f63656c6f2e6f72672f636f72652f766f746500000000000000000000000000008152506012019050604051602081830303815290604052805190602001206146e5565b9050919050565b6001806000828254019250508190555060006001549050612ede8560405160200180807f63656c6f2e6f72672f636f72652f766f746500000000000000000000000000008152506012019050604051602081830303815290604052805190602001208686866175be565b612f2e8560405160200180807f63656c6f2e6f72672f636f72652f766f74650000000000000000000000000000815250601201905060405160208183030381529060405280519060200120613909565b3373ffffffffffffffffffffffffffffffffffffffff167faab5f8a189373aaa290f42ae65ea5d7971b732366ca5bf66556e76263944af2886604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a2600154811461301f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050565b6000613033848484614d32565b8061316e5750600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160019054906101000a900460ff16801561316d57508373ffffffffffffffffffffffffffffffffffffffff16600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60006132618260405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f720000000000000000008152506017019050604051602081830303815290604052805190602001206146e5565b9050919050565b60008060008060016002600080839350829250819150809050935093509350935090919293565b61329833612a5d565b6132ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260358152602001806188bb6035913960400191505060405180910390fd5b6132f6826179c4565b801561330857506133073383617a1e565b5b61335d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061891f6022913960400191505060405180910390fd5b604051806040016040528060011515815260200160001515815250600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff021916908315150217905550905050803373ffffffffffffffffffffffffffffffffffffffff167f7a162218a1b7bec7fb15b4bb95220fbf423fa3a49718133f5c50361ff1c8537684604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a35050565b60075481565b600080600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461357d578061357f565b835b91505092915050565b6060600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156136605780601f1061363557610100808354040283529160200191613660565b820191906000526020600020905b81548152906001019060200180831161364357829003601f168201915b50505050509050919050565b60006136be8260405160200180807f63656c6f2e6f72672f636f72652f766f7465000000000000000000000000000081525060120190506040516020818303038152906040528051906020012061299b565b9050919050565b60006137178260405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e000000000000008152506019019050604051602081830303815290604052805190602001206146e5565b9050919050565b60006137708260405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f72000000000000000000815250601701905060405160208183030381529060405280519060200120617b4b565b9050919050565b60006137c98260405160200180807f63656c6f2e6f72672f636f72652f766f74650000000000000000000000000000815250601201905060405160208183030381529060405280519060200120617b4b565b9050919050565b6137d861498b565b61384a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b61391233612a5d565b613967576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806185fd6036913960400191505060405180910390fd5b613970826179c4565b6139c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806186d36022913960400191505060405180910390fd5b6139cf3383617a1e565b613a41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4e6f742061207369676e657220666f722074686973206163636f756e7400000081525060200191505060405180910390fd5b613a4c338383613026565b613aa1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f8152602001806188f0602f913960400191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050613aed82617034565b15613d425760405160200180807f63656c6f2e6f72672f636f72652f766f74650000000000000000000000000000815250601201905060405160208183030381529060405280519060200120821415613b8b57828160010160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550613cbb565b60405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e00000000000000815250601901905060405160208183030381529060405280519060200120821415613c2457828160010160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550613cba565b60405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f72000000000000000000815250601701905060405160208183030381529060405280519060200120821415613cb957828160010160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b5b3373ffffffffffffffffffffffffffffffffffffffff167fc5cd67202a8095484f559b338b2b6fee0dd81af9f70c4814c6517fcf9a09564c8484604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a2613e54565b82600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f2613ed414d18d8152e86c896c04ccce344b75a2f06141f04d39ad069a38725238484604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a25b3373ffffffffffffffffffffffffffffffffffffffff167f8a00ae3e0722558391733230bfc96d425df2dd7b44f7ce506580785adcf171a28484604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a2505050565b613ee433612a5d565b613f56576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508282826007019190613fac92919061831d565b503373ffffffffffffffffffffffffffffffffffffffff167f0b5629fec5b6b5a1c2cfe0de7495111627a8cf297dced72e0669527425d3f01b848460405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a2505050565b6008602052816000526040600020818154811061404557fe5b90600052602060002001600091509150508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156140ea5780601f106140bf576101008083540402835291602001916140ea565b820191906000526020600020905b8154815290600101906020018083116140cd57829003601f168201915b505050505081565b60006141443360405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e000000000000008152506019019050604051602081830303815290604052805190602001206146e5565b90506141968160405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e00000000000000815250601901905060405160208183030381529060405280519060200120617126565b3373ffffffffffffffffffffffffffffffffffffffff167f14670729407debb6ed03d885f8ba57155de89ce39bf17127ae4900ec7c2ad10382604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250565b6142668460405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e000000000000008152506019019050604051602081830303815290604052805190602001208585856175be565b6142b68460405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e00000000000000815250601901905060405160208183030381529060405280519060200120613909565b3373ffffffffffffffffffffffffffffffffffffffff167f9dfbc5a621c3e2d0d83beee687a17dfc796bbce2118793e5e254409bb265ca0b85604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250505050565b600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006143ae8260405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e00000000000000815250601901905060405160208183030381529060405280519060200120617b4b565b9050919050565b60006143c082617034565b6143d3576143ce83836134cd565b6143de565b6143dd83836146e5565b5b905092915050565b60608060008090506060858590506040519080825280602002602001820160405280156144225781602001602082028038833980820191505090505b50905060008090505b86869050811015614510576003600088888481811061444657fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018054600181600116156101000203166002900490508282815181106144c157fe5b6020026020010181815250506144f38282815181106144dc57fe5b60200260200101518461783290919063ffffffff16565b925061450960018261783290919063ffffffff16565b905061442b565b506060826040519080825280601f01601f1916602001820160405280156145465781602001600182028038833980820191505090505b509050600080905060008090505b888890508110156146d35760008090505b84828151811061457157fe5b60200260200101518110156146b757600360008b8b8581811061459057fe5b9050602002013573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018181546001816001161561010002031660029004811061460657fe5b8154600116156146255790600052602060002090602091828204019190065b9054901a7f01000000000000000000000000000000000000000000000000000000000000000284848151811061465757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535061469a60018461783290919063ffffffff16565b92506146b060018261783290919063ffffffff16565b9050614565565b506146cc60018261783290919063ffffffff16565b9050614554565b50828295509550505050509250929050565b60006146f082617034565b614762576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f526f6c65206973206e6f742061206c6567616379207369676e6572000000000081525060200191505060405180910390fd5b6000600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600060405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f72000000000000000000815250601701905060405160208183030381529060405280519060200120841415614824578160010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061491c565b60405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e000000000000008152506019019050604051602081830303815290604052805190602001208414156148a1578160010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061491b565b60405160200180807f63656c6f2e6f72672f636f72652f766f7465000000000000000000000000000081525060120190506040516020818303038152906040528051906020012084141561491a578160010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b5b5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146149565780614958565b845b9250505092915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166149cd617cb6565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b6149f233612a5d565b614a47576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806185fd6036913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415614acd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806186f56021913960400191505060405180910390fd5b614ad561839d565b614ade82617cbe565b9050614afa614aeb617cdc565b82617d0290919063ffffffff16565b614b4f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806187cf6023913960400191505060405180910390fd5b60405180604001604052808473ffffffffffffffffffffffffffffffffffffffff16815260200182815250600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001016000820151816000015550509050508273ffffffffffffffffffffffffffffffffffffffff167f3bff8b126c8f283f709ae37dc0d3fc03cae85ca4772cfb25b601f4b0b49ca6df836040518082815260200191505060405180910390a2505050565b614c7433612a5d565b614c8257614c80615590565b505b614ccf88888080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505061675f565b614d1c86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506126ef565b614d2884848484615229565b5050505050505050565b600080600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f7200000000000000000081525060170190506040516020818303038152906040528051906020012083148015614e1d57508373ffffffffffffffffffffffffffffffffffffffff168160010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b15614e2c576001915050614f9e565b60405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e0000000000000081525060190190506040516020818303038152906040528051906020012083148015614ed357508373ffffffffffffffffffffffffffffffffffffffff168160010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b15614ee2576001915050614f9e565b60405160200180807f63656c6f2e6f72672f636f72652f766f7465000000000000000000000000000081525060120190506040516020818303038152906040528051906020012083148015614f8957508373ffffffffffffffffffffffffffffffffffffffff168160010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b15614f98576001915050614f9e565b60009150505b9392505050565b614fb28585858585617d18565b604051806040016040528060011515815260200160011515815250600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600086815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff021916908315150217905550905050833373ffffffffffffffffffffffffffffffffffffffff167f6cc56bd06daacce5b10fdf5ad1dc781941e14d7a71d29d33e7001e2956d14e0787604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a35050505050565b600080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146151c15780915050615224565b6151ca83612a5d565b61521f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806185fd6036913960400191505060405180910390fd5b829150505b919050565b61523233612a5d565b6152a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061530a5750600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b6154895760007369baecd458e7c08b13a18e11887dbb078fb3cbb46396ef41a1338686866040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018460ff1660ff16815260200183815260200182815260200194505050505060206040518083038186803b1580156153a957600080fd5b505af41580156153bd573d6000803e3d6000fd5b505050506040513d60208110156153d357600080fd5b810190808051906020019092919050505090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614615487576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f496e76616c6964207369676e617475726500000000000000000000000000000081525060200191505060405180910390fd5b505b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050848160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167ff81d74398fd47e35c36b714019df15f200f623dde569b5b531d6a0b4da5c5f2686604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a25050505050565b600061559b336179c4565b80156155ac57506155ab33617ddc565b5b615601576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604d81526020018061883f604d913960600191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060018160000160006101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167f805996f252884581e2f74cf3d2b03564d5ec26ccc90850ae12653dc1b72d1fa260405160405180910390a2600191505090565b6000806000600960008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661573882600101604051806020016040529081600082015481525050617e73565b9250925050915091565b61574b82612a5d565b6157a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252604d8152602001806187f2604d913960600191505060405180910390fd5b6157a9336179c4565b80156157bb57506157ba8233617a1e565b5b615810576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602281526020018061891f6022913960400191505060405180910390fd5b60011515600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16151514615927576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f5369676e657220617574686f72697a6174696f6e206e6f74207374617274656481525060200191505060405180910390fd5b81600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160016101000a81548160ff021916908315150217905550808273ffffffffffffffffffffffffffffffffffffffff167f9eeca140dda0bdb74fc9acfda0f1c0324e188a732bd48e078a96b16d97eb54e533604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a35050565b6000615b1f3360405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f720000000000000000008152506017019050604051602081830303815290604052805190602001206146e5565b9050615b718160405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f72000000000000000000815250601701905060405160208183030381529060405280519060200120617126565b3373ffffffffffffffffffffffffffffffffffffffff167fa54764c62865ff0cd3f271fb1d4635662bff10f0878694f1654fb7fbdecb830d82604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a250565b6060600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206007018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015615cc65780601f10615c9b57610100808354040283529160200191615cc6565b820191906000526020600020905b815481529060010190602001808311615ca957829003601f168201915b50505050509050919050565b615cda61498b565b615d4c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415615def576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f43616e6e6f7420726567697374657220746865206e756c6c206164647265737381525060200191505060405180910390fd5b80600260016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f27fe5f0c1c3b1ed427cc63d0f05759ffdecf9aec9e18d31ef366fc8a6cb5dc3b60405160405180910390a250565b6060600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206006018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015615f4e5780601f10615f2357610100808354040283529160200191615f4e565b820191906000526020600020905b815481529060010190602001808311615f3157829003601f168201915b50505050509050919050565b615f6333612a5d565b615fd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208282909180600181540180825580915050906001820390600052602060002001600090919293909192939091929091925091906160529291906183b0565b50503373ffffffffffffffffffffffffffffffffffffffff167f15dfb3066a1bbbdaf9a7f62c47db990114058ae1739fd70a90361ea715bbf3c8838360405180806020018281038252848482818152602001925080828437600081840152601f19601f820116905080830192505050935050505060405180910390a25050565b60046020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806040518080618697603c9139603c0190506040518091039020888888604051602001808581526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019450505050506040516020818303038152906040528051906020012090507369baecd458e7c08b13a18e11887dbb078fb3cbb46334d1a233600754838888886040518663ffffffff1660e01b8152600401808681526020018581526020018460ff1660ff1681526020018381526020018281526020019550505050505060206040518083038186803b15801561623057600080fd5b505af4158015616244573d6000803e3d6000fd5b505050506040513d602081101561625a57600080fd5b81019080805190602001909291905050509150509695505050505050565b60006162b384848460405160200180838380828437808301925050509250505060405160208183030381529060405280519060200120617277565b90509392505050565b60018060008282540192505081905550600060015490506163268560405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f720000000000000000008152506017019050604051602081830303815290604052805190602001208686866175be565b6163768560405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f72000000000000000000815250601701905060405160208183030381529060405280519060200120613909565b61637e617737565b73ffffffffffffffffffffffffffffffffffffffff1663facd743b336040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156163fa57600080fd5b505afa15801561640e573d6000803e3d6000fd5b505050506040513d602081101561642457600080fd5b81019080805190602001909291905050501561648b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061875c6021913960400191505060405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167f16e382723fb40543364faf68863212ba253a099607bf6d3a5b47e50a8bf9494386604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a2600154811461657c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f7265656e7472616e742063616c6c00000000000000000000000000000000000081525060200191505060405180910390fd5b5050505050565b61658c33612a5d565b6165e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806185fd6036913960400191505060405180910390fd5b6040518060400160405280600073ffffffffffffffffffffffffffffffffffffffff1681526020016166136000617cbe565b815250600960003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101600082015181600001555050905050600073ffffffffffffffffffffffffffffffffffffffff167f3bff8b126c8f283f709ae37dc0d3fc03cae85ca4772cfb25b601f4b0b49ca6df60006040518082815260200191505060405180910390a2565b60006167588260405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e0000000000000081525060190190506040516020818303038152906040528051906020012061299b565b9050919050565b61676833612a5d565b6167bd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018061888c602f913960400191505060405180910390fd5b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905081816005019080519060200190616818929190618430565b503373ffffffffffffffffffffffffffffffffffffffff167fa6e2c5a23bb917ba0a584c4b250257ddad698685829b66a8813c004b39934fe4836040518080602001828103825283818151815260200191508051906020019080838360005b83811015616892578082015181840152602081019050616877565b50505050905090810190601f1680156168bf5780820380516001836020036101000a031916815260200191505b509250505060405180910390a25050565b60006168db82617034565b6168ef576168ea848484612313565b6168fb565b6168fa848484614d32565b5b90509392505050565b600260009054906101000a900460ff1615616987576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f636f6e747261637420616c726561647920696e697469616c697a65640000000081525060200191505060405180910390fd5b6001600260006101000a81548160ff0219169083151502179055506169ab33617e81565b6169b481615cd2565b6169bc6178ba565b50565b6000600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167fe553a3065d5a77d4ec2a0e0c31d49be4bf4d9f4c45883b2d67f61ba9c1b89c5d8284604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a25050565b616b5333612a5d565b616bc5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f556e6b6e6f776e206163636f756e74000000000000000000000000000000000081525060200191505060405180910390fd5b600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490508110616c7c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f496e76616c69642073746f7261676520726f6f7420696e64657800000000000081525060200191505060405180910390fd5b60006001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490500390506060600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110616d1257fe5b906000526020600020018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015616db05780601f10616d8557610100808354040283529160200191616db0565b820191906000526020600020905b815481529060010190602001808311616d9357829003601f168201915b50505050509050600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208281548110616e0157fe5b90600052602060002001600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208481548110616e5557fe5b906000526020600020019080546001816001161561010002031660029004616e7e9291906184b0565b50600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805480919060019003616ed19190618537565b503373ffffffffffffffffffffffffffffffffffffffff167fae0f2fa495a3eb65d46fe97b0baea8b6fd7edb243175c70f2455e6e83bc6fbaf82856040518080602001838152602001828103825284818151815260200191508051906020019080838360005b83811015616f52578082015181840152602081019050616f37565b50505050905090810190601f168015616f7f5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a2505050565b6040518080618697603c9139603c019050604051809103902081565b616fb661498b565b617028576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61703181617e81565b50565b600060405160200180807f63656c6f2e6f72672f636f72652f766f746500000000000000000000000000008152506012019050604051602081830303815290604052805190602001208214806170cf575060405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f7200000000000000000081525060170190506040516020818303038152906040528051906020012082145b8061711f575060405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e0000000000000081525060190190506040516020818303038152906040528051906020012082145b9050919050565b6171313383836168d0565b156171405761713f81612217565b5b600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600080820160006101000a81549060ff02191690556000820160016101000a81549060ff02191690555050803373ffffffffffffffffffffffffffffffffffffffff167fde9ce22cf1f8631ae2b668300f0493971114f40edd305173bd099ce7100fbe0b84604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a35050565b600061728282617034565b6172955761729083836122d0565b6172a0565b61729f838361299b565b5b905092915050565b6000600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600060405160200180807f63656c6f2e6f72672f636f72652f76616c696461746f720000000000000000008152506017019050604051602081830303815290604052805190602001208314156173b1578160010160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260010160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550617537565b60405160200180807f63656c6f2e6f72672f636f72652f6174746573746174696f6e00000000000000815250601901905060405160208183030381529060405280519060200120831415617475578160010160020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260010160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550617536565b60405160200180807f63656c6f2e6f72672f636f72652f766f74650000000000000000000000000000815250601201905060405160208183030381529060405280519060200120831415617535578160010160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008260010160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b5b3373ffffffffffffffffffffffffffffffffffffffff167fdd0b0d959c29750e7bfabbb7543a56957699d07edc512d2523ffe7502901ac198285604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a2505050565b6175ca85848484617fc5565b604051806040016040528060011515815260200160011515815250600660003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600086815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff021916908315150217905550905050833373ffffffffffffffffffffffffffffffffffffffff167f6cc56bd06daacce5b10fdf5ad1dc781941e14d7a71d29d33e7001e2956d14e0787604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a35050505050565b6000600260019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dcf0aaed60405160200180807f56616c696461746f727300000000000000000000000000000000000000000000815250600a019050604051602081830303815290604052805190602001206040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156177f257600080fd5b505afa158015617806573d6000803e3d6000fd5b505050506040513d602081101561781c57600080fd5b8101908080519060200190929190505050905090565b6000808284019050838110156178b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000469050604051808061877d60529139605201905060405180910390206040518060400160405280601381526020017f43656c6f20436f726520436f6e747261637473000000000000000000000000008152508051906020012060405180807f312e300000000000000000000000000000000000000000000000000000000000815250600301905060405180910390208330604051602001808681526020018581526020018481526020018381526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001955050505050506040516020818303038152906040528051906020012060078190555050565b6000600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a900460ff16159050919050565b60008073ffffffffffffffffffffffffffffffffffffffff16600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161480617b4357508273ffffffffffffffffffffffffffffffffffffffff16600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b905092915050565b600080600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614617c4d57617bef818585613026565b617c44576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806189416025913960400191505060405180910390fd5b80915050617cb0565b617c5684612a5d565b617cab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806185fd6036913960400191505060405180910390fd5b839150505b92915050565b600033905090565b617cc661839d565b6040518060200160405280838152509050919050565b617ce461839d565b604051806020016040528069d3c21bcecceda1000000815250905090565b6000816000015183600001511115905092915050565b6000617d28338787878787616105565b90508573ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614617dcb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f496e76616c6964207369676e617475726500000000000000000000000000000081525060200191505060405180910390fd5b617dd48661814e565b505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff16600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16149050919050565b600081600001519050919050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415617f07576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806186716026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60007369baecd458e7c08b13a18e11887dbb078fb3cbb46396ef41a1338686866040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018460ff1660ff16815260200183815260200182815260200194505050505060206040518083038186803b15801561806057600080fd5b505af4158015618074573d6000803e3d6000fd5b505050506040513d602081101561808a57600080fd5b810190808051906020019092919050505090508473ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161461813e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f496e76616c6964207369676e617475726500000000000000000000000000000081525060200191505060405180910390fd5b6181478561814e565b5050505050565b61815733612a5d565b6181ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603e815260200180618633603e913960400191505060405180910390fd5b6181b5816179c4565b80156181c757506181c63382617a1e565b5b61821c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260468152602001806187166046913960600191505060405180910390fd5b33600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106182de57805160ff191683800117855561830c565b8280016001018555821561830c579182015b8281111561830b5782518255916020019190600101906182f0565b5b5090506183199190618563565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061835e57803560ff191683800117855561838c565b8280016001018555821561838c579182015b8281111561838b578235825591602001919060010190618370565b5b5090506183999190618563565b5090565b6040518060200160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106183f157803560ff191683800117855561841f565b8280016001018555821561841f579182015b8281111561841e578235825591602001919060010190618403565b5b50905061842c9190618563565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061847157805160ff191683800117855561849f565b8280016001018555821561849f579182015b8281111561849e578251825591602001919060010190618483565b5b5090506184ac9190618563565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106184e95780548555618526565b8280016001018555821561852657600052602060002091601f016020900482015b8281111561852557825482559160010191906001019061850a565b5b5090506185339190618563565b5090565b81548183558181111561855e5781836000526020600020918201910161855d9190618588565b5b505050565b61858591905b80821115618581576000816000905550600101618569565b5090565b90565b6185b191905b808211156185ad57600081816185a491906185b4565b5060010161858e565b5090565b90565b50805460018160011615610100020316600290046000825580601f106185da57506185f9565b601f0160209004906000526020600020908101906185f89190618563565b5b5056fe4d75737420666972737420726567697374657220616464726573732077697468204163636f756e742e6372656174654163636f756e74556e6b6e6f776e206163636f756e743a2073656e646572206d7573742072656769737465722077697468206372656174654163636f756e742066697273744f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373417574686f72697a655369676e65722861646472657373206163636f756e742c61646472657373207369676e65722c6279746573333220726f6c652943616e6e6f7420617574686f72697a65206163636f756e74206173207369676e657242656e65666963696172792063616e6e6f7420626520616464726573732030783043616e6e6f742072652d617574686f72697a652061646472657373206f72206c6f636b656420676f6c64206163636f756e7420666f7220616e6f74686572206163636f756e7443616e6e6f7420617574686f72697a652076616c696461746f72207369676e6572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e7472616374294672616374696f6e206d757374206e6f742062652067726561746572207468616e2031556e6b6e6f776e204163636f756e743a2041646472657373207468617420617574686f72697a6564207369676e696e67206d75737420626520612072656769737465726564204163636f756e744163636f756e7420616c726561647920657869737473206f72206164647265737320697320616e20617574686f72697a6564207369676e657220666f7220616e6f74686572206163636f756e7452656769737465722077697468206372656174654163636f756e7420746f20736574206163636f756e74206e616d654d7573742066697273742072656769737465722073656e6465722077697468204163636f756e742e6372656174654163636f756e744d75737420617574686f72697a65207369676e6572206265666f72652073657474696e672061732064656661756c7443616e6e6f742072652d617574686f72697a652061646472657373207369676e65726e6f742061637469766520617574686f72697a6564207369676e657220666f7220726f6c654661696c656420746f20757064617465204543445341207075626c6963206b6579a265627a7a72315820c0fc4ba3b9ae1355f32ca611df67b02d52c491f199f7667c27a4a04273d28bc464736f6c634300050d0032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : test (bool): True
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode Sourcemap
445:42647:5:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;445:42647:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16475:143;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;16475:143:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;27744:255;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;27744:255:5;;;;;;;;;;;;;;;;;:::i;:::-;;35452:144;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;35452:144:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;30683:172;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;30683:172:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;10956:496;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;10956:496:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;10956:496:5;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;10956:496:5;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;10956:496:5;;;;;;;;;;;;:::i;:::-;;21193:334;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;21193:334:5;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;21193:334:5;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;21193:334:5;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;21193:334:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;21193:334:5;;;;;;;;;;;;;;;:::i;:::-;;28679:188;;;:::i;:::-;;35198:142;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;35198:142:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;319:23:7;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;18151:124:5;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;18151:124:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;36083:107;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;36083:107:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;12706:843;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;12706:843:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;12706:843:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;12706:843:5;;;;;;;;;;;;;;;;;;;6316:83;;;:::i;:::-;;34251:124;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;34251:124:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;9389:286;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;9389:286:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;31642:253;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;31642:253:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;18492:127;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;18492:127:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;34591:134;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;34591:134:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;18896:117;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25847:504;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;25847:504:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;3160:36;;;:::i;:::-;;;;;;;;;;;;;;;;;;;33399:217;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;33399:217:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;17161:112;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;17161:112:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;17161:112:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16125:133;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;16125:133:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;34931:138;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;34931:138:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;32221:146;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;32221:146:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;14811:138;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;14811:138:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;1684:137:3;;;:::i;:::-;;23047:1032:5;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;23047:1032:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;7501:270;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;7501:270:5;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;7501:270:5;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;7501:270:5;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;7501:270:5;;;;;;;;;;;;:::i;:::-;;3264:55;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3264:55:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;3264:55:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29427:216;;;:::i;:::-;;25346:279;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;25346:279:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;3352:25:9;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;14339:152:5;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;14339:152:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;33869:190;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;33869:190:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;11698:764;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;11698:764:5;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;11698:764:5;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;11698:764:5;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;11698:764:5;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;11698:764:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;11698:764:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32620:526;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;32620:526:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;899:77:3;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;1250:92;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;21948:523:5;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;21948:523:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;7025:352;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;7025:352:5;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;7025:352:5;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;7025:352:5;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;7025:352:5;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;7025:352:5;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;7025:352:5;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;7025:352:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;29915:496;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;29915:496:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;24580:368;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;24580:368:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;15223:342;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;15223:342:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;20501:520;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;20501:520:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;19111:360;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;13767:232;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;13767:232:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26580:679;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;26580:679:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;29042:208;;;:::i;:::-;;17470:126;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;17470:126:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;17470:126:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3956:230:9;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;3956:230:9;;;;;;;;;;;;;;;;;;;:::i;:::-;;17835:137:5;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;17835:137:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;17835:137:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7893:213;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;7893:213:5;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;7893:213:5;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;7893:213:5;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;7893:213:5;;;;;;;;;;;;:::i;:::-;;2618:47;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;2618:47:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;36752:386;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;36752:386:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;15743:175;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;15743:175:5;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;15743:175:5;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;15743:175:5;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;15743:175:5;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;10079:398;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;10079:398:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;22587:280;;;:::i;:::-;;16839:147;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;16839:147:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;19569:256;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;19569:256:5;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;19569:256:5;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;19569:256:5;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;19569:256:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;19569:256:5;;;;;;;;;;;;;;;:::i;:::-;;31126:254;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;31126:254:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;6045:174;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;6045:174:5;;;;;;;;;;;;;;;;;;;:::i;:::-;;27379:218;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;27379:218:5;;;;;;;;;;;;;;;;;:::i;:::-;;8463:535;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;8463:535:5;;;;;;;;;;;;;;;;;:::i;:::-;;3020:136;;;:::i;:::-;;;;;;;;;;;;;;;;;;;1970:107:3;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1970:107:3;;;;;;;;;;;;;;;;;;;:::i;:::-;;37267:155:5;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;37267:155:5;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;28242:266;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;28242:266:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;35710:187;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;35710:187:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;16475:143;16553:4;16572:41;16588:7;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;16572:15;:41::i;:::-;16565:48;;16475:143;;;:::o;27744:255::-;27800:17;27820:34;27837:10;27849:4;27820:16;:34::i;:::-;27800:54;;27860:18;27873:4;27860:12;:18::i;:::-;:73;;27908:25;27928:4;27908:19;:25::i;:::-;27860:73;;;27881:24;27900:4;27881:18;:24::i;:::-;27860:73;27966:10;27945:49;;;27978:9;27989:4;27945:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;27744:255;;:::o;35452:144::-;35530:4;35584:7;35549:42;;:31;35566:7;35575:4;35549:16;:31::i;:::-;:42;;;;35542:49;;35452:144;;;;:::o;30683:172::-;30792:4;30844:6;30811:39;;:14;:23;30826:7;30811:23;;;;;;;;;;;;;;;:29;30835:4;30811:29;;;;;;;;;;;;;;;;;;;;;:39;;;30804:46;;30683:172;;;;;:::o;10956:496::-;835:1:17;818:13;;:18;;;;;;;;;;;842:20;865:13;;842:36;;11133:68:5;11168:6;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;11193:1;11196;11199;11133:34;:68::i;:::-;11207:41;11224:6;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;11207:16;:41::i;:::-;11270:15;:13;:15::i;:::-;:36;;;11307:10;11319:6;11327:14;;11270:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;11270:72:5;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11270:72:5;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;11270:72:5;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;11270:72:5;;;;;;;;;;;;;;;;11255:136;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11428:10;11402:45;;;11440:6;11402:45;;;;;;;;;;;;;;;;;;;;;;915:13:17;;899:12;:29;891:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10956:496:5;;;;;;;:::o;21193:334::-;21311:2;21283:17;:24;:30;;21275:75;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21356:23;21382:8;:20;21391:10;21382:20;;;;;;;;;;;;;;;21356:46;;21436:17;21408:7;:25;;:45;;;;;;;;;;;;:::i;:::-;;21492:10;21464:58;;;21504:17;21464:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;21464:58:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21193:334;;:::o;28679:188::-;28720:14;28737:39;28753:10;3692:38;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3692:38:5;;;3682:49;;;;;;28737:15;:39::i;:::-;28720:56;;28782:32;28795:6;3692:38;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3692:38:5;;;3682:49;;;;;;28782:12;:32::i;:::-;28843:10;28825:37;;;28855:6;28825:37;;;;;;;;;;;;;;;;;;;;;;28679:188;:::o;35198:142::-;35275:4;35328:7;35294:41;;:30;35310:7;35319:4;35294:15;:30::i;:::-;:41;;;;35287:48;;35198:142;;;;:::o;319:23:7:-;;;;;;;;;;;;;:::o;18151:124:5:-;18217:7;18239:8;:17;18248:7;18239:17;;;;;;;;;;;;;;;:31;;;;;;;;;;;;18232:38;;18151:124;;;:::o;36083:107::-;36140:4;36160:8;:17;36169:7;36160:17;;;;;;;;;;;;;;;:24;;;;;;;;;;;;36152:33;;36083:107;;;:::o;12706:843::-;12787:12;12801:16;12833:18;12843:7;12833:9;:18::i;:::-;12825:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12877:19;12899:20;:29;12920:7;12899:29;;;;;;;;;;;;;;;:36;;;;12877:58;;12941:19;12963:1;12941:23;;12975:9;12987:1;12975:13;;12970:127;12994:11;12990:1;:15;12970:127;;;13034:56;13050:20;:29;13071:7;13050:29;;;;;;;;;;;;;;;13080:1;13050:32;;;;;;;;;;;;;;;:39;;;;;;;;;;;;;;;;13034:11;:15;;:56;;;;:::i;:::-;13020:70;;13007:3;;;;;;;12970:127;;;;13103:25;13141:11;13131:22;;;;;;;;;;;;;;;;;;;;;;;;;29:1:-1;21:6;17:14;116:4;104:10;96:6;87:34;147:4;139:6;135:17;125:27;;0:156;13131:22:5;;;;13103:50;;13159:17;13179:1;13159:21;;13186:24;13227:11;13213:26;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;148:4;140:6;136:17;126:27;;0:157;13213:26:5;;;;13186:53;;13250:9;13262:1;13250:13;;13245:263;13269:11;13265:1;:15;13245:263;;;13295:18;13316:20;:29;13337:7;13316:29;;;;;;;;;;;;;;;13346:1;13316:32;;;;;;;;;;;;;;;13295:53;;13369:4;:11;;;;;;;;;;;;;;;;13356:7;13364:1;13356:10;;;;;;;;;;;;;:24;;;;;13393:9;13405:1;13393:13;;13388:114;13412:7;13420:1;13412:10;;;;;;;;;;;;;;13408:1;:14;13388:114;;;13465:4;13470:1;13465:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;13439:12;13452:9;13439:23;;;;;;;;;;;:33;;;;;;;;;;;13482:11;;;;;;;13424:3;;;;;;;13388:114;;;;13245:263;13282:3;;;;;;;13245:263;;;;13522:12;13536:7;13514:30;;;;;;;;;12706:843;;;:::o;6316:83::-;6367:27;:25;:27::i;:::-;6316:83::o;34251:124::-;34312:7;34334:36;34350:7;3692:38;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3692:38:5;;;3682:49;;;;;;34334:15;:36::i;:::-;34327:43;;34251:124;;;:::o;9389:286::-;835:1:17;818:13;;:18;;;;;;;;;;;842:20;865:13;;842:36;;9513:63:5;9548:6;3692:38;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3692:38:5;;;3682:49;;;;;;9568:1;9571;9574;9513:34;:63::i;:::-;9582:36;9599:6;3692:38;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3692:38:5;;;3682:49;;;;;;9582:16;:36::i;:::-;9651:10;9630:40;;;9663:6;9630:40;;;;;;;;;;;;;;;;;;;;;;915:13:17;;899:12;:29;891:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9389:286:5;;;;;:::o;31642:253::-;31728:4;31753:37;31768:7;31777:6;31785:4;31753:14;:37::i;:::-;:137;;;;31801:20;:29;31822:7;31801:29;;;;;;;;;;;;;;;:35;31831:4;31801:35;;;;;;;;;;;:43;31837:6;31801:43;;;;;;;;;;;;;;;:53;;;;;;;;;;;;:88;;;;;31882:7;31858:31;;:12;:20;31871:6;31858:20;;;;;;;;;;;;;;;;;;;;;;;;;:31;;;31801:88;31753:137;31740:150;;31642:253;;;;;:::o;18492:127::-;18559:4;18611:1;18579:34;;:12;:20;18592:6;18579:20;;;;;;;;;;;;;;;;;;;;;;;;;:34;;;;18571:43;;18492:127;;;:::o;34591:134::-;34657:7;34679:41;34695:7;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;34679:15;:41::i;:::-;34672:48;;34591:134;;;:::o;18896:117::-;18947:7;18956;18965;18974;18997:1;19000;19003;19006;18989:19;;;;;;;;;;;;;;;;;;;;18896:117;;;;:::o;25847:504::-;25923:21;25933:10;25923:9;:21::i;:::-;25915:87;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26023:20;26036:6;26023:12;:20::i;:::-;:82;;;;;26047:58;26086:10;26098:6;26047:38;:58::i;:::-;26023:82;26008:147;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26211:72;;;;;;;;26248:4;26211:72;;;;;;26271:5;26211:72;;;;;26162:20;:32;26183:10;26162:32;;;;;;;;;;;;;;;:38;26195:4;26162:38;;;;;;;;;;;:46;26201:6;26162:46;;;;;;;;;;;;;;;:121;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26341:4;26321:10;26294:52;;;26333:6;26294:52;;;;;;;;;;;;;;;;;;;;;;25847:504;;:::o;3160:36::-;;;;:::o;33399:217::-;33477:7;33492:21;33516:14;:23;33531:7;33516:23;;;;;;;;;;;;;;;:29;33540:4;33516:29;;;;;;;;;;;;;;;;;;;;;33492:53;;33583:1;33558:27;;:13;:27;;;:53;;33598:13;33558:53;;;33588:7;33558:53;33551:60;;;33399:217;;;;:::o;17161:112::-;17218:13;17246:8;:17;17255:7;17246:17;;;;;;;;;;;;;;;:22;;17239:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17161:112;;;:::o;16125:133::-;16198:4;16217:36;16233:7;3692:38;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3692:38:5;;;3682:49;;;;;;16217:15;:36::i;:::-;16210:43;;16125:133;;;:::o;34931:138::-;34999:7;35021:43;35037:7;3602:45;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3602:45:5;;;3592:56;;;;;;35021:15;:43::i;:::-;35014:50;;34931:138;;;:::o;32221:146::-;32292:7;32314:48;32338:6;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;32314:23;:48::i;:::-;32307:55;;32221:146;;;:::o;14811:138::-;14879:7;14901:43;14925:6;3692:38;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3692:38:5;;;3682:49;;;;;;14901:23;:43::i;:::-;14894:50;;14811:138;;;:::o;1684:137:3:-;1103:9;:7;:9::i;:::-;1095:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1782:1;1745:40;;1766:6;;;;;;;;;;;1745:40;;;;;;;;;;;;1812:1;1795:6;;:19;;;;;;;;;;;;;;;;;;1684:137::o;23047:1032:5:-;23124:21;23134:10;23124:9;:21::i;:::-;23116:88;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23218:20;23231:6;23218:12;:20::i;:::-;23210:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23298:58;23337:10;23349:6;23298:38;:58::i;:::-;23283:118;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23415:34;23424:10;23436:6;23444:4;23415:8;:34::i;:::-;23407:94;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23508:23;23534:8;:20;23543:10;23534:20;;;;;;;;;;;;;;;23508:46;;23564:18;23577:4;23564:12;:18::i;:::-;23560:461;;;3692:38;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3692:38:5;;;3682:49;;;;;;23596:4;:18;23592:252;;;23649:6;23626:7;:15;;:20;;;:29;;;;;;;;;;;;;;;;;;23592:252;;;3602:45;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3602:45:5;;;3592:56;;;;;;23674:4;:25;23670:174;;;23741:6;23711:7;:15;;:27;;;:36;;;;;;;;;;;;;;;;;;23670:174;;;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;23766:4;:23;23762:82;;;23829:6;23801:7;:15;;:25;;;:34;;;;;;;;;;;;;;;;;;23762:82;23670:174;23592:252;23872:10;23856:41;;;23884:6;23892:4;23856:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;23560:461;;;23953:6;23918:14;:26;23933:10;23918:26;;;;;;;;;;;;;;;:32;23945:4;23918:32;;;;;;;;;;;;:41;;;;;;;;;;;;;;;;;;23989:10;23972:42;;;24001:6;24009:4;23972:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;23560:461;24049:10;24032:42;;;24061:6;24069:4;24032:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;23047:1032;;;:::o;7501:270::-;7577:21;7587:10;7577:9;:21::i;:::-;7569:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7624:23;7650:8;:20;7659:10;7650:20;;;;;;;;;;;;;;;7624:46;;7698:11;;7676:7;:19;;:33;;;;;;;:::i;:::-;;7742:10;7720:46;;;7754:11;;7720:46;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;7720:46:5;;;;;;;;;;;;;;7501:270;;;:::o;3264:55::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;29427:216::-;29475:14;29492:46;29508:10;3602:45;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3602:45:5;;;3592:56;;;;;;29492:15;:46::i;:::-;29475:63;;29544:39;29557:6;3602:45;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3602:45:5;;;3592:56;;;;;;29544:12;:39::i;:::-;29619:10;29594:44;;;29631:6;29594:44;;;;;;;;;;;;;;;;;;;;;;29427:216;:::o;25346:279::-;25442:70;25477:6;3602:45;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3602:45:5;;;3592:56;;;;;;25504:1;25507;25510;25442:34;:70::i;:::-;25518:43;25535:6;3602:45;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3602:45:5;;;3592:56;;;;;;25518:16;:43::i;:::-;25601:10;25573:47;;;25613:6;25573:47;;;;;;;;;;;;;;;;;;;;;;25346:279;;;;:::o;3352:25:9:-;;;;;;;;;;;;;:::o;14339:152:5:-;14414:7;14436:50;14460:6;3602:45;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3602:45:5;;;3592:56;;;;;;14436:23;:50::i;:::-;14429:57;;14339:152;;;:::o;33869:190::-;33947:7;33969:18;33982:4;33969:12;:18::i;:::-;:85;;34023:31;34040:7;34049:4;34023:16;:31::i;:::-;33969:85;;;33990:30;34006:7;34015:4;33990:15;:30::i;:::-;33969:85;33962:92;;33869:190;;;;:::o;11698:764::-;11794:16;11812:12;11832:17;11852:1;11832:21;;11859:22;11898:15;;:22;;11884:37;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;148:4;140:6;136:17;126:27;;0:157;11884:37:5;;;;11859:62;;11932:9;11944:1;11932:13;;11927:185;11951:15;;:22;;11947:1;:26;11927:185;;;12014:8;:28;12023:15;;12039:1;12023:18;;;;;;;;;;;;;;;12014:28;;;;;;;;;;;;;;;:40;;12008:54;;;;;;;;;;;;;;;;11997:5;12003:1;11997:8;;;;;;;;;;;;;:65;;;;;12082:23;12096:5;12102:1;12096:8;;;;;;;;;;;;;;12082:9;:13;;:23;;;;:::i;:::-;12070:35;;11979:8;11985:1;11979;:5;;:8;;;;:::i;:::-;11975:12;;11927:185;;;;12118:17;12148:9;12138:20;;;;;;;;;;;;;;;;;;;;;;;;;29:1:-1;21:6;17:14;116:4;104:10;96:6;87:34;147:4;139:6;135:17;125:27;;0:156;12138:20:5;;;;12118:40;;12164:15;12182:1;12164:19;;12194:9;12206:1;12194:13;;12189:243;12213:15;;:22;;12209:1;:26;12189:243;;;12264:9;12276:1;12264:13;;12259:167;12283:5;12289:1;12283:8;;;;;;;;;;;;;;12279:1;:12;12259:167;;;12339:8;:28;12348:15;;12364:1;12348:18;;;;;;;;;;;;;;;12339:28;;;;;;;;;;;;;;;:40;;12381:1;12333:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12317:4;12322:7;12317:13;;;;;;;;;;;:66;;;;;;;;;;;12403:14;12415:1;12403:7;:11;;:14;;;;:::i;:::-;12393:24;;12297:8;12303:1;12297;:5;;:8;;;;:::i;:::-;12293:12;;12259:167;;;;12241:8;12247:1;12241;:5;;:8;;;;:::i;:::-;12237:12;;12189:243;;;;12445:5;12452:4;12437:20;;;;;;;;11698:764;;;;;:::o;32620:526::-;32698:7;32721:18;32734:4;32721:12;:18::i;:::-;32713:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32778:23;32804:8;:18;32813:8;32804:18;;;;;;;;;;;;;;;32778:44;;32828:14;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;32852:4;:23;32848:240;;;32894:7;:15;;:25;;;;;;;;;;;;32885:34;;32848:240;;;3602:45;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3602:45:5;;;3592:56;;;;;;32936:4;:25;32932:156;;;32980:7;:15;;:27;;;;;;;;;;;;32971:36;;32932:156;;;3692:38;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3692:38:5;;;3682:49;;;;;;33024:4;:18;33020:68;;;33061:7;:15;;:20;;;;;;;;;;;;33052:29;;33020:68;32932:156;32848:240;33119:1;33101:20;;:6;:20;;;:40;;33135:6;33101:40;;;33124:8;33101:40;33094:47;;;;32620:526;;;;:::o;899:77:3:-;937:7;963:6;;;;;;;;;;;956:13;;899:77;:::o;1250:92::-;1290:4;1329:6;;;;;;;;;;;1313:22;;:12;:10;:12::i;:::-;:22;;;1306:29;;1250:92;:::o;21948:523:5:-;22038:21;22048:10;22038:9;:21::i;:::-;22030:88;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22155:1;22132:25;;:11;:25;;;;22124:71;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22201:29;;:::i;:::-;22233:26;22250:8;22233:16;:26::i;:::-;22201:58;;22273:27;22279:20;:18;:20::i;:::-;22273:1;:5;;:27;;;;:::i;:::-;22265:75;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22379:33;;;;;;;;22397:11;22379:33;;;;;;22410:1;22379:33;;;22346:18;:30;22365:10;22346:30;;;;;;;;;;;;;;;:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22444:11;22423:43;;;22457:8;22423:43;;;;;;;;;;;;;;;;;;21948:523;;;:::o;7025:352::-;7203:21;7213:10;7203:9;:21::i;:::-;7198:58;;7234:15;:13;:15::i;:::-;;7198:58;7261:13;7269:4;;7261:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;7261:13:5;;;;;;:7;:13::i;:::-;7280:46;7308:17;;7280:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;7280:46:5;;;;;;:27;:46::i;:::-;7332:40;7349:13;7364:1;7367;7370;7332:16;:40::i;:::-;7025:352;;;;;;;;:::o;29915:496::-;30024:4;30036:23;30062:8;:18;30071:8;30062:18;;;;;;;;;;;;;;;30036:44;;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;30090:4;:23;:62;;;;;30146:6;30117:35;;:7;:15;;:25;;;;;;;;;;;;:35;;;30090:62;30086:321;;;30169:4;30162:11;;;;;30086:321;3602:45;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3602:45:5;;;3592:56;;;;;;30190:4;:25;:66;;;;;30250:6;30219:37;;:7;:15;;:27;;;;;;;;;;;;:37;;;30190:66;30186:221;;;30273:4;30266:11;;;;;30186:221;3692:38;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3692:38:5;;;3682:49;;;;;;30294:4;:18;:52;;;;;30340:6;30316:30;;:7;:15;;:20;;;;;;;;;;;;:30;;;30294:52;30290:117;;;30363:4;30356:11;;;;;30290:117;30395:5;30388:12;;;29915:496;;;;;;:::o;24580:368::-;24716:47;24741:6;24749:4;24755:1;24758;24761;24716:24;:47::i;:::-;24818:71;;;;;;;;24855:4;24818:71;;;;;;24878:4;24818:71;;;;;24769:20;:32;24790:10;24769:32;;;;;;;;;;;;;;;:38;24802:4;24769:38;;;;;;;;;;;:46;24808:6;24769:46;;;;;;;;;;;;;;;:120;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24938:4;24918:10;24901:42;;;24930:6;24901:42;;;;;;;;;;;;;;;;;;;;;;24580:368;;;;;:::o;15223:342::-;15287:7;15302:26;15331:12;:20;15344:6;15331:20;;;;;;;;;;;;;;;;;;;;;;;;;15302:49;;15391:1;15361:32;;:18;:32;;;15357:204;;15410:18;15403:25;;;;;15357:204;15457:17;15467:6;15457:9;:17::i;:::-;15449:84;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15548:6;15541:13;;;15223:342;;;;:::o;20501:520::-;20602:21;20612:10;20602:9;:21::i;:::-;20594:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20672:10;20655:27;;:13;:27;;;:60;;;;20711:3;20686:29;;:13;:29;;;20655:60;20649:212;;20726:14;20743:10;:29;20773:10;20785:1;20788;20791;20743:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;20743:50:5;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;20743:50:5;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;20743:50:5;;;;;;;;;;;;;;;;20726:67;;20819:13;20809:23;;:6;:23;;;20801:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20649:212;;20866:23;20892:8;:20;20901:10;20892:20;;;;;;;;;;;;;;;20866:46;;20942:13;20918:7;:21;;;:37;;;;;;;;;;;;;;;;;;20990:10;20966:50;;;21002:13;20966:50;;;;;;;;;;;;;;;;;;;;;;20501:520;;;;;:::o;19111:360::-;19152:4;19179:24;19192:10;19179:12;:24::i;:::-;:61;;;;;19207:33;19229:10;19207:21;:33::i;:::-;19179:61;19164:169;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19339:23;19365:8;:20;19374:10;19365:20;;;;;;;;;;;;;;;19339:46;;19408:4;19391:7;:14;;;:21;;;;;;;;;;;;;;;;;;19438:10;19423:26;;;;;;;;;;;;19462:4;19455:11;;;19111:360;:::o;13767:232::-;13837:7;13846;13861:36;13900:18;:27;13919:7;13900:27;;;;;;;;;;;;;;;13861:66;;13941:10;:22;;;;;;;;;;;;13965:28;:10;:19;;:26;;;;;;;;;;;;;;;;;;:28::i;:::-;13933:61;;;;;13767:232;;;:::o;26580:679::-;26676:18;26686:7;26676:9;:18::i;:::-;26661:126;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26808:24;26821:10;26808:12;:24::i;:::-;:87;;;;;26836:59;26875:7;26884:10;26836:38;:59::i;:::-;26808:87;26793:152;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27025:4;26966:63;;:20;:29;26987:7;26966:29;;;;;;;;;;;;;;;:35;26996:4;26966:35;;;;;;;;;;;:47;27002:10;26966:47;;;;;;;;;;;;;;;:55;;;;;;;;;;;;:63;;;26951:126;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27111:7;27084:12;:24;27097:10;27084:24;;;;;;;;;;;;;;;;:34;;;;;;;;;;;;;;;;;;27184:4;27124:20;:29;27145:7;27124:29;;;;;;;;;;;;;;;:35;27154:4;27124:35;;;;;;;;;;;:47;27160:10;27124:47;;;;;;;;;;;;;;;:57;;;:64;;;;;;;;;;;;;;;;;;27249:4;27228:7;27199:55;;;27237:10;27199:55;;;;;;;;;;;;;;;;;;;;;;26580:679;;:::o;29042:208::-;29088:14;29105:44;29121:10;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;29105:15;:44::i;:::-;29088:61;;29155:37;29168:6;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;29155:12;:37::i;:::-;29226:10;29203:42;;;29238:6;29203:42;;;;;;;;;;;;;;;;;;;;;;29042:208;:::o;17470:126::-;17534:13;17562:8;:17;17571:7;17562:17;;;;;;;;;;;;;;;:29;;17555:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17470:126;;;:::o;3956:230:9:-;1103:9:3;:7;:9::i;:::-;1095:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4060:1:9;4033:29;;:15;:29;;;;4025:74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4126:15;4105:8;;:37;;;;;;;;;;;;;;;;;;4165:15;4153:28;;;;;;;;;;;;3956:230;:::o;17835:137:5:-;17905:12;17932:8;:17;17941:7;17932:17;;;;;;;;;;;;;;;:35;;17925:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;17835:137;;;:::o;7893:213::-;7960:21;7970:10;7960:9;:21::i;:::-;7952:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8007:20;:32;8028:10;8007:32;;;;;;;;;;;;;;;8045:3;;8007:42;;;39:1:-1;33:3;27:10;23:18;57:10;52:3;45:23;79:10;72:17;;0:93;8007:42:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;8085:10;8060:41;;;8097:3;;8060:41;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;8060:41:5;;;;;;;;;;;;;;7893:213;;:::o;2618:47::-;;;;;;;;;;;;;;;;;;;;;;:::o;36752:386::-;36915:7;36930:18;3083:73;;;;;;;;;;;;;;;;;;;37013:7;37022:6;37030:4;36968:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;36968:67:5;;;36951:90;;;;;;36930:111;;37054:10;:35;37090:21;;37113:10;37125:1;37128;37131;37054:79;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;37054:79:5;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37054:79:5;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;37054:79:5;;;;;;;;;;;;;;;;37047:86;;;36752:386;;;;;;;;:::o;15743:175::-;15834:4;15853:60;15870:7;15906:4;;15889:22;;;;;;;30:3:-1;22:6;14;1:33;57:3;49:6;45:16;35:26;;15889:22:5;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;15889:22:5;;;15879:33;;;;;;15853:16;:60::i;:::-;15846:67;;15743:175;;;;;:::o;10079:398::-;835:1:17;818:13;;:18;;;;;;;;;;;842:20;865:13;;842:36;;10208:68:5;10243:6;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;10268:1;10271;10274;10208:34;:68::i;:::-;10282:41;10299:6;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;10282:16;:41::i;:::-;10339:15;:13;:15::i;:::-;:27;;;10367:10;10339:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10339:39:5;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10339:39:5;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;10339:39:5;;;;;;;;;;;;;;;;10338:40;10330:86;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10453:10;10427:45;;;10465:6;10427:45;;;;;;;;;;;;;;;;;;;;;;915:13:17;;899:12;:29;891:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10079:398:5;;;;;:::o;22587:280::-;22643:21;22653:10;22643:9;:21::i;:::-;22635:88;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22762:52;;;;;;;;22788:3;22762:52;;;;;;22794:19;22811:1;22794:16;:19::i;:::-;22762:52;;;22729:18;:30;22748:10;22729:30;;;;;;;;;;;;;;;:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22854:3;22825:37;;;22860:1;22825:37;;;;;;;;;;;;;;;;;;22587:280::o;16839:147::-;16919:4;16938:43;16954:7;3602:45;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3602:45:5;;;3592:56;;;;;;16938:15;:43::i;:::-;16931:50;;16839:147;;;:::o;19569:256::-;19627:21;19637:10;19627:9;:21::i;:::-;19619:81;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19706:23;19732:8;:20;19741:10;19732:20;;;;;;;;;;;;;;;19706:46;;19773:4;19758:7;:12;;:19;;;;;;;;;;;;:::i;:::-;;19803:10;19788:32;;;19815:4;19788:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;19788:32:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19569:256;;:::o;31126:254::-;31235:4;31260:18;31273:4;31260:12;:18::i;:::-;:115;;31337:38;31353:7;31362:6;31370:4;31337:15;:38::i;:::-;31260:115;;;31289:37;31304:7;31313:6;31321:4;31289:14;:37::i;:::-;31260:115;31247:128;;31126:254;;;;;:::o;6045:174::-;476:11:7;;;;;;;;;;;475:12;467:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;540:4;526:11;;:18;;;;;;;;;;;;;;;;;;6117:30:5;6136:10;6117:18;:30::i;:::-;6153:28;6165:15;6153:11;:28::i;:::-;6187:27;:25;:27::i;:::-;6045:174;:::o;27379:218::-;27435:14;27452;:26;27467:10;27452:26;;;;;;;;;;;;;;;:32;27479:4;27452:32;;;;;;;;;;;;;;;;;;;;;27435:49;;27533:1;27490:14;:26;27505:10;27490:26;;;;;;;;;;;;;;;:32;27517:4;27490:32;;;;;;;;;;;;:45;;;;;;;;;;;;;;;;;;27567:10;27546:46;;;27579:6;27587:4;27546:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;27379:218;;:::o;8463:535::-;8528:21;8538:10;8528:9;:21::i;:::-;8520:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8591:20;:32;8612:10;8591:32;;;;;;;;;;;;;;;:39;;;;8583:5;:47;8575:86;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8667:17;8729:1;8687:20;:32;8708:10;8687:32;;;;;;;;;;;;;;;:39;;;;:43;8667:63;;8736:16;8755:20;:32;8776:10;8755:32;;;;;;;;;;;;;;;8788:5;8755:39;;;;;;;;;;;;;;;8736:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8842:20;:32;8863:10;8842:32;;;;;;;;;;;;;;;8875:9;8842:43;;;;;;;;;;;;;;;8800:20;:32;8821:10;8800:32;;;;;;;;;;;;;;;8833:5;8800:39;;;;;;;;;;;;;;;:85;;;;;;;;;;;;;;;;;;;;:::i;:::-;;8891:20;:32;8912:10;8891:32;;;;;;;;;;;;;;;:41;;;;;;;;;;;;:::i;:::-;;8970:10;8943:50;;;8982:3;8987:5;8943:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;8943:50:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8463:535;;;:::o;3020:136::-;3083:73;;;;;;;;;;;;;;;;;;;3020:136;:::o;1970:107:3:-;1103:9;:7;:9::i;:::-;1095:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2042:28;2061:8;2042:18;:28::i;:::-;1970:107;:::o;37267:155:5:-;37324:4;3692:38;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3692:38:5;;;3682:49;;;;;;37343:4;:18;:45;;;;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;37365:4;:23;37343:45;:74;;;;3602:45;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3602:45:5;;;3592:56;;;;;;37392:4;:25;37343:74;37336:81;;37267:155;;;:::o;28242:266::-;28311:41;28327:10;28339:6;28347:4;28311:15;:41::i;:::-;28307:87;;;28362:25;28382:4;28362:19;:25::i;:::-;28307:87;28407:20;:32;28428:10;28407:32;;;;;;;;;;;;;;;:38;28440:4;28407:38;;;;;;;;;;;:46;28446:6;28407:46;;;;;;;;;;;;;;;;28400:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28498:4;28478:10;28464:39;;;28490:6;28464:39;;;;;;;;;;;;;;;;;;;;;;28242:266;;:::o;35710:187::-;35788:4;35807:18;35820:4;35807:12;:18::i;:::-;:85;;35861:31;35878:7;35887:4;35861:16;:31::i;:::-;35807:85;;;35828:30;35844:7;35853:4;35828:15;:30::i;:::-;35807:85;35800:92;;35710:187;;;;:::o;40161:564::-;40217:23;40243:8;:20;40252:10;40243:20;;;;;;;;;;;;;;;40217:46;;40270:14;3507:43;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3507:43:5;;;3497:54;;;;;;40294:4;:23;40290:375;;;40336:7;:15;;:25;;;;;;;;;;;;40327:34;;40405:1;40369:7;:15;;:25;;;:38;;;;;;;;;;;;;;;;;;40290:375;;;3602:45;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3602:45:5;;;3592:56;;;;;;40424:4;:25;40420:245;;;40468:7;:15;;:27;;;;;;;;;;;;40459:36;;40541:1;40503:7;:15;;:27;;;:40;;;;;;;;;;;;;;;;;;40420:245;;;3692:38;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;3692:38:5;;;3682:49;;;;;;40560:4;:18;40556:109;;;40597:7;:15;;:20;;;;;;;;;;;;40588:29;;40656:1;40625:7;:15;;:20;;;:33;;;;;;;;;;;;;;;;;;40556:109;40420:245;40290:375;40695:10;40675:45;;;40707:6;40715:4;40675:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;40161:564;;;:::o;39560:361::-;39703:33;39720:6;39728:1;39731;39734;39703:16;:33::i;:::-;39791:71;;;;;;;;39828:4;39791:71;;;;;;39851:4;39791:71;;;;;39742:20;:32;39763:10;39742:32;;;;;;;;;;;;;;;:38;39775:4;39742:38;;;;;;;;;;;:46;39781:6;39742:46;;;;;;;;;;;;;;;:120;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39911:4;39891:10;39874:42;;;39903:6;39874:42;;;;;;;;;;;;;;;;;;;;;;39560:361;;;;;:::o;6385:143:9:-;6433:11;6471:8;;;;;;;;;;;:27;;;2692:30;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;2692:30:9;;;2682:41;;;;;;6471:51;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;6471:51:9;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;6471:51:9;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;6471:51:9;;;;;;;;;;;;;;;;6452:71;;6385:143;:::o;834:176:2:-;892:7;911:9;927:1;923;:5;911:17;;951:1;946;:6;;938:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1002:1;995:8;;;834:176;;;;:::o;37519:430:5:-;37571:15;37620:7;37609:18;;37700:115;;;;;;;;;;;;;;;;;;;37835:28;;;;;;;;;;;;;;;;;37825:39;;;;;;37874:16;;;;;;;;;;;;;;;;;;;37900:7;37925:4;37680:258;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;37680:258:5;;;37663:281;;;;;;37639:21;:305;;;;37519:430;:::o;38135:113::-;38197:4;38218:8;:17;38227:7;38218:17;;;;;;;;;;;;;;;:24;;;;;;;;;;;;38217:25;38209:34;;38135:113;;;:::o;38937:211::-;39053:4;39105:1;39073:34;;:12;:20;39086:6;39073:20;;;;;;;;;;;;;;;;;;;;;;;;;:34;;;:69;;;;39135:7;39111:31;;:12;:20;39124:6;39111:20;;;;;;;;;;;;;;;;;;;;;;;;;:31;;;39073:69;39065:78;;38937:211;;;;:::o;39152:404::-;39238:7;39253:15;39271:12;:20;39284:6;39271:20;;;;;;;;;;;;;;;;;;;;;;;;;39253:38;;39320:1;39301:21;;:7;:21;;;39297:145;;39340:31;39349:7;39358:6;39366:4;39340:8;:31::i;:::-;39332:81;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39428:7;39421:14;;;;;39297:145;39456:17;39466:6;39456:9;:17::i;:::-;39448:84;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;39545:6;39538:13;;;39152:404;;;;;:::o;788:96:0:-;833:15;867:10;860:17;;788:96;:::o;1552:94:6:-;1600:15;;:::i;:::-;1630:11;;;;;;;;1639:1;1630:11;;;1623:18;;1552:94;;;:::o;1230:97::-;1271:15;;:::i;:::-;1301:21;;;;;;;;889:25;1301:21;;;1294:28;;1230:97;:::o;9997:116::-;10071:4;10101:1;:7;;;10090:1;:7;;;:18;;10083:25;;9997:116;;;;:::o;42145:308:5:-;42282:14;42299:65;42326:10;42338;42350:4;42356:1;42359;42362;42299:26;:65::i;:::-;42282:82;;42388:10;42378:20;;:6;:20;;;42370:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42427:21;42437:10;42427:9;:21::i;:::-;42145:308;;;;;;:::o;38469:130::-;38539:4;38591:1;38559:34;;:12;:20;38572:6;38559:20;;;;;;;;;;;;;;;;;;;;;;;;;:34;;;38551:43;;38469:130;;;:::o;1724:92:6:-;1782:7;1804:1;:7;;;1797:14;;1724:92;;;:::o;2178:225:3:-;2271:1;2251:22;;:8;:22;;;;2243:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2360:8;2331:38;;2352:6;;;;;;;;;;;2331:38;;;;;;;;;;;;2388:8;2379:6;;:17;;;;;;;;;;;;;;;;;;2178:225;:::o;41292:247:5:-;41383:14;41400:10;:29;41430:10;41442:1;41445;41448;41400:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41400:50:5;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41400:50:5;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;41400:50:5;;;;;;;;;;;;;;;;41383:67;;41474:10;41464:20;;:6;:20;;;41456:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41513:21;41523:10;41513:9;:21::i;:::-;41292:247;;;;;:::o;42677:413::-;42745:21;42755:10;42745:9;:21::i;:::-;42730:114;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42865:24;42878:10;42865:12;:24::i;:::-;:90;;;;;42893:62;42932:10;42944;42893:38;:62::i;:::-;42865:90;42850:191;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43075:10;43048:12;:24;43061:10;43048:24;;;;;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;42677:413;:::o;445:42647::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o
Swarm Source
bzzr://c0fc4ba3b9ae1355f32ca611df67b02d52c491f199f7667c27a4a04273d28bc4
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.