Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
17407642 | 385 days ago | Contract Creation | 0 ETH |
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:
GovernancePatchUpgrade
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
Yes with 10000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; import "../v1/Governance.sol"; import "../v3-relayer-registry/GovernanceStakingUpgrade.sol"; contract GovernancePatchUpgrade is GovernanceStakingUpgrade { mapping(uint256 => bytes32) public proposalCodehashes; constructor(address stakingRewardsAddress, address gasCompLogic, address userVaultAddress) public GovernanceStakingUpgrade(stakingRewardsAddress, gasCompLogic, userVaultAddress) { } /// @notice Return the version of the contract function version() external pure virtual override returns (string memory) { return "4.patch-exploit"; } /** * @notice Execute a proposal * @dev This upgrade should protect against Metamorphic contracts by comparing the proposal's extcodehash with a stored one * @param proposalId The proposal's ID */ function execute(uint256 proposalId) public payable virtual override(Governance) { require(msg.sender != address(this), "Governance::propose: pseudo-external function"); Proposal storage proposal = proposals[proposalId]; address target = proposal.target; bytes32 proposalCodehash; assembly { proposalCodehash := extcodehash(target) } require( proposalCodehash == proposalCodehashes[proposalId], "Governance::propose: metamorphic contracts not allowed" ); super.execute(proposalId); } /** * @notice Internal function called from propoese * @dev This should store the extcodehash of the proposal contract * @param proposer proposer address * @param target smart contact address that will be executed as result of voting * @param description description of the proposal * @return proposalId new proposal id */ function _propose(address proposer, address target, string memory description) internal virtual override(Governance) returns (uint256 proposalId) { // Implies all former predicates were valid proposalId = super._propose(proposer, target, description); bytes32 proposalCodehash; assembly { proposalCodehash := extcodehash(target) } proposalCodehashes[proposalId] = proposalCodehash; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/upgrades-core/contracts/Initializable.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "torn-token/contracts/ENS.sol"; import "torn-token/contracts/TORN.sol"; import "./Delegation.sol"; import "./Configuration.sol"; contract Governance is Initializable, Configuration, Delegation, EnsResolve { using SafeMath for uint256; /// @notice Possible states that a proposal may be in enum ProposalState { Pending, Active, Defeated, Timelocked, AwaitingExecution, Executed, Expired } struct Proposal { // Creator of the proposal address proposer; // target addresses for the call to be made address target; // The block at which voting begins uint256 startTime; // The block at which voting ends: votes must be cast prior to this block uint256 endTime; // Current number of votes in favor of this proposal uint256 forVotes; // Current number of votes in opposition to this proposal uint256 againstVotes; // Flag marking whether the proposal has been executed bool executed; // Flag marking whether the proposal voting time has been extended // Voting time can be extended once, if the proposal outcome has changed during CLOSING_PERIOD bool extended; // Receipts of ballots for the entire set of voters mapping(address => Receipt) receipts; } /// @notice Ballot receipt record for a voter struct Receipt { // Whether or not a vote has been cast bool hasVoted; // Whether or not the voter supports the proposal bool support; // The number of votes the voter had, which were cast uint256 votes; } /// @notice The official record of all proposals ever proposed Proposal[] public proposals; /// @notice The latest proposal for each proposer mapping(address => uint256) public latestProposalIds; /// @notice Timestamp when a user can withdraw tokens mapping(address => uint256) public canWithdrawAfter; TORN public torn; /// @notice An event emitted when a new proposal is created event ProposalCreated( uint256 indexed id, address indexed proposer, address target, uint256 startTime, uint256 endTime, string description ); /// @notice An event emitted when a vote has been cast on a proposal event Voted(uint256 indexed proposalId, address indexed voter, bool indexed support, uint256 votes); /// @notice An event emitted when a proposal has been executed event ProposalExecuted(uint256 indexed proposalId); /// @notice Makes this instance inoperable to prevent selfdestruct attack /// Proxy will still be able to properly initialize its storage constructor() public initializer { torn = TORN(0x000000000000000000000000000000000000dEaD); _initializeConfiguration(); } function initialize(bytes32 _torn) public initializer { torn = TORN(resolve(_torn)); // Create a dummy proposal so that indexes start from 1 proposals.push( Proposal({ proposer: address(this), target: 0x000000000000000000000000000000000000dEaD, startTime: 0, endTime: 0, forVotes: 0, againstVotes: 0, executed: true, extended: false }) ); _initializeConfiguration(); } function lock(address owner, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual { torn.permit(owner, address(this), amount, deadline, v, r, s); _transferTokens(owner, amount); } function lockWithApproval(uint256 amount) public virtual { _transferTokens(msg.sender, amount); } function unlock(uint256 amount) public virtual { require(getBlockTimestamp() > canWithdrawAfter[msg.sender], "Governance: tokens are locked"); lockedBalance[msg.sender] = lockedBalance[msg.sender].sub(amount, "Governance: insufficient balance"); require(torn.transfer(msg.sender, amount), "TORN: transfer failed"); } function propose(address target, string memory description) external returns (uint256) { return _propose(msg.sender, target, description); } /** * @notice Propose implementation * @param proposer proposer address * @param target smart contact address that will be executed as result of voting * @param description description of the proposal * @return the new proposal id */ function _propose(address proposer, address target, string memory description) internal virtual override(Delegation) returns (uint256) { uint256 votingPower = lockedBalance[proposer]; require( votingPower >= PROPOSAL_THRESHOLD, "Governance::propose: proposer votes below proposal threshold" ); // target should be a contract require(Address.isContract(target), "Governance::propose: not a contract"); uint256 latestProposalId = latestProposalIds[proposer]; if (latestProposalId != 0) { ProposalState proposersLatestProposalState = state(latestProposalId); require( proposersLatestProposalState != ProposalState.Active && proposersLatestProposalState != ProposalState.Pending, "Governance::propose: one live proposal per proposer, found an already active proposal" ); } uint256 startTime = getBlockTimestamp().add(VOTING_DELAY); uint256 endTime = startTime.add(VOTING_PERIOD); Proposal memory newProposal = Proposal({ proposer: proposer, target: target, startTime: startTime, endTime: endTime, forVotes: 0, againstVotes: 0, executed: false, extended: false }); proposals.push(newProposal); uint256 proposalId = proposalCount(); latestProposalIds[newProposal.proposer] = proposalId; _lockTokens(proposer, endTime.add(VOTE_EXTEND_TIME).add(EXECUTION_EXPIRATION).add(EXECUTION_DELAY)); emit ProposalCreated(proposalId, proposer, target, startTime, endTime, description); return proposalId; } function execute(uint256 proposalId) public payable virtual { require( state(proposalId) == ProposalState.AwaitingExecution, "Governance::execute: invalid proposal state" ); Proposal storage proposal = proposals[proposalId]; proposal.executed = true; address target = proposal.target; require(Address.isContract(target), "Governance::execute: not a contract"); (bool success, bytes memory data) = target.delegatecall(abi.encodeWithSignature("executeProposal()")); if (!success) { if (data.length > 0) { revert(string(data)); } else { revert("Proposal execution failed"); } } emit ProposalExecuted(proposalId); } function castVote(uint256 proposalId, bool support) external virtual { _castVote(msg.sender, proposalId, support); } function _castVote(address voter, uint256 proposalId, bool support) internal override(Delegation) { require(state(proposalId) == ProposalState.Active, "Governance::_castVote: voting is closed"); Proposal storage proposal = proposals[proposalId]; Receipt storage receipt = proposal.receipts[voter]; bool beforeVotingState = proposal.forVotes <= proposal.againstVotes; uint256 votes = lockedBalance[voter]; require(votes > 0, "Governance: balance is 0"); if (receipt.hasVoted) { if (receipt.support) { proposal.forVotes = proposal.forVotes.sub(receipt.votes); } else { proposal.againstVotes = proposal.againstVotes.sub(receipt.votes); } } if (support) { proposal.forVotes = proposal.forVotes.add(votes); } else { proposal.againstVotes = proposal.againstVotes.add(votes); } if (!proposal.extended && proposal.endTime.sub(getBlockTimestamp()) < CLOSING_PERIOD) { bool afterVotingState = proposal.forVotes <= proposal.againstVotes; if (beforeVotingState != afterVotingState) { proposal.extended = true; proposal.endTime = proposal.endTime.add(VOTE_EXTEND_TIME); } } receipt.hasVoted = true; receipt.support = support; receipt.votes = votes; _lockTokens( voter, proposal.endTime.add(VOTE_EXTEND_TIME).add(EXECUTION_EXPIRATION).add(EXECUTION_DELAY) ); emit Voted(proposalId, voter, support, votes); } function _lockTokens(address owner, uint256 timestamp) internal { if (timestamp > canWithdrawAfter[owner]) { canWithdrawAfter[owner] = timestamp; } } function _transferTokens(address owner, uint256 amount) internal virtual { require(torn.transferFrom(owner, address(this), amount), "TORN: transferFrom failed"); lockedBalance[owner] = lockedBalance[owner].add(amount); } function getReceipt(uint256 proposalId, address voter) public view returns (Receipt memory) { return proposals[proposalId].receipts[voter]; } function state(uint256 proposalId) public view returns (ProposalState) { require(proposalId <= proposalCount() && proposalId > 0, "Governance::state: invalid proposal id"); Proposal storage proposal = proposals[proposalId]; if (getBlockTimestamp() <= proposal.startTime) { return ProposalState.Pending; } else if (getBlockTimestamp() <= proposal.endTime) { return ProposalState.Active; } else if ( proposal.forVotes <= proposal.againstVotes || proposal.forVotes + proposal.againstVotes < QUORUM_VOTES ) { return ProposalState.Defeated; } else if (proposal.executed) { return ProposalState.Executed; } else if (getBlockTimestamp() >= proposal.endTime.add(EXECUTION_DELAY).add(EXECUTION_EXPIRATION)) { return ProposalState.Expired; } else if (getBlockTimestamp() >= proposal.endTime.add(EXECUTION_DELAY)) { return ProposalState.AwaitingExecution; } else { return ProposalState.Timelocked; } } function proposalCount() public view returns (uint256) { return proposals.length - 1; } function getBlockTimestamp() internal view virtual returns (uint256) { // solium-disable-next-line security/no-block-members return block.timestamp; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; import { GovernanceGasUpgrade } from "../v2-vault-and-gas/GovernanceGasUpgrade.sol"; import { ITornadoStakingRewards } from "./interfaces/ITornadoStakingRewards.sol"; /** * @notice The Governance staking upgrade. Adds modifier to any un/lock operation to update rewards * @dev CONTRACT RISKS: * - if updateRewards reverts (should not happen due to try/catch) locks/unlocks could be blocked * - generally inherits risks from former governance upgrades */ contract GovernanceStakingUpgrade is GovernanceGasUpgrade { ITornadoStakingRewards public immutable Staking; event RewardUpdateSuccessful(address indexed account); event RewardUpdateFailed(address indexed account, bytes indexed errorData); constructor(address stakingRewardsAddress, address gasCompLogic, address userVaultAddress) public GovernanceGasUpgrade(gasCompLogic, userVaultAddress) { Staking = ITornadoStakingRewards(stakingRewardsAddress); } /** * @notice This modifier should make a call to Staking to update the rewards for account without impacting logic on revert * @dev try / catch block to handle reverts * @param account Account to update rewards for. * */ modifier updateRewards(address account) { try Staking.updateRewardsOnLockedBalanceChange(account, lockedBalance[account]) { emit RewardUpdateSuccessful(account); } catch (bytes memory errorData) { emit RewardUpdateFailed(account, errorData); } _; } function lock(address owner, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual override updateRewards(owner) { super.lock(owner, amount, deadline, v, r, s); } function lockWithApproval(uint256 amount) public virtual override updateRewards(msg.sender) { super.lockWithApproval(amount); } function unlock(uint256 amount) public virtual override updateRewards(msg.sender) { super.unlock(amount); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b > a) return (false, 0); return (true, a - b); } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a / b); } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { if (b == 0) return (false, 0); return (true, a % b); } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) return 0; uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: division by zero"); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "SafeMath: modulo by zero"); return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); return a - b; } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryDiv}. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.24 <0.7.0; /** * @title Initializable * * @dev Deprecated. This contract is kept in the Upgrades Plugins for backwards compatibility purposes. * Users should use openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol instead. * * Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. address self = address(this); uint256 cs; assembly { cs := extcodesize(self) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.2 <0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * 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 account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; interface ENS { function resolver(bytes32 node) external view returns (Resolver); } interface Resolver { function addr(bytes32 node) external view returns (address); } contract EnsResolve { function resolve(bytes32 node) public view virtual returns (address) { ENS Registry = ENS( getChainId() == 1 ? 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e : 0x8595bFb0D940DfEDC98943FA8a907091203f25EE ); return Registry.resolver(node).addr(node); } function bulkResolve(bytes32[] memory domains) public view returns (address[] memory result) { result = new address[](domains.length); for (uint256 i = 0; i < domains.length; i++) { result[i] = resolve(domains[i]); } } function getChainId() internal pure returns (uint256) { uint256 chainId; assembly { chainId := chainid() } return chainId; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; import "@openzeppelin/contracts/math/Math.sol"; import "./ERC20Permit.sol"; import "./ENS.sol"; contract TORN is ERC20("TornadoCash", "TORN"), ERC20Burnable, ERC20Permit, Pausable, EnsResolve { using SafeERC20 for IERC20; uint256 public immutable canUnpauseAfter; address public immutable governance; mapping(address => bool) public allowedTransferee; event Allowed(address target); event Disallowed(address target); struct Recipient { bytes32 to; uint256 amount; } constructor( bytes32 _governance, uint256 _pausePeriod, Recipient[] memory _vestings ) public { address _resolvedGovernance = resolve(_governance); governance = _resolvedGovernance; allowedTransferee[_resolvedGovernance] = true; for (uint256 i = 0; i < _vestings.length; i++) { address to = resolve(_vestings[i].to); _mint(to, _vestings[i].amount); allowedTransferee[to] = true; } canUnpauseAfter = blockTimestamp().add(_pausePeriod); _pause(); require(totalSupply() == 10000000 ether, "TORN: incorrect distribution"); } modifier onlyGovernance() { require(_msgSender() == governance, "TORN: only governance can perform this action"); _; } function changeTransferability(bool decision) public onlyGovernance { require(blockTimestamp() > canUnpauseAfter, "TORN: cannot change transferability yet"); if (decision) { _unpause(); } else { _pause(); } } function addToAllowedList(address[] memory target) public onlyGovernance { for (uint256 i = 0; i < target.length; i++) { allowedTransferee[target[i]] = true; emit Allowed(target[i]); } } function removeFromAllowedList(address[] memory target) public onlyGovernance { for (uint256 i = 0; i < target.length; i++) { allowedTransferee[target[i]] = false; emit Disallowed(target[i]); } } function _beforeTokenTransfer( address from, address to, uint256 amount ) internal override { super._beforeTokenTransfer(from, to, amount); require(!paused() || allowedTransferee[from] || allowedTransferee[to], "TORN: paused"); require(to != address(this), "TORN: invalid recipient"); } /// @dev Method to claim junk and accidentally sent tokens function rescueTokens( IERC20 _token, address payable _to, uint256 _balance ) external onlyGovernance { require(_to != address(0), "TORN: can not send to zero address"); if (_token == IERC20(0)) { // for Ether uint256 totalBalance = address(this).balance; uint256 balance = _balance == 0 ? totalBalance : Math.min(totalBalance, _balance); _to.transfer(balance); } else { // any other erc20 uint256 totalBalance = _token.balanceOf(address(this)); uint256 balance = _balance == 0 ? totalBalance : Math.min(totalBalance, _balance); require(balance > 0, "TORN: trying to send 0 balance"); _token.safeTransfer(_to, balance); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; import "./Core.sol"; abstract contract Delegation is Core { /// @notice Delegatee records mapping(address => address) public delegatedTo; event Delegated(address indexed account, address indexed to); event Undelegated(address indexed account, address indexed from); function delegate(address to) external { address previous = delegatedTo[msg.sender]; require( to != msg.sender && to != address(this) && to != address(0) && to != previous, "Governance: invalid delegatee" ); if (previous != address(0)) { emit Undelegated(msg.sender, previous); } delegatedTo[msg.sender] = to; emit Delegated(msg.sender, to); } function undelegate() external { address previous = delegatedTo[msg.sender]; require(previous != address(0), "Governance: tokens are already undelegated"); delegatedTo[msg.sender] = address(0); emit Undelegated(msg.sender, previous); } function proposeByDelegate(address from, address target, string memory description) external returns (uint256) { require(delegatedTo[from] == msg.sender, "Governance: not authorized"); return _propose(from, target, description); } function _propose(address proposer, address target, string memory description) internal virtual returns (uint256); function castDelegatedVote(address[] memory from, uint256 proposalId, bool support) external virtual { for (uint256 i = 0; i < from.length; i++) { require(delegatedTo[from[i]] == msg.sender, "Governance: not authorized"); _castVote(from[i], proposalId, support); } if (lockedBalance[msg.sender] > 0) { _castVote(msg.sender, proposalId, support); } } function _castVote(address voter, uint256 proposalId, bool support) internal virtual; }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; contract Configuration { /// @notice Time delay between proposal vote completion and its execution uint256 public EXECUTION_DELAY; /// @notice Time before a passed proposal is considered expired uint256 public EXECUTION_EXPIRATION; /// @notice The number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed uint256 public QUORUM_VOTES; /// @notice The number of votes required in order for a voter to become a proposer uint256 public PROPOSAL_THRESHOLD; /// @notice The delay before voting on a proposal may take place, once proposed /// It is needed to prevent reorg attacks that replace the proposal uint256 public VOTING_DELAY; /// @notice The duration of voting on a proposal uint256 public VOTING_PERIOD; /// @notice If the outcome of a proposal changes during CLOSING_PERIOD, the vote will be extended by VOTE_EXTEND_TIME (no more than once) uint256 public CLOSING_PERIOD; /// @notice If the outcome of a proposal changes during CLOSING_PERIOD, the vote will be extended by VOTE_EXTEND_TIME (no more than once) uint256 public VOTE_EXTEND_TIME; modifier onlySelf() { require(msg.sender == address(this), "Governance: unauthorized"); _; } function _initializeConfiguration() internal { EXECUTION_DELAY = 2 days; EXECUTION_EXPIRATION = 3 days; QUORUM_VOTES = 25_000e18; // 0.25% of TORN PROPOSAL_THRESHOLD = 1000e18; // 0.01% of TORN VOTING_DELAY = 75 seconds; VOTING_PERIOD = 3 days; CLOSING_PERIOD = 1 hours; VOTE_EXTEND_TIME = 6 hours; } function setExecutionDelay(uint256 executionDelay) external onlySelf { EXECUTION_DELAY = executionDelay; } function setExecutionExpiration(uint256 executionExpiration) external onlySelf { EXECUTION_EXPIRATION = executionExpiration; } function setQuorumVotes(uint256 quorumVotes) external onlySelf { QUORUM_VOTES = quorumVotes; } function setProposalThreshold(uint256 proposalThreshold) external onlySelf { PROPOSAL_THRESHOLD = proposalThreshold; } function setVotingDelay(uint256 votingDelay) external onlySelf { VOTING_DELAY = votingDelay; } function setVotingPeriod(uint256 votingPeriod) external onlySelf { VOTING_PERIOD = votingPeriod; } function setClosingPeriod(uint256 closingPeriod) external onlySelf { CLOSING_PERIOD = closingPeriod; } function setVoteExtendTime(uint256 voteExtendTime) external onlySelf { // VOTE_EXTEND_TIME should be less EXECUTION_DELAY to prevent double voting require(voteExtendTime < EXECUTION_DELAY, "Governance: incorrect voteExtendTime"); VOTE_EXTEND_TIME = voteExtendTime; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; import { GovernanceVaultUpgrade } from "./GovernanceVaultUpgrade.sol"; import { GasCompensator } from "./GasCompensator.sol"; import { Math } from "@openzeppelin/contracts/math/Math.sol"; /** * @notice This contract should upgrade governance to be able to compensate gas for certain actions. * These actions are set to castVote, castDelegatedVote in this contract. * */ contract GovernanceGasUpgrade is GovernanceVaultUpgrade, GasCompensator { /** * @notice constructor * @param _gasCompLogic gas compensation vault address * @param _userVault tornado vault address * */ constructor(address _gasCompLogic, address _userVault) public GovernanceVaultUpgrade(_userVault) GasCompensator(_gasCompLogic) { } /// @notice check that msg.sender is multisig modifier onlyMultisig() { require(msg.sender == returnMultisigAddress(), "only multisig"); _; } /** * @notice receive ether function, does nothing but receive ether * */ receive() external payable { } /** * @notice function to add a certain amount of ether for gas compensations * @dev send ether is used in the logic as we don't expect multisig to make a reentrancy attack on governance * @param gasCompensationsLimit the amount of gas to be compensated * */ function setGasCompensations(uint256 gasCompensationsLimit) external virtual override onlyMultisig { require( payable(address(gasCompensationVault)).send( Math.min(gasCompensationsLimit, address(this).balance) ) ); } /** * @notice function to withdraw funds from the gas compensator * @dev send ether is used in the logic as we don't expect multisig to make a reentrancy attack on governance * @param amount the amount of ether to withdraw * */ function withdrawFromHelper(uint256 amount) external virtual override onlyMultisig { gasCompensationVault.withdrawToGovernance(amount); } /** * @notice function to cast callers votes on a proposal * @dev IMPORTANT: This function uses the gasCompensation modifier. * as such this function can trigger a payable fallback. * It is not possible to vote without revert more than once, * without hasAccountVoted being true, eliminating gas refunds in this case. * Gas compensation is also using the low level send(), forwarding 23000 gas * as to disallow further logic execution above that threshold. * @param proposalId id of proposal account is voting on * @param support true if yes false if no * */ function castVote(uint256 proposalId, bool support) external virtual override gasCompensation( msg.sender, !hasAccountVoted(proposalId, msg.sender) && !checkIfQuorumReached(proposalId), (msg.sender == tx.origin ? 21e3 : 0) ) { _castVote(msg.sender, proposalId, support); } /** * @notice function to cast callers votes and votes delegated to the caller * @param from array of addresses that should have delegated to voter * @param proposalId id of proposal account is voting on * @param support true if yes false if no * */ function castDelegatedVote(address[] memory from, uint256 proposalId, bool support) external virtual override { require(from.length > 0, "Can not be empty"); _castDelegatedVote( from, proposalId, support, !hasAccountVoted(proposalId, msg.sender) && !checkIfQuorumReached(proposalId) ); } /// @notice checker for success on deployment /// @return returns precise version of governance function version() external pure virtual override returns (string memory) { return "2.lottery-and-gas-upgrade"; } /** * @notice function to check if quorum has been reached on a given proposal * @param proposalId id of proposal * @return true if quorum has been reached * */ function checkIfQuorumReached(uint256 proposalId) public view returns (bool) { return (proposals[proposalId].forVotes + proposals[proposalId].againstVotes >= QUORUM_VOTES); } /** * @notice function to check if account has voted on a proposal * @param proposalId id of proposal account should have voted on * @param account address of the account * @return true if acc has voted * */ function hasAccountVoted(uint256 proposalId, address account) public view returns (bool) { return proposals[proposalId].receipts[account].hasVoted; } /** * @notice function to retrieve the multisig address * @dev reasoning: if multisig changes we need governance to approve the next multisig address, * so simply inherit in a governance upgrade from this function and set the new address * @return the multisig address * */ function returnMultisigAddress() public pure virtual returns (address) { return 0xb04E030140b30C27bcdfaafFFA98C57d80eDa7B4; } /** * @notice This should handle the logic of the external function * @dev IMPORTANT: This function uses the gasCompensation modifier. * as such this function can trigger a payable fallback. * It is not possible to vote without revert more than once, * without hasAccountVoted being true, eliminating gas refunds in this case. * Gas compensation is also using the low level send(), forwarding 23000 gas * as to disallow further logic execution above that threshold. * @param from array of addresses that should have delegated to voter * @param proposalId id of proposal account is voting on * @param support true if yes false if no * @param gasCompensated true if gas should be compensated (given all internal checks pass) * */ function _castDelegatedVote(address[] memory from, uint256 proposalId, bool support, bool gasCompensated) internal gasCompensation(msg.sender, gasCompensated, (msg.sender == tx.origin ? 21e3 : 0)) { for (uint256 i = 0; i < from.length; i++) { address delegator = from[i]; require( delegatedTo[delegator] == msg.sender || delegator == msg.sender, "Governance: not authorized" ); require(!gasCompensated || !hasAccountVoted(proposalId, delegator), "Governance: voted already"); _castVote(delegator, proposalId, support); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; interface ITornadoStakingRewards { function updateRewardsOnLockedBalanceChange(address account, uint256 amountLockedBeforehand) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../../utils/Context.sol"; import "./IERC20.sol"; import "../../math/SafeMath.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for {name} and {symbol}, initializes {decimals} with * a default value of 18. * * To select a different value for {decimals}, use {_setupDecimals}. * * All three of these values are immutable: they can only be set once during * construction. */ constructor (string memory name_, string memory symbol_) public { _name = name_; _symbol = symbol_; _decimals = 18; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * Requirements: * * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Sets {decimals} to a value other than the default one of 18. * * WARNING: This function should only be called from the constructor. Most * applications that interact with token contracts will not expect * {decimals} to ever change, and may work incorrectly if it does. */ function _setupDecimals(uint8 decimals_) internal virtual { _decimals = decimals_; } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../../utils/Context.sol"; import "./ERC20.sol"; /** * @dev Extension of {ERC20} that allows token holders to destroy both their own * tokens and those that they have an allowance for, in a way that can be * recognized off-chain (via event analysis). */ abstract contract ERC20Burnable is Context, ERC20 { using SafeMath for uint256; /** * @dev Destroys `amount` tokens from the caller. * * See {ERC20-_burn}. */ function burn(uint256 amount) public virtual { _burn(_msgSender(), amount); } /** * @dev Destroys `amount` tokens from `account`, deducting from the caller's * allowance. * * See {ERC20-_burn} and {ERC20-allowance}. * * Requirements: * * - the caller must have allowance for ``accounts``'s tokens of at least * `amount`. */ function burnFrom(address account, uint256 amount) public virtual { uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance"); _approve(account, _msgSender(), decreasedAllowance); _burn(account, amount); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./IERC20.sol"; import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; import "./Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor () internal { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; // Adapted copy from https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2237/files import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "./ECDSA.sol"; /** * @dev Extension of {ERC20} that allows token holders to use their tokens * without sending any transactions by setting {IERC20-allowance} with a * signature using the {permit} method, and then spend them via * {IERC20-transferFrom}. * * The {permit} signature mechanism conforms to the {IERC2612Permit} interface. */ abstract contract ERC20Permit is ERC20 { mapping(address => uint256) private _nonces; bytes32 private constant _PERMIT_TYPEHASH = keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ); // Mapping of ChainID to domain separators. This is a very gas efficient way // to not recalculate the domain separator on every call, while still // automatically detecting ChainID changes. mapping(uint256 => bytes32) private _domainSeparators; constructor() internal { _updateDomainSeparator(); } /** * @dev See {IERC2612Permit-permit}. * * If https://eips.ethereum.org/EIPS/eip-1344[ChainID] ever changes, the * EIP712 Domain Separator is automatically recalculated. */ function permit( address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public { require(blockTimestamp() <= deadline, "ERC20Permit: expired deadline"); bytes32 hashStruct = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, amount, _nonces[owner], deadline)); bytes32 hash = keccak256(abi.encodePacked(uint16(0x1901), _domainSeparator(), hashStruct)); address signer = ECDSA.recover(hash, v, r, s); require(signer == owner, "ERC20Permit: invalid signature"); _nonces[owner]++; _approve(owner, spender, amount); } /** * @dev See {IERC2612Permit-nonces}. */ function nonces(address owner) public view returns (uint256) { return _nonces[owner]; } function _updateDomainSeparator() private returns (bytes32) { uint256 _chainID = chainID(); bytes32 newDomainSeparator = keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name())), keccak256(bytes("1")), // Version _chainID, address(this) ) ); _domainSeparators[_chainID] = newDomainSeparator; return newDomainSeparator; } // Returns the domain separator, updating it if chainID changes function _domainSeparator() private returns (bytes32) { bytes32 domainSeparator = _domainSeparators[chainID()]; if (domainSeparator != 0x00) { return domainSeparator; } else { return _updateDomainSeparator(); } } function chainID() public view virtual returns (uint256 _chainID) { assembly { _chainID := chainid() } } function blockTimestamp() public view virtual returns (uint256) { return block.timestamp; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; pragma experimental ABIEncoderV2; abstract contract Core { /// @notice Locked token balance for each account mapping(address => uint256) public lockedBalance; }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; import { Governance } from "../v1/Governance.sol"; import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; import { ITornadoVault } from "./interfaces/ITornadoVault.sol"; /// @title Version 2 Governance contract of the tornado.cash governance contract GovernanceVaultUpgrade is Governance { using SafeMath for uint256; // vault which stores user TORN ITornadoVault public immutable userVault; // call Governance v1 constructor constructor(address _userVault) public Governance() { userVault = ITornadoVault(_userVault); } /// @notice Withdraws TORN from governance if conditions permit /// @param amount the amount of TORN to withdraw function unlock(uint256 amount) public virtual override { require(getBlockTimestamp() > canWithdrawAfter[msg.sender], "Governance: tokens are locked"); lockedBalance[msg.sender] = lockedBalance[msg.sender].sub(amount, "Governance: insufficient balance"); userVault.withdrawTorn(msg.sender, amount); } /// @notice checker for success on deployment /// @return returns precise version of governance function version() external pure virtual returns (string memory) { return "2.vault-migration"; } /// @notice transfers tokens from the contract to the vault, withdrawals are unlock() /// @param owner account/contract which (this) spender will send to the user vault /// @param amount amount which spender will send to the user vault function _transferTokens(address owner, uint256 amount) internal virtual override { require(torn.transferFrom(owner, address(userVault), amount), "TORN: transferFrom failed"); lockedBalance[owner] = lockedBalance[owner].add(amount); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; interface IGasCompensationVault { function compensateGas(address recipient, uint256 gasAmount) external; function withdrawToGovernance(uint256 amount) external; } /** * @notice This abstract contract is used to add gas compensation functionality to a contract. * */ abstract contract GasCompensator { using SafeMath for uint256; /// @notice this vault is necessary for the gas compensation functionality to work IGasCompensationVault public immutable gasCompensationVault; constructor(address _gasCompensationVault) public { gasCompensationVault = IGasCompensationVault(_gasCompensationVault); } /** * @notice modifier which should compensate gas to account if eligible * @dev Consider reentrancy, repeated calling of the function being compensated, eligibility. * @param account address to be compensated * @param eligible if the account is eligible for compensations or not * @param extra extra amount in gas to be compensated, will be multiplied by basefee * */ modifier gasCompensation(address account, bool eligible, uint256 extra) { if (eligible) { uint256 startGas = gasleft(); _; uint256 gasToCompensate = startGas.sub(gasleft()).add(extra).add(10e3); gasCompensationVault.compensateGas(account, gasToCompensate); } else { _; } } /** * @notice inheritable unimplemented function to withdraw ether from the vault * */ function withdrawFromHelper(uint256 amount) external virtual; /** * @notice inheritable unimplemented function to deposit ether into the vault * */ function setGasCompensations(uint256 _gasCompensationsLimit) external virtual; }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0 <0.8.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; // A copy from https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2237/files /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { // Check the signature length if (signature.length != 65) { revert("ECDSA: invalid signature length"); } // Divide the signature in r, s and v variables bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. // solhint-disable-next-line no-inline-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := mload(add(signature, 0x41)) } return recover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover-bytes32-bytes-} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. require(uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: invalid signature 's' value"); require(v == 27 || v == 28, "ECDSA: invalid signature 'v' value"); // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); require(signer != address(0), "ECDSA: invalid signature"); return signer; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * replicates the behavior of the * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`] * JSON-RPC method. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.12; pragma experimental ABIEncoderV2; interface ITornadoVault { function withdrawTorn(address recipient, uint256 amount) external; }
{ "remappings": [ "@forge-std/=lib/forge-std/src/", "@gnosis.pm/=node_modules/@gnosis.pm/", "@gnosis.pm/ido-contracts/=node_modules/@gnosis.pm/ido-contracts/", "@interfaces/=test/forge/interfaces/", "@openzeppelin/=node_modules/@openzeppelin/", "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/", "@openzeppelin/upgrades-core/=node_modules/@openzeppelin/upgrades-core/", "@proprietary/=src/proprietary/", "@root/=src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "torn-token/=node_modules/torn-token/", "tornado-governance/=node_modules/tornado-governance/" ], "optimizer": { "enabled": true, "runs": 10000000 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "istanbul", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"stakingRewardsAddress","type":"address"},{"internalType":"address","name":"gasCompLogic","type":"address"},{"internalType":"address","name":"userVaultAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Delegated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"proposer","type":"address"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endTime","type":"uint256"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"ProposalCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"ProposalExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"bytes","name":"errorData","type":"bytes"}],"name":"RewardUpdateFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"RewardUpdateSuccessful","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"}],"name":"Undelegated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalId","type":"uint256"},{"indexed":true,"internalType":"address","name":"voter","type":"address"},{"indexed":true,"internalType":"bool","name":"support","type":"bool"},{"indexed":false,"internalType":"uint256","name":"votes","type":"uint256"}],"name":"Voted","type":"event"},{"inputs":[],"name":"CLOSING_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXECUTION_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXECUTION_EXPIRATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROPOSAL_THRESHOLD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUORUM_VOTES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Staking","outputs":[{"internalType":"contract ITornadoStakingRewards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VOTE_EXTEND_TIME","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VOTING_DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VOTING_PERIOD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"domains","type":"bytes32[]"}],"name":"bulkResolve","outputs":[{"internalType":"address[]","name":"result","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"canWithdrawAfter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"from","type":"address[]"},{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"bool","name":"support","type":"bool"}],"name":"castDelegatedVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"bool","name":"support","type":"bool"}],"name":"castVote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"checkIfQuorumReached","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegatedTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"gasCompensationVault","outputs":[{"internalType":"contract IGasCompensationVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"address","name":"voter","type":"address"}],"name":"getReceipt","outputs":[{"components":[{"internalType":"bool","name":"hasVoted","type":"bool"},{"internalType":"bool","name":"support","type":"bool"},{"internalType":"uint256","name":"votes","type":"uint256"}],"internalType":"struct Governance.Receipt","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"hasAccountVoted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_torn","type":"bytes32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"latestProposalIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"lockWithApproval","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lockedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposalCodehashes","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proposalCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposals","outputs":[{"internalType":"address","name":"proposer","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"forVotes","type":"uint256"},{"internalType":"uint256","name":"againstVotes","type":"uint256"},{"internalType":"bool","name":"executed","type":"bool"},{"internalType":"bool","name":"extended","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"string","name":"description","type":"string"}],"name":"propose","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"target","type":"address"},{"internalType":"string","name":"description","type":"string"}],"name":"proposeByDelegate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"returnMultisigAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"closingPeriod","type":"uint256"}],"name":"setClosingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"executionDelay","type":"uint256"}],"name":"setExecutionDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"executionExpiration","type":"uint256"}],"name":"setExecutionExpiration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"gasCompensationsLimit","type":"uint256"}],"name":"setGasCompensations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalThreshold","type":"uint256"}],"name":"setProposalThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"quorumVotes","type":"uint256"}],"name":"setQuorumVotes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"voteExtendTime","type":"uint256"}],"name":"setVoteExtendTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"votingDelay","type":"uint256"}],"name":"setVotingDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"votingPeriod","type":"uint256"}],"name":"setVotingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"proposalId","type":"uint256"}],"name":"state","outputs":[{"internalType":"enum Governance.ProposalState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"torn","outputs":[{"internalType":"contract TORN","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"undelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"userVault","outputs":[{"internalType":"contract ITornadoVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawFromHelper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60e06040523480156200001157600080fd5b50604051620043643803806200436483398101604081905262000034916200016b565b82828281818181600060019054906101000a900460ff16806200005c57506200005c62000124565b806200006b575060005460ff16155b620000935760405162461bcd60e51b81526004016200008a90620001be565b60405180910390fd5b600054610100900460ff16158015620000bf576000805460ff1961ff0019909116610100171660011790555b604080546001600160a01b03191661dead179055620000dd6200012a565b8015620000f0576000805461ff00191690555b506001600160601b0319606091821b811660805291811b821660a0529590951b90941660c052506200022595505050505050565b303b1590565b6202a3006033556203f480603481905569054b40b1f852bda00000603555683635c9adc5dea00000603655604b603755603855610e10603955615460603a55565b60008060006060848603121562000180578283fd5b83516200018d816200020c565b6020850151909350620001a0816200020c565b6040850151909250620001b3816200020c565b809150509250925092565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201526d195b881a5b9a5d1a585b1a5e995960921b606082015260800190565b6001600160a01b03811681146200022257600080fd5b50565b60805160601c60a05160601c60c05160601c6140dc62000288600039806110c9528061190c5280611df75280611f42525080610a4052806112f552806114935280611d40528061275f5250806118625280612540528061311a52506140dc6000f3fe6080604052600436106103175760003560e01c80639ae697bf1161019a578063da35c664116100e1578063ece40cc11161008a578063f57df22e11610064578063f57df22e1461088b578063f9e54234146108a0578063fe0d94c1146108cd5761031e565b8063ece40cc11461082b578063ef3f8bb11461084b578063f0b768921461086b5761031e565b8063e4917d9f116100bb578063e4917d9f146107cb578063e525aa08146107eb578063ea0217cf1461080b5761031e565b8063da35c66414610769578063e01f52371461077e578063e23a9a521461079e5761031e565b8063b54426c811610143578063ce25d71c1161011d578063ce25d71c1461071f578063d6159fe514610734578063d6f0948c146107495761031e565b8063b54426c8146106bf578063b859f11b146106df578063c0c0e820146106ff5761031e565b8063a72edda311610174578063a72edda314610675578063adf898a414610695578063b1610d7e146106aa5761031e565b80639ae697bf1461062b5780639daafec71461064b578063a6c26603146106605761031e565b80635c23bdf51161025e57806370b0f66011610207578063932d5157116101e1578063932d5157146105cb5780639498bd71146105eb5780639a9e3b6e1461060b5761031e565b806370b0f660146105815780638b34a960146105a157806392ab89bb146105b65761031e565b8063671dd27511610238578063671dd275146105375780636a6617551461054c5780636dc2dc6c146105615761031e565b80635c23bdf5146104d75780636198e339146104f757806365da1264146105175761031e565b806337f135d7116102c0578063587a6ecb1161029a578063587a6ecb1461048257806358e9fff0146104975780635c19a95c146104b75761031e565b806337f135d71461041e5780633e4f49e61461043357806354fd4d50146104605761031e565b806317977c61116102f157806317977c61146103a257806324b0435f146103cf57806332687ec1146103f15761031e565b8063013cf08b1461032357806302ec8f9e1461036057806315373e3d146103825761031e565b3661031e57005b600080fd5b34801561032f57600080fd5b5061034361033e366004613604565b6108e0565b60405161035798979695949392919061374d565b60405180910390f35b34801561036c57600080fd5b5061038061037b366004613604565b610952565b005b34801561038e57600080fd5b5061038061039d36600461364b565b610999565b3480156103ae57600080fd5b506103c26103bd366004613356565b610ac2565b6040516103579190613898565b3480156103db57600080fd5b506103e4610ad4565b60405161035791906136d5565b3480156103fd57600080fd5b5061041161040c366004613604565b610aec565b604051610357919061388d565b34801561042a57600080fd5b506103c2610b3a565b34801561043f57600080fd5b5061045361044e366004613604565b610b40565b60405161035791906138a1565b34801561046c57600080fd5b50610475610c9c565b60405161035791906138b5565b34801561048e57600080fd5b506103c2610cd3565b3480156104a357600080fd5b506103c26104b236600461338e565b610cd9565b3480156104c357600080fd5b506103806104d2366004613356565b610d4e565b3480156104e357600080fd5b506103e46104f2366004613604565b610f0a565b34801561050357600080fd5b50610380610512366004613604565b61107b565b34801561052357600080fd5b506103e4610532366004613356565b611208565b34801561054357600080fd5b506103c2611230565b34801561055857600080fd5b506103c2611236565b34801561056d57600080fd5b5061038061057c366004613604565b61123c565b34801561058d57600080fd5b5061038061059c366004613604565b6112b5565b3480156105ad57600080fd5b506103e46112f3565b3480156105c257600080fd5b50610380611317565b3480156105d757600080fd5b506103806105e6366004613604565b6113ea565b3480156105f757600080fd5b50610380610606366004613604565b6114f6565b34801561061757600080fd5b50610380610626366004613604565b611810565b34801561063757600080fd5b506103c2610646366004613356565b61184e565b34801561065757600080fd5b506103e4611860565b34801561066c57600080fd5b506103c2611884565b34801561068157600080fd5b506103c2610690366004613356565b61188a565b3480156106a157600080fd5b506103e461189c565b3480156106b657600080fd5b506103c26118b8565b3480156106cb57600080fd5b506103806106da366004613604565b6118be565b3480156106eb57600080fd5b506103806106fa36600461349c565b611a47565b34801561070b57600080fd5b5061038061071a366004613604565b611aaf565b34801561072b57600080fd5b506103c2611aed565b34801561074057600080fd5b506103c2611af3565b34801561075557600080fd5b506103c26107643660046133ee565b611af9565b34801561077557600080fd5b506103c2611b0f565b34801561078a57600080fd5b506103c2610799366004613604565b611b37565b3480156107aa57600080fd5b506107be6107b936600461361c565b611b49565b6040516103579190613fde565b3480156107d757600080fd5b506103806107e6366004613604565b611bc8565b3480156107f757600080fd5b5061041161080636600461361c565b611c06565b34801561081757600080fd5b50610380610826366004613604565b611c56565b34801561083757600080fd5b50610380610846366004613604565b611c94565b34801561085757600080fd5b50610380610866366004613604565b611cd2565b34801561087757600080fd5b5061038061088636600461343c565b611da5565b34801561089757600080fd5b506103e4611f40565b3480156108ac57600080fd5b506108c06108bb366004613558565b611f64565b6040516103579190613833565b6103806108db366004613604565b61200c565b603d81815481106108ed57fe5b6000918252602090912060089091020180546001820154600283015460038401546004850154600586015460069096015473ffffffffffffffffffffffffffffffffffffffff9586169750949093169491939092919060ff8082169161010090041688565b333014610994576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b60405180910390fd5b603555565b336109a48333611c06565b1580156109b757506109b583610aec565b155b3332146109c55760006109c9565b6152085b61ffff168115610ab05760005a90506109e33387876120df565b6000610a006127106109fa856109fa5a87906123b6565b906123f8565b6040517fa99ce80700000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a99ce80790610a7790889085906004016136f6565b600060405180830381600087803b158015610a9157600080fd5b505af1158015610aa5573d6000803e3d6000fd5b505050505050610abb565b610abb3386866120df565b5050505050565b603e6020526000908152604090205481565b73b04e030140b30c27bcdfaafffa98c57d80eda7b490565b6000603554603d8381548110610afe57fe5b906000526020600020906008020160050154603d8481548110610b1d57fe5b90600052602060002090600802016004015401101590505b919050565b60335481565b6000610b4a611b0f565b8211158015610b595750600082115b610b8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613e7f565b6000603d8381548110610b9e57fe5b906000526020600020906008020190508060020154610bbb612437565b11610bca576000915050610b35565b8060030154610bd7612437565b11610be6576001915050610b35565b80600501548160040154111580610c0857506035548160050154826004015401105b15610c17576002915050610b35565b600681015460ff1615610c2e576005915050610b35565b610c4d6034546109fa60335484600301546123f890919063ffffffff16565b610c55612437565b10610c64576006915050610b35565b6033546003820154610c75916123f8565b610c7d612437565b10610c8c576004915050610b35565b6003915050610b35565b50919050565b60408051808201909152600f81527f342e70617463682d6578706c6f69740000000000000000000000000000000000602082015290565b603a5481565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152603c60205260408120549091163314610d3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613f39565b610d4684848461243b565b949350505050565b336000818152603c602052604090205473ffffffffffffffffffffffffffffffffffffffff9081169190831614801590610d9e575073ffffffffffffffffffffffffffffffffffffffff82163014155b8015610dbf575073ffffffffffffffffffffffffffffffffffffffff821615155b8015610df757508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b610e2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613d20565b73ffffffffffffffffffffffffffffffffffffffff811615610e8d5760405173ffffffffffffffffffffffffffffffffffffffff82169033907f1af5b1c85495b3618ea659a1ba256c8b8974b437297d3b914e321e086a28da7290600090a35b336000818152603c602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff871690811790915590519092917f4bc154dd35d6a5cb9206482ecb473cdbf2473006d6bce728b9cc0741bcc59ea291a35050565b600080610f15612463565b600114610f3657738595bfb0d940dfedc98943fa8a907091203f25ee610f47565b6e0c2e074ec69a0dfb2997ba6c7d2e1e5b6040517f0178b8bf00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff821690630178b8bf90610f9c908690600401613898565b60206040518083038186803b158015610fb457600080fd5b505afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190613372565b73ffffffffffffffffffffffffffffffffffffffff16633b3b57de846040518263ffffffff1660e01b81526004016110249190613898565b60206040518083038186803b15801561103c57600080fd5b505afa158015611050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110749190613372565b9392505050565b336000818152603b6020526040908190205490517fe113335f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163e113335f916110fe9185916004016136f6565b600060405180830381600087803b15801561111857600080fd5b505af1925050508015611129575060015b6111b9573d808015611157576040519150601f19603f3d011682016040523d82523d6000602084013e61115c565b606091505b508060405161116b91906136b9565b6040519081900381209073ffffffffffffffffffffffffffffffffffffffff8416907f5a6216e80d86159dc87dcebfe519205477a94005b7d9d6bd313606450a5344f690600090a3506111fb565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f9b227b0c1ae308b34f72d4fdf9a1943fa769ff4814933595e7bc5230a117698b90600090a25b61120482612467565b5050565b603c6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60355481565b60345481565b333014611275576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b60335481106112b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613bb0565b603a55565b3330146112ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b603755565b7f000000000000000000000000000000000000000000000000000000000000000081565b336000908152603c602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613edc565b336000818152603c602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555173ffffffffffffffffffffffffffffffffffffffff841692917f1af5b1c85495b3618ea659a1ba256c8b8974b437297d3b914e321e086a28da7291a350565b6113f2610ad4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611456576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613e48565b6040517fe822f78400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063e822f784906114c8908490600401613898565b600060405180830381600087803b1580156114e257600080fd5b505af1158015610abb573d6000803e3d6000fd5b600054610100900460ff168061150f575061150f61258b565b8061151d575060005460ff16155b611553576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613deb565b600054610100900460ff161580156115b957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b6115c282610f0a565b604080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161782558151610100808201845230825261dead602083019081526000948301858152606084018681526080850187815260a08601888152600160c0880181815260e089018b8152603d80549384018155909b5297517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc3600890920291820180548b16918d1691909117905594517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc4860180549099169a169990991790965590517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc5830155517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc682015592517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc784015593517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc8830155517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc9909101805492517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316911515919091177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169115159092021790556117de612591565b801561120457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555050565b333014611849576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b603455565b603b6020526000908152604090205481565b7f000000000000000000000000000000000000000000000000000000000000000081565b60365481565b603f6020526000908152604090205481565b60405473ffffffffffffffffffffffffffffffffffffffff1681565b60385481565b336000818152603b6020526040908190205490517fe113335f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163e113335f916119419185916004016136f6565b600060405180830381600087803b15801561195b57600080fd5b505af192505050801561196c575060015b6119fc573d80801561199a576040519150601f19603f3d011682016040523d82523d6000602084013e61199f565b606091505b50806040516119ae91906136b9565b6040519081900381209073ffffffffffffffffffffffffffffffffffffffff8416907f5a6216e80d86159dc87dcebfe519205477a94005b7d9d6bd313606450a5344f690600090a350611a3e565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f9b227b0c1ae308b34f72d4fdf9a1943fa769ff4814933595e7bc5230a117698b90600090a25b611204826125d2565b6000835111611a82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613cb2565b611aaa838383611a928633611c06565b158015611aa55750611aa386610aec565b155b6125dc565b505050565b333014611ae8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b603955565b60395481565b60375481565b6000611b0633848461243b565b90505b92915050565b603d547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60416020526000908152604090205481565b611b5161322f565b603d8381548110611b5e57fe5b6000918252602080832073ffffffffffffffffffffffffffffffffffffffff95909516835260089190910290930160070183526040908190208151606081018352815460ff8082161515835261010090910416151594810194909452600101549083015250919050565b333014611c01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b603355565b6000603d8381548110611c1557fe5b6000918252602080832073ffffffffffffffffffffffffffffffffffffffff861684526007600890930201919091019052604090205460ff16905092915050565b333014611c8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b603855565b333014611ccd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b603655565b611cda610ad4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613e48565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166108fc611d8283476128e1565b6040518115909202916000818181858888f19350505050611da257600080fd5b50565b73ffffffffffffffffffffffffffffffffffffffff8087166000908152603b6020526040908190205490517fe113335f00000000000000000000000000000000000000000000000000000000815288927f0000000000000000000000000000000000000000000000000000000000000000169163e113335f91611e2c9185916004016136f6565b600060405180830381600087803b158015611e4657600080fd5b505af1925050508015611e57575060015b611ee7573d808015611e85576040519150601f19603f3d011682016040523d82523d6000602084013e611e8a565b606091505b5080604051611e9991906136b9565b6040519081900381209073ffffffffffffffffffffffffffffffffffffffff8416907f5a6216e80d86159dc87dcebfe519205477a94005b7d9d6bd313606450a5344f690600090a350611f29565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f9b227b0c1ae308b34f72d4fdf9a1943fa769ff4814933595e7bc5230a117698b90600090a25b611f378787878787876128f7565b50505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6060815167ffffffffffffffff81118015611f7e57600080fd5b50604051908082528060200260200182016040528015611fa8578160200160208202803683370190505b50905060005b8251811015610c9657611fd3838281518110611fc657fe5b6020026020010151610f0a565b828281518110611fdf57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101611fae565b33301415612046576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613a62565b6000603d828154811061205557fe5b60009182526020808320600160089093020191820154858452604190915260409092205490925073ffffffffffffffffffffffffffffffffffffffff90911690813f9081146120d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613b53565b6120d98461299d565b50505050565b60016120ea83610b40565b60068111156120f557fe5b1461212c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613a05565b6000603d838154811061213b57fe5b6000918252602080832073ffffffffffffffffffffffffffffffffffffffff8816845260076008909302019182018152604080842060058401546004850154603b9094529190942054929450101590806121c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613d57565b825460ff1615612210578254610100900460ff16156121f757600183015460048501546121ed916123b6565b6004850155612210565b6001830154600585015461220a916123b6565b60058501555b841561222f57600484015461222590826123f8565b6004850155612244565b600584015461223e90826123f8565b60058501555b6006840154610100900460ff161580156122745750603954612272612267612437565b6003870154906123b6565b105b156122d55760058401546004850154111582151581146122d3576006850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055603a5460038601546122cd916123f8565b60038601555b505b825460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911681177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100871515021784558301819055603354603454603a54600387015461235b938b936123569391926109fa928391906123f8565b612bfd565b8415158773ffffffffffffffffffffffffffffffffffffffff16877f7c2de587c00d75474a0c6c6fa96fd3b45dc974cd4e8a75f712bb84c950dce1b5846040516123a59190613898565b60405180910390a450505050505050565b6000828211156123f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613c44565b50900390565b600082820183811015611b06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613b1c565b4290565b6000612448848484612c54565b6000818152604160205260409020933f909355509092915050565b4690565b336000908152603f602052604090205461247f612437565b116124b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613c0d565b60408051808201825260208082527f476f7665726e616e63653a20696e73756666696369656e742062616c616e636581830152336000908152603b9091529190912054612504918390613084565b336000818152603b6020526040908190209290925590517f91fe35730000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16916391fe3573916114c8919085906004016136f6565b303b1590565b6202a3006033556203f480603481905569054b40b1f852bda00000603555683635c9adc5dea00000603655604b603755603855610e10603955615460603a55565b611da233826130ca565b33813282146125ec5760006125f0565b6152085b61ffff1681156127cf5760005a905060005b885181101561270757600089828151811061261957fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff8082166000908152603c90935260409092205490925016331480612673575073ffffffffffffffffffffffffffffffffffffffff811633145b6126a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613f39565b8615806126bd57506126bb8982611c06565b155b6126f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613fa7565b6126fe818a8a6120df565b50600101612602565b50600061271f6127106109fa856109fa5a87906123b6565b6040517fa99ce80700000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063a99ce8079061279690889085906004016136f6565b600060405180830381600087803b1580156127b057600080fd5b505af11580156127c4573d6000803e3d6000fd5b505050505050611f37565b60005b87518110156128d75760008882815181106127e957fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff8082166000908152603c90935260409092205490925016331480612843575073ffffffffffffffffffffffffffffffffffffffff811633145b612879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613f39565b85158061288d575061288b8882611c06565b155b6128c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613fa7565b6128ce8189896120df565b506001016127d2565b5050505050505050565b60008183106128f05781611b06565b5090919050565b6040805490517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d505accf9061295990899030908a908a908a908a908a906004016137a0565b600060405180830381600087803b15801561297357600080fd5b505af1158015612987573d6000803e3d6000fd5b5050505061299586866130ca565b505050505050565b60046129a882610b40565b60068111156129b357fe5b146129ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613925565b6000603d82815481106129f957fe5b60009182526020909120600660089092020190810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915581015490915073ffffffffffffffffffffffffffffffffffffffff16612a5f81613229565b612a95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b906138c8565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f373058b800000000000000000000000000000000000000000000000000000000179052905160009160609173ffffffffffffffffffffffffffffffffffffffff851691612b14916136b9565b600060405180830381855af49150503d8060008114612b4f576040519150601f19603f3d011682016040523d82523d6000602084013e612b54565b606091505b509150915081612bcb57805115612b9957806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b91906138b5565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613f70565b60405185907f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f90600090a25050505050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152603f60205260409020548111156112045773ffffffffffffffffffffffffffffffffffffffff919091166000908152603f6020526040902055565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603b6020526040812054603654811015612cb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613abf565b612cbf84613229565b612cf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613d8e565b73ffffffffffffffffffffffffffffffffffffffff85166000908152603e60205260409020548015612d8e576000612d2c82610b40565b90506001816006811115612d3c57fe5b14158015612d5657506000816006811115612d5357fe5b14155b612d8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613982565b505b6000612d9e6037546109fa612437565b90506000612db7603854836123f890919063ffffffff16565b9050612dc161324f565b5060408051610100808201835273ffffffffffffffffffffffffffffffffffffffff808c1683528a8116602084019081529383018681526060840186815260006080860181815260a0870182815260c0880183815260e08901848152603d80546001810182559086528a5160089091027fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc381018054928b167fffffffffffffffffffffffff00000000000000000000000000000000000000009384161790559b517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc48d01805491909a1691161790975594517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc58a015592517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc6890155517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc788015590517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc887015590517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc99095018054925115159093027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff9515157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179490941617905590612fd3611b0f565b825173ffffffffffffffffffffffffffffffffffffffff166000908152603e60205260409020819055603354603454603a54929350613022928d926123569290916109fa919082908a906123f8565b8973ffffffffffffffffffffffffffffffffffffffff16817f90ec05050aa23d54ba425e926fe646c318e85825bc400b13a46010abe86eb2f08b87878d60405161306f94939291906137ee565b60405180910390a39998505050505050505050565b600081848411156130c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b91906138b5565b505050900390565b6040805490517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd906131449085907f000000000000000000000000000000000000000000000000000000000000000090869060040161371c565b602060405180830381600087803b15801561315e57600080fd5b505af1158015613172573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061319691906135e8565b6131cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613c7b565b73ffffffffffffffffffffffffffffffffffffffff82166000908152603b60205260409020546131fc90826123f8565b73ffffffffffffffffffffffffffffffffffffffff9092166000908152603b602052604090209190915550565b3b151590565b604080516060810182526000808252602082018190529181019190915290565b604051806101000160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b8035611b0981614098565b600082601f8301126132df578081fd5b813567ffffffffffffffff8111156132f5578182fd5b61332660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614003565b915080825283602082850101111561333d57600080fd5b8060208401602084013760009082016020015292915050565b600060208284031215613367578081fd5b8135611b0681614076565b600060208284031215613383578081fd5b8151611b0681614076565b6000806000606084860312156133a2578182fd5b83356133ad81614076565b925060208401356133bd81614076565b9150604084013567ffffffffffffffff8111156133d8578182fd5b6133e4868287016132cf565b9150509250925092565b60008060408385031215613400578182fd5b823561340b81614076565b9150602083013567ffffffffffffffff811115613426578182fd5b613432858286016132cf565b9150509250929050565b60008060008060008060c08789031215613454578182fd5b863561345f81614076565b95506020870135945060408701359350606087013560ff81168114613482578283fd5b9598949750929560808101359460a0909101359350915050565b6000806000606084860312156134b0578283fd5b833567ffffffffffffffff8111156134c6578384fd5b8401601f810186136134d6578384fd5b80356134e96134e48261402a565b614003565b80828252602080830192508085018a828387028801011115613509578889fd5b8895505b8486101561353457803561352081614076565b84526001959095019492810192810161350d565b50909650870135945061354f925087915050604086016132c4565b90509250925092565b6000602080838503121561356a578182fd5b823567ffffffffffffffff811115613580578283fd5b8301601f81018513613590578283fd5b803561359e6134e48261402a565b81815283810190838501858402850186018910156135ba578687fd5b8694505b838510156135dc5780358352600194909401939185019185016135be565b50979650505050505050565b6000602082840312156135f9578081fd5b8151611b0681614098565b600060208284031215613615578081fd5b5035919050565b6000806040838503121561362e578182fd5b82359150602083013561364081614076565b809150509250929050565b6000806040838503121561365d578182fd5b82359150602083013561364081614098565b6000815180845261368781602086016020860161404a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082516136cb81846020870161404a565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff988916815296909716602087015260408601949094526060850192909252608084015260a0830152151560c082015290151560e08201526101000190565b73ffffffffffffffffffffffffffffffffffffffff97881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b600073ffffffffffffffffffffffffffffffffffffffff8616825284602083015283604083015260806060830152613829608083018461366f565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561388157835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161384f565b50909695505050505050565b901515815260200190565b90815260200190565b60208101600783106138af57fe5b91905290565b600060208252611b06602083018461366f565b60208082526023908201527f476f7665726e616e63653a3a657865637574653a206e6f74206120636f6e747260408201527f6163740000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602b908201527f476f7665726e616e63653a3a657865637574653a20696e76616c69642070726f60408201527f706f73616c207374617465000000000000000000000000000000000000000000606082015260800190565b60208082526055908201527f476f7665726e616e63653a3a70726f706f73653a206f6e65206c69766520707260408201527f6f706f73616c207065722070726f706f7365722c20666f756e6420616e20616c60608201527f7265616479206163746976652070726f706f73616c0000000000000000000000608082015260a00190565b60208082526027908201527f476f7665726e616e63653a3a5f63617374566f74653a20766f74696e6720697360408201527f20636c6f73656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252602d908201527f476f7665726e616e63653a3a70726f706f73653a2070736575646f2d6578746560408201527f726e616c2066756e6374696f6e00000000000000000000000000000000000000606082015260800190565b6020808252603c908201527f476f7665726e616e63653a3a70726f706f73653a2070726f706f73657220766f60408201527f7465732062656c6f772070726f706f73616c207468726573686f6c6400000000606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526036908201527f476f7665726e616e63653a3a70726f706f73653a206d6574616d6f727068696360408201527f20636f6e747261637473206e6f7420616c6c6f77656400000000000000000000606082015260800190565b60208082526024908201527f476f7665726e616e63653a20696e636f727265637420766f7465457874656e6460408201527f54696d6500000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f476f7665726e616e63653a20746f6b656e7320617265206c6f636b6564000000604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526019908201527f544f524e3a207472616e7366657246726f6d206661696c656400000000000000604082015260600190565b60208082526010908201527f43616e206e6f7420626520656d70747900000000000000000000000000000000604082015260600190565b60208082526018908201527f476f7665726e616e63653a20756e617574686f72697a65640000000000000000604082015260600190565b6020808252601d908201527f476f7665726e616e63653a20696e76616c69642064656c656761746565000000604082015260600190565b60208082526018908201527f476f7665726e616e63653a2062616c616e636520697320300000000000000000604082015260600190565b60208082526023908201527f476f7665726e616e63653a3a70726f706f73653a206e6f74206120636f6e747260408201527f6163740000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201527f656e20696e697469616c697a6564000000000000000000000000000000000000606082015260800190565b6020808252600d908201527f6f6e6c79206d756c746973696700000000000000000000000000000000000000604082015260600190565b60208082526026908201527f476f7665726e616e63653a3a73746174653a20696e76616c69642070726f706f60408201527f73616c2069640000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f476f7665726e616e63653a20746f6b656e732061726520616c7265616479207560408201527f6e64656c65676174656400000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f476f7665726e616e63653a206e6f7420617574686f72697a6564000000000000604082015260600190565b60208082526019908201527f50726f706f73616c20657865637574696f6e206661696c656400000000000000604082015260600190565b60208082526019908201527f476f7665726e616e63653a20766f74656420616c726561647900000000000000604082015260600190565b8151151581526020808301511515908201526040918201519181019190915260600190565b60405181810167ffffffffffffffff8111828210171561402257600080fd5b604052919050565b600067ffffffffffffffff821115614040578081fd5b5060209081020190565b60005b8381101561406557818101518382015260200161404d565b838111156120d95750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114611da257600080fd5b8015158114611da257600080fdfea2646970667358221220c4f48f2194f841375bd257efea0e5d23a6052a40e69789faad3c34e37d7f834964736f6c634300060c00330000000000000000000000005b3f656c80e8ddb9ec01dd9018815576e9238c29000000000000000000000000fa4c1f3f7d5dd7c12a9adb82cd7dda542e3d59ef0000000000000000000000002f50508a8a3d323b91336fa3ea6ae50e55f32185
Deployed Bytecode
0x6080604052600436106103175760003560e01c80639ae697bf1161019a578063da35c664116100e1578063ece40cc11161008a578063f57df22e11610064578063f57df22e1461088b578063f9e54234146108a0578063fe0d94c1146108cd5761031e565b8063ece40cc11461082b578063ef3f8bb11461084b578063f0b768921461086b5761031e565b8063e4917d9f116100bb578063e4917d9f146107cb578063e525aa08146107eb578063ea0217cf1461080b5761031e565b8063da35c66414610769578063e01f52371461077e578063e23a9a521461079e5761031e565b8063b54426c811610143578063ce25d71c1161011d578063ce25d71c1461071f578063d6159fe514610734578063d6f0948c146107495761031e565b8063b54426c8146106bf578063b859f11b146106df578063c0c0e820146106ff5761031e565b8063a72edda311610174578063a72edda314610675578063adf898a414610695578063b1610d7e146106aa5761031e565b80639ae697bf1461062b5780639daafec71461064b578063a6c26603146106605761031e565b80635c23bdf51161025e57806370b0f66011610207578063932d5157116101e1578063932d5157146105cb5780639498bd71146105eb5780639a9e3b6e1461060b5761031e565b806370b0f660146105815780638b34a960146105a157806392ab89bb146105b65761031e565b8063671dd27511610238578063671dd275146105375780636a6617551461054c5780636dc2dc6c146105615761031e565b80635c23bdf5146104d75780636198e339146104f757806365da1264146105175761031e565b806337f135d7116102c0578063587a6ecb1161029a578063587a6ecb1461048257806358e9fff0146104975780635c19a95c146104b75761031e565b806337f135d71461041e5780633e4f49e61461043357806354fd4d50146104605761031e565b806317977c61116102f157806317977c61146103a257806324b0435f146103cf57806332687ec1146103f15761031e565b8063013cf08b1461032357806302ec8f9e1461036057806315373e3d146103825761031e565b3661031e57005b600080fd5b34801561032f57600080fd5b5061034361033e366004613604565b6108e0565b60405161035798979695949392919061374d565b60405180910390f35b34801561036c57600080fd5b5061038061037b366004613604565b610952565b005b34801561038e57600080fd5b5061038061039d36600461364b565b610999565b3480156103ae57600080fd5b506103c26103bd366004613356565b610ac2565b6040516103579190613898565b3480156103db57600080fd5b506103e4610ad4565b60405161035791906136d5565b3480156103fd57600080fd5b5061041161040c366004613604565b610aec565b604051610357919061388d565b34801561042a57600080fd5b506103c2610b3a565b34801561043f57600080fd5b5061045361044e366004613604565b610b40565b60405161035791906138a1565b34801561046c57600080fd5b50610475610c9c565b60405161035791906138b5565b34801561048e57600080fd5b506103c2610cd3565b3480156104a357600080fd5b506103c26104b236600461338e565b610cd9565b3480156104c357600080fd5b506103806104d2366004613356565b610d4e565b3480156104e357600080fd5b506103e46104f2366004613604565b610f0a565b34801561050357600080fd5b50610380610512366004613604565b61107b565b34801561052357600080fd5b506103e4610532366004613356565b611208565b34801561054357600080fd5b506103c2611230565b34801561055857600080fd5b506103c2611236565b34801561056d57600080fd5b5061038061057c366004613604565b61123c565b34801561058d57600080fd5b5061038061059c366004613604565b6112b5565b3480156105ad57600080fd5b506103e46112f3565b3480156105c257600080fd5b50610380611317565b3480156105d757600080fd5b506103806105e6366004613604565b6113ea565b3480156105f757600080fd5b50610380610606366004613604565b6114f6565b34801561061757600080fd5b50610380610626366004613604565b611810565b34801561063757600080fd5b506103c2610646366004613356565b61184e565b34801561065757600080fd5b506103e4611860565b34801561066c57600080fd5b506103c2611884565b34801561068157600080fd5b506103c2610690366004613356565b61188a565b3480156106a157600080fd5b506103e461189c565b3480156106b657600080fd5b506103c26118b8565b3480156106cb57600080fd5b506103806106da366004613604565b6118be565b3480156106eb57600080fd5b506103806106fa36600461349c565b611a47565b34801561070b57600080fd5b5061038061071a366004613604565b611aaf565b34801561072b57600080fd5b506103c2611aed565b34801561074057600080fd5b506103c2611af3565b34801561075557600080fd5b506103c26107643660046133ee565b611af9565b34801561077557600080fd5b506103c2611b0f565b34801561078a57600080fd5b506103c2610799366004613604565b611b37565b3480156107aa57600080fd5b506107be6107b936600461361c565b611b49565b6040516103579190613fde565b3480156107d757600080fd5b506103806107e6366004613604565b611bc8565b3480156107f757600080fd5b5061041161080636600461361c565b611c06565b34801561081757600080fd5b50610380610826366004613604565b611c56565b34801561083757600080fd5b50610380610846366004613604565b611c94565b34801561085757600080fd5b50610380610866366004613604565b611cd2565b34801561087757600080fd5b5061038061088636600461343c565b611da5565b34801561089757600080fd5b506103e4611f40565b3480156108ac57600080fd5b506108c06108bb366004613558565b611f64565b6040516103579190613833565b6103806108db366004613604565b61200c565b603d81815481106108ed57fe5b6000918252602090912060089091020180546001820154600283015460038401546004850154600586015460069096015473ffffffffffffffffffffffffffffffffffffffff9586169750949093169491939092919060ff8082169161010090041688565b333014610994576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b60405180910390fd5b603555565b336109a48333611c06565b1580156109b757506109b583610aec565b155b3332146109c55760006109c9565b6152085b61ffff168115610ab05760005a90506109e33387876120df565b6000610a006127106109fa856109fa5a87906123b6565b906123f8565b6040517fa99ce80700000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000fa4c1f3f7d5dd7c12a9adb82cd7dda542e3d59ef169063a99ce80790610a7790889085906004016136f6565b600060405180830381600087803b158015610a9157600080fd5b505af1158015610aa5573d6000803e3d6000fd5b505050505050610abb565b610abb3386866120df565b5050505050565b603e6020526000908152604090205481565b73b04e030140b30c27bcdfaafffa98c57d80eda7b490565b6000603554603d8381548110610afe57fe5b906000526020600020906008020160050154603d8481548110610b1d57fe5b90600052602060002090600802016004015401101590505b919050565b60335481565b6000610b4a611b0f565b8211158015610b595750600082115b610b8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613e7f565b6000603d8381548110610b9e57fe5b906000526020600020906008020190508060020154610bbb612437565b11610bca576000915050610b35565b8060030154610bd7612437565b11610be6576001915050610b35565b80600501548160040154111580610c0857506035548160050154826004015401105b15610c17576002915050610b35565b600681015460ff1615610c2e576005915050610b35565b610c4d6034546109fa60335484600301546123f890919063ffffffff16565b610c55612437565b10610c64576006915050610b35565b6033546003820154610c75916123f8565b610c7d612437565b10610c8c576004915050610b35565b6003915050610b35565b50919050565b60408051808201909152600f81527f342e70617463682d6578706c6f69740000000000000000000000000000000000602082015290565b603a5481565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152603c60205260408120549091163314610d3b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613f39565b610d4684848461243b565b949350505050565b336000818152603c602052604090205473ffffffffffffffffffffffffffffffffffffffff9081169190831614801590610d9e575073ffffffffffffffffffffffffffffffffffffffff82163014155b8015610dbf575073ffffffffffffffffffffffffffffffffffffffff821615155b8015610df757508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b610e2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613d20565b73ffffffffffffffffffffffffffffffffffffffff811615610e8d5760405173ffffffffffffffffffffffffffffffffffffffff82169033907f1af5b1c85495b3618ea659a1ba256c8b8974b437297d3b914e321e086a28da7290600090a35b336000818152603c602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff871690811790915590519092917f4bc154dd35d6a5cb9206482ecb473cdbf2473006d6bce728b9cc0741bcc59ea291a35050565b600080610f15612463565b600114610f3657738595bfb0d940dfedc98943fa8a907091203f25ee610f47565b6e0c2e074ec69a0dfb2997ba6c7d2e1e5b6040517f0178b8bf00000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff821690630178b8bf90610f9c908690600401613898565b60206040518083038186803b158015610fb457600080fd5b505afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190613372565b73ffffffffffffffffffffffffffffffffffffffff16633b3b57de846040518263ffffffff1660e01b81526004016110249190613898565b60206040518083038186803b15801561103c57600080fd5b505afa158015611050573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110749190613372565b9392505050565b336000818152603b6020526040908190205490517fe113335f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000005b3f656c80e8ddb9ec01dd9018815576e9238c29169163e113335f916110fe9185916004016136f6565b600060405180830381600087803b15801561111857600080fd5b505af1925050508015611129575060015b6111b9573d808015611157576040519150601f19603f3d011682016040523d82523d6000602084013e61115c565b606091505b508060405161116b91906136b9565b6040519081900381209073ffffffffffffffffffffffffffffffffffffffff8416907f5a6216e80d86159dc87dcebfe519205477a94005b7d9d6bd313606450a5344f690600090a3506111fb565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f9b227b0c1ae308b34f72d4fdf9a1943fa769ff4814933595e7bc5230a117698b90600090a25b61120482612467565b5050565b603c6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b60355481565b60345481565b333014611275576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b60335481106112b0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613bb0565b603a55565b3330146112ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b603755565b7f000000000000000000000000fa4c1f3f7d5dd7c12a9adb82cd7dda542e3d59ef81565b336000908152603c602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611374576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613edc565b336000818152603c602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690555173ffffffffffffffffffffffffffffffffffffffff841692917f1af5b1c85495b3618ea659a1ba256c8b8974b437297d3b914e321e086a28da7291a350565b6113f2610ad4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611456576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613e48565b6040517fe822f78400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000fa4c1f3f7d5dd7c12a9adb82cd7dda542e3d59ef169063e822f784906114c8908490600401613898565b600060405180830381600087803b1580156114e257600080fd5b505af1158015610abb573d6000803e3d6000fd5b600054610100900460ff168061150f575061150f61258b565b8061151d575060005460ff16155b611553576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613deb565b600054610100900460ff161580156115b957600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff909116610100171660011790555b6115c282610f0a565b604080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff9384161782558151610100808201845230825261dead602083019081526000948301858152606084018681526080850187815260a08601888152600160c0880181815260e089018b8152603d80549384018155909b5297517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc3600890920291820180548b16918d1691909117905594517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc4860180549099169a169990991790965590517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc5830155517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc682015592517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc784015593517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc8830155517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc9909101805492517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316911515919091177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169115159092021790556117de612591565b801561120457600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1690555050565b333014611849576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b603455565b603b6020526000908152604090205481565b7f0000000000000000000000002f50508a8a3d323b91336fa3ea6ae50e55f3218581565b60365481565b603f6020526000908152604090205481565b60405473ffffffffffffffffffffffffffffffffffffffff1681565b60385481565b336000818152603b6020526040908190205490517fe113335f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000005b3f656c80e8ddb9ec01dd9018815576e9238c29169163e113335f916119419185916004016136f6565b600060405180830381600087803b15801561195b57600080fd5b505af192505050801561196c575060015b6119fc573d80801561199a576040519150601f19603f3d011682016040523d82523d6000602084013e61199f565b606091505b50806040516119ae91906136b9565b6040519081900381209073ffffffffffffffffffffffffffffffffffffffff8416907f5a6216e80d86159dc87dcebfe519205477a94005b7d9d6bd313606450a5344f690600090a350611a3e565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f9b227b0c1ae308b34f72d4fdf9a1943fa769ff4814933595e7bc5230a117698b90600090a25b611204826125d2565b6000835111611a82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613cb2565b611aaa838383611a928633611c06565b158015611aa55750611aa386610aec565b155b6125dc565b505050565b333014611ae8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b603955565b60395481565b60375481565b6000611b0633848461243b565b90505b92915050565b603d547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b60416020526000908152604090205481565b611b5161322f565b603d8381548110611b5e57fe5b6000918252602080832073ffffffffffffffffffffffffffffffffffffffff95909516835260089190910290930160070183526040908190208151606081018352815460ff8082161515835261010090910416151594810194909452600101549083015250919050565b333014611c01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b603355565b6000603d8381548110611c1557fe5b6000918252602080832073ffffffffffffffffffffffffffffffffffffffff861684526007600890930201919091019052604090205460ff16905092915050565b333014611c8f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b603855565b333014611ccd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613ce9565b603655565b611cda610ad4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613e48565b7f000000000000000000000000fa4c1f3f7d5dd7c12a9adb82cd7dda542e3d59ef73ffffffffffffffffffffffffffffffffffffffff166108fc611d8283476128e1565b6040518115909202916000818181858888f19350505050611da257600080fd5b50565b73ffffffffffffffffffffffffffffffffffffffff8087166000908152603b6020526040908190205490517fe113335f00000000000000000000000000000000000000000000000000000000815288927f0000000000000000000000005b3f656c80e8ddb9ec01dd9018815576e9238c29169163e113335f91611e2c9185916004016136f6565b600060405180830381600087803b158015611e4657600080fd5b505af1925050508015611e57575060015b611ee7573d808015611e85576040519150601f19603f3d011682016040523d82523d6000602084013e611e8a565b606091505b5080604051611e9991906136b9565b6040519081900381209073ffffffffffffffffffffffffffffffffffffffff8416907f5a6216e80d86159dc87dcebfe519205477a94005b7d9d6bd313606450a5344f690600090a350611f29565b60405173ffffffffffffffffffffffffffffffffffffffff8216907f9b227b0c1ae308b34f72d4fdf9a1943fa769ff4814933595e7bc5230a117698b90600090a25b611f378787878787876128f7565b50505050505050565b7f0000000000000000000000005b3f656c80e8ddb9ec01dd9018815576e9238c2981565b6060815167ffffffffffffffff81118015611f7e57600080fd5b50604051908082528060200260200182016040528015611fa8578160200160208202803683370190505b50905060005b8251811015610c9657611fd3838281518110611fc657fe5b6020026020010151610f0a565b828281518110611fdf57fe5b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910190910152600101611fae565b33301415612046576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613a62565b6000603d828154811061205557fe5b60009182526020808320600160089093020191820154858452604190915260409092205490925073ffffffffffffffffffffffffffffffffffffffff90911690813f9081146120d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613b53565b6120d98461299d565b50505050565b60016120ea83610b40565b60068111156120f557fe5b1461212c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613a05565b6000603d838154811061213b57fe5b6000918252602080832073ffffffffffffffffffffffffffffffffffffffff8816845260076008909302019182018152604080842060058401546004850154603b9094529190942054929450101590806121c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613d57565b825460ff1615612210578254610100900460ff16156121f757600183015460048501546121ed916123b6565b6004850155612210565b6001830154600585015461220a916123b6565b60058501555b841561222f57600484015461222590826123f8565b6004850155612244565b600584015461223e90826123f8565b60058501555b6006840154610100900460ff161580156122745750603954612272612267612437565b6003870154906123b6565b105b156122d55760058401546004850154111582151581146122d3576006850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055603a5460038601546122cd916123f8565b60038601555b505b825460017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090911681177fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100871515021784558301819055603354603454603a54600387015461235b938b936123569391926109fa928391906123f8565b612bfd565b8415158773ffffffffffffffffffffffffffffffffffffffff16877f7c2de587c00d75474a0c6c6fa96fd3b45dc974cd4e8a75f712bb84c950dce1b5846040516123a59190613898565b60405180910390a450505050505050565b6000828211156123f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613c44565b50900390565b600082820183811015611b06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613b1c565b4290565b6000612448848484612c54565b6000818152604160205260409020933f909355509092915050565b4690565b336000908152603f602052604090205461247f612437565b116124b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613c0d565b60408051808201825260208082527f476f7665726e616e63653a20696e73756666696369656e742062616c616e636581830152336000908152603b9091529190912054612504918390613084565b336000818152603b6020526040908190209290925590517f91fe35730000000000000000000000000000000000000000000000000000000081527f0000000000000000000000002f50508a8a3d323b91336fa3ea6ae50e55f3218573ffffffffffffffffffffffffffffffffffffffff16916391fe3573916114c8919085906004016136f6565b303b1590565b6202a3006033556203f480603481905569054b40b1f852bda00000603555683635c9adc5dea00000603655604b603755603855610e10603955615460603a55565b611da233826130ca565b33813282146125ec5760006125f0565b6152085b61ffff1681156127cf5760005a905060005b885181101561270757600089828151811061261957fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff8082166000908152603c90935260409092205490925016331480612673575073ffffffffffffffffffffffffffffffffffffffff811633145b6126a9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613f39565b8615806126bd57506126bb8982611c06565b155b6126f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613fa7565b6126fe818a8a6120df565b50600101612602565b50600061271f6127106109fa856109fa5a87906123b6565b6040517fa99ce80700000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000fa4c1f3f7d5dd7c12a9adb82cd7dda542e3d59ef169063a99ce8079061279690889085906004016136f6565b600060405180830381600087803b1580156127b057600080fd5b505af11580156127c4573d6000803e3d6000fd5b505050505050611f37565b60005b87518110156128d75760008882815181106127e957fe5b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff8082166000908152603c90935260409092205490925016331480612843575073ffffffffffffffffffffffffffffffffffffffff811633145b612879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613f39565b85158061288d575061288b8882611c06565b155b6128c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613fa7565b6128ce8189896120df565b506001016127d2565b5050505050505050565b60008183106128f05781611b06565b5090919050565b6040805490517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d505accf9061295990899030908a908a908a908a908a906004016137a0565b600060405180830381600087803b15801561297357600080fd5b505af1158015612987573d6000803e3d6000fd5b5050505061299586866130ca565b505050505050565b60046129a882610b40565b60068111156129b357fe5b146129ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613925565b6000603d82815481106129f957fe5b60009182526020909120600660089092020190810180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600190811790915581015490915073ffffffffffffffffffffffffffffffffffffffff16612a5f81613229565b612a95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b906138c8565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f373058b800000000000000000000000000000000000000000000000000000000179052905160009160609173ffffffffffffffffffffffffffffffffffffffff851691612b14916136b9565b600060405180830381855af49150503d8060008114612b4f576040519150601f19603f3d011682016040523d82523d6000602084013e612b54565b606091505b509150915081612bcb57805115612b9957806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b91906138b5565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613f70565b60405185907f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f90600090a25050505050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152603f60205260409020548111156112045773ffffffffffffffffffffffffffffffffffffffff919091166000908152603f6020526040902055565b73ffffffffffffffffffffffffffffffffffffffff83166000908152603b6020526040812054603654811015612cb6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613abf565b612cbf84613229565b612cf5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613d8e565b73ffffffffffffffffffffffffffffffffffffffff85166000908152603e60205260409020548015612d8e576000612d2c82610b40565b90506001816006811115612d3c57fe5b14158015612d5657506000816006811115612d5357fe5b14155b612d8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613982565b505b6000612d9e6037546109fa612437565b90506000612db7603854836123f890919063ffffffff16565b9050612dc161324f565b5060408051610100808201835273ffffffffffffffffffffffffffffffffffffffff808c1683528a8116602084019081529383018681526060840186815260006080860181815260a0870182815260c0880183815260e08901848152603d80546001810182559086528a5160089091027fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc381018054928b167fffffffffffffffffffffffff00000000000000000000000000000000000000009384161790559b517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc48d01805491909a1691161790975594517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc58a015592517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc6890155517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc788015590517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc887015590517fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc99095018054925115159093027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff9515157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179490941617905590612fd3611b0f565b825173ffffffffffffffffffffffffffffffffffffffff166000908152603e60205260409020819055603354603454603a54929350613022928d926123569290916109fa919082908a906123f8565b8973ffffffffffffffffffffffffffffffffffffffff16817f90ec05050aa23d54ba425e926fe646c318e85825bc400b13a46010abe86eb2f08b87878d60405161306f94939291906137ee565b60405180910390a39998505050505050505050565b600081848411156130c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b91906138b5565b505050900390565b6040805490517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906323b872dd906131449085907f0000000000000000000000002f50508a8a3d323b91336fa3ea6ae50e55f3218590869060040161371c565b602060405180830381600087803b15801561315e57600080fd5b505af1158015613172573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061319691906135e8565b6131cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161098b90613c7b565b73ffffffffffffffffffffffffffffffffffffffff82166000908152603b60205260409020546131fc90826123f8565b73ffffffffffffffffffffffffffffffffffffffff9092166000908152603b602052604090209190915550565b3b151590565b604080516060810182526000808252602082018190529181019190915290565b604051806101000160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b8035611b0981614098565b600082601f8301126132df578081fd5b813567ffffffffffffffff8111156132f5578182fd5b61332660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614003565b915080825283602082850101111561333d57600080fd5b8060208401602084013760009082016020015292915050565b600060208284031215613367578081fd5b8135611b0681614076565b600060208284031215613383578081fd5b8151611b0681614076565b6000806000606084860312156133a2578182fd5b83356133ad81614076565b925060208401356133bd81614076565b9150604084013567ffffffffffffffff8111156133d8578182fd5b6133e4868287016132cf565b9150509250925092565b60008060408385031215613400578182fd5b823561340b81614076565b9150602083013567ffffffffffffffff811115613426578182fd5b613432858286016132cf565b9150509250929050565b60008060008060008060c08789031215613454578182fd5b863561345f81614076565b95506020870135945060408701359350606087013560ff81168114613482578283fd5b9598949750929560808101359460a0909101359350915050565b6000806000606084860312156134b0578283fd5b833567ffffffffffffffff8111156134c6578384fd5b8401601f810186136134d6578384fd5b80356134e96134e48261402a565b614003565b80828252602080830192508085018a828387028801011115613509578889fd5b8895505b8486101561353457803561352081614076565b84526001959095019492810192810161350d565b50909650870135945061354f925087915050604086016132c4565b90509250925092565b6000602080838503121561356a578182fd5b823567ffffffffffffffff811115613580578283fd5b8301601f81018513613590578283fd5b803561359e6134e48261402a565b81815283810190838501858402850186018910156135ba578687fd5b8694505b838510156135dc5780358352600194909401939185019185016135be565b50979650505050505050565b6000602082840312156135f9578081fd5b8151611b0681614098565b600060208284031215613615578081fd5b5035919050565b6000806040838503121561362e578182fd5b82359150602083013561364081614076565b809150509250929050565b6000806040838503121561365d578182fd5b82359150602083013561364081614098565b6000815180845261368781602086016020860161404a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082516136cb81846020870161404a565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff988916815296909716602087015260408601949094526060850192909252608084015260a0830152151560c082015290151560e08201526101000190565b73ffffffffffffffffffffffffffffffffffffffff97881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b600073ffffffffffffffffffffffffffffffffffffffff8616825284602083015283604083015260806060830152613829608083018461366f565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561388157835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161384f565b50909695505050505050565b901515815260200190565b90815260200190565b60208101600783106138af57fe5b91905290565b600060208252611b06602083018461366f565b60208082526023908201527f476f7665726e616e63653a3a657865637574653a206e6f74206120636f6e747260408201527f6163740000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602b908201527f476f7665726e616e63653a3a657865637574653a20696e76616c69642070726f60408201527f706f73616c207374617465000000000000000000000000000000000000000000606082015260800190565b60208082526055908201527f476f7665726e616e63653a3a70726f706f73653a206f6e65206c69766520707260408201527f6f706f73616c207065722070726f706f7365722c20666f756e6420616e20616c60608201527f7265616479206163746976652070726f706f73616c0000000000000000000000608082015260a00190565b60208082526027908201527f476f7665726e616e63653a3a5f63617374566f74653a20766f74696e6720697360408201527f20636c6f73656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252602d908201527f476f7665726e616e63653a3a70726f706f73653a2070736575646f2d6578746560408201527f726e616c2066756e6374696f6e00000000000000000000000000000000000000606082015260800190565b6020808252603c908201527f476f7665726e616e63653a3a70726f706f73653a2070726f706f73657220766f60408201527f7465732062656c6f772070726f706f73616c207468726573686f6c6400000000606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526036908201527f476f7665726e616e63653a3a70726f706f73653a206d6574616d6f727068696360408201527f20636f6e747261637473206e6f7420616c6c6f77656400000000000000000000606082015260800190565b60208082526024908201527f476f7665726e616e63653a20696e636f727265637420766f7465457874656e6460408201527f54696d6500000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f476f7665726e616e63653a20746f6b656e7320617265206c6f636b6564000000604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526019908201527f544f524e3a207472616e7366657246726f6d206661696c656400000000000000604082015260600190565b60208082526010908201527f43616e206e6f7420626520656d70747900000000000000000000000000000000604082015260600190565b60208082526018908201527f476f7665726e616e63653a20756e617574686f72697a65640000000000000000604082015260600190565b6020808252601d908201527f476f7665726e616e63653a20696e76616c69642064656c656761746565000000604082015260600190565b60208082526018908201527f476f7665726e616e63653a2062616c616e636520697320300000000000000000604082015260600190565b60208082526023908201527f476f7665726e616e63653a3a70726f706f73653a206e6f74206120636f6e747260408201527f6163740000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201527f656e20696e697469616c697a6564000000000000000000000000000000000000606082015260800190565b6020808252600d908201527f6f6e6c79206d756c746973696700000000000000000000000000000000000000604082015260600190565b60208082526026908201527f476f7665726e616e63653a3a73746174653a20696e76616c69642070726f706f60408201527f73616c2069640000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f476f7665726e616e63653a20746f6b656e732061726520616c7265616479207560408201527f6e64656c65676174656400000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f476f7665726e616e63653a206e6f7420617574686f72697a6564000000000000604082015260600190565b60208082526019908201527f50726f706f73616c20657865637574696f6e206661696c656400000000000000604082015260600190565b60208082526019908201527f476f7665726e616e63653a20766f74656420616c726561647900000000000000604082015260600190565b8151151581526020808301511515908201526040918201519181019190915260600190565b60405181810167ffffffffffffffff8111828210171561402257600080fd5b604052919050565b600067ffffffffffffffff821115614040578081fd5b5060209081020190565b60005b8381101561406557818101518382015260200161404d565b838111156120d95750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114611da257600080fd5b8015158114611da257600080fdfea2646970667358221220c4f48f2194f841375bd257efea0e5d23a6052a40e69789faad3c34e37d7f834964736f6c634300060c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005b3f656c80e8ddb9ec01dd9018815576e9238c29000000000000000000000000fa4c1f3f7d5dd7c12a9adb82cd7dda542e3d59ef0000000000000000000000002f50508a8a3d323b91336fa3ea6ae50e55f32185
-----Decoded View---------------
Arg [0] : stakingRewardsAddress (address): 0x5B3f656C80E8ddb9ec01Dd9018815576E9238c29
Arg [1] : gasCompLogic (address): 0xFA4C1f3f7D5dd7c12a9Adb82Cd7dDA542E3d59ef
Arg [2] : userVaultAddress (address): 0x2F50508a8a3D323B91336FA3eA6ae50E55f32185
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000005b3f656c80e8ddb9ec01dd9018815576e9238c29
Arg [1] : 000000000000000000000000fa4c1f3f7d5dd7c12a9adb82cd7dda542e3d59ef
Arg [2] : 0000000000000000000000002f50508a8a3d323b91336fa3ea6ae50e55f32185
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.