Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- FundingContract
- Optimization enabled
- true
- Compiler version
- v0.8.22+commit.4fc1097e
- Optimization runs
- 200
- EVM Version
- paris
- Verified at
- 2025-02-11T19:46:44.725609Z
Constructor Arguments
0x000000000000000000000000f33b4027f106cd1e2685516102785650a34d0c5f
Arg [0] (<b>address</b>) : <a href="{#{address_path(@conn, :show, @address)}}">0xf33b4027f106cd1e2685516102785650a34d0c5f</a>
Contract source code
// File: @openzeppelin/contracts/security/ReentrancyGuard.sol // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } } // File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @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 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) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; /** * @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. * * The initial owner is set to the address provided by the deployer. 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; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(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 { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: @openzeppelin/contracts/utils/math/SafeMath.sol // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ 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) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { 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) { unchecked { // 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) { unchecked { 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) { unchecked { 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) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return 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) { return a * b; } /** * @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. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { 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) { 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) { unchecked { 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. * * 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) { unchecked { 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) { unchecked { require(b > 0, errorMessage); return a % b; } } } // File: fundingcontract.sol pragma solidity ^0.8.22; contract FundingContract is ReentrancyGuard, Ownable { using SafeMath for uint256; struct Beneficiary { uint256 totalAllotment; uint256 unlockedAmount; uint256 lastClaimBlock; uint256 unlockInterval; // in blocks string label; bool isPaused; // Pause funding for this beneficiary } uint256 public blockTime = 5; // 5 seconds per block mapping(address => Beneficiary) public beneficiaries; address[] public beneficiaryList; uint256 public contractBalance; event FundsAdded(uint256 amount); event FundsWithdrawn(uint256 amount); event BeneficiaryAdded(address indexed beneficiary, uint256 amount, uint256 unlockInterval, string label); event BeneficiaryRemoved(address indexed beneficiary); event FundsClaimed(address indexed beneficiary, uint256 amount); event BeneficiaryPaused(address indexed beneficiary); event BeneficiaryUnpaused(address indexed beneficiary); event Staked(address indexed user, uint256 amount); event Unstaked(address indexed user, uint256 amount); constructor(address initialOwner) Ownable(initialOwner) {} // Add funds to the contract function addFunds() external payable onlyOwner { require(msg.value > 0, "No funds added"); contractBalance = contractBalance.add(msg.value); emit FundsAdded(msg.value); } // Add or update a beneficiary's allotment function allotFunds( address _beneficiary, uint256 _amount, string memory _unlockInterval, string memory _label ) external onlyOwner { require(_beneficiary != address(0), "Invalid address"); require(_amount > 0, "Amount must be greater than zero"); uint256 unlockIntervalBlocks = calculateUnlockInterval(_unlockInterval); Beneficiary storage beneficiary = beneficiaries[_beneficiary]; if (beneficiary.totalAllotment == 0) { beneficiaryList.push(_beneficiary); } beneficiary.totalAllotment = _amount; beneficiary.unlockedAmount = 0; beneficiary.lastClaimBlock = block.number; beneficiary.unlockInterval = unlockIntervalBlocks; beneficiary.label = _label; beneficiary.isPaused = false; emit BeneficiaryAdded(_beneficiary, _amount, unlockIntervalBlocks, _label); } // Remove a beneficiary's allotment function removeBeneficiary(address _beneficiary) external onlyOwner { require(beneficiaries[_beneficiary].totalAllotment > 0, "No allotment found"); delete beneficiaries[_beneficiary]; emit BeneficiaryRemoved(_beneficiary); } // Pause funding for a specific beneficiary function pauseBeneficiary(address _beneficiary) external onlyOwner { require(beneficiaries[_beneficiary].totalAllotment > 0, "No allotment found"); beneficiaries[_beneficiary].isPaused = true; emit BeneficiaryPaused(_beneficiary); } // Unpause funding for a specific beneficiary function unpauseBeneficiary(address _beneficiary) external onlyOwner { require(beneficiaries[_beneficiary].totalAllotment > 0, "No allotment found"); beneficiaries[_beneficiary].isPaused = false; emit BeneficiaryUnpaused(_beneficiary); } // Claim funds function claim() external nonReentrant { Beneficiary storage beneficiary = beneficiaries[msg.sender]; require(beneficiary.totalAllotment > 0, "No allotment found"); require(!beneficiary.isPaused, "Funding for this beneficiary is paused"); uint256 blocksSinceLastClaim = block.number.sub(beneficiary.lastClaimBlock); require(blocksSinceLastClaim >= beneficiary.unlockInterval, "Claim period not reached"); uint256 claimableIntervals = blocksSinceLastClaim.div(beneficiary.unlockInterval); uint256 claimableAmount = beneficiary.totalAllotment .div(365 * 24 * 60 * 60 / blockTime / beneficiary.unlockInterval) .mul(claimableIntervals); if (claimableAmount.add(beneficiary.unlockedAmount) > beneficiary.totalAllotment) { claimableAmount = beneficiary.totalAllotment.sub(beneficiary.unlockedAmount); } require(claimableAmount > 0, "No funds to claim"); require(claimableAmount <= address(this).balance, "Insufficient contract balance"); beneficiary.unlockedAmount = beneficiary.unlockedAmount.add(claimableAmount); beneficiary.lastClaimBlock = beneficiary.lastClaimBlock.add(claimableIntervals.mul(beneficiary.unlockInterval)); payable(msg.sender).transfer(claimableAmount); emit FundsClaimed(msg.sender, claimableAmount); } // Stake funds (example function) function stake() external payable { require(msg.value > 0, "No funds staked"); emit Staked(msg.sender, msg.value); } // Unstake funds (example function) function unstake(uint256 _amount) external nonReentrant { require(_amount > 0, "Amount must be greater than zero"); require(_amount <= address(this).balance, "Insufficient balance"); payable(msg.sender).transfer(_amount); emit Unstaked(msg.sender, _amount); } // Withdraw excess funds from the contract function withdrawFunds(uint256 _amount) external onlyOwner { require(_amount <= address(this).balance, "Insufficient balance"); contractBalance = contractBalance.sub(_amount); payable(owner()).transfer(_amount); emit FundsWithdrawn(_amount); } // View all beneficiaries function getAllBeneficiaries() external view returns (address[] memory) { return beneficiaryList; } // View details of a specific beneficiary function getBeneficiaryDetails(address _beneficiary) external view returns (Beneficiary memory) { return beneficiaries[_beneficiary]; } // Helper function to calculate unlock interval in blocks function calculateUnlockInterval(string memory _unlockInterval) internal view returns (uint256) { if (keccak256(bytes(_unlockInterval)) == keccak256(bytes("monthly"))) { return (30 * 24 * 60 * 60) / blockTime; } else if (keccak256(bytes(_unlockInterval)) == keccak256(bytes("quarterly"))) { return (90 * 24 * 60 * 60) / blockTime; } else if (keccak256(bytes(_unlockInterval)) == keccak256(bytes("half-yearly"))) { return (180 * 24 * 60 * 60) / blockTime; } else if (keccak256(bytes(_unlockInterval)) == keccak256(bytes("yearly"))) { return (365 * 24 * 60 * 60) / blockTime; } else { revert("Invalid unlock interval"); } } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"initialOwner","internalType":"address"}]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"event","name":"BeneficiaryAdded","inputs":[{"type":"address","name":"beneficiary","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"unlockInterval","internalType":"uint256","indexed":false},{"type":"string","name":"label","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"BeneficiaryPaused","inputs":[{"type":"address","name":"beneficiary","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"BeneficiaryRemoved","inputs":[{"type":"address","name":"beneficiary","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"BeneficiaryUnpaused","inputs":[{"type":"address","name":"beneficiary","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"FundsAdded","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"FundsClaimed","inputs":[{"type":"address","name":"beneficiary","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"FundsWithdrawn","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Staked","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Unstaked","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"payable","outputs":[],"name":"addFunds","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"allotFunds","inputs":[{"type":"address","name":"_beneficiary","internalType":"address"},{"type":"uint256","name":"_amount","internalType":"uint256"},{"type":"string","name":"_unlockInterval","internalType":"string"},{"type":"string","name":"_label","internalType":"string"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"totalAllotment","internalType":"uint256"},{"type":"uint256","name":"unlockedAmount","internalType":"uint256"},{"type":"uint256","name":"lastClaimBlock","internalType":"uint256"},{"type":"uint256","name":"unlockInterval","internalType":"uint256"},{"type":"string","name":"label","internalType":"string"},{"type":"bool","name":"isPaused","internalType":"bool"}],"name":"beneficiaries","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"beneficiaryList","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"blockTime","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claim","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"contractBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getAllBeneficiaries","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct FundingContract.Beneficiary","components":[{"type":"uint256","name":"totalAllotment","internalType":"uint256"},{"type":"uint256","name":"unlockedAmount","internalType":"uint256"},{"type":"uint256","name":"lastClaimBlock","internalType":"uint256"},{"type":"uint256","name":"unlockInterval","internalType":"uint256"},{"type":"string","name":"label","internalType":"string"},{"type":"bool","name":"isPaused","internalType":"bool"}]}],"name":"getBeneficiaryDetails","inputs":[{"type":"address","name":"_beneficiary","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pauseBeneficiary","inputs":[{"type":"address","name":"_beneficiary","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeBeneficiary","inputs":[{"type":"address","name":"_beneficiary","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"stake","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unpauseBeneficiary","inputs":[{"type":"address","name":"_beneficiary","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unstake","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawFunds","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]}]
Contract Creation Code
0x6080604052600560025534801561001557600080fd5b50604051611853380380611853833981016040819052610034916100ca565b6001600055806001600160a01b03811661006857604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b61007181610078565b50506100fa565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000602082840312156100dc57600080fd5b81516001600160a01b03811681146100f357600080fd5b9392505050565b61174a806101096000396000f3fe6080604052600436106101095760003560e01c806359633a1c116100955780638da5cb5b116100645780638da5cb5b146102a65780639e761bbb146102d8578063a26759cb146102f8578063f2dcb31514610300578063f2fde38b1461032057600080fd5b806359633a1c1461023b578063715018a61461025b5780638564c847146102705780638b7afe2e1461029057600080fd5b80632f14bae8116100dc5780632f14bae8146101ab5780633a4b66f1146101cd57806348b15166146101d55780634c3d4f1b146101f95780634e71d92d1461022657600080fd5b8063015677391461010e57806314b55b5214610149578063155dd5ee1461016b5780632e17de781461018b575b600080fd5b34801561011a57600080fd5b5061012e61012936600461127c565b610340565b604051610140969594939291906112dd565b60405180910390f35b34801561015557600080fd5b506101696101643660046113c0565b610407565b005b34801561017757600080fd5b5061016961018636600461143e565b6105a8565b34801561019757600080fd5b506101696101a636600461143e565b610678565b3480156101b757600080fd5b506101c0610787565b6040516101409190611457565b6101696107e9565b3480156101e157600080fd5b506101eb60025481565b604051908152602001610140565b34801561020557600080fd5b5061021961021436600461127c565b610862565b60405161014091906114a4565b34801561023257600080fd5b5061016961099e565b34801561024757600080fd5b5061016961025636600461127c565b610c67565b34801561026757600080fd5b50610169610d26565b34801561027c57600080fd5b5061016961028b36600461127c565b610d38565b34801561029c57600080fd5b506101eb60055481565b3480156102b257600080fd5b506001546001600160a01b03165b6040516001600160a01b039091168152602001610140565b3480156102e457600080fd5b506102c06102f336600461143e565b610dc4565b610169610dee565b34801561030c57600080fd5b5061016961031b36600461127c565b610e7c565b34801561032c57600080fd5b5061016961033b36600461127c565b610f05565b600360205280600052604060002060009150905080600001549080600101549080600201549080600301549080600401805461037b90611500565b80601f01602080910402602001604051908101604052809291908181526020018280546103a790611500565b80156103f45780601f106103c9576101008083540402835291602001916103f4565b820191906000526020600020905b8154815290600101906020018083116103d757829003601f168201915b5050506005909301549192505060ff1686565b61040f610f40565b6001600160a01b03841661045c5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b60448201526064015b60405180910390fd5b600083116104ac5760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610453565b60006104b783610f6d565b6001600160a01b0386166000908152600360205260408120805492935091900361052757600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b0388161790555b84815560006001820155436002820155600381018290556004810161054c848261158b565b5060058101805460ff191690556040516001600160a01b038716907f5367c35a8cbf1024f689c3420f598ba2b53a4d0a1ba202a4a9b1173ef01f8356906105989088908690889061164b565b60405180910390a2505050505050565b6105b0610f40565b478111156105f75760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610453565b6005546106049082611135565b6005556001546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015610641573d6000803e3d6000fd5b506040518181527f4a37b25aab49761ecf63117fe82b98d750917451133cf797507bc9fb5b96044a9060200160405180910390a150565b610680611148565b600081116106d05760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610453565b478111156107175760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610453565b604051339082156108fc029083906000818181858888f19350505050158015610744573d6000803e3d6000fd5b5060405181815233907f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f759060200160405180910390a26107846001600055565b50565b606060048054806020026020016040519081016040528092919081815260200182805480156107df57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116107c1575b5050505050905090565b6000341161082b5760405162461bcd60e51b815260206004820152600f60248201526e139bc8199d5b991cc81cdd185ad959608a1b6044820152606401610453565b60405134815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d9060200160405180910390a2565b61089d6040518060c0016040528060008152602001600081526020016000815260200160008152602001606081526020016000151581525090565b60036000836001600160a01b03166001600160a01b031681526020019081526020016000206040518060c00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201805461090590611500565b80601f016020809104026020016040519081016040528092919081815260200182805461093190611500565b801561097e5780601f106109535761010080835404028352916020019161097e565b820191906000526020600020905b81548152906001019060200180831161096157829003601f168201915b50505091835250506005919091015460ff16151560209091015292915050565b6109a6611148565b33600090815260036020526040902080546109d35760405162461bcd60e51b815260040161045390611673565b600581015460ff1615610a375760405162461bcd60e51b815260206004820152602660248201527f46756e64696e6720666f7220746869732062656e6566696369617279206973206044820152651c185d5cd95960d21b6064820152608401610453565b6000610a5082600201544361113590919063ffffffff16565b90508160030154811015610aa65760405162461bcd60e51b815260206004820152601860248201527f436c61696d20706572696f64206e6f74207265616368656400000000000000006044820152606401610453565b6000610abf8360030154836111a190919063ffffffff16565b90506000610af982610af386600301546002546301e13380610ae191906116b5565b610aeb91906116b5565b8754906111a1565b906111ad565b8454600186015491925090610b0f9083906111b9565b1115610b285760018401548454610b2591611135565b90505b60008111610b6c5760405162461bcd60e51b81526020600482015260116024820152704e6f2066756e647320746f20636c61696d60781b6044820152606401610453565b47811115610bbc5760405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e7420636f6e74726163742062616c616e63650000006044820152606401610453565b6001840154610bcb90826111b9565b60018501556003840154610bef90610be49084906111ad565b6002860154906111b9565b6002850155604051339082156108fc029083906000818181858888f19350505050158015610c21573d6000803e3d6000fd5b5060405181815233907fa65a8b4f7f65a1063243d7f7e9e4da00ff767599acf21549ef2548a45d1695ae9060200160405180910390a250505050610c656001600055565b565b610c6f610f40565b6001600160a01b038116600090815260036020526040902054610ca45760405162461bcd60e51b815260040161045390611673565b6001600160a01b03811660009081526003602081905260408220828155600181018390556002810183905590810182905590610ce36004830182611217565b50600501805460ff191690556040516001600160a01b038216907f72977dad29432f655f11c2f0e72ef5124bb9ade7a512fb7a43a9f504df22342890600090a250565b610d2e610f40565b610c6560006111c5565b610d40610f40565b6001600160a01b038116600090815260036020526040902054610d755760405162461bcd60e51b815260040161045390611673565b6001600160a01b038116600081815260036020526040808220600501805460ff19166001179055517f11dc51d41c66f7c36ffaa5c696a64074215ff817878631872421ea9505bbad0c9190a250565b60048181548110610dd457600080fd5b6000918252602090912001546001600160a01b0316905081565b610df6610f40565b60003411610e375760405162461bcd60e51b815260206004820152600e60248201526d139bc8199d5b991cc8185919195960921b6044820152606401610453565b600554610e4490346111b9565b6005556040513481527fd30fc8a1b5907be76206421a3040262f1f6aed0d418c05312ef5ff8de0c9ae4c9060200160405180910390a1565b610e84610f40565b6001600160a01b038116600090815260036020526040902054610eb95760405162461bcd60e51b815260040161045390611673565b6001600160a01b038116600081815260036020526040808220600501805460ff19169055517f9903599066f3132548c4b56deb3c9420499fbb5a418ca6b44863f708340666719190a250565b610f0d610f40565b6001600160a01b038116610f3757604051631e4fbdf760e01b815260006004820152602401610453565b610784816111c5565b6001546001600160a01b03163314610c655760405163118cdaa760e01b8152336004820152602401610453565b6040805180820190915260078152666d6f6e74686c7960c81b6020918201528151908201206000907fbc653c95ba6ab0e1ef2c238d03b66718c3dadf383ac23d2821c24ea540886de801610fd157600254610fcb9062278d006116b5565b92915050565b604080518082019091526009815268717561727465726c7960b81b6020918201528251908301207fb99532807eda912da02940857de7093eee3ddee12d0360df0af333bb5a9bcf7d0161102e57600254610fcb906276a7006116b5565b60408051808201909152600b81526a68616c662d796561726c7960a81b6020918201528251908301207fb2ecc0bf796e2da563ff374d3c28c76c064e72b80624d134e39e10eed9625f160161108d57600254610fcb9062ed4e006116b5565b604080518082019091526006815265796561726c7960d01b6020918201528251908301207f9a121b243c6becf8570e4498f5b5b66f2ca2f469fd618c1bc6a022a965722bf5016110e857600254610fcb906301e133806116b5565b60405162461bcd60e51b815260206004820152601760248201527f496e76616c696420756e6c6f636b20696e74657276616c0000000000000000006044820152606401610453565b919050565b600061114182846116d7565b9392505050565b60026000540361119a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610453565b6002600055565b600061114182846116b5565b600061114182846116ea565b60006111418284611701565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b50805461122390611500565b6000825580601f10611233575050565b601f01602090049060005260206000209081019061078491905b80821115611261576000815560010161124d565b5090565b80356001600160a01b038116811461113057600080fd5b60006020828403121561128e57600080fd5b61114182611265565b6000815180845260005b818110156112bd576020818501810151868301820152016112a1565b506000602082860101526020601f19601f83011685010191505092915050565b86815285602082015284604082015283606082015260c06080820152600061130860c0830185611297565b905082151560a0830152979650505050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261134457600080fd5b813567ffffffffffffffff8082111561135f5761135f61131d565b604051601f8301601f19908116603f011681019082821181831017156113875761138761131d565b816040528381528660208588010111156113a057600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080608085870312156113d657600080fd5b6113df85611265565b935060208501359250604085013567ffffffffffffffff8082111561140357600080fd5b61140f88838901611333565b9350606087013591508082111561142557600080fd5b5061143287828801611333565b91505092959194509250565b60006020828403121561145057600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156114985783516001600160a01b031683529284019291840191600101611473565b50909695505050505050565b60208152815160208201526020820151604082015260408201516060820152606082015160808201526000608083015160c060a08401526114e860e0840182611297565b905060a0840151151560c08401528091505092915050565b600181811c9082168061151457607f821691505b60208210810361153457634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611586576000816000526020600020601f850160051c810160208610156115635750805b601f850160051c820191505b818110156115825782815560010161156f565b5050505b505050565b815167ffffffffffffffff8111156115a5576115a561131d565b6115b9816115b38454611500565b8461153a565b602080601f8311600181146115ee57600084156115d65750858301515b600019600386901b1c1916600185901b178555611582565b600085815260208120601f198616915b8281101561161d578886015182559484019460019091019084016115fe565b508582101561163b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b83815282602082015260606040820152600061166a6060830184611297565b95945050505050565b602080825260129082015271139bc8185b1b1bdd1b595b9d08199bdd5b9960721b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6000826116d257634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610fcb57610fcb61169f565b8082028115828204841417610fcb57610fcb61169f565b80820180821115610fcb57610fcb61169f56fea26469706673582212209006447ffd9cbec88379d220e96d62fdb1d7ff03cd7b87fe1c6079547eff824164736f6c63430008160033000000000000000000000000f33b4027f106cd1e2685516102785650a34d0c5f
Deployed ByteCode
0x6080604052600436106101095760003560e01c806359633a1c116100955780638da5cb5b116100645780638da5cb5b146102a65780639e761bbb146102d8578063a26759cb146102f8578063f2dcb31514610300578063f2fde38b1461032057600080fd5b806359633a1c1461023b578063715018a61461025b5780638564c847146102705780638b7afe2e1461029057600080fd5b80632f14bae8116100dc5780632f14bae8146101ab5780633a4b66f1146101cd57806348b15166146101d55780634c3d4f1b146101f95780634e71d92d1461022657600080fd5b8063015677391461010e57806314b55b5214610149578063155dd5ee1461016b5780632e17de781461018b575b600080fd5b34801561011a57600080fd5b5061012e61012936600461127c565b610340565b604051610140969594939291906112dd565b60405180910390f35b34801561015557600080fd5b506101696101643660046113c0565b610407565b005b34801561017757600080fd5b5061016961018636600461143e565b6105a8565b34801561019757600080fd5b506101696101a636600461143e565b610678565b3480156101b757600080fd5b506101c0610787565b6040516101409190611457565b6101696107e9565b3480156101e157600080fd5b506101eb60025481565b604051908152602001610140565b34801561020557600080fd5b5061021961021436600461127c565b610862565b60405161014091906114a4565b34801561023257600080fd5b5061016961099e565b34801561024757600080fd5b5061016961025636600461127c565b610c67565b34801561026757600080fd5b50610169610d26565b34801561027c57600080fd5b5061016961028b36600461127c565b610d38565b34801561029c57600080fd5b506101eb60055481565b3480156102b257600080fd5b506001546001600160a01b03165b6040516001600160a01b039091168152602001610140565b3480156102e457600080fd5b506102c06102f336600461143e565b610dc4565b610169610dee565b34801561030c57600080fd5b5061016961031b36600461127c565b610e7c565b34801561032c57600080fd5b5061016961033b36600461127c565b610f05565b600360205280600052604060002060009150905080600001549080600101549080600201549080600301549080600401805461037b90611500565b80601f01602080910402602001604051908101604052809291908181526020018280546103a790611500565b80156103f45780601f106103c9576101008083540402835291602001916103f4565b820191906000526020600020905b8154815290600101906020018083116103d757829003601f168201915b5050506005909301549192505060ff1686565b61040f610f40565b6001600160a01b03841661045c5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b60448201526064015b60405180910390fd5b600083116104ac5760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610453565b60006104b783610f6d565b6001600160a01b0386166000908152600360205260408120805492935091900361052757600480546001810182556000919091527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b0388161790555b84815560006001820155436002820155600381018290556004810161054c848261158b565b5060058101805460ff191690556040516001600160a01b038716907f5367c35a8cbf1024f689c3420f598ba2b53a4d0a1ba202a4a9b1173ef01f8356906105989088908690889061164b565b60405180910390a2505050505050565b6105b0610f40565b478111156105f75760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610453565b6005546106049082611135565b6005556001546040516001600160a01b039091169082156108fc029083906000818181858888f19350505050158015610641573d6000803e3d6000fd5b506040518181527f4a37b25aab49761ecf63117fe82b98d750917451133cf797507bc9fb5b96044a9060200160405180910390a150565b610680611148565b600081116106d05760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206d7573742062652067726561746572207468616e207a65726f6044820152606401610453565b478111156107175760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610453565b604051339082156108fc029083906000818181858888f19350505050158015610744573d6000803e3d6000fd5b5060405181815233907f0f5bb82176feb1b5e747e28471aa92156a04d9f3ab9f45f28e2d704232b93f759060200160405180910390a26107846001600055565b50565b606060048054806020026020016040519081016040528092919081815260200182805480156107df57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116107c1575b5050505050905090565b6000341161082b5760405162461bcd60e51b815260206004820152600f60248201526e139bc8199d5b991cc81cdd185ad959608a1b6044820152606401610453565b60405134815233907f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d9060200160405180910390a2565b61089d6040518060c0016040528060008152602001600081526020016000815260200160008152602001606081526020016000151581525090565b60036000836001600160a01b03166001600160a01b031681526020019081526020016000206040518060c00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201805461090590611500565b80601f016020809104026020016040519081016040528092919081815260200182805461093190611500565b801561097e5780601f106109535761010080835404028352916020019161097e565b820191906000526020600020905b81548152906001019060200180831161096157829003601f168201915b50505091835250506005919091015460ff16151560209091015292915050565b6109a6611148565b33600090815260036020526040902080546109d35760405162461bcd60e51b815260040161045390611673565b600581015460ff1615610a375760405162461bcd60e51b815260206004820152602660248201527f46756e64696e6720666f7220746869732062656e6566696369617279206973206044820152651c185d5cd95960d21b6064820152608401610453565b6000610a5082600201544361113590919063ffffffff16565b90508160030154811015610aa65760405162461bcd60e51b815260206004820152601860248201527f436c61696d20706572696f64206e6f74207265616368656400000000000000006044820152606401610453565b6000610abf8360030154836111a190919063ffffffff16565b90506000610af982610af386600301546002546301e13380610ae191906116b5565b610aeb91906116b5565b8754906111a1565b906111ad565b8454600186015491925090610b0f9083906111b9565b1115610b285760018401548454610b2591611135565b90505b60008111610b6c5760405162461bcd60e51b81526020600482015260116024820152704e6f2066756e647320746f20636c61696d60781b6044820152606401610453565b47811115610bbc5760405162461bcd60e51b815260206004820152601d60248201527f496e73756666696369656e7420636f6e74726163742062616c616e63650000006044820152606401610453565b6001840154610bcb90826111b9565b60018501556003840154610bef90610be49084906111ad565b6002860154906111b9565b6002850155604051339082156108fc029083906000818181858888f19350505050158015610c21573d6000803e3d6000fd5b5060405181815233907fa65a8b4f7f65a1063243d7f7e9e4da00ff767599acf21549ef2548a45d1695ae9060200160405180910390a250505050610c656001600055565b565b610c6f610f40565b6001600160a01b038116600090815260036020526040902054610ca45760405162461bcd60e51b815260040161045390611673565b6001600160a01b03811660009081526003602081905260408220828155600181018390556002810183905590810182905590610ce36004830182611217565b50600501805460ff191690556040516001600160a01b038216907f72977dad29432f655f11c2f0e72ef5124bb9ade7a512fb7a43a9f504df22342890600090a250565b610d2e610f40565b610c6560006111c5565b610d40610f40565b6001600160a01b038116600090815260036020526040902054610d755760405162461bcd60e51b815260040161045390611673565b6001600160a01b038116600081815260036020526040808220600501805460ff19166001179055517f11dc51d41c66f7c36ffaa5c696a64074215ff817878631872421ea9505bbad0c9190a250565b60048181548110610dd457600080fd5b6000918252602090912001546001600160a01b0316905081565b610df6610f40565b60003411610e375760405162461bcd60e51b815260206004820152600e60248201526d139bc8199d5b991cc8185919195960921b6044820152606401610453565b600554610e4490346111b9565b6005556040513481527fd30fc8a1b5907be76206421a3040262f1f6aed0d418c05312ef5ff8de0c9ae4c9060200160405180910390a1565b610e84610f40565b6001600160a01b038116600090815260036020526040902054610eb95760405162461bcd60e51b815260040161045390611673565b6001600160a01b038116600081815260036020526040808220600501805460ff19169055517f9903599066f3132548c4b56deb3c9420499fbb5a418ca6b44863f708340666719190a250565b610f0d610f40565b6001600160a01b038116610f3757604051631e4fbdf760e01b815260006004820152602401610453565b610784816111c5565b6001546001600160a01b03163314610c655760405163118cdaa760e01b8152336004820152602401610453565b6040805180820190915260078152666d6f6e74686c7960c81b6020918201528151908201206000907fbc653c95ba6ab0e1ef2c238d03b66718c3dadf383ac23d2821c24ea540886de801610fd157600254610fcb9062278d006116b5565b92915050565b604080518082019091526009815268717561727465726c7960b81b6020918201528251908301207fb99532807eda912da02940857de7093eee3ddee12d0360df0af333bb5a9bcf7d0161102e57600254610fcb906276a7006116b5565b60408051808201909152600b81526a68616c662d796561726c7960a81b6020918201528251908301207fb2ecc0bf796e2da563ff374d3c28c76c064e72b80624d134e39e10eed9625f160161108d57600254610fcb9062ed4e006116b5565b604080518082019091526006815265796561726c7960d01b6020918201528251908301207f9a121b243c6becf8570e4498f5b5b66f2ca2f469fd618c1bc6a022a965722bf5016110e857600254610fcb906301e133806116b5565b60405162461bcd60e51b815260206004820152601760248201527f496e76616c696420756e6c6f636b20696e74657276616c0000000000000000006044820152606401610453565b919050565b600061114182846116d7565b9392505050565b60026000540361119a5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610453565b6002600055565b600061114182846116b5565b600061114182846116ea565b60006111418284611701565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b50805461122390611500565b6000825580601f10611233575050565b601f01602090049060005260206000209081019061078491905b80821115611261576000815560010161124d565b5090565b80356001600160a01b038116811461113057600080fd5b60006020828403121561128e57600080fd5b61114182611265565b6000815180845260005b818110156112bd576020818501810151868301820152016112a1565b506000602082860101526020601f19601f83011685010191505092915050565b86815285602082015284604082015283606082015260c06080820152600061130860c0830185611297565b905082151560a0830152979650505050505050565b634e487b7160e01b600052604160045260246000fd5b600082601f83011261134457600080fd5b813567ffffffffffffffff8082111561135f5761135f61131d565b604051601f8301601f19908116603f011681019082821181831017156113875761138761131d565b816040528381528660208588010111156113a057600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080608085870312156113d657600080fd5b6113df85611265565b935060208501359250604085013567ffffffffffffffff8082111561140357600080fd5b61140f88838901611333565b9350606087013591508082111561142557600080fd5b5061143287828801611333565b91505092959194509250565b60006020828403121561145057600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b818110156114985783516001600160a01b031683529284019291840191600101611473565b50909695505050505050565b60208152815160208201526020820151604082015260408201516060820152606082015160808201526000608083015160c060a08401526114e860e0840182611297565b905060a0840151151560c08401528091505092915050565b600181811c9082168061151457607f821691505b60208210810361153457634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611586576000816000526020600020601f850160051c810160208610156115635750805b601f850160051c820191505b818110156115825782815560010161156f565b5050505b505050565b815167ffffffffffffffff8111156115a5576115a561131d565b6115b9816115b38454611500565b8461153a565b602080601f8311600181146115ee57600084156115d65750858301515b600019600386901b1c1916600185901b178555611582565b600085815260208120601f198616915b8281101561161d578886015182559484019460019091019084016115fe565b508582101561163b5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b83815282602082015260606040820152600061166a6060830184611297565b95945050505050565b602080825260129082015271139bc8185b1b1bdd1b595b9d08199bdd5b9960721b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b6000826116d257634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610fcb57610fcb61169f565b8082028115828204841417610fcb57610fcb61169f565b80820180821115610fcb57610fcb61169f56fea26469706673582212209006447ffd9cbec88379d220e96d62fdb1d7ff03cd7b87fe1c6079547eff824164736f6c63430008160033