Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x3d602d80 | 20415692 | 603 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 18738399 | 838 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 18687712 | 845 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 18687559 | 845 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 18675980 | 847 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 18659431 | 849 days ago | Contract Creation | 0 ETH | |||
| 0x60806040 | 17712716 | 982 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 17450883 | 1018 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 16564026 | 1143 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 16551101 | 1145 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 16449860 | 1159 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 16113527 | 1206 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 15971527 | 1226 days ago | Contract Creation | 0 ETH | |||
| 0x3d602d80 | 15595561 | 1279 days ago | Contract Creation | 0 ETH | |||
| - | 14994658 | 1374 days ago | Contract Creation | 0 ETH | |||
| - | 14917521 | 1387 days ago | Contract Creation | 0 ETH | |||
| - | 14917207 | 1387 days ago | Contract Creation | 0 ETH | |||
| - | 14904930 | 1389 days ago | Contract Creation | 0 ETH | |||
| - | 14899283 | 1390 days ago | Contract Creation | 0 ETH | |||
| - | 14888199 | 1392 days ago | Contract Creation | 0 ETH | |||
| - | 14887219 | 1392 days ago | Contract Creation | 0 ETH | |||
| - | 14838438 | 1400 days ago | Contract Creation | 0 ETH | |||
| - | 14832932 | 1401 days ago | Contract Creation | 0 ETH | |||
| - | 14825221 | 1402 days ago | Contract Creation | 0 ETH | |||
| - | 14819023 | 1403 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
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:
GovernQueueFactory
Compiler Version
v0.6.8+commit.0bbfe453
Contract Source Code (Solidity Standard Json-Input format)
/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
import "@aragon/govern-core/contracts/pipelines/GovernQueue.sol";
import "@aragon/govern-contract-utils/contracts/minimal-proxies/ERC1167ProxyFactory.sol";
contract GovernQueueFactory {
using ERC1167ProxyFactory for address;
address public base;
constructor() public {
setupBase();
}
function newQueue(address _aclRoot, ERC3000Data.Config memory _config, bytes32 _salt) public returns (GovernQueue queue) {
if (_salt != bytes32(0)) {
return GovernQueue(base.clone2(_salt, abi.encodeWithSelector(queue.initialize.selector, _aclRoot, _config)));
} else {
return new GovernQueue(_aclRoot, _config);
}
}
function setupBase() private {
ERC3000Data.Collateral memory noCollateral;
ERC3000Data.Config memory config = ERC3000Data.Config(
3600, // how many seconds to wait before being able to call `execute`
noCollateral,
noCollateral,
address(0),
"",
100000 // initial maxCalldatasize
);
base = address(new GovernQueue(address(2), config));
}
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity 0.6.8;
import "erc3k/contracts/IERC3000.sol";
import "@aragon/govern-core/contracts/Govern.sol";
import "@aragon/govern-contract-utils/contracts/minimal-proxies/ERC1167ProxyFactory.sol";
import "@aragon/govern-contract-utils/contracts/address-utils/AddressUtils.sol";
contract GovernFactory {
using ERC1167ProxyFactory for address;
using AddressUtils for address;
address public base;
constructor() public {
setupBase();
}
function newGovern(IERC3000 _initialExecutor, bytes32 _salt) public returns (Govern govern) {
if (_salt != bytes32(0)) {
return Govern(base.clone2(_salt, abi.encodeWithSelector(govern.initialize.selector, _initialExecutor)).toPayable());
} else {
return new Govern(address(_initialExecutor));
}
}
function setupBase() private {
base = address(new Govern(address(2)));
}
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
import "./ERC3000Data.sol";
abstract contract IERC3000 {
/**
* @notice Schedules an action for execution, allowing for challenges and vetos on a defined time window
* @param container A Container struct holding both the payload being scheduled for execution and
* the current configuration of the system
* @return containerHash
*/
function schedule(ERC3000Data.Container memory container) virtual public returns (bytes32 containerHash);
event Scheduled(bytes32 indexed containerHash, ERC3000Data.Payload payload);
/**
* @notice Executes an action after its execution delay has passed and its state hasn't been altered by a challenge or veto
* @param container A ERC3000Data.Container struct holding both the payload being scheduled for execution and
* the current configuration of the system
* MUST be an ERC3000Executor call: payload.executor.exec(payload.actions)
* @return failureMap
* @return execResults
*/
function execute(ERC3000Data.Container memory container) virtual public returns (bytes32 failureMap, bytes[] memory execResults);
event Executed(bytes32 indexed containerHash, address indexed actor);
/**
* @notice Challenge a container in case its scheduling is illegal as per Config.rules. Pulls collateral and dispute fees from sender into contract
* @param container A ERC3000Data.Container struct holding both the payload being scheduled for execution and
* the current configuration of the system
* @param reason Hint for case reviewers as to why the scheduled container is illegal
* @return resolverId
*/
function challenge(ERC3000Data.Container memory container, bytes memory reason) virtual public returns (uint256 resolverId);
event Challenged(bytes32 indexed containerHash, address indexed actor, bytes reason, uint256 resolverId, ERC3000Data.Collateral collateral);
/**
* @notice Apply arbitrator's ruling over a challenge once it has come to a final ruling
* @param container A ERC3000Data.Container struct holding both the payload being scheduled for execution and
* the current configuration of the system
* @param resolverId disputeId in the arbitrator in which the dispute over the container was created
* @return failureMap
* @return execResults
*/
function resolve(ERC3000Data.Container memory container, uint256 resolverId) virtual public returns (bytes32 failureMap, bytes[] memory execResults);
event Resolved(bytes32 indexed containerHash, address indexed actor, bool approved);
/**
* @notice Apply arbitrator's ruling over a challenge once it has come to a final ruling
* @param container A ERC3000Data.Container struct holding both the payload being scheduled for execution and
* the current configuration of the system
* @param reason Justification for the veto
*/
function veto(ERC3000Data.Container memory container, bytes memory reason) virtual public;
event Vetoed(bytes32 indexed containerHash, address indexed actor, bytes reason);
/**
* @notice Apply a new configuration for all *new* containers to be scheduled
* @param config A ERC3000Data.Config struct holding all the new params that will control the system
* @return configHash
*/
function configure(ERC3000Data.Config memory config) virtual public returns (bytes32 configHash);
event Configured(bytes32 indexed configHash, address indexed actor, ERC3000Data.Config config);
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
import "erc3k/contracts/IERC3000Executor.sol";
import "erc3k/contracts/IERC3000.sol";
import "@aragon/govern-contract-utils/contracts/acl/ACL.sol";
import "@aragon/govern-contract-utils/contracts/adaptive-erc165/AdaptiveERC165.sol";
import "@aragon/govern-contract-utils/contracts/bitmaps/BitmapLib.sol";
import "@aragon/govern-contract-utils/contracts/address-utils/AddressUtils.sol";
import "@aragon/govern-contract-utils/contracts/erc20/ERC20.sol";
import "@aragon/govern-contract-utils/contracts/erc20/SafeERC20.sol";
import "./erc1271/ERC1271.sol";
contract Govern is IERC3000Executor, AdaptiveERC165, ERC1271, ACL {
using BitmapLib for bytes32;
using AddressUtils for address;
using SafeERC20 for ERC20;
string private constant ERROR_DEPOSIT_AMOUNT_ZERO = "GOVERN_DEPOSIT_AMOUNT_ZERO";
string private constant ERROR_ETH_DEPOSIT_AMOUNT_MISMATCH = "GOVERN_ETH_DEPOSIT_AMOUNT_MISMATCH";
string private constant ERROR_TOKEN_NOT_CONTRACT = "GOVERN_TOKEN_NOT_CONTRACT";
string private constant ERROR_TOKEN_DEPOSIT_FAILED = "GOVERN_TOKEN_DEPOSIT_FAILED";
string private constant ERROR_TOO_MANY_ACTIONS = "GOVERN_TOO_MANY_ACTIONS";
string private constant ERROR_ACTION_CALL_FAILED = "GOVERN_ACTION_CALL_FAILED";
string private constant ERROR_TOKEN_WITHDRAW_FAILED = "GOVERN_TOKEN_WITHDRAW_FAILED";
string private constant ERROR_ETH_WITHDRAW_FAILED = "GOVERN_ETH_WITHDRAW_FAILED";
bytes4 internal constant EXEC_ROLE = this.exec.selector;
bytes4 internal constant WITHDRAW_ROLE = this.withdraw.selector;
bytes4 internal constant REGISTER_STANDARD_ROLE = this.registerStandardAndCallback.selector;
bytes4 internal constant SET_SIGNATURE_VALIDATOR_ROLE = this.setSignatureValidator.selector;
uint256 internal constant MAX_ACTIONS = 256;
ERC1271 signatureValidator;
// ETHDeposited and Deposited are both needed. ETHDeposited makes sure that whoever sends funds
// with `send/transfer`, receive function can still be executed without reverting due to gas cost
// increases in EIP-2929. To still use `send/transfer`, access list is needed that has the address
// of the contract(base contract) that is behind the proxy.
event ETHDeposited(address sender, uint256 amount);
event Deposited(address indexed sender, address indexed token, uint256 amount, string _reference);
event Withdrawn(address indexed token, address indexed to, address from, uint256 amount, string _reference);
constructor(address _initialExecutor) ACL(address(this)) public {
initialize(_initialExecutor);
}
function initialize(address _initialExecutor) public initACL(address(this)) onlyInit("govern") {
_grant(EXEC_ROLE, address(_initialExecutor));
_grant(WITHDRAW_ROLE, address(this));
// freeze the withdraw so that only GovernExecutor can call
_freeze(WITHDRAW_ROLE);
_grant(REGISTER_STANDARD_ROLE, address(this));
_grant(SET_SIGNATURE_VALIDATOR_ROLE, address(this));
_registerStandard(ERC3000_EXEC_INTERFACE_ID);
_registerStandard(type(ERC1271).interfaceId);
}
receive () external payable {
emit ETHDeposited(msg.sender, msg.value);
}
fallback () external {
_handleCallback(msg.sig, msg.data); // WARN: does a low-level return, any code below would be unreacheable
}
function deposit(address _token, uint256 _amount, string calldata _reference) external payable {
require(_amount > 0, ERROR_DEPOSIT_AMOUNT_ZERO);
if (_token == address(0)) {
require(msg.value == _amount, ERROR_ETH_DEPOSIT_AMOUNT_MISMATCH);
} else {
require(_token.isContract(), ERROR_TOKEN_NOT_CONTRACT);
require(ERC20(_token).safeTransferFrom(msg.sender, address(this), _amount), ERROR_TOKEN_DEPOSIT_FAILED);
}
emit Deposited(msg.sender, _token, _amount, _reference);
}
function withdraw(address _token, address _from, address _to, uint256 _amount, string memory _reference) public auth(WITHDRAW_ROLE) {
if (_token == address(0)) {
(bool ok, ) = _to.call{value: _amount}("");
require(ok, ERROR_ETH_WITHDRAW_FAILED);
} else {
require(ERC20(_token).safeTransfer(_to, _amount), ERROR_TOKEN_WITHDRAW_FAILED);
}
emit Withdrawn(_token, _to, _from, _amount, _reference);
}
function exec(ERC3000Data.Action[] memory actions, bytes32 allowFailuresMap, bytes32 memo) override public auth(EXEC_ROLE) returns (bytes32, bytes[] memory) {
require(actions.length <= MAX_ACTIONS, ERROR_TOO_MANY_ACTIONS); // need to limit since we use 256-bit bitmaps
bytes[] memory execResults = new bytes[](actions.length);
bytes32 failureMap = BitmapLib.empty; // start with an empty bitmap
for (uint256 i = 0; i < actions.length; i++) {
// TODO: optimize with assembly
(bool ok, bytes memory ret) = actions[i].to.call{value: actions[i].value}(actions[i].data);
require(ok || allowFailuresMap.get(uint8(i)), ERROR_ACTION_CALL_FAILED);
// if a call fails, flip that bit to signal failure
failureMap = ok ? failureMap : failureMap.flip(uint8(i));
execResults[i] = ret;
}
emit Executed(msg.sender, actions, memo, failureMap, execResults);
return (failureMap, execResults);
}
function registerStandardAndCallback(bytes4 _interfaceId, bytes4 _callbackSig, bytes4 _magicNumber) external auth(REGISTER_STANDARD_ROLE) {
_registerStandardAndCallback(_interfaceId, _callbackSig, _magicNumber);
}
function setSignatureValidator(ERC1271 _signatureValidator) external auth(SET_SIGNATURE_VALIDATOR_ROLE) {
signatureValidator = _signatureValidator;
}
function isValidSignature(bytes32 _hash, bytes memory _signature) override public view returns (bytes4) {
if (address(signatureValidator) == address(0)) return bytes4(0); // invalid magic number
return signatureValidator.isValidSignature(_hash, _signature); // forward call to set validation contract
}
}/*
* SPDX-License-Identifier: MIT
*/
// Inspired by: https://github.com/optionality/clone-factory
pragma solidity ^0.6.8;
library ERC1167ProxyFactory {
function clone(address _implementation) internal returns (address cloneAddr) {
bytes memory createData = generateCreateData(_implementation);
assembly {
cloneAddr := create(0, add(createData, 0x20), 55)
}
require(cloneAddr != address(0), "proxy-factory: bad create");
}
function clone(address _implementation, bytes memory _initData) internal returns (address cloneAddr) {
cloneAddr = clone(_implementation);
(bool ok, bytes memory ret) = cloneAddr.call(_initData);
require(ok, _getRevertMsg(ret));
}
function clone2(address _implementation, bytes32 _salt) internal returns (address cloneAddr) {
bytes memory createData = generateCreateData(_implementation);
assembly {
cloneAddr := create2(0, add(createData, 0x20), 55, _salt)
}
require(cloneAddr != address(0), "proxy-factory: bad create2");
}
function clone2(address _implementation, bytes32 _salt, bytes memory _initData) internal returns (address cloneAddr) {
cloneAddr = clone2(_implementation, _salt);
(bool ok, bytes memory ret) = cloneAddr.call(_initData);
require(ok, _getRevertMsg(ret));
}
function generateCreateData(address _implementation) internal pure returns (bytes memory) {
return abi.encodePacked(
//---- constructor -----
bytes10(0x3d602d80600a3d3981f3),
//---- proxy code -----
bytes10(0x363d3d373d3d3d363d73),
_implementation,
bytes15(0x5af43d82803e903d91602b57fd5bf3)
);
}
// From: https://ethereum.stackexchange.com/a/83577
function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {
// If the _res length is less than 68, then the transaction failed silently (without a revert message)
if (_returnData.length < 68) return '';
assembly {
_returnData := add(_returnData, 0x04) // Slice the sighash.
}
return abi.decode(_returnData, (string)); // All that remains is the revert string
}
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
library AddressUtils {
function toPayable(address addr) internal pure returns (address payable) {
return address(bytes20(addr));
}
/**
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*/
function isContract(address addr) internal view returns (bool result) {
assembly {
result := iszero(iszero(extcodesize(addr)))
}
}
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
import "./IERC3000Executor.sol";
library ERC3000Data {
// TODO: come up with a non-shitty name
struct Container {
Payload payload;
Config config;
}
// WARN: Always remember to change the 'hash' function if modifying the struct
struct Payload {
uint256 nonce;
uint256 executionTime;
address submitter;
IERC3000Executor executor;
Action[] actions;
bytes32 allowFailuresMap;
bytes proof;
}
struct Action {
address to;
uint256 value;
bytes data;
}
struct Config {
uint256 executionDelay; // how many seconds to wait before being able to call `execute`.
Collateral scheduleDeposit; // fees for scheduling
Collateral challengeDeposit; // fees for challenging
address resolver; // resolver that will rule the disputes
bytes rules; // rules of how DAO should be managed
uint256 maxCalldataSize; // max calldatasize for the schedule
}
struct Collateral {
address token;
uint256 amount;
}
function containerHash(bytes32 payloadHash, bytes32 configHash) internal view returns (bytes32) {
uint chainId;
assembly {
chainId := chainid()
}
return keccak256(abi.encodePacked("erc3k-v1", address(this), chainId, payloadHash, configHash));
}
function hash(Container memory container) internal view returns (bytes32) {
return containerHash(hash(container.payload), hash(container.config));
}
function hash(Payload memory payload) internal pure returns (bytes32) {
return keccak256(
abi.encode(
payload.nonce,
payload.executionTime,
payload.submitter,
payload.executor,
keccak256(abi.encode(payload.actions)),
payload.allowFailuresMap,
keccak256(payload.proof)
)
);
}
function hash(Config memory config) internal pure returns (bytes32) {
return keccak256(abi.encode(config));
}
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
import "./ERC3000Data.sol";
abstract contract IERC3000Executor {
bytes4 internal constant ERC3000_EXEC_INTERFACE_ID = this.exec.selector;
/**
* @notice Executes all given actions
* @param actions A array of ERC3000Data.Action for later executing those
* @param allowFailuresMap A map with the allowed failures
* @param memo The hash of the ERC3000Data.Container
* @return failureMap
* @return execResults
*/
function exec(ERC3000Data.Action[] memory actions, bytes32 allowFailuresMap, bytes32 memo) virtual public returns (bytes32 failureMap, bytes[] memory execResults);
event Executed(address indexed actor, ERC3000Data.Action[] actions, bytes32 memo, bytes32 failureMap, bytes[] execResults);
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
import "../initializable/Initializable.sol";
import "./IACLOracle.sol";
library ACLData {
enum BulkOp { Grant, Revoke, Freeze }
struct BulkItem {
BulkOp op;
bytes4 role;
address who;
}
}
contract ACL is Initializable {
bytes4 public constant ROOT_ROLE =
this.grant.selector
^ this.revoke.selector
^ this.freeze.selector
^ this.bulk.selector
;
// "Who" constants
address internal constant ANY_ADDR = address(-1);
// "Access" flags
address internal constant UNSET_ROLE = address(0);
address internal constant FREEZE_FLAG = address(1); // Also used as "who"
address internal constant ALLOW_FLAG = address(2);
// Role -> Who -> Access flag (unset or allow) or ACLOracle (any other address denominates auth via ACLOracle)
mapping (bytes4 => mapping (address => address)) public roles;
event Granted(bytes4 indexed role, address indexed actor, address indexed who, IACLOracle oracle);
event Revoked(bytes4 indexed role, address indexed actor, address indexed who);
event Frozen(bytes4 indexed role, address indexed actor);
modifier auth(bytes4 _role) {
require(willPerform(_role, msg.sender, msg.data), "acl: auth");
_;
}
modifier initACL(address _initialRoot) {
// ACL might have been already initialized by constructors
if (initBlocks["acl"] == 0) {
_initializeACL(_initialRoot);
} else {
require(roles[ROOT_ROLE][_initialRoot] == ALLOW_FLAG, "acl: initial root misaligned");
}
_;
}
constructor(address _initialRoot) public initACL(_initialRoot) { }
function grant(bytes4 _role, address _who) external auth(ROOT_ROLE) {
_grant(_role, _who);
}
function grantWithOracle(bytes4 _role, address _who, IACLOracle _oracle) external auth(ROOT_ROLE) {
_grantWithOracle(_role, _who, _oracle);
}
function revoke(bytes4 _role, address _who) external auth(ROOT_ROLE) {
_revoke(_role, _who);
}
function freeze(bytes4 _role) external auth(ROOT_ROLE) {
_freeze(_role);
}
function bulk(ACLData.BulkItem[] calldata items) external auth(ROOT_ROLE) {
for (uint256 i = 0; i < items.length; i++) {
ACLData.BulkItem memory item = items[i];
if (item.op == ACLData.BulkOp.Grant) _grant(item.role, item.who);
else if (item.op == ACLData.BulkOp.Revoke) _revoke(item.role, item.who);
else if (item.op == ACLData.BulkOp.Freeze) _freeze(item.role);
}
}
function willPerform(bytes4 _role, address _who, bytes memory _data) internal returns (bool) {
// First check if the given who is auth'd, then if any address is auth'd
return _checkRole(_role, _who, _data) || _checkRole(_role, ANY_ADDR, _data);
}
function isFrozen(bytes4 _role) public view returns (bool) {
return roles[_role][FREEZE_FLAG] == FREEZE_FLAG;
}
function _initializeACL(address _initialRoot) internal onlyInit("acl") {
_grant(ROOT_ROLE, _initialRoot);
}
function _grant(bytes4 _role, address _who) internal {
_grantWithOracle(_role, _who, IACLOracle(ALLOW_FLAG));
}
function _grantWithOracle(bytes4 _role, address _who, IACLOracle _oracle) internal {
require(!isFrozen(_role), "acl: frozen");
require(_who != FREEZE_FLAG, "acl: bad freeze");
roles[_role][_who] = address(_oracle);
emit Granted(_role, msg.sender, _who, _oracle);
}
function _revoke(bytes4 _role, address _who) internal {
require(!isFrozen(_role), "acl: frozen");
roles[_role][_who] = UNSET_ROLE;
emit Revoked(_role, msg.sender, _who);
}
function _freeze(bytes4 _role) internal {
require(!isFrozen(_role), "acl: frozen");
roles[_role][FREEZE_FLAG] = FREEZE_FLAG;
emit Frozen(_role, msg.sender);
}
function _checkRole(bytes4 _role, address _who, bytes memory _data) internal returns (bool) {
address accessFlagOrAclOracle = roles[_role][_who];
if (accessFlagOrAclOracle != UNSET_ROLE) {
if (accessFlagOrAclOracle == ALLOW_FLAG) return true;
// Since it's not a flag, assume it's an ACLOracle and try-catch to skip failures
try IACLOracle(accessFlagOrAclOracle).willPerform(_role, _who, _data) returns (bool allowed) {
if (allowed) return true;
} catch { }
}
return false;
}
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
import "../erc165/ERC165.sol";
contract AdaptiveERC165 is ERC165 {
// ERC165 interface ID -> whether it is supported
mapping (bytes4 => bool) internal standardSupported;
// Callback function signature -> magic number to return
mapping (bytes4 => bytes32) internal callbackMagicNumbers;
bytes32 internal constant UNREGISTERED_CALLBACK = bytes32(0);
event RegisteredStandard(bytes4 interfaceId);
event RegisteredCallback(bytes4 sig, bytes4 magicNumber);
event ReceivedCallback(bytes4 indexed sig, bytes data);
function supportsInterface(bytes4 _interfaceId) override virtual public view returns (bool) {
return standardSupported[_interfaceId] || super.supportsInterface(_interfaceId);
}
function _handleCallback(bytes4 _sig, bytes memory _data) internal {
bytes32 magicNumber = callbackMagicNumbers[_sig];
require(magicNumber != UNREGISTERED_CALLBACK, "adap-erc165: unknown callback");
emit ReceivedCallback(_sig, _data);
// low-level return magic number
assembly {
mstore(0x00, magicNumber)
return(0x00, 0x20)
}
}
function _registerStandardAndCallback(bytes4 _interfaceId, bytes4 _callbackSig, bytes4 _magicNumber) internal {
_registerStandard(_interfaceId);
_registerCallback(_callbackSig, _magicNumber);
}
function _registerStandard(bytes4 _interfaceId) internal {
standardSupported[_interfaceId] = true;
emit RegisteredStandard(_interfaceId);
}
function _registerCallback(bytes4 _callbackSig, bytes4 _magicNumber) internal {
callbackMagicNumbers[_callbackSig] = _magicNumber;
emit RegisteredCallback(_callbackSig, _magicNumber);
}
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
library BitmapLib {
bytes32 constant internal empty = bytes32(0);
function flip(bytes32 map, uint8 index) internal pure returns (bytes32) {
return bytes32(uint256(map) ^ uint256(1) << index);
}
function get(bytes32 map, uint8 index) internal pure returns (bool) {
return (uint256(map) >> index & 1) == 1;
}
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
/**
* @title ERC20 interface
* @dev see https://github.com/ethereum/EIPs/issues/20
*/
interface ERC20 {
// Optional fields
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address _who) external view returns (uint256);
function allowance(address _owner, address _spender) external view returns (uint256);
function transfer(address _to, uint256 _value) external returns (bool);
function approve(address _spender, uint256 _value) external returns (bool);
function transferFrom(address _from, address _to, uint256 _value) external returns (bool);
event Transfer(
address indexed from,
address indexed to,
uint256 value
);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}/*
* SPDX-License-Identifier: MIT
*/
// From https://github.com/aragon/aragonOS/blob/next/contracts/common/SafeERC20.sol
// Inspired by AdEx (https://github.com/AdExNetwork/adex-protocol-eth/blob/b9df617829661a7518ee10f4cb6c4108659dd6d5/contracts/libs/SafeERC20.sol)
// and 0x (https://github.com/0xProject/0x-monorepo/blob/737d1dc54d72872e24abce5a1dbe1b66d35fa21a/contracts/protocol/contracts/protocol/AssetProxy/ERC20Proxy.sol#L143)
pragma solidity ^0.6.8;
import "../address-utils/AddressUtils.sol";
import "./ERC20.sol";
library SafeERC20 {
using AddressUtils for address;
function invokeAndCheckSuccess(address _addr, bytes memory _calldata)
private
returns (bool ret)
{
if (!_addr.isContract()) {
return false;
}
assembly {
let ptr := mload(0x40) // free memory pointer
let success := call(
gas(), // forward all
_addr, // address
0, // no value
add(_calldata, 0x20), // calldata start
mload(_calldata), // calldata length
ptr, // write output over free memory
0x20 // uint256 return
)
if gt(success, 0) {
// Check number of bytes returned from last function call
switch returndatasize()
// No bytes returned: assume success
case 0 {
ret := 1
}
// 32 bytes returned: check if non-zero
case 0x20 {
// Only return success if returned data was true
// Already have output in ptr
ret := iszero(iszero(mload(ptr)))
}
// Not sure what was returned: don't mark as success
default { }
}
}
}
/**
* @dev Same as a standards-compliant ERC20.transfer() that never reverts (returns false).
* Note that this makes an external call to the token.
*/
function safeTransfer(ERC20 _token, address _to, uint256 _amount) internal returns (bool) {
bytes memory transferCallData = abi.encodeWithSelector(
_token.transfer.selector,
_to,
_amount
);
return invokeAndCheckSuccess(address(_token), transferCallData);
}
/**
* @dev Same as a standards-compliant ERC20.transferFrom() that never reverts (returns false).
* Note that this makes an external call to the token.
*/
function safeTransferFrom(ERC20 _token, address _from, address _to, uint256 _amount) internal returns (bool) {
bytes memory transferFromCallData = abi.encodeWithSelector(
_token.transferFrom.selector,
_from,
_to,
_amount
);
return invokeAndCheckSuccess(address(_token), transferFromCallData);
}
/**
* @dev Same as a standards-compliant ERC20.approve() that never reverts (returns false).
* Note that this makes an external call to the token.
*/
function safeApprove(ERC20 _token, address _spender, uint256 _amount) internal returns (bool) {
bytes memory approveCallData = abi.encodeWithSelector(
_token.approve.selector,
_spender,
_amount
);
return invokeAndCheckSuccess(address(_token), approveCallData);
}
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
/**
* @title ERC1271 interface
* @dev see https://eips.ethereum.org/EIPS/eip-1271
*/
abstract contract ERC1271 {
// bytes4(keccak256("isValidSignature(bytes32,bytes)")
bytes4 constant internal MAGICVALUE = 0x1626ba7e;
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param _hash Keccak256 hash of arbitrary length data signed on the behalf of address(this)
* @param _signature Signature byte array associated with _data
*
* MUST return the bytes4 magic value 0x1626ba7e when function passes.
* MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)
* MUST allow external calls
*/
function isValidSignature(bytes32 _hash, bytes memory _signature) virtual public view returns (bytes4 magicValue);
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity 0.6.8;
contract Initializable {
mapping (string => uint256) public initBlocks;
event Initialized(string indexed key);
modifier onlyInit(string memory key) {
require(initBlocks[key] == 0, "initializable: already initialized");
initBlocks[key] = block.number;
_;
emit Initialized(key);
}
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
interface IACLOracle {
function willPerform(bytes4 role, address who, bytes calldata data) external returns (bool allowed);
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
abstract contract ERC165 {
// Includes supportsInterface method:
bytes4 internal constant ERC165_INTERFACE_ID = bytes4(0x01ffc9a7);
/**
* @dev Query if a contract implements a certain interface
* @param _interfaceId The interface identifier being queried, as specified in ERC-165
* @return True if the contract implements the requested interface and if its not 0xffffffff, false otherwise
*/
function supportsInterface(bytes4 _interfaceId) virtual public view returns (bool) {
return _interfaceId == ERC165_INTERFACE_ID;
}
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
import "@aragon/govern-core/contracts/GovernRegistry.sol";
import "@aragon/govern-token/contracts/GovernTokenFactory.sol";
import "@aragon/govern-token/contracts/interfaces/IERC20.sol";
import "@aragon/govern-token/contracts/GovernMinter.sol";
import "@aragon/govern-token/contracts/libraries/TokenLib.sol";
import "./core-factories/GovernFactory.sol";
import "./core-factories/GovernQueueFactory.sol";
contract GovernBaseFactory {
address internal constant ANY_ADDR = address(-1);
uint256 internal constant MAX_SCHEDULE_ACCESS_LIST_ALLOWED = 10;
string private constant ERROR_SCHEDULE_LIST_EXCEEDED = "basefactory: schedule list exceeded";
GovernFactory public governFactory;
GovernQueueFactory public queueFactory;
GovernTokenFactory public tokenFactory;
GovernRegistry public registry;
constructor(
GovernRegistry _registry,
GovernFactory _governFactory,
GovernQueueFactory _queueFactory,
GovernTokenFactory _tokenFactory
) public {
governFactory = _governFactory;
queueFactory = _queueFactory;
tokenFactory = _tokenFactory;
registry = _registry;
}
function newGovern(
TokenLib.TokenConfig calldata _token,
address[] calldata _scheduleAccessList,
bool _useProxies,
ERC3000Data.Config calldata _config,
string calldata _name
) external returns (Govern govern, GovernQueue queue) {
require(_scheduleAccessList.length <= MAX_SCHEDULE_ACCESS_LIST_ALLOWED, ERROR_SCHEDULE_LIST_EXCEEDED);
bytes32 salt = _useProxies ? keccak256(abi.encodePacked(_name)) : bytes32(0);
queue = queueFactory.newQueue(address(this), _config, salt);
govern = governFactory.newGovern(queue, salt);
IERC20 token = _token.tokenAddress;
GovernMinter minter;
if (address(token) == address(0)) {
(token, minter) = tokenFactory.newToken(
govern,
_token,
_useProxies
);
// if both(scheduleDeposit and challengeDeposit) are non-zero,
// they have already been set and no need for a config change.
if (_config.scheduleDeposit.token == address(0) || _config.challengeDeposit.token == address(0)) {
// give base factory the permission so that it can change
// the config with new token in the same transaction
queue.grant(queue.configure.selector, address(this));
ERC3000Data.Config memory newConfig = ERC3000Data.Config({
executionDelay: _config.executionDelay,
scheduleDeposit: ERC3000Data.Collateral({
token: _config.scheduleDeposit.token != address(0) ? _config.scheduleDeposit.token : address(token),
amount: _config.scheduleDeposit.amount
}),
challengeDeposit: ERC3000Data.Collateral({
token: _config.challengeDeposit.token != address(0) ? _config.challengeDeposit.token : address(token),
amount: _config.challengeDeposit.amount
}),
resolver: _config.resolver,
rules: _config.rules,
maxCalldataSize: _config.maxCalldataSize
});
queue.configure(newConfig);
queue.revoke(queue.configure.selector, address(this));
}
}
registry.register(govern, queue, token, address(minter), _name, "");
uint256 bulkSize = _scheduleAccessList.length == 0 ? 7 : 6 + _scheduleAccessList.length;
ACLData.BulkItem[] memory items = new ACLData.BulkItem[](bulkSize);
items[0] = ACLData.BulkItem(ACLData.BulkOp.Grant, queue.execute.selector, ANY_ADDR);
items[1] = ACLData.BulkItem(ACLData.BulkOp.Grant, queue.challenge.selector, ANY_ADDR);
items[2] = ACLData.BulkItem(ACLData.BulkOp.Grant, queue.configure.selector, address(govern));
items[3] = ACLData.BulkItem(ACLData.BulkOp.Revoke, queue.ROOT_ROLE(), address(this));
items[4] = ACLData.BulkItem(ACLData.BulkOp.Grant, queue.ROOT_ROLE(), address(govern));
items[5] = ACLData.BulkItem(ACLData.BulkOp.Freeze, queue.ROOT_ROLE(), address(0));
// If the schedule access list is empty, anyone can schedule
// otherwise, only the addresses specified are allowed.
if (_scheduleAccessList.length == 0) {
items[6] = ACLData.BulkItem(ACLData.BulkOp.Grant, queue.schedule.selector, ANY_ADDR);
} else {
for (uint256 i = 0; i < _scheduleAccessList.length; i++) {
items[6 + i] = ACLData.BulkItem(
ACLData.BulkOp.Grant,
queue.schedule.selector,
_scheduleAccessList[i]
);
}
}
queue.bulk(items);
}
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity 0.6.8;
import "erc3k/contracts/IERC3000.sol";
import "erc3k/contracts/IERC3000Executor.sol";
import "erc3k/contracts/IERC3000Registry.sol";
import "@aragon/govern-contract-utils/contracts/erc165/ERC165.sol";
contract GovernRegistry is IERC3000Registry {
mapping(string => bool) public nameUsed;
function register(
IERC3000Executor _executor,
IERC3000 _queue,
IERC20 _token,
address minter,
string calldata _name,
bytes calldata _initialMetadata
) override external
{
require(!nameUsed[_name], "registry: name used");
nameUsed[_name] = true;
emit Registered(_executor, _queue, _token, minter, msg.sender, _name);
_setMetadata(_executor, _initialMetadata);
}
function setMetadata(bytes memory _metadata) override public {
_setMetadata(IERC3000Executor(msg.sender), _metadata);
}
function _setMetadata(IERC3000Executor _executor, bytes memory _metadata) internal {
emit SetMetadata(_executor, _metadata);
}
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
import "@aragon/govern-contract-utils/contracts/minimal-proxies/ERC1167ProxyFactory.sol";
import "./libraries/TokenLib.sol";
import "erc3k/contracts/IERC3000Executor.sol";
import "./GovernToken.sol";
import "./GovernMinter.sol";
import "./MerkleDistributor.sol";
contract GovernTokenFactory {
using ERC1167ProxyFactory for address;
address public tokenBase;
address public minterBase;
address public distributorBase;
event CreatedToken(GovernToken token, GovernMinter minter);
constructor() public {
setupBases();
}
function newToken(
IERC3000Executor _governExecutor,
TokenLib.TokenConfig calldata _token,
bool _useProxies
) external returns (
GovernToken token,
GovernMinter minter
) {
if (!_useProxies) {
(token, minter) = _deployContracts(_token.tokenName, _token.tokenSymbol, _token.tokenDecimals);
} else {
token = GovernToken(tokenBase.clone(abi.encodeWithSelector(
token.initialize.selector,
address(this),
_token.tokenName,
_token.tokenSymbol,
_token.tokenDecimals
)));
minter = GovernMinter(minterBase.clone(abi.encodeWithSelector(
minter.initialize.selector,
token,
address(this),
MerkleDistributor(distributorBase)
)));
}
token.changeMinter(address(minter));
if (_token.mintAmount > 0) {
minter.mint(_token.mintAddress, _token.mintAmount, "initial mint");
}
if (_token.merkleRoot != bytes32(0)) {
minter.merkleMint(_token.merkleRoot, _token.merkleMintAmount, _token.merkleTree, _token.merkleContext);
}
bytes4 mintRole = minter.mint.selector ^ minter.merkleMint.selector;
bytes4 rootRole = minter.ROOT_ROLE();
ACLData.BulkItem[] memory items = new ACLData.BulkItem[](4);
items[0] = ACLData.BulkItem(ACLData.BulkOp.Grant, mintRole, address(_governExecutor));
items[1] = ACLData.BulkItem(ACLData.BulkOp.Grant, rootRole, address(_governExecutor));
items[2] = ACLData.BulkItem(ACLData.BulkOp.Revoke, mintRole, address(this));
items[3] = ACLData.BulkItem(ACLData.BulkOp.Revoke, rootRole, address(this));
minter.bulk(items);
emit CreatedToken(token, minter);
}
function setupBases() private {
distributorBase = address(new MerkleDistributor(ERC20(tokenBase), bytes32(0)));
(GovernToken token, GovernMinter minter) = _deployContracts(
"GovernToken base",
"GTB",
0
);
token.changeMinter(address(minter));
// test the bases
minter.mint(msg.sender, 1, "test mint");
minter.merkleMint(bytes32(0), 1, "no tree", "test merkle mint");
// store bases
tokenBase = address(token);
minterBase = address(minter);
}
function _deployContracts(
string memory _tokenName,
string memory _tokenSymbol,
uint8 _tokenDecimals
) internal returns (
GovernToken token,
GovernMinter minter
) {
token = new GovernToken(address(this), _tokenName, _tokenSymbol, _tokenDecimals);
minter = new GovernMinter(GovernToken(token), address(this), MerkleDistributor(distributorBase));
}
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity ^0.6.8;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transfer(address recipient, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity ^0.6.8;
pragma experimental ABIEncoderV2;
import "@aragon/govern-contract-utils/contracts/acl/ACL.sol";
import "@aragon/govern-contract-utils/contracts/minimal-proxies/ERC1167ProxyFactory.sol";
import "./GovernToken.sol";
import "./MerkleDistributor.sol";
contract GovernMinter is ACL {
using ERC1167ProxyFactory for address;
bytes4 constant internal MINT_ROLE =
this.mint.selector ^
this.merkleMint.selector
;
GovernToken public token;
address public distributorBase;
event MintedSingle(address indexed to, uint256 amount, bytes context);
event MintedMerkle(address indexed distributor, bytes32 indexed merkleRoot, uint256 totalAmount, bytes tree, bytes context);
constructor(GovernToken _token, address _initialMinter, MerkleDistributor _distributorBase) ACL(_initialMinter) public {
initialize(_token, _initialMinter, _distributorBase);
}
function initialize(GovernToken _token, address _initialMinter, MerkleDistributor _distributorBase) public initACL(_initialMinter) onlyInit("minter") {
token = _token;
distributorBase = address(_distributorBase);
_grant(MINT_ROLE, _initialMinter);
}
function mint(address _to, uint256 _amount, bytes calldata _context) external auth(MINT_ROLE) {
token.mint(_to, _amount);
emit MintedSingle(_to, _amount, _context);
}
function merkleMint(bytes32 _merkleRoot, uint256 _totalAmount, bytes calldata _tree, bytes calldata _context) external auth(MINT_ROLE) returns (MerkleDistributor distributor) {
address distributorAddr = distributorBase.clone(abi.encodeWithSelector(distributor.initialize.selector, token, _merkleRoot));
token.mint(distributorAddr, _totalAmount);
emit MintedMerkle(distributorAddr, _merkleRoot, _totalAmount, _tree, _context);
return MerkleDistributor(distributorAddr);
}
function eject(address _newMinter) external auth(this.eject.selector) {
token.changeMinter(_newMinter);
}
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
import "../interfaces/IERC20.sol";
library TokenLib {
struct TokenConfig {
IERC20 tokenAddress;
uint8 tokenDecimals;
string tokenName;
string tokenSymbol;
address mintAddress; // initial minter address
uint256 mintAmount; // how much to mint to initial minter address
// merkle settings
bytes32 merkleRoot; // merkle distribution root.
uint256 merkleMintAmount; // how much to mint for the distributor.
bytes merkleTree; // merkle tree object
bytes merkleContext; // context/string what's the actual reason is...
}
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity 0.6.8;
import "./IERC3000.sol";
import "./IERC3000Executor.sol";
import "@aragon/govern-token/contracts/interfaces/IERC20.sol";
abstract contract IERC3000Registry {
/**
* @notice Registers a IERC3000Executor and IERC3000 contract by a name and with his metadata
* @param executor IERC3000Executor contract
* @param queue IERC3000 contract
* @param name The name of this DAO
* @param token Governance token of the DAO
* @param initialMetadata Additional data to store for this DAO
*/
function register(IERC3000Executor executor, IERC3000 queue, IERC20 token, address minter, string calldata name, bytes calldata initialMetadata) virtual external;
event Registered(IERC3000Executor indexed executor, IERC3000 queue, IERC20 indexed token, address minter, address indexed registrant, string name);
/**
* @notice Sets or updates the metadata of a DAO
* @param metadata Additional data to store for this DAO
*/
function setMetadata(bytes memory metadata) virtual public;
event SetMetadata(IERC3000Executor indexed executor, bytes metadata);
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity ^0.6.8;
import '@aragon/govern-contract-utils/contracts/initializable/Initializable.sol';
import '@aragon/govern-contract-utils/contracts/safe-math/SafeMath.sol';
import './interfaces/IERC20.sol';
// Copied and slightly modified from https://github.com/aragon/aragon-network-token/blob/v2-v1.0.0/packages/v2/contracts/token.sol
// Lightweight token modelled after UNI-LP: https://github.com/Uniswap/uniswap-v2-core/blob/v1.0.1/contracts/UniswapV2ERC20.sol
// Adds:
// - An exposed `mint()` with minting role
// - An exposed `burn()`
// - ERC-3009 (`transferWithAuthorization()`)
contract GovernToken is IERC20, Initializable {
using SafeMath for uint256;
// bytes32 private constant EIP712DOMAIN_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")
bytes32 private constant EIP712DOMAIN_HASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;
// bytes32 private constant VERSION_HASH = keccak256("1")
bytes32 private constant VERSION_HASH = 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6;
// bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
// bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH =
// keccak256("TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)");
bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH = 0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267;
string public name;
string public symbol;
uint8 public decimals;
address public minter;
uint256 override public totalSupply;
mapping (address => uint256) override public balanceOf;
mapping (address => mapping (address => uint256)) override public allowance;
// ERC-2612, ERC-3009 state
mapping (address => uint256) public nonces;
mapping (address => mapping (bytes32 => bool)) public authorizationState;
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 value);
event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce);
event ChangeMinter(address indexed minter);
modifier onlyMinter {
require(msg.sender == minter, "token: not minter");
_;
}
constructor(address _initialMinter, string memory _name, string memory _symbol, uint8 _decimals) public {
initialize(_initialMinter, _name, _symbol, _decimals);
}
function initialize(address _initialMinter, string memory _name, string memory _symbol, uint8 _decimals) public onlyInit("token") {
_changeMinter(_initialMinter);
name = _name;
symbol = _symbol;
decimals = _decimals;
}
function _validateSignedData(address signer, bytes32 encodeData, uint8 v, bytes32 r, bytes32 s) internal view {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
getDomainSeparator(),
encodeData
)
);
address recoveredAddress = ecrecover(digest, v, r, s);
// Explicitly disallow authorizations for address(0) as ecrecover returns address(0) on malformed messages
require(recoveredAddress != address(0) && recoveredAddress == signer, "token: bad sig");
}
function _changeMinter(address newMinter) internal {
minter = newMinter;
emit ChangeMinter(newMinter);
}
function _mint(address to, uint256 value) internal {
totalSupply = totalSupply.add(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(address(0), to, value);
}
function _burn(address from, uint value) internal {
// Balance is implicitly checked with SafeMath's underflow protection
balanceOf[from] = balanceOf[from].sub(value);
totalSupply = totalSupply.sub(value);
emit Transfer(from, address(0), value);
}
function _approve(address owner, address spender, uint256 value) private {
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
function _transfer(address from, address to, uint256 value) private {
require(to != address(this) && to != address(0), "token: bad to");
// Balance is implicitly checked with SafeMath's underflow protection
balanceOf[from] = balanceOf[from].sub(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(from, to, value);
}
function getChainId() public pure returns (uint256 chainId) {
assembly { chainId := chainid() }
}
function getDomainSeparator() public view returns (bytes32) {
return keccak256(
abi.encode(
EIP712DOMAIN_HASH,
keccak256(abi.encodePacked(name)),
VERSION_HASH,
getChainId(),
address(this)
)
);
}
function mint(address to, uint256 value) external onlyMinter returns (bool) {
_mint(to, value);
return true;
}
function changeMinter(address newMinter) external onlyMinter {
_changeMinter(newMinter);
}
function burn(uint256 value) external returns (bool) {
_burn(msg.sender, value);
return true;
}
function approve(address spender, uint256 value) override external returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transfer(address to, uint256 value) override external returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function transferFrom(address from, address to, uint256 value) override external returns (bool) {
uint256 fromAllowance = allowance[from][msg.sender];
if (fromAllowance != uint256(-1)) {
// Allowance is implicitly checked with SafeMath's underflow protection
allowance[from][msg.sender] = fromAllowance.sub(value);
}
_transfer(from, to, value);
return true;
}
function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external {
require(deadline >= block.timestamp, "token: auth expired");
bytes32 encodeData = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline));
_validateSignedData(owner, encodeData, v, r, s);
_approve(owner, spender, value);
}
function transferWithAuthorization(
address from,
address to,
uint256 value,
uint256 validAfter,
uint256 validBefore,
bytes32 nonce,
uint8 v,
bytes32 r,
bytes32 s
)
external
{
require(block.timestamp > validAfter, "token: auth wait");
require(block.timestamp < validBefore, "token: auth expired");
require(!authorizationState[from][nonce], "token: auth used");
bytes32 encodeData = keccak256(abi.encode(TRANSFER_WITH_AUTHORIZATION_TYPEHASH, from, to, value, validAfter, validBefore, nonce));
_validateSignedData(from, encodeData, v, r, s);
authorizationState[from][nonce] = true;
emit AuthorizationUsed(from, nonce);
_transfer(from, to, value);
}
}/*
* SPDX-License-Identifier: GPL-3.0
*/
// Copied and modified from: https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol
pragma solidity ^0.6.8;
import "@openzeppelin/contracts/cryptography/MerkleProof.sol";
import "@aragon/govern-contract-utils/contracts/erc20/SafeERC20.sol";
import "@aragon/govern-contract-utils/contracts/initializable/Initializable.sol";
contract MerkleDistributor is Initializable {
using SafeERC20 for ERC20;
ERC20 public token;
bytes32 public merkleRoot;
// This is a packed array of booleans.
mapping (uint256 => uint256) private claimedBitMap;
event Claimed(uint256 indexed index, address indexed to, uint256 amount);
constructor(ERC20 _token, bytes32 _merkleRoot) public {
initialize(_token, _merkleRoot);
}
function initialize(ERC20 _token, bytes32 _merkleRoot) public onlyInit("distributor") {
token = _token;
merkleRoot = _merkleRoot;
}
function claim(uint256 _index, address _to, uint256 _amount, bytes32[] calldata _merkleProof) external {
require(!isClaimed(_index), "dist: already claimed");
require(_verifyBalanceOnTree(_index, _to, _amount, _merkleProof), "dist: proof failed");
_setClaimed(_index);
token.safeTransfer(_to, _amount);
emit Claimed(_index, _to, _amount);
}
function unclaimedBalance(uint256 _index, address _to, uint256 _amount, bytes32[] memory _proof) public view returns (uint256) {
if (isClaimed(_index)) return 0;
return _verifyBalanceOnTree(_index, _to, _amount, _proof) ? _amount : 0;
}
function _verifyBalanceOnTree(uint256 _index, address _to, uint256 _amount, bytes32[] memory _proof) internal view returns (bool) {
bytes32 node = keccak256(abi.encodePacked(_index, _to, _amount));
return MerkleProof.verify(_proof, merkleRoot, node);
}
function isClaimed(uint256 _index) public view returns (bool) {
uint256 claimedWord_index = _index / 256;
uint256 claimedBit_index = _index % 256;
uint256 claimedWord = claimedBitMap[claimedWord_index];
uint256 mask = (1 << claimedBit_index);
return claimedWord & mask == mask;
}
function _setClaimed(uint256 _index) private {
uint256 claimedWord_index = _index / 256;
uint256 claimedBit_index = _index % 256;
claimedBitMap[claimedWord_index] = claimedBitMap[claimedWord_index] | (1 << claimedBit_index);
}
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity ^0.6.8;
// A library for performing overflow-safe math, courtesy of DappHub: https://github.com/dapphub/ds-math/blob/d0ef6d6a5f/src/math.sol
// Modified to include only the essentials
library SafeMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x, "math: overflow");
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x, "math: underflow");
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev These functions deal with verification of Merkle trees (hash trees),
*/
library MerkleProof {
/**
* @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
* defined by `root`. For this, a `proof` must be provided, containing
* sibling hashes on the branch from the leaf to the root of the tree. Each
* pair of leaves and each pair of pre-images are assumed to be sorted.
*/
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
bytes32 proofElement = proof[i];
if (computedHash <= proofElement) {
// Hash(current computed hash + current element of the proof)
computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
} else {
// Hash(current element of the proof + current computed hash)
computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
}
}
// Check if the computed hash (root) is equal to the provided root
return computedHash == root;
}
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2; // required for passing structs in calldata (fairly secure at this point)
import "erc3k/contracts/IERC3000.sol";
import "@aragon/govern-contract-utils/contracts/acl/ACL.sol";
import "@aragon/govern-contract-utils/contracts/adaptive-erc165/AdaptiveERC165.sol";
import "@aragon/govern-contract-utils/contracts/deposits/DepositLib.sol";
import "@aragon/govern-contract-utils/contracts/erc20/SafeERC20.sol";
import '@aragon/govern-contract-utils/contracts/safe-math/SafeMath.sol';
import "../protocol/IArbitrable.sol";
import "../protocol/IArbitrator.sol";
library GovernQueueStateLib {
enum State {
None,
Scheduled,
Challenged,
Approved,
Rejected,
Cancelled,
Executed
}
struct Item {
State state;
}
function checkState(Item storage _item, State _requiredState) internal view {
require(_item.state == _requiredState, "queue: bad state");
}
function setState(Item storage _item, State _state) internal {
_item.state = _state;
}
function checkAndSetState(Item storage _item, State _fromState, State _toState) internal {
checkState(_item, _fromState);
setState(_item, _toState);
}
}
contract GovernQueue is IERC3000, IArbitrable, AdaptiveERC165, ACL {
// Syntax sugar to enable method-calling syntax on types
using ERC3000Data for *;
using DepositLib for ERC3000Data.Collateral;
using GovernQueueStateLib for GovernQueueStateLib.Item;
using SafeERC20 for ERC20;
using SafeMath for uint256;
// Map '4' as the 'allow' ruling; this implicitly maps '3' as the 'reject' ruling
uint256 internal constant ALLOW_RULING = 4;
// Permanent state
bytes32 public configHash; // keccak256 hash of the current ERC3000Data.Config
uint256 public nonce; // number of scheduled payloads so far
mapping (bytes32 => GovernQueueStateLib.Item) public queue; // container hash -> execution state
// Temporary state
mapping (bytes32 => address) public challengerCache; // container hash -> challenger addr (used after challenging and before dispute resolution)
mapping (bytes32 => mapping (IArbitrator => uint256)) public disputeItemCache; // container hash -> arbitrator addr -> dispute id (used between dispute creation and ruling)
/**
* @param _aclRoot account that will be given root permissions on ACL (commonly given to factory)
* @param _initialConfig initial configuration parameters
*/
constructor(address _aclRoot, ERC3000Data.Config memory _initialConfig)
public
ACL(_aclRoot) // note that this contract directly derives from ACL (ACL is local to contract and not global to system in Govern)
{
initialize(_aclRoot, _initialConfig);
}
function initialize(address _aclRoot, ERC3000Data.Config memory _initialConfig) public initACL(_aclRoot) onlyInit("queue") {
_setConfig(_initialConfig);
_registerStandard(type(IERC3000).interfaceId);
}
/**
* @notice Schedules an action for execution, allowing for challenges and vetos on a defined time window. Pulls collateral from submitter into contract.
* @param _container A ERC3000Data.Container struct holding both the payload being scheduled for execution and
* the current configuration of the system
*/
function schedule(ERC3000Data.Container memory _container) // TO FIX: Container is in memory and function has to be public to avoid an unestrutable solidity crash
public
override
auth(this.schedule.selector) // note that all functions in this contract are ACL protected (commonly some of them will be open for any addr to perform)
returns (bytes32 containerHash)
{
// prevent griefing by front-running (the same container is sent by two different people and one must be challenged)
// and ensure container hashes are unique
require(_container.payload.nonce == ++nonce, "queue: bad nonce");
// hash using ERC3000Data.hash(ERC3000Data.Config)
bytes32 _configHash = _container.config.hash();
// ensure that the hash of the config passed in the container matches the current config (implicit agreement approval by scheduler)
require(_configHash == configHash, "queue: bad config");
// ensure that the time delta to the execution timestamp provided in the payload is at least after the config's execution delay
require(_container.payload.executionTime >= _container.config.executionDelay.add(block.timestamp), "queue: bad delay");
// ensure that the submitter of the payload is also the sender of this call
require(_container.payload.submitter == msg.sender, "queue: bad submitter");
// Restrict the size of calldata to _container.config.maxCalldataSize to make sure challenge function stays callable
uint calldataSize;
assembly {
calldataSize := calldatasize()
}
require(calldataSize <= _container.config.maxCalldataSize, "calldatasize: limit exceeded");
// store and set container's hash
containerHash = ERC3000Data.containerHash(_container.payload.hash(), _configHash);
queue[containerHash].checkAndSetState(
GovernQueueStateLib.State.None, // ensure that the state for this container is None
GovernQueueStateLib.State.Scheduled // and if so perform a state transition to Scheduled
);
// we don't need to save any more state about the container in storage
// we just authenticate the hash and assign it a state, since all future
// actions regarding the container will need to provide it as a witness
// all witnesses are logged from this contract at least once, so the
// trust assumption should be the same as storing all on-chain (move complexity to clients)
ERC3000Data.Collateral memory collateral = _container.config.scheduleDeposit;
collateral.collectFrom(_container.payload.submitter); // pull collateral from submitter (requires previous approval)
// the configured resolver may specify additional out-of-band payments for scheduling actions
// schedule() leaves these requirements up to the callers of `schedule()` or other users to fulfill
// emit an event to ensure data availability of all state that cannot be otherwise fetched (see how config isn't emitted since an observer should already have it)
emit Scheduled(containerHash, _container.payload);
}
/**
* @notice Executes an action after its execution delay has passed and its state hasn't been altered by a challenge or veto
* @param _container A ERC3000Data.Container struct holding both the payload being scheduled for execution and
* the current configuration of the system
*/
function execute(ERC3000Data.Container memory _container)
public
override
auth(this.execute.selector) // in most instances this will be open for any addr, but leaving configurable for flexibility
returns (bytes32 failureMap, bytes[] memory)
{
// ensure enough time has passed
require(block.timestamp >= _container.payload.executionTime, "queue: wait more");
bytes32 containerHash = _container.hash();
queue[containerHash].checkAndSetState(
GovernQueueStateLib.State.Scheduled, // note that we will revert here if the container wasn't previously scheduled
GovernQueueStateLib.State.Executed
);
_container.config.scheduleDeposit.releaseTo(_container.payload.submitter); // release collateral to original submitter
return _execute(_container.payload, containerHash);
}
/**
* @notice Challenge a container in case its scheduling is illegal as per Config.rules. Pulls collateral and dispute fees from sender into contract
* @param _container A ERC3000Data.Container struct holding both the payload being scheduled for execution and
* the current configuration of the system
* @param _reason Hint for case reviewers as to why the scheduled container is illegal
*/
function challenge(ERC3000Data.Container memory _container, bytes memory _reason) auth(this.challenge.selector) override public returns (uint256 disputeId) {
bytes32 containerHash = _container.hash();
challengerCache[containerHash] = msg.sender; // cache challenger address while it is needed
queue[containerHash].checkAndSetState(
GovernQueueStateLib.State.Scheduled,
GovernQueueStateLib.State.Challenged
);
ERC3000Data.Collateral memory collateral = _container.config.challengeDeposit;
collateral.collectFrom(msg.sender); // pull challenge collateral from sender
// create dispute on arbitrator
IArbitrator arbitrator = IArbitrator(_container.config.resolver);
(address recipient, ERC20 feeToken, uint256 feeAmount) = arbitrator.getDisputeFees();
require(feeToken.safeTransferFrom(msg.sender, address(this), feeAmount), "queue: bad fee pull");
require(feeToken.safeApprove(recipient, feeAmount), "queue: bad approve");
disputeId = arbitrator.createDispute(2, abi.encode(_container)); // create dispute sending full container ABI encoded (could prob just send payload to save gas)
require(feeToken.safeApprove(recipient, 0), "queue: bad reset"); // reset just in case non-compliant tokens (that fail on non-zero to non-zero approvals) are used
// submit both arguments as evidence and close evidence period. no more evidence can be submitted and a settlement can't happen (could happen off-protocol)
arbitrator.submitEvidence(disputeId, _container.payload.submitter, _container.payload.proof);
arbitrator.submitEvidence(disputeId, msg.sender, _reason);
arbitrator.closeEvidencePeriod(disputeId);
disputeItemCache[containerHash][arbitrator] = disputeId + 1; // cache a relation between disputeId and containerHash while needed
emit Challenged(containerHash, msg.sender, _reason, disputeId, collateral);
}
/**
* @notice Apply arbitrator's ruling over a challenge once it has come to a final ruling
* @param _container A ERC3000Data.Container struct holding both the payload being scheduled for execution and
* the current configuration of the system
* @param _disputeId disputeId in the arbitrator in which the dispute over the container was created
*/
function resolve(ERC3000Data.Container memory _container, uint256 _disputeId) override public returns (bytes32 failureMap, bytes[] memory) {
bytes32 containerHash = _container.hash();
IArbitrator arbitrator = IArbitrator(_container.config.resolver);
require(disputeItemCache[containerHash][arbitrator] == _disputeId + 1, "queue: bad dispute id");
delete disputeItemCache[containerHash][arbitrator]; // release state to refund gas; no longer needed in state
queue[containerHash].checkState(GovernQueueStateLib.State.Challenged);
(address subject, uint256 ruling) = arbitrator.rule(_disputeId);
require(subject == address(this), "queue: not subject");
bool arbitratorApproved = ruling == ALLOW_RULING;
queue[containerHash].setState(
arbitratorApproved
? GovernQueueStateLib.State.Approved
: GovernQueueStateLib.State.Rejected
);
emit Resolved(containerHash, msg.sender, arbitratorApproved);
emit Ruled(arbitrator, _disputeId, ruling);
if (arbitratorApproved) {
return _executeApproved(_container);
} else {
return _settleRejection(_container);
}
}
function veto(ERC3000Data.Container memory _container, bytes memory _reason) auth(this.veto.selector) override public {
bytes32 containerHash = _container.hash();
GovernQueueStateLib.Item storage item = queue[containerHash];
if (item.state == GovernQueueStateLib.State.Challenged) {
item.checkAndSetState(
GovernQueueStateLib.State.Challenged,
GovernQueueStateLib.State.Cancelled
);
address challenger = challengerCache[containerHash];
// release state to refund gas; no longer needed in state
delete challengerCache[containerHash];
delete disputeItemCache[containerHash][IArbitrator(_container.config.resolver)];
// release collateral to challenger and scheduler
_container.config.scheduleDeposit.releaseTo(_container.payload.submitter);
_container.config.challengeDeposit.releaseTo(challenger);
} else {
// If the given container doesn't have the state Challenged
// has it to be the Scheduled state and otherwise should it throw as expected
item.checkAndSetState(
GovernQueueStateLib.State.Scheduled,
GovernQueueStateLib.State.Cancelled
);
_container.config.scheduleDeposit.releaseTo(_container.payload.submitter);
}
emit Vetoed(containerHash, msg.sender, _reason);
}
/**
* @notice Apply a new configuration for all *new* containers to be scheduled
* @param _config A ERC3000Data.Config struct holding all the new params that will control the queue
*/
function configure(ERC3000Data.Config memory _config)
public
override
auth(this.configure.selector)
returns (bytes32)
{
return _setConfig(_config);
}
// Internal
function _executeApproved(ERC3000Data.Container memory _container) internal returns (bytes32 failureMap, bytes[] memory) {
bytes32 containerHash = _container.hash();
queue[containerHash].checkAndSetState(
GovernQueueStateLib.State.Approved,
GovernQueueStateLib.State.Executed
);
delete challengerCache[containerHash]; // release state to refund gas; no longer needed in state
// release all collateral to submitter
_container.config.scheduleDeposit.releaseTo(_container.payload.submitter);
_container.config.challengeDeposit.releaseTo(_container.payload.submitter);
return _execute(_container.payload, containerHash);
}
function _settleRejection(ERC3000Data.Container memory _container) internal returns (bytes32, bytes[] memory) {
bytes32 containerHash = _container.hash();
queue[containerHash].checkAndSetState(
GovernQueueStateLib.State.Rejected,
GovernQueueStateLib.State.Cancelled
);
address challenger = challengerCache[containerHash];
delete challengerCache[containerHash]; // release state to refund gas; no longer needed in state
// release all collateral to challenger
_container.config.scheduleDeposit.releaseTo(challenger);
_container.config.challengeDeposit.releaseTo(challenger);
// return zero values as nothing is executed on rejection
}
function _execute(ERC3000Data.Payload memory _payload, bytes32 _containerHash) internal returns (bytes32, bytes[] memory) {
emit Executed(_containerHash, msg.sender);
return _payload.executor.exec(_payload.actions, _payload.allowFailuresMap, _containerHash);
}
function _setConfig(ERC3000Data.Config memory _config)
internal
returns (bytes32)
{
// validate collaterals by calling balanceOf on their interface
if(_config.challengeDeposit.amount != 0 && _config.challengeDeposit.token != address(0)) {
(bool ok, bytes memory value) = _config.challengeDeposit.token.call(
abi.encodeWithSelector(ERC20.balanceOf.selector, address(this))
);
require(ok && value.length > 0, "queue: bad config");
}
if(_config.scheduleDeposit.amount != 0 && _config.scheduleDeposit.token != address(0)) {
(bool ok, bytes memory value) = _config.scheduleDeposit.token.call(
abi.encodeWithSelector(ERC20.balanceOf.selector, address(this))
);
require(ok && value.length > 0, "queue: bad config");
}
configHash = _config.hash();
emit Configured(configHash, msg.sender, _config);
return configHash;
}
}/*
* SPDX-License-Identifier: MIT
*/
pragma solidity ^0.6.8;
import "erc3k/contracts/ERC3000Data.sol";
import "../erc20/ERC20.sol";
import "../erc20/SafeERC20.sol";
library DepositLib {
using SafeERC20 for ERC20;
event Locked(address indexed token, address indexed from, uint256 amount);
event Unlocked(address indexed token, address indexed to, uint256 amount);
function collectFrom(ERC3000Data.Collateral memory _collateral, address _from) internal {
if (_collateral.amount > 0) {
ERC20 token = ERC20(_collateral.token);
require(token.safeTransferFrom(_from, address(this), _collateral.amount), "deposit: bad token lock");
emit Locked(_collateral.token, _from, _collateral.amount);
}
}
function releaseTo(ERC3000Data.Collateral memory _collateral, address _to) internal {
if (_collateral.amount > 0) {
ERC20 token = ERC20(_collateral.token);
require(token.safeTransfer(_to, _collateral.amount), "deposit: bad token release");
emit Unlocked(_collateral.token, _to, _collateral.amount);
}
}
}/*
* SPDX-License-Identifier: MIT
*/
// From https://github.com/aragon/protocol/blob/f1b3361a160da92b9bb449c0a05dee0c30e41594/packages/evm/contracts/arbitration/IArbitrable.sol
pragma solidity ^0.6.8;
import "./IArbitrator.sol";
/**
* @dev The Arbitrable instances actually don't require to follow any specific interface.
* Note that this is actually optional, although it does allow the Protocol to at least have a way to identify a specific set of instances.
*/
abstract contract IArbitrable {
/**
* @dev Emitted when an IArbitrable instance's dispute is ruled by an IArbitrator
* @param arbitrator IArbitrator instance ruling the dispute
* @param disputeId Identification number of the dispute being ruled by the arbitrator
* @param ruling Ruling given by the arbitrator
*/
event Ruled(IArbitrator indexed arbitrator, uint256 indexed disputeId, uint256 ruling);
}/*
* SPDX-License-Identifier: MIT
*/
// From https://github.com/aragon/protocol/blob/f1b3361a160da92b9bb449c0a05dee0c30e41594/packages/evm/contracts/arbitration/IArbitrator.sol
pragma solidity ^0.6.8;
import "@aragon/govern-contract-utils/contracts/erc20/ERC20.sol";
interface IArbitrator {
/**
* @dev Create a dispute over the Arbitrable sender with a number of possible rulings
* @param _possibleRulings Number of possible rulings allowed for the dispute
* @param _metadata Optional metadata that can be used to provide additional information on the dispute to be created
* @return Dispute identification number
*/
function createDispute(uint256 _possibleRulings, bytes calldata _metadata) external returns (uint256);
/**
* @dev Submit evidence for a dispute
* @param _disputeId Id of the dispute in the Protocol
* @param _submitter Address of the account submitting the evidence
* @param _evidence Data submitted for the evidence related to the dispute
*/
function submitEvidence(uint256 _disputeId, address _submitter, bytes calldata _evidence) external;
/**
* @dev Close the evidence period of a dispute
* @param _disputeId Identification number of the dispute to close its evidence submitting period
*/
function closeEvidencePeriod(uint256 _disputeId) external;
/**
* @notice Rule dispute #`_disputeId` if ready
* @param _disputeId Identification number of the dispute to be ruled
* @return subject Subject associated to the dispute
* @return ruling Ruling number computed for the given dispute
*/
function rule(uint256 _disputeId) external returns (address subject, uint256 ruling);
/**
* @dev Tell the dispute fees information to create a dispute
* @return recipient Address where the corresponding dispute fees must be transferred to
* @return feeToken ERC20 token used for the fees
* @return feeAmount Total amount of fees that must be allowed to the recipient
*/
function getDisputeFees() external view returns (address recipient, ERC20 feeToken, uint256 feeAmount);
/**
* @dev Tell the payments recipient address
* @return Address of the payments recipient module
*/
function getPaymentsRecipient() external view returns (address);
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
import "@aragon/govern-token/contracts/GovernMinter.sol";
import "@aragon/govern-token/contracts/GovernToken.sol";
import "@aragon/govern-token/contracts/libraries/TokenLib.sol";
contract GovernTokenFactoryMock {
event NewTokenCalledWith(address initialMinter, string _tokenName, string _tokenSymbol, uint8 tokenDecimals, address mintAddr, uint256 mintAmount, bool useProxies);
function newToken(
address _initialMinter,
TokenLib.TokenConfig calldata _token,
bool _useProxies
) external returns (
GovernToken token,
GovernMinter minter
) {
emit NewTokenCalledWith(
_initialMinter,
_token.tokenName,
_token.tokenSymbol,
_token.tokenDecimals,
_token.mintAddress,
_token.mintAmount,
_useProxies
);
token = GovernToken(address(this));
minter = GovernMinter(address(this));
}
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;
import "@aragon/govern-core/contracts/pipelines/GovernQueue.sol";
import "@aragon/govern-contract-utils/contracts/acl/ACL.sol";
contract GovernQueueFactoryMock {
event NewQueueCalledWith(address aclRoot, bytes32 salt);
event BulkCalled(ACLData.BulkItem[] items);
bytes4 public constant ROOT_ROLE = "0x";
function schedule() public pure {}
function execute() public pure {}
function challenge() public pure {}
function configure(ERC3000Data.Config memory /*_config*/) public pure returns(bool) {
// TODO: emit events and catch it in the govern-base-factory-unit.test.ts
return true;
}
// probably ACL inheritance can be used instead of implementing ACL functions again.
function grant(bytes4 _role, address _who) public pure {
// TODO: emit events and catch it in the govern-base-factory-unit.test.ts
}
function revoke(bytes4 _role, address _who) public pure {
// TODO: emit events and catch it in the govern-base-factory-unit.test.ts
}
function bulk(ACLData.BulkItem[] memory items) public {
emit BulkCalled(items);
}
function newQueue(address _aclRoot, ERC3000Data.Config memory /*_config*/, bytes32 _salt) public returns (GovernQueue queue) {
/*
TODO:There seems to be a bug with waffle. After it's been fixed, emit the _config too and in the test,
assert it. https://github.com/EthWorks/Waffle/issues/454
*/
emit NewQueueCalledWith(_aclRoot, _salt);
return GovernQueue(address(this));
}
}/*
* SPDX-License-Identifier: GPL-3.0
*/
pragma solidity 0.6.8;
import "erc3k/contracts/IERC3000.sol";
import "@aragon/govern-core/contracts/Govern.sol";
import "@aragon/govern-contract-utils/contracts/address-utils/AddressUtils.sol";
contract GovernFactoryMock {
using AddressUtils for address;
event NewGovernCalledWith(IERC3000 executor, bytes32 salt);
function newGovern(IERC3000 _initialExecutor, bytes32 _salt) public returns (Govern govern) {
emit NewGovernCalledWith(_initialExecutor, _salt);
return Govern(address(this).toPayable());
}
}{
"optimizer": {
"enabled": true,
"runs": 20000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"base","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_aclRoot","type":"address"},{"components":[{"internalType":"uint256","name":"executionDelay","type":"uint256"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ERC3000Data.Collateral","name":"scheduleDeposit","type":"tuple"},{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ERC3000Data.Collateral","name":"challengeDeposit","type":"tuple"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"bytes","name":"rules","type":"bytes"},{"internalType":"uint256","name":"maxCalldataSize","type":"uint256"}],"internalType":"struct ERC3000Data.Config","name":"_config","type":"tuple"},{"internalType":"bytes32","name":"_salt","type":"bytes32"}],"name":"newQueue","outputs":[{"internalType":"contract GovernQueue","name":"queue","type":"address"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b50620000256001600160e01b036200002b16565b62000254565b62000035620000ec565b6200003f62000103565b6040518060c00160405280610e10815260200183815260200183815260200160006001600160a01b03168152602001604051806020016040528060008152508152602001620186a081525090506002816040516200009d9062000152565b620000aa92919062000178565b604051809103906000f080158015620000c7573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b03929092169190911790555050565b604080518082019091526000808252602082015290565b6040518060c00160405280600081526020016200011f620000ec565b81526020016200012e620000ec565b815260200160006001600160a01b0316815260200160608152602001600081525090565b61473a80620052af83390190565b80516001600160a01b03168252602090810151910152565b600060018060a01b03808516835260406020840152835160408401526020840151620001a8606085018262000160565b506040840151620001bd60a085018262000160565b5060608401511660e08301526080830151610100808401528051620001e781610140860162000218565b620001f782826020860162000221565b60a0959095015161012094909401939093525050601f01601f191601919050565b90815260200190565b60005b838110156200023e57818101518382015260200162000224565b838111156200024e576000848401525b50505050565b61504b80620002646000396000f3fe60806040523480156200001157600080fd5b50600436106200003a5760003560e01c80635001f3b5146200003f578063a691fc671462000061575b600080fd5b6200004962000078565b6040516200005891906200073e565b60405180910390f35b6200004962000072366004620004c6565b62000094565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b600081156200016b576200016382638f8b35b260e01b8686604051602401620000bf9291906200075f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915260005473ffffffffffffffffffffffffffffffffffffffff16919063ffffffff620001b016565b9050620001a9565b83836040516200017b90620003db565b620001889291906200075f565b604051809103906000f080158015620001a5573d6000803e3d6000fd5b5090505b9392505050565b6000620001be84846200028e565b9050600060608273ffffffffffffffffffffffffffffffffffffffff1684604051620001eb919062000720565b6000604051808303816000865af19150503d80600081146200022a576040519150601f19603f3d011682016040523d82523d6000602084013e6200022f565b606091505b509150915081620002408262000302565b9062000284576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200027b9190620007f1565b60405180910390fd5b5050509392505050565b600060606200029d8462000349565b9050826037602083016000f5915073ffffffffffffffffffffffffffffffffffffffff8216620002fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200027b9062000806565b5092915050565b606060448251101562000325575060408051602081019091526000815262000344565b60048201915081806020019051810190620003419190620005a7565b90505b919050565b604051606090620003c5907f3d602d80600a3d3981f300000000000000000000000000000000000000000000907f363d3d373d3d3d363d73000000000000000000000000000000000000000000009085907f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000009060200162000697565b6040516020818303038152906040529050919050565b61473a80620008dc83390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200040e57600080fd5b92915050565b600082601f83011262000425578081fd5b81356200043c620004368262000865565b6200083d565b91508082528360208285010111156200045457600080fd5b8060208401602084013760009082016020015292915050565b6000604082840312156200047f578081fd5b6200048b60406200083d565b9050813573ffffffffffffffffffffffffffffffffffffffff81168114620004b257600080fd5b808252506020820135602082015292915050565b600080600060608486031215620004db578283fd5b620004e78585620003e9565b9250602084013567ffffffffffffffff8082111562000504578384fd5b818601610100818903121562000518578485fd5b6200052460c06200083d565b9250803583526200053988602083016200046d565b60208401526200054d88606083016200046d565b6040840152620005618860a08301620003e9565b606084015260c08101358281111562000578578586fd5b620005868982840162000414565b60808501525060e0013560a083015250929592945050506040919091013590565b600060208284031215620005b9578081fd5b815167ffffffffffffffff811115620005d0578182fd5b80830184601f820112620005e2578283fd5b80519150620005f5620004368362000865565b8281528560208484010111156200060a578384fd5b6200061d836020830160208501620008a8565b95945050505050565b6000815180845262000640816020860160208601620008a8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b805173ffffffffffffffffffffffffffffffffffffffff168252602090810151910152565b7fffffffffffffffffffff00000000000000000000000000000000000000000000948516815292909316600a83015260601b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660148201527fffffffffffffffffffffffffffffff000000000000000000000000000000000091909116602882015260370190565b6000825162000734818460208701620008a8565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8085168352604060208401528351604084015260208401516200079d606085018262000672565b506040840151620007b260a085018262000672565b5060608401511660e0830152608083015161010080840152620007da61014084018262000626565b60a085015161012085015280925050509392505050565b600060208252620001a9602083018462000626565b6020808252601a908201527f70726f78792d666163746f72793a206261642063726561746532000000000000604082015260600190565b60405181810167ffffffffffffffff811182821017156200085d57600080fd5b604052919050565b600067ffffffffffffffff8211156200087c578081fd5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b83811015620008c5578181015183820152602001620008ab565b83811115620008d5576000848401525b5050505056fe60806040523480156200001157600080fd5b506040516200473a3803806200473a833981016040819052620000349162000858565b81806002604051620000469062000967565b90815260200160405180910390205460001415620000785762000072816001600160e01b03620000ec16565b620000cc565b6001600160a01b038181166000908152600080516020620046fa833981519152602052604090205416600214620000cc5760405162461bcd60e51b8152600401620000c39062000a31565b60405180910390fd5b50620000e4905082826001600160e01b03620001bd16565b505062000b84565b604051806040016040528060038152602001621858db60ea1b8152506002816040516200011a919062000949565b9081526020016040518091039020546000146200014b5760405162461bcd60e51b8152600401620000c390620009ef565b436002826040516200015e919062000949565b908152604051908190036020019020556200018a63161b7d8160e21b836001600160e01b036200033416565b806040516200019a919062000949565b604051908190038120906000805160206200471a83398151915290600090a25050565b816002604051620001ce9062000967565b908152602001604051809103902054600014156200020057620001fa816001600160e01b03620000ec16565b6200024b565b6001600160a01b038181166000908152600080516020620046fa8339815191526020526040902054166002146200024b5760405162461bcd60e51b8152600401620000c39062000a31565b60405180604001604052806005815260200164717565756560d81b8152506002816040516200027b919062000949565b908152602001604051809103902054600014620002ac5760405162461bcd60e51b8152600401620000c390620009ef565b43600282604051620002bf919062000949565b90815260405190819003602001902055620002e3836001600160e01b036200034f16565b50620002ff63d311828160e01b6001600160e01b03620005de16565b806040516200030f919062000949565b604051908190038120906000805160206200471a83398151915290600090a250505050565b6200034b828260026001600160e01b036200063f16565b5050565b60008160400151602001516000141580156200037857506040820151516001600160a01b031615155b156200046957600060608360400151600001516001600160a01b03166370a0823160e01b30604051602401620003af919062000976565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620003ef919062000949565b6000604051808303816000865af19150503d80600081146200042e576040519150601f19603f3d011682016040523d82523d6000602084013e62000433565b606091505b509150915081801562000447575060008151115b620004665760405162461bcd60e51b8152600401620000c3906200099f565b50505b6020808301510151158015906200048d57506020820151516001600160a01b031615155b156200057e57600060608360200151600001516001600160a01b03166370a0823160e01b30604051602401620004c4919062000976565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905162000504919062000949565b6000604051808303816000865af19150503d806000811462000543576040519150601f19603f3d011682016040523d82523d6000602084013e62000548565b606091505b50915091508180156200055c575060008151115b6200057b5760405162461bcd60e51b8152600401620000c3906200099f565b50505b62000594826200072960201b620016e11760201c565b60048190556040513391907f844435c59f7ccdf12de134e8f9b3b7d664fe9f06e3263680779599ba4097bc3f90620005ce90869062000a91565b60405180910390a3505060045490565b6001600160e01b0319811660009081526020819052604090819020805460ff19166001179055517fbf5e1f87f5ab65b58074cd29244d7c487a948983cda4b932e0f966b62bd34aca90620006349083906200098a565b60405180910390a150565b62000653836001600160e01b036200075b16565b15620006735760405162461bcd60e51b8152600401620000c390620009ca565b6001600160a01b03821660011415620006a05760405162461bcd60e51b8152600401620000c39062000a68565b6001600160e01b0319831660008181526003602090815260408083206001600160a01b03878116808652919093529281902080546001600160a01b0319169286169290921790915551909133917fc62063b81f7036fd97a0dc546516e99f11004d2d76ca0fddd3866346c86e7091906200071c90869062000976565b60405180910390a4505050565b6000816040516020016200073e919062000a91565b604051602081830303815290604052805190602001209050919050565b6001600160e01b031916600090815260036020908152604080832060018085529252909120546001600160a01b03161490565b80516001600160a01b0381168114620007a657600080fd5b92915050565b600082601f830112620007bd578081fd5b81516001600160401b03811115620007d3578182fd5b620007e8601f8201601f191660200162000b2a565b91508082528360208285010111156200080057600080fd5b6200081381602084016020860162000b51565b5092915050565b6000604082840312156200082c578081fd5b62000838604062000b2a565b90506200084683836200078e565b81526020820151602082015292915050565b600080604083850312156200086b578182fd5b6200087784846200078e565b60208401519092506001600160401b038082111562000894578283fd5b8185016101008188031215620008a8578384fd5b620008b460c062000b2a565b925080518352620008c987602083016200081a565b6020840152620008dd87606083016200081a565b6040840152620008f18760a083016200078e565b606084015260c08101518281111562000908578485fd5b6200091688828401620007ac565b60808501525060e0015160a083015250919491935090915050565b80516001600160a01b03168252602090810151910152565b600082516200095d81846020870162000b51565b9190910192915050565b621858db60ea1b815260030190565b6001600160a01b0391909116815260200190565b6001600160e01b031991909116815260200190565b60208082526011908201527071756575653a2062616420636f6e66696760781b604082015260600190565b6020808252600b908201526a30b1b61d10333937bd32b760a91b604082015260600190565b60208082526022908201527f696e697469616c697a61626c653a20616c726561647920696e697469616c697a604082015261195960f21b606082015260800190565b6020808252601c908201527f61636c3a20696e697469616c20726f6f74206d6973616c69676e656400000000604082015260600190565b6020808252600f908201526e61636c3a2062616420667265657a6560881b604082015260600190565b60006020825282516020830152602083015162000ab2604084018262000931565b50604083015162000ac7608084018262000931565b5060608301516001600160a01b031660c0830152608083015161010060e084018190528151610120850181905261014062000b09828288016020870162000b51565b60a0969096015191850191909152601f01601f191690920190920192915050565b6040518181016001600160401b038111828210171562000b4957600080fd5b604052919050565b60005b8381101562000b6e57818101518382015260200162000b54565b8381111562000b7e576000848401525b50505050565b613b668062000b946000396000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c80637e8c7f08116100d8578063affed0e01161008c578063c832048011610066578063c832048014610334578063cc1d4cab14610347578063e1f1176d1461035a57610182565b8063affed0e014610306578063bdf9a7261461030e578063c8182af01461032157610182565b806396fc8abd116100bd57806396fc8abd146102c0578063a157a10d146102e0578063a2157227146102f357610182565b80637e8c7f08146102985780638f8b35b2146102ad57610182565b80633e2da6a91161013a5780635a08160b116101145780635a08160b146102525780637744efda146102655780637c10dea61461027857610182565b80633e2da6a914610219578063495a98251461022c578063588497341461023f57610182565b80631c47671b1161016b5780631c47671b146101d15780631f13405b146101e65780633da956aa1461020657610182565b806301ffc9a71461018757806314d56921146101b0575b600080fd5b61019a610195366004612db5565b610362565b6040516101a79190613335565b60405180910390f35b6101c36101be366004612f90565b6103ac565b6040516101a7929190613349565b6101e46101df366004612c4b565b610631565b005b6101f96101f4366004612f39565b61076b565b6040516101a79190613340565b6101c3610214366004612f06565b610c88565b6101f9610227366004612d86565b610d7d565b61019a61023a366004612db5565b610d9a565b6101e461024d366004612dd1565b610df2565b6101e4610260366004612f39565b610e80565b6101f9610273366004612ed3565b61105e565b61028b610286366004612cd8565b6110d6565b6040516101a7919061348e565b6102a06110eb565b6040516101a791906133cf565b6101e46102bb366004612bd0565b61110f565b6102d36102ce366004612dd1565b6112b5565b6040516101a79190613285565b6101e46102ee366004612dd1565b6112e8565b6101e4610301366004612dfe565b611371565b6101f96113fb565b6101e461031c366004612db5565b611401565b6102d361032f366004612cd8565b61148d565b6101f9610342366004612f06565b6114b5565b6101f9610355366004612e48565b6116be565b6101f96116db565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081526020819052604081205460ff16806103a657506103a682611711565b92915050565b6000606060006103bb8561175b565b60208087015160600151600083815260088352604080822073ffffffffffffffffffffffffffffffffffffffff8416835290935291909120549192509060018601146104225760405162461bcd60e51b815260040161041990613597565b60405180910390fd5b600082815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845282528083208390558483526006909152902061046f90600263ffffffff61177f16565b6000808273ffffffffffffffffffffffffffffffffffffffff1663db18af6c886040518263ffffffff1660e01b81526004016104ab9190613340565b6040805180830381600087803b1580156104c457600080fd5b505af11580156104d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fc9190612c1e565b909250905073ffffffffffffffffffffffffffffffffffffffff821630146105365760405162461bcd60e51b81526004016104199061381a565b600481146105668161054957600461054c565b60035b60008781526006602052604090209063ffffffff6117b816565b3373ffffffffffffffffffffffffffffffffffffffff16857f027d8a5d945eb361475964ed2c71b8332b27af2d630ab5daf829d67afd2584e6836040516105ad9190613335565b60405180910390a3878473ffffffffffffffffffffffffffffffffffffffff167f56c8631a8915c0d362dbe57a61215fdde954f73f81c8a3a1f55572fb015207b1846040516105fc9190613340565b60405180910390a3801561062157610613896117f7565b96509650505050505061062a565b610613896118b8565b9250929050565b60408051602036601f81018290048202830182019093528282527f586df604000000000000000000000000000000000000000000000000000000009261069492849233926000918190840183828082843760009201919091525061197592505050565b6106b05760405162461bcd60e51b815260040161041990613560565b60005b82811015610765576106c36127f3565b8484838181106106cf57fe5b9050606002018036038101906106e59190612e7b565b90506000815160028111156106f657fe5b14156107135761070e816020015182604001516119bb565b61075c565b60018151600281111561072257fe5b141561073a5761070e816020015182604001516119c7565b60028151600281111561074957fe5b141561075c5761075c8160200151611a95565b506001016106b3565b50505050565b6000631f13405b60e01b6107b781336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b6107d35760405162461bcd60e51b815260040161041990613560565b60006107de8561175b565b600081815260076020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905560069091529020909150610834906001600263ffffffff611b4d16565b61083c612815565b50602085015160400151610856813363ffffffff611b6116565b6000866020015160600151905060008060008373ffffffffffffffffffffffffffffffffffffffff16637b751b9e6040518163ffffffff1660e01b815260040160606040518083038186803b1580156108ae57600080fd5b505afa1580156108c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e69190612b8e565b9194509250905061091573ffffffffffffffffffffffffffffffffffffffff831633308463ffffffff611c2b16565b6109315760405162461bcd60e51b815260040161041990613673565b61095873ffffffffffffffffffffffffffffffffffffffff8316848363ffffffff611cdf16565b6109745760405162461bcd60e51b815260040161041990613718565b8373ffffffffffffffffffffffffffffffffffffffff1663c13517e160028c6040516020016109a39190613940565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016109cf9291906134a2565b602060405180830381600087803b1580156109e957600080fd5b505af11580156109fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a219190612fd3565b9750610a4b73ffffffffffffffffffffffffffffffffffffffff831684600063ffffffff611cdf16565b610a675760405162461bcd60e51b81526004016104199061363c565b895160408082015160c09092015190517f7cb57c6400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871692637cb57c6492610ac8928d9291906004016139aa565b600060405180830381600087803b158015610ae257600080fd5b505af1158015610af6573d6000803e3d6000fd5b50506040517f7cb57c6400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87169250637cb57c649150610b50908b9033908e906004016139aa565b600060405180830381600087803b158015610b6a57600080fd5b505af1158015610b7e573d6000803e3d6000fd5b50506040517f7e9adccf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87169250637e9adccf9150610bd4908b90600401613340565b600060405180830381600087803b158015610bee57600080fd5b505af1158015610c02573d6000803e3d6000fd5b505050600087815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff891684529091529081902060018b0190555133915087907f429df837eb45b6713f725a0d3e57db939fd7dd7d58bb3cd967fa37091572db9f90610c73908d908d908b90613466565b60405180910390a35050505050505092915050565b60006060633da956aa60e01b610cd681336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b610cf25760405162461bcd60e51b815260040161041990613560565b835160200151421015610d175760405162461bcd60e51b8152600401610419906137ac565b6000610d228561175b565b6000818152600660208190526040909120919250610d49919060019063ffffffff611b4d16565b8451604001516020808701510151610d669163ffffffff611d9016565b8451610d729082611e4b565b935093505050915091565b600860209081526000928352604080842090915290825290205481565b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152600360209081526040808320600180855292529091205473ffffffffffffffffffffffffffffffffffffffff161490565b60408051602036601f81018290048202830182019093528282527f586df6040000000000000000000000000000000000000000000000000000000092610e5592849233926000918190840183828082843760009201919091525061197592505050565b610e715760405162461bcd60e51b815260040161041990613560565b610e7b83836119c7565b505050565b635a08160b60e01b610eca81336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b610ee65760405162461bcd60e51b815260040161041990613560565b6000610ef18461175b565b60008181526006602052604090209091506002815460ff166006811115610f1457fe5b1415610fd857610f2d816002600563ffffffff611b4d16565b600082815260076020908152604080832080547fffffffffffffffffffffffff000000000000000000000000000000000000000081169091556008835281842089840180516060015173ffffffffffffffffffffffffffffffffffffffff908116875291855283862095909555895190920151935190920151911691610fb9919063ffffffff611d9016565b602086015160400151610fd2908263ffffffff611d9016565b50611008565b610feb816001600563ffffffff611b4d16565b84516040015160208087015101516110089163ffffffff611d9016565b3373ffffffffffffffffffffffffffffffffffffffff16827fe2530b9681f9726904f9ca7fe725c0c53ea1b72370981ac6a5beaa9758c8c3568660405161104f9190613453565b60405180910390a35050505050565b6000637744efda60e01b6110aa81336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b6110c65760405162461bcd60e51b815260040161041990613560565b6110cf83611f45565b9392505050565b60066020526000908152604090205460ff1681565b7f586df6040000000000000000000000000000000000000000000000000000000081565b81600260405161111e906131f4565b908152602001604051809103902054600014156111435761113e81612277565b6111a9565b73ffffffffffffffffffffffffffffffffffffffff81811660009081527fd87da3e1f08043464b74e6b0861ccd8d8a5174e228287ac9b9f6efc1673da4ec6020526040902054166002146111a95760405162461bcd60e51b815260040161041990613888565b6040518060400160405280600581526020017f71756575650000000000000000000000000000000000000000000000000000008152506002816040516111ef91906131d8565b90815260200160405180910390205460001461121d5760405162461bcd60e51b81526004016104199061374f565b4360028260405161122e91906131d8565b9081526040519081900360200190205561124783611f45565b506112717fd311828100000000000000000000000000000000000000000000000000000000612378565b8060405161127f91906131d8565b604051908190038120907f7bc2a48a4a566e237a12186f19d985b0f76afc9d5290601edac19876253670c290600090a250505050565b600360209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff1681565b60408051602036601f81018290048202830182019093528282527f586df604000000000000000000000000000000000000000000000000000000009261134b92849233926000918190840183828082843760009201919091525061197592505050565b6113675760405162461bcd60e51b815260040161041990613560565b610e7b83836119bb565b60408051602036601f81018290048202830182019093528282527f586df60400000000000000000000000000000000000000000000000000000000926113d492849233926000918190840183828082843760009201919091525061197592505050565b6113f05760405162461bcd60e51b815260040161041990613560565b61076584848461240d565b60055481565b60408051602036601f81018290048202830182019093528282527f586df604000000000000000000000000000000000000000000000000000000009261146492849233926000918190840183828082843760009201919091525061197592505050565b6114805760405162461bcd60e51b815260040161041990613560565b61148982611a95565b5050565b60076020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b600063c832048060e01b61150181336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b61151d5760405162461bcd60e51b815260040161041990613560565b6005805460010190819055835151146115485760405162461bcd60e51b8152600401610419906135ce565b600061155784602001516116e1565b9050600454811461157a5760405162461bcd60e51b815260040161041990613529565b602084015151611590904263ffffffff61252e16565b84516020015110156115b45760405162461bcd60e51b815260040161041990613605565b83516040015173ffffffffffffffffffffffffffffffffffffffff1633146115ee5760405162461bcd60e51b8152600401610419906136aa565b602084015160a0015136908111156116185760405162461bcd60e51b815260040161041990613851565b61162e6116288660000151612551565b836125b9565b60008181526006602052604081209195506116519190600163ffffffff611b4d16565b611659612815565b50602080860151015185516040015161167990829063ffffffff611b6116565b847f67f87ff46443c95843c7bd72a026dd23ba0015528ce9f8f15c5c6917645034ef87600001516040516116ad9190613997565b60405180910390a250505050919050565b805160208183018101805160028252928201919093012091525481565b60045481565b6000816040516020016116f4919061392d565b604051602081830303815290604052805190602001209050919050565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f01ffc9a70000000000000000000000000000000000000000000000000000000014919050565b60006103a661176d8360000151612551565b61177a84602001516116e1565b6125b9565b80600681111561178b57fe5b825460ff16600681111561179b57fe5b146114895760405162461bcd60e51b8152600401610419906134f2565b8154819083907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360068111156117ee57fe5b02179055505050565b6000606060006118068461175b565b600081815260066020819052604090912091925061182d919060039063ffffffff611b4d16565b60008181526007602090815260409182902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905585519091015185820151909101516118829163ffffffff611d9016565b83516040908101516020860151909101516118a29163ffffffff611d9016565b83516118ae9082611e4b565b9250925050915091565b6000606060006118c78461175b565b60008181526006602052604090209091506118eb906004600563ffffffff611b4d16565b600081815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000008116909155858201519091015173ffffffffffffffffffffffffffffffffffffffff90911690611955908263ffffffff611d9016565b60208501516040015161196e908263ffffffff611d9016565b5050915091565b60006119828484846125f4565b806119b357506119b3847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff846125f4565b949350505050565b6114898282600261240d565b6119d082610d9a565b156119ed5760405162461bcd60e51b8152600401610419906136e1565b7fffffffff000000000000000000000000000000000000000000000000000000008216600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055519092339290917f682f2c466c1e9f6883eb72cbced01373e1cb18b05ae5c8bc04dc73d73e29f8cd9190a45050565b611a9e81610d9a565b15611abb5760405162461bcd60e51b8152600401610419906136e1565b7fffffffff00000000000000000000000000000000000000000000000000000000811660008181526003602090815260408083206001808552925280832080547fffffffffffffffffffffffff000000000000000000000000000000000000000016909217909155513392917f049c6b8b07a879425742523fa80f8ffb25e39ad518c93a5896a0df19518397e591a350565b611b57838361177f565b610e7b83826117b8565b6020820151156114895781516020830151611b9d9073ffffffffffffffffffffffffffffffffffffffff8316908490309063ffffffff611c2b16565b611bb95760405162461bcd60e51b8152600401610419906137e3565b8173ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff167f989eaa915cbb416ea3d6f9a63b1a3de51770c7674b11fe21ecdf76b4e1d139108560200151604051611c1e9190613340565b60405180910390a3505050565b600060606323b872dd60e01b858585604051602401611c4c939291906132a6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050611cd5868261275c565b9695505050505050565b6000606063095ea7b360e01b8484604051602401611cfe9291906132d7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050611d87858261275c565b95945050505050565b6020820151156114895781516020830151611dca9073ffffffffffffffffffffffffffffffffffffffff831690849063ffffffff6127ce16565b611de65760405162461bcd60e51b8152600401610419906134bb565b8173ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff167fe6e0ef9cd056ca98561ca60e347ada61e1ede2f1142a078951b7a52e1e508e608560200151604051611c1e9190613340565b604051600090606090339084907f59c3746e635078efc737fb3f37dd8188203b8df10bbad35878a7d156f4f51c41908590a3836060015173ffffffffffffffffffffffffffffffffffffffff1663c2d85afc85608001518660a00151866040518463ffffffff1660e01b8152600401611ec693929190613310565b600060405180830381600087803b158015611ee057600080fd5b505af1158015611ef4573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f3a9190810190612cf0565b915091509250929050565b6000816040015160200151600014158015611f7a575060408201515173ffffffffffffffffffffffffffffffffffffffff1615155b156120b8576000606083604001516000015173ffffffffffffffffffffffffffffffffffffffff166370a0823160e01b30604051602401611fbb9190613285565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161204491906131d8565b6000604051808303816000865af19150503d8060008114612081576040519150601f19603f3d011682016040523d82523d6000602084013e612086565b606091505b5091509150818015612099575060008151115b6120b55760405162461bcd60e51b815260040161041990613529565b50505b6020808301510151158015906120e8575060208201515173ffffffffffffffffffffffffffffffffffffffff1615155b15612226576000606083602001516000015173ffffffffffffffffffffffffffffffffffffffff166370a0823160e01b306040516024016121299190613285565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516121b291906131d8565b6000604051808303816000865af19150503d80600081146121ef576040519150601f19603f3d011682016040523d82523d6000602084013e6121f4565b606091505b5091509150818015612207575060008151115b6122235760405162461bcd60e51b815260040161041990613529565b50505b61222f826116e1565b60048190556040513391907f844435c59f7ccdf12de134e8f9b3b7d664fe9f06e3263680779599ba4097bc3f9061226790869061392d565b60405180910390a3505060045490565b6040518060400160405280600381526020017f61636c00000000000000000000000000000000000000000000000000000000008152506002816040516122bd91906131d8565b9081526020016040518091039020546000146122eb5760405162461bcd60e51b81526004016104199061374f565b436002826040516122fc91906131d8565b908152604051908190036020019020556123367f586df60400000000000000000000000000000000000000000000000000000000836119bb565b8060405161234491906131d8565b604051908190038120907f7bc2a48a4a566e237a12186f19d985b0f76afc9d5290601edac19876253670c290600090a25050565b7fffffffff0000000000000000000000000000000000000000000000000000000081166000908152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517fbf5e1f87f5ab65b58074cd29244d7c487a948983cda4b932e0f966b62bd34aca906124029083906133cf565b60405180910390a150565b61241683610d9a565b156124335760405162461bcd60e51b8152600401610419906136e1565b73ffffffffffffffffffffffffffffffffffffffff82166001141561246a5760405162461bcd60e51b8152600401610419906138bf565b7fffffffff000000000000000000000000000000000000000000000000000000008316600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff878116808652919093529281902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169286169290921790915551909133917fc62063b81f7036fd97a0dc546516e99f11004d2d76ca0fddd3866346c86e709190612521908690613285565b60405180910390a4505050565b808201828110156103a65760405162461bcd60e51b8152600401610419906138f6565b60008160000151826020015183604001518460600151856080015160405160200161257c91906132fd565b604051602081830303815290604052805190602001208660a001518760c00151805190602001206040516020016116f497969594939291906139df565b60405160009046906125d590309083908790879060200161321d565b6040516020818303038152906040528051906020012091505092915050565b7fffffffff000000000000000000000000000000000000000000000000000000008316600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff808716855292528220541680156127515773ffffffffffffffffffffffffffffffffffffffff8116600214156126775760019150506110cf565b6040517f097c810800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063097c8108906126cd908890889088906004016133fc565b602060405180830381600087803b1580156126e757600080fd5b505af1925050508015612735575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261273291810190612cb8565b60015b61273e57612751565b801561274f576001925050506110cf565b505b506000949350505050565b600061277d8373ffffffffffffffffffffffffffffffffffffffff166127ed565b612789575060006103a6565b6040516020818451602086016000885af180156127c6573d80156127b457602081146127bd576127c4565b600193506127c4565b8251151593505b505b505092915050565b6000606063a9059cbb60e01b8484604051602401611cfe9291906132d7565b3b151590565b6040805160608101909152806000815260006020820181905260409091015290565b604080518082019091526000808252602082015290565b80356103a681613add565b600082601f830112612847578081fd5b813561285a61285582613a4f565b613a28565b818152915060208083019084810160005b8481101561290f57813587016060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838c030112156128aa57600080fd5b6128b381613a28565b858301356128c081613add565b8152604083810135878301528284013567ffffffffffffffff8111156128e557600080fd5b6128f38d898388010161291a565b918301919091525086525050928201929082019060010161286b565b505050505092915050565b600082601f83011261292a578081fd5b813561293861285582613a6f565b915080825283602082850101111561294f57600080fd5b8060208401602084013760009082016020015292915050565b600082601f830112612978578081fd5b815161298661285582613a6f565b915080825283602082850101111561299d57600080fd5b6129ae816020840160208601613ab1565b5092915050565b6000604082840312156129c6578081fd5b6129d06040613a28565b905081356129dd81613add565b808252506020820135602082015292915050565b60006101008284031215612a03578081fd5b612a0d60c0613a28565b905081358152612a2083602084016129b5565b6020820152612a3283606084016129b5565b604082015260a0820135612a4581613add565b606082015260c082013567ffffffffffffffff811115612a6457600080fd5b612a708482850161291a565b60808301525060e082013560a082015292915050565b600060408284031215612a97578081fd5b612aa16040613a28565b9050813567ffffffffffffffff80821115612abb57600080fd5b81840160e08187031215612ace57600080fd5b612ad860e0613a28565b92508035835260208101356020840152612af5866040830161282c565b6040840152612b07866060830161282c565b6060840152608081013582811115612b1e57600080fd5b612b2a87828401612837565b60808501525060a081013560a084015260c081013582811115612b4c57600080fd5b612b588782840161291a565b60c0850152505090825260208301359080821115612b7557600080fd5b50612b82848285016129f1565b60208301525092915050565b600080600060608486031215612ba2578283fd5b8351612bad81613add565b6020850151909350612bbe81613add565b80925050604084015190509250925092565b60008060408385031215612be2578182fd5b8235612bed81613add565b9150602083013567ffffffffffffffff811115612c08578182fd5b612c14858286016129f1565b9150509250929050565b60008060408385031215612c30578182fd5b8251612c3b81613add565b6020939093015192949293505050565b60008060208385031215612c5d578182fd5b823567ffffffffffffffff80821115612c74578384fd5b81850186601f820112612c85578485fd5b8035925081831115612c95578485fd5b866020606085028301011115612ca9578485fd5b60200196919550909350505050565b600060208284031215612cc9578081fd5b815180151581146110cf578182fd5b600060208284031215612ce9578081fd5b5035919050565b60008060408385031215612d02578182fd5b8251915060208084015167ffffffffffffffff811115612d20578283fd5b80850186601f820112612d31578384fd5b80519150612d4161285583613a4f565b82815283810190828501865b85811015612d7657612d648b888451880101612968565b84529286019290860190600101612d4d565b5096999098509650505050505050565b60008060408385031215612d98578182fd5b823591506020830135612daa81613add565b809150509250929050565b600060208284031215612dc6578081fd5b81356110cf81613b02565b60008060408385031215612de3578182fd5b8235612dee81613b02565b91506020830135612daa81613add565b600080600060608486031215612e12578081fd5b8335612e1d81613b02565b92506020840135612e2d81613add565b91506040840135612e3d81613add565b809150509250925092565b600060208284031215612e59578081fd5b813567ffffffffffffffff811115612e6f578182fd5b6119b38482850161291a565b600060608284031215612e8c578081fd5b612e966060613a28565b823560038110612ea4578283fd5b81526020830135612eb481613b02565b60208201526040830135612ec781613add565b60408201529392505050565b600060208284031215612ee4578081fd5b813567ffffffffffffffff811115612efa578182fd5b6119b3848285016129f1565b600060208284031215612f17578081fd5b813567ffffffffffffffff811115612f2d578182fd5b6119b384828501612a86565b60008060408385031215612f4b578182fd5b823567ffffffffffffffff80821115612f62578384fd5b612f6e86838701612a86565b93506020850135915080821115612f83578283fd5b50612c148582860161291a565b60008060408385031215612fa2578182fd5b823567ffffffffffffffff811115612fb8578283fd5b612fc485828601612a86565b95602094909401359450505050565b600060208284031215612fe4578081fd5b5051919050565b6000815180845260208085019450848183028601828601855b858110156130645783830389528151606073ffffffffffffffffffffffffffffffffffffffff82511685528682015187860152604080830151828288015261304e83880182613071565b9c89019c96505050928601925050600101613004565b5090979650505050505050565b60008151808452613089816020860160208601613ab1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b805173ffffffffffffffffffffffffffffffffffffffff168252602090810151910152565b60006101008251845260208301516130fb60208601826130bb565b50604083015161310e60608601826130bb565b5073ffffffffffffffffffffffffffffffffffffffff60608401511660a085015260808301518160c086015261314682860182613071565b60a085015160e087015280935050505092915050565b60008151835260208201516020840152604082015173ffffffffffffffffffffffffffffffffffffffff80821660408601528060608501511660608601525050608082015160e060808501526131b560e0850182612feb565b60a084015160a086015260c0840151915084810360c0860152611d878183613071565b600082516131ea818460208701613ab1565b9190910192915050565b7f61636c0000000000000000000000000000000000000000000000000000000000815260030190565b7f657263336b2d7631000000000000000000000000000000000000000000000000815260609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166008850152601c840192909252603c830152605c820152607c0190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6000602082526110cf6020830184612feb565b6000606082526133236060830186612feb565b60208301949094525060400152919050565b901515815260200190565b90815260200190565b600060408201848352602060408185015281855180845260608601915060608382028701019350828701855b828110156133c1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030184526133af868351613071565b95509284019290840190600101613375565b509398975050505050505050565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b60007fffffffff000000000000000000000000000000000000000000000000000000008516825273ffffffffffffffffffffffffffffffffffffffff8416602083015260606040830152611d876060830184613071565b6000602082526110cf6020830184613071565b6000608082526134796080830186613071565b90508360208301526119b360408301846130bb565b602081016007831061349c57fe5b91905290565b6000838252604060208301526119b36040830184613071565b6020808252601a908201527f6465706f7369743a2062616420746f6b656e2072656c65617365000000000000604082015260600190565b60208082526010908201527f71756575653a2062616420737461746500000000000000000000000000000000604082015260600190565b60208082526011908201527f71756575653a2062616420636f6e666967000000000000000000000000000000604082015260600190565b60208082526009908201527f61636c3a20617574680000000000000000000000000000000000000000000000604082015260600190565b60208082526015908201527f71756575653a2062616420646973707574652069640000000000000000000000604082015260600190565b60208082526010908201527f71756575653a20626164206e6f6e636500000000000000000000000000000000604082015260600190565b60208082526010908201527f71756575653a206261642064656c617900000000000000000000000000000000604082015260600190565b60208082526010908201527f71756575653a2062616420726573657400000000000000000000000000000000604082015260600190565b60208082526013908201527f71756575653a20626164206665652070756c6c00000000000000000000000000604082015260600190565b60208082526014908201527f71756575653a20626164207375626d6974746572000000000000000000000000604082015260600190565b6020808252600b908201527f61636c3a2066726f7a656e000000000000000000000000000000000000000000604082015260600190565b60208082526012908201527f71756575653a2062616420617070726f76650000000000000000000000000000604082015260600190565b60208082526022908201527f696e697469616c697a61626c653a20616c726561647920696e697469616c697a60408201527f6564000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526010908201527f71756575653a2077616974206d6f726500000000000000000000000000000000604082015260600190565b60208082526017908201527f6465706f7369743a2062616420746f6b656e206c6f636b000000000000000000604082015260600190565b60208082526012908201527f71756575653a206e6f74207375626a6563740000000000000000000000000000604082015260600190565b6020808252601c908201527f63616c6c6461746173697a653a206c696d697420657863656564656400000000604082015260600190565b6020808252601c908201527f61636c3a20696e697469616c20726f6f74206d6973616c69676e656400000000604082015260600190565b6020808252600f908201527f61636c3a2062616420667265657a650000000000000000000000000000000000604082015260600190565b6020808252600e908201527f6d6174683a206f766572666c6f77000000000000000000000000000000000000604082015260600190565b6000602082526110cf60208301846130e0565b60006020825282516040602084015261395c606084018261315c565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848203016040850152611d8781836130e0565b6000602082526110cf602083018461315c565b600084825273ffffffffffffffffffffffffffffffffffffffff8416602083015260606040830152611d876060830184613071565b968752602087019590955273ffffffffffffffffffffffffffffffffffffffff9384166040870152919092166060850152608084019190915260a083015260c082015260e00190565b60405181810167ffffffffffffffff81118282101715613a4757600080fd5b604052919050565b600067ffffffffffffffff821115613a65578081fd5b5060209081020190565b600067ffffffffffffffff821115613a85578081fd5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b83811015613acc578181015183820152602001613ab4565b838111156107655750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114613aff57600080fd5b50565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114613aff57600080fdfea2646970667358221220047f58de53e183d409d81810d17312376c0fd2479adb7e90037508e7eab281fa64736f6c63430006080033d87da3e1f08043464b74e6b0861ccd8d8a5174e228287ac9b9f6efc1673da4ec7bc2a48a4a566e237a12186f19d985b0f76afc9d5290601edac19876253670c2a2646970667358221220b172753c8385a1d34d2071a1ee0f7d825f059cbdd1b587f3a6383726a08b6eb764736f6c6343000608003360806040523480156200001157600080fd5b506040516200473a3803806200473a833981016040819052620000349162000858565b81806002604051620000469062000967565b90815260200160405180910390205460001415620000785762000072816001600160e01b03620000ec16565b620000cc565b6001600160a01b038181166000908152600080516020620046fa833981519152602052604090205416600214620000cc5760405162461bcd60e51b8152600401620000c39062000a31565b60405180910390fd5b50620000e4905082826001600160e01b03620001bd16565b505062000b84565b604051806040016040528060038152602001621858db60ea1b8152506002816040516200011a919062000949565b9081526020016040518091039020546000146200014b5760405162461bcd60e51b8152600401620000c390620009ef565b436002826040516200015e919062000949565b908152604051908190036020019020556200018a63161b7d8160e21b836001600160e01b036200033416565b806040516200019a919062000949565b604051908190038120906000805160206200471a83398151915290600090a25050565b816002604051620001ce9062000967565b908152602001604051809103902054600014156200020057620001fa816001600160e01b03620000ec16565b6200024b565b6001600160a01b038181166000908152600080516020620046fa8339815191526020526040902054166002146200024b5760405162461bcd60e51b8152600401620000c39062000a31565b60405180604001604052806005815260200164717565756560d81b8152506002816040516200027b919062000949565b908152602001604051809103902054600014620002ac5760405162461bcd60e51b8152600401620000c390620009ef565b43600282604051620002bf919062000949565b90815260405190819003602001902055620002e3836001600160e01b036200034f16565b50620002ff63d311828160e01b6001600160e01b03620005de16565b806040516200030f919062000949565b604051908190038120906000805160206200471a83398151915290600090a250505050565b6200034b828260026001600160e01b036200063f16565b5050565b60008160400151602001516000141580156200037857506040820151516001600160a01b031615155b156200046957600060608360400151600001516001600160a01b03166370a0823160e01b30604051602401620003af919062000976565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620003ef919062000949565b6000604051808303816000865af19150503d80600081146200042e576040519150601f19603f3d011682016040523d82523d6000602084013e62000433565b606091505b509150915081801562000447575060008151115b620004665760405162461bcd60e51b8152600401620000c3906200099f565b50505b6020808301510151158015906200048d57506020820151516001600160a01b031615155b156200057e57600060608360200151600001516001600160a01b03166370a0823160e01b30604051602401620004c4919062000976565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905162000504919062000949565b6000604051808303816000865af19150503d806000811462000543576040519150601f19603f3d011682016040523d82523d6000602084013e62000548565b606091505b50915091508180156200055c575060008151115b6200057b5760405162461bcd60e51b8152600401620000c3906200099f565b50505b62000594826200072960201b620016e11760201c565b60048190556040513391907f844435c59f7ccdf12de134e8f9b3b7d664fe9f06e3263680779599ba4097bc3f90620005ce90869062000a91565b60405180910390a3505060045490565b6001600160e01b0319811660009081526020819052604090819020805460ff19166001179055517fbf5e1f87f5ab65b58074cd29244d7c487a948983cda4b932e0f966b62bd34aca90620006349083906200098a565b60405180910390a150565b62000653836001600160e01b036200075b16565b15620006735760405162461bcd60e51b8152600401620000c390620009ca565b6001600160a01b03821660011415620006a05760405162461bcd60e51b8152600401620000c39062000a68565b6001600160e01b0319831660008181526003602090815260408083206001600160a01b03878116808652919093529281902080546001600160a01b0319169286169290921790915551909133917fc62063b81f7036fd97a0dc546516e99f11004d2d76ca0fddd3866346c86e7091906200071c90869062000976565b60405180910390a4505050565b6000816040516020016200073e919062000a91565b604051602081830303815290604052805190602001209050919050565b6001600160e01b031916600090815260036020908152604080832060018085529252909120546001600160a01b03161490565b80516001600160a01b0381168114620007a657600080fd5b92915050565b600082601f830112620007bd578081fd5b81516001600160401b03811115620007d3578182fd5b620007e8601f8201601f191660200162000b2a565b91508082528360208285010111156200080057600080fd5b6200081381602084016020860162000b51565b5092915050565b6000604082840312156200082c578081fd5b62000838604062000b2a565b90506200084683836200078e565b81526020820151602082015292915050565b600080604083850312156200086b578182fd5b6200087784846200078e565b60208401519092506001600160401b038082111562000894578283fd5b8185016101008188031215620008a8578384fd5b620008b460c062000b2a565b925080518352620008c987602083016200081a565b6020840152620008dd87606083016200081a565b6040840152620008f18760a083016200078e565b606084015260c08101518281111562000908578485fd5b6200091688828401620007ac565b60808501525060e0015160a083015250919491935090915050565b80516001600160a01b03168252602090810151910152565b600082516200095d81846020870162000b51565b9190910192915050565b621858db60ea1b815260030190565b6001600160a01b0391909116815260200190565b6001600160e01b031991909116815260200190565b60208082526011908201527071756575653a2062616420636f6e66696760781b604082015260600190565b6020808252600b908201526a30b1b61d10333937bd32b760a91b604082015260600190565b60208082526022908201527f696e697469616c697a61626c653a20616c726561647920696e697469616c697a604082015261195960f21b606082015260800190565b6020808252601c908201527f61636c3a20696e697469616c20726f6f74206d6973616c69676e656400000000604082015260600190565b6020808252600f908201526e61636c3a2062616420667265657a6560881b604082015260600190565b60006020825282516020830152602083015162000ab2604084018262000931565b50604083015162000ac7608084018262000931565b5060608301516001600160a01b031660c0830152608083015161010060e084018190528151610120850181905261014062000b09828288016020870162000b51565b60a0969096015191850191909152601f01601f191690920190920192915050565b6040518181016001600160401b038111828210171562000b4957600080fd5b604052919050565b60005b8381101562000b6e57818101518382015260200162000b54565b8381111562000b7e576000848401525b50505050565b613b668062000b946000396000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c80637e8c7f08116100d8578063affed0e01161008c578063c832048011610066578063c832048014610334578063cc1d4cab14610347578063e1f1176d1461035a57610182565b8063affed0e014610306578063bdf9a7261461030e578063c8182af01461032157610182565b806396fc8abd116100bd57806396fc8abd146102c0578063a157a10d146102e0578063a2157227146102f357610182565b80637e8c7f08146102985780638f8b35b2146102ad57610182565b80633e2da6a91161013a5780635a08160b116101145780635a08160b146102525780637744efda146102655780637c10dea61461027857610182565b80633e2da6a914610219578063495a98251461022c578063588497341461023f57610182565b80631c47671b1161016b5780631c47671b146101d15780631f13405b146101e65780633da956aa1461020657610182565b806301ffc9a71461018757806314d56921146101b0575b600080fd5b61019a610195366004612db5565b610362565b6040516101a79190613335565b60405180910390f35b6101c36101be366004612f90565b6103ac565b6040516101a7929190613349565b6101e46101df366004612c4b565b610631565b005b6101f96101f4366004612f39565b61076b565b6040516101a79190613340565b6101c3610214366004612f06565b610c88565b6101f9610227366004612d86565b610d7d565b61019a61023a366004612db5565b610d9a565b6101e461024d366004612dd1565b610df2565b6101e4610260366004612f39565b610e80565b6101f9610273366004612ed3565b61105e565b61028b610286366004612cd8565b6110d6565b6040516101a7919061348e565b6102a06110eb565b6040516101a791906133cf565b6101e46102bb366004612bd0565b61110f565b6102d36102ce366004612dd1565b6112b5565b6040516101a79190613285565b6101e46102ee366004612dd1565b6112e8565b6101e4610301366004612dfe565b611371565b6101f96113fb565b6101e461031c366004612db5565b611401565b6102d361032f366004612cd8565b61148d565b6101f9610342366004612f06565b6114b5565b6101f9610355366004612e48565b6116be565b6101f96116db565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081526020819052604081205460ff16806103a657506103a682611711565b92915050565b6000606060006103bb8561175b565b60208087015160600151600083815260088352604080822073ffffffffffffffffffffffffffffffffffffffff8416835290935291909120549192509060018601146104225760405162461bcd60e51b815260040161041990613597565b60405180910390fd5b600082815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845282528083208390558483526006909152902061046f90600263ffffffff61177f16565b6000808273ffffffffffffffffffffffffffffffffffffffff1663db18af6c886040518263ffffffff1660e01b81526004016104ab9190613340565b6040805180830381600087803b1580156104c457600080fd5b505af11580156104d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fc9190612c1e565b909250905073ffffffffffffffffffffffffffffffffffffffff821630146105365760405162461bcd60e51b81526004016104199061381a565b600481146105668161054957600461054c565b60035b60008781526006602052604090209063ffffffff6117b816565b3373ffffffffffffffffffffffffffffffffffffffff16857f027d8a5d945eb361475964ed2c71b8332b27af2d630ab5daf829d67afd2584e6836040516105ad9190613335565b60405180910390a3878473ffffffffffffffffffffffffffffffffffffffff167f56c8631a8915c0d362dbe57a61215fdde954f73f81c8a3a1f55572fb015207b1846040516105fc9190613340565b60405180910390a3801561062157610613896117f7565b96509650505050505061062a565b610613896118b8565b9250929050565b60408051602036601f81018290048202830182019093528282527f586df604000000000000000000000000000000000000000000000000000000009261069492849233926000918190840183828082843760009201919091525061197592505050565b6106b05760405162461bcd60e51b815260040161041990613560565b60005b82811015610765576106c36127f3565b8484838181106106cf57fe5b9050606002018036038101906106e59190612e7b565b90506000815160028111156106f657fe5b14156107135761070e816020015182604001516119bb565b61075c565b60018151600281111561072257fe5b141561073a5761070e816020015182604001516119c7565b60028151600281111561074957fe5b141561075c5761075c8160200151611a95565b506001016106b3565b50505050565b6000631f13405b60e01b6107b781336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b6107d35760405162461bcd60e51b815260040161041990613560565b60006107de8561175b565b600081815260076020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905560069091529020909150610834906001600263ffffffff611b4d16565b61083c612815565b50602085015160400151610856813363ffffffff611b6116565b6000866020015160600151905060008060008373ffffffffffffffffffffffffffffffffffffffff16637b751b9e6040518163ffffffff1660e01b815260040160606040518083038186803b1580156108ae57600080fd5b505afa1580156108c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e69190612b8e565b9194509250905061091573ffffffffffffffffffffffffffffffffffffffff831633308463ffffffff611c2b16565b6109315760405162461bcd60e51b815260040161041990613673565b61095873ffffffffffffffffffffffffffffffffffffffff8316848363ffffffff611cdf16565b6109745760405162461bcd60e51b815260040161041990613718565b8373ffffffffffffffffffffffffffffffffffffffff1663c13517e160028c6040516020016109a39190613940565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016109cf9291906134a2565b602060405180830381600087803b1580156109e957600080fd5b505af11580156109fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a219190612fd3565b9750610a4b73ffffffffffffffffffffffffffffffffffffffff831684600063ffffffff611cdf16565b610a675760405162461bcd60e51b81526004016104199061363c565b895160408082015160c09092015190517f7cb57c6400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871692637cb57c6492610ac8928d9291906004016139aa565b600060405180830381600087803b158015610ae257600080fd5b505af1158015610af6573d6000803e3d6000fd5b50506040517f7cb57c6400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87169250637cb57c649150610b50908b9033908e906004016139aa565b600060405180830381600087803b158015610b6a57600080fd5b505af1158015610b7e573d6000803e3d6000fd5b50506040517f7e9adccf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87169250637e9adccf9150610bd4908b90600401613340565b600060405180830381600087803b158015610bee57600080fd5b505af1158015610c02573d6000803e3d6000fd5b505050600087815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff891684529091529081902060018b0190555133915087907f429df837eb45b6713f725a0d3e57db939fd7dd7d58bb3cd967fa37091572db9f90610c73908d908d908b90613466565b60405180910390a35050505050505092915050565b60006060633da956aa60e01b610cd681336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b610cf25760405162461bcd60e51b815260040161041990613560565b835160200151421015610d175760405162461bcd60e51b8152600401610419906137ac565b6000610d228561175b565b6000818152600660208190526040909120919250610d49919060019063ffffffff611b4d16565b8451604001516020808701510151610d669163ffffffff611d9016565b8451610d729082611e4b565b935093505050915091565b600860209081526000928352604080842090915290825290205481565b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152600360209081526040808320600180855292529091205473ffffffffffffffffffffffffffffffffffffffff161490565b60408051602036601f81018290048202830182019093528282527f586df6040000000000000000000000000000000000000000000000000000000092610e5592849233926000918190840183828082843760009201919091525061197592505050565b610e715760405162461bcd60e51b815260040161041990613560565b610e7b83836119c7565b505050565b635a08160b60e01b610eca81336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b610ee65760405162461bcd60e51b815260040161041990613560565b6000610ef18461175b565b60008181526006602052604090209091506002815460ff166006811115610f1457fe5b1415610fd857610f2d816002600563ffffffff611b4d16565b600082815260076020908152604080832080547fffffffffffffffffffffffff000000000000000000000000000000000000000081169091556008835281842089840180516060015173ffffffffffffffffffffffffffffffffffffffff908116875291855283862095909555895190920151935190920151911691610fb9919063ffffffff611d9016565b602086015160400151610fd2908263ffffffff611d9016565b50611008565b610feb816001600563ffffffff611b4d16565b84516040015160208087015101516110089163ffffffff611d9016565b3373ffffffffffffffffffffffffffffffffffffffff16827fe2530b9681f9726904f9ca7fe725c0c53ea1b72370981ac6a5beaa9758c8c3568660405161104f9190613453565b60405180910390a35050505050565b6000637744efda60e01b6110aa81336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b6110c65760405162461bcd60e51b815260040161041990613560565b6110cf83611f45565b9392505050565b60066020526000908152604090205460ff1681565b7f586df6040000000000000000000000000000000000000000000000000000000081565b81600260405161111e906131f4565b908152602001604051809103902054600014156111435761113e81612277565b6111a9565b73ffffffffffffffffffffffffffffffffffffffff81811660009081527fd87da3e1f08043464b74e6b0861ccd8d8a5174e228287ac9b9f6efc1673da4ec6020526040902054166002146111a95760405162461bcd60e51b815260040161041990613888565b6040518060400160405280600581526020017f71756575650000000000000000000000000000000000000000000000000000008152506002816040516111ef91906131d8565b90815260200160405180910390205460001461121d5760405162461bcd60e51b81526004016104199061374f565b4360028260405161122e91906131d8565b9081526040519081900360200190205561124783611f45565b506112717fd311828100000000000000000000000000000000000000000000000000000000612378565b8060405161127f91906131d8565b604051908190038120907f7bc2a48a4a566e237a12186f19d985b0f76afc9d5290601edac19876253670c290600090a250505050565b600360209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff1681565b60408051602036601f81018290048202830182019093528282527f586df604000000000000000000000000000000000000000000000000000000009261134b92849233926000918190840183828082843760009201919091525061197592505050565b6113675760405162461bcd60e51b815260040161041990613560565b610e7b83836119bb565b60408051602036601f81018290048202830182019093528282527f586df60400000000000000000000000000000000000000000000000000000000926113d492849233926000918190840183828082843760009201919091525061197592505050565b6113f05760405162461bcd60e51b815260040161041990613560565b61076584848461240d565b60055481565b60408051602036601f81018290048202830182019093528282527f586df604000000000000000000000000000000000000000000000000000000009261146492849233926000918190840183828082843760009201919091525061197592505050565b6114805760405162461bcd60e51b815260040161041990613560565b61148982611a95565b5050565b60076020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b600063c832048060e01b61150181336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b61151d5760405162461bcd60e51b815260040161041990613560565b6005805460010190819055835151146115485760405162461bcd60e51b8152600401610419906135ce565b600061155784602001516116e1565b9050600454811461157a5760405162461bcd60e51b815260040161041990613529565b602084015151611590904263ffffffff61252e16565b84516020015110156115b45760405162461bcd60e51b815260040161041990613605565b83516040015173ffffffffffffffffffffffffffffffffffffffff1633146115ee5760405162461bcd60e51b8152600401610419906136aa565b602084015160a0015136908111156116185760405162461bcd60e51b815260040161041990613851565b61162e6116288660000151612551565b836125b9565b60008181526006602052604081209195506116519190600163ffffffff611b4d16565b611659612815565b50602080860151015185516040015161167990829063ffffffff611b6116565b847f67f87ff46443c95843c7bd72a026dd23ba0015528ce9f8f15c5c6917645034ef87600001516040516116ad9190613997565b60405180910390a250505050919050565b805160208183018101805160028252928201919093012091525481565b60045481565b6000816040516020016116f4919061392d565b604051602081830303815290604052805190602001209050919050565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f01ffc9a70000000000000000000000000000000000000000000000000000000014919050565b60006103a661176d8360000151612551565b61177a84602001516116e1565b6125b9565b80600681111561178b57fe5b825460ff16600681111561179b57fe5b146114895760405162461bcd60e51b8152600401610419906134f2565b8154819083907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360068111156117ee57fe5b02179055505050565b6000606060006118068461175b565b600081815260066020819052604090912091925061182d919060039063ffffffff611b4d16565b60008181526007602090815260409182902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905585519091015185820151909101516118829163ffffffff611d9016565b83516040908101516020860151909101516118a29163ffffffff611d9016565b83516118ae9082611e4b565b9250925050915091565b6000606060006118c78461175b565b60008181526006602052604090209091506118eb906004600563ffffffff611b4d16565b600081815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000008116909155858201519091015173ffffffffffffffffffffffffffffffffffffffff90911690611955908263ffffffff611d9016565b60208501516040015161196e908263ffffffff611d9016565b5050915091565b60006119828484846125f4565b806119b357506119b3847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff846125f4565b949350505050565b6114898282600261240d565b6119d082610d9a565b156119ed5760405162461bcd60e51b8152600401610419906136e1565b7fffffffff000000000000000000000000000000000000000000000000000000008216600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055519092339290917f682f2c466c1e9f6883eb72cbced01373e1cb18b05ae5c8bc04dc73d73e29f8cd9190a45050565b611a9e81610d9a565b15611abb5760405162461bcd60e51b8152600401610419906136e1565b7fffffffff00000000000000000000000000000000000000000000000000000000811660008181526003602090815260408083206001808552925280832080547fffffffffffffffffffffffff000000000000000000000000000000000000000016909217909155513392917f049c6b8b07a879425742523fa80f8ffb25e39ad518c93a5896a0df19518397e591a350565b611b57838361177f565b610e7b83826117b8565b6020820151156114895781516020830151611b9d9073ffffffffffffffffffffffffffffffffffffffff8316908490309063ffffffff611c2b16565b611bb95760405162461bcd60e51b8152600401610419906137e3565b8173ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff167f989eaa915cbb416ea3d6f9a63b1a3de51770c7674b11fe21ecdf76b4e1d139108560200151604051611c1e9190613340565b60405180910390a3505050565b600060606323b872dd60e01b858585604051602401611c4c939291906132a6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050611cd5868261275c565b9695505050505050565b6000606063095ea7b360e01b8484604051602401611cfe9291906132d7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050611d87858261275c565b95945050505050565b6020820151156114895781516020830151611dca9073ffffffffffffffffffffffffffffffffffffffff831690849063ffffffff6127ce16565b611de65760405162461bcd60e51b8152600401610419906134bb565b8173ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff167fe6e0ef9cd056ca98561ca60e347ada61e1ede2f1142a078951b7a52e1e508e608560200151604051611c1e9190613340565b604051600090606090339084907f59c3746e635078efc737fb3f37dd8188203b8df10bbad35878a7d156f4f51c41908590a3836060015173ffffffffffffffffffffffffffffffffffffffff1663c2d85afc85608001518660a00151866040518463ffffffff1660e01b8152600401611ec693929190613310565b600060405180830381600087803b158015611ee057600080fd5b505af1158015611ef4573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f3a9190810190612cf0565b915091509250929050565b6000816040015160200151600014158015611f7a575060408201515173ffffffffffffffffffffffffffffffffffffffff1615155b156120b8576000606083604001516000015173ffffffffffffffffffffffffffffffffffffffff166370a0823160e01b30604051602401611fbb9190613285565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161204491906131d8565b6000604051808303816000865af19150503d8060008114612081576040519150601f19603f3d011682016040523d82523d6000602084013e612086565b606091505b5091509150818015612099575060008151115b6120b55760405162461bcd60e51b815260040161041990613529565b50505b6020808301510151158015906120e8575060208201515173ffffffffffffffffffffffffffffffffffffffff1615155b15612226576000606083602001516000015173ffffffffffffffffffffffffffffffffffffffff166370a0823160e01b306040516024016121299190613285565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516121b291906131d8565b6000604051808303816000865af19150503d80600081146121ef576040519150601f19603f3d011682016040523d82523d6000602084013e6121f4565b606091505b5091509150818015612207575060008151115b6122235760405162461bcd60e51b815260040161041990613529565b50505b61222f826116e1565b60048190556040513391907f844435c59f7ccdf12de134e8f9b3b7d664fe9f06e3263680779599ba4097bc3f9061226790869061392d565b60405180910390a3505060045490565b6040518060400160405280600381526020017f61636c00000000000000000000000000000000000000000000000000000000008152506002816040516122bd91906131d8565b9081526020016040518091039020546000146122eb5760405162461bcd60e51b81526004016104199061374f565b436002826040516122fc91906131d8565b908152604051908190036020019020556123367f586df60400000000000000000000000000000000000000000000000000000000836119bb565b8060405161234491906131d8565b604051908190038120907f7bc2a48a4a566e237a12186f19d985b0f76afc9d5290601edac19876253670c290600090a25050565b7fffffffff0000000000000000000000000000000000000000000000000000000081166000908152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517fbf5e1f87f5ab65b58074cd29244d7c487a948983cda4b932e0f966b62bd34aca906124029083906133cf565b60405180910390a150565b61241683610d9a565b156124335760405162461bcd60e51b8152600401610419906136e1565b73ffffffffffffffffffffffffffffffffffffffff82166001141561246a5760405162461bcd60e51b8152600401610419906138bf565b7fffffffff000000000000000000000000000000000000000000000000000000008316600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff878116808652919093529281902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169286169290921790915551909133917fc62063b81f7036fd97a0dc546516e99f11004d2d76ca0fddd3866346c86e709190612521908690613285565b60405180910390a4505050565b808201828110156103a65760405162461bcd60e51b8152600401610419906138f6565b60008160000151826020015183604001518460600151856080015160405160200161257c91906132fd565b604051602081830303815290604052805190602001208660a001518760c00151805190602001206040516020016116f497969594939291906139df565b60405160009046906125d590309083908790879060200161321d565b6040516020818303038152906040528051906020012091505092915050565b7fffffffff000000000000000000000000000000000000000000000000000000008316600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff808716855292528220541680156127515773ffffffffffffffffffffffffffffffffffffffff8116600214156126775760019150506110cf565b6040517f097c810800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063097c8108906126cd908890889088906004016133fc565b602060405180830381600087803b1580156126e757600080fd5b505af1925050508015612735575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261273291810190612cb8565b60015b61273e57612751565b801561274f576001925050506110cf565b505b506000949350505050565b600061277d8373ffffffffffffffffffffffffffffffffffffffff166127ed565b612789575060006103a6565b6040516020818451602086016000885af180156127c6573d80156127b457602081146127bd576127c4565b600193506127c4565b8251151593505b505b505092915050565b6000606063a9059cbb60e01b8484604051602401611cfe9291906132d7565b3b151590565b6040805160608101909152806000815260006020820181905260409091015290565b604080518082019091526000808252602082015290565b80356103a681613add565b600082601f830112612847578081fd5b813561285a61285582613a4f565b613a28565b818152915060208083019084810160005b8481101561290f57813587016060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838c030112156128aa57600080fd5b6128b381613a28565b858301356128c081613add565b8152604083810135878301528284013567ffffffffffffffff8111156128e557600080fd5b6128f38d898388010161291a565b918301919091525086525050928201929082019060010161286b565b505050505092915050565b600082601f83011261292a578081fd5b813561293861285582613a6f565b915080825283602082850101111561294f57600080fd5b8060208401602084013760009082016020015292915050565b600082601f830112612978578081fd5b815161298661285582613a6f565b915080825283602082850101111561299d57600080fd5b6129ae816020840160208601613ab1565b5092915050565b6000604082840312156129c6578081fd5b6129d06040613a28565b905081356129dd81613add565b808252506020820135602082015292915050565b60006101008284031215612a03578081fd5b612a0d60c0613a28565b905081358152612a2083602084016129b5565b6020820152612a3283606084016129b5565b604082015260a0820135612a4581613add565b606082015260c082013567ffffffffffffffff811115612a6457600080fd5b612a708482850161291a565b60808301525060e082013560a082015292915050565b600060408284031215612a97578081fd5b612aa16040613a28565b9050813567ffffffffffffffff80821115612abb57600080fd5b81840160e08187031215612ace57600080fd5b612ad860e0613a28565b92508035835260208101356020840152612af5866040830161282c565b6040840152612b07866060830161282c565b6060840152608081013582811115612b1e57600080fd5b612b2a87828401612837565b60808501525060a081013560a084015260c081013582811115612b4c57600080fd5b612b588782840161291a565b60c0850152505090825260208301359080821115612b7557600080fd5b50612b82848285016129f1565b60208301525092915050565b600080600060608486031215612ba2578283fd5b8351612bad81613add565b6020850151909350612bbe81613add565b80925050604084015190509250925092565b60008060408385031215612be2578182fd5b8235612bed81613add565b9150602083013567ffffffffffffffff811115612c08578182fd5b612c14858286016129f1565b9150509250929050565b60008060408385031215612c30578182fd5b8251612c3b81613add565b6020939093015192949293505050565b60008060208385031215612c5d578182fd5b823567ffffffffffffffff80821115612c74578384fd5b81850186601f820112612c85578485fd5b8035925081831115612c95578485fd5b866020606085028301011115612ca9578485fd5b60200196919550909350505050565b600060208284031215612cc9578081fd5b815180151581146110cf578182fd5b600060208284031215612ce9578081fd5b5035919050565b60008060408385031215612d02578182fd5b8251915060208084015167ffffffffffffffff811115612d20578283fd5b80850186601f820112612d31578384fd5b80519150612d4161285583613a4f565b82815283810190828501865b85811015612d7657612d648b888451880101612968565b84529286019290860190600101612d4d565b5096999098509650505050505050565b60008060408385031215612d98578182fd5b823591506020830135612daa81613add565b809150509250929050565b600060208284031215612dc6578081fd5b81356110cf81613b02565b60008060408385031215612de3578182fd5b8235612dee81613b02565b91506020830135612daa81613add565b600080600060608486031215612e12578081fd5b8335612e1d81613b02565b92506020840135612e2d81613add565b91506040840135612e3d81613add565b809150509250925092565b600060208284031215612e59578081fd5b813567ffffffffffffffff811115612e6f578182fd5b6119b38482850161291a565b600060608284031215612e8c578081fd5b612e966060613a28565b823560038110612ea4578283fd5b81526020830135612eb481613b02565b60208201526040830135612ec781613add565b60408201529392505050565b600060208284031215612ee4578081fd5b813567ffffffffffffffff811115612efa578182fd5b6119b3848285016129f1565b600060208284031215612f17578081fd5b813567ffffffffffffffff811115612f2d578182fd5b6119b384828501612a86565b60008060408385031215612f4b578182fd5b823567ffffffffffffffff80821115612f62578384fd5b612f6e86838701612a86565b93506020850135915080821115612f83578283fd5b50612c148582860161291a565b60008060408385031215612fa2578182fd5b823567ffffffffffffffff811115612fb8578283fd5b612fc485828601612a86565b95602094909401359450505050565b600060208284031215612fe4578081fd5b5051919050565b6000815180845260208085019450848183028601828601855b858110156130645783830389528151606073ffffffffffffffffffffffffffffffffffffffff82511685528682015187860152604080830151828288015261304e83880182613071565b9c89019c96505050928601925050600101613004565b5090979650505050505050565b60008151808452613089816020860160208601613ab1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b805173ffffffffffffffffffffffffffffffffffffffff168252602090810151910152565b60006101008251845260208301516130fb60208601826130bb565b50604083015161310e60608601826130bb565b5073ffffffffffffffffffffffffffffffffffffffff60608401511660a085015260808301518160c086015261314682860182613071565b60a085015160e087015280935050505092915050565b60008151835260208201516020840152604082015173ffffffffffffffffffffffffffffffffffffffff80821660408601528060608501511660608601525050608082015160e060808501526131b560e0850182612feb565b60a084015160a086015260c0840151915084810360c0860152611d878183613071565b600082516131ea818460208701613ab1565b9190910192915050565b7f61636c0000000000000000000000000000000000000000000000000000000000815260030190565b7f657263336b2d7631000000000000000000000000000000000000000000000000815260609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166008850152601c840192909252603c830152605c820152607c0190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6000602082526110cf6020830184612feb565b6000606082526133236060830186612feb565b60208301949094525060400152919050565b901515815260200190565b90815260200190565b600060408201848352602060408185015281855180845260608601915060608382028701019350828701855b828110156133c1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030184526133af868351613071565b95509284019290840190600101613375565b509398975050505050505050565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b60007fffffffff000000000000000000000000000000000000000000000000000000008516825273ffffffffffffffffffffffffffffffffffffffff8416602083015260606040830152611d876060830184613071565b6000602082526110cf6020830184613071565b6000608082526134796080830186613071565b90508360208301526119b360408301846130bb565b602081016007831061349c57fe5b91905290565b6000838252604060208301526119b36040830184613071565b6020808252601a908201527f6465706f7369743a2062616420746f6b656e2072656c65617365000000000000604082015260600190565b60208082526010908201527f71756575653a2062616420737461746500000000000000000000000000000000604082015260600190565b60208082526011908201527f71756575653a2062616420636f6e666967000000000000000000000000000000604082015260600190565b60208082526009908201527f61636c3a20617574680000000000000000000000000000000000000000000000604082015260600190565b60208082526015908201527f71756575653a2062616420646973707574652069640000000000000000000000604082015260600190565b60208082526010908201527f71756575653a20626164206e6f6e636500000000000000000000000000000000604082015260600190565b60208082526010908201527f71756575653a206261642064656c617900000000000000000000000000000000604082015260600190565b60208082526010908201527f71756575653a2062616420726573657400000000000000000000000000000000604082015260600190565b60208082526013908201527f71756575653a20626164206665652070756c6c00000000000000000000000000604082015260600190565b60208082526014908201527f71756575653a20626164207375626d6974746572000000000000000000000000604082015260600190565b6020808252600b908201527f61636c3a2066726f7a656e000000000000000000000000000000000000000000604082015260600190565b60208082526012908201527f71756575653a2062616420617070726f76650000000000000000000000000000604082015260600190565b60208082526022908201527f696e697469616c697a61626c653a20616c726561647920696e697469616c697a60408201527f6564000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526010908201527f71756575653a2077616974206d6f726500000000000000000000000000000000604082015260600190565b60208082526017908201527f6465706f7369743a2062616420746f6b656e206c6f636b000000000000000000604082015260600190565b60208082526012908201527f71756575653a206e6f74207375626a6563740000000000000000000000000000604082015260600190565b6020808252601c908201527f63616c6c6461746173697a653a206c696d697420657863656564656400000000604082015260600190565b6020808252601c908201527f61636c3a20696e697469616c20726f6f74206d6973616c69676e656400000000604082015260600190565b6020808252600f908201527f61636c3a2062616420667265657a650000000000000000000000000000000000604082015260600190565b6020808252600e908201527f6d6174683a206f766572666c6f77000000000000000000000000000000000000604082015260600190565b6000602082526110cf60208301846130e0565b60006020825282516040602084015261395c606084018261315c565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848203016040850152611d8781836130e0565b6000602082526110cf602083018461315c565b600084825273ffffffffffffffffffffffffffffffffffffffff8416602083015260606040830152611d876060830184613071565b968752602087019590955273ffffffffffffffffffffffffffffffffffffffff9384166040870152919092166060850152608084019190915260a083015260c082015260e00190565b60405181810167ffffffffffffffff81118282101715613a4757600080fd5b604052919050565b600067ffffffffffffffff821115613a65578081fd5b5060209081020190565b600067ffffffffffffffff821115613a85578081fd5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b83811015613acc578181015183820152602001613ab4565b838111156107655750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114613aff57600080fd5b50565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114613aff57600080fdfea2646970667358221220047f58de53e183d409d81810d17312376c0fd2479adb7e90037508e7eab281fa64736f6c63430006080033d87da3e1f08043464b74e6b0861ccd8d8a5174e228287ac9b9f6efc1673da4ec7bc2a48a4a566e237a12186f19d985b0f76afc9d5290601edac19876253670c2
Deployed Bytecode
0x60806040523480156200001157600080fd5b50600436106200003a5760003560e01c80635001f3b5146200003f578063a691fc671462000061575b600080fd5b6200004962000078565b6040516200005891906200073e565b60405180910390f35b6200004962000072366004620004c6565b62000094565b60005473ffffffffffffffffffffffffffffffffffffffff1681565b600081156200016b576200016382638f8b35b260e01b8686604051602401620000bf9291906200075f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915260005473ffffffffffffffffffffffffffffffffffffffff16919063ffffffff620001b016565b9050620001a9565b83836040516200017b90620003db565b620001889291906200075f565b604051809103906000f080158015620001a5573d6000803e3d6000fd5b5090505b9392505050565b6000620001be84846200028e565b9050600060608273ffffffffffffffffffffffffffffffffffffffff1684604051620001eb919062000720565b6000604051808303816000865af19150503d80600081146200022a576040519150601f19603f3d011682016040523d82523d6000602084013e6200022f565b606091505b509150915081620002408262000302565b9062000284576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200027b9190620007f1565b60405180910390fd5b5050509392505050565b600060606200029d8462000349565b9050826037602083016000f5915073ffffffffffffffffffffffffffffffffffffffff8216620002fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200027b9062000806565b5092915050565b606060448251101562000325575060408051602081019091526000815262000344565b60048201915081806020019051810190620003419190620005a7565b90505b919050565b604051606090620003c5907f3d602d80600a3d3981f300000000000000000000000000000000000000000000907f363d3d373d3d3d363d73000000000000000000000000000000000000000000009085907f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000009060200162000697565b6040516020818303038152906040529050919050565b61473a80620008dc83390190565b803573ffffffffffffffffffffffffffffffffffffffff811681146200040e57600080fd5b92915050565b600082601f83011262000425578081fd5b81356200043c620004368262000865565b6200083d565b91508082528360208285010111156200045457600080fd5b8060208401602084013760009082016020015292915050565b6000604082840312156200047f578081fd5b6200048b60406200083d565b9050813573ffffffffffffffffffffffffffffffffffffffff81168114620004b257600080fd5b808252506020820135602082015292915050565b600080600060608486031215620004db578283fd5b620004e78585620003e9565b9250602084013567ffffffffffffffff8082111562000504578384fd5b818601610100818903121562000518578485fd5b6200052460c06200083d565b9250803583526200053988602083016200046d565b60208401526200054d88606083016200046d565b6040840152620005618860a08301620003e9565b606084015260c08101358281111562000578578586fd5b620005868982840162000414565b60808501525060e0013560a083015250929592945050506040919091013590565b600060208284031215620005b9578081fd5b815167ffffffffffffffff811115620005d0578182fd5b80830184601f820112620005e2578283fd5b80519150620005f5620004368362000865565b8281528560208484010111156200060a578384fd5b6200061d836020830160208501620008a8565b95945050505050565b6000815180845262000640816020860160208601620008a8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b805173ffffffffffffffffffffffffffffffffffffffff168252602090810151910152565b7fffffffffffffffffffff00000000000000000000000000000000000000000000948516815292909316600a83015260601b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660148201527fffffffffffffffffffffffffffffff000000000000000000000000000000000091909116602882015260370190565b6000825162000734818460208701620008a8565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8085168352604060208401528351604084015260208401516200079d606085018262000672565b506040840151620007b260a085018262000672565b5060608401511660e0830152608083015161010080840152620007da61014084018262000626565b60a085015161012085015280925050509392505050565b600060208252620001a9602083018462000626565b6020808252601a908201527f70726f78792d666163746f72793a206261642063726561746532000000000000604082015260600190565b60405181810167ffffffffffffffff811182821017156200085d57600080fd5b604052919050565b600067ffffffffffffffff8211156200087c578081fd5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b83811015620008c5578181015183820152602001620008ab565b83811115620008d5576000848401525b5050505056fe60806040523480156200001157600080fd5b506040516200473a3803806200473a833981016040819052620000349162000858565b81806002604051620000469062000967565b90815260200160405180910390205460001415620000785762000072816001600160e01b03620000ec16565b620000cc565b6001600160a01b038181166000908152600080516020620046fa833981519152602052604090205416600214620000cc5760405162461bcd60e51b8152600401620000c39062000a31565b60405180910390fd5b50620000e4905082826001600160e01b03620001bd16565b505062000b84565b604051806040016040528060038152602001621858db60ea1b8152506002816040516200011a919062000949565b9081526020016040518091039020546000146200014b5760405162461bcd60e51b8152600401620000c390620009ef565b436002826040516200015e919062000949565b908152604051908190036020019020556200018a63161b7d8160e21b836001600160e01b036200033416565b806040516200019a919062000949565b604051908190038120906000805160206200471a83398151915290600090a25050565b816002604051620001ce9062000967565b908152602001604051809103902054600014156200020057620001fa816001600160e01b03620000ec16565b6200024b565b6001600160a01b038181166000908152600080516020620046fa8339815191526020526040902054166002146200024b5760405162461bcd60e51b8152600401620000c39062000a31565b60405180604001604052806005815260200164717565756560d81b8152506002816040516200027b919062000949565b908152602001604051809103902054600014620002ac5760405162461bcd60e51b8152600401620000c390620009ef565b43600282604051620002bf919062000949565b90815260405190819003602001902055620002e3836001600160e01b036200034f16565b50620002ff63d311828160e01b6001600160e01b03620005de16565b806040516200030f919062000949565b604051908190038120906000805160206200471a83398151915290600090a250505050565b6200034b828260026001600160e01b036200063f16565b5050565b60008160400151602001516000141580156200037857506040820151516001600160a01b031615155b156200046957600060608360400151600001516001600160a01b03166370a0823160e01b30604051602401620003af919062000976565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051620003ef919062000949565b6000604051808303816000865af19150503d80600081146200042e576040519150601f19603f3d011682016040523d82523d6000602084013e62000433565b606091505b509150915081801562000447575060008151115b620004665760405162461bcd60e51b8152600401620000c3906200099f565b50505b6020808301510151158015906200048d57506020820151516001600160a01b031615155b156200057e57600060608360200151600001516001600160a01b03166370a0823160e01b30604051602401620004c4919062000976565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905162000504919062000949565b6000604051808303816000865af19150503d806000811462000543576040519150601f19603f3d011682016040523d82523d6000602084013e62000548565b606091505b50915091508180156200055c575060008151115b6200057b5760405162461bcd60e51b8152600401620000c3906200099f565b50505b62000594826200072960201b620016e11760201c565b60048190556040513391907f844435c59f7ccdf12de134e8f9b3b7d664fe9f06e3263680779599ba4097bc3f90620005ce90869062000a91565b60405180910390a3505060045490565b6001600160e01b0319811660009081526020819052604090819020805460ff19166001179055517fbf5e1f87f5ab65b58074cd29244d7c487a948983cda4b932e0f966b62bd34aca90620006349083906200098a565b60405180910390a150565b62000653836001600160e01b036200075b16565b15620006735760405162461bcd60e51b8152600401620000c390620009ca565b6001600160a01b03821660011415620006a05760405162461bcd60e51b8152600401620000c39062000a68565b6001600160e01b0319831660008181526003602090815260408083206001600160a01b03878116808652919093529281902080546001600160a01b0319169286169290921790915551909133917fc62063b81f7036fd97a0dc546516e99f11004d2d76ca0fddd3866346c86e7091906200071c90869062000976565b60405180910390a4505050565b6000816040516020016200073e919062000a91565b604051602081830303815290604052805190602001209050919050565b6001600160e01b031916600090815260036020908152604080832060018085529252909120546001600160a01b03161490565b80516001600160a01b0381168114620007a657600080fd5b92915050565b600082601f830112620007bd578081fd5b81516001600160401b03811115620007d3578182fd5b620007e8601f8201601f191660200162000b2a565b91508082528360208285010111156200080057600080fd5b6200081381602084016020860162000b51565b5092915050565b6000604082840312156200082c578081fd5b62000838604062000b2a565b90506200084683836200078e565b81526020820151602082015292915050565b600080604083850312156200086b578182fd5b6200087784846200078e565b60208401519092506001600160401b038082111562000894578283fd5b8185016101008188031215620008a8578384fd5b620008b460c062000b2a565b925080518352620008c987602083016200081a565b6020840152620008dd87606083016200081a565b6040840152620008f18760a083016200078e565b606084015260c08101518281111562000908578485fd5b6200091688828401620007ac565b60808501525060e0015160a083015250919491935090915050565b80516001600160a01b03168252602090810151910152565b600082516200095d81846020870162000b51565b9190910192915050565b621858db60ea1b815260030190565b6001600160a01b0391909116815260200190565b6001600160e01b031991909116815260200190565b60208082526011908201527071756575653a2062616420636f6e66696760781b604082015260600190565b6020808252600b908201526a30b1b61d10333937bd32b760a91b604082015260600190565b60208082526022908201527f696e697469616c697a61626c653a20616c726561647920696e697469616c697a604082015261195960f21b606082015260800190565b6020808252601c908201527f61636c3a20696e697469616c20726f6f74206d6973616c69676e656400000000604082015260600190565b6020808252600f908201526e61636c3a2062616420667265657a6560881b604082015260600190565b60006020825282516020830152602083015162000ab2604084018262000931565b50604083015162000ac7608084018262000931565b5060608301516001600160a01b031660c0830152608083015161010060e084018190528151610120850181905261014062000b09828288016020870162000b51565b60a0969096015191850191909152601f01601f191690920190920192915050565b6040518181016001600160401b038111828210171562000b4957600080fd5b604052919050565b60005b8381101562000b6e57818101518382015260200162000b54565b8381111562000b7e576000848401525b50505050565b613b668062000b946000396000f3fe608060405234801561001057600080fd5b50600436106101825760003560e01c80637e8c7f08116100d8578063affed0e01161008c578063c832048011610066578063c832048014610334578063cc1d4cab14610347578063e1f1176d1461035a57610182565b8063affed0e014610306578063bdf9a7261461030e578063c8182af01461032157610182565b806396fc8abd116100bd57806396fc8abd146102c0578063a157a10d146102e0578063a2157227146102f357610182565b80637e8c7f08146102985780638f8b35b2146102ad57610182565b80633e2da6a91161013a5780635a08160b116101145780635a08160b146102525780637744efda146102655780637c10dea61461027857610182565b80633e2da6a914610219578063495a98251461022c578063588497341461023f57610182565b80631c47671b1161016b5780631c47671b146101d15780631f13405b146101e65780633da956aa1461020657610182565b806301ffc9a71461018757806314d56921146101b0575b600080fd5b61019a610195366004612db5565b610362565b6040516101a79190613335565b60405180910390f35b6101c36101be366004612f90565b6103ac565b6040516101a7929190613349565b6101e46101df366004612c4b565b610631565b005b6101f96101f4366004612f39565b61076b565b6040516101a79190613340565b6101c3610214366004612f06565b610c88565b6101f9610227366004612d86565b610d7d565b61019a61023a366004612db5565b610d9a565b6101e461024d366004612dd1565b610df2565b6101e4610260366004612f39565b610e80565b6101f9610273366004612ed3565b61105e565b61028b610286366004612cd8565b6110d6565b6040516101a7919061348e565b6102a06110eb565b6040516101a791906133cf565b6101e46102bb366004612bd0565b61110f565b6102d36102ce366004612dd1565b6112b5565b6040516101a79190613285565b6101e46102ee366004612dd1565b6112e8565b6101e4610301366004612dfe565b611371565b6101f96113fb565b6101e461031c366004612db5565b611401565b6102d361032f366004612cd8565b61148d565b6101f9610342366004612f06565b6114b5565b6101f9610355366004612e48565b6116be565b6101f96116db565b7fffffffff00000000000000000000000000000000000000000000000000000000811660009081526020819052604081205460ff16806103a657506103a682611711565b92915050565b6000606060006103bb8561175b565b60208087015160600151600083815260088352604080822073ffffffffffffffffffffffffffffffffffffffff8416835290935291909120549192509060018601146104225760405162461bcd60e51b815260040161041990613597565b60405180910390fd5b600082815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845282528083208390558483526006909152902061046f90600263ffffffff61177f16565b6000808273ffffffffffffffffffffffffffffffffffffffff1663db18af6c886040518263ffffffff1660e01b81526004016104ab9190613340565b6040805180830381600087803b1580156104c457600080fd5b505af11580156104d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fc9190612c1e565b909250905073ffffffffffffffffffffffffffffffffffffffff821630146105365760405162461bcd60e51b81526004016104199061381a565b600481146105668161054957600461054c565b60035b60008781526006602052604090209063ffffffff6117b816565b3373ffffffffffffffffffffffffffffffffffffffff16857f027d8a5d945eb361475964ed2c71b8332b27af2d630ab5daf829d67afd2584e6836040516105ad9190613335565b60405180910390a3878473ffffffffffffffffffffffffffffffffffffffff167f56c8631a8915c0d362dbe57a61215fdde954f73f81c8a3a1f55572fb015207b1846040516105fc9190613340565b60405180910390a3801561062157610613896117f7565b96509650505050505061062a565b610613896118b8565b9250929050565b60408051602036601f81018290048202830182019093528282527f586df604000000000000000000000000000000000000000000000000000000009261069492849233926000918190840183828082843760009201919091525061197592505050565b6106b05760405162461bcd60e51b815260040161041990613560565b60005b82811015610765576106c36127f3565b8484838181106106cf57fe5b9050606002018036038101906106e59190612e7b565b90506000815160028111156106f657fe5b14156107135761070e816020015182604001516119bb565b61075c565b60018151600281111561072257fe5b141561073a5761070e816020015182604001516119c7565b60028151600281111561074957fe5b141561075c5761075c8160200151611a95565b506001016106b3565b50505050565b6000631f13405b60e01b6107b781336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b6107d35760405162461bcd60e51b815260040161041990613560565b60006107de8561175b565b600081815260076020908152604080832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000163317905560069091529020909150610834906001600263ffffffff611b4d16565b61083c612815565b50602085015160400151610856813363ffffffff611b6116565b6000866020015160600151905060008060008373ffffffffffffffffffffffffffffffffffffffff16637b751b9e6040518163ffffffff1660e01b815260040160606040518083038186803b1580156108ae57600080fd5b505afa1580156108c2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108e69190612b8e565b9194509250905061091573ffffffffffffffffffffffffffffffffffffffff831633308463ffffffff611c2b16565b6109315760405162461bcd60e51b815260040161041990613673565b61095873ffffffffffffffffffffffffffffffffffffffff8316848363ffffffff611cdf16565b6109745760405162461bcd60e51b815260040161041990613718565b8373ffffffffffffffffffffffffffffffffffffffff1663c13517e160028c6040516020016109a39190613940565b6040516020818303038152906040526040518363ffffffff1660e01b81526004016109cf9291906134a2565b602060405180830381600087803b1580156109e957600080fd5b505af11580156109fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a219190612fd3565b9750610a4b73ffffffffffffffffffffffffffffffffffffffff831684600063ffffffff611cdf16565b610a675760405162461bcd60e51b81526004016104199061363c565b895160408082015160c09092015190517f7cb57c6400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff871692637cb57c6492610ac8928d9291906004016139aa565b600060405180830381600087803b158015610ae257600080fd5b505af1158015610af6573d6000803e3d6000fd5b50506040517f7cb57c6400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87169250637cb57c649150610b50908b9033908e906004016139aa565b600060405180830381600087803b158015610b6a57600080fd5b505af1158015610b7e573d6000803e3d6000fd5b50506040517f7e9adccf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff87169250637e9adccf9150610bd4908b90600401613340565b600060405180830381600087803b158015610bee57600080fd5b505af1158015610c02573d6000803e3d6000fd5b505050600087815260086020908152604080832073ffffffffffffffffffffffffffffffffffffffff891684529091529081902060018b0190555133915087907f429df837eb45b6713f725a0d3e57db939fd7dd7d58bb3cd967fa37091572db9f90610c73908d908d908b90613466565b60405180910390a35050505050505092915050565b60006060633da956aa60e01b610cd681336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b610cf25760405162461bcd60e51b815260040161041990613560565b835160200151421015610d175760405162461bcd60e51b8152600401610419906137ac565b6000610d228561175b565b6000818152600660208190526040909120919250610d49919060019063ffffffff611b4d16565b8451604001516020808701510151610d669163ffffffff611d9016565b8451610d729082611e4b565b935093505050915091565b600860209081526000928352604080842090915290825290205481565b7fffffffff00000000000000000000000000000000000000000000000000000000166000908152600360209081526040808320600180855292529091205473ffffffffffffffffffffffffffffffffffffffff161490565b60408051602036601f81018290048202830182019093528282527f586df6040000000000000000000000000000000000000000000000000000000092610e5592849233926000918190840183828082843760009201919091525061197592505050565b610e715760405162461bcd60e51b815260040161041990613560565b610e7b83836119c7565b505050565b635a08160b60e01b610eca81336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b610ee65760405162461bcd60e51b815260040161041990613560565b6000610ef18461175b565b60008181526006602052604090209091506002815460ff166006811115610f1457fe5b1415610fd857610f2d816002600563ffffffff611b4d16565b600082815260076020908152604080832080547fffffffffffffffffffffffff000000000000000000000000000000000000000081169091556008835281842089840180516060015173ffffffffffffffffffffffffffffffffffffffff908116875291855283862095909555895190920151935190920151911691610fb9919063ffffffff611d9016565b602086015160400151610fd2908263ffffffff611d9016565b50611008565b610feb816001600563ffffffff611b4d16565b84516040015160208087015101516110089163ffffffff611d9016565b3373ffffffffffffffffffffffffffffffffffffffff16827fe2530b9681f9726904f9ca7fe725c0c53ea1b72370981ac6a5beaa9758c8c3568660405161104f9190613453565b60405180910390a35050505050565b6000637744efda60e01b6110aa81336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b6110c65760405162461bcd60e51b815260040161041990613560565b6110cf83611f45565b9392505050565b60066020526000908152604090205460ff1681565b7f586df6040000000000000000000000000000000000000000000000000000000081565b81600260405161111e906131f4565b908152602001604051809103902054600014156111435761113e81612277565b6111a9565b73ffffffffffffffffffffffffffffffffffffffff81811660009081527fd87da3e1f08043464b74e6b0861ccd8d8a5174e228287ac9b9f6efc1673da4ec6020526040902054166002146111a95760405162461bcd60e51b815260040161041990613888565b6040518060400160405280600581526020017f71756575650000000000000000000000000000000000000000000000000000008152506002816040516111ef91906131d8565b90815260200160405180910390205460001461121d5760405162461bcd60e51b81526004016104199061374f565b4360028260405161122e91906131d8565b9081526040519081900360200190205561124783611f45565b506112717fd311828100000000000000000000000000000000000000000000000000000000612378565b8060405161127f91906131d8565b604051908190038120907f7bc2a48a4a566e237a12186f19d985b0f76afc9d5290601edac19876253670c290600090a250505050565b600360209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff1681565b60408051602036601f81018290048202830182019093528282527f586df604000000000000000000000000000000000000000000000000000000009261134b92849233926000918190840183828082843760009201919091525061197592505050565b6113675760405162461bcd60e51b815260040161041990613560565b610e7b83836119bb565b60408051602036601f81018290048202830182019093528282527f586df60400000000000000000000000000000000000000000000000000000000926113d492849233926000918190840183828082843760009201919091525061197592505050565b6113f05760405162461bcd60e51b815260040161041990613560565b61076584848461240d565b60055481565b60408051602036601f81018290048202830182019093528282527f586df604000000000000000000000000000000000000000000000000000000009261146492849233926000918190840183828082843760009201919091525061197592505050565b6114805760405162461bcd60e51b815260040161041990613560565b61148982611a95565b5050565b60076020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b600063c832048060e01b61150181336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061197592505050565b61151d5760405162461bcd60e51b815260040161041990613560565b6005805460010190819055835151146115485760405162461bcd60e51b8152600401610419906135ce565b600061155784602001516116e1565b9050600454811461157a5760405162461bcd60e51b815260040161041990613529565b602084015151611590904263ffffffff61252e16565b84516020015110156115b45760405162461bcd60e51b815260040161041990613605565b83516040015173ffffffffffffffffffffffffffffffffffffffff1633146115ee5760405162461bcd60e51b8152600401610419906136aa565b602084015160a0015136908111156116185760405162461bcd60e51b815260040161041990613851565b61162e6116288660000151612551565b836125b9565b60008181526006602052604081209195506116519190600163ffffffff611b4d16565b611659612815565b50602080860151015185516040015161167990829063ffffffff611b6116565b847f67f87ff46443c95843c7bd72a026dd23ba0015528ce9f8f15c5c6917645034ef87600001516040516116ad9190613997565b60405180910390a250505050919050565b805160208183018101805160028252928201919093012091525481565b60045481565b6000816040516020016116f4919061392d565b604051602081830303815290604052805190602001209050919050565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f01ffc9a70000000000000000000000000000000000000000000000000000000014919050565b60006103a661176d8360000151612551565b61177a84602001516116e1565b6125b9565b80600681111561178b57fe5b825460ff16600681111561179b57fe5b146114895760405162461bcd60e51b8152600401610419906134f2565b8154819083907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360068111156117ee57fe5b02179055505050565b6000606060006118068461175b565b600081815260066020819052604090912091925061182d919060039063ffffffff611b4d16565b60008181526007602090815260409182902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905585519091015185820151909101516118829163ffffffff611d9016565b83516040908101516020860151909101516118a29163ffffffff611d9016565b83516118ae9082611e4b565b9250925050915091565b6000606060006118c78461175b565b60008181526006602052604090209091506118eb906004600563ffffffff611b4d16565b600081815260076020908152604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000008116909155858201519091015173ffffffffffffffffffffffffffffffffffffffff90911690611955908263ffffffff611d9016565b60208501516040015161196e908263ffffffff611d9016565b5050915091565b60006119828484846125f4565b806119b357506119b3847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff846125f4565b949350505050565b6114898282600261240d565b6119d082610d9a565b156119ed5760405162461bcd60e51b8152600401610419906136e1565b7fffffffff000000000000000000000000000000000000000000000000000000008216600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616808552925280832080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055519092339290917f682f2c466c1e9f6883eb72cbced01373e1cb18b05ae5c8bc04dc73d73e29f8cd9190a45050565b611a9e81610d9a565b15611abb5760405162461bcd60e51b8152600401610419906136e1565b7fffffffff00000000000000000000000000000000000000000000000000000000811660008181526003602090815260408083206001808552925280832080547fffffffffffffffffffffffff000000000000000000000000000000000000000016909217909155513392917f049c6b8b07a879425742523fa80f8ffb25e39ad518c93a5896a0df19518397e591a350565b611b57838361177f565b610e7b83826117b8565b6020820151156114895781516020830151611b9d9073ffffffffffffffffffffffffffffffffffffffff8316908490309063ffffffff611c2b16565b611bb95760405162461bcd60e51b8152600401610419906137e3565b8173ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff167f989eaa915cbb416ea3d6f9a63b1a3de51770c7674b11fe21ecdf76b4e1d139108560200151604051611c1e9190613340565b60405180910390a3505050565b600060606323b872dd60e01b858585604051602401611c4c939291906132a6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050611cd5868261275c565b9695505050505050565b6000606063095ea7b360e01b8484604051602401611cfe9291906132d7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050611d87858261275c565b95945050505050565b6020820151156114895781516020830151611dca9073ffffffffffffffffffffffffffffffffffffffff831690849063ffffffff6127ce16565b611de65760405162461bcd60e51b8152600401610419906134bb565b8173ffffffffffffffffffffffffffffffffffffffff16836000015173ffffffffffffffffffffffffffffffffffffffff167fe6e0ef9cd056ca98561ca60e347ada61e1ede2f1142a078951b7a52e1e508e608560200151604051611c1e9190613340565b604051600090606090339084907f59c3746e635078efc737fb3f37dd8188203b8df10bbad35878a7d156f4f51c41908590a3836060015173ffffffffffffffffffffffffffffffffffffffff1663c2d85afc85608001518660a00151866040518463ffffffff1660e01b8152600401611ec693929190613310565b600060405180830381600087803b158015611ee057600080fd5b505af1158015611ef4573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f3a9190810190612cf0565b915091509250929050565b6000816040015160200151600014158015611f7a575060408201515173ffffffffffffffffffffffffffffffffffffffff1615155b156120b8576000606083604001516000015173ffffffffffffffffffffffffffffffffffffffff166370a0823160e01b30604051602401611fbb9190613285565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161204491906131d8565b6000604051808303816000865af19150503d8060008114612081576040519150601f19603f3d011682016040523d82523d6000602084013e612086565b606091505b5091509150818015612099575060008151115b6120b55760405162461bcd60e51b815260040161041990613529565b50505b6020808301510151158015906120e8575060208201515173ffffffffffffffffffffffffffffffffffffffff1615155b15612226576000606083602001516000015173ffffffffffffffffffffffffffffffffffffffff166370a0823160e01b306040516024016121299190613285565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516121b291906131d8565b6000604051808303816000865af19150503d80600081146121ef576040519150601f19603f3d011682016040523d82523d6000602084013e6121f4565b606091505b5091509150818015612207575060008151115b6122235760405162461bcd60e51b815260040161041990613529565b50505b61222f826116e1565b60048190556040513391907f844435c59f7ccdf12de134e8f9b3b7d664fe9f06e3263680779599ba4097bc3f9061226790869061392d565b60405180910390a3505060045490565b6040518060400160405280600381526020017f61636c00000000000000000000000000000000000000000000000000000000008152506002816040516122bd91906131d8565b9081526020016040518091039020546000146122eb5760405162461bcd60e51b81526004016104199061374f565b436002826040516122fc91906131d8565b908152604051908190036020019020556123367f586df60400000000000000000000000000000000000000000000000000000000836119bb565b8060405161234491906131d8565b604051908190038120907f7bc2a48a4a566e237a12186f19d985b0f76afc9d5290601edac19876253670c290600090a25050565b7fffffffff0000000000000000000000000000000000000000000000000000000081166000908152602081905260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517fbf5e1f87f5ab65b58074cd29244d7c487a948983cda4b932e0f966b62bd34aca906124029083906133cf565b60405180910390a150565b61241683610d9a565b156124335760405162461bcd60e51b8152600401610419906136e1565b73ffffffffffffffffffffffffffffffffffffffff82166001141561246a5760405162461bcd60e51b8152600401610419906138bf565b7fffffffff000000000000000000000000000000000000000000000000000000008316600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff878116808652919093529281902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169286169290921790915551909133917fc62063b81f7036fd97a0dc546516e99f11004d2d76ca0fddd3866346c86e709190612521908690613285565b60405180910390a4505050565b808201828110156103a65760405162461bcd60e51b8152600401610419906138f6565b60008160000151826020015183604001518460600151856080015160405160200161257c91906132fd565b604051602081830303815290604052805190602001208660a001518760c00151805190602001206040516020016116f497969594939291906139df565b60405160009046906125d590309083908790879060200161321d565b6040516020818303038152906040528051906020012091505092915050565b7fffffffff000000000000000000000000000000000000000000000000000000008316600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff808716855292528220541680156127515773ffffffffffffffffffffffffffffffffffffffff8116600214156126775760019150506110cf565b6040517f097c810800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063097c8108906126cd908890889088906004016133fc565b602060405180830381600087803b1580156126e757600080fd5b505af1925050508015612735575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261273291810190612cb8565b60015b61273e57612751565b801561274f576001925050506110cf565b505b506000949350505050565b600061277d8373ffffffffffffffffffffffffffffffffffffffff166127ed565b612789575060006103a6565b6040516020818451602086016000885af180156127c6573d80156127b457602081146127bd576127c4565b600193506127c4565b8251151593505b505b505092915050565b6000606063a9059cbb60e01b8484604051602401611cfe9291906132d7565b3b151590565b6040805160608101909152806000815260006020820181905260409091015290565b604080518082019091526000808252602082015290565b80356103a681613add565b600082601f830112612847578081fd5b813561285a61285582613a4f565b613a28565b818152915060208083019084810160005b8481101561290f57813587016060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838c030112156128aa57600080fd5b6128b381613a28565b858301356128c081613add565b8152604083810135878301528284013567ffffffffffffffff8111156128e557600080fd5b6128f38d898388010161291a565b918301919091525086525050928201929082019060010161286b565b505050505092915050565b600082601f83011261292a578081fd5b813561293861285582613a6f565b915080825283602082850101111561294f57600080fd5b8060208401602084013760009082016020015292915050565b600082601f830112612978578081fd5b815161298661285582613a6f565b915080825283602082850101111561299d57600080fd5b6129ae816020840160208601613ab1565b5092915050565b6000604082840312156129c6578081fd5b6129d06040613a28565b905081356129dd81613add565b808252506020820135602082015292915050565b60006101008284031215612a03578081fd5b612a0d60c0613a28565b905081358152612a2083602084016129b5565b6020820152612a3283606084016129b5565b604082015260a0820135612a4581613add565b606082015260c082013567ffffffffffffffff811115612a6457600080fd5b612a708482850161291a565b60808301525060e082013560a082015292915050565b600060408284031215612a97578081fd5b612aa16040613a28565b9050813567ffffffffffffffff80821115612abb57600080fd5b81840160e08187031215612ace57600080fd5b612ad860e0613a28565b92508035835260208101356020840152612af5866040830161282c565b6040840152612b07866060830161282c565b6060840152608081013582811115612b1e57600080fd5b612b2a87828401612837565b60808501525060a081013560a084015260c081013582811115612b4c57600080fd5b612b588782840161291a565b60c0850152505090825260208301359080821115612b7557600080fd5b50612b82848285016129f1565b60208301525092915050565b600080600060608486031215612ba2578283fd5b8351612bad81613add565b6020850151909350612bbe81613add565b80925050604084015190509250925092565b60008060408385031215612be2578182fd5b8235612bed81613add565b9150602083013567ffffffffffffffff811115612c08578182fd5b612c14858286016129f1565b9150509250929050565b60008060408385031215612c30578182fd5b8251612c3b81613add565b6020939093015192949293505050565b60008060208385031215612c5d578182fd5b823567ffffffffffffffff80821115612c74578384fd5b81850186601f820112612c85578485fd5b8035925081831115612c95578485fd5b866020606085028301011115612ca9578485fd5b60200196919550909350505050565b600060208284031215612cc9578081fd5b815180151581146110cf578182fd5b600060208284031215612ce9578081fd5b5035919050565b60008060408385031215612d02578182fd5b8251915060208084015167ffffffffffffffff811115612d20578283fd5b80850186601f820112612d31578384fd5b80519150612d4161285583613a4f565b82815283810190828501865b85811015612d7657612d648b888451880101612968565b84529286019290860190600101612d4d565b5096999098509650505050505050565b60008060408385031215612d98578182fd5b823591506020830135612daa81613add565b809150509250929050565b600060208284031215612dc6578081fd5b81356110cf81613b02565b60008060408385031215612de3578182fd5b8235612dee81613b02565b91506020830135612daa81613add565b600080600060608486031215612e12578081fd5b8335612e1d81613b02565b92506020840135612e2d81613add565b91506040840135612e3d81613add565b809150509250925092565b600060208284031215612e59578081fd5b813567ffffffffffffffff811115612e6f578182fd5b6119b38482850161291a565b600060608284031215612e8c578081fd5b612e966060613a28565b823560038110612ea4578283fd5b81526020830135612eb481613b02565b60208201526040830135612ec781613add565b60408201529392505050565b600060208284031215612ee4578081fd5b813567ffffffffffffffff811115612efa578182fd5b6119b3848285016129f1565b600060208284031215612f17578081fd5b813567ffffffffffffffff811115612f2d578182fd5b6119b384828501612a86565b60008060408385031215612f4b578182fd5b823567ffffffffffffffff80821115612f62578384fd5b612f6e86838701612a86565b93506020850135915080821115612f83578283fd5b50612c148582860161291a565b60008060408385031215612fa2578182fd5b823567ffffffffffffffff811115612fb8578283fd5b612fc485828601612a86565b95602094909401359450505050565b600060208284031215612fe4578081fd5b5051919050565b6000815180845260208085019450848183028601828601855b858110156130645783830389528151606073ffffffffffffffffffffffffffffffffffffffff82511685528682015187860152604080830151828288015261304e83880182613071565b9c89019c96505050928601925050600101613004565b5090979650505050505050565b60008151808452613089816020860160208601613ab1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b805173ffffffffffffffffffffffffffffffffffffffff168252602090810151910152565b60006101008251845260208301516130fb60208601826130bb565b50604083015161310e60608601826130bb565b5073ffffffffffffffffffffffffffffffffffffffff60608401511660a085015260808301518160c086015261314682860182613071565b60a085015160e087015280935050505092915050565b60008151835260208201516020840152604082015173ffffffffffffffffffffffffffffffffffffffff80821660408601528060608501511660608601525050608082015160e060808501526131b560e0850182612feb565b60a084015160a086015260c0840151915084810360c0860152611d878183613071565b600082516131ea818460208701613ab1565b9190910192915050565b7f61636c0000000000000000000000000000000000000000000000000000000000815260030190565b7f657263336b2d7631000000000000000000000000000000000000000000000000815260609490941b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166008850152601c840192909252603c830152605c820152607c0190565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6000602082526110cf6020830184612feb565b6000606082526133236060830186612feb565b60208301949094525060400152919050565b901515815260200190565b90815260200190565b600060408201848352602060408185015281855180845260608601915060608382028701019350828701855b828110156133c1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030184526133af868351613071565b95509284019290840190600101613375565b509398975050505050505050565b7fffffffff0000000000000000000000000000000000000000000000000000000091909116815260200190565b60007fffffffff000000000000000000000000000000000000000000000000000000008516825273ffffffffffffffffffffffffffffffffffffffff8416602083015260606040830152611d876060830184613071565b6000602082526110cf6020830184613071565b6000608082526134796080830186613071565b90508360208301526119b360408301846130bb565b602081016007831061349c57fe5b91905290565b6000838252604060208301526119b36040830184613071565b6020808252601a908201527f6465706f7369743a2062616420746f6b656e2072656c65617365000000000000604082015260600190565b60208082526010908201527f71756575653a2062616420737461746500000000000000000000000000000000604082015260600190565b60208082526011908201527f71756575653a2062616420636f6e666967000000000000000000000000000000604082015260600190565b60208082526009908201527f61636c3a20617574680000000000000000000000000000000000000000000000604082015260600190565b60208082526015908201527f71756575653a2062616420646973707574652069640000000000000000000000604082015260600190565b60208082526010908201527f71756575653a20626164206e6f6e636500000000000000000000000000000000604082015260600190565b60208082526010908201527f71756575653a206261642064656c617900000000000000000000000000000000604082015260600190565b60208082526010908201527f71756575653a2062616420726573657400000000000000000000000000000000604082015260600190565b60208082526013908201527f71756575653a20626164206665652070756c6c00000000000000000000000000604082015260600190565b60208082526014908201527f71756575653a20626164207375626d6974746572000000000000000000000000604082015260600190565b6020808252600b908201527f61636c3a2066726f7a656e000000000000000000000000000000000000000000604082015260600190565b60208082526012908201527f71756575653a2062616420617070726f76650000000000000000000000000000604082015260600190565b60208082526022908201527f696e697469616c697a61626c653a20616c726561647920696e697469616c697a60408201527f6564000000000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526010908201527f71756575653a2077616974206d6f726500000000000000000000000000000000604082015260600190565b60208082526017908201527f6465706f7369743a2062616420746f6b656e206c6f636b000000000000000000604082015260600190565b60208082526012908201527f71756575653a206e6f74207375626a6563740000000000000000000000000000604082015260600190565b6020808252601c908201527f63616c6c6461746173697a653a206c696d697420657863656564656400000000604082015260600190565b6020808252601c908201527f61636c3a20696e697469616c20726f6f74206d6973616c69676e656400000000604082015260600190565b6020808252600f908201527f61636c3a2062616420667265657a650000000000000000000000000000000000604082015260600190565b6020808252600e908201527f6d6174683a206f766572666c6f77000000000000000000000000000000000000604082015260600190565b6000602082526110cf60208301846130e0565b60006020825282516040602084015261395c606084018261315c565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848203016040850152611d8781836130e0565b6000602082526110cf602083018461315c565b600084825273ffffffffffffffffffffffffffffffffffffffff8416602083015260606040830152611d876060830184613071565b968752602087019590955273ffffffffffffffffffffffffffffffffffffffff9384166040870152919092166060850152608084019190915260a083015260c082015260e00190565b60405181810167ffffffffffffffff81118282101715613a4757600080fd5b604052919050565b600067ffffffffffffffff821115613a65578081fd5b5060209081020190565b600067ffffffffffffffff821115613a85578081fd5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b83811015613acc578181015183820152602001613ab4565b838111156107655750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114613aff57600080fd5b50565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114613aff57600080fdfea2646970667358221220047f58de53e183d409d81810d17312376c0fd2479adb7e90037508e7eab281fa64736f6c63430006080033d87da3e1f08043464b74e6b0861ccd8d8a5174e228287ac9b9f6efc1673da4ec7bc2a48a4a566e237a12186f19d985b0f76afc9d5290601edac19876253670c2a2646970667358221220b172753c8385a1d34d2071a1ee0f7d825f059cbdd1b587f3a6383726a08b6eb764736f6c63430006080033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.